|
@@ -61,6 +61,12 @@
|
|
|
:show-overflow-tooltip="true"
|
|
:show-overflow-tooltip="true"
|
|
|
min-width="180"
|
|
min-width="180"
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <el-table-column
|
|
|
|
|
+ label="工期(天)"
|
|
|
|
|
+ align="center"
|
|
|
|
|
+ prop="durationDays"
|
|
|
|
|
+ width="90"
|
|
|
|
|
+ />
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
label="施工开始时间"
|
|
label="施工开始时间"
|
|
|
align="center"
|
|
align="center"
|
|
@@ -136,6 +142,24 @@
|
|
|
</el-col>
|
|
</el-col>
|
|
|
</el-row>
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
+ <el-row :gutter="20">
|
|
|
|
|
+ <el-col :span="12">
|
|
|
|
|
+ <el-form-item label="工期" prop="durationDays">
|
|
|
|
|
+ <el-input-number
|
|
|
|
|
+ v-model="form.durationDays"
|
|
|
|
|
+ :min="1"
|
|
|
|
|
+ :max="3650"
|
|
|
|
|
+ :step="1"
|
|
|
|
|
+ placeholder="请输入工期,如:3天"
|
|
|
|
|
+ controls-position="right"
|
|
|
|
|
+ style="width: 100%"
|
|
|
|
|
+ @change="handleDurationChange"
|
|
|
|
|
+ />
|
|
|
|
|
+ <span class="form-tip">单位:天,录入工期+开始时间自动算结束时间</span>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+ </el-col>
|
|
|
|
|
+ </el-row>
|
|
|
|
|
+
|
|
|
<el-row :gutter="20">
|
|
<el-row :gutter="20">
|
|
|
<el-col :span="12">
|
|
<el-col :span="12">
|
|
|
<el-form-item label="施工开始时间" prop="workStartTime">
|
|
<el-form-item label="施工开始时间" prop="workStartTime">
|
|
@@ -146,6 +170,7 @@
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
format="YYYY-MM-DD HH:mm"
|
|
format="YYYY-MM-DD HH:mm"
|
|
|
style="width: 100%"
|
|
style="width: 100%"
|
|
|
|
|
+ @change="handleStartTimeChange"
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
@@ -158,6 +183,7 @@
|
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
format="YYYY-MM-DD HH:mm"
|
|
format="YYYY-MM-DD HH:mm"
|
|
|
style="width: 100%"
|
|
style="width: 100%"
|
|
|
|
|
+ @change="handleEndTimeChange"
|
|
|
/>
|
|
/>
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
@@ -266,6 +292,9 @@
|
|
|
<el-descriptions-item label="项目名称">
|
|
<el-descriptions-item label="项目名称">
|
|
|
{{ viewForm.workTitle }}
|
|
{{ viewForm.workTitle }}
|
|
|
</el-descriptions-item>
|
|
</el-descriptions-item>
|
|
|
|
|
+ <el-descriptions-item label="工期(天)">
|
|
|
|
|
+ {{ viewForm.durationDays ?? '-' }}
|
|
|
|
|
+ </el-descriptions-item>
|
|
|
<el-descriptions-item label="施工开始时间">
|
|
<el-descriptions-item label="施工开始时间">
|
|
|
{{ viewForm.workStartTime }}
|
|
{{ viewForm.workStartTime }}
|
|
|
</el-descriptions-item>
|
|
</el-descriptions-item>
|
|
@@ -414,6 +443,7 @@ const data = reactive<any>({
|
|
|
workContent: '',
|
|
workContent: '',
|
|
|
workStartTime: '',
|
|
workStartTime: '',
|
|
|
workEndTime: '',
|
|
workEndTime: '',
|
|
|
|
|
+ durationDays: undefined,
|
|
|
reporterName: '',
|
|
reporterName: '',
|
|
|
contactPhone: '',
|
|
contactPhone: '',
|
|
|
photoList: [],
|
|
photoList: [],
|
|
@@ -432,6 +462,21 @@ const data = reactive<any>({
|
|
|
rules: {
|
|
rules: {
|
|
|
workType: [{ required: true, message: '请选择作业类型', trigger: 'change' }],
|
|
workType: [{ required: true, message: '请选择作业类型', trigger: 'change' }],
|
|
|
workTitle: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
|
|
workTitle: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
|
|
|
|
|
+ durationDays: [
|
|
|
|
|
+ { required: true, message: '请输入工期', trigger: 'blur' },
|
|
|
|
|
+ {
|
|
|
|
|
+ validator: (_rule: any, value: any, callback: any) => {
|
|
|
|
|
+ if (value === undefined || value === null || value === '') {
|
|
|
|
|
+ callback(new Error('请输入工期'));
|
|
|
|
|
+ } else if (Number(value) < 1) {
|
|
|
|
|
+ callback(new Error('工期必须大于等于1天'));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ callback();
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ trigger: 'blur'
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
workStartTime: [{ required: true, message: '请选择施工开始时间', trigger: 'change' }],
|
|
workStartTime: [{ required: true, message: '请选择施工开始时间', trigger: 'change' }],
|
|
|
workEndTime: [
|
|
workEndTime: [
|
|
|
{ required: true, message: '请选择施工结束时间', trigger: 'change' },
|
|
{ required: true, message: '请选择施工结束时间', trigger: 'change' },
|
|
@@ -651,6 +696,7 @@ const reset = () => {
|
|
|
workContent: '',
|
|
workContent: '',
|
|
|
workStartTime: '',
|
|
workStartTime: '',
|
|
|
workEndTime: '',
|
|
workEndTime: '',
|
|
|
|
|
+ durationDays: undefined,
|
|
|
reporterName: '',
|
|
reporterName: '',
|
|
|
contactPhone: '',
|
|
contactPhone: '',
|
|
|
photoList: [],
|
|
photoList: [],
|
|
@@ -669,6 +715,78 @@ const closeDialog = () => {
|
|
|
reset();
|
|
reset();
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+// ============ 工期 ↔ 时间 联动计算 ============
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 根据工期(天)和开始时间,计算结束时间字符串
|
|
|
|
|
+ */
|
|
|
|
|
+const computeEndTimeByDuration = (startTime: string, days: number): string => {
|
|
|
|
|
+ if (!startTime || !days || days <= 0) return '';
|
|
|
|
|
+ const start = new Date(startTime);
|
|
|
|
|
+ if (isNaN(start.getTime())) return '';
|
|
|
|
|
+ const end = new Date(start.getTime() + days * 24 * 60 * 60 * 1000);
|
|
|
|
|
+ // 格式化为 YYYY-MM-DD HH:mm:ss (与 value-format 一致)
|
|
|
|
|
+ const pad = (n: number) => String(n).padStart(2, '0');
|
|
|
|
|
+ return (
|
|
|
|
|
+ end.getFullYear() +
|
|
|
|
|
+ '-' +
|
|
|
|
|
+ pad(end.getMonth() + 1) +
|
|
|
|
|
+ '-' +
|
|
|
|
|
+ pad(end.getDate()) +
|
|
|
|
|
+ ' ' +
|
|
|
|
|
+ pad(end.getHours()) +
|
|
|
|
|
+ ':' +
|
|
|
|
|
+ pad(end.getMinutes()) +
|
|
|
|
|
+ ':' +
|
|
|
|
|
+ pad(end.getSeconds())
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 根据开始时间和结束时间,向上取整计算工期(天)
|
|
|
|
|
+ * 1ms ~ 1天 都视为1天
|
|
|
|
|
+ */
|
|
|
|
|
+const computeDurationByRange = (startTime: string, endTime: string): number => {
|
|
|
|
|
+ if (!startTime || !endTime) return 0;
|
|
|
|
|
+ const start = new Date(startTime);
|
|
|
|
|
+ const end = new Date(endTime);
|
|
|
|
|
+ if (isNaN(start.getTime()) || isNaN(end.getTime())) return 0;
|
|
|
|
|
+ const diff = end.getTime() - start.getTime();
|
|
|
|
|
+ if (diff <= 0) return 0;
|
|
|
|
|
+ const oneDay = 24 * 60 * 60 * 1000;
|
|
|
|
|
+ return Math.ceil(diff / oneDay);
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/** 工期变化 → 若有开始时间,自动算出结束时间 */
|
|
|
|
|
+const handleDurationChange = (val: number | undefined) => {
|
|
|
|
|
+ if (!val || val <= 0) return;
|
|
|
|
|
+ if (form.value.workStartTime) {
|
|
|
|
|
+ form.value.workEndTime = computeEndTimeByDuration(form.value.workStartTime, val);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/** 开始时间变化 → 若结束时间已填,重算工期;否则若工期已填,重算结束时间 */
|
|
|
|
|
+const handleStartTimeChange = (val: string | null) => {
|
|
|
|
|
+ if (!val) return;
|
|
|
|
|
+ if (form.value.workEndTime) {
|
|
|
|
|
+ // 结束时间已有 → 重算工期(用户期望改开始时间后工期随之变化)
|
|
|
|
|
+ const days = computeDurationByRange(val, form.value.workEndTime);
|
|
|
|
|
+ if (days > 0) form.value.durationDays = days;
|
|
|
|
|
+ } else if (form.value.durationDays && form.value.durationDays > 0) {
|
|
|
|
|
+ // 结束时间为空 + 工期有值 → 重算结束时间
|
|
|
|
|
+ form.value.workEndTime = computeEndTimeByDuration(val, form.value.durationDays);
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/** 结束时间变化 → 若开始时间已填,重算工期 */
|
|
|
|
|
+const handleEndTimeChange = (val: string | null) => {
|
|
|
|
|
+ if (!val) return;
|
|
|
|
|
+ if (form.value.workStartTime) {
|
|
|
|
|
+ const days = computeDurationByRange(form.value.workStartTime, val);
|
|
|
|
|
+ if (days > 0) form.value.durationDays = days;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
// ============ 上传相关 ============
|
|
// ============ 上传相关 ============
|
|
|
|
|
|
|
|
const handleUploadError = () => {
|
|
const handleUploadError = () => {
|
|
@@ -912,6 +1030,12 @@ onMounted(() => {
|
|
|
.readonly-text {
|
|
.readonly-text {
|
|
|
color: #303133;
|
|
color: #303133;
|
|
|
}
|
|
}
|
|
|
|
|
+.form-tip {
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ margin-left: 8px;
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+}
|
|
|
.audit-opinion.pass {
|
|
.audit-opinion.pass {
|
|
|
color: #67c23a;
|
|
color: #67c23a;
|
|
|
}
|
|
}
|