| | |
| | | <template> |
| | | <div> |
| | | <el-dialog :title="operationType === 'add' ? '新增巡检任务' : '编辑巡检任务'" |
| | | v-model="dialogVisitable" width="800px" @close="cancel"> |
| | | <el-dialog |
| | | v-model="dialogVisitable" |
| | | :title="operationType === 'add' ? '新增巡检任务' : '编辑巡检任务'" |
| | | width="800px" |
| | | @close="cancel" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称" prop="taskId"> |
| | | <el-select v-model="form.taskId" @change="setDeviceModel"> |
| | | <el-form-item label="所属区域" prop="areaId"> |
| | | <el-tree-select |
| | | v-model="form.areaId" |
| | | :data="areaOptions" |
| | | :props="areaTreeProps" |
| | | node-key="id" |
| | | value-key="id" |
| | | check-strictly |
| | | clearable |
| | | filterable |
| | | placeholder="请选择所属区域" |
| | | style="width: 100%" |
| | | @change="handleAreaChange" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称" prop="deviceLedgerIds"> |
| | | <el-select |
| | | v-model="form.deviceLedgerIds" |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | clearable |
| | | filterable |
| | | placeholder="请选择设备" |
| | | style="width: 100%" |
| | | @change="setDeviceModels" |
| | | > |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | v-for="item in deviceOptions" |
| | | :key="item.id" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检人" prop="inspector"> |
| | | <el-select v-model="form.inspector" placeholder="请选择" multiple clearable> |
| | | <el-option v-for="item in userList" :label="item.nickName" :value="item.userId" :key="item.userId"/> |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="巡检项目" prop="inspectionProject"> |
| | | <el-input v-model="form.inspectionProject" placeholder="请输入巡检项目" type="textarea" :autosize="{ minRows: 2, maxRows: 6 }" /> |
| | | <el-form-item label="规格型号"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="自动带出规格型号" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="备注" prop="remarks"> |
| | | <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" :autosize="{ minRows: 2, maxRows: 6 }" /> |
| | | <el-input v-model="form.remarks" placeholder="请输入备注" type="textarea" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否启用" prop="isEnabled"> |
| | | <el-radio-group v-model="form.isEnabled"> |
| | | <el-radio :value="1">是</el-radio> |
| | | <el-radio :value="0">否</el-radio> |
| | | </el-radio-group> |
| | | <el-switch |
| | | v-model="form.isEnabled" |
| | | :active-value="1" |
| | | :inactive-value="0" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-option label="每日" value="DAILY"/> |
| | | <el-option label="每周" value="WEEKLY"/> |
| | | <el-option label="每月" value="MONTHLY"/> |
| | | <!-- <el-option label="季度" value="QUARTERLY"/> --> |
| | | <el-option label="每年" value="YEARLY" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'DAILY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-time-picker v-model="form.frequencyDetail" placeholder="选择时间" format="HH:mm" |
| | | value-format="HH:mm" /> |
| | | <el-time-picker |
| | | v-model="form.frequencyDetail" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'WEEKLY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-select v-model="form.week" placeholder="请选择" clearable style="width: 50%"> |
| | | <el-option label="周一" value="MON"/> |
| | |
| | | <el-option label="周六" value="SAT"/> |
| | | <el-option label="周日" value="SUN"/> |
| | | </el-select> |
| | | <el-time-picker v-model="form.time" placeholder="选择时间" format="HH:mm" |
| | | value-format="HH:mm" style="width: 50%"/> |
| | | <el-time-picker |
| | | v-model="form.time" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 50%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'MONTHLY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'YEARLY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {reactive, ref, getCurrentInstance, toRefs} from "vue"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getCurrentInstance, reactive, ref, toRefs } from "vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import {addOrEditTimingTask} from "@/api/inspectionManagement/index.js"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { |
| | | getDeviceAreaTree, |
| | | getDeviceAreaTreeWithDevices, |
| | | } from "@/api/equipmentManagement/deviceArea"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits() |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(["closeDia"]); |
| | | const userStore = useUserStore(); |
| | | const dialogVisitable = ref(false); |
| | | const operationType = ref('add'); |
| | | const operationType = ref("add"); |
| | | const areaOptions = ref([]); |
| | | const deviceOptions = ref([]); |
| | | const userList = ref([]); |
| | | const areaTreeProps = { |
| | | label: "areaName", |
| | | children: "children", |
| | | }; |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | areaId: undefined, |
| | | taskId: undefined, |
| | | taskIds: [], |
| | | taskIdsStr: undefined, |
| | | deviceLedgerIds: [], |
| | | deviceLedgerIdsStr: undefined, |
| | | taskName: undefined, |
| | | inspector: '', |
| | | inspectorIds: '', |
| | | inspectionProject: '', |
| | | deviceModel: undefined, |
| | | inspector: [], |
| | | inspectorIds: "", |
| | | remarks: "", |
| | | isEnabled: 1, |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '' |
| | | frequencyType: "", |
| | | frequencyDetail: "", |
| | | week: "", |
| | | time: "", |
| | | }, |
| | | rules: { |
| | | taskId: [{ required: true, message: "请选择设备", trigger: "change" },], |
| | | inspector: [{ required: true, message: "请输入巡检人", trigger: "blur" },], |
| | | dateStr: [{ required: true, message: "请选择登记时间", trigger: "change" }], |
| | | areaId: [{ required: true, message: "请选择所属区域", trigger: "change" }], |
| | | deviceLedgerIds: [{ required: true, message: "请选择设备", trigger: "change" }], |
| | | inspector: [{ required: true, message: "请选择巡检人", trigger: "change" }], |
| | | frequencyType: [{ required: true, message: "请选择任务频率", trigger: "change" }], |
| | | frequencyDetail: [ |
| | | { |
| | | required: true, |
| | | message: "请选择日期", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (!form.value.frequencyType) { |
| | | callback() |
| | | return |
| | | callback(); |
| | | return; |
| | | } |
| | | if (form.value.frequencyType === 'WEEKLY') { |
| | | if (form.value.frequencyType === "WEEKLY") { |
| | | if (!form.value.week || !form.value.time) { |
| | | callback(new Error("请选择日期和时间")) |
| | | callback(new Error("请选择日期和时间")); |
| | | } else { |
| | | callback() |
| | | callback(); |
| | | } |
| | | } else { |
| | | return; |
| | | } |
| | | if (!value) { |
| | | callback(new Error("请选择日期")) |
| | | } else { |
| | | callback() |
| | | callback(new Error("请选择日期")); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | callback(); |
| | | }, |
| | | }, |
| | | ], |
| | | week: [ |
| | | { |
| | | required: true, |
| | | message: "请选择星期", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (form.value.frequencyType === 'WEEKLY' && !value) { |
| | | callback(new Error("请选择星期")) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | } |
| | | ], |
| | | time: [ |
| | | { |
| | | required: true, |
| | | message: "请选择时间", |
| | | trigger: "change", |
| | | validator: (rule, value, callback) => { |
| | | if (form.value.frequencyType === 'WEEKLY' && !value) { |
| | | callback(new Error("请选择时间")) |
| | | } else { |
| | | callback() |
| | | } |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | const userList = ref([]) |
| | | }, |
| | | }); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | const { form, rules } = toRefs(data); |
| | | |
| | | const loadAreaTree = async () => { |
| | | const { data } = await getDeviceAreaTree(); |
| | | areaOptions.value = Array.isArray(data) ? data : []; |
| | | }; |
| | | |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.taskName = option.deviceName; |
| | | const normalizeIdList = (value) => { |
| | | if (Array.isArray(value)) { |
| | | return value |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (typeof value === "string") { |
| | | return value |
| | | .split(",") |
| | | .map((item) => Number(item.trim())) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (value !== undefined && value !== null && value !== "") { |
| | | const numericValue = Number(value); |
| | | return Number.isFinite(numericValue) ? [numericValue] : []; |
| | | } |
| | | return []; |
| | | }; |
| | | |
| | | // 打开弹框 |
| | | const getNodeDevices = (node) => { |
| | | const candidates = [ |
| | | node?.deviceList, |
| | | node?.devices, |
| | | node?.deviceLedgerList, |
| | | node?.deviceLedgers, |
| | | node?.ledgerList, |
| | | node?.ledgers, |
| | | ]; |
| | | return candidates.find((item) => Array.isArray(item)) || []; |
| | | }; |
| | | |
| | | const normalizeDevice = (item) => ({ |
| | | ...item, |
| | | id: item.id ?? item.deviceLedgerId, |
| | | deviceName: item.deviceName ?? item.name, |
| | | deviceModel: item.deviceModel ?? item.model, |
| | | }); |
| | | |
| | | const collectDevices = (node) => { |
| | | const currentDevices = getNodeDevices(node).map(normalizeDevice); |
| | | const childDevices = (node?.children || []).flatMap((child) => |
| | | collectDevices(child) |
| | | ); |
| | | const deviceMap = new Map(); |
| | | [...currentDevices, ...childDevices].forEach((item) => { |
| | | if (item?.id !== undefined && item?.id !== null) { |
| | | deviceMap.set(Number(item.id), item); |
| | | } |
| | | }); |
| | | return Array.from(deviceMap.values()); |
| | | }; |
| | | |
| | | const findAreaNode = (nodes, areaId) => { |
| | | for (const node of nodes || []) { |
| | | if (Number(node.id) === Number(areaId)) { |
| | | return node; |
| | | } |
| | | const target = findAreaNode(node.children, areaId); |
| | | if (target) { |
| | | return target; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const loadDevicesByArea = async (areaId) => { |
| | | if (!areaId) { |
| | | deviceOptions.value = []; |
| | | return; |
| | | } |
| | | const { data } = await getDeviceAreaTreeWithDevices(); |
| | | const treeData = Array.isArray(data) ? data : []; |
| | | const currentNode = findAreaNode(treeData, areaId); |
| | | deviceOptions.value = currentNode ? collectDevices(currentNode) : []; |
| | | }; |
| | | |
| | | const syncDeviceFields = (deviceIds) => { |
| | | const selectedIds = normalizeIdList(deviceIds); |
| | | const selectedDevices = selectedIds |
| | | .map((deviceId) => |
| | | deviceOptions.value.find((item) => Number(item.id) === Number(deviceId)) |
| | | ) |
| | | .filter(Boolean); |
| | | |
| | | form.value.deviceLedgerIds = selectedIds; |
| | | form.value.deviceLedgerIdsStr = selectedIds.join(","); |
| | | form.value.taskIds = [...selectedIds]; |
| | | form.value.taskIdsStr = selectedIds.join(","); |
| | | form.value.taskId = selectedIds[0]; |
| | | form.value.taskName = selectedDevices |
| | | .map((item) => item.deviceName) |
| | | .filter(Boolean) |
| | | .join(","); |
| | | form.value.deviceModel = selectedDevices |
| | | .map((item) => item.deviceModel || "-") |
| | | .join(","); |
| | | }; |
| | | |
| | | const setDeviceModels = (deviceIds) => { |
| | | syncDeviceFields(deviceIds); |
| | | }; |
| | | |
| | | const handleAreaChange = async (areaId) => { |
| | | form.value.taskId = undefined; |
| | | form.value.taskIds = []; |
| | | form.value.taskIdsStr = undefined; |
| | | form.value.deviceLedgerIds = []; |
| | | form.value.deviceLedgerIdsStr = undefined; |
| | | form.value.taskName = undefined; |
| | | form.value.deviceModel = undefined; |
| | | await loadDevicesByArea(areaId); |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields(); |
| | | } |
| | | form.value = { |
| | | areaId: undefined, |
| | | taskId: undefined, |
| | | taskIds: [], |
| | | taskIdsStr: undefined, |
| | | deviceLedgerIds: [], |
| | | deviceLedgerIdsStr: undefined, |
| | | taskName: undefined, |
| | | deviceModel: undefined, |
| | | inspector: [], |
| | | inspectorIds: "", |
| | | remarks: "", |
| | | isEnabled: 1, |
| | | frequencyType: "", |
| | | frequencyDetail: "", |
| | | week: "", |
| | | time: "", |
| | | }; |
| | | }; |
| | | |
| | | const openDialog = async (type, row) => { |
| | | dialogVisitable.value = true |
| | | operationType.value = type |
| | | |
| | | // 重置表单 |
| | | dialogVisitable.value = true; |
| | | operationType.value = type; |
| | | resetForm(); |
| | | |
| | | // 加载用户列表 |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | |
| | | // 加载设备列表 |
| | | await loadDeviceName(); |
| | | await loadAreaTree(); |
| | | |
| | | if (type === 'edit' && row) { |
| | | form.value = {...row} |
| | | form.value.inspector = form.value.inspectorIds.split(',').map(Number) |
| | | |
| | | // 如果有设备ID,自动设置设备信息 |
| | | if (form.value.taskId) { |
| | | setDeviceModel(form.value.taskId); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 关闭对话框 |
| | | const cancel = () => { |
| | | resetForm() |
| | | dialogVisitable.value = false |
| | | emit('closeDia') |
| | | } |
| | | |
| | | // 重置表单函数 |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields() |
| | | } |
| | | // 重置表单数据确保设备信息正确重置 |
| | | if (type === "edit" && row) { |
| | | form.value = { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | inspector: '', |
| | | inspectorIds: '', |
| | | inspectionProject: '', |
| | | isEnabled: 1, |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '' |
| | | } |
| | | } |
| | | ...form.value, |
| | | ...row, |
| | | isEnabled: Number(row.isEnabled ?? row.status ?? 1), |
| | | inspector: row.inspectorIds |
| | | ? String(row.inspectorIds) |
| | | .split(",") |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)) |
| | | : [], |
| | | }; |
| | | |
| | | // 提交表单 |
| | | form.value.deviceLedgerIds = normalizeIdList( |
| | | row.deviceLedgerIds ?? |
| | | row.deviceLedgerIdsStr ?? |
| | | row.taskIds ?? |
| | | row.taskIdsStr ?? |
| | | row.taskId |
| | | ); |
| | | form.value.deviceLedgerIdsStr = form.value.deviceLedgerIds.join(","); |
| | | form.value.taskIds = [...form.value.deviceLedgerIds]; |
| | | form.value.taskIdsStr = form.value.deviceLedgerIds.join(","); |
| | | form.value.taskId = form.value.deviceLedgerIds[0]; |
| | | |
| | | if (form.value.areaId) { |
| | | await loadDevicesByArea(form.value.areaId); |
| | | syncDeviceFields(form.value.deviceLedgerIds); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const cancel = () => { |
| | | resetForm(); |
| | | dialogVisitable.value = false; |
| | | emit("closeDia"); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | proxy.$refs.formRef.validate(async (valid) => { |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | try { |
| | | form.value.inspectorIds = form.value.inspector.join(',') |
| | | delete form.value.inspector |
| | | syncDeviceFields(form.value.deviceLedgerIds); |
| | | const payload = { ...form.value }; |
| | | |
| | | if (form.value.frequencyType === 'WEEKLY') { |
| | | let frequencyDetail = '' |
| | | frequencyDetail = form.value.week + ',' + form.value.time |
| | | form.value.frequencyDetail = frequencyDetail |
| | | payload.inspectorIds = Array.isArray(form.value.inspector) |
| | | ? form.value.inspector.join(",") |
| | | : ""; |
| | | delete payload.inspector; |
| | | |
| | | if (payload.frequencyType === "WEEKLY") { |
| | | payload.frequencyDetail = `${payload.week},${payload.time}`; |
| | | } |
| | | |
| | | let res = await userStore.getInfo() |
| | | form.value.registrantId = res.user.userId |
| | | const userInfo = await userStore.getInfo(); |
| | | payload.registrantId = userInfo.user.userId; |
| | | payload.taskId = form.value.deviceLedgerIds[0]; |
| | | payload.taskIds = [...form.value.deviceLedgerIds]; |
| | | payload.taskIdsStr = form.value.deviceLedgerIds.join(","); |
| | | payload.deviceLedgerIds = [...form.value.deviceLedgerIds]; |
| | | payload.deviceLedgerIdsStr = form.value.deviceLedgerIds.join(","); |
| | | payload.taskName = form.value.taskName; |
| | | payload.deviceModel = form.value.deviceModel || "-"; |
| | | payload.isEnabled = Number(form.value.isEnabled ?? 1); |
| | | |
| | | await addOrEditTimingTask(form.value) |
| | | cancel() |
| | | proxy.$modal.msgSuccess('提交成功') |
| | | await addOrEditTimingTask(payload); |
| | | cancel(); |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | } catch (error) { |
| | | proxy.$modal.msgError('提交失败,请重试') |
| | | proxy.$modal.msgError("提交失败,请重试"); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | defineExpose({ openDialog }) |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ openDialog }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | | <style scoped></style> |
| | |
| | | <el-form :model="form" label-width="120px" :rules="formRules" ref="formRef"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="所属区域" prop="areaId"> |
| | | <el-tree-select |
| | | v-model="form.areaId" |
| | | :data="areaOptions" |
| | | :props="areaTreeProps" |
| | | node-key="id" |
| | | value-key="id" |
| | | check-strictly |
| | | clearable |
| | | filterable |
| | | placeholder="请选择所属区域" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称" prop="deviceName"> |
| | | <el-input v-model="form.deviceName" placeholder="请输入设备名称" /> |
| | | </el-form-item> |
| | |
| | | <el-input v-model="form.deviceModel" placeholder="请输入规格型号" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <!-- <el-col :span="12"> |
| | | <el-form-item label="设备品牌" prop="deviceBrand"> |
| | | <el-input v-model="form.deviceBrand" placeholder="请输入设备品牌" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-col> --> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备类型" prop="type"> |
| | | <el-select |
| | |
| | | <el-form-item label="数量" prop="number"> |
| | | <el-input-number :min="1" style="width: 100%" |
| | | v-model="form.number" |
| | | disabled |
| | | placeholder="请输入数量" |
| | | @change="mathNum" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="含税单价" prop="taxIncludingPriceUnit"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" |
| | | v-model="form.taxIncludingPriceUnit" |
| | | placeholder="请输入含税单价" |
| | | maxlength="10" |
| | | @change="mathNum" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="含税总价" prop="taxIncludingPriceTotal"> |
| | | <el-input |
| | | v-model="form.taxIncludingPriceTotal" |
| | | placeholder="自动生成" |
| | | type="number" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="税率(%)" prop="taxRate"> |
| | | <el-select |
| | | v-model="form.taxRate" |
| | | placeholder="请选择" |
| | | clearable |
| | | @change="mathNum" |
| | | > |
| | | <el-option |
| | | v-for="dict in tax_rate" |
| | | :key="dict.value" |
| | | :label="dict.label" |
| | | :value="Number(dict.value)" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="不含税总价" prop="unTaxIncludingPriceTotal"> |
| | | <el-input |
| | | v-model="form.unTaxIncludingPriceTotal" |
| | | placeholder="自动生成" |
| | | type="number" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="含税单价" prop="taxIncludingPriceUnit">--> |
| | | <!-- <el-input-number :step="0.01" :min="0" style="width: 100%"--> |
| | | <!-- v-model="form.taxIncludingPriceUnit"--> |
| | | <!-- placeholder="请输入含税单价"--> |
| | | <!-- maxlength="10"--> |
| | | <!-- @change="mathNum"--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="含税总价" prop="taxIncludingPriceTotal">--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="form.taxIncludingPriceTotal"--> |
| | | <!-- placeholder="自动生成"--> |
| | | <!-- type="number"--> |
| | | <!-- disabled--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="税率(%)" prop="taxRate">--> |
| | | <!-- <!– <el-input--> |
| | | <!-- v-model="form.taxRate"--> |
| | | <!-- placeholder="请输入税率"--> |
| | | <!-- type="number"--> |
| | | <!-- >--> |
| | | <!-- <template #append> % </template>--> |
| | | <!-- </el-input> –>--> |
| | | <!-- <el-select--> |
| | | <!-- v-model="form.taxRate"--> |
| | | <!-- placeholder="请选择"--> |
| | | <!-- clearable--> |
| | | <!-- @change="mathNum"--> |
| | | <!-- >--> |
| | | <!-- <el-option label="1" :value="1" />--> |
| | | <!-- <el-option label="6" :value="6" />--> |
| | | <!-- <el-option label="13" :value="13" />--> |
| | | <!-- </el-select>--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- <el-col :span="12">--> |
| | | <!-- <el-form-item label="不含税总价" prop="unTaxIncludingPriceTotal">--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="form.unTaxIncludingPriceTotal"--> |
| | | <!-- placeholder="自动生成"--> |
| | | <!-- type="number"--> |
| | | <!-- disabled--> |
| | | <!-- />--> |
| | | <!-- </el-form-item>--> |
| | | <!-- </el-col>--> |
| | | <!-- <el-col :span="12"> |
| | | <el-form-item label="录入人" prop="createUser"> |
| | | <el-input v-model="form.createUser" placeholder="请输入录入人" /> |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="设备图片" prop="storageBlobDTOs"> |
| | | <AttachmentUploadImage |
| | | v-model:fileList="fileList" |
| | | :limit="20" |
| | | :fileSize="5" |
| | | :buttonText="'上传图片'" |
| | | /> |
| | | <el-col :span="12"> |
| | | <el-form-item label="物联设备" prop="isIotDevice"> |
| | | <el-switch v-model="form.isIotDevice" :active-value="1" :inactive-value="0" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.isIotDevice === 1"> |
| | | <el-form-item label="外部编码" prop="externalCode"> |
| | | <el-input v-model="form.externalCode" placeholder="请输入外部编码" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | import useFormData from "@/hooks/useFormData"; |
| | | // import useUserStore from "@/store/modules/user"; |
| | | import { getLedgerById } from "@/api/equipmentManagement/ledger"; |
| | | import { getDeviceAreaTree } from "@/api/equipmentManagement/deviceArea"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | calculateTaxIncludeTotalPrice, |
| | | calculateTaxExclusiveTotalPrice, |
| | | } from "@/utils/summarizeTable"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { ref, getCurrentInstance, computed } from "vue"; |
| | | import AttachmentUploadImage from '@/components/AttachmentUpload/image/index.vue'; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const { tax_rate } = proxy.useDict("tax_rate"); |
| | | import { ref, onMounted } from "vue"; |
| | | |
| | | defineOptions({ |
| | | name: "设备台账表单", |
| | | }); |
| | | const formRef = ref(null); |
| | | const operationType = ref(''); |
| | | const areaOptions = ref([]); |
| | | const areaTreeProps = { |
| | | label: "areaName", |
| | | children: "children", |
| | | }; |
| | | // 设备类型固定选项 |
| | | const deviceTypeOptions = ref([ |
| | | '生产设备', |
| | |
| | | '其他设备' |
| | | ]); |
| | | const formRules = { |
| | | areaId: [{ required: true, trigger: "change", message: "请选择所属区域" }], |
| | | deviceName: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | deviceModel: [{ required: true, trigger: "blur", message: "请输入" }], |
| | | type: [{ required: true, trigger: "change", message: "请选择或输入设备类型" }], |
| | |
| | | trigger: "blur" |
| | | } |
| | | ], |
| | | externalCode: [ |
| | | { |
| | | validator: (rule, value, callback) => { |
| | | if (form.isIotDevice === 1 && !value) { |
| | | callback(new Error('物联设备为是时,请输入外部编码')); |
| | | } else { |
| | | callback(); |
| | | } |
| | | }, |
| | | trigger: "blur" |
| | | } |
| | | ], |
| | | } |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | areaId: undefined, // 区域ID |
| | | deviceName: undefined, // 设备名称 |
| | | deviceModel: undefined, // 规格型号 |
| | | deviceBrand: undefined, // 设备品牌 |
| | | // deviceBrand: undefined, // 设备品牌 |
| | | type: undefined, // 设备类型 |
| | | supplierName: undefined, // 供应商 |
| | | storageLocation: undefined, // 存放位置 |
| | |
| | | unTaxIncludingPriceTotal: undefined, // 不含税总价 |
| | | // createUser: useUserStore().nickName, // 录入人 |
| | | createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // 录入日期 |
| | | planRuntimeTime: dayjs().format("YYYY-MM-DD"), // 录入日期 |
| | | storageBlobDTOs: undefined, // 设备图片提交 |
| | | storageBlobVOs: undefined, // 设备图片展示 |
| | | }); |
| | | |
| | | const fileList = computed({ |
| | | get() { |
| | | return form.storageBlobVOs || []; |
| | | }, |
| | | set(val) { |
| | | form.storageBlobDTOs = val; |
| | | form.storageBlobVOs = val; |
| | | } |
| | | planRuntimeTime: dayjs().format("YYYY-MM-DD"), // 预计运行时间 |
| | | isIotDevice: 0, // 是否为物联设备 0-否 1-是 |
| | | externalCode: undefined, // 外部编码 |
| | | }); |
| | | |
| | | const loadForm = async (id) => { |
| | |
| | | } |
| | | const { code, data } = await getLedgerById(id); |
| | | if (code == 200) { |
| | | form.areaId = data.areaId; |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.deviceBrand = data.deviceBrand; |
| | | // form.deviceBrand = data.deviceBrand; |
| | | form.type = data.type; |
| | | form.supplierName = data.supplierName; |
| | | form.storageLocation = data.storageLocation; |
| | |
| | | } else { |
| | | form.planRuntimeTime = undefined; |
| | | } |
| | | form.storageBlobVOs = data.storageBlobVOs; |
| | | form.storageBlobDTOs = data.storageBlobVOs; |
| | | // 物联设备和外部编码 |
| | | form.isIotDevice = data.isIotDevice ?? 0; |
| | | form.externalCode = data.externalCode; |
| | | } |
| | | }; |
| | | |
| | | const setAreaId = (areaId) => { |
| | | form.areaId = areaId; |
| | | }; |
| | | |
| | | const loadAreaOptions = async () => { |
| | | const res = await getDeviceAreaTree(); |
| | | areaOptions.value = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : []; |
| | | }; |
| | | |
| | | const handleDeviceTypeChange = (value) => { |
| | |
| | | clearValidate(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | loadAreaOptions(); |
| | | }); |
| | | |
| | | defineExpose({ |
| | | form, |
| | | loadForm, |
| | | setAreaId, |
| | | resetForm, |
| | | clearValidate, |
| | | resetFormAndValidate, |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="安装位置:" prop="instationLocation"> |
| | | <el-input |
| | | v-model="form.instationLocation" |
| | | placeholder="请输入" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检定单位:" prop="unit"> |
| | | <el-input |
| | | v-model="form.unit" |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="证书编号:" prop="model"> |
| | | <el-input |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="最新鉴定日期:" prop="mostDate"> |
| | | <el-date-picker |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="有效日期(天):" prop="valid"> |
| | | <el-input |
| | |
| | | > |
| | | <template #append>日</template> |
| | | </el-input> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="检定周期:" prop="cycle"> |
| | | <el-input |
| | | v-model="form.cycle" |
| | | placeholder="请输入检定周期" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | form: { |
| | | code: "", |
| | | name: "", |
| | | instationLocation: "", |
| | | mostDate:"", |
| | | model: "", |
| | | cycle:"", |
| | | validDate: "", |
| | | nextDate: "", |
| | | userId: "", |
| | |
| | | nextDate: [{required: true, message: "请选择", trigger: "change"}], |
| | | userId: [{required: true, message: "请选择", trigger: "change"}], |
| | | recordDate: [{required: true, message: "请选择", trigger: "change"}], |
| | | instationLocation: [{required: true, message: "请输入", trigger: "blur"}], |
| | | mostDate: [{required: true, message: "请选择", trigger: "change"}], |
| | | cycle: [{required: true, message: "请选择", trigger: "blur"}], |
| | | valid: [ |
| | | {required: true, message: "请输入", trigger: "blur"}, |
| | | { |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog v-model="dialogFormVisible" title="上传附件" width="50%" @close="closeDia"> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | title="上传附件" |
| | | width="50%" |
| | | @close="closeDia" |
| | | > |
| | | <div style="margin-bottom: 10px;text-align: right"> |
| | | <el-upload v-model:file-list="fileList" class="upload-demo" :action="uploadUrl" |
| | | :on-success="handleUploadSuccess" :on-error="handleUploadError" name="files" :show-file-list="false" |
| | | :headers="headers" style="display: inline;margin-right: 10px"> |
| | | <el-upload |
| | | v-model:file-list="fileList" |
| | | class="upload-demo" |
| | | :action="uploadUrl" |
| | | :on-success="handleUploadSuccess" |
| | | :on-error="handleUploadError" |
| | | name="file" |
| | | :show-file-list="false" |
| | | :headers="headers" |
| | | style="display: inline;margin-right: 10px" |
| | | > |
| | | <el-button type="primary">上传附件</el-button> |
| | | </el-upload> |
| | | <el-button type="danger" plain @click="handleDelete">删除</el-button> |
| | | </div> |
| | | <PIMTable rowKey="id" :column="tableColumn" :tableData="tableData" :page="page" :tableLoading="tableLoading" |
| | | :isSelection="true" @selection-change="handleSelectionChange" @pagination="paginationSearch" height="500"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :tableLoading="tableLoading" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="paginationSearch" |
| | | height="500" |
| | | > |
| | | </PIMTable> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import { |
| | | addStorageAttachment, |
| | | delStorageAttachment, |
| | | getStorageAttachmentList |
| | | } from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | fileAdd, |
| | | fileDel, |
| | | fileListPage |
| | | } from "@/api/financialManagement/revenueManagement.js"; |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits(['close']) |
| | | |
| | |
| | | const headers = ref({ |
| | | Authorization: "Bearer " + getToken(), |
| | | }); |
| | | const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的服务器地址 |
| | | const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/file/upload"); // 上传的图片服务器地址 |
| | | |
| | | // 打开弹框 |
| | | const openDialog = (row, type) => { |
| | |
| | | const paginationSearch = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | // 前端分页暂不处理,直接调用获取全量列表 |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | getStorageAttachmentList({ recordId: currentId.value, recordType: accountType.value }).then(res => { |
| | | tableData.value = res.data; |
| | | page.total = res.data ? res.data.length : 0; |
| | | fileListPage({accountId: currentId.value,accountType:accountType.value, ...page}).then(res => { |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | } |
| | | // 表格选择数据 |
| | |
| | | // 上传成功处理 |
| | | function handleUploadSuccess(res, file) { |
| | | // 如果上传成功 |
| | | if (res.code == 200 && res.data && res.data.length > 0) { |
| | | const newFiles = res.data.map(item => ({ |
| | | ...item, |
| | | name: item.originalFilename || item.name |
| | | })); |
| | | const mergedFiles = [...(tableData.value || []), ...newFiles]; |
| | | const storageAttachmentDTO = { |
| | | recordType: accountType.value, |
| | | recordId: currentId.value, |
| | | application: "file", |
| | | storageBlobDTOs: mergedFiles |
| | | }; |
| | | addStorageAttachment(storageAttachmentDTO).then(r => { |
| | | proxy.$modal.msgSuccess("文件上传成功"); |
| | | getList() |
| | | }) |
| | | if (res.code == 200) { |
| | | const fileRow = {} |
| | | fileRow.name = res.data.originalName |
| | | fileRow.url = res.data.tempPath |
| | | uploadFile(fileRow) |
| | | } else { |
| | | proxy.$modal.msgError("文件上传失败"); |
| | | } |
| | | } |
| | | function uploadFile(file) { |
| | | file.accountId = currentId.value; |
| | | file.accountType = accountType.value; |
| | | fileAdd(file).then(res => { |
| | | proxy.$modal.msgSuccess("文件上传成功"); |
| | | getList() |
| | | }) |
| | | } |
| | | // 上传失败处理 |
| | | function handleUploadError() { |
| | |
| | | } |
| | | // 下载附件 |
| | | const downLoadFile = (row) => { |
| | | proxy.$download.byUrl(row.url, row.originalFilename); |
| | | proxy.$download.name(row.url); |
| | | } |
| | | // 删除 |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.storageAttachmentId); |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("请选择数据"); |
| | | return; |
| | |
| | | cancelButtonText: "取消", |
| | | type: "warning", |
| | | }).then(() => { |
| | | delStorageAttachment(ids).then((res) => { |
| | | fileDel(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("删除成功"); |
| | | getList(); |
| | | }); |
| | |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped></style> |
| | | <style scoped> |
| | | |
| | | </style> |
| | |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="120px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称" prop="taskId"> |
| | | <el-select v-model="form.taskId" @change="setDeviceModel" filterable> |
| | | <el-form-item label="所属区域" prop="areaId"> |
| | | <el-tree-select |
| | | v-model="form.areaId" |
| | | :data="areaOptions" |
| | | :props="areaTreeProps" |
| | | node-key="id" |
| | | value-key="id" |
| | | check-strictly |
| | | clearable |
| | | filterable |
| | | placeholder="请选择所属区域" |
| | | style="width: 100%" |
| | | @change="handleAreaChange" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设备名称" prop="deviceLedgerIds"> |
| | | <el-select |
| | | v-model="form.deviceLedgerIds" |
| | | filterable |
| | | clearable |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | placeholder="请选择设备" |
| | | style="width: 100%" |
| | | @change="setDeviceModels" |
| | | > |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | v-for="item in deviceOptions" |
| | | :key="item.id" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <el-form-item label="规格型号"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请输入规格型号" |
| | | placeholder="自动带出规格型号" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.userId" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | :key="item.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="保养项目" prop="machineryCategory"> |
| | | <el-input |
| | | v-model.trim="form.machineryCategory" |
| | | placeholder="请输入保养项目" |
| | | maxlength="100" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="保养人" prop="maintenancePerson"> |
| | | <el-input |
| | | v-model.trim="form.maintenancePerson" |
| | | placeholder="请输入保养人姓名" |
| | | maxlength="100" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="任务频率" prop="frequencyType"> |
| | | <el-select v-model="form.frequencyType" placeholder="请选择" clearable> |
| | | <el-option label="每日" value="DAILY"/> |
| | | <el-option label="每周" value="WEEKLY"/> |
| | | <el-option label="每月" value="MONTHLY"/> |
| | | <el-option label="季度" value="QUARTERLY"/> |
| | | <el-option label="每年" value="YEARLY" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'DAILY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'DAILY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-time-picker v-model="form.frequencyDetail" placeholder="选择时间" format="HH:mm" |
| | | value-format="HH:mm" /> |
| | | <el-time-picker |
| | | v-model="form.frequencyDetail" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'WEEKLY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'WEEKLY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-select v-model="form.week" placeholder="请选择" clearable style="width: 50%"> |
| | | <el-option label="周一" value="MON"/> |
| | |
| | | <el-option label="周六" value="SAT"/> |
| | | <el-option label="周日" value="SUN"/> |
| | | </el-select> |
| | | <el-time-picker v-model="form.time" placeholder="选择时间" format="HH:mm" |
| | | value-format="HH:mm" style="width: 50%"/> |
| | | <el-time-picker |
| | | v-model="form.time" |
| | | placeholder="选择时间" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | style="width: 50%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'MONTHLY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'MONTHLY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY' && form.frequencyType"> |
| | | <el-col :span="12" v-if="form.frequencyType === 'QUARTERLY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | |
| | | placeholder="选择开始日期" |
| | | format="MM,DD,HH:mm" |
| | | value-format="MM,DD,HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12" v-if="form.frequencyType === 'YEARLY'"> |
| | | <el-form-item label="日期" prop="frequencyDetail"> |
| | | <el-date-picker |
| | | v-model="form.frequencyDetail" |
| | | type="datetime" |
| | | clearable |
| | | placeholder="选择开始日期" |
| | | format="MM,DD,HH:mm" |
| | | value-format="MM,DD,HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="是否启用" prop="isEnabled"> |
| | | <el-switch |
| | | v-model="form.isEnabled" |
| | | :active-value="1" |
| | | :inactive-value="0" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { getCurrentInstance, reactive, ref, toRefs } from "vue"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { reactive, ref, getCurrentInstance, toRefs } from "vue"; |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { deviceMaintenanceTaskAdd, deviceMaintenanceTaskEdit } from "@/api/equipmentManagement/upkeep"; |
| | | import { |
| | | getDeviceAreaTree, |
| | | getDeviceAreaTreeWithDevices, |
| | | } from "@/api/equipmentManagement/deviceArea"; |
| | | import { |
| | | deviceMaintenanceTaskAdd, |
| | | deviceMaintenanceTaskEdit, |
| | | } from "@/api/equipmentManagement/upkeep"; |
| | | import { getCurrentDate } from "@/utils/index.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const emit = defineEmits() |
| | | const { proxy } = getCurrentInstance(); |
| | | const emit = defineEmits(["closeDia"]); |
| | | const dialogVisitable = ref(false); |
| | | const operationType = ref('add'); |
| | | const operationType = ref("add"); |
| | | const areaOptions = ref([]); |
| | | const deviceOptions = ref([]); |
| | | const userList = ref([]); |
| | | const areaTreeProps = { |
| | | label: "areaName", |
| | | children: "children", |
| | | }; |
| | | const userStore = useUserStore(); |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | areaId: undefined, |
| | | taskId: undefined, |
| | | taskIds: [], |
| | | taskIdsStr: undefined, |
| | | deviceLedgerIds: [], |
| | | deviceLedgerIdsStr: undefined, |
| | | taskName: undefined, |
| | | // 录入人:单选一个用户 id |
| | | isEnabled: 1, |
| | | inspector: undefined, |
| | | machineryCategory: "", |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '', |
| | | deviceModel: undefined, // 规格型号 |
| | | registrationDate: '', |
| | | maintenancePerson: '' // 保养人 |
| | | remarks: "", |
| | | frequencyType: "", |
| | | frequencyDetail: "", |
| | | week: "", |
| | | time: "", |
| | | deviceModel: undefined, |
| | | registrationDate: "", |
| | | }, |
| | | rules: { |
| | | taskId: [{ required: true, message: "请选择设备", trigger: "change" },], |
| | | inspector: [{ required: true, message: "请选择录入人", trigger: "blur" },], |
| | | areaId: [{ required: true, message: "请选择所属区域", trigger: "change" }], |
| | | deviceLedgerIds: [{ required: true, message: "请选择设备", trigger: "change" }], |
| | | inspector: [{ required: true, message: "请选择录入人", trigger: "change" }], |
| | | registrationDate: [{ required: true, message: "请选择登记时间", trigger: "change" }], |
| | | machineryCategory: [{ required: true, message: "请输入保养项目", trigger: "blur" }] |
| | | } |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | const userList = ref([]) |
| | | }, |
| | | }); |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | const { form, rules } = toRefs(data); |
| | | |
| | | const loadAreaTree = async () => { |
| | | const { data } = await getDeviceAreaTree(); |
| | | areaOptions.value = Array.isArray(data) ? data : []; |
| | | }; |
| | | |
| | | // 选择设备时,回填设备名称(taskName)和规格型号(deviceModel) |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.taskId = option.id; |
| | | form.value.taskName = option.deviceName; |
| | | form.value.deviceModel = option.deviceModel; |
| | | const normalizeIdList = (value) => { |
| | | if (Array.isArray(value)) { |
| | | return value |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (typeof value === "string") { |
| | | return value |
| | | .split(",") |
| | | .map((item) => Number(item.trim())) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (value !== undefined && value !== null && value !== "") { |
| | | const numericValue = Number(value); |
| | | return Number.isFinite(numericValue) ? [numericValue] : []; |
| | | } |
| | | return []; |
| | | }; |
| | | |
| | | // 打开弹框 |
| | | const getNodeDevices = (node) => { |
| | | const candidates = [ |
| | | node?.deviceList, |
| | | node?.devices, |
| | | node?.deviceLedgerList, |
| | | node?.deviceLedgers, |
| | | node?.ledgerList, |
| | | node?.ledgers, |
| | | ]; |
| | | return candidates.find((item) => Array.isArray(item)) || []; |
| | | }; |
| | | |
| | | const normalizeDevice = (item) => ({ |
| | | ...item, |
| | | id: item.id ?? item.deviceLedgerId, |
| | | deviceName: item.deviceName ?? item.name, |
| | | deviceModel: item.deviceModel ?? item.model, |
| | | }); |
| | | |
| | | const collectDevices = (node) => { |
| | | const currentDevices = getNodeDevices(node).map(normalizeDevice); |
| | | const childDevices = (node?.children || []).flatMap((child) => |
| | | collectDevices(child) |
| | | ); |
| | | const deviceMap = new Map(); |
| | | [...currentDevices, ...childDevices].forEach((item) => { |
| | | if (item?.id !== undefined && item?.id !== null) { |
| | | deviceMap.set(Number(item.id), item); |
| | | } |
| | | }); |
| | | return Array.from(deviceMap.values()); |
| | | }; |
| | | |
| | | const findAreaNode = (nodes, areaId) => { |
| | | for (const node of nodes || []) { |
| | | if (Number(node.id) === Number(areaId)) { |
| | | return node; |
| | | } |
| | | const target = findAreaNode(node.children, areaId); |
| | | if (target) { |
| | | return target; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const loadDevicesByArea = async (areaId) => { |
| | | if (!areaId) { |
| | | deviceOptions.value = []; |
| | | return; |
| | | } |
| | | const { data } = await getDeviceAreaTreeWithDevices(); |
| | | const treeData = Array.isArray(data) ? data : []; |
| | | const currentNode = findAreaNode(treeData, areaId); |
| | | deviceOptions.value = currentNode ? collectDevices(currentNode) : []; |
| | | }; |
| | | |
| | | const syncDeviceFields = (deviceIds) => { |
| | | const selectedIds = normalizeIdList(deviceIds); |
| | | const selectedDevices = selectedIds |
| | | .map((deviceId) => |
| | | deviceOptions.value.find((item) => Number(item.id) === Number(deviceId)) |
| | | ) |
| | | .filter(Boolean); |
| | | |
| | | form.value.deviceLedgerIds = selectedIds; |
| | | form.value.deviceLedgerIdsStr = selectedIds.join(","); |
| | | form.value.taskIds = [...selectedIds]; |
| | | form.value.taskIdsStr = selectedIds.join(","); |
| | | form.value.taskId = selectedIds[0]; |
| | | form.value.taskName = selectedDevices |
| | | .map((item) => item.deviceName) |
| | | .filter(Boolean) |
| | | .join(","); |
| | | form.value.deviceModel = selectedDevices |
| | | .map((item) => item.deviceModel || "-") |
| | | .join(","); |
| | | }; |
| | | |
| | | const setDeviceModels = (deviceIds) => { |
| | | syncDeviceFields(deviceIds); |
| | | }; |
| | | |
| | | const handleAreaChange = async (areaId) => { |
| | | form.value.taskId = undefined; |
| | | form.value.taskIds = []; |
| | | form.value.taskIdsStr = undefined; |
| | | form.value.deviceLedgerIds = []; |
| | | form.value.deviceLedgerIdsStr = undefined; |
| | | form.value.taskName = undefined; |
| | | form.value.deviceModel = undefined; |
| | | await loadDevicesByArea(areaId); |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields(); |
| | | } |
| | | form.value = { |
| | | areaId: undefined, |
| | | taskId: undefined, |
| | | taskIds: [], |
| | | taskIdsStr: undefined, |
| | | deviceLedgerIds: [], |
| | | deviceLedgerIdsStr: undefined, |
| | | taskName: undefined, |
| | | isEnabled: 1, |
| | | inspector: undefined, |
| | | remarks: "", |
| | | frequencyType: "", |
| | | frequencyDetail: "", |
| | | week: "", |
| | | time: "", |
| | | deviceModel: undefined, |
| | | registrationDate: "", |
| | | }; |
| | | }; |
| | | |
| | | const openDialog = async (type, row) => { |
| | | dialogVisitable.value = true |
| | | operationType.value = type |
| | | |
| | | // 重置表单 |
| | | dialogVisitable.value = true; |
| | | operationType.value = type; |
| | | resetForm(); |
| | | |
| | | // 加载用户列表 |
| | | userListNoPageByTenantId().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | |
| | | // 加载设备列表 |
| | | await loadDeviceName(); |
| | | await loadAreaTree(); |
| | | |
| | | if (type === 'edit' && row) { |
| | | form.value = { ...row } |
| | | // 编辑时用接口返回的 registrantId 回显录入人 |
| | | if (row.registrantId) { |
| | | form.value.inspector = row.registrantId |
| | | } |
| | | |
| | | // 如果有设备ID,自动设置设备信息 |
| | | if (form.value.taskId) { |
| | | setDeviceModel(form.value.taskId); |
| | | } |
| | | } else if (type === 'add') { |
| | | // 新增时设置登记日期为当天 |
| | | form.value.registrationDate = getCurrentDate(); |
| | | // 新增时设置录入人为当前登录账户 |
| | | form.value.inspector = userStore.id; |
| | | } |
| | | } |
| | | |
| | | // 关闭对话框 |
| | | const cancel = () => { |
| | | resetForm() |
| | | dialogVisitable.value = false |
| | | emit('closeDia') |
| | | } |
| | | |
| | | // 重置表单函数 |
| | | const resetForm = () => { |
| | | if (proxy.$refs.formRef) { |
| | | proxy.$refs.formRef.resetFields() |
| | | } |
| | | // 重置表单数据确保设备信息正确重置 |
| | | if (type === "edit" && row) { |
| | | form.value = { |
| | | taskId: undefined, |
| | | taskName: undefined, |
| | | inspector: undefined, |
| | | machineryCategory: "", |
| | | remarks: '', |
| | | frequencyType: '', |
| | | frequencyDetail: '', |
| | | week: '', |
| | | time: '', |
| | | deviceModel: undefined, |
| | | registrationDate: '', |
| | | maintenancePerson: '' |
| | | } |
| | | } |
| | | ...form.value, |
| | | ...row, |
| | | isEnabled: Number(row.isEnabled ?? row.status ?? 1), |
| | | inspector: row.registrantId || row.inspector, |
| | | }; |
| | | form.value.deviceLedgerIds = normalizeIdList( |
| | | row.deviceLedgerIds ?? |
| | | row.deviceLedgerIdsStr ?? |
| | | row.taskIds ?? |
| | | row.taskIdsStr ?? |
| | | row.taskId |
| | | ); |
| | | form.value.deviceLedgerIdsStr = form.value.deviceLedgerIds.join(","); |
| | | form.value.taskIds = [...form.value.deviceLedgerIds]; |
| | | form.value.taskIdsStr = form.value.deviceLedgerIds.join(","); |
| | | form.value.taskId = form.value.deviceLedgerIds[0]; |
| | | |
| | | // 提交表单 |
| | | if (form.value.areaId) { |
| | | await loadDevicesByArea(form.value.areaId); |
| | | syncDeviceFields(form.value.deviceLedgerIds); |
| | | } |
| | | } else { |
| | | form.value.registrationDate = getCurrentDate(); |
| | | form.value.inspector = userStore.id; |
| | | deviceOptions.value = []; |
| | | } |
| | | }; |
| | | |
| | | const cancel = () => { |
| | | resetForm(); |
| | | dialogVisitable.value = false; |
| | | emit("closeDia"); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(async valid => { |
| | | if (valid) { |
| | | proxy.$refs.formRef.validate(async (valid) => { |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | try { |
| | | const payload = { ...form.value } |
| | | // 不再向后端传保养人字段,仅使用接口要求的 registrant / registrantId |
| | | // 根据选择的"录入人"设置 registrant / registrantId |
| | | syncDeviceFields(form.value.deviceLedgerIds); |
| | | const payload = { ...form.value }; |
| | | |
| | | if (payload.inspector) { |
| | | const selectedUser = userList.value.find( |
| | | (u) => String(u.userId) === String(payload.inspector) |
| | | ) |
| | | (item) => String(item.userId) === String(payload.inspector) |
| | | ); |
| | | if (selectedUser) { |
| | | payload.registrantId = selectedUser.userId |
| | | payload.registrant = selectedUser.nickName |
| | | payload.registrantId = selectedUser.userId; |
| | | payload.registrant = selectedUser.nickName; |
| | | } |
| | | } |
| | | delete payload.inspector |
| | | delete payload.inspectorIds |
| | | |
| | | if (payload.frequencyType === 'WEEKLY') { |
| | | let frequencyDetail = '' |
| | | frequencyDetail = payload.week + ',' + payload.time |
| | | payload.frequencyDetail = frequencyDetail |
| | | } |
| | | |
| | | // 录入日期:直接使用表单里的 registrationDate 字段 |
| | | // 一些默认状态字段 |
| | | if (payload.status === undefined || payload.status === null || payload.status === '') { |
| | | payload.status = '0' // 默认状态,可按实际枚举调整 |
| | | } |
| | | payload.active = true |
| | | payload.deleted = 0 |
| | | delete payload.inspector; |
| | | delete payload.inspectorIds; |
| | | |
| | | if (operationType.value === 'edit') { |
| | | await deviceMaintenanceTaskEdit(payload) |
| | | if (payload.frequencyType === "WEEKLY") { |
| | | payload.frequencyDetail = `${payload.week},${payload.time}`; |
| | | } |
| | | |
| | | payload.isEnabled = Number(form.value.isEnabled ?? 1); |
| | | |
| | | payload.deviceLedgerIds = [...form.value.deviceLedgerIds]; |
| | | payload.deviceLedgerIdsStr = form.value.deviceLedgerIds.join(","); |
| | | payload.taskIds = [...form.value.deviceLedgerIds]; |
| | | payload.taskIdsStr = form.value.deviceLedgerIds.join(","); |
| | | payload.taskId = form.value.deviceLedgerIds[0]; |
| | | payload.taskName = form.value.taskName; |
| | | payload.deviceModel = form.value.deviceModel || "-"; |
| | | payload.active = true; |
| | | payload.deleted = 0; |
| | | |
| | | if (operationType.value === "edit") { |
| | | await deviceMaintenanceTaskEdit(payload); |
| | | } else { |
| | | await deviceMaintenanceTaskAdd(payload) |
| | | await deviceMaintenanceTaskAdd(payload); |
| | | } |
| | | cancel() |
| | | proxy.$modal.msgSuccess('提交成功') |
| | | |
| | | cancel(); |
| | | proxy.$modal.msgSuccess("提交成功"); |
| | | } catch (error) { |
| | | proxy.$modal.msgError('提交失败,请重试') |
| | | proxy.$modal.msgError("提交失败,请重试"); |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | defineExpose({ openDialog }) |
| | | }); |
| | | }; |
| | | |
| | | defineExpose({ openDialog }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | |
| | | </style> |
| | | <style scoped></style> |