423 lines
12 KiB
Vue
423 lines
12 KiB
Vue
<template>
|
||
<div>
|
||
<div v-if="dialogFormVisible" class="dialog">
|
||
<div class="head_box">
|
||
<span class="title">{{ title }}</span>
|
||
<div>
|
||
<el-button v-if="!infoActive" type="primary" size="small" @click="submit" :loading="btnLoading">保存</el-button>
|
||
<el-button size="small" @click="close">关闭</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dialogWrapper">
|
||
<div class="label">任务包基本信息</div>
|
||
<el-descriptions class="margin-top" :column="3" border>
|
||
<!-- <template #extra>-->
|
||
<!-- <el-button type="primary">Operation</el-button>-->
|
||
<!-- </template>-->
|
||
<el-descriptions-item label="方格名称">
|
||
{{ form?.fgMc }}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="预警等级">
|
||
<dict-tag :options="D_ZDXL_FGXLRW_YJDJ" :value="form?.fgYjdj" :tag="false" />
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="警情数量">
|
||
{{ form?.fgYjjqsl }}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="高发时段">
|
||
{{ form?.fgYjgfsd }}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="高发类型">
|
||
{{ form?.fgJqtjLx }}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="任务日期">
|
||
{{ form?.rwRq }}
|
||
</el-descriptions-item>
|
||
<el-descriptions-item label="小时统计">
|
||
{{ form?.fgJqtjXsLabel }}
|
||
</el-descriptions-item>
|
||
</el-descriptions>
|
||
|
||
<div class="label" style="margin-top: 1rem">任务包下发编辑信息</div>
|
||
<el-form ref="formRef" :model="form" :rules="rules" :inline="true">
|
||
<el-form-item prop="xlghSc" label="巡逻时长:">
|
||
<el-input-number style="width: 80%" min="0" :disabled="disabled" placeholder="请填写巡逻时长"
|
||
v-model="form.xlghSc"></el-input-number>
|
||
<el-tag size="small" type="warning">分钟</el-tag>
|
||
</el-form-item>
|
||
<el-form-item prop="xlghPcRy" label="盘查人员:">
|
||
<el-input placeholder="请填写盘查人员" clearable :disabled="disabled" v-model="form.xlghPcRy"></el-input>
|
||
</el-form-item>
|
||
<el-form-item prop="xlghPcCl" label="盘查车辆:">
|
||
<el-input placeholder="请填写盘查车辆" clearable :disabled="disabled" v-model="form.xlghPcCl"></el-input>
|
||
</el-form-item>
|
||
<el-form-item prop="xlghXllc" label="巡逻里程:">
|
||
<el-input-number style="width: 80%" min="0" :disabled="disabled" placeholder="请填写巡逻里程"
|
||
v-model="form.xlghXllc"></el-input-number>
|
||
<el-tag size="small" type="warning">公里</el-tag>
|
||
</el-form-item>
|
||
<el-form-item label="下发巡组:">
|
||
<el-input placeholder="请填写下发巡组" clearable :disabled="disabled" v-model="form.xfbbName"
|
||
@click="visible = true" readonly></el-input>
|
||
</el-form-item>
|
||
<div v-if="form?.rwZt !== '01'" style="flex: 1; display: flex; justify-content: flex-end">
|
||
<el-button :disabled="isButtonDisabled" @click="checkInCardOpen">追加打卡</el-button>
|
||
</div>
|
||
<el-row style="width: 100%">
|
||
<el-col>
|
||
<MyTable :tableData="form?.bddList" :tableColumn="pageData.tableColumn"
|
||
:tableConfiger="pageData.tableConfiger" @chooseData="handleChooseDataChange" :selectable="selectable">
|
||
<template #xlghDkcs="{ row, $index }">
|
||
<div class="validation-container">
|
||
<el-input-number style="width: 30%" :placeholder="`输入打卡点${$index + 1}需打卡次数`" clearable min="0"
|
||
:disabled="!selectable(row)" v-model="row.xlghDkcs" :class="{ 'is-error': hasError($index) }"
|
||
@blur="validateField($index)" />
|
||
|
||
<!-- 展示错误信息 -->
|
||
<span v-if="hasError($index)" class="error-message">
|
||
{{ getError($index) }}
|
||
</span>
|
||
</div>
|
||
</template>
|
||
</MyTable>
|
||
<div style="display: none">
|
||
<template v-for="(item, index) in form?.bddList" :key="index">
|
||
<el-form-item :prop="`bddList[${index}].xlghDkcs`" :label="item?.bddMc" :rules="checkPointRules">
|
||
<el-input-number style="width: 100%" :placeholder="`输入打卡点${index + 1}需打卡次数`" clearable
|
||
v-model="item.xlghDkcs" />
|
||
</el-form-item>
|
||
</template>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
</el-form>
|
||
</div>
|
||
</div>
|
||
|
||
<distribute-patrol-team-dialog v-model="visible" @selection-change="handleChange" />
|
||
<add-check-in-card ref="addCheckInCardRef" :disabledIds="disabledIds" :bddList="form?.bddList"
|
||
v-model="checkInCardVisible" @change="handleSelectChange" />
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, getCurrentInstance, computed, watch } from "vue";
|
||
import { updateData } from "@/api/service/dailyTaskPackage";
|
||
import DictTag from "@/components/DictTag/index.vue";
|
||
import MyTable from "@/components/aboutTable/MyTable.vue";
|
||
import DistributePatrolTeamDialog from "@/views/backOfficeSystem/service/taskPage/dailyTaskPackage/components/DistributePatrolTeamDialog.vue";
|
||
import AddCheckInCard from "@/views/backOfficeSystem/service/taskPage/dailyTaskPackage/components/addCheckInCard.vue";
|
||
const { proxy } = getCurrentInstance();
|
||
const { D_ZDXL_FGXLRW_YJDJ } = proxy.$dict("D_ZDXL_FGXLRW_YJDJ");
|
||
const btnLoading = ref(false); //按钮截流
|
||
const title = ref("修改");
|
||
const formRef = ref(null);
|
||
const addCheckInCardRef = ref(null);
|
||
const infoActive = ref(true);
|
||
const visible = ref(false);
|
||
const checkInCardVisible = ref(false);
|
||
|
||
const pageData = reactive({
|
||
tableConfiger: {
|
||
rowKey: "bddId",
|
||
rowHieght: 61,
|
||
haveControls: false,
|
||
showSelectType: "checkBox",
|
||
defaultSelectKeys: [],
|
||
loading: false
|
||
},
|
||
total: 0,
|
||
selectCheckList: [],
|
||
tableColumn: [
|
||
{
|
||
label: "必到点",
|
||
prop: "bddMc"
|
||
},
|
||
{
|
||
label: "打卡次数",
|
||
prop: "xlghDkcs",
|
||
showSolt: true
|
||
}
|
||
]
|
||
});
|
||
|
||
//级联选择器配置
|
||
const props = defineProps({
|
||
modelValue: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
});
|
||
|
||
const emits = defineEmits(["update:modelValue", "ok"]);
|
||
|
||
const dialogFormVisible = computed({
|
||
get() {
|
||
return props.modelValue;
|
||
},
|
||
set(val) {
|
||
emits("update:modelValue", val);
|
||
}
|
||
});
|
||
|
||
//表单数据
|
||
const form = ref({
|
||
bddList: [{ xlghDkcs: 1 }, { xlghDkcs: "" }]
|
||
});
|
||
|
||
const isButtonDisabled = computed(() => {
|
||
// const target = new Date('2025-09-18')
|
||
const target = new Date(form.value?.rwRq);
|
||
const now = new Date();
|
||
|
||
// 只比较日期,忽略时间
|
||
return target.setHours(0, 0, 0, 0) < now.setHours(0, 0, 0, 0);
|
||
});
|
||
|
||
const disabled = computed(() => {
|
||
// const targetDate = new Date(form.value?.rwRq);
|
||
// const today = new Date();
|
||
return form.value?.rwZt === "03" || isButtonDisabled.value;
|
||
});
|
||
|
||
// 打卡点验证规则
|
||
const checkPointRules = [
|
||
{ required: true, message: "请输入打卡次数", trigger: "change" },
|
||
{
|
||
validator: (rule, value, callback) => {
|
||
if (value < 1) {
|
||
callback(new Error("打卡次数必须大于0"));
|
||
} else {
|
||
callback();
|
||
}
|
||
},
|
||
trigger: "change"
|
||
}
|
||
];
|
||
|
||
//表单验证
|
||
const rules = reactive({
|
||
xlghXllc: [
|
||
{
|
||
required: true,
|
||
message: "请填写巡逻里程",
|
||
trigger: "change"
|
||
}
|
||
],
|
||
xlghSc: [
|
||
{
|
||
required: true,
|
||
message: "请填写巡逻时长",
|
||
trigger: "change"
|
||
}
|
||
],
|
||
xlghPcRy: [
|
||
{
|
||
required: true,
|
||
message: "请填写盘查人员",
|
||
trigger: "change"
|
||
}
|
||
],
|
||
xlghPcCl: [
|
||
{
|
||
required: true,
|
||
message: "请填写盘查车辆",
|
||
trigger: "change"
|
||
}
|
||
]
|
||
});
|
||
|
||
//新增
|
||
function open(row = {}, type) {
|
||
infoActive.value = type === "view";
|
||
form.value = { ...row, xfbbName: row?.xfxz };
|
||
form.value?.bddList?.forEach((item, index) => {
|
||
item.index = index; // 直接添加index属性
|
||
});
|
||
|
||
pageData.tableConfiger.defaultSelectKeys = form.value?.bddList?.map((i) => {
|
||
if (i?.selected) return i?.bddId;
|
||
});
|
||
|
||
title.value = type === "view" ? "查看详情" : "编辑信息";
|
||
dialogFormVisible.value = true;
|
||
}
|
||
|
||
//关闭弹窗
|
||
function close() {
|
||
formRef.value.resetFields();
|
||
dialogFormVisible.value = false;
|
||
}
|
||
|
||
const handleChange = (val) => {
|
||
form.value.xfbbId = val?.id;
|
||
form.value.xfbbQwJlId = val?.xfbbQwJlId?.[0];
|
||
form.value.xfbbName = val?.xfbbName;
|
||
};
|
||
|
||
const selectList = ref([]);
|
||
const handleChooseDataChange = (event) => {
|
||
selectList.value = [...event];
|
||
};
|
||
|
||
// 保存原始bddList的ID用于对比
|
||
const disabledIds = ref(new Set());
|
||
|
||
const updateDisabledIds = () => {
|
||
disabledIds.value = new Set(form.value?.bddList?.map((i) => i.bddId));
|
||
};
|
||
|
||
const selectable = (row) => {
|
||
return !disabledIds.value.has(row.bddId);
|
||
};
|
||
|
||
const handleSelectChange = (selection) => {
|
||
pageData.selectCheckList = selection;
|
||
|
||
// 添加新项目
|
||
const newItems = selection.filter(
|
||
(item) => !disabledIds.value.has(item.bddId)
|
||
);
|
||
form.value.bddList = [...form.value.bddList, ...newItems];
|
||
|
||
// 更新禁用ID集合
|
||
updateDisabledIds();
|
||
emits("ok", false);
|
||
};
|
||
|
||
// 监听form.bddList的变化,确保禁用集合同步更新
|
||
watch(
|
||
() => form.value.bddList,
|
||
() => {
|
||
updateDisabledIds();
|
||
},
|
||
{ deep: true }
|
||
);
|
||
|
||
const checkInCardOpen = () => {
|
||
addCheckInCardRef.value?.open(form.value);
|
||
};
|
||
|
||
const fieldErrors = ref({});
|
||
|
||
// 检查指定索引是否有错误
|
||
const hasError = (index) => {
|
||
const propPath = `bddList[${index}].xlghDkcs`;
|
||
return !!fieldErrors.value[propPath];
|
||
};
|
||
|
||
// 获取指定索引的错误信息
|
||
const getError = (index) => {
|
||
const propPath = `bddList[${index}].xlghDkcs`;
|
||
return fieldErrors.value[propPath] || "";
|
||
};
|
||
|
||
// 验证单个字段
|
||
const validateField = async (propPath) => {
|
||
return new Promise((resolve) => {
|
||
formRef.value.validateField(propPath, (errorMessage) => {
|
||
fieldErrors.value[propPath] = errorMessage;
|
||
resolve(!errorMessage);
|
||
});
|
||
});
|
||
};
|
||
|
||
const validateAllCheckpoints = async () => {
|
||
if (!form.value.bddList) return true;
|
||
const validations =
|
||
form.value?.bddList?.map((_, index) =>
|
||
validateField(`bddList[${index}].xlghDkcs`)
|
||
) || [];
|
||
|
||
const results = await Promise.all(validations);
|
||
return results.every((result) => result);
|
||
};
|
||
|
||
//提交
|
||
const submit = async () => {
|
||
try {
|
||
await validateAllCheckpoints();
|
||
await formRef.value.validate();
|
||
|
||
await updateData({ ...form.value, bddList: selectList.value || [] });
|
||
proxy.$message({
|
||
type: "success",
|
||
message: "修改成功"
|
||
});
|
||
dialogFormVisible.value = false;
|
||
emits("ok");
|
||
} catch (error) {
|
||
console.log(error);
|
||
}
|
||
};
|
||
|
||
defineExpose({ open });
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
@import "~@/assets/css/layout.scss";
|
||
@import "~@/assets/css/element-plus.scss";
|
||
|
||
.dialog {
|
||
::v-deep {
|
||
.el-table__header-wrapper .el-checkbox {
|
||
display: none;
|
||
}
|
||
|
||
.el-checkbox__input.is-disabled .el-checkbox__inner,
|
||
.el-checkbox__input.is-checked .el-checkbox__inner {
|
||
background-color: var(--el-checkbox-checked-bg-color);
|
||
border-color: var(--el-checkbox-checked-input-border-color);
|
||
}
|
||
|
||
.el-checkbox__input.is-disabled .el-checkbox__inner,
|
||
.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after {
|
||
border: 1px solid var(--el-checkbox-checked-icon-color);
|
||
border-left: 0;
|
||
border-top: 0;
|
||
}
|
||
}
|
||
|
||
.dialogWrapper {
|
||
margin: 20px 20px 0 20px;
|
||
|
||
.el-form--inline {
|
||
padding: 0 0 0rem 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.label {
|
||
margin-bottom: 1rem;
|
||
}
|
||
|
||
.validation-container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 4px;
|
||
min-height: 60px;
|
||
/* 预留错误信息空间 */
|
||
}
|
||
|
||
.error-message {
|
||
color: #f56c6c;
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
padding: 2px 0;
|
||
display: block;
|
||
}
|
||
|
||
.is-error .el-input-number__inner {
|
||
border-color: #f56c6c;
|
||
}
|
||
|
||
/* 确保表格行高度适应错误信息 */
|
||
.el-table .cell {
|
||
min-height: 40px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
}
|
||
</style>
|