feat: 现场需求前端改动
- 会议管理:顶部新增“会议看板提示”条(点击跳会议看板)
- 计量器具:校准模块新增“新增校准”(下拉选择计量器具并关联)
- 采购报表:支持按录入日期排序(PIMTable 支持服务端排序)
- 客户拜访记录:新增 新增/编辑/删除
- 设备报修:新增报修表单必填校验(设备名称)
- 部门管理:操作列新增 上移/下移 排序(两套页面)
- 报工台账:移除“参数详情”功能
| | |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | // 新增拜访记录 |
| | | export function addVisit(data) { |
| | | return request({ |
| | | url: '/customerVisits/add', |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // 编辑拜访记录 |
| | | export function updateVisit(data) { |
| | | return request({ |
| | | url: '/customerVisits/update', |
| | | method: 'post', |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // 删除拜访记录 |
| | | export function delVisit(id) { |
| | | return request({ |
| | | url: '/customerVisits/' + id, |
| | | method: 'delete' |
| | | }) |
| | | } |
| | |
| | | data: ids, |
| | | }); |
| | | } |
| | | // 计量器具下拉(校准选择用,当前租户全部计量器具) |
| | | export function ledgerOptions() { |
| | | return request({ |
| | | url: "/measuringInstrumentLedger/options", |
| | | method: "get", |
| | | }); |
| | | } |
| | |
| | | method: 'delete'
|
| | | })
|
| | | } |
| | |
|
| | | // 修改部门排序(批量)
|
| | | export function updateDeptSort(data) {
|
| | | return request({
|
| | | url: '/system/dept/sort',
|
| | | method: 'put',
|
| | | data: data
|
| | | })
|
| | | } |
| | |
| | | @current-change="currentChange" |
| | | @selection-change="handleSelectionChange" |
| | | @expand-change="expandChange" |
| | | @sort-change="handleSortChange" |
| | | class="lims-table"> |
| | | <el-table-column align="center" |
| | | type="selection" |
| | |
| | | :prop="item.prop" |
| | | :show-overflow-tooltip="item.dataType !== 'action' && item.dataType !== 'slot'" |
| | | :align="item.align" |
| | | :sortable="!!item.sortable" |
| | | :sortable="item.sortable || false" |
| | | :type="item.type" |
| | | :width="item.width" |
| | | :minWidth="item.minWidth"> |
| | |
| | | "expand-change", |
| | | "selection-change", |
| | | "row-click", |
| | | "sort-change", |
| | | ]); |
| | | |
| | | // Filters |
| | |
| | | const handleSelectionChange = newSelection => { |
| | | emit("selection-change", newSelection); |
| | | }; |
| | | |
| | | const handleSortChange = ({ column, prop, order }) => { |
| | | emit("sort-change", { column, prop, order }); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">搜索</el-button> |
| | | <el-button type="primary" @click="handleAdd">新增</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | |
| | | <el-table-column label="拜访时间" prop="purposeDate" width="180" show-overflow-tooltip /> |
| | | <el-table-column label="拜访地点" prop="visitAddress" min-width="200" show-overflow-tooltip /> |
| | | <el-table-column label="拜访人" prop="visitingPeople" width="120" show-overflow-tooltip /> |
| | | <el-table-column fixed="right" label="操作" width="100" align="center"> |
| | | <el-table-column fixed="right" label="操作" width="160" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="viewDetail(scope.row)" style="color: #67C23A">查看</el-button> |
| | | <el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button> |
| | | <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 新增/编辑弹窗 --> |
| | | <el-dialog |
| | | v-model="formVisible" |
| | | :title="formTitle" |
| | | width="600px" |
| | | @close="closeForm" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="客户名称:" prop="customerName"> |
| | | <el-input v-model="form.customerName" placeholder="请输入客户名称" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系人:" prop="contact"> |
| | | <el-input v-model="form.contact" placeholder="请输入联系人" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="联系电话:" prop="contactPhone"> |
| | | <el-input v-model="form.contactPhone" placeholder="请输入联系电话" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="拜访人:" prop="visitingPeople"> |
| | | <el-input v-model="form.visitingPeople" placeholder="请输入拜访人" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="拜访目的:" prop="purposeVisit"> |
| | | <el-input v-model="form.purposeVisit" placeholder="请输入拜访目的" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="拜访时间:" prop="purposeDate"> |
| | | <el-date-picker |
| | | v-model="form.purposeDate" |
| | | type="datetime" |
| | | placeholder="请选择拜访时间" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="拜访地点:" prop="visitAddress"> |
| | | <el-input v-model="form.visitAddress" placeholder="请输入拜访地点" clearable /> |
| | | </el-form-item> |
| | | <el-form-item label="备注:" prop="remark"> |
| | | <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button @click="closeForm">取消</el-button> |
| | | <el-button type="primary" :loading="submitting" @click="submitForm">确定</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, getCurrentInstance } from 'vue' |
| | | import pagination from '@/components/PIMTable/Pagination.vue' |
| | | import { getVisitRecords } from '@/api/collaborativeApproval/customerVisit.js' |
| | | import { getVisitRecords, addVisit, updateVisit, delVisit } from '@/api/collaborativeApproval/customerVisit.js' |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const tableData = ref([]) |
| | |
| | | detailForm.value = {} |
| | | } |
| | | |
| | | // ===== 新增 / 编辑 ===== |
| | | const formVisible = ref(false) |
| | | const formTitle = ref('新增客户拜访记录') |
| | | const formRef = ref(null) |
| | | const submitting = ref(false) |
| | | const form = reactive({ |
| | | id: undefined, |
| | | customerName: '', |
| | | contact: '', |
| | | contactPhone: '', |
| | | visitingPeople: '', |
| | | purposeVisit: '', |
| | | purposeDate: '', |
| | | visitAddress: '', |
| | | remark: '' |
| | | }) |
| | | const rules = { |
| | | customerName: [{ required: true, message: '请输入客户名称', trigger: 'blur' }], |
| | | purposeVisit: [{ required: true, message: '请输入拜访目的', trigger: 'blur' }], |
| | | purposeDate: [{ required: true, message: '请选择拜访时间', trigger: 'change' }], |
| | | visitAddress: [{ required: true, message: '请输入拜访地点', trigger: 'blur' }] |
| | | } |
| | | |
| | | const resetForm = () => { |
| | | Object.assign(form, { |
| | | id: undefined, |
| | | customerName: '', |
| | | contact: '', |
| | | contactPhone: '', |
| | | visitingPeople: '', |
| | | purposeVisit: '', |
| | | purposeDate: '', |
| | | visitAddress: '', |
| | | remark: '' |
| | | }) |
| | | formRef.value?.clearValidate() |
| | | } |
| | | |
| | | // 新增 |
| | | const handleAdd = () => { |
| | | resetForm() |
| | | formTitle.value = '新增客户拜访记录' |
| | | formVisible.value = true |
| | | } |
| | | |
| | | // 编辑 |
| | | const handleEdit = (row) => { |
| | | resetForm() |
| | | Object.assign(form, { |
| | | id: row.id, |
| | | customerName: row.customerName, |
| | | contact: row.contact, |
| | | contactPhone: row.contactPhone, |
| | | visitingPeople: row.visitingPeople, |
| | | purposeVisit: row.purposeVisit, |
| | | purposeDate: row.purposeDate, |
| | | visitAddress: row.visitAddress, |
| | | remark: row.remark |
| | | }) |
| | | formTitle.value = '编辑客户拜访记录' |
| | | formVisible.value = true |
| | | } |
| | | |
| | | // 关闭弹窗 |
| | | const closeForm = () => { |
| | | formVisible.value = false |
| | | resetForm() |
| | | } |
| | | |
| | | // 提交(新增或编辑) |
| | | const submitForm = () => { |
| | | formRef.value.validate((valid) => { |
| | | if (!valid) return |
| | | submitting.value = true |
| | | const payload = { ...form } |
| | | const req = payload.id ? updateVisit(payload) : addVisit(payload) |
| | | req |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess(payload.id ? '编辑成功' : '新增成功') |
| | | formVisible.value = false |
| | | getList() |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || '操作失败') |
| | | } |
| | | }) |
| | | .finally(() => { |
| | | submitting.value = false |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // 删除 |
| | | const handleDelete = (row) => { |
| | | proxy.$modal |
| | | .confirm(`确认删除客户“${row.customerName}”的拜访记录吗?`) |
| | | .then(() => { |
| | | delVisit(row.id).then((res) => { |
| | | if (res.code === 200) { |
| | | proxy.$modal.msgSuccess('删除成功') |
| | | getList() |
| | | } else { |
| | | proxy.$modal.msgError(res.msg || '删除失败') |
| | | } |
| | | }) |
| | | }) |
| | | .catch(() => {}) |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getList() |
| | | }) |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- 会议看板提示条 --> |
| | | <div |
| | | class="meeting-board-tip" |
| | | :class="{ 'is-active': stats.underWay > 0 || stats.toStart > 0 }" |
| | | @click="goMeetingBoard" |
| | | > |
| | | <el-icon class="tip-icon"><BellFilled /></el-icon> |
| | | <div class="tip-body"> |
| | | <span class="tip-title">会议看板提示</span> |
| | | <span class="tip-text"> |
| | | 共 <b>{{ stats.total }}</b> 场会议 · |
| | | 进行中 <b class="num-ongoing">{{ stats.underWay }}</b> 场 · |
| | | 即将开始 <b class="num-soon">{{ stats.toStart }}</b> 场 |
| | | </span> |
| | | </div> |
| | | <span class="tip-link">查看会议看板 ›</span> |
| | | </div> |
| | | |
| | | <div class="tabs-wrapper"> |
| | | <el-tabs |
| | | v-model="activeTab" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed } from 'vue' |
| | | import { ref, computed, onMounted, onActivated } from 'vue' |
| | | import { useRouter } from 'vue-router' |
| | | import { BellFilled } from '@element-plus/icons-vue' |
| | | import { getMeetSummary } from '@/api/collaborativeApproval/meeting.js' |
| | | import MeetSetting from '../notificationManagement/meetSetting/index.vue' |
| | | import MeetIndex from '../notificationManagement/meetIndex/index.vue' |
| | | import MeetApplication from '../notificationManagement/meetApplication/index.vue' |
| | |
| | | function handleTabChange(name) { |
| | | activeTab.value = name |
| | | } |
| | | |
| | | // 会议看板提示条数据 |
| | | const router = useRouter() |
| | | const stats = ref({ total: 0, underWay: 0, completed: 0, toStart: 0 }) |
| | | |
| | | const loadMeetingStats = async () => { |
| | | try { |
| | | const { data } = await getMeetSummary() |
| | | stats.value = { |
| | | total: Number(data?.total) || 0, |
| | | underWay: Number(data?.underWay) || 0, |
| | | completed: Number(data?.completed) || 0, |
| | | toStart: Number(data?.toStart) || 0 |
| | | } |
| | | } catch (e) { |
| | | // 提示条数据加载失败不影响会议管理主流程 |
| | | console.warn('会议看板提示加载失败:', e) |
| | | } |
| | | } |
| | | |
| | | const goMeetingBoard = () => { |
| | | router.push('/collaborativeApproval/meetingBoard') |
| | | } |
| | | |
| | | let tipInited = false |
| | | onMounted(loadMeetingStats) |
| | | onActivated(() => { |
| | | // keep-alive 缓存时,切回页面刷新提示条 |
| | | if (tipInited) loadMeetingStats() |
| | | tipInited = true |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | |
| | | .meeting-board-tip { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | padding: 10px 16px; |
| | | margin-bottom: 12px; |
| | | border-radius: 8px; |
| | | cursor: pointer; |
| | | background: #f4f8ff; |
| | | border: 1px solid #d6e4ff; |
| | | transition: background 0.2s, border-color 0.2s; |
| | | } |
| | | |
| | | .meeting-board-tip:hover { |
| | | background: #e8f1ff; |
| | | } |
| | | |
| | | .meeting-board-tip.is-active { |
| | | background: #fff7e6; |
| | | border-color: #ffd591; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-icon { |
| | | font-size: 18px; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .meeting-board-tip.is-active .tip-icon { |
| | | color: #fa8c16; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-body { |
| | | flex: 1; |
| | | min-width: 0; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-title { |
| | | font-weight: 600; |
| | | color: #1f2d3d; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-text { |
| | | font-size: 13px; |
| | | color: #5b6b7f; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-text b { |
| | | font-size: 15px; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-text .num-ongoing { |
| | | color: #fa8c16; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-text .num-soon { |
| | | color: #13c2c2; |
| | | } |
| | | |
| | | .meeting-board-tip .tip-link { |
| | | font-size: 13px; |
| | | color: #409eff; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .tabs-wrapper { |
| | | margin-bottom: 10px; |
| | | } |
| | |
| | | <el-button @click="handleReset" style="margin-left: 10px">重置</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openCalibrationDia('add')">新增校准</el-button> |
| | | <el-button @click="handleOut">导出</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | <div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="计量器具" |
| | | :title="dialogTitle" |
| | | width="50%" |
| | | draggable |
| | | @close="closeDia" |
| | |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-row :gutter="30"> |
| | | <el-row :gutter="30" v-if="operationType === 'add'"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="计量器具:" prop="measuringInstrumentLedgerId"> |
| | | <el-select |
| | | v-model="form.measuringInstrumentLedgerId" |
| | | placeholder="请选择计量器具" |
| | | filterable |
| | | clearable |
| | | style="width: 100%" |
| | | @change="handleInstrumentChange" |
| | | > |
| | | <el-option |
| | | v-for="item in instrumentOptions" |
| | | :key="item.id" |
| | | :label="`${item.code} - ${item.name}`" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30" v-else> |
| | | <el-col :span="12"> |
| | | <el-form-item label="计量器具编号:" prop="customerName"> |
| | | <el-input |
| | |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- <el-row :gutter="30">--> |
| | | <!-- <el-col :span="24">--> |
| | | <!-- <el-form-item label="附件材料:" prop="remark">--> |
| | | <!-- <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload--> |
| | | <!-- :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"--> |
| | | <!-- :on-success="handleUploadSuccess" :on-remove="handleRemove">--> |
| | | <!-- <el-button type="primary" v-if="operationType !== 'view'">上传</el-button>--> |
| | | <!-- <template #tip v-if="operationType !== 'view'">--> |
| | | <!-- <div class="el-upload__tip">--> |
| | | <!-- 文件格式支持--> |
| | | <!-- doc,docx,xls,xlsx,ppt,pptx,pdf,txt,xml,jpg,jpeg,png,gif,bmp,rar,zip,7z--> |
| | | <!-- </div>--> |
| | | <!-- </template>--> |
| | | <!-- </el-upload>--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- </el-row>--> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, toRefs, getCurrentInstance} from "vue"; |
| | | import {ref, reactive, toRefs, getCurrentInstance, computed} from "vue"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import {afterSalesServiceAdd, afterSalesServiceUpdate} from "@/api/customerService/index.js"; |
| | | import {getToken} from "@/utils/auth.js"; |
| | | import {ledgerRecordUpdate, ledgerRecordVerifying} from "@/api/equipmentManagement/calibration.js"; |
| | | import {delLedgerFile} from "@/api/salesManagement/salesLedger.js"; |
| | | import {ledgerRecordUpdate, ledgerRecordVerifying, ledgerOptions} from "@/api/equipmentManagement/calibration.js"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | |
| | | const operationType = ref('') |
| | | const userStore = useUserStore(); |
| | | |
| | | const dialogTitle = computed(() => { |
| | | if (operationType.value === 'add') return '新增校准' |
| | | if (operationType.value === 'verifying') return '计量器具检定' |
| | | return '编辑校准' |
| | | }) |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | id: undefined, |
| | | measuringInstrumentLedgerId: undefined, |
| | | code: "", |
| | | name: "", |
| | | model: "", |
| | | valid: "", |
| | | recordDate: "", |
| | | userId: "", |
| | |
| | | tempFileIds: [] |
| | | }, |
| | | rules: { |
| | | measuringInstrumentLedgerId: [{required: true, message: "请选择计量器具", trigger: "change"}], |
| | | code: [{required: true, message: "请输入", trigger: "blur"}], |
| | | name: [{required: true, message: "请输入", trigger: "blur"}], |
| | | valid: [ |
| | |
| | | }) |
| | | const { form, rules } = toRefs(data); |
| | | const userList = ref([]) |
| | | const instrumentOptions = ref([]); |
| | | const fileList = ref([]); |
| | | const upload = reactive({ |
| | | // 上传的地址 |
| | |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | }); |
| | | |
| | | // 加载计量器具下拉(当前租户全部计量器具) |
| | | const loadInstrumentOptions = () => { |
| | | ledgerOptions().then((res) => { |
| | | instrumentOptions.value = res.data || []; |
| | | }).catch(() => { |
| | | instrumentOptions.value = []; |
| | | }); |
| | | }; |
| | | |
| | | // 选择计量器具后回填编号/名称/证书编号,并记住台账ID(verifying 用 id 作为台账ID) |
| | | const handleInstrumentChange = (id) => { |
| | | const it = instrumentOptions.value.find(o => o.id === id); |
| | | if (it) { |
| | | form.value.id = it.id; |
| | | form.value.code = it.code; |
| | | form.value.name = it.name; |
| | | form.value.model = it.model; |
| | | } else { |
| | | form.value.id = undefined; |
| | | form.value.code = ""; |
| | | form.value.name = ""; |
| | | form.value.model = ""; |
| | | } |
| | | }; |
| | | |
| | | // 打开弹框 |
| | | const openDialog = (type, row) => { |
| | | console.log(row) |
| | | const openDialog = (type, row = {}) => { |
| | | operationType.value = type; |
| | | dialogFormVisible.value = true; |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | fileList.value = [] |
| | | if(type !== "add"){ |
| | | fileList.value = []; |
| | | // 重置表单 |
| | | form.value.id = undefined; |
| | | form.value.measuringInstrumentLedgerId = undefined; |
| | | form.value.code = ""; |
| | | form.value.name = ""; |
| | | form.value.model = ""; |
| | | form.value.valid = ""; |
| | | form.value.recordDate = ""; |
| | | form.value.tempFileIds = []; |
| | | |
| | | if (type === "add") { |
| | | loadInstrumentOptions(); |
| | | } |
| | | if (type === "edit") { |
| | | form.value.id = row.id; |
| | | form.value.code = row.code; |
| | | form.value.name = row.name; |
| | | form.value.valid = row.valid; |
| | | form.value.recordDate = row.recordDate; |
| | | fileList.value = row.commonFiles; |
| | | } |
| | | if(type === "add"){ |
| | | fileList.value = row.commonFiles; |
| | | } |
| | | if(type === "verifying"){ |
| | | form.value.id = row.id; |
| | | form.value.code = row.code; |
| | | form.value.name = row.name; |
| | | form.value.model = row.model; |
| | | form.value.valid = row.valid; |
| | | form.value.recordDate = row.mostDate; |
| | | } |
| | | |
| | | form.value.id = row.id; |
| | | form.value.code = row.code; |
| | | form.value.name = row.name; |
| | | form.value.userId = userStore.id; |
| | | form.value.entryDate = getCurrentDate(); |
| | | } |
| | |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "verifying") { |
| | | if (operationType.value === "add") { |
| | | // 新增校准:复用检定接口,写一条校准记录并同步更新台账检定日期/有效期 |
| | | ledgerRecordVerifying(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("新增校准成功") |
| | | closeDia() |
| | | }) |
| | | } else if (operationType.value === "verifying") { |
| | | ledgerRecordVerifying(form.value).then(response => { |
| | | proxy.$modal.msgSuccess("检定校准成功") |
| | | closeDia() |
| | |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose"> |
| | | <el-form :model="form" |
| | | <el-form ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称"> |
| | | <el-form-item label="设备名称" |
| | | prop="deviceLedgerId"> |
| | | <el-select v-model="form.deviceLedgerId" |
| | | @change="setDeviceModel" |
| | | filterable |
| | |
| | | const userStore = useUserStore(); |
| | | const deviceOptions = ref([]); |
| | | const fileList = ref([]); |
| | | const formRef = ref(); |
| | | |
| | | const rules = { |
| | | deviceLedgerId: [ |
| | | { required: true, message: "请选择设备", trigger: "change" }, |
| | | ], |
| | | }; |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | const valid = await formRef.value.validate().catch(() => false); |
| | | if (!valid) return; |
| | | loading.value = true; |
| | | try { |
| | | const { code } = id.value |
| | |
| | | const openAdd = async () => { |
| | | id.value = undefined; |
| | | operationType.value = "add"; |
| | | resetForm(); |
| | | visible.value = true; |
| | | fileList.value = []; |
| | | await nextTick(); |
| | |
| | | </el-table-column> |
| | | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" icon="Top" @click="moveUp(scope.row)" v-hasPermi="['system:dept:edit']">上移</el-button> |
| | | <el-button link type="primary" icon="Bottom" @click="moveDown(scope.row)" v-hasPermi="['system:dept:edit']">下移</el-button> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dept:edit']">修改</el-button> |
| | | <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:dept:add']">新增</el-button> |
| | | <el-button v-if="scope.row.parentId != 0" link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dept:remove']">删除</el-button> |
| | |
| | | </template> |
| | | |
| | | <script setup name="Dept"> |
| | | import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept" |
| | | import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild, updateDeptSort } from "@/api/system/dept" |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const { sys_normal_disable } = proxy.useDict("sys_normal_disable") |
| | |
| | | }).catch(() => {}) |
| | | } |
| | | |
| | | /** 找到部门在同级中的位置 */ |
| | | function findSiblings(targetId, list = deptList.value) { |
| | | for (let i = 0; i < list.length; i++) { |
| | | if (list[i].deptId === targetId) { |
| | | return { list, index: i } |
| | | } |
| | | if (list[i].children && list[i].children.length) { |
| | | const r = findSiblings(targetId, list[i].children) |
| | | if (r) return r |
| | | } |
| | | } |
| | | return null |
| | | } |
| | | |
| | | /** 保存同级排序(重排 0..n-1) */ |
| | | function saveDeptSort(siblings) { |
| | | const payload = siblings.map((d, i) => ({ deptId: d.deptId, orderNum: i })) |
| | | return updateDeptSort(payload).then(() => { |
| | | proxy.$modal.msgSuccess("排序成功") |
| | | getList() |
| | | }) |
| | | } |
| | | |
| | | /** 上移 */ |
| | | function moveUp(row) { |
| | | const s = findSiblings(row.deptId) |
| | | if (!s || s.index <= 0) { |
| | | proxy.$modal.msgWarning("已经是第一个了") |
| | | return |
| | | } |
| | | const { list, index } = s |
| | | const tmp = list[index - 1] |
| | | list[index - 1] = list[index] |
| | | list[index] = tmp |
| | | saveDeptSort(list) |
| | | } |
| | | |
| | | /** 下移 */ |
| | | function moveDown(row) { |
| | | const s = findSiblings(row.deptId) |
| | | if (!s || s.index >= s.list.length - 1) { |
| | | proxy.$modal.msgWarning("已经是最后一个了") |
| | | return |
| | | } |
| | | const { list, index } = s |
| | | const tmp = list[index + 1] |
| | | list[index + 1] = list[index] |
| | | list[index] = tmp |
| | | saveDeptSort(list) |
| | | } |
| | | |
| | | getList() |
| | | </script> |
| | | |
| | |
| | | :is-show-pagination="true" |
| | | :page="page" |
| | | @pagination="handlePagination" |
| | | @sort-change="handleSortChange" |
| | | /> |
| | | </div> |
| | | </el-card> |
| | |
| | | { |
| | | label: '录入日期', |
| | | prop: 'entryDate', |
| | | width: 120 |
| | | width: 120, |
| | | sortable: 'custom' |
| | | } |
| | | ]) |
| | | |
| | |
| | | current: 1, |
| | | size: 50, |
| | | }) |
| | | |
| | | // 排序状态(按录入日期排序) |
| | | const sortState = reactive({ prop: '', order: '' }) |
| | | |
| | | // 表格排序变化 |
| | | const handleSortChange = ({ prop, order }) => { |
| | | if (order) { |
| | | sortState.prop = prop |
| | | sortState.order = order === 'ascending' ? 'asc' : 'desc' |
| | | } else { |
| | | sortState.prop = '' |
| | | sortState.order = '' |
| | | } |
| | | page.current = 1 |
| | | handleSearch() |
| | | } |
| | | |
| | | // 转换产品树数据,将 id 改为 value |
| | | function convertIdToValue(data) { |
| | |
| | | params.current = page.current |
| | | params.size = page.size |
| | | |
| | | // 排序参数(按录入日期) |
| | | if (sortState.prop) { |
| | | params.orderByColumn = sortState.prop |
| | | params.isAsc = sortState.order |
| | | } |
| | | |
| | | const res = await procurementBusinessSummaryListPage(params) |
| | | if (res && res.data) { |
| | | // 兼容后端可能直接返回数组/或返回分页对象 |
| | |
| | | <input-modal v-if="isShowInput" |
| | | v-model:visible="isShowInput" |
| | | :production-product-main-id="isShowingId" /> |
| | | <!-- 参数详情弹窗 --> |
| | | <el-dialog v-model="paramDetailVisible" |
| | | title="参数详情" |
| | | width="600px"> |
| | | <div v-if="currentParams && currentParams.length > 0" |
| | | class="param-detail-list"> |
| | | <el-descriptions :column="1" |
| | | border> |
| | | <el-descriptions-item v-for="param in currentParams" |
| | | :key="param.id" |
| | | :label="param.paramName"> |
| | | {{ param.inputValue }} |
| | | <span v-if="param.unit && param.unit !== '/'" |
| | | class="unit-text">({{ param.unit }})</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | <el-empty v-else |
| | | description="暂无参数数据" /> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="paramDetailVisible = false">关闭</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | }, |
| | | }, |
| | | { |
| | | name: "参数详情", |
| | | type: "text", |
| | | clickFun: row => { |
| | | showParamDetail(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "删除", |
| | | type: "danger", |
| | | clickFun: row => { |
| | |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const paramDetailVisible = ref(false); |
| | | const currentParams = ref([]); |
| | | |
| | | const showParamDetail = row => { |
| | | currentParams.value = row.productionOperationParamList || []; |
| | | paramDetailVisible.value = true; |
| | | }; |
| | | const selectedRows = ref([]); |
| | | const tableLoading = ref(false); |
| | | const childrenLoading = ref(false); |
| | |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .unit-text { |
| | | margin-left: 5px; |
| | | color: #909399; |
| | | font-size: 12px; |
| | | } |
| | | .param-detail-list { |
| | | padding: 10px; |
| | | } |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | |
| | | </el-table-column>
|
| | | <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
| | | <template #default="scope">
|
| | | <el-button link type="primary" icon="Top" @click="moveUp(scope.row)" v-hasPermi="['system:dept:edit']">上移</el-button> |
| | | <el-button link type="primary" icon="Bottom" @click="moveDown(scope.row)" v-hasPermi="['system:dept:edit']">下移</el-button> |
| | | <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dept:edit']">修改</el-button>
|
| | | <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:dept:add']">新增</el-button>
|
| | | <el-button v-if="scope.row.parentId != 0" link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dept:remove']">删除</el-button>
|
| | |
| | | </template>
|
| | |
|
| | | <script setup name="Dept">
|
| | | import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept"
|
| | | import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild, updateDeptSort } from "@/api/system/dept"
|
| | |
|
| | | const { proxy } = getCurrentInstance()
|
| | | const { sys_normal_disable } = proxy.useDict("sys_normal_disable")
|
| | |
| | | }).catch(() => {})
|
| | | }
|
| | |
|
| | | /** 找到部门在同级中的位置 */
|
| | | function findSiblings(targetId, list = deptList.value) {
|
| | | for (let i = 0; i < list.length; i++) {
|
| | | if (list[i].deptId === targetId) {
|
| | | return { list, index: i }
|
| | | }
|
| | | if (list[i].children && list[i].children.length) {
|
| | | const r = findSiblings(targetId, list[i].children)
|
| | | if (r) return r
|
| | | }
|
| | | }
|
| | | return null
|
| | | }
|
| | |
|
| | | /** 保存同级排序(重排 0..n-1) */
|
| | | function saveDeptSort(siblings) {
|
| | | const payload = siblings.map((d, i) => ({ deptId: d.deptId, orderNum: i }))
|
| | | return updateDeptSort(payload).then(() => {
|
| | | proxy.$modal.msgSuccess("排序成功")
|
| | | getList()
|
| | | })
|
| | | }
|
| | |
|
| | | /** 上移 */
|
| | | function moveUp(row) {
|
| | | const s = findSiblings(row.deptId)
|
| | | if (!s || s.index <= 0) {
|
| | | proxy.$modal.msgWarning("已经是第一个了")
|
| | | return
|
| | | }
|
| | | const { list, index } = s
|
| | | const tmp = list[index - 1]
|
| | | list[index - 1] = list[index]
|
| | | list[index] = tmp
|
| | | saveDeptSort(list)
|
| | | }
|
| | |
|
| | | /** 下移 */
|
| | | function moveDown(row) {
|
| | | const s = findSiblings(row.deptId)
|
| | | if (!s || s.index >= s.list.length - 1) {
|
| | | proxy.$modal.msgWarning("已经是最后一个了")
|
| | | return
|
| | | }
|
| | | const { list, index } = s
|
| | | const tmp = list[index + 1]
|
| | | list[index + 1] = list[index]
|
| | | list[index] = tmp
|
| | | saveDeptSort(list)
|
| | | }
|
| | |
|
| | | getList()
|
| | | </script>
|