dispatchDialog.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. <template>
  2. <ele-modal
  3. :centered="true"
  4. :visible.sync="dispatchDialog"
  5. title="派单"
  6. :close-on-click-modal="false"
  7. width="1000px"
  8. append-to-body
  9. @close="handleClose"
  10. >
  11. <el-form
  12. ref="addFormRef"
  13. :model="addForm"
  14. label-width="120px"
  15. class="add_form"
  16. >
  17. <el-row>
  18. <el-col :span="12">
  19. <el-form-item label="编码" prop="code">
  20. <el-input
  21. v-model="addForm.code"
  22. size="small"
  23. placeholder="请输入"
  24. disabled
  25. ></el-input>
  26. </el-form-item>
  27. </el-col>
  28. <el-col :span="12">
  29. <el-form-item
  30. label="计划名称"
  31. prop="name"
  32. :rules="{
  33. required: true,
  34. message: '请输入计划名称',
  35. trigger: 'change'
  36. }"
  37. >
  38. <el-input
  39. v-model="addForm.name"
  40. size="small"
  41. placeholder="请输入"
  42. ></el-input>
  43. </el-form-item>
  44. </el-col>
  45. <el-col :span="12">
  46. <el-form-item label="自动派单" prop="isSyncBill">
  47. <el-select
  48. v-model="addForm.isSyncBill"
  49. size="small"
  50. style="width: 100%"
  51. >
  52. <el-option :value="1" label="是"></el-option>
  53. <el-option :value="0" label="否"></el-option>
  54. </el-select>
  55. </el-form-item>
  56. </el-col>
  57. <el-col :span="12">
  58. <el-form-item
  59. label="预计售后时长"
  60. prop="duration"
  61. :rules="{
  62. required: true,
  63. message: '请输入预计售后时长',
  64. trigger: 'change'
  65. }"
  66. >
  67. <div style="display: flex">
  68. <el-input
  69. type="number"
  70. v-model="addForm.duration"
  71. size="small"
  72. placeholder="请输入"
  73. min="1"
  74. @input="formDataDurationTime"
  75. >
  76. <template #suffix>
  77. <el-select
  78. v-model="addForm.durationUnit"
  79. size="small"
  80. style="width: 120px"
  81. >
  82. <el-option :value="'1'" label="分钟"></el-option>
  83. <el-option :value="'2'" label="小时"></el-option>
  84. <el-option :value="'3'" label="天"></el-option>
  85. </el-select>
  86. </template>
  87. </el-input>
  88. </div>
  89. </el-form-item>
  90. </el-col>
  91. </el-row>
  92. <el-row>
  93. <el-col :span="12">
  94. <el-form-item
  95. label="部门"
  96. prop="executeGroupId"
  97. :rules="{
  98. required: true,
  99. message: '请选择部门',
  100. trigger: 'change'
  101. }"
  102. >
  103. <deptSelect
  104. v-model="addForm.executeGroupId"
  105. @changeGroup="searchDeptNodeClick"
  106. />
  107. </el-form-item>
  108. </el-col>
  109. <el-col :span="12">
  110. <el-form-item
  111. label="工单执行人"
  112. prop="executeUserId"
  113. :rules="{
  114. required: true,
  115. message: '请选择执行人',
  116. trigger: 'change'
  117. }"
  118. >
  119. <el-select
  120. v-model="addForm.executeUserId"
  121. size="small"
  122. style="width: 100%"
  123. filterable
  124. @change="changeUser"
  125. >
  126. <el-option
  127. v-for="item in executorList"
  128. :key="item.id"
  129. :value="item.id"
  130. :label="item.name"
  131. ></el-option>
  132. </el-select>
  133. </el-form-item>
  134. </el-col>
  135. <el-col :span="12">
  136. <el-form-item
  137. label="紧急程度"
  138. prop="urgent"
  139. :rules="{
  140. required: true,
  141. message: '请选择紧急程度',
  142. trigger: 'change'
  143. }"
  144. >
  145. <DictSelection
  146. dictName="紧急程度"
  147. clearable
  148. v-model="addForm.urgent"
  149. ></DictSelection>
  150. </el-form-item>
  151. </el-col>
  152. <el-col :span="12">
  153. <el-form-item label="备注" prop="remark">
  154. <el-input
  155. type="textarea"
  156. resize="none"
  157. v-model="addForm.remark"
  158. :rows="2"
  159. placeholder="请详细说明"
  160. size="small"
  161. ></el-input>
  162. </el-form-item>
  163. </el-col>
  164. </el-row>
  165. </el-form>
  166. <div slot="footer" class="footer">
  167. <el-button type="primary" @click="handleSubmit" :loading="loading">确认</el-button>
  168. <el-button @click="handleClose" :loading="loading">取消</el-button>
  169. </div>
  170. </ele-modal>
  171. </template>
  172. <script>
  173. import deptSelect from '@/components/CommomSelect/dept-select.vue';
  174. import { getUserPage } from '@/api/system/organization';
  175. import { getCurrentUser } from '@/utils/token-util';
  176. import { demanDispatch } from '@/api/salesServiceManagement/index';
  177. let submitData = {};
  178. export default {
  179. components: { deptSelect },
  180. computed: {
  181. loginChangeGroupVOList() {
  182. return this.$store.state.user?.info?.loginChangeGroupVOList;
  183. }
  184. },
  185. data() {
  186. return {
  187. dispatchDialog: false,
  188. addForm: {
  189. code: '', // 编码
  190. name: '', // 计划名称
  191. isSyncBill: 1, // 是否自动派单
  192. duration: null, // 原始时长值
  193. durationUnit: '1', // 时长单位(1:分钟 2:小时 3:天)
  194. executeGroupId: '', // 执行部门ID
  195. executeGroupName: '', // 执行部门名称
  196. executeUserId: '', // 执行人ID
  197. executeUserName: '', // 执行人名称
  198. urgent: null, // 紧急程度
  199. remark: '' // 备注
  200. },
  201. loading: false,
  202. executorList: [],
  203. submitSource: 1 // 1:新增;2:修改
  204. };
  205. },
  206. methods: {
  207. handleClose() {
  208. this.dispatchDialog = false;
  209. this.addForm = {
  210. code: '',
  211. name: '',
  212. isSyncBill: 1,
  213. duration: null,
  214. durationUnit: '1',
  215. executeGroupId: '',
  216. executeGroupName: '',
  217. executeUserId: '',
  218. executeUserName: '',
  219. urgent: null,
  220. remark: ''
  221. };
  222. this.$refs.addFormRef?.resetFields();
  223. },
  224. open(data, type) {
  225. this.submitSource = type === 'add' ? 1 : 2;
  226. this.dispatchDialog = true;
  227. submitData = { ...data }; // 深拷贝避免原数据污染
  228. const currentUser = getCurrentUser();
  229. if (this.loginChangeGroupVOList && this.loginChangeGroupVOList.length > 0) {
  230. const obj = this.loginChangeGroupVOList.find(
  231. el => el.groupId === currentUser.currentGroupId
  232. );
  233. this.addForm.executeGroupId = currentUser.currentGroupId || '';
  234. this.searchDeptNodeClick(currentUser.currentGroupId, {
  235. name: obj?.groupName || ''
  236. });
  237. }
  238. },
  239. // 选择部门后获取部门人员
  240. searchDeptNodeClick(groupId, data) {
  241. if (groupId) {
  242. this.addForm.executeGroupId = groupId;
  243. this.addForm.executeGroupName = data?.name || '';
  244. // 获取部门下的人员列表
  245. this.getUserList({ groupId });
  246. } else {
  247. this.addForm.executeGroupId = '';
  248. this.addForm.executeGroupName = '';
  249. this.executorList = [];
  250. this.addForm.executeUserId = '';
  251. this.addForm.executeUserName = '';
  252. }
  253. },
  254. // 获取部门人员列表
  255. async getUserList(params) {
  256. try {
  257. const res = await getUserPage({
  258. pageNum: 1,
  259. size: -1,
  260. ...params
  261. });
  262. this.executorList = res.list || [];
  263. } catch (error) {
  264. this.executorList = [];
  265. console.error('获取人员列表失败:', error);
  266. }
  267. },
  268. // 选择执行人
  269. changeUser(val) {
  270. if (!val) {
  271. this.addForm.executeUserName = '';
  272. return;
  273. }
  274. const user = this.executorList.find(item => item.id === val);
  275. this.addForm.executeUserName = user?.name || '';
  276. },
  277. // 处理时长输入(去除前置0)
  278. formDataDurationTime(value) {
  279. if (value && value > 0) {
  280. this.addForm.duration = Number(value.toString().replace(/^0+/, ''));
  281. } else {
  282. this.addForm.duration = null;
  283. }
  284. },
  285. // 转换时长为小时(后端要求)
  286. calculateDuration() {
  287. if (this.addForm.duration === null) return null;
  288. const duration = Number(this.addForm.duration);
  289. switch (this.addForm.durationUnit) {
  290. case '1': // 分钟转小时(向上取整)
  291. return Math.ceil(duration / 60);
  292. case '2': // 小时直接使用
  293. return duration;
  294. case '3': // 天转小时
  295. return duration * 24;
  296. default:
  297. return duration;
  298. }
  299. },
  300. // 提交表单
  301. handleSubmit() {
  302. this.$refs.addFormRef.validate(async (valid) => {
  303. if (valid) {
  304. // 构造后端要求的参数结构
  305. const planAddPO = {
  306. workOrderExecuteUserId: this.addForm.executeUserId ? Number(this.addForm.executeUserId) : null,
  307. workOrderExecuteUserName: this.addForm.executeUserName,
  308. workOrderExecuteGroupId: this.addForm.executeGroupId ? Number(this.addForm.executeGroupId) : null,
  309. workOrderExecuteGroupName: this.addForm.executeGroupName,
  310. workOrderUrgent: this.addForm.urgent ? Number(this.addForm.urgent) : null,
  311. workOrderRemark: this.addForm.remark,
  312. duration: this.calculateDuration() // 转换为小时
  313. };
  314. const submitParams = {
  315. ...submitData,
  316. planAddPO,
  317. submitSource: this.submitSource
  318. };
  319. this.loading = true;
  320. try {
  321. const res = await demanDispatch(submitParams);
  322. if (res) {
  323. this.$message.success('派单成功');
  324. this.handleClose();
  325. this.$emit('savExit');
  326. }
  327. } catch (error) {
  328. this.$message.error('派单失败:' + (error.message || '未知错误'));
  329. } finally {
  330. this.loading = false;
  331. }
  332. } else {
  333. this.$message.warning('请完善表单信息');
  334. return false;
  335. }
  336. });
  337. }
  338. }
  339. };
  340. </script>
  341. <style scoped lang="scss">
  342. .add_form {
  343. .el-col-12 {
  344. padding-bottom: 13px;
  345. }
  346. }
  347. .footer {
  348. text-align: center;
  349. }
  350. </style>