change.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <template>
  2. <div class="safety-platform-container">
  3. <header class="safety-platform-container__header">
  4. <div class="breadcrumb-title">
  5. <BreadcrumbBack />
  6. 变更非公共区域责任清单
  7. </div>
  8. </header>
  9. <main class="safety-platform-container__main">
  10. <el-form ref="formRef" label-width="auto" :model="formValue" :rules="rules">
  11. <el-form-item label="楼号">
  12. <el-input v-model="formValue.buildingNo" disabled size="large" style="width: 50%" />
  13. </el-form-item>
  14. <el-form-item label="楼宇/区域">
  15. <el-input v-model="formValue.buildingArea" disabled size="large" style="width: 50%" />
  16. </el-form-item>
  17. <el-form-item label="楼层/房号">
  18. <el-input v-model="formValue.floorRoomNo" disabled size="large" style="width: 50%" />
  19. </el-form-item>
  20. <el-form-item label="名称/功能">
  21. <el-input v-model="formValue.nameFunction" disabled size="large" style="width: 50%" />
  22. </el-form-item>
  23. <el-form-item label="安全责任所/中心">
  24. <el-cascader
  25. v-model="formValue.safetyResponsibleCenterId"
  26. disabled
  27. style="width: 50%"
  28. size="large"
  29. :options="firstLevelDepts"
  30. :props="cascaderProp"
  31. :show-all-levels="false"
  32. />
  33. </el-form-item>
  34. <el-form-item label="安全责任所/中心负责人">
  35. <el-select v-model="formValue.safetyCenterManager" disabled size="large" style="width: 50%">
  36. <el-option
  37. v-for="item in oldCenterManagerOptions"
  38. :key="item.value"
  39. :label="item.label"
  40. :value="item.value"
  41. />
  42. </el-select>
  43. </el-form-item>
  44. <h5 style="margin: 30px 0; font-weight: bold; color: #409eff">信息变更</h5>
  45. <el-form-item label="变更后的安全责任部门" prop="safetyResponsibleDepartmentTodo">
  46. <el-cascader
  47. v-model="formValue.safetyResponsibleDepartmentIdTodo"
  48. style="width: 50%"
  49. size="large"
  50. :ref="(el) => (cascaderRef['safetyResponsibleDepartmentTodo'] = el)"
  51. :options="firstLevelDepts"
  52. :props="cascaderProp"
  53. :show-all-levels="false"
  54. placeholder="请选择新的责任部门"
  55. filterable
  56. clearable
  57. @change="(val) => handleChangeDept(val, 'safetyResponsibleDepartmentTodo')"
  58. />
  59. </el-form-item>
  60. <el-form-item label="变更后的安全具体责任人" prop="safetySpecificPersonTodo">
  61. <el-select
  62. :disabled="!todoUserOptions.length"
  63. v-model="formValue.safetySpecificPersonTodo"
  64. placeholder="请选择新的具体责任人"
  65. size="large"
  66. style="width: 50%"
  67. filterable
  68. clearable
  69. @change="(val) => syncUserName(todoUserOptions, val, 'safetySpecificPersonNameTodo')"
  70. >
  71. <el-option v-for="item in todoUserOptions" :key="item.value" :label="item.label" :value="item.value" />
  72. </el-select>
  73. </el-form-item>
  74. <el-form-item label="变更原因" prop="changeReason">
  75. <el-input
  76. v-model="formValue.changeReason"
  77. type="textarea"
  78. :rows="5"
  79. placeholder="请详细描述变更原因"
  80. style="width: 70%"
  81. maxlength="200"
  82. show-word-limit
  83. />
  84. </el-form-item>
  85. </el-form>
  86. </main>
  87. <footer class="safety-platform-container__footer">
  88. <el-button @click="$router.push({ name: 'listResponsibilities:nonPublic' })">返回</el-button>
  89. <el-button type="primary" :loading="submiting" @click="handleSubmit">提交变更</el-button>
  90. </footer>
  91. </div>
  92. </template>
  93. <script lang="ts" setup>
  94. import { ref, reactive, onMounted, nextTick } from 'vue';
  95. import { useRouter, useRoute } from 'vue-router';
  96. import { ElMessage } from 'element-plus';
  97. import { getAllDepartments } from '@/api/auth/dept';
  98. import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
  99. import {
  100. areaCheckListQueryDetail,
  101. areaCheckListChange,
  102. queryAvailableUserList,
  103. } from '@/api/production-safety/responsibility-implementation';
  104. const router = useRouter();
  105. const route = useRoute();
  106. const formRef = ref<any>(null);
  107. const submiting = ref(false);
  108. // 数据源
  109. const firstLevelDepts = ref<any[]>([]);
  110. const oldCenterManagerOptions = ref<any[]>([]); // 旧负责人数据源
  111. const todoUserOptions = ref<any[]>([]); // 新负责人下拉数据源
  112. const cascaderRef = ref({});
  113. const cascaderProp = { expandTrigger: 'click', checkStrictly: true, value: 'id', label: 'deptName' };
  114. const formValue = reactive({
  115. id: undefined,
  116. buildingNo: '',
  117. buildingArea: '',
  118. floorRoomNo: '',
  119. nameFunction: '',
  120. // 旧数据
  121. safetyResponsibleCenter: '',
  122. safetyResponsibleCenterId: [],
  123. safetyCenterManager: null as number | null,
  124. // 变更数据
  125. safetyResponsibleDepartmentTodo: '',
  126. safetyResponsibleDepartmentIdTodo: [],
  127. safetySpecificPersonTodo: null as number | null,
  128. safetySpecificPersonNameTodo: '',
  129. changeReason: '',
  130. });
  131. const rules = reactive({
  132. safetyResponsibleDepartmentTodo: [{ required: true, message: '请选择变更后的责任部门', trigger: 'change' }],
  133. safetySpecificPersonTodo: [{ required: true, message: '请选择变更后的具体责任人', trigger: 'change' }],
  134. changeReason: [{ required: true, message: '请输入变更原因', trigger: 'blur' }],
  135. });
  136. // 获取部门树
  137. const getDeptData = async () => {
  138. const res = await getAllDepartments();
  139. firstLevelDepts.value = formatDeptTree(res);
  140. };
  141. // 获取用户列表封装
  142. const getUserData = (optionList, deptName) => {
  143. return queryAvailableUserList({
  144. pageNumber: 1,
  145. pageSize: 200,
  146. queryParam: { deptName },
  147. }).then((res: any) => {
  148. optionList.value = (res.records || []).map((u: any) => ({
  149. value: u.id,
  150. label: u.realname,
  151. }));
  152. });
  153. };
  154. // 级联选择处理
  155. const handleChangeDept = (val, prop) => {
  156. const cascader = cascaderRef.value?.[prop];
  157. const deptInfo = cascader?.getCheckedNodes();
  158. if (deptInfo?.length) {
  159. formValue[prop] = deptInfo[0].label;
  160. // 级联变更后清空已选人员并重新加载
  161. formValue.safetySpecificPersonTodo = null;
  162. getUserData(todoUserOptions, deptInfo[0].label);
  163. }
  164. };
  165. const syncUserName = (optionList, id: number, nameField: string) => {
  166. const user = optionList.find((u) => u.value === id);
  167. if (user) formValue[nameField] = user.label;
  168. };
  169. // 详情回显
  170. const handlAreaCheckListQueryDetail = async () => {
  171. const id = route.query.id;
  172. if (!id) return;
  173. try {
  174. const res: any = await areaCheckListQueryDetail({ id });
  175. if (res) {
  176. Object.assign(formValue, res);
  177. // 1. 解析旧部门级联路径
  178. if (typeof res.safetyResponsibleCenterId === 'string') {
  179. formValue.safetyResponsibleCenterId = JSON.parse(res.safetyResponsibleCenterId);
  180. }
  181. // 2. 加载旧负责人列表以显示名称
  182. if (formValue.safetyResponsibleCenter) {
  183. getUserData(oldCenterManagerOptions, formValue.safetyResponsibleCenter);
  184. }
  185. // 3. 纠正 ID 类型
  186. if (formValue.safetyCenterManager) formValue.safetyCenterManager = Number(formValue.safetyCenterManager);
  187. }
  188. } catch (err) {
  189. ElMessage.error('加载详情失败');
  190. }
  191. };
  192. onMounted(async () => {
  193. await getDeptData();
  194. await handlAreaCheckListQueryDetail();
  195. });
  196. const handleSubmit = () => {
  197. formRef.value?.validate((valid: boolean) => {
  198. if (valid) {
  199. submiting.value = true;
  200. const submitData = {
  201. id: Number(route.query.id),
  202. safetyResponsibleDepartmentTodo: formValue.safetyResponsibleDepartmentTodo,
  203. safetyResponsibleDepartmentIdTodo: JSON.stringify(formValue.safetyResponsibleDepartmentIdTodo), // 根据接口需求决定是否 stringify
  204. safetySpecificPersonTodo: formValue.safetySpecificPersonTodo,
  205. safetySpecificPersonNameTodo: formValue.safetySpecificPersonNameTodo,
  206. changeReason: formValue.changeReason,
  207. };
  208. areaCheckListChange(submitData)
  209. .then(() => {
  210. ElMessage.success('变更申请提交成功!');
  211. router.push({ name: 'listResponsibilities:nonPublic' });
  212. })
  213. .finally(() => (submiting.value = false));
  214. }
  215. });
  216. };
  217. </script>
  218. <style lang="scss" scoped>
  219. @use '@/styles/page-main-layout.scss' as *;
  220. @use '@/styles/page-details-layout.scss' as *;
  221. @use '@/styles/basic-table-action.scss' as *;
  222. </style>