diff --git a/src/pages/bill/index.less b/src/pages/bill/index.less index cd64979..4ec2b84 100644 --- a/src/pages/bill/index.less +++ b/src/pages/bill/index.less @@ -4,11 +4,6 @@ padding: 20rpx 24rpx 60rpx; box-sizing: border-box; - // 多选模式为底部导出栏留出空间 - &--select { - padding-bottom: 160rpx; - } - // 底部待支付汇总栏留出空间 &--pay { padding-bottom: 180rpx; @@ -55,7 +50,7 @@ } } - // ===== 状态筛选 + 导出入口 ===== + // ===== 状态筛选 ===== .bill-toolbar { display: flex; align-items: center; @@ -67,22 +62,6 @@ white-space: nowrap; margin-bottom: 0; } - - &__export { - flex-shrink: 0; - margin-left: 16rpx; - padding: 12rpx 28rpx; - border-radius: 999rpx; - background: #fff; - border: 1rpx solid #ee0a24; - color: #ee0a24; - font-size: 26rpx; - - &.active { - background: #ee0a24; - color: #fff; - } - } } .status-scroll { @@ -132,11 +111,6 @@ padding: 24rpx; margin-bottom: 16rpx; - &--select { - display: flex; - align-items: center; - } - &__content { flex: 1; min-width: 0; @@ -192,7 +166,24 @@ font-size: 32rpx; color: #323233; font-weight: 600; + } + + // 右侧栏:金额 + 导出按钮 + &__side { margin-left: 20rpx; + flex-shrink: 0; + display: flex; + flex-direction: column; + align-items: flex-end; + } + + &__export { + margin-top: 12rpx; + padding: 6rpx 24rpx; + border-radius: 999rpx; + border: 1rpx solid #ee0a24; + color: #ee0a24; + font-size: 22rpx; } &__footer { @@ -213,68 +204,6 @@ } } - // ===== 勾选圆圈 ===== - .bill-check { - width: 36rpx; - height: 36rpx; - border-radius: 50%; - border: 2rpx solid #c8c9cc; - margin-right: 20rpx; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - box-sizing: border-box; - - &.on { - background: #ee0a24; - border-color: #ee0a24; - } - } - - // ===== 导出操作栏 ===== - .export-bar { - position: fixed; - left: 0; - right: 0; - bottom: 0; - z-index: 99; - display: flex; - align-items: center; - padding: 16rpx 24rpx calc(16rpx + env(safe-area-inset-bottom)); - background: #fff; - box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06); - - &__count { - flex: 1; - min-width: 0; - font-size: 26rpx; - color: #646566; - } - - &__all { - padding: 12rpx 24rpx; - margin-right: 16rpx; - border: 1rpx solid #dcdee0; - border-radius: 999rpx; - font-size: 26rpx; - color: #323233; - } - - &__btn { - padding: 14rpx 40rpx; - border-radius: 999rpx; - background: #ee0a24; - color: #fff; - font-size: 28rpx; - font-weight: 500; - - &.disabled { - opacity: 0.5; - } - } - } - // ===== 分类选择弹层 ===== .category-popup { padding: 32rpx 32rpx 24rpx; diff --git a/src/pages/bill/index.tsx b/src/pages/bill/index.tsx index 4d1dcb2..19214b7 100644 --- a/src/pages/bill/index.tsx +++ b/src/pages/bill/index.tsx @@ -11,9 +11,6 @@ import './index.less' const PAGE_SIZE = 10 -/** 单次导出上限(后端限制 1~100 张) */ -const EXPORT_MAX = 100 - /** 状态筛选(接口 status 为原始支付状态:0 未支付含审核中 / 1 已支付) */ const STATUS_FILTERS: Array<{ value: 0 | 1 | undefined; label: string }> = [ { value: undefined, label: '全部' }, @@ -30,7 +27,7 @@ interface CategoryOption { /** * 账单列表页 * 采购单完成后由后台按门店生成(只读);底部汇总栏为门店口径待支付汇总(含审核中,不受筛选影响) - * 支持多选账单合并导出 Excel(可按一级分类过滤商品明细) + * 每个账单可单独导出 Excel(可按一级分类过滤商品明细),不支持合并导出 */ export default function BillListPage() { const token = useAuthStore(s => s.token) @@ -43,9 +40,8 @@ export default function BillListPage() { const [finished, setFinished] = useState(false) const loadingRef = useRef(false) - /** 导出:多选模式 + 已选账单 + 分类弹层 */ - const [selectMode, setSelectMode] = useState(false) - const [selectedIds, setSelectedIds] = useState([]) + /** 导出:待导出账单 + 分类弹层 */ + const [exportBill, setExportBill] = useState(null) const [showCategory, setShowCategory] = useState(false) const [categories, setCategories] = useState([]) @@ -107,72 +103,35 @@ export default function BillListPage() { Taro.navigateTo({ url: '/pages/payment/index' }) }, []) - /** 进入/退出多选导出模式 */ - const toggleSelectMode = useCallback(() => { - setSelectMode(prev => !prev) - setSelectedIds([]) - }, []) - - /** 账单点击:多选模式切换勾选,否则进详情 */ - const handleItemTap = useCallback( - (bill: Bill) => { - if (!selectMode) { - goDetail(bill.id) - return - } - setSelectedIds(prev => { - if (prev.includes(bill.id)) return prev.filter(i => i !== bill.id) - if (prev.length >= EXPORT_MAX) { - Taro.showToast({ title: `最多导出 ${EXPORT_MAX} 张`, icon: 'none' }) - return prev + /** 打开分类选择弹层(首次加载分类树根节点) */ + const handleExportTap = useCallback( + async (bill: Bill) => { + if (categories.length === 0) { + try { + const res = await getCategoriesApi() + setCategories([ + { id: 0, name: '全部分类' }, + ...res.data.map(c => ({ id: c.id, name: c.name })), + ]) + } catch { + return // 错误已由 request 层 toast } - return [...prev, bill.id] - }) + } + setExportBill(bill) + setShowCategory(true) }, - [selectMode, goDetail], + [categories], ) - /** 全选当前已加载账单(受导出上限约束) */ - const handleSelectAll = useCallback(() => { - setSelectedIds(prev => { - if (prev.length === bills.length) return [] - if (bills.length > EXPORT_MAX) { - Taro.showToast({ title: `最多导出 ${EXPORT_MAX} 张,已选前 ${EXPORT_MAX} 张`, icon: 'none' }) - return bills.slice(0, EXPORT_MAX).map(b => b.id) - } - return bills.map(b => b.id) - }) - }, [bills]) - - /** 打开分类选择弹层(首次加载分类树根节点) */ - const handleExportTap = useCallback(async () => { - if (selectedIds.length === 0) { - Taro.showToast({ title: '请先勾选要导出的账单', icon: 'none' }) - return - } - if (categories.length === 0) { - try { - const res = await getCategoriesApi() - setCategories([ - { id: 0, name: '全部分类' }, - ...res.data.map(c => ({ id: c.id, name: c.name })), - ]) - } catch { - return // 错误已由 request 层 toast - } - } - setShowCategory(true) - }, [selectedIds, categories]) - - /** 按所选分类导出合并 Excel */ + /** 按所选分类导出单个账单 Excel */ const handleExport = useCallback( async (categoryId: number) => { + if (!exportBill) return const isH5 = process.env.TARO_ENV === 'h5' Taro.showLoading({ title: '导出中...', mask: true }) try { - await downloadExportFile(getBillExportUrl(selectedIds, categoryId), '门店账单.xlsx') + await downloadExportFile(getBillExportUrl(exportBill.id, categoryId), `账单-${exportBill.bill_no}.xlsx`) setShowCategory(false) - toggleSelectMode() if (isH5) { Taro.showToast({ title: '导出成功', icon: 'success' }) } @@ -182,15 +141,15 @@ export default function BillListPage() { Taro.hideLoading() } }, - [selectedIds, toggleSelectMode], + [exportBill], ) - /** 底部待支付汇总栏是否可见(多选导出时让位给导出栏) */ - const showPayBar = loggedIn && !selectMode && !!summary && summary.unpaid_count > 0 + /** 底部待支付汇总栏是否可见 */ + const showPayBar = loggedIn && !!summary && summary.unpaid_count > 0 return ( - - {/* ========== 状态筛选 + 导出入口 ========== */} + + {/* ========== 状态筛选 ========== */} {STATUS_FILTERS.map(item => ( @@ -203,11 +162,6 @@ export default function BillListPage() { ))} - {loggedIn && bills.length > 0 && ( - - {selectMode ? '取消' : '导出'} - - )} {/* ========== 账单列表 ========== */} @@ -222,45 +176,44 @@ export default function BillListPage() { ) ) : ( - bills.map(bill => { - const checked = selectMode && selectedIds.includes(bill.id) - return ( - handleItemTap(bill)} - > - {selectMode && ( - - {checked && } - - )} - - - {bill.bill_no} - - {bill.pay_state_name} - - - - - 账单日期 {bill.bill_date} - {bill.purchase && ( - 采购单 {bill.purchase.purchase_no} - )} - - ¥{bill.total_amount} - - - 应结算 {bill.settlement_date} - {bill.pay_state === 2 && bill.paid_at && ( - 已于 {bill.paid_at} 支付 + bills.map(bill => ( + goDetail(bill.id)}> + + + {bill.bill_no} + + {bill.pay_state_name} + + + + + 账单日期 {bill.bill_date} + {bill.purchase && ( + 采购单 {bill.purchase.purchase_no} )} + + ¥{bill.total_amount} + { + e.stopPropagation() + handleExportTap(bill) + }} + > + 导出 + + + + + 应结算 {bill.settlement_date} + {bill.pay_state === 2 && bill.paid_at && ( + 已于 {bill.paid_at} 支付 + )} - ) - }) + + )) )} {loggedIn && finished && bills.length > 0 && ( @@ -278,22 +231,6 @@ export default function BillListPage() { )} - {/* ========== 导出操作栏 ========== */} - {selectMode && ( - - 已选 {selectedIds.length} 张 - - {selectedIds.length === bills.length && bills.length > 0 ? '取消全选' : '全选'} - - - 导出 Excel - - - )} - {/* ========== 分类选择弹层 ========== */}