|
|
@@ -0,0 +1,438 @@
|
|
|
+<template>
|
|
|
+ <el-dialog title="结单" v-model="visible" width="800px" append-to-body @close="handleClose">
|
|
|
+ <el-alert type="info" :closable="false" style="border-color: #14b8a6; background-color: #f0fdfa; color: #0d9488; height: 35px;">
|
|
|
+ <template #default>
|
|
|
+ <i class="fa fa-file-text-o mr-2" style="color: #0d9488;"> 请输入相关作业信息,请上传附件完成结单。</i>
|
|
|
+ </template>
|
|
|
+ </el-alert>
|
|
|
+ <el-form ref="finishRef" :model="formData" :rules="finishRules" label-width="120px" label-position="top">
|
|
|
+ <!-- 工单信息 -->
|
|
|
+ <h4 class="text-sm font-medium text-gray-800 mb-3"></h4>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="工单编码">
|
|
|
+ <el-input v-model="formData.workOrderProjectNo" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="工单状态" prop="workOrderStatus">
|
|
|
+ <el-select v-model="formData.workOrderStatus" disabled>
|
|
|
+ <el-option
|
|
|
+ v-for="dict in workOrderStatusOptions"
|
|
|
+ :key="dict.value"
|
|
|
+ :label="dict.label"
|
|
|
+ :value="dict.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="风机编号">
|
|
|
+ <el-input v-model="formData.pcsDeviceName" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="维保中心">
|
|
|
+ <el-input v-model="formData.gxtCenter" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="场站">
|
|
|
+ <el-input v-model="formData.pcsStationName" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="品牌">
|
|
|
+ <el-input v-model="formData.brand" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="机型">
|
|
|
+ <el-input v-model="formData.model" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12" v-if="formData.infoEntry == '1'">
|
|
|
+ <el-form-item label="MIS工单编码">
|
|
|
+ <el-input v-model="formData.misNo" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12" v-if="formData.infoEntry == '2'">
|
|
|
+ <el-form-item label="工作票编号">
|
|
|
+ <el-input v-model="formData.workPermitNum" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="接单人">
|
|
|
+ <el-input v-model="formData.acceptUserName" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="接单时间">
|
|
|
+ <el-input v-model="formData.acceptTime" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="开始时间" prop="realStartTime">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="formData.realStartTime"
|
|
|
+ type="datetime"
|
|
|
+ format="YYYY-MM-DD HH:mm"
|
|
|
+ value-format="YYYY-MM-DD HH:mm"
|
|
|
+ placeholder="请选择开始时间"
|
|
|
+ style="width: 100%"
|
|
|
+ :readonly="formData.infoEntry == '1'"
|
|
|
+ :disabled-date="disabledStartDate"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="结束时间" prop="realEndTime">
|
|
|
+ <el-date-picker
|
|
|
+ v-model="formData.realEndTime"
|
|
|
+ type="datetime"
|
|
|
+ format="YYYY-MM-DD HH:mm"
|
|
|
+ value-format="YYYY-MM-DD HH:mm"
|
|
|
+ placeholder="请选择结束时间"
|
|
|
+ style="width: 100%"
|
|
|
+ :readonly="formData.infoEntry == '1'"
|
|
|
+ :disabled-date="disabledEndDate"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="外委人员数(人)" prop="wwryNum">
|
|
|
+ <el-input-number
|
|
|
+ v-model="formData.wwryNum"
|
|
|
+ placeholder="请输入外委人员数"
|
|
|
+ controls-position="right"
|
|
|
+ style="width: 100%"
|
|
|
+ class="input-number-left"
|
|
|
+ :min="0"
|
|
|
+ :step="1"
|
|
|
+ :precision="0"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="外来人员数(人)" prop="wlryNum">
|
|
|
+ <el-input-number
|
|
|
+ v-model="formData.wlryNum"
|
|
|
+ placeholder="请输入外来人员数"
|
|
|
+ controls-position="right"
|
|
|
+ style="width: 100%"
|
|
|
+ class="input-number-left"
|
|
|
+ :min="0"
|
|
|
+ :step="1"
|
|
|
+ :precision="0"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <!-- 维保详情 -->
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="维保内容" prop="content">
|
|
|
+ <el-input v-model="formData.content" type="textarea" :rows="3" maxlength="500" show-word-limit />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="工作负责人">
|
|
|
+ <el-input v-model="formData.teamLeaderName" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="检修人员" prop="workGroupMemberName">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.workGroupMemberName"
|
|
|
+ maxlength="200"
|
|
|
+ show-word-limit
|
|
|
+ :readonly="formData.infoEntry == '1'"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="附件(可选)">
|
|
|
+ <preview :limit="8" v-model="formData.attachmentUrls" :filesize="5"></preview>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="handleCancel">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="handleSubmit" :loading="submitLoading">确认结单</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, defineProps, defineEmits, getCurrentInstance, watch } from 'vue'
|
|
|
+import preview from '@/components/FileUpload/preview.vue'
|
|
|
+
|
|
|
+// 获取当前实例
|
|
|
+const { proxy } = getCurrentInstance()
|
|
|
+
|
|
|
+// 定义属性
|
|
|
+const props = defineProps({
|
|
|
+ modelValue: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ data: {
|
|
|
+ type: Object,
|
|
|
+ default: () => ({})
|
|
|
+ },
|
|
|
+ workOrderStatusOptions: {
|
|
|
+ type: Array,
|
|
|
+ default: () => ([])
|
|
|
+ },
|
|
|
+ listUserData: {
|
|
|
+ type: Function,
|
|
|
+ default: null
|
|
|
+ },
|
|
|
+ onSubmit: {
|
|
|
+ type: Function,
|
|
|
+ default: null
|
|
|
+ }
|
|
|
+})
|
|
|
+// 定义事件
|
|
|
+const emit = defineEmits(['update:modelValue', 'success'])
|
|
|
+
|
|
|
+// 响应式数据
|
|
|
+const visible = ref(false)
|
|
|
+const formData = ref({})
|
|
|
+const finishRef = ref()
|
|
|
+const submitLoading = ref(false)
|
|
|
+
|
|
|
+// 表单验证规则
|
|
|
+const finishRules = ref({
|
|
|
+ realStartTime: [
|
|
|
+ { required: true, message: "开始时间不能为空", trigger: "change" },
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (value && new Date(value) > new Date() && formData.value.infoEntry == '2') {
|
|
|
+ callback(new Error('开始时间不能大于当前时间'));
|
|
|
+ } else if(value && new Date(value) < new Date(formData.value.acceptTime) && formData.value.infoEntry == '2') {
|
|
|
+ callback(new Error('开始时间不能小于接单时间'));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: 'change'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ realEndTime: [
|
|
|
+ { required: true, message: "结束时间不能为空", trigger: "change" },
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (value && new Date(value) > new Date() && formData.value.infoEntry == '2') {
|
|
|
+ callback(new Error('结束时间不能大于当前时间'));
|
|
|
+ } else if(value && new Date(value) < new Date(formData.value.realStartTime) && formData.value.infoEntry == '2') {
|
|
|
+ callback(new Error('结束时间不能小于开始时间'));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: 'change'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ workGroupMemberName: [
|
|
|
+ { required: false, message: "请输入检修人员", trigger: "blur" },
|
|
|
+ {
|
|
|
+ validator: async (rule, value, callback) => {
|
|
|
+ // 如果值为空、关联MIS,直接通过验证
|
|
|
+ if (!value || formData.value.infoEntry == '1') {
|
|
|
+ return callback();
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // 将输入的检修人员姓名按逗号分割
|
|
|
+ const names = value.split(',').map(name => name.trim());
|
|
|
+
|
|
|
+ // 验证每个检修人员是否存在于组织架构中
|
|
|
+ for (const name of names) {
|
|
|
+ if (name.length > 0) {
|
|
|
+ // 使用从属性传入的listUserData方法(如果有的话)
|
|
|
+ if (props.listUserData) {
|
|
|
+ const response = await props.listUserData({nickName: name});
|
|
|
+ if (!response.rows || response.rows.length === 0) {
|
|
|
+ return callback(new Error(`检修人员"${name}"非系统内人员,请重新输入`));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return callback(new Error(`请正确输入检修人员名单`));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ callback();
|
|
|
+ } catch (error) {
|
|
|
+ callback(new Error('验证检修人员时发生错误'));
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ content: [
|
|
|
+ { required: true, message: "请输入维保内容", trigger: "blur" }
|
|
|
+ ]
|
|
|
+})
|
|
|
+// 时间禁用函数
|
|
|
+const disabledStartDate = (time) => {
|
|
|
+ const getYYYYMMDD = (date) => {
|
|
|
+ const y = date.getFullYear();
|
|
|
+ const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
|
+ const d = String(date.getDate()).padStart(2, '0');
|
|
|
+ return `${y}-${m}-${d}`;
|
|
|
+ };
|
|
|
+
|
|
|
+ const today = getYYYYMMDD(new Date());
|
|
|
+
|
|
|
+ let acceptDateStr = null;
|
|
|
+ const acceptStr = formData.value.acceptTime;
|
|
|
+ if (acceptStr) {
|
|
|
+ acceptDateStr = acceptStr.split(' ')[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ const selectedDateStr = getYYYYMMDD(time);
|
|
|
+
|
|
|
+ // 如果没有 acceptTime,只禁用未来日期
|
|
|
+ if (!acceptDateStr) {
|
|
|
+ return selectedDateStr > today;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 要用:早于 acceptDate 或 晚于今天
|
|
|
+ return selectedDateStr < acceptDateStr || selectedDateStr > today;
|
|
|
+};
|
|
|
+
|
|
|
+const disabledEndDate = (time) => {
|
|
|
+ const getYYYYMMDD = (date) => {
|
|
|
+ const y = date.getFullYear();
|
|
|
+ const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
|
+ const d = String(date.getDate()).padStart(2, '0');
|
|
|
+ return `${y}-${m}-${d}`;
|
|
|
+ };
|
|
|
+
|
|
|
+ const today = getYYYYMMDD(new Date());
|
|
|
+
|
|
|
+ let acceptDateStr = null;
|
|
|
+ const acceptStr = formData.value.acceptTime;
|
|
|
+ const startStr = formData.value.realStartTime;
|
|
|
+ if (startStr) {
|
|
|
+ acceptDateStr = startStr.split(' ')[0];
|
|
|
+ } else if(acceptStr) {
|
|
|
+ acceptDateStr = acceptStr.split(' ')[0];
|
|
|
+ }
|
|
|
+
|
|
|
+ const selectedDateStr = getYYYYMMDD(time);
|
|
|
+
|
|
|
+ // 如果没有 acceptTime,只禁用未来日期
|
|
|
+ if (!acceptDateStr) {
|
|
|
+ return selectedDateStr > today;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 要用:早于 acceptDate 或 晚于今天
|
|
|
+ return selectedDateStr < acceptDateStr || selectedDateStr > today;
|
|
|
+};
|
|
|
+
|
|
|
+// 监听modelValue变化
|
|
|
+watch(() => props.modelValue, (val) => {
|
|
|
+ visible.value = val
|
|
|
+ if (val) {
|
|
|
+ // 初始化表单数据
|
|
|
+ formData.value = { ...props.data }
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 监听props.data变化
|
|
|
+watch(() => props.data, (newData) => {
|
|
|
+ if (visible.value) {
|
|
|
+ // 只有在对话框打开时才更新数据
|
|
|
+ formData.value = { ...newData }
|
|
|
+ }
|
|
|
+}, { deep: true })
|
|
|
+
|
|
|
+// 监听visible变化
|
|
|
+watch(visible, (val) => {
|
|
|
+ emit('update:modelValue', val)
|
|
|
+ if (val) {
|
|
|
+ // 打开对话框后重置表单验证错误
|
|
|
+ proxy.$nextTick(() => {
|
|
|
+ if (finishRef.value) {
|
|
|
+ finishRef.value.clearValidate()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 关闭对话框
|
|
|
+const handleClose = () => {
|
|
|
+ visible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+// 取消操作
|
|
|
+const handleCancel = () => {
|
|
|
+ visible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+// 提交操作
|
|
|
+const handleSubmit = async () => {
|
|
|
+ if (!finishRef.value) return
|
|
|
+
|
|
|
+ await finishRef.value.validate(async (valid) => {
|
|
|
+ if (valid) {
|
|
|
+ try {
|
|
|
+ if (!formData.value.realEndTime) {
|
|
|
+ proxy.$modal.msgError("该工单未结束,无法结单!")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ submitLoading.value = true
|
|
|
+
|
|
|
+ // 调用父组件传入的提交函数
|
|
|
+ if (props.onSubmit && typeof props.onSubmit === 'function') {
|
|
|
+ await props.onSubmit(formData.value)
|
|
|
+ } else {
|
|
|
+ throw new Error("未提供提交方法")
|
|
|
+ }
|
|
|
+
|
|
|
+ proxy.$modal.msgSuccess("结单成功")
|
|
|
+ visible.value = false
|
|
|
+ emit('success')
|
|
|
+ } catch (error) {
|
|
|
+ proxy.$modal.msgError("操作失败: " + (error.message || "未知错误"))
|
|
|
+ } finally {
|
|
|
+ submitLoading.value = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+/* 表单中的列间距调整 */
|
|
|
+:deep(.el-col) {
|
|
|
+ padding-left: 5px;
|
|
|
+ padding-right: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 穿透修改组件内部输入框的对齐方式(关键) */
|
|
|
+:deep(.input-number-left .el-input__inner) {
|
|
|
+ text-align: left !important; /* !important 覆盖组件默认的居中 */
|
|
|
+}
|
|
|
+</style>
|