PlansAndProgramsDialog.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <template>
  2. <el-dialog
  3. :model-value="props.modelValue"
  4. @update:model-value="$emit('update:modelValue', $event)"
  5. :title="props.dialogInfo.title"
  6. width="600"
  7. @close="clearData"
  8. >
  9. <el-form ref="formRef" label-width="auto" :model="formData" :rules="rules">
  10. <el-form-item label="计划和名称" prop="planName">
  11. <el-input :disabled="isView" v-model="formData.planName" size="large" />
  12. </el-form-item>
  13. <el-form-item label="执行部门" prop="execDepartmentId">
  14. <el-cascader
  15. :disabled="isView"
  16. style="width: 100%"
  17. v-model="formData.execDepartmentId"
  18. size="large"
  19. ref="cascaderRef"
  20. :options="firstLevelDepts"
  21. :props="cascaderProp"
  22. :show-all-levels="false"
  23. placeholder="请选择责任部门"
  24. filterable
  25. @change="handleChangeDept('execDepartmentId')"
  26. />
  27. </el-form-item>
  28. <el-form-item label="执行人" prop="executor">
  29. <el-select
  30. :disabled="isView"
  31. multiple
  32. v-model="formData.executor"
  33. placeholder="请选择"
  34. size="large"
  35. style="width: 100%"
  36. filterable
  37. >
  38. <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value" />
  39. </el-select>
  40. </el-form-item>
  41. <el-form-item label="计划内容" prop="planContent">
  42. <el-input :disabled="isView" v-model="formData.planContent" type="textarea" :rows="6" size="large" />
  43. </el-form-item>
  44. <el-form-item prop="planStartDate" label="计划开始日期">
  45. <el-date-picker
  46. :disabled="isView"
  47. v-model="formData.planStartDate"
  48. size="large"
  49. format="YYYY-MM-DD"
  50. value-format="YYYY-MM-DD"
  51. style="width: 100%"
  52. placeholder="计划开始日期"
  53. />
  54. </el-form-item>
  55. <el-form-item prop="planEndDate" label="计划结束日期">
  56. <el-date-picker
  57. :disabled="isView"
  58. v-model="formData.planEndDate"
  59. style="width: 100%"
  60. size="large"
  61. format="YYYY-MM-DD"
  62. value-format="YYYY-MM-DD"
  63. placeholder="计划结束日期"
  64. />
  65. </el-form-item>
  66. <el-form-item prop="teamName" label="是否推送">
  67. <el-radio-group :disabled="isView" v-model="formData.status">
  68. <el-radio :value="1">待开始</el-radio>
  69. <el-radio :value="2">进行中</el-radio>
  70. <el-radio :value="3">已完成</el-radio>
  71. </el-radio-group>
  72. </el-form-item>
  73. </el-form>
  74. <template #footer>
  75. <div>
  76. <el-button type="primary" @click="submitForm" :loading="submitLoading" :disabled="isView"> 保存 </el-button>
  77. <el-button @click="handleCancel">取消</el-button>
  78. </div>
  79. </template>
  80. </el-dialog>
  81. </template>
  82. <script setup lang="ts">
  83. import { ref, reactive, watch, onMounted, computed } from 'vue';
  84. import type { FormInstance, FormRules } from 'element-plus';
  85. import { getAllDepartments } from '@/api/auth/dept';
  86. import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
  87. import dayjs from 'dayjs';
  88. import {
  89. queryAvailableUserList,
  90. safetyHazardInventoryQueryPlanDetail,
  91. } from '@/api/production-safety/responsibility-implementation';
  92. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  93. const props = defineProps<{
  94. modelValue: boolean;
  95. dialogInfo: { [key: string]: any };
  96. }>();
  97. const formRef = ref<FormInstance>();
  98. const emit = defineEmits(['close', 'submit', 'update:modelValue']);
  99. const submitLoading = ref(false);
  100. const showDialog = ref(false);
  101. const firstLevelDepts = ref<any[]>([]);
  102. const cascaderProp = {
  103. expandTrigger: 'click',
  104. checkStrictly: true,
  105. value: 'id',
  106. label: 'deptName',
  107. };
  108. const cascaderRef = ref<any>();
  109. const userOptions = ref<any[]>([]);
  110. const isView = computed(() => props.dialogInfo.type === 'view');
  111. const formData = reactive<any>({
  112. planName: '',
  113. execDepartment: '',
  114. execDepartmentId: [],
  115. planStartDate: null,
  116. planEndDate: null,
  117. status: 1,
  118. executor: '',
  119. planContent: '',
  120. });
  121. const rules = reactive<Record<string, any>>({
  122. planName: [{ required: true, message: '请输入计划和名称' }],
  123. planContent: [{ required: true, message: '请输入计划内容' }],
  124. execDepartment: [{ required: true, message: '请输入执行部门' }],
  125. planStartDate: [
  126. { required: true, message: '请选择计划开始日期' },
  127. {
  128. validator: (rule, value) => {
  129. return new Promise((resolve, reject) => {
  130. if (value && formData.planEndDate) {
  131. if (dayjs(value).isAfter(formData.planEndDate)) {
  132. reject(new Error('开始日期不能大于结束日期'));
  133. return;
  134. }
  135. }
  136. resolve(true);
  137. });
  138. },
  139. },
  140. ],
  141. planEndDate: [
  142. { required: true, message: '请选择计划结束日期' },
  143. {
  144. validator: (rule, value) => {
  145. return new Promise((resolve, reject) => {
  146. if (value && formData.planStartDate) {
  147. if (dayjs(value).isBefore(formData.planStartDate)) {
  148. reject(new Error('结束日期不能小于开始日期'));
  149. return;
  150. }
  151. }
  152. resolve(true);
  153. });
  154. },
  155. },
  156. ],
  157. executor: [{ required: true, message: '请输入执行人' }],
  158. });
  159. const handleQueryAvailableUserList = (deptName, realname = '') => {
  160. return queryAvailableUserList({
  161. pageNumber: 1,
  162. pageSize: 200,
  163. queryParam: {
  164. deptName,
  165. realname,
  166. },
  167. }).then((res: any) => {
  168. userOptions.value = (res.records || []).map((u: any) => ({
  169. value: u.userId || u.id,
  170. label: u.realname,
  171. }));
  172. // switch (prop) {
  173. // case 'safetyResponsibleCenter':
  174. // formValue.safetyCenterManager = null;
  175. // safetyCenterManagerOptions.value = (res.records || []).map((u: any) => ({
  176. // value: u.userId || u.id,
  177. // label: u.realname,
  178. // }));
  179. // break;
  180. // case 'safetyResponsibleDepartment':
  181. // alert('');
  182. // formValue.safetyDepartmentManager = null;
  183. // formValue.safetySpecificPerson = null;
  184. // safetyDepartmentUserOptions.value = (res.records || []).map((u: any) => ({
  185. // value: u.userId || u.id,
  186. // label: u.realname,
  187. // }));
  188. // break;
  189. // default:
  190. // break;
  191. // }
  192. });
  193. };
  194. function dialogShow() {
  195. showDialog.value = true;
  196. }
  197. function dialogHide() {
  198. showDialog.value = false;
  199. }
  200. const getDeptData = () => {
  201. return getAllDepartments().then((res) => {
  202. firstLevelDepts.value = formatDeptTree(res);
  203. });
  204. };
  205. const handleChangeDept = (prop) => {
  206. const cascader = cascaderRef.value;
  207. const deptInfo = cascader?.getCheckedNodes();
  208. formData['execDepartmentId'] = deptInfo[0].pathValues;
  209. formData['execDepartment'] = deptInfo[0].label;
  210. formRef.value?.validateField('execDepartment');
  211. // nextTick(() => {
  212. // handleQueryAvailableUserList(deptInfo[0].label, prop);
  213. // });
  214. };
  215. const handleCancel = () => {
  216. emit('update:modelValue', false);
  217. };
  218. function clearData() {
  219. formRef.value?.resetFields();
  220. Object.assign(formData, {
  221. planName: '',
  222. execDepartment: '',
  223. planStartDate: null,
  224. planEndDate: null,
  225. status: 0,
  226. execPerson: '',
  227. });
  228. }
  229. function submitForm() {
  230. formRef.value?.validate((valid) => {
  231. if (!valid) {
  232. return;
  233. }
  234. emit('submit', formData, submitLoading);
  235. });
  236. }
  237. const handlesafetyHazardInventoryQueryPlanDetail = async (id) => {
  238. const res = await safetyHazardInventoryQueryPlanDetail(id as string);
  239. return res;
  240. };
  241. onMounted(async () => {
  242. await Promise.all([getDeptData(), handleQueryAvailableUserList('')]);
  243. if (props.dialogInfo.type !== 'add') {
  244. handlesafetyHazardInventoryQueryPlanDetail(props.dialogInfo.currentRow.id).then((res) => {
  245. Object.assign(formData, {
  246. ...res,
  247. execDepartmentId: res.execDepartmentId ? res.execDepartmentId.split(',').map((item) => Number(item)) : [],
  248. executor: res.executor ? res.executor.split(',').map((item) => Number(item)) : [],
  249. });
  250. });
  251. }
  252. });
  253. defineExpose({
  254. submitLoading,
  255. dialogShow,
  256. dialogHide,
  257. });
  258. </script>
  259. <style scoped lang="scss"></style>