| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æç´¢æ --> |
| | | <div class="search_form" style="display: flex; justify-content: space-between; gap: 12px; align-items: flex-start;"> |
| | | <div style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px;"> |
| | | <span class="search_title">ç»ç®åå·:</span> |
| | | <el-input |
| | | v-model="searchForm.settleNo" |
| | | style="width: 240px" |
| | | placeholder="ç»ç®åå·" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | <span class="search_title">æ¿è¿å:</span> |
| | | <el-input |
| | | v-model="searchForm.carrierName" |
| | | style="width: 240px" |
| | | placeholder="æ¿è¿å" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @keyup.enter="handleQuery" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery">æç´¢</el-button> |
| | | <el-button @click="resetQuery">éç½®</el-button> |
| | | </div> |
| | | |
| | | <div> |
| | | <el-button type="primary" @click="openCreate">å建ç»ç®å</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- è¡¨æ ¼ --> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <div class="table_list"> |
| | | <el-table |
| | | border |
| | | v-loading="tableLoading" |
| | | :data="tableData" |
| | | :header-cell-style="{ background: '#F0F1F5', color: '#333333' }" |
| | | height="calc(100vh - 18.5em)" |
| | | :highlight-current-row="true" |
| | | style="width: 100%" |
| | | stripe |
| | | tooltip-effect="dark" |
| | | class="lims-table" |
| | | > |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column label="ç»ç®åå·" prop="settleNo" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="æ¿è¿å" prop="carrierName" width="200" show-overflow-tooltip /> |
| | | <el-table-column label="å票å·ç " prop="invoiceNo" width="160" show-overflow-tooltip /> |
| | | <el-table-column label="å票éé¢(å
)" prop="invoiceAmt" width="140" align="right"> |
| | | <template #default="{ row }">{{ toMoney(row.invoiceAmt) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å¼ç¥¨æ¥æ" prop="invoiceDate" width="120" /> |
| | | <el-table-column label="æ´æ°æ¶é´" prop="updateTime" width="170" /> |
| | | |
| | | <el-table-column fixed="right" label="æä½" width="200" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click.stop="openView(scope.row)">æ¥ç</el-button> |
| | | <el-button link type="primary" size="small" @click.stop="openEdit(scope.row)">ç¼è¾</el-button> |
| | | <el-button link type="danger" size="small" @click.stop="handleDelete(scope.row)">å é¤</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination |
| | | v-show="total > 0" |
| | | @pagination="paginationSearch" |
| | | :total="total" |
| | | :layout="page.layout" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | /> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- å建/ç¼è¾å¼¹çª --> |
| | | <el-dialog |
| | | v-model="editVisible" |
| | | :title="editMode === 'create' ? 'å建ç»ç®å' : 'ç¼è¾ç»ç®å'" |
| | | width="720px" |
| | | :close-on-click-modal="false" |
| | | destroy-on-close |
| | | > |
| | | <el-form ref="editFormRef" :model="editForm" :rules="rules" label-width="120px"> |
| | | <el-row :gutter="12"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»ç®åå·" prop="settleNo"> |
| | | <el-input v-model="editForm.settleNo" placeholder="å¦ FS-20260130-0001" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¿è¿ååç§°" prop="carrierName"> |
| | | <el-input v-model="editForm.carrierName" placeholder="请è¾å
¥æ¿è¿ååç§°" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票å·ç " prop="invoiceNo"> |
| | | <el-input v-model="editForm.invoiceNo" placeholder="请è¾å
¥å票å·" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票éé¢(å
)" prop="invoiceAmt"> |
| | | <el-input-number v-model="editForm.invoiceAmt" :min="0" :precision="2" style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼ç¥¨æ¥æ" prop="invoiceDate"> |
| | | <el-date-picker |
| | | v-model="editForm.invoiceDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | <template #footer> |
| | | <el-button @click="editVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" :loading="saving" @click="submitEdit">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- æ¥çå¼¹çª --> |
| | | <el-dialog v-model="viewVisible" title="ç»ç®åä¿¡æ¯æ¥ç" width="720px" destroy-on-close> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="ç»ç®åå·">{{ viewRow.settleNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¿è¿å">{{ viewRow.carrierName }}</el-descriptions-item> |
| | | <el-descriptions-item label="å票å·ç ">{{ viewRow.invoiceNo }}</el-descriptions-item> |
| | | <el-descriptions-item label="å票éé¢(å
)">{{ toMoney(viewRow.invoiceAmt) }}</el-descriptions-item> |
| | | <el-descriptions-item label="å¼ç¥¨æ¥æ">{{ viewRow.invoiceDate }}</el-descriptions-item> |
| | | <el-descriptions-item label="å建æ¶é´">{{ viewRow.createTime }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ´æ°æ¶é´">{{ viewRow.updateTime }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | <template #footer> |
| | | <el-button @click="viewVisible = false">å
³é</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import pagination from "@/components/PIMTable/Pagination.vue"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | getFreightSettlementPage, |
| | | getFreightSettlementDetail, |
| | | addFreightSettlement, |
| | | updateFreightSettlement, |
| | | deleteFreightSettlement, |
| | | } from "@/api/inventoryManagement/CarrierManagement"; |
| | | |
| | | const toMoney = (v) => { |
| | | if (v === undefined || v === null || v === "") return "0.00"; |
| | | const n = Number(v); |
| | | return Number.isFinite(n) ? n.toFixed(2) : "0.00"; |
| | | }; |
| | | |
| | | // éé
åç«¯åæ®µ |
| | | const normalizeRow = (raw = {}) => { |
| | | return { |
| | | id: raw.id, |
| | | settleNo: raw.settleNo, |
| | | carrierName: raw.carrierName, |
| | | invoiceNo: raw.invoiceNo, |
| | | invoiceAmt: raw.invoiceAmt, |
| | | invoiceDate: raw.invoiceDate, |
| | | createTime: raw.createTime, |
| | | updateTime: raw.updateTime, |
| | | }; |
| | | }; |
| | | |
| | | // ------------------ 页é¢ç¶æ ------------------ |
| | | const searchForm = reactive({ |
| | | keyword: "", |
| | | invoiceDateRange: [], |
| | | invoiceDateStart: undefined, |
| | | invoiceDateEnd: undefined, |
| | | }); |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | layout: "total, sizes, prev, pager, next, jumper", |
| | | }); |
| | | |
| | | const total = ref(0); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | const buildListParams = () => { |
| | | return { |
| | | current: page.current, |
| | | size: page.size, |
| | | settleNo: searchForm.settleNo || undefined, |
| | | carrierName: searchForm.carrierName || undefined, |
| | | }; |
| | | }; |
| | | |
| | | const changeDateRange = (date) => { |
| | | if (date && date.length === 2) { |
| | | searchForm.invoiceDateStart = date[0]; |
| | | searchForm.invoiceDateEnd = date[1]; |
| | | } else { |
| | | searchForm.invoiceDateStart = undefined; |
| | | searchForm.invoiceDateEnd = undefined; |
| | | } |
| | | getList(); |
| | | }; |
| | | |
| | | const clearRange = () => { |
| | | searchForm.invoiceDateRange = []; |
| | | getList(); |
| | | }; |
| | | |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const resetQuery = () => { |
| | | searchForm.keyword = ""; |
| | | searchForm.invoiceDateRange = []; |
| | | searchForm.invoiceDateStart = undefined; |
| | | searchForm.invoiceDateEnd = undefined; |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const paginationSearch = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = async () => { |
| | | tableLoading.value = true; |
| | | try { |
| | | const res = await getFreightSettlementPage(buildListParams()); |
| | | const data = res?.data ?? res; |
| | | const records = data?.records ?? data?.rows ?? data?.list ?? []; |
| | | const t = data?.total ?? data?.count ?? 0; |
| | | |
| | | tableData.value = (records || []).map(normalizeRow); |
| | | total.value = t; |
| | | } catch (e) { |
| | | ElMessage.error(e?.message || e?.msg || "å 载失败"); |
| | | } finally { |
| | | tableLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | // ------------------ å建/ç¼è¾/æ¥ç/å é¤ ------------------ |
| | | const editVisible = ref(false); |
| | | const viewVisible = ref(false); |
| | | const editMode = ref("create"); |
| | | const saving = ref(false); |
| | | const editFormRef = ref(); |
| | | |
| | | const editForm = reactive({ |
| | | id: undefined, |
| | | settleNo: "", |
| | | carrierName: "", |
| | | invoiceNo: "", |
| | | invoiceAmt: 0, |
| | | invoiceDate: "", |
| | | }); |
| | | |
| | | const rules = { |
| | | settleNo: [{ required: true, message: "请è¾å
¥ç»ç®åå·", trigger: "blur" }], |
| | | carrierName: [{ required: true, message: "请è¾å
¥æ¿è¿ååç§°", trigger: "blur" }], |
| | | invoiceNo: [{ required: true, message: "请è¾å
¥å票å·ç ", trigger: "blur" }], |
| | | invoiceAmt: [{ required: true, message: "请è¾å
¥å票éé¢", trigger: "change" }, |
| | | {validator: (rule, value, callback) => {if (value <= 0) {callback(new Error("å票éé¢å¿
须大äº0"));} else {callback();}}, trigger: "change",}], |
| | | invoiceDate: [{ required: true, message: "è¯·éæ©å¼ç¥¨æ¥æ", trigger: "change" }], |
| | | }; |
| | | |
| | | const openCreate = () => { |
| | | editMode.value = "create"; |
| | | Object.assign(editForm, { |
| | | id: undefined, |
| | | settleNo: `FS-${dayjs().format("YYYYMMDD")}-${String(Math.floor(Math.random() * 9000 + 1000))}`, |
| | | carrierName: "", |
| | | invoiceNo: "", |
| | | invoiceAmt: 0, |
| | | invoiceDate: dayjs().format("YYYY-MM-DD"), |
| | | }); |
| | | editVisible.value = true; |
| | | queueMicrotask(() => editFormRef.value?.clearValidate?.()); |
| | | }; |
| | | |
| | | const openEdit = async (row) => { |
| | | editMode.value = "edit"; |
| | | Object.assign(editForm, { ...row }); |
| | | |
| | | if (row?.id) { |
| | | try { |
| | | const res = await getFreightSettlementDetail(row.id); |
| | | const detail = res?.data ?? res; |
| | | Object.assign(editForm, normalizeRow(detail)); |
| | | } catch { |
| | | // ignore |
| | | } |
| | | } |
| | | |
| | | editVisible.value = true; |
| | | queueMicrotask(() => editFormRef.value?.clearValidate?.()); |
| | | }; |
| | | |
| | | const viewRow = reactive({}); |
| | | const openView = async (row) => { |
| | | Object.assign(viewRow, row); |
| | | viewVisible.value = true; |
| | | |
| | | if (row?.id) { |
| | | try { |
| | | const res = await getFreightSettlementDetail(row.id); |
| | | const detail = res?.data ?? res; |
| | | Object.assign(viewRow, normalizeRow(detail)); |
| | | } catch { |
| | | // ignore |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const submitEdit = async () => { |
| | | saving.value = true; |
| | | try { |
| | | await editFormRef.value?.validate?.(); |
| | | |
| | | const payload = { |
| | | id: editForm.id, |
| | | settleNo: editForm.settleNo, |
| | | carrierName: editForm.carrierName, |
| | | invoiceNo: editForm.invoiceNo, |
| | | invoiceAmt: editForm.invoiceAmt, |
| | | invoiceDate: editForm.invoiceDate, |
| | | }; |
| | | |
| | | if (editMode.value === "create") { |
| | | await addFreightSettlement(payload); |
| | | ElMessage.success("å建æå"); |
| | | page.current = 1; |
| | | } else { |
| | | await updateFreightSettlement(payload); |
| | | ElMessage.success("æ´æ°æå"); |
| | | } |
| | | |
| | | editVisible.value = false; |
| | | await getList(); |
| | | } catch (e) { |
| | | if (e?.message) ElMessage.error(e.message); |
| | | } finally { |
| | | saving.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handleDelete = async (row) => { |
| | | await ElMessageBox.confirm(`确认å é¤ç»ç®åã${row.settleNo}ãï¼`, "æç¤º", { |
| | | confirmButtonText: "å é¤", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | |
| | | tableLoading.value = true; |
| | | try { |
| | | await deleteFreightSettlement(row.id); |
| | | ElMessage.success("å 餿å"); |
| | | |
| | | // å é¤å妿å½åé¡µæ æ°æ®ååé |
| | | const res = await getFreightSettlementPage(buildListParams()); |
| | | const data = res?.data ?? res; |
| | | const records = data?.records ?? data?.rows ?? data?.list ?? []; |
| | | if ((records || []).length === 0 && page.current > 1) { |
| | | page.current -= 1; |
| | | } |
| | | |
| | | await getList(); |
| | | } catch (e) { |
| | | ElMessage.error(e?.message || e?.msg || "å é¤å¤±è´¥"); |
| | | } finally { |
| | | tableLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .el-pagination { |
| | | width: 100%; |
| | | height: 55px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | float: right; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | background: #fff; |
| | | margin: -20px 0 0 0; |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | .pagination-container { |
| | | margin-top: 0; |
| | | } |
| | | </style> |