| | |
| | | <el-form :model="searchForm" class="demo-form-inline"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-form-item label="退货单号"> |
| | | <el-input v-model="searchForm.returnNo" placeholder="请输入退货单号" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-form-item label="客户名称"> |
| | | <el-input v-model="searchForm.customerName" placeholder="客户名称" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-form-item label="销售单号"> |
| | | <el-input v-model="searchForm.salesContractNo" placeholder="销售单号" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-form-item label="关联出库单号"> |
| | | <el-input v-model="searchForm.shippingNo" placeholder="关联出库单号" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div class="table_header" style="display:flex;justify-content:space-between;align-items:center;"> |
| | | <div> |
| | | <div class="table_header" style="display: flex;justify-content: flex-end;margin-bottom: 10px;"> |
| | | <el-button type="primary" @click="openForm('add')">新建销售退货</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="danger" plain @click="handleDelete">删除</el-button> |
| | | <el-button @click="columnsDialogVisible = true">列表字段</el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="visibleColumns" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | /> |
| | | > |
| | | <template #status="{ row }"> |
| | | <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery" /> |
| | | |
| | | <el-dialog v-model="columnsDialogVisible" title="自定义显示列项" width="600px"> |
| | | <div class="columns-tip">注:列表项显示不得少于5项;拖动右侧把手可调整显示顺序</div> |
| | | <ul class="columns-list"> |
| | | <li v-for="(col, idx) in allColumns" :key="col.prop" |
| | | class="columns-item" |
| | | draggable="true" |
| | | @dragstart="onDragStart(idx)" |
| | | @dragover.prevent |
| | | @drop="onDrop(idx)"> |
| | | <el-checkbox v-model="col.selected">{{ col.label }}</el-checkbox> |
| | | <span class="drag-handle">≡</span> |
| | | </li> |
| | | </ul> |
| | | <template #footer> |
| | | <el-button @click="resetColumns">恢复默认</el-button> |
| | | <el-button type="primary" @click="saveColumns">保存</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | <detail-dia ref="detailDia" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { reactive, ref, toRefs, computed, getCurrentInstance, nextTick, onMounted } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import FormDia from "./components/formDia.vue"; |
| | | import DetailDia from "./components/detailDia.vue"; |
| | | import { returnManagementList, returnManagementDel, returnManagementHandle } from "@/api/salesManagement/returnOrder.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const formDia = ref(); |
| | | const detailDia = ref(); |
| | | const openForm = (type, row) => { |
| | | nextTick(() => formDia.value?.openDialog(type, row)); |
| | | }; |
| | | |
| | | const openDetail = (row) => { |
| | | nextTick(() => detailDia.value?.openDialog(row)); |
| | | }; |
| | | |
| | | const handleRowDelete = (row) => { |
| | |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const documentStatusOptions = ref([ |
| | | { label: "待审核", value: 0 }, |
| | | { label: "审核中", value: 1 }, |
| | | { label: "已审核", value: 2 } |
| | | { label: "待处理", value: 0 }, |
| | | { label: "已处理", value: 1 } |
| | | ]); |
| | | |
| | | const defaultColumns = [ |
| | | { label: "退货单号", prop: "returnNo", minWidth: 160 }, |
| | | { label: "单据状态", prop: "status", minWidth: 120, formatData: (v) => ({ "0": "待审核", "1": "审核中", "2": "已审核" }[String(v)] ?? v) }, |
| | | { label: "制单时间", prop: "makeTime", minWidth: 170 }, |
| | | { label: "客户名称", prop: "customerName", minWidth: 220 }, |
| | | { label: "销售单号", prop: "salesContractNo", minWidth: 160 }, |
| | | { label: "业务员", prop: "salesman", minWidth: 120 }, |
| | | { label: "关联出库单号", prop: "shippingNo", minWidth: 170 }, |
| | | { label: "项目名称", prop: "projectName", minWidth: 180 }, |
| | | { label: "项目阶段", prop: "projectStage", minWidth: 120 }, |
| | | { label: "制单人", prop: "maker", minWidth: 120 }, |
| | | { label: "结算人", prop: "settler", minWidth: 120 }, |
| | | { label: "退货单号", prop: "returnNo", width: 160 }, |
| | | { label: "单据状态", prop: "status", width: 90, dataType: "slot", slot: "status" }, |
| | | { label: "制单时间", prop: "makeTime", width: 170 }, |
| | | { label: "客户名称", prop: "customerName", width: 220 }, |
| | | { label: "销售单号", prop: "salesContractNo", width: 160 }, |
| | | { label: "业务员", prop: "salesman", width: 120 }, |
| | | { label: "关联出库单号", prop: "shippingNo", width: 170 }, |
| | | { label: "项目名称", prop: "projectName", width: 180 }, |
| | | { label: "制单人", prop: "maker", width: 120 }, |
| | | { |
| | | label: "操作", |
| | | prop: "operation", |
| | | dataType: "action", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 160, |
| | | width: 240, |
| | | operation: [ |
| | | { name: "编辑", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => openForm("edit", row) }, |
| | | { name: "处理", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => handleRowHandle(row) }, |
| | | { name: "退款处理", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => handleRowHandle(row) }, |
| | | { name: "详情", type: "text", clickFun: (row) => openDetail(row) }, |
| | | { name: "删除", disabled: (row) => row.status !== 0, type: "text", clickFun: (row) => handleRowDelete(row) }, |
| | | ], |
| | | }, |
| | | ]; |
| | | const COLUMNS_KEY = "return_order_columns_v2"; |
| | | const columnsDialogVisible = ref(false); |
| | | const allColumns = ref([]); |
| | | |
| | | const initColumns = () => { |
| | | const saved = localStorage.getItem(COLUMNS_KEY); |
| | | if (saved) { |
| | | try { |
| | | const parsed = JSON.parse(saved); |
| | | // 合并默认列与已保存配置,避免后续新增列丢失 |
| | | const map = new Map(parsed.map(c => [c.prop, c])); |
| | | allColumns.value = defaultColumns.map(d => { |
| | | const found = map.get(d.prop); |
| | | return { ...d, selected: found ? !!found.selected : true }; |
| | | }); |
| | | // 以保存的顺序为准 |
| | | const order = parsed.map(p => p.prop); |
| | | allColumns.value.sort((a, b) => order.indexOf(a.prop) - order.indexOf(b.prop)); |
| | | return; |
| | | } catch {} |
| | | } |
| | | allColumns.value = defaultColumns.map(c => ({ ...c, selected: true })); |
| | | }; |
| | | initColumns(); |
| | | |
| | | const visibleColumns = computed(() => allColumns.value.filter(c => c.selected)); |
| | | |
| | | let dragFrom = -1; |
| | | const onDragStart = (idx) => { |
| | | dragFrom = idx; |
| | | }; |
| | | const onDrop = (to) => { |
| | | if (dragFrom < 0 || dragFrom === to) return; |
| | | const arr = [...allColumns.value]; |
| | | const [moved] = arr.splice(dragFrom, 1); |
| | | arr.splice(to, 0, moved); |
| | | allColumns.value = arr; |
| | | dragFrom = -1; |
| | | }; |
| | | |
| | | const resetColumns = () => { |
| | | allColumns.value = defaultColumns.map(c => ({ ...c, selected: true })); |
| | | localStorage.removeItem(COLUMNS_KEY); |
| | | }; |
| | | const saveColumns = () => { |
| | | const toSave = allColumns.value.map(({ label, prop, width, selected }) => ({ label, prop, width, selected })); |
| | | localStorage.setItem(COLUMNS_KEY, JSON.stringify(toSave)); |
| | | columnsDialogVisible.value = false; |
| | | }; |
| | | const tableColumn = defaultColumns; |
| | | |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | |
| | | |
| | | const handleReset = () => { |
| | | Object.keys(searchForm.value).forEach(k => searchForm.value[k] = ""); |
| | | handleQuery(); |
| | | }; |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | |
| | | }); |
| | | }; |
| | | |
| | | const getStatusType = (status) => { |
| | | const statusMap = { |
| | | 0: "warning", |
| | | 1: "success" |
| | | }; |
| | | return statusMap[status] || "info"; |
| | | }; |
| | | |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | 0: "待处理", |
| | | 1: "已处理" |
| | | }; |
| | | return statusMap[status] || "未知"; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | |
| | | padding: 1rem 1rem 0 1rem; |
| | | border: 8px; |
| | | border-radius: 16px; |
| | | } |
| | | .table_list { |
| | | height: calc(100vh - 230px); |
| | | min-height: 360px; |
| | | background: #fff; |
| | | margin-top: 20px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .columns-tip{color:#909399;margin-bottom:10px;font-size:12px;} |
| | | .columns-list{list-style:none;padding:0;margin:0;max-height:360px;overflow:auto;} |
| | | .columns-item{display:flex;justify-content:space-between;align-items:center;padding:8px 10px;border:1px solid #f0f0f0;border-radius:6px;margin-bottom:8px;cursor:move;background:#fff;} |
| | | .columns-item .drag-handle{color:#909399;padding-left:12px;user-select:none;} |
| | | .table_header { |
| | | margin-bottom: 15px; |
| | | } |
| | | </style> |