合并河南鹤壁问题
1、客户往来没有合同金额
2、销售台账需要详情按钮查看
3、主生产计划,统一居左展示。把销售合同号移到前面展示而不是往后拉才可以看到
4、设备报修-只需要展示关键数据。新增一个详情按钮,其他数据在详情里查看
5、计量器台账-应该是叫编辑而不是查看
6、设备巡检tab页更名、表格无法拖拉问题
7、任务管理不需要巡检结果
8、 反馈登记-问题描述修改为客户诉求
| | |
| | | }) |
| | | |
| | | // 详情模式不展示“确认”按钮,其它类型正常显示 |
| | | const showConfirm = computed(() => props.operationType !== 'detail') |
| | | const showConfirm = computed(() => props.operationType !== 'detail' && props.operationType !== 'view') |
| | | |
| | | const computedTitle = computed(() => { |
| | | if (typeof props.title === 'function') { |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item label="问题描述:" |
| | | <el-form-item label="客户诉求:" |
| | | prop="proDesc"> |
| | | <el-input v-model="form.proDesc" |
| | | placeholder="请输入问题描述" /> |
| | | placeholder="请输入客户诉求" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="workorder-stats"> |
| | | <div |
| | | v-for="(item, index) in statsList" |
| | | :key="index" |
| | | class="stat-card" |
| | | > |
| | | <div class="stat-icon" :style="{ backgroundColor: item.bgColor }"> |
| | | <el-icon :color="item.color" :size="20"> |
| | | <div v-for="(item, index) in statsList" |
| | | :key="index" |
| | | class="stat-card"> |
| | | <div class="stat-icon" |
| | | :style="{ backgroundColor: item.bgColor }"> |
| | | <el-icon :color="item.color" |
| | | :size="20"> |
| | | <component :is="item.icon" /> |
| | | </el-icon> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | <div class="search-wrapper"> |
| | | <el-form |
| | | :model="searchForm" |
| | | class="demo-form-inline" |
| | | > |
| | | <el-form :model="searchForm" |
| | | class="demo-form-inline"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-input |
| | | v-model="searchForm.afterSalesServiceNo" |
| | | placeholder="请输入工单编号" |
| | | clearable |
| | | /> |
| | | <el-input v-model="searchForm.afterSalesServiceNo" |
| | | placeholder="请输入工单编号" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-select |
| | | v-model="searchForm.status" |
| | | placeholder="请选择工单状态" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="dict in workOrderStatusOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | <el-select v-model="searchForm.status" |
| | | placeholder="请选择工单状态" |
| | | clearable> |
| | | <el-option v-for="dict in workOrderStatusOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-select |
| | | v-model="searchForm.urgency" |
| | | placeholder="请选择紧急程度" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="dict in degreeOfUrgencyOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | <el-select v-model="searchForm.urgency" |
| | | placeholder="请选择紧急程度" |
| | | clearable> |
| | | <el-option v-for="dict in degreeOfUrgencyOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-select |
| | | v-model="searchForm.serviceType" |
| | | placeholder="请选择售后类型" |
| | | clearable |
| | | > |
| | | <el-option |
| | | v-for="dict in classificationOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" |
| | | /> |
| | | <el-select v-model="searchForm.serviceType" |
| | | placeholder="请选择售后类型" |
| | | clearable> |
| | | <el-option v-for="dict in classificationOptions" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="dict.value" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-input |
| | | v-model="searchForm.orderNo" |
| | | placeholder="请输入销售单号" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | |
| | | |
| | | |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-input v-model="searchForm.orderNo" |
| | | placeholder="请输入销售单号" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- 按钮 --> |
| | | <el-col :span="4"> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery"> |
| | | <el-button type="primary" |
| | | @click="handleQuery"> |
| | | 搜索 |
| | | </el-button> |
| | | <el-button @click="handleReset"> |
| | |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div class="table_header" style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div class="table_header" |
| | | style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">新增售后单</el-button> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">新增售后单</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button @click="handleOut">导出</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">删除</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除</el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :height="tableHeight" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :height="tableHeight" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination"></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | <form-dia ref="formDia" |
| | | @close="handleQuery"></form-dia> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, reactive, ref, toRefs, computed, getCurrentInstance, nextTick} from "vue"; |
| | | import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import {afterSalesServiceDelete, afterSalesServiceListPage, getSalesLedgerDetail} from "@/api/customerService/index.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore() |
| | | import { Document, FolderOpened, UserFilled } from "@element-plus/icons-vue" |
| | | import { markRaw } from 'vue' |
| | | import { |
| | | onMounted, |
| | | reactive, |
| | | ref, |
| | | toRefs, |
| | | computed, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import FormDia from "@/views/customerService/feedbackRegistration/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { |
| | | afterSalesServiceDelete, |
| | | afterSalesServiceListPage, |
| | | getSalesLedgerDetail, |
| | | } from "@/api/customerService/index.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | import { Document, FolderOpened, UserFilled } from "@element-plus/icons-vue"; |
| | | import { markRaw } from "vue"; |
| | | |
| | | const statsList = ref([ |
| | | { |
| | | icon: markRaw(Document), |
| | | count: 0, |
| | | label: '全部工单', |
| | | color: '#4080ff', |
| | | bgColor: '#eaf2ff' |
| | | }, |
| | | { |
| | | icon: markRaw(FolderOpened), |
| | | count: 0, |
| | | label: '已处理', |
| | | color: '#ff9a2e', |
| | | bgColor: '#fff5e6' |
| | | }, |
| | | { |
| | | icon: markRaw(UserFilled), |
| | | count: 0, |
| | | label: '已完成', |
| | | color: '#00b42a', |
| | | bgColor: '#e6f7ed' |
| | | }, |
| | | ]) |
| | | |
| | | const data = reactive({ |
| | | searchForm : { |
| | | customerName: "", |
| | | status: "", |
| | | urgency: "", |
| | | serviceType: "", |
| | | reviewStatus: "", |
| | | orderNo: "", |
| | | } |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "工单编号", |
| | | prop:"afterSalesServiceNo", |
| | | width: 150, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "销售单号", |
| | | prop:"salesContractNo", |
| | | width: 150, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "处理状态", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | |
| | | formatData: (params) => { |
| | | if (params) { |
| | | let part = String(params) |
| | | const item = workOrderStatusOptions.value.find(item => item.value === part); |
| | | return item?.label || params; |
| | | } |
| | | return null; |
| | | const statsList = ref([ |
| | | { |
| | | icon: markRaw(Document), |
| | | count: 0, |
| | | label: "全部工单", |
| | | color: "#4080ff", |
| | | bgColor: "#eaf2ff", |
| | | }, |
| | | formatType: (params) => { |
| | | if (params === 1) { |
| | | return "danger"; |
| | | } else if (params === 2) { |
| | | return "success"; |
| | | } else { |
| | | { |
| | | icon: markRaw(FolderOpened), |
| | | count: 0, |
| | | label: "已处理", |
| | | color: "#ff9a2e", |
| | | bgColor: "#fff5e6", |
| | | }, |
| | | { |
| | | icon: markRaw(UserFilled), |
| | | count: 0, |
| | | label: "已完成", |
| | | color: "#00b42a", |
| | | bgColor: "#e6f7ed", |
| | | }, |
| | | ]); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | customerName: "", |
| | | status: "", |
| | | urgency: "", |
| | | serviceType: "", |
| | | reviewStatus: "", |
| | | orderNo: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "工单编号", |
| | | prop: "afterSalesServiceNo", |
| | | width: 150, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "销售单号", |
| | | prop: "salesContractNo", |
| | | width: 150, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "处理状态", |
| | | prop: "status", |
| | | dataType: "tag", |
| | | |
| | | formatData: params => { |
| | | if (params) { |
| | | let part = String(params); |
| | | const item = workOrderStatusOptions.value.find( |
| | | item => item.value === part |
| | | ); |
| | | return item?.label || params; |
| | | } |
| | | return null; |
| | | } |
| | | }, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "反馈日期", |
| | | prop: "feedbackDate", |
| | | width: 150, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "登记人", |
| | | prop: "checkNickName", |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "紧急程度", |
| | | prop: "urgency", |
| | | // 根据degreeOfUrgencyOptions字典去自动匹配 |
| | | formatData: (params) => { |
| | | if (params) { |
| | | const item = degreeOfUrgencyOptions.value.find(item => item.value === params); |
| | | return item?.label || params; |
| | | } |
| | | return null; |
| | | }, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "售后类型", |
| | | prop: "serviceType", |
| | | // 根据classificationOptions字典去自动匹配 |
| | | formatData: (params) => { |
| | | if (params) { |
| | | const item = classificationOptions.value.find(item => item.value === params); |
| | | return item?.label || params; |
| | | } |
| | | return null; |
| | | }, |
| | | align: "center" |
| | | }, |
| | | { |
| | | label: "问题描述", |
| | | prop: "proDesc", |
| | | width:300, |
| | | }, |
| | | { |
| | | label: "关联部门", |
| | | prop: "deptName", |
| | | width: 200, |
| | | align: "center" |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | console.log(row) |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: (row) => { |
| | | return row.status !== 1 |
| | | }, |
| | | formatType: params => { |
| | | if (params === 1) { |
| | | return "danger"; |
| | | } else if (params === 2) { |
| | | return "success"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | ], |
| | | align: "center" |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | const tableHeight = computed(() => "calc(100% -80px)"); |
| | | |
| | | const handleReset = () => { |
| | | Object.keys(searchForm.value).forEach(key => { |
| | | searchForm.value[key] = "" |
| | | }) |
| | | page.current = 1; |
| | | getList(); |
| | | } |
| | | // 表格选择数据 |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref() |
| | | |
| | | // 字典获取 |
| | | /* |
| | | post_sale_waiting_list 新增的售后分类 |
| | | degree_of_urgency 新增的紧急程度 |
| | | work_order_status 主页的工单状态 |
| | | review_status 首页的审核状态 |
| | | */ |
| | | const { post_sale_waiting_list, degree_of_urgency, work_order_status, review_status } = proxy.useDict( |
| | | "post_sale_waiting_list", |
| | | "degree_of_urgency", |
| | | "work_order_status", |
| | | "review_status" |
| | | ); |
| | | |
| | | const classificationOptions = computed(() => post_sale_waiting_list?.value || []); |
| | | const degreeOfUrgencyOptions = computed(() => degree_of_urgency?.value || []); |
| | | const workOrderStatusOptions = computed(() => work_order_status?.value || []); |
| | | |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getSalesLedgerDetails() |
| | | afterSalesServiceListPage({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "反馈日期", |
| | | prop: "feedbackDate", |
| | | width: 150, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "登记人", |
| | | prop: "checkNickName", |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "紧急程度", |
| | | prop: "urgency", |
| | | // 根据degreeOfUrgencyOptions字典去自动匹配 |
| | | formatData: params => { |
| | | if (params) { |
| | | const item = degreeOfUrgencyOptions.value.find( |
| | | item => item.value === params |
| | | ); |
| | | return item?.label || params; |
| | | } |
| | | return null; |
| | | }, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "售后类型", |
| | | prop: "serviceType", |
| | | // 根据classificationOptions字典去自动匹配 |
| | | formatData: params => { |
| | | if (params) { |
| | | const item = classificationOptions.value.find( |
| | | item => item.value === params |
| | | ); |
| | | return item?.label || params; |
| | | } |
| | | return null; |
| | | }, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "客户诉求", |
| | | prop: "proDesc", |
| | | width: 300, |
| | | }, |
| | | { |
| | | label: "关联部门", |
| | | prop: "deptName", |
| | | width: 200, |
| | | align: "center", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | fixed: "right", |
| | | operation: [ |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: row => { |
| | | console.log(row); |
| | | openForm("edit", row); |
| | | }, |
| | | disabled: row => { |
| | | return row.status !== 1; |
| | | }, |
| | | }, |
| | | ], |
| | | align: "center", |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | }; |
| | | const selectedRows = ref([]); |
| | | const tableHeight = computed(() => "calc(100% -80px)"); |
| | | |
| | | // 打开弹框 |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | const handleReset = () => { |
| | | Object.keys(searchForm.value).forEach(key => { |
| | | searchForm.value[key] = ""; |
| | | }); |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | // 表格选择数据 |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref(); |
| | | |
| | | function handleDelete() { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // 检查是否有他人维护的数据 |
| | | const unauthorizedData = selectedRows.value.filter(item => item.checkUserId !== userStore.id); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("不可删除他人维护的数据"); |
| | | // 字典获取 |
| | | /* |
| | | post_sale_waiting_list 新增的售后分类 |
| | | degree_of_urgency 新增的紧急程度 |
| | | work_order_status 主页的工单状态 |
| | | review_status 首页的审核状态 |
| | | */ |
| | | const { |
| | | post_sale_waiting_list, |
| | | degree_of_urgency, |
| | | work_order_status, |
| | | review_status, |
| | | } = proxy.useDict( |
| | | "post_sale_waiting_list", |
| | | "degree_of_urgency", |
| | | "work_order_status", |
| | | "review_status" |
| | | ); |
| | | |
| | | const classificationOptions = computed( |
| | | () => post_sale_waiting_list?.value || [] |
| | | ); |
| | | const degreeOfUrgencyOptions = computed(() => degree_of_urgency?.value || []); |
| | | const workOrderStatusOptions = computed(() => work_order_status?.value || []); |
| | | |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | getSalesLedgerDetails(); |
| | | afterSalesServiceListPage({ ...searchForm.value, ...page }).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }); |
| | | }; |
| | | |
| | | // 打开弹框 |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | |
| | | function handleDelete() { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // 检查是否有他人维护的数据 |
| | | const unauthorizedData = selectedRows.value.filter( |
| | | item => item.checkUserId !== userStore.id |
| | | ); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("不可删除他人维护的数据"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | afterSalesServiceDelete(ids) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | } |
| | | |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/afterSalesService/export", {}, "反馈登记.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | const getStatsCountByStatus = (list, status) => { |
| | | if (!Array.isArray(list)) return 0; |
| | | return list.find((item) => item?.status === status)?.count || 0; |
| | | }; |
| | | const getStatsCountByStatus = (list, status) => { |
| | | if (!Array.isArray(list)) return 0; |
| | | return list.find(item => item?.status === status)?.count || 0; |
| | | }; |
| | | |
| | | // 获取统计数据并刷新顶部卡片 |
| | | const getSalesLedgerDetails = () => { |
| | | getSalesLedgerDetail({}).then((res) => { |
| | | getSalesLedgerDetail({}).then(res => { |
| | | if (res.code === 200) { |
| | | const statsData = Array.isArray(res.data) ? res.data : []; |
| | | statsList.value[0].count = getStatsCountByStatus(statsData, 3); |
| | |
| | | statsList.value[2].count = getStatsCountByStatus(statsData, 1); |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | |
| | | }); |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .search-wrapper { |
| | | background: white; |
| | | padding: 1rem 1rem 0 1rem; |
| | | border: 8px; |
| | | border-radius: 16px; |
| | | } |
| | | .search-wrapper { |
| | | background: white; |
| | | padding: 1rem 1rem 0 1rem; |
| | | border: 8px; |
| | | border-radius: 16px; |
| | | } |
| | | |
| | | .expand-btn { |
| | | width: 100%; |
| | | padding: 20px; /* 上下左右各20px,点击这个范围都能触发事件 */ |
| | | cursor: pointer; /* 鼠标悬浮显示手型,提升体验 */ |
| | | text-align: center; |
| | | } |
| | | .expand-btn { |
| | | width: 100%; |
| | | padding: 20px; /* 上下左右各20px,点击这个范围都能触发事件 */ |
| | | cursor: pointer; /* 鼠标悬浮显示手型,提升体验 */ |
| | | text-align: center; |
| | | } |
| | | |
| | | .workorder-stats { |
| | | display: flex; |
| | | gap: 16px; |
| | | padding-bottom:1rem; |
| | | border-radius: 8px; |
| | | } |
| | | .workorder-stats { |
| | | display: flex; |
| | | gap: 16px; |
| | | padding-bottom: 1rem; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 20px; |
| | | background-color: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); |
| | | } |
| | | .stat-card { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 20px; |
| | | background-color: #fff; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06); |
| | | } |
| | | |
| | | .stat-icon { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 8px; |
| | | } |
| | | .stat-icon { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | width: 48px; |
| | | height: 48px; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .stat-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 4px; |
| | | } |
| | | .stat-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | line-height: 1; |
| | | } |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | line-height: 1; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | line-height: 1; |
| | | } |
| | | .table_header{ |
| | | padding-bottom: 10px; |
| | | } |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | line-height: 1; |
| | | } |
| | | .table_header { |
| | | padding-bottom: 10px; |
| | | } |
| | | |
| | | .table_list { |
| | | height: calc(100vh - 380px); |
| | | background: #fff; |
| | | margin-top: 20px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .table_list { |
| | | height: calc(100vh - 380px); |
| | | background: #fff; |
| | | margin-top: 20px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | :deep(.table_list .pagination-container) { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | margin-top: auto; |
| | | padding: 12px 0 0; |
| | | } |
| | | :deep(.table_list .pagination-container) { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | margin-top: auto; |
| | | padding: 12px 0 0; |
| | | } |
| | | |
| | | :deep(.table_list .el-pagination) { |
| | | flex-wrap: nowrap; |
| | | justify-content: flex-end; |
| | | width: 100%; |
| | | } |
| | | :deep(.table_list .el-pagination) { |
| | | flex-wrap: nowrap; |
| | | justify-content: flex-end; |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | total: total, |
| | | layout: 'total, sizes, prev, pager, next, jumper' |
| | | }" |
| | | :table-style="{ width: '100%', height: 'calc(100vh - 23em)' }"> |
| | | height="calc(100vh - 23em)" |
| | | :table-style="{ width: '100%' }"> |
| | | <template #inspector="{ row }"> |
| | | <div class="person-tags"> |
| | | <!-- 调试信息,上线时删除 --> |
| | |
| | | // 单选框配置 |
| | | const activeRadio = ref("taskManage"); |
| | | const radios = reactive([ |
| | | { name: "taskManage", label: "定时任务管理" }, |
| | | { name: "task", label: "定时任务记录" }, |
| | | { name: "taskManage", label: "巡检任务" }, |
| | | { name: "task", label: "巡检记录" }, |
| | | ]); |
| | | |
| | | // 表格数据 |
| | |
| | | |
| | | // 列配置 |
| | | const columns = ref([ |
| | | { prop: "taskName", label: "巡检任务名称", minWidth: 160 }, |
| | | { prop: "inspectionProject", label: "巡检项目", minWidth: 150 }, |
| | | { prop: "remarks", label: "备注", minWidth: 150 }, |
| | | { prop: "inspector", label: "执行巡检人", minWidth: 150, slot: "inspector" }, |
| | | { prop: "taskName", label: "巡检任务名称", minWidth: 200 }, |
| | | { prop: "inspectionProject", label: "巡检项目", minWidth: 180 }, |
| | | { prop: "remarks", label: "备注", minWidth: 180 }, |
| | | { prop: "inspector", label: "执行巡检人", minWidth: 180, slot: "inspector" }, |
| | | { |
| | | prop: "isEnabled", |
| | | label: "是否启用", |
| | |
| | | { |
| | | prop: "frequencyType", |
| | | label: "频次", |
| | | minWidth: 150, |
| | | // formatter: (_, __, val) => ({ |
| | | // DAILY: "每日", |
| | | // WEEKLY: "每周", |
| | | // MONTHLY: "每月", |
| | | // QUARTERLY: "季度" |
| | | // }[val] || "") |
| | | minWidth: 120, |
| | | formatData: params => { |
| | | return params === "DAILY" |
| | | ? "每日" |
| | |
| | | { |
| | | prop: "frequencyDetail", |
| | | label: "开始日期与时间", |
| | | minWidth: 150, |
| | | minWidth: 200, |
| | | formatter: (row, column, cellValue) => { |
| | | // 先判断是否是字符串 |
| | | if (typeof cellValue !== "string") return ""; |
| | |
| | | ); |
| | | }, |
| | | }, |
| | | { prop: "registrant", label: "登记人", minWidth: 100 }, |
| | | { prop: "registrant", label: "登记人", minWidth: 120 }, |
| | | { |
| | | prop: "createTime", |
| | | label: "登记日期", |
| | | minWidth: 100, |
| | | minWidth: 180, |
| | | formatData: cell => { |
| | | if (!cell) return "-"; |
| | | try { |
| | |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | prop: "inspectionResult", |
| | | label: "巡检结果", |
| | | minWidth: 100, |
| | | dataType: "tag", |
| | | formatData: val => { |
| | | return val == 1 ? "正常" : "异常"; |
| | | }, |
| | | formatType: val => { |
| | | return val == 1 ? "success" : "danger"; |
| | | }, |
| | | }, |
| | | { prop: "abnormalDescription", label: "异常描述", minWidth: 100 }, |
| | | // { |
| | | // prop: "inspectionResult", |
| | | // label: "巡检结果", |
| | | // minWidth: 100, |
| | | // dataType: "tag", |
| | | // formatData: val => { |
| | | // return val == 1 ? "正常" : "异常"; |
| | | // }, |
| | | // formatType: val => { |
| | | // return val == 1 ? "success" : "danger"; |
| | | // }, |
| | | // }, |
| | | { prop: "abnormalDescription", label: "异常描述", minWidth: 150 }, |
| | | ]); |
| | | |
| | | // 操作列配置 |
| | |
| | | label: "操作", |
| | | width: operations.length > 1 ? 180 : 130, |
| | | fixed: "right", |
| | | align: 'center', |
| | | align: "center", |
| | | dataType: "action", |
| | | operation: operations |
| | | .map(op => { |
| | |
| | | operationsArr.value = ["edit"]; |
| | | } else if (value === "task") { |
| | | const operationColumn = getOperationColumn(["upload", "viewFile"]); |
| | | // 定时任务记录不展示"是否启用"列 |
| | | // 巡检记录不展示"是否启用"列 |
| | | const taskColumns = columns.value.filter(col => col.prop !== "isEnabled"); |
| | | tableColumns.value = [ |
| | | ...taskColumns, |
| | |
| | | .then(() => { |
| | | // 根据当前选中的标签页调用不同的导出接口 |
| | | if (activeRadio.value === "taskManage") { |
| | | // 定时任务管理 |
| | | proxy.download("/timingTask/export", {}, "定时任务管理.xlsx"); |
| | | // 巡检任务 |
| | | proxy.download("/timingTask/export", {}, "巡检任务.xlsx"); |
| | | } else if (activeRadio.value === "task") { |
| | | // 定时任务记录 |
| | | proxy.download("/inspectionTask/export", {}, "定时任务记录.xlsx"); |
| | | // 巡检记录 |
| | | proxy.download("/inspectionTask/export", {}, "巡检记录.xlsx"); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">录入日期:</span> |
| | | <el-date-picker |
| | | v-model="searchForm.recordDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable |
| | | style="width: 160px" |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">计量器具编号:</span> |
| | | <el-input v-model="searchForm.code" placeholder="请输入编号" clearable style="width: 240px" @change="handleQuery"/> |
| | | <span class="search_title ml10">状态:</span> |
| | | <el-select v-model="searchForm.status" placeholder="请选择状态" @change="handleQuery" style="width: 160px" clearable> |
| | | <el-option label="有效" :value="1"></el-option> |
| | | <el-option label="逾期" :value="2"></el-option> |
| | | </el-select> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >搜索</el-button |
| | | > |
| | | <el-button @click="handleReset" style="margin-left: 10px">重置</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">新增计量器具</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">删除</el-button> |
| | | <el-button @click="handleOut">导出</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :dbRowClick="dbRowClick" |
| | | :rowClassName="rowClassName" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | <calibration-dia ref="calibrationDia" @close="handleQuery"></calibration-dia> |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">录入日期:</span> |
| | | <el-date-picker v-model="searchForm.recordDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable |
| | | style="width: 160px" |
| | | @change="handleQuery" /> |
| | | <span class="search_title ml10">计量器具编号:</span> |
| | | <el-input v-model="searchForm.code" |
| | | placeholder="请输入编号" |
| | | clearable |
| | | style="width: 240px" |
| | | @change="handleQuery" /> |
| | | <span class="search_title ml10">状态:</span> |
| | | <el-select v-model="searchForm.status" |
| | | placeholder="请选择状态" |
| | | @change="handleQuery" |
| | | style="width: 160px" |
| | | clearable> |
| | | <el-option label="有效" |
| | | :value="1"></el-option> |
| | | <el-option label="逾期" |
| | | :value="2"></el-option> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">搜索</el-button> |
| | | <el-button @click="handleReset" |
| | | style="margin-left: 10px">重置</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">新增计量器具</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">删除</el-button> |
| | | <el-button @click="handleOut">导出</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :dbRowClick="dbRowClick" |
| | | :rowClassName="rowClassName"></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" |
| | | @close="handleQuery"></form-dia> |
| | | <calibration-dia ref="calibrationDia" |
| | | @close="handleQuery"></calibration-dia> |
| | | <files-dia ref="filesDia"></files-dia> |
| | | <rowClickDataForm ref="rowClickData"></rowClickDataForm> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import FormDia from "@/views/equipmentManagement/measurementEquipment/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue"; |
| | | import { |
| | | measuringInstrumentDelete, |
| | | measuringInstrumentListPage, |
| | | } from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import FilesDia from "./filesDia.vue"; |
| | | import rowClickDataForm from "./components/rowClickData.vue" |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore() |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import FormDia from "@/views/equipmentManagement/measurementEquipment/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue"; |
| | | import { |
| | | measuringInstrumentDelete, |
| | | measuringInstrumentListPage, |
| | | } from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import FilesDia from "./filesDia.vue"; |
| | | import rowClickDataForm from "./components/rowClickData.vue"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | recordDate: "", |
| | | code: "", |
| | | status: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | recordDate: "", |
| | | code: "", |
| | | status: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "出厂编号", |
| | | prop: "code", |
| | | minWidth:150, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "计量器具名称", |
| | | prop: "name", |
| | | width: '160px', |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "检定单位", |
| | | prop: "unit", |
| | | width: 200, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "证书编号", |
| | | prop: "model", |
| | | width:200, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "最新鉴定日期", |
| | | prop: "mostDate", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "录入人", |
| | | prop: "userName", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "录入日期", |
| | | prop: "recordDate", |
| | | align:"center", |
| | | minWidth: 130 |
| | | }, |
| | | { |
| | | label: "有效日期", |
| | | prop: "valid", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "状态", |
| | | prop: "status", |
| | | width: 130, |
| | | align: "center", |
| | | formatData: (params) => { |
| | | if (params === 1) { |
| | | return "有效"; |
| | | } else if (params === 2) { |
| | | return "逾期"; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | | width: '130', |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "附件", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "出厂编号", |
| | | prop: "code", |
| | | minWidth: 150, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "计量器具名称", |
| | | prop: "name", |
| | | width: "160px", |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "检定单位", |
| | | prop: "unit", |
| | | width: 200, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "证书编号", |
| | | prop: "model", |
| | | width: 200, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "最新鉴定日期", |
| | | prop: "mostDate", |
| | | width: 130, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "录入人", |
| | | prop: "userName", |
| | | width: 130, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "录入日期", |
| | | prop: "recordDate", |
| | | align: "center", |
| | | minWidth: 130, |
| | | }, |
| | | { |
| | | label: "有效日期", |
| | | prop: "valid", |
| | | width: 130, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "状态", |
| | | prop: "status", |
| | | width: 130, |
| | | align: "center", |
| | | formatData: params => { |
| | | if (params === 1) { |
| | | return "有效"; |
| | | } else if (params === 2) { |
| | | return "逾期"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | { |
| | | name: "查看", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openCalibrationDia("verifying", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const rowClickData = ref([]) |
| | | const filesDia = ref() |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "操作", |
| | | align: "center", |
| | | width: "130", |
| | | fixed: "right", |
| | | operation: [ |
| | | { |
| | | name: "附件", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "编辑", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openCalibrationDia("verifying", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const rowClickData = ref([]); |
| | | const filesDia = ref(); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | |
| | | // 打开附件弹框 |
| | | const openFilesFormDia = (row) => { |
| | | filesDia.value?.openDialog(row,'measuring_instrument_ledger') |
| | | }; |
| | | // 打开附件弹框 |
| | | const openFilesFormDia = row => { |
| | | filesDia.value?.openDialog(row, "measuring_instrument_ledger"); |
| | | }; |
| | | |
| | | const dbRowClick = (row)=>{ |
| | | rowClickData.value?.openDialog(row) |
| | | } |
| | | const dbRowClick = row => { |
| | | rowClickData.value?.openDialog(row); |
| | | }; |
| | | |
| | | // 行样式:快到期(7天内)或逾期标红 |
| | | const rowClassName = ({ row }) => { |
| | | console.log('rowClassName called:', row); |
| | | // valid 是有效天数,mostDate 是最新检定日期 |
| | | if (row.valid && row.mostDate) { |
| | | const mostDate = new Date(row.mostDate); |
| | | // 计算到期日期 = 检定日期 + 有效天数 |
| | | const validDays = parseInt(row.valid) || 0; |
| | | const expireDate = new Date(mostDate); |
| | | expireDate.setDate(expireDate.getDate() + validDays); |
| | | |
| | | const now = new Date(); |
| | | const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24)); |
| | | console.log('row:', row.code, 'validDays:', validDays, 'expireDate:', expireDate, 'diffDays:', diffDays); |
| | | // 7天内到期或已逾期都标红 |
| | | if (diffDays <= 7) { |
| | | console.log('return warning-row'); |
| | | return 'warning-row'; |
| | | // 行样式:快到期(7天内)或逾期标红 |
| | | const rowClassName = ({ row }) => { |
| | | console.log("rowClassName called:", row); |
| | | // valid 是有效天数,mostDate 是最新检定日期 |
| | | if (row.valid && row.mostDate) { |
| | | const mostDate = new Date(row.mostDate); |
| | | // 计算到期日期 = 检定日期 + 有效天数 |
| | | const validDays = parseInt(row.valid) || 0; |
| | | const expireDate = new Date(mostDate); |
| | | expireDate.setDate(expireDate.getDate() + validDays); |
| | | |
| | | const now = new Date(); |
| | | const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24)); |
| | | console.log( |
| | | "row:", |
| | | row.code, |
| | | "validDays:", |
| | | validDays, |
| | | "expireDate:", |
| | | expireDate, |
| | | "diffDays:", |
| | | diffDays |
| | | ); |
| | | // 7天内到期或已逾期都标红 |
| | | if (diffDays <= 7) { |
| | | console.log("return warning-row"); |
| | | return "warning-row"; |
| | | } |
| | | } else { |
| | | console.log("row missing valid or mostDate:", row.valid, row.mostDate); |
| | | } |
| | | } else { |
| | | console.log('row missing valid or mostDate:', row.valid, row.mostDate); |
| | | } |
| | | return ''; |
| | | } |
| | | return ""; |
| | | }; |
| | | |
| | | // 表格选择数据 |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref() |
| | | const calibrationDia = ref() |
| | | // 表格选择数据 |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref(); |
| | | const calibrationDia = ref(); |
| | | |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | // 查询列表 |
| | | /** 搜索按钮操作 */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | // 重置搜索条件 |
| | | const handleReset = () => { |
| | | searchForm.value.recordDate = ""; |
| | | searchForm.value.code = ""; |
| | | searchForm.value.status = ""; |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentListPage({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch((err) => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | // 重置搜索条件 |
| | | const handleReset = () => { |
| | | searchForm.value.recordDate = ""; |
| | | searchForm.value.code = ""; |
| | | searchForm.value.status = ""; |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentListPage({ ...searchForm.value, ...page }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // 打开弹框 |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // 打开检定校准弹框 |
| | | const openCalibrationDia = (type, row) => { |
| | | nextTick(() => { |
| | | calibrationDia.value?.openDialog(type, row) |
| | | }) |
| | | } |
| | | // 打开弹框 |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // 打开检定校准弹框 |
| | | const openCalibrationDia = (type, row) => { |
| | | nextTick(() => { |
| | | calibrationDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentDelete(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/measuringInstrumentLedger/export", {}, "计量器具台账.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentDelete(ids) |
| | | .then(res => { |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download( |
| | | "/measuringInstrumentLedger/export", |
| | | {}, |
| | | "计量器具台账.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | :deep(.el-table .warning-row) { |
| | | background-color: #fef0f0 !important; |
| | | } |
| | | :deep(.el-table .warning-row:hover > td) { |
| | | background-color: #f9d5d5 !important; |
| | | } |
| | | :deep(.el-table .el-table__body tr.warning-row td) { |
| | | background-color: #fef0f0 !important; |
| | | } |
| | | :deep(.el-table .warning-row) { |
| | | background-color: #fef0f0 !important; |
| | | } |
| | | :deep(.el-table .warning-row:hover > td) { |
| | | background-color: #f9d5d5 !important; |
| | | } |
| | | :deep(.el-table .el-table__body tr.warning-row td) { |
| | | background-color: #fef0f0 !important; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="id ? '编辑设备报修' : '新增设备报修'" |
| | | width="800px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <FormDialog v-model="visible" |
| | | :title="computedTitle" |
| | | :operation-type="operationType" |
| | | width="800px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose"> |
| | | <el-form :model="form" |
| | | label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称"> |
| | | <el-select v-model="form.deviceLedgerId" @change="setDeviceModel" filterable> |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | <el-select v-model="form.deviceLedgerId" |
| | | @change="setDeviceModel" |
| | | filterable |
| | | :disabled="operationType === 'view'"> |
| | | <el-option v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="规格型号"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请输入规格型号" |
| | | disabled |
| | | /> |
| | | <el-input v-model="form.deviceModel" |
| | | placeholder="请输入规格型号" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报修日期"> |
| | | <el-date-picker |
| | | v-model="form.repairTime" |
| | | placeholder="请选择报修日期" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | <el-date-picker v-model="form.repairTime" |
| | | placeholder="请选择报修日期" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | clearable |
| | | style="width: 100%" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报修人"> |
| | | <el-input v-model="form.repairName" placeholder="请输入报修人" /> |
| | | <el-input v-model="form.repairName" |
| | | placeholder="请输入报修人" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报修报修项目"> |
| | | <el-input v-model="form.machineryCategory" placeholder="请输入报修报修项目" /> |
| | | <el-input v-model="form.machineryCategory" |
| | | placeholder="请输入报修报修项目" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="维修人"> |
| | | <el-input v-model="form.maintenanceName" placeholder="请输入维修人姓名" /> |
| | | <el-input v-model="form.maintenanceName" |
| | | placeholder="请输入维修人姓名" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-if="id"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="报修状态"> |
| | | <el-select v-model="form.status" disabled> |
| | | <el-option label="待维修" :value="0"></el-option> |
| | | <el-option label="已验收" :value="1"></el-option> |
| | | <el-option label="失败" :value="2"></el-option> |
| | | <el-select v-model="form.status" |
| | | disabled> |
| | | <el-option label="待维修" |
| | | :value="0"></el-option> |
| | | <el-option label="已验收" |
| | | :value="1"></el-option> |
| | | <el-option label="失败" |
| | | :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- 验收信息展示 --> |
| | | <el-row v-if="id && form.status === 1"> |
| | | <el-row v-if="id && (form.status === 1 || form.status === 3)"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="验收人"> |
| | | <el-input v-model="form.acceptanceName" disabled /> |
| | | <el-input v-model="form.acceptanceName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="验收时间"> |
| | | <el-input v-model="form.acceptanceTime" disabled /> |
| | | <el-input v-model="form.acceptanceTime" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="验收备注"> |
| | | <el-input v-model="form.acceptanceRemark" type="textarea" :rows="2" disabled /> |
| | | <el-input v-model="form.acceptanceRemark" |
| | | type="textarea" |
| | | :rows="2" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="故障现象"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | :rows="2" |
| | | type="textarea" |
| | | placeholder="请输入故障现象" |
| | | /> |
| | | <el-input v-model="form.remark" |
| | | :rows="2" |
| | | type="textarea" |
| | | placeholder="请输入故障现象" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-row v-if="operationType !== 'view'" |
| | | :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="附件" prop="attachmentIds"> |
| | | <FileUpload v-model:file-list="form.storageBlobDTOs" /> |
| | | <el-form-item label="附件" |
| | | prop="attachmentIds"> |
| | | <FileUpload v-model:file-list="form.storageBlobDTOs" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import { |
| | | addRepair, |
| | | editRepair, |
| | | getRepairById, |
| | | } from "@/api/equipmentManagement/repair"; |
| | | import { ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import { |
| | | addRepair, |
| | | editRepair, |
| | | getRepairById, |
| | | } from "@/api/equipmentManagement/repair"; |
| | | import { ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | defineOptions({ |
| | | name: "设备报修弹窗", |
| | | }); |
| | | defineOptions({ |
| | | name: "设备报修弹窗", |
| | | }); |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const operationType = ref(""); // add, edit, view |
| | | |
| | | const userStore = useUserStore(); |
| | | const deviceOptions = ref([]); |
| | | const fileList = ref([]); |
| | | const computedTitle = computed(() => { |
| | | if (operationType.value === "add") return "新增设备报修"; |
| | | if (operationType.value === "edit") return "编辑设备报修"; |
| | | if (operationType.value === "view") return "设备报修详情"; |
| | | return ""; |
| | | }); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | const userStore = useUserStore(); |
| | | const deviceOptions = ref([]); |
| | | const fileList = ref([]); |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设备Id |
| | | deviceName: undefined, // 设备名称 |
| | | deviceModel: undefined, // 规格型号 |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // 报修日期,默认当天 |
| | | repairName: userStore.nickName, // 报修人 |
| | | remark: undefined, // 故障现象 |
| | | status: 0, // 报修状态 |
| | | machineryCategory: undefined, |
| | | storageBlobDTOs: [], |
| | | maintenanceName: undefined, // 维修人 |
| | | }); |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | |
| | | const setDeviceModel = (deviceId) => { |
| | | const option = deviceOptions.value.find((item) => item.id === deviceId); |
| | | form.deviceModel = option.deviceModel; |
| | | }; |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设备Id |
| | | deviceName: undefined, // 设备名称 |
| | | deviceModel: undefined, // 规格型号 |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // 报修日期,默认当天 |
| | | repairName: userStore.nickName, // 报修人 |
| | | remark: undefined, // 故障现象 |
| | | status: 0, // 报修状态 |
| | | machineryCategory: undefined, |
| | | storageBlobDTOs: [], |
| | | maintenanceName: undefined, // 维修人 |
| | | }); |
| | | |
| | | const setForm = (data) => { |
| | | form.deviceLedgerId = data.deviceLedgerId; |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.repairTime = data.repairTime; |
| | | form.repairName = data.repairName; |
| | | form.remark = data.remark; |
| | | form.status = data.status; |
| | | form.machineryCategory = data.machineryCategory; |
| | | form.storageBlobDTOs = data.storageBlobVOs || []; |
| | | form.maintenanceName = data.maintenanceName; |
| | | form.acceptanceName = data.acceptanceName; |
| | | form.acceptanceTime = data.acceptanceTime; |
| | | form.acceptanceRemark = data.acceptanceRemark; |
| | | }; |
| | | const setDeviceModel = deviceId => { |
| | | const option = deviceOptions.value.find(item => item.id === deviceId); |
| | | form.deviceModel = option.deviceModel; |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const { code } = id.value |
| | | ? await editRepair({ id: unref(id), ...form }) |
| | | : await addRepair(form); |
| | | if (code == 200) { |
| | | ElMessage.success(`${id.value ? "编辑" : "新增"}报修成功`); |
| | | visible.value = false; |
| | | emits("ok"); |
| | | const setForm = data => { |
| | | form.deviceLedgerId = data.deviceLedgerId; |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.repairTime = data.repairTime; |
| | | form.repairName = data.repairName; |
| | | form.remark = data.remark; |
| | | form.status = data.status; |
| | | form.machineryCategory = data.machineryCategory; |
| | | form.storageBlobDTOs = data.storageBlobVOs || []; |
| | | form.maintenanceName = data.maintenanceName; |
| | | form.acceptanceName = data.acceptanceName; |
| | | form.acceptanceTime = data.acceptanceTime; |
| | | form.acceptanceRemark = data.acceptanceRemark; |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const { code } = id.value |
| | | ? await editRepair({ id: unref(id), ...form }) |
| | | : await addRepair(form); |
| | | if (code == 200) { |
| | | ElMessage.success(`${id.value ? "编辑" : "新增"}报修成功`); |
| | | visible.value = false; |
| | | emits("ok"); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const openAdd = async () => { |
| | | id.value = undefined; |
| | | visible.value = true; |
| | | fileList.value = []; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | }; |
| | | const openAdd = async () => { |
| | | id.value = undefined; |
| | | operationType.value = "add"; |
| | | visible.value = true; |
| | | fileList.value = []; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | }; |
| | | |
| | | const openEdit = async (editId) => { |
| | | const { data } = await getRepairById(editId); |
| | | id.value = editId; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | setForm(data); |
| | | }; |
| | | const openEdit = async editId => { |
| | | const { data } = await getRepairById(editId); |
| | | id.value = editId; |
| | | operationType.value = "edit"; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openAdd, |
| | | openEdit, |
| | | }); |
| | | const openView = async viewId => { |
| | | const { data } = await getRepairById(viewId); |
| | | id.value = viewId; |
| | | operationType.value = "view"; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openAdd, |
| | | openEdit, |
| | | openView, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :model="filters" :inline="true"> |
| | | <el-form :model="filters" |
| | | :inline="true"> |
| | | <el-form-item label="设备名称"> |
| | | <el-input |
| | | v-model="filters.deviceName" |
| | | style="width: 240px" |
| | | placeholder="请输入设备名称" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | <el-input v-model="filters.deviceName" |
| | | style="width: 240px" |
| | | placeholder="请输入设备名称" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | </el-form-item> |
| | | <el-form-item label="规格型号"> |
| | | <el-input |
| | | v-model="filters.deviceModel" |
| | | style="width: 240px" |
| | | placeholder="请选择规格型号" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | <el-input v-model="filters.deviceModel" |
| | | style="width: 240px" |
| | | placeholder="请选择规格型号" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | </el-form-item> |
| | | <el-form-item label="故障现象"> |
| | | <el-input |
| | | v-model="filters.remark" |
| | | style="width: 240px" |
| | | placeholder="请输入故障现象" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | <el-input v-model="filters.remark" |
| | | style="width: 240px" |
| | | placeholder="请输入故障现象" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | </el-form-item> |
| | | <el-form-item label="维修人"> |
| | | <el-input |
| | | v-model="filters.maintenanceName" |
| | | style="width: 240px" |
| | | placeholder="请输入维修人" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | <el-input v-model="filters.maintenanceName" |
| | | style="width: 240px" |
| | | placeholder="请输入维修人" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | </el-form-item> |
| | | <el-form-item label="报修日期"> |
| | | <el-date-picker |
| | | v-model="filters.repairTimeStr" |
| | | type="date" |
| | | placeholder="请选择报修日期" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" |
| | | /> |
| | | <el-date-picker v-model="filters.repairTimeStr" |
| | | type="date" |
| | | placeholder="请选择报修日期" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" /> |
| | | </el-form-item> |
| | | <el-form-item label="维修日期"> |
| | | <el-date-picker |
| | | v-model="filters.maintenanceTimeStr" |
| | | type="date" |
| | | placeholder="请选择维修日期" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" |
| | | /> |
| | | <el-date-picker v-model="filters.maintenanceTimeStr" |
| | | type="date" |
| | | placeholder="请选择维修日期" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getTableData">搜索</el-button> |
| | | <el-button type="primary" |
| | | @click="getTableData">搜索</el-button> |
| | | <el-button @click="resetFilters">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <el-text class="mx-1" size="large">设备报修</el-text> |
| | | <el-text class="mx-1" |
| | | size="large">设备报修</el-text> |
| | | <div> |
| | | <el-button type="success" icon="Van" @click="addRepair"> |
| | | <el-button type="success" |
| | | icon="Van" |
| | | @click="addRepair"> |
| | | 新增报修 |
| | | </el-button> |
| | | <el-button @click="handleOut"> |
| | | 导出 |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | > |
| | | <el-button type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))"> |
| | | 批量删除 |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | <PIMTable rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | total: pagination.total, |
| | | }" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage" |
| | | > |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage"> |
| | | <template #statusRef="{ row }"> |
| | | <el-tag v-if="row.status === 2" type="danger">失败</el-tag> |
| | | <el-tag v-if="row.status === 1" type="success">完结</el-tag> |
| | | <el-tag v-if="row.status === 3" type="info">待验收</el-tag> |
| | | <el-tag v-if="row.status === 0" type="warning">待维修</el-tag> |
| | | <el-tag v-if="row.status === 2" |
| | | type="danger">失败</el-tag> |
| | | <el-tag v-if="row.status === 1" |
| | | type="success">完结</el-tag> |
| | | <el-tag v-if="row.status === 3" |
| | | type="info">待验收</el-tag> |
| | | <el-tag v-if="row.status === 0" |
| | | type="warning">待维修</el-tag> |
| | | </template> |
| | | <template #operation="{ row }"> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | :disabled="row.status === 1 || row.status === 3" |
| | | @click="editRepair(row.id)" |
| | | > |
| | | <el-button type="primary" |
| | | link |
| | | @click="viewRepair(row.id)"> |
| | | 详情 |
| | | </el-button> |
| | | <el-button type="primary" |
| | | link |
| | | :disabled="row.status === 1 || row.status === 3" |
| | | @click="editRepair(row.id)"> |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | link |
| | | :disabled="row.status !== 0" |
| | | @click="addMaintain(row)" |
| | | > |
| | | <el-button type="success" |
| | | link |
| | | :disabled="row.status !== 0" |
| | | @click="addMaintain(row)"> |
| | | 维修 |
| | | </el-button> |
| | | <el-button |
| | | type="warning" |
| | | link |
| | | :disabled="row.status !== 3" |
| | | @click="openAcceptance(row)" |
| | | > |
| | | <el-button type="warning" |
| | | link |
| | | :disabled="row.status !== 3" |
| | | @click="openAcceptance(row)"> |
| | | 验收 |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | link |
| | | :disabled="row.status === 1 || row.status === 3" |
| | | @click="delRepairByIds(row.id)" |
| | | > |
| | | <el-button type="danger" |
| | | link |
| | | :disabled="row.status === 1 || row.status === 3" |
| | | @click="delRepairByIds(row.id)"> |
| | | 删除 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | @click="openFileDialog(row)" |
| | | > |
| | | <el-button type="primary" |
| | | link |
| | | @click="openFileDialog(row)"> |
| | | 附件 |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <RepairModal ref="repairModalRef" @ok="getTableData"/> |
| | | <MaintainModal ref="maintainModalRef" @ok="getTableData"/> |
| | | <AcceptanceModal ref="acceptanceModalRef" @ok="getTableData"/> |
| | | <FileList v-if="fileDialogVisible" v-model:visible="fileDialogVisible" :record-type="'device_repair'" :record-id="recordId" /> |
| | | <RepairModal ref="repairModalRef" |
| | | @ok="getTableData" /> |
| | | <MaintainModal ref="maintainModalRef" |
| | | @ok="getTableData" /> |
| | | <AcceptanceModal ref="acceptanceModalRef" |
| | | @ok="getTableData" /> |
| | | <FileList v-if="fileDialogVisible" |
| | | v-model:visible="fileDialogVisible" |
| | | :record-type="'device_repair'" |
| | | :record-id="recordId" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, getCurrentInstance, computed, ref, defineAsyncComponent} from "vue"; |
| | | import {usePaginationApi} from "@/hooks/usePaginationApi"; |
| | | import {getRepairPage, delRepair} from "@/api/equipmentManagement/repair"; |
| | | import RepairModal from "./Modal/RepairModal.vue"; |
| | | import {ElMessageBox, ElMessage} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import MaintainModal from "./Modal/MaintainModal.vue"; |
| | | import AcceptanceModal from "./Modal/AcceptanceModal.vue"; |
| | | const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue")); |
| | | import { |
| | | onMounted, |
| | | getCurrentInstance, |
| | | computed, |
| | | ref, |
| | | defineAsyncComponent, |
| | | } from "vue"; |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | import { getRepairPage, delRepair } from "@/api/equipmentManagement/repair"; |
| | | import RepairModal from "./Modal/RepairModal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import MaintainModal from "./Modal/MaintainModal.vue"; |
| | | import AcceptanceModal from "./Modal/AcceptanceModal.vue"; |
| | | const FileList = defineAsyncComponent(() => |
| | | import("@/components/Dialog/FileList.vue") |
| | | ); |
| | | |
| | | defineOptions({ |
| | | name: "设备报修", |
| | | }); |
| | | defineOptions({ |
| | | name: "设备报修", |
| | | }); |
| | | |
| | | const {proxy} = getCurrentInstance(); |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // 模态框实例 |
| | | const repairModalRef = ref(); |
| | | const maintainModalRef = ref(); |
| | | const acceptanceModalRef = ref(); |
| | | // 模态框实例 |
| | | const repairModalRef = ref(); |
| | | const maintainModalRef = ref(); |
| | | const acceptanceModalRef = ref(); |
| | | |
| | | // 表格多选框选中项 |
| | | const multipleList = ref([]); |
| | | // 表格多选框选中项 |
| | | const multipleList = ref([]); |
| | | |
| | | // 表格钩子 |
| | | const { |
| | | filters, |
| | | columns, |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | } = usePaginationApi( |
| | | // 表格钩子 |
| | | const { |
| | | filters, |
| | | columns, |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | } = usePaginationApi( |
| | | getRepairPage, |
| | | { |
| | | deviceName: undefined, |
| | |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | label: "报修项目", |
| | | align: "center", |
| | | prop: "machineryCategory", |
| | | }, |
| | | { |
| | | label: "报修日期", |
| | | align: "center", |
| | | prop: "repairTime", |
| | | formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"), |
| | | formatData: cell => dayjs(cell).format("YYYY-MM-DD"), |
| | | }, |
| | | { |
| | | label: "报修人", |
| | | align: "center", |
| | | prop: "repairName", |
| | | }, |
| | | { |
| | | label: "故障现象", |
| | | align: "center", |
| | | prop: "remark", |
| | | }, |
| | | { |
| | | label: "维修人", |
| | | align: "center", |
| | | prop: "maintenanceName", |
| | | }, |
| | | { |
| | | label: "维修结果", |
| | | align: "center", |
| | | prop: "maintenanceResult", |
| | | }, |
| | | { |
| | | label: "维修日期", |
| | | align: "center", |
| | | prop: "maintenanceTime", |
| | | formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""), |
| | | }, |
| | | { |
| | | label: "验收人", |
| | | align: "center", |
| | | prop: "acceptanceName", |
| | | }, |
| | | { |
| | | label: "验收时间", |
| | | align: "center", |
| | | prop: "acceptanceTime", |
| | | formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : ""), |
| | | }, |
| | | { |
| | | label: "状态", |
| | |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "300px", |
| | | width: "320px", |
| | | }, |
| | | ] |
| | | ); |
| | | ); |
| | | |
| | | // type === 1 维修 2报修间 |
| | | const handleDateChange = (value, type) => { |
| | | filters.maintenanceTimeStr = null |
| | | filters.c = null |
| | | if (type === 1) { |
| | | if (value) { |
| | | filters.maintenanceTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | // type === 1 维修 2报修间 |
| | | const handleDateChange = (value, type) => { |
| | | filters.maintenanceTimeStr = null; |
| | | filters.c = null; |
| | | if (type === 1) { |
| | | if (value) { |
| | | filters.maintenanceTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } else { |
| | | if (value) { |
| | | filters.repairTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } |
| | | } else { |
| | | if (value) { |
| | | filters.repairTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } |
| | | getTableData(); |
| | | }; |
| | | getTableData(); |
| | | }; |
| | | |
| | | // 打开附件弹窗 |
| | | const recordId =ref(0) |
| | | const fileDialogVisible = ref(false) |
| | | // 打开附件弹窗 |
| | | const recordId = ref(0); |
| | | const fileDialogVisible = ref(false); |
| | | |
| | | const openFileDialog = async (row) => { |
| | | recordId.value = row.id |
| | | fileDialogVisible.value = true |
| | | } |
| | | const openFileDialog = async row => { |
| | | recordId.value = row.id; |
| | | fileDialogVisible.value = true; |
| | | }; |
| | | |
| | | // 多选后做什么 |
| | | const handleSelectionChange = (selectionList) => { |
| | | multipleList.value = selectionList; |
| | | }; |
| | | // 多选后做什么 |
| | | const handleSelectionChange = selectionList => { |
| | | multipleList.value = selectionList; |
| | | }; |
| | | |
| | | // 检查选中的记录中是否有完结状态的 |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1) |
| | | }) |
| | | |
| | | // 新增报修 |
| | | const addRepair = () => { |
| | | repairModalRef.value.openAdd(); |
| | | }; |
| | | |
| | | // 编辑报修 |
| | | const editRepair = (id) => { |
| | | repairModalRef.value.openEdit(id); |
| | | }; |
| | | |
| | | // 新增维修 |
| | | const addMaintain = (row) => { |
| | | maintainModalRef.value.open(row.id, row); |
| | | }; |
| | | |
| | | // 打开验收弹窗 |
| | | const openAcceptance = (row) => { |
| | | acceptanceModalRef.value.open(row); |
| | | }; |
| | | |
| | | const changePage = ({page, limit}) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | onCurrentChange(page); |
| | | }; |
| | | |
| | | // 单行删除 |
| | | const delRepairByIds = async (ids) => { |
| | | // 检查是否有完结状态的记录 |
| | | const idsArray = Array.isArray(ids) ? ids : [ids]; |
| | | const hasFinished = idsArray.some(id => { |
| | | const record = dataList.value.find(item => item.id === id); |
| | | return record && record.status === 1; |
| | | // 检查选中的记录中是否有完结状态的 |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1); |
| | | }); |
| | | |
| | | if (hasFinished) { |
| | | ElMessage.warning('不能删除状态为完结的记录'); |
| | | return; |
| | | } |
| | | // 新增报修 |
| | | const addRepair = () => { |
| | | repairModalRef.value.openAdd(); |
| | | }; |
| | | |
| | | ElMessageBox.confirm("确认删除报修数据, 此操作不可逆?", "警告", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(async () => { |
| | | const {code} = await delRepair(ids); |
| | | if (code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | getTableData(); |
| | | // 详情查看 |
| | | const viewRepair = id => { |
| | | repairModalRef.value.openView(id); |
| | | }; |
| | | |
| | | // 编辑报修 |
| | | const editRepair = id => { |
| | | repairModalRef.value.openEdit(id); |
| | | }; |
| | | |
| | | // 新增维修 |
| | | const addMaintain = row => { |
| | | maintainModalRef.value.open(row.id, row); |
| | | }; |
| | | |
| | | // 打开验收弹窗 |
| | | const openAcceptance = row => { |
| | | acceptanceModalRef.value.open(row); |
| | | }; |
| | | |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | onCurrentChange(page); |
| | | }; |
| | | |
| | | // 单行删除 |
| | | const delRepairByIds = async ids => { |
| | | // 检查是否有完结状态的记录 |
| | | const idsArray = Array.isArray(ids) ? ids : [ids]; |
| | | const hasFinished = idsArray.some(id => { |
| | | const record = dataList.value.find(item => item.id === id); |
| | | return record && record.status === 1; |
| | | }); |
| | | |
| | | if (hasFinished) { |
| | | ElMessage.warning("不能删除状态为完结的记录"); |
| | | return; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | ElMessageBox.confirm("确认删除报修数据, 此操作不可逆?", "警告", { |
| | | confirmButtonText: "确定", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(async () => { |
| | | const { code } = await delRepair(ids); |
| | | if (code === 200) { |
| | | ElMessage.success("删除成功"); |
| | | getTableData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 导出 |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/device/repair/export", {}, "设备报修.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.info("已取消"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTableData(); |
| | | }); |
| | | onMounted(() => { |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | return params == "销售" ? "销售" : "内部"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "销售合同号", |
| | | prop: "salesContractNo", |
| | | width: "200px", |
| | | dataType: "slot", |
| | | slot: "salesContractNo", |
| | | }, |
| | | |
| | | { |
| | | label: "产品名称", |
| | |
| | | label: "所需数量", |
| | | prop: "qtyRequired", |
| | | width: "150px", |
| | | align: "right", |
| | | dataType: "slot", |
| | | slot: "qtyRequired", |
| | | className: "volume-cell", |
| | |
| | | className: "date-cell", |
| | | formatData: cell => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""), |
| | | }, |
| | | { |
| | | label: "销售合同号", |
| | | prop: "salesContractNo", |
| | | width: "200px", |
| | | dataType: "slot", |
| | | slot: "salesContractNo", |
| | | }, |
| | | |
| | | { |
| | | label: "客户名称", |
| | | prop: "customerName", |
| | |
| | | show-overflow-tooltip |
| | | width="200" /> |
| | | <el-table-column label="合同金额(元)" |
| | | prop="invoiceTotal" |
| | | prop="contractAmounts" |
| | | show-overflow-tooltip |
| | | :formatter="formattedNumber" |
| | | width="200" /> |
| | |
| | | :formatter="formattedNumber" |
| | | width="200" /> |
| | | <el-table-column label="应收金额(元)" |
| | | prop="unReceiptPaymentAmount" |
| | | prop="receiptableAmount" |
| | | show-overflow-tooltip |
| | | width="200"> |
| | | <template #default="{ row, column }"> |
| | | <el-text type="danger"> |
| | | {{ formattedNumber(row, column, row.unReceiptPaymentAmount) }} |
| | | {{ formattedNumber(row, column, row.receiptableAmount) }} |
| | | </el-text> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | show-overflow-tooltip /> |
| | | <el-table-column fixed="right" |
| | | label="操作" |
| | | width="130" |
| | | width="220" |
| | | align="center"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | type="primary" |
| | | @click="openForm('view', scope.row)">详情 |
| | | </el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="openForm('edit', scope.row)" |
| | |
| | | @pagination="paginationChange" /> |
| | | </div> |
| | | <FormDialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? '新增销售台账页面' : '编辑销售台账页面'" |
| | | :title="operationType === 'add' ? '新增销售台账页面' : (operationType === 'edit' ? '编辑销售台账页面' : '销售台账详情')" |
| | | :width="'70%'" |
| | | :operation-type="operationType" |
| | | @close="closeDia" |
| | |
| | | <el-input v-model="form.salesContractNo" |
| | | :placeholder="form.autoGenerateContractNo ? '自动生成' : '请输入'" |
| | | clearable |
| | | :disabled="form.autoGenerateContractNo" /> |
| | | :disabled="form.autoGenerateContractNo || operationType === 'view'" /> |
| | | </div> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | :reserve-keyword="false" |
| | | placeholder="请选择" |
| | | clearable |
| | | :disabled="operationType === 'view'" |
| | | @change="changs"> |
| | | <el-option v-for="item in userList" |
| | | :key="item.userId" |
| | |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable /> |
| | | clearable |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="请选择" |
| | | clearable /> |
| | | clearable |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-row v-if="operationType !== 'view'" |
| | | :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="附件材料:" |
| | | prop="salesLedgerFiles"> |
| | | <FileUpload v-model:file-list="fileList" /> |
| | | <FileUpload v-model:file-list="fileList" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | |
| | | // 构建打印内容 |
| | | let printContent = ` |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <title>打印预览</title> |
| | | <style> |
| | | body { |
| | | margin: 0; |
| | | padding: 0; |
| | | font-family: "SimSun", serif; |
| | | background: white; |
| | | } |
| | | .print-page { |
| | | width: 200mm; |
| | | height: 75mm; |
| | | padding: 10mm; |
| | | padding-left: 20mm; |
| | | background: white; |
| | | box-sizing: border-box; |
| | | page-break-after: always; |
| | | page-break-inside: avoid; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | .delivery-note { |
| | | width: 100%; |
| | | height: 100%; |
| | | font-size: 12px; |
| | | line-height: 1.2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | color: #000; |
| | | } |
| | | .header { |
| | | text-align: center; |
| | | margin-bottom: 8px; |
| | | } |
| | | .company-name { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 4px; |
| | | } |
| | | .document-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | .info-section { |
| | | margin-bottom: 8px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .info-row { |
| | | line-height: 20px; |
| | | } |
| | | .label { |
| | | font-weight: bold; |
| | | width: 60px; |
| | | font-size: 12px; |
| | | } |
| | | .value { |
| | | margin-right: 20px; |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .table-section { |
| | | margin-bottom: 40px; |
| | | // flex: 0.6; |
| | | } |
| | | .product-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #000; |
| | | } |
| | | .product-table th, .product-table td { |
| | | border: 1px solid #000; |
| | | padding: 6px; |
| | | text-align: center; |
| | | font-size: 12px; |
| | | line-height: 1.4; |
| | | } |
| | | .product-table th { |
| | | font-weight: bold; |
| | | } |
| | | .total-value { |
| | | font-weight: bold; |
| | | } |
| | | .footer-section { |
| | | margin-top: auto; |
| | | } |
| | | .footer-row { |
| | | display: flex; |
| | | margin-bottom: 3px; |
| | | line-height: 22px; |
| | | justify-content: space-between; |
| | | } |
| | | .footer-item { |
| | | display: flex; |
| | | margin-right: 20px; |
| | | } |
| | | .footer-item .label { |
| | | font-weight: bold; |
| | | width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .footer-item .value { |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .address-item .address-value { |
| | | min-width: 200px; |
| | | } |
| | | @media print { |
| | | body { |
| | | margin: 0; |
| | | padding: 0; |
| | | } |
| | | .print-page { |
| | | margin: 0; |
| | | padding: 10mm; |
| | | /* padding-left: 20mm; */ |
| | | page-break-inside: avoid; |
| | | page-break-after: always; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | `; |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta charset="UTF-8"> |
| | | <title>打印预览</title> |
| | | <style> |
| | | body { |
| | | margin: 0; |
| | | padding: 0; |
| | | font-family: "SimSun", serif; |
| | | background: white; |
| | | } |
| | | .print-page { |
| | | width: 200mm; |
| | | height: 75mm; |
| | | padding: 10mm; |
| | | padding-left: 20mm; |
| | | background: white; |
| | | box-sizing: border-box; |
| | | page-break-after: always; |
| | | page-break-inside: avoid; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | .delivery-note { |
| | | width: 100%; |
| | | height: 100%; |
| | | font-size: 12px; |
| | | line-height: 1.2; |
| | | display: flex; |
| | | flex-direction: column; |
| | | color: #000; |
| | | } |
| | | .header { |
| | | text-align: center; |
| | | margin-bottom: 8px; |
| | | } |
| | | .company-name { |
| | | font-size: 18px; |
| | | font-weight: bold; |
| | | margin-bottom: 4px; |
| | | } |
| | | .document-title { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | } |
| | | .info-section { |
| | | margin-bottom: 8px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .info-row { |
| | | line-height: 20px; |
| | | } |
| | | .label { |
| | | font-weight: bold; |
| | | width: 60px; |
| | | font-size: 12px; |
| | | } |
| | | .value { |
| | | margin-right: 20px; |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .table-section { |
| | | margin-bottom: 40px; |
| | | // flex: 0.6; |
| | | } |
| | | .product-table { |
| | | width: 100%; |
| | | border-collapse: collapse; |
| | | border: 1px solid #000; |
| | | } |
| | | .product-table th, .product-table td { |
| | | border: 1px solid #000; |
| | | padding: 6px; |
| | | text-align: center; |
| | | font-size: 12px; |
| | | line-height: 1.4; |
| | | } |
| | | .product-table th { |
| | | font-weight: bold; |
| | | } |
| | | .total-value { |
| | | font-weight: bold; |
| | | } |
| | | .footer-section { |
| | | margin-top: auto; |
| | | } |
| | | .footer-row { |
| | | display: flex; |
| | | margin-bottom: 3px; |
| | | line-height: 22px; |
| | | justify-content: space-between; |
| | | } |
| | | .footer-item { |
| | | display: flex; |
| | | margin-right: 20px; |
| | | } |
| | | .footer-item .label { |
| | | font-weight: bold; |
| | | width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .footer-item .value { |
| | | min-width: 80px; |
| | | font-size: 12px; |
| | | } |
| | | .address-item .address-value { |
| | | min-width: 200px; |
| | | } |
| | | @media print { |
| | | body { |
| | | margin: 0; |
| | | padding: 0; |
| | | } |
| | | .print-page { |
| | | margin: 0; |
| | | padding: 10mm; |
| | | /* padding-left: 20mm; */ |
| | | page-break-inside: avoid; |
| | | page-break-after: always; |
| | | } |
| | | .print-page:last-child { |
| | | page-break-after: avoid; |
| | | } |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | `; |
| | | |
| | | // 为每条数据生成打印页面 |
| | | printData.value.forEach((item, index) => { |
| | | printContent += ` |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="document-title">零售发货单</div> |
| | | </div> |
| | | |
| | | <div class="info-section"> |
| | | <div class="info-row"> |
| | | <div> |
| | | <span class="label">发货日期:</span> |
| | | <span class="value">${formatDate( |
| | | item.createTime |
| | | )}</span> |
| | | </div> |
| | | <div> |
| | | <span class="label">客户名称:</span> |
| | | <span class="value">${ |
| | | item.customerName |
| | | }</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <span class="label">单号:</span> |
| | | <span class="value">${ |
| | | item.salesContractNo || |
| | | "" |
| | | }</span> |
| | | </div> |
| | | </div> |
| | | <div class="print-page"> |
| | | <div class="delivery-note"> |
| | | <div class="header"> |
| | | <div class="document-title">零售发货单</div> |
| | | </div> |
| | | |
| | | <div class="table-section"> |
| | | <table class="product-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>产品名称</th> |
| | | <th>规格型号</th> |
| | | <th>单位</th> |
| | | <th>单价</th> |
| | | <th>零售数量</th> |
| | | <th>零售金额</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | ${ |
| | | item.products && |
| | | item |
| | | .products |
| | | .length > |
| | | 0 |
| | | ? item.products |
| | | .map( |
| | | product => ` |
| | | <tr> |
| | | <td>${ |
| | | product.productCategory || |
| | | "" |
| | | }</td> |
| | | <td>${ |
| | | product.specificationModel || |
| | | "" |
| | | }</td> |
| | | <td>${ |
| | | product.unit || |
| | | "" |
| | | }</td> |
| | | <td>${ |
| | | product.taxInclusiveUnitPrice || |
| | | "0" |
| | | }</td> |
| | | <td>${ |
| | | product.quantity || |
| | | "0" |
| | | }</td> |
| | | <td>${ |
| | | product.taxInclusiveTotalPrice || |
| | | "0" |
| | | }</td> |
| | | </tr> |
| | | ` |
| | | ) |
| | | .join( |
| | | "" |
| | | ) |
| | | : '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>' |
| | | } |
| | | </tbody> |
| | | <tfoot> |
| | | <tr> |
| | | <td class="label">合计</td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value">${getTotalQuantityForPrint( |
| | | item.products |
| | | )}</td> |
| | | <td class="total-value">${getTotalAmountForPrint( |
| | | item.products |
| | | )}</td> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | <div class="info-section"> |
| | | <div class="info-row"> |
| | | <div> |
| | | <span class="label">发货日期:</span> |
| | | <span class="value">${formatDate( |
| | | item.createTime |
| | | )}</span> |
| | | </div> |
| | | <div> |
| | | <span class="label">客户名称:</span> |
| | | <span class="value">${ |
| | | item.customerName |
| | | }</span> |
| | | </div> |
| | | </div> |
| | | <div class="info-row"> |
| | | <span class="label">单号:</span> |
| | | <span class="value">${ |
| | | item.salesContractNo || |
| | | "" |
| | | }</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="footer-section"> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">收货电话:</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">收货人:</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item address-item"> |
| | | <span class="label">收货地址:</span> |
| | | <span class="value address-value"></span> |
| | | </div> |
| | | </div> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">操作员:</span> |
| | | <span class="value">${ |
| | | userStore.nickName || |
| | | "撕开前" |
| | | }</span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">打印日期:</span> |
| | | <span class="value">${formatDateTime( |
| | | new Date() |
| | | )}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | `; |
| | | <div class="table-section"> |
| | | <table class="product-table"> |
| | | <thead> |
| | | <tr> |
| | | <th>产品名称</th> |
| | | <th>规格型号</th> |
| | | <th>单位</th> |
| | | <th>单价</th> |
| | | <th>零售数量</th> |
| | | <th>零售金额</th> |
| | | </tr> |
| | | </thead> |
| | | <tbody> |
| | | ${ |
| | | item.products && |
| | | item |
| | | .products |
| | | .length > |
| | | 0 |
| | | ? item.products |
| | | .map( |
| | | product => ` |
| | | <tr> |
| | | <td>${ |
| | | product.productCategory || |
| | | "" |
| | | }</td> |
| | | <td>${ |
| | | product.specificationModel || |
| | | "" |
| | | }</td> |
| | | <td>${ |
| | | product.unit || |
| | | "" |
| | | }</td> |
| | | <td>${ |
| | | product.taxInclusiveUnitPrice || |
| | | "0" |
| | | }</td> |
| | | <td>${ |
| | | product.quantity || |
| | | "0" |
| | | }</td> |
| | | <td>${ |
| | | product.taxInclusiveTotalPrice || |
| | | "0" |
| | | }</td> |
| | | </tr> |
| | | ` |
| | | ) |
| | | .join( |
| | | "" |
| | | ) |
| | | : '<tr><td colspan="6" style="text-align: center; color: #999;">暂无产品数据</td></tr>' |
| | | } |
| | | </tbody> |
| | | <tfoot> |
| | | <tr> |
| | | <td class="label">合计</td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value"></td> |
| | | <td class="total-value">${getTotalQuantityForPrint( |
| | | item.products |
| | | )}</td> |
| | | <td class="total-value">${getTotalAmountForPrint( |
| | | item.products |
| | | )}</td> |
| | | </tr> |
| | | </tfoot> |
| | | </table> |
| | | </div> |
| | | |
| | | <div class="footer-section"> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">收货电话:</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">收货人:</span> |
| | | <span class="value"></span> |
| | | </div> |
| | | <div class="footer-item address-item"> |
| | | <span class="label">收货地址:</span> |
| | | <span class="value address-value"></span> |
| | | </div> |
| | | </div> |
| | | <div class="footer-row"> |
| | | <div class="footer-item"> |
| | | <span class="label">操作员:</span> |
| | | <span class="value">${ |
| | | userStore.nickName || |
| | | "撕开前" |
| | | }</span> |
| | | </div> |
| | | <div class="footer-item"> |
| | | <span class="label">打印日期:</span> |
| | | <span class="value">${formatDateTime( |
| | | new Date() |
| | | )}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | `; |
| | | }); |
| | | |
| | | printContent += ` |
| | | </body> |
| | | </html> |
| | | `; |
| | | </body> |
| | | </html> |
| | | `; |
| | | |
| | | // 写入内容到新窗口 |
| | | printWindow.document.write(printContent); |