|
|
@@ -0,0 +1,261 @@
|
|
|
+<template>
|
|
|
+ <div class="app-page">
|
|
|
+ <section class="glass-card section-card">
|
|
|
+ <el-form :model="filters" inline class="filter-form">
|
|
|
+ <el-form-item label="结算单号">
|
|
|
+ <el-input v-model="filters.settlementNo" placeholder="结算单号" clearable style="width:170px" @keyup.enter="loadData" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="供应商">
|
|
|
+ <el-select v-model="filters.supplier" placeholder="全部供应商" clearable style="width:160px">
|
|
|
+ <el-option v-for="s in suppliers" :key="s" :label="s" :value="s" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="状态">
|
|
|
+ <el-select v-model="filters.status" placeholder="全部" clearable style="width:130px">
|
|
|
+ <el-option label="待确认" value="待确认" />
|
|
|
+ <el-option label="待付款" value="待付款" />
|
|
|
+ <el-option label="已付款" value="已付款" />
|
|
|
+ <el-option label="已关闭" value="已关闭" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="loadData">查询</el-button>
|
|
|
+ <el-button @click="resetFilters">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="glass-card section-card" style="padding:12px 24px">
|
|
|
+ <div class="table-toolbar" style="margin-bottom:0">
|
|
|
+ <div class="chip-list">
|
|
|
+ <el-button type="primary" @click="openCreate">新建结算单</el-button>
|
|
|
+ <el-button @click="doExport">导出</el-button>
|
|
|
+ </div>
|
|
|
+ <el-button @click="loadData">刷新</el-button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="glass-card section-card">
|
|
|
+ <el-table :data="filteredItems" stripe style="width:100%" v-loading="loading">
|
|
|
+ <el-table-column prop="settlementNo" label="结算单号" width="170" />
|
|
|
+ <el-table-column prop="supplier" label="供应商" min-width="160" />
|
|
|
+ <el-table-column prop="period" label="结算周期" width="180" />
|
|
|
+ <el-table-column prop="poCount" label="采购单数" width="90" align="center" />
|
|
|
+ <el-table-column prop="totalAmount" label="应付金额" width="120">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span style="font-weight:600">{{ row.currency }} {{ row.totalAmount }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="paidAmount" label="已付金额" width="120">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ row.currency }} {{ row.paidAmount }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="status" label="状态" width="90">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag :type="statusTag(row.status)" size="small">{{ row.status }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="dueDate" label="到期日" width="110" />
|
|
|
+ <el-table-column prop="createdAt" label="创建时间" width="160" />
|
|
|
+ <el-table-column label="操作" width="200" fixed="right">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button link type="primary" @click="openDetail(row)">详情</el-button>
|
|
|
+ <el-button link type="primary" @click="openPayment(row)" v-if="row.status === '待付款'">付款</el-button>
|
|
|
+ <el-button link type="primary" @click="closeSettlement(row)" v-if="row.status === '待确认'">确认</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <template #empty>
|
|
|
+ <el-empty description="暂无数据" />
|
|
|
+ </template>
|
|
|
+ </el-table>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="glass-card section-card" style="padding:16px">
|
|
|
+ <div class="stat-grid" style="grid-template-columns:repeat(4, 1fr)">
|
|
|
+ <article class="stat-card">
|
|
|
+ <div class="stat-card__label">本月应付</div>
|
|
|
+ <div class="stat-card__value" style="font-size:24px;color:var(--cb-primary)">$128,500</div>
|
|
|
+ </article>
|
|
|
+ <article class="stat-card">
|
|
|
+ <div class="stat-card__label">本月已付</div>
|
|
|
+ <div class="stat-card__value" style="font-size:24px">$86,200</div>
|
|
|
+ </article>
|
|
|
+ <article class="stat-card">
|
|
|
+ <div class="stat-card__label">待付款</div>
|
|
|
+ <div class="stat-card__value" style="font-size:24px;color:var(--cb-accent)">$42,300</div>
|
|
|
+ </article>
|
|
|
+ <article class="stat-card">
|
|
|
+ <div class="stat-card__label">逾期未付</div>
|
|
|
+ <div class="stat-card__value" style="font-size:24px;color:var(--cb-danger)">$8,500</div>
|
|
|
+ </article>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <el-dialog v-model="detailVisible" title="结算单详情" width="700px" destroy-on-close>
|
|
|
+ <el-descriptions :column="2" border v-if="detailItem">
|
|
|
+ <el-descriptions-item label="结算单号">{{ detailItem.settlementNo }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="供应商">{{ detailItem.supplier }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="结算周期" :span="2">{{ detailItem.period }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="应付金额">{{ detailItem.currency }} {{ detailItem.totalAmount }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="已付金额">{{ detailItem.currency }} {{ detailItem.paidAmount }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="状态">
|
|
|
+ <el-tag :type="statusTag(detailItem.status)">{{ detailItem.status }}</el-tag>
|
|
|
+ </el-descriptions-item>
|
|
|
+ <el-descriptions-item label="到期日">{{ detailItem.dueDate }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="创建时间" :span="2">{{ detailItem.createdAt }}</el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ <el-table :data="poList" stripe size="small" style="margin-top:16px">
|
|
|
+ <el-table-column prop="poNo" label="采购单号" width="150" />
|
|
|
+ <el-table-column prop="poAmount" label="采购金额" width="100" />
|
|
|
+ <el-table-column prop="status" label="状态" width="80" />
|
|
|
+ </el-table>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog v-model="paymentVisible" title="付款确认" width="500px" destroy-on-close>
|
|
|
+ <el-form :model="paymentForm" label-width="100px">
|
|
|
+ <el-form-item label="结算单号">
|
|
|
+ <el-input :value="detailItem?.settlementNo" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="付款金额">
|
|
|
+ <el-input :value="`${detailItem?.currency} ${detailItem?.totalAmount}`" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="付款方式" required>
|
|
|
+ <el-select v-model="paymentForm.method" placeholder="选择付款方式" style="width:100%">
|
|
|
+ <el-option label="银行转账" value="银行转账" />
|
|
|
+ <el-option label="支付宝" value="支付宝" />
|
|
|
+ <el-option label="微信支付" value="微信支付" />
|
|
|
+ <el-option label="信用证" value="信用证" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="付款凭证">
|
|
|
+ <el-upload action="#" :auto-upload="false">
|
|
|
+ <el-button size="small">上传凭证</el-button>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="备注">
|
|
|
+ <el-input v-model="paymentForm.remark" type="textarea" :rows="2" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="paymentVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmPayment">确认付款</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog v-model="createVisible" title="新建结算单" width="560px" destroy-on-close>
|
|
|
+ <el-form :model="createForm" label-width="100px">
|
|
|
+ <el-form-item label="供应商" required>
|
|
|
+ <el-select v-model="createForm.supplier" placeholder="选择供应商" style="width:100%">
|
|
|
+ <el-option v-for="s in suppliers" :key="s" :label="s" :value="s" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="结算周期" required>
|
|
|
+ <el-date-picker v-model="createForm.period" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="关联采购单">
|
|
|
+ <el-select v-model="createForm.poNos" multiple placeholder="选择采购单" style="width:100%">
|
|
|
+ <el-option label="PO-20260415-001 - $12,500" value="PO-20260415-001" />
|
|
|
+ <el-option label="PO-20260410-002 - $8,300" value="PO-20260410-002" />
|
|
|
+ <el-option label="PO-20260405-003 - $15,200" value="PO-20260405-003" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="到期日">
|
|
|
+ <el-date-picker v-model="createForm.dueDate" type="date" placeholder="选择到期日" style="width:100%" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="备注">
|
|
|
+ <el-input v-model="createForm.remark" type="textarea" :rows="2" />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="createVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmCreate">确认创建</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed, onMounted, reactive, ref } from 'vue';
|
|
|
+import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
+
|
|
|
+interface SettlementItem {
|
|
|
+ settlementNo: string;
|
|
|
+ supplier: string;
|
|
|
+ period: string;
|
|
|
+ poCount: number;
|
|
|
+ currency: string;
|
|
|
+ totalAmount: string;
|
|
|
+ paidAmount: string;
|
|
|
+ status: string;
|
|
|
+ dueDate: string;
|
|
|
+ createdAt: string;
|
|
|
+}
|
|
|
+
|
|
|
+const items = ref<SettlementItem[]>([
|
|
|
+ { settlementNo: 'ST-202604-001', supplier: '深圳鼎力供应商', period: '2026-04-01 至 2026-04-15', poCount: 3, currency: 'USD', totalAmount: '25,800', paidAmount: '25,800', status: '已付款', dueDate: '2026-04-30', createdAt: '2026-04-16 10:00:00' },
|
|
|
+ { settlementNo: 'ST-202604-002', supplier: '义乌恒达皮具', period: '2026-04-01 至 2026-04-15', poCount: 2, currency: 'USD', totalAmount: '18,500', paidAmount: '10,000', status: '待付款', dueDate: '2026-04-28', createdAt: '2026-04-16 14:30:00' },
|
|
|
+ { settlementNo: 'ST-202604-003', supplier: '深圳鼎力供应商', period: '2026-04-16 至 2026-04-20', poCount: 2, currency: 'USD', totalAmount: '15,200', paidAmount: '0', status: '待确认', dueDate: '2026-05-05', createdAt: '2026-04-20 09:00:00' },
|
|
|
+ { settlementNo: 'ST-202603-005', supplier: '美国西部仓', period: '2026-03-01 至 2026-03-31', poCount: 4, currency: 'USD', totalAmount: '32,000', paidAmount: '32,000', status: '已付款', dueDate: '2026-04-15', createdAt: '2026-04-01 11:00:00' }
|
|
|
+]);
|
|
|
+
|
|
|
+const poList = ref([{ poNo: 'PO-20260415-001', poAmount: '12,500', status: '已完结' }, { poNo: 'PO-20260410-002', poAmount: '8,300', status: '已完结' }]);
|
|
|
+
|
|
|
+const suppliers = ['深圳鼎力供应商', '义乌恒达皮具', '美国西部仓', '云途物流'];
|
|
|
+const loading = ref(false);
|
|
|
+const detailVisible = ref(false);
|
|
|
+const paymentVisible = ref(false);
|
|
|
+const createVisible = ref(false);
|
|
|
+const detailItem = ref<SettlementItem | null>(null);
|
|
|
+
|
|
|
+const filters = ref({ settlementNo: '', supplier: '', status: '' });
|
|
|
+
|
|
|
+const paymentForm = reactive({ method: '', remark: '' });
|
|
|
+const createForm = reactive({ supplier: '', period: '', poNos: [] as string[], dueDate: '', remark: '' });
|
|
|
+
|
|
|
+const filteredItems = computed(() => {
|
|
|
+ return items.value.filter(item => {
|
|
|
+ if (filters.value.settlementNo && !item.settlementNo.includes(filters.value.settlementNo)) return false;
|
|
|
+ if (filters.value.supplier && item.supplier !== filters.value.supplier) return false;
|
|
|
+ if (filters.value.status && item.status !== filters.value.status) return false;
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+const statusTag = (status: string) => {
|
|
|
+ const map: Record<string, string> = { '待确认': 'warning', '待付款': 'primary', '已付款': 'success', '已关闭': 'info' };
|
|
|
+ return map[status] || '';
|
|
|
+};
|
|
|
+
|
|
|
+const loadData = () => { loading.value = true; setTimeout(() => { loading.value = false; }, 300); };
|
|
|
+const resetFilters = () => { filters.value = { settlementNo: '', supplier: '', status: '' }; };
|
|
|
+
|
|
|
+const openDetail = (row: SettlementItem) => { detailItem.value = row; detailVisible.value = true; };
|
|
|
+const openPayment = (row: SettlementItem) => { detailItem.value = row; Object.assign(paymentForm, { method: '', remark: '' }); paymentVisible.value = true; };
|
|
|
+const closeSettlement = async (row: SettlementItem) => { await ElMessageBox.confirm('确认此结算单?', '确认'); const idx = items.value.findIndex(i => i.settlementNo === row.settlementNo); if (idx !== -1) items.value[idx].status = '待付款'; ElMessage.success('已确认'); };
|
|
|
+
|
|
|
+const confirmPayment = async () => {
|
|
|
+ if (!paymentForm.method) { ElMessage.warning('请选择付款方式'); return; }
|
|
|
+ const idx = items.value.findIndex(i => i.settlementNo === detailItem.value!.settlementNo);
|
|
|
+ if (idx !== -1) items.value[idx].status = '已付款';
|
|
|
+ paymentVisible.value = false;
|
|
|
+ ElMessage.success('付款已确认');
|
|
|
+};
|
|
|
+
|
|
|
+const openCreate = () => { Object.assign(createForm, { supplier: '', period: '', poNos: [], dueDate: '', remark: '' }); createVisible.value = true; };
|
|
|
+
|
|
|
+const confirmCreate = async () => {
|
|
|
+ if (!createForm.supplier || !createForm.period) { ElMessage.warning('请填写必填项'); return; }
|
|
|
+ items.value.unshift({ settlementNo: `ST-${new Date().toISOString().slice(0, 7).replace(/-/g, '')}-${String(items.value.length + 1).padStart(3, '0')}`, supplier: createForm.supplier, period: '自定义周期', poCount: createForm.poNos.length, currency: 'USD', totalAmount: '0', paidAmount: '0', status: '待确认', dueDate: '', createdAt: new Date().toLocaleString() });
|
|
|
+ createVisible.value = false;
|
|
|
+ ElMessage.success('结算单已创建');
|
|
|
+};
|
|
|
+
|
|
|
+const doExport = () => { ElMessage.info('导出开始'); };
|
|
|
+
|
|
|
+onMounted(loadData);
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.filter-form :deep(.el-form-item) { margin-bottom: 0; }
|
|
|
+</style>
|