edit.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. <template>
  2. <view class="page fault">
  3. <scroll-view scroll-y="true" class="detail">
  4. <view class="form-content">
  5. <uni-forms
  6. ref="faultFormRef"
  7. labelWidth="140px"
  8. :modelValue="maintain"
  9. :rules="maintainRules"
  10. >
  11. <!-- 设备 -->
  12. <uni-forms-item
  13. class="form-item"
  14. :label="$t('maintenanceWorkOrder.equipment')"
  15. name="deviceName"
  16. :required="true"
  17. >
  18. <uni-easyinput
  19. style="text-align: right"
  20. :inputBorder="false"
  21. :clearable="false"
  22. :styles="{ disableColor: '#fff' }"
  23. :placeholder="$t('operation.PleaseSelect')"
  24. v-model="maintain.deviceName"
  25. @focus="onAddDevice"
  26. />
  27. </uni-forms-item>
  28. <!-- 是否解决 -->
  29. <uni-forms-item
  30. class="form-item"
  31. :label="$t('workOrder.isSolved')"
  32. name="ifDeal"
  33. :required="true"
  34. >
  35. <uni-data-select
  36. :clear="false"
  37. v-model="maintain.ifDeal"
  38. :localdata="yesOrNoRange"
  39. @change="ifDealChange"
  40. >
  41. </uni-data-select>
  42. </uni-forms-item>
  43. <!-- 是否协助 -->
  44. <uni-forms-item
  45. class="form-item"
  46. :label="$t('workOrder.isHelp')"
  47. name="needHelp"
  48. :required="true"
  49. >
  50. <uni-data-select
  51. :clear="false"
  52. v-model="maintain.needHelp"
  53. :localdata="yesOrNoRange"
  54. @change="needHelpChange"
  55. >
  56. </uni-data-select>
  57. </uni-forms-item>
  58. <!-- 故障系统 -->
  59. <uni-forms-item
  60. class="form-item"
  61. :label="$t('fault.faultSystem')"
  62. name="failureSystem"
  63. :required="true"
  64. >
  65. <uni-easyinput
  66. style="text-align: right"
  67. :inputBorder="false"
  68. :clearable="false"
  69. :styles="{ disableColor: '#fff' }"
  70. v-model="maintain.failureSystem"
  71. :placeholder="$t('operation.PleaseFillIn')"
  72. />
  73. </uni-forms-item>
  74. <!-- 故障时间 -->
  75. <uni-forms-item
  76. class="form-item"
  77. :label="$t('fault.faultTime')"
  78. name="failureTime"
  79. :required="true"
  80. >
  81. <uni-datetime-picker
  82. type="datetime"
  83. :border="false"
  84. returnType="timestamp"
  85. :placeholder="$t('operation.PleaseSelect')"
  86. :style="{
  87. color: maintain.failureTime ? '#333' : '#999',
  88. 'font-size': maintain.failureTime
  89. ? '14px !important'
  90. : 'inherit !important',
  91. }"
  92. :end="dateMax"
  93. v-model="maintain.failureTime"
  94. >
  95. </uni-datetime-picker>
  96. </uni-forms-item>
  97. <!-- 故障解决时间 是否解决为是,是否协助为否时需要填写-->
  98. <uni-forms-item
  99. class="form-item"
  100. :label="$t('fault.faultResolutionTime')"
  101. name="dealTime"
  102. :required="true"
  103. v-if="maintain.ifDeal"
  104. >
  105. <!-- :end="dateMax" -->
  106. <uni-datetime-picker
  107. type="datetime"
  108. :border="false"
  109. returnType="timestamp"
  110. :placeholder="$t('operation.PleaseSelect')"
  111. :style="{
  112. color: maintain.dealTime ? '#333' : '#999',
  113. 'font-size': maintain.dealTime
  114. ? '14px !important'
  115. : 'inherit !important',
  116. }"
  117. :end="dateMax"
  118. v-model="maintain.dealTime"
  119. >
  120. </uni-datetime-picker>
  121. </uni-forms-item>
  122. <!-- 审批人 是否解决为否 时需要选择 -->
  123. <uni-forms-item
  124. class="form-item"
  125. :label="$t('workOrder.approver')"
  126. name="approvalId"
  127. :required="true"
  128. v-if="maintain.ifDeal == 0"
  129. >
  130. <uni-data-select
  131. :clear="false"
  132. :disabled="true"
  133. v-model="maintain.approvalId"
  134. :localdata="approvalList"
  135. @click="
  136. openLocalSearch(
  137. approvalList,
  138. 'approvalId',
  139. $t('workOrder.approver')
  140. )
  141. "
  142. >
  143. </uni-data-select>
  144. </uni-forms-item>
  145. <!-- 是否停机 -->
  146. <uni-forms-item
  147. class="form-item"
  148. :label="$t('equipmentMaintenance.isStop')"
  149. name="ifStop"
  150. :required="false"
  151. >
  152. <uni-data-select
  153. :clear="false"
  154. v-model="maintain.ifStop"
  155. :localdata="yesOrNoRange"
  156. >
  157. </uni-data-select>
  158. </uni-forms-item>
  159. <!-- 图片 -->
  160. <uni-forms-item
  161. class="form-item"
  162. :label="$t('general.picture')"
  163. name="picList"
  164. :required="false"
  165. >
  166. <uni-file-picker
  167. file-mediatype="image"
  168. mode="grid"
  169. :auto-upload="false"
  170. :limit="1"
  171. :imageStyles="{ border: false }"
  172. v-model="maintain.picList"
  173. @select="upload"
  174. >
  175. <template #default>
  176. <view
  177. class="flex-col align-center justify-center"
  178. style="width: 60px; height: 60px; background-color: #f4f4f4"
  179. >
  180. <uni-icons type="plusempty" color="#ACACAC" size="12" />
  181. </view>
  182. </template>
  183. </uni-file-picker>
  184. </uni-forms-item>
  185. <!-- 故障影响 -->
  186. <uni-forms-item
  187. class="form-item"
  188. :label="$t('fault.faultImpact')"
  189. name="failureInfluence"
  190. :required="false"
  191. >
  192. <uni-easyinput
  193. style="text-align: right"
  194. :inputBorder="false"
  195. :clearable="false"
  196. :styles="{ disableColor: '#fff' }"
  197. v-model="maintain.failureInfluence"
  198. :placeholder="$t('operation.PleaseFillIn')"
  199. />
  200. </uni-forms-item>
  201. <!-- 解决办法 是否解决为是,是否协助为否时需要填写 -->
  202. <uni-forms-item
  203. class="form-item"
  204. :label="$t('fault.solution')"
  205. :required="true"
  206. name="solution"
  207. v-if="maintain.ifDeal"
  208. >
  209. <uni-easyinput
  210. style="text-align: right"
  211. type="textarea"
  212. :autoHeight="true"
  213. :inputBorder="false"
  214. :clearable="false"
  215. :styles="{ disableColor: '#fff' }"
  216. v-model="maintain.solution"
  217. :placeholder="$t('operation.PleaseFillIn')"
  218. />
  219. </uni-forms-item>
  220. <!-- 故障描述 -->
  221. <uni-forms-item
  222. class="form-item"
  223. :label="$t('fault.description')"
  224. :required="false"
  225. name="description"
  226. >
  227. <uni-easyinput
  228. style="text-align: right"
  229. type="textarea"
  230. :autoHeight="true"
  231. :inputBorder="false"
  232. :clearable="false"
  233. :styles="{ disableColor: '#fff' }"
  234. v-model="maintain.description"
  235. :placeholder="$t('operation.PleaseFillIn')"
  236. />
  237. </uni-forms-item>
  238. <!-- 备注 -->
  239. <uni-forms-item
  240. class="form-item"
  241. :label="$t('operation.remark')"
  242. :required="false"
  243. name="remark"
  244. >
  245. <uni-easyinput
  246. style="text-align: right"
  247. type="textarea"
  248. :autoHeight="true"
  249. :inputBorder="false"
  250. :clearable="false"
  251. :styles="{ disableColor: '#fff' }"
  252. v-model="maintain.remark"
  253. :placeholder="$t('operation.PleaseFillIn')"
  254. />
  255. </uni-forms-item>
  256. </uni-forms>
  257. </view>
  258. </scroll-view>
  259. <button class="submit-btn" type="primary" @click="formSubmit(faultFormRef)">
  260. {{ $t("operation.submit") }}
  261. </button>
  262. </view>
  263. <!-- 设备选择 -->
  264. <device-single ref="deviceSingleRef" @devide-submit="onChooseDevice" />
  265. <!-- 本地搜索 (选择审批人) -->
  266. <local-search ref="localSearchRef" @choosed="onChooseLocalSearch" />
  267. </template>
  268. <script setup>
  269. import { onLoad, onReady, onBackPress } from "@dcloudio/uni-app";
  270. import {
  271. reactive,
  272. ref,
  273. watch,
  274. computed,
  275. watchEffect,
  276. onMounted,
  277. onBeforeUnmount,
  278. nextTick,
  279. getCurrentInstance,
  280. } from "vue";
  281. import {
  282. updateFault,
  283. getFaultDetail,
  284. getFailureApprovalList,
  285. } from "@/api/fault.js";
  286. import { getRandomNumber } from "@/utils/methods";
  287. import dayjs from "dayjs";
  288. import { uploadFile } from "@/api";
  289. import deviceSingle from "@/components/device/single.vue";
  290. import LocalSearch from "@/components/local-search.vue";
  291. import { useDataDictStore } from "@/store/modules/dataDict";
  292. const { getDataDictList } = useDataDictStore();
  293. // 引用全局变量$t
  294. const { appContext } = getCurrentInstance();
  295. const t = appContext.config.globalProperties.$t;
  296. //
  297. const yesOrNoRange = ref([
  298. {
  299. value: 1,
  300. text: t("operation.yes"),
  301. },
  302. {
  303. value: 0,
  304. text: t("operation.no"),
  305. },
  306. ]);
  307. // 获取当前时间
  308. const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
  309. const dateMax = ref(now);
  310. //故障详情
  311. const maintain = ref({
  312. deviceId: "",
  313. deviceName: "",
  314. picList: [], //用于上传照片 提交时删除
  315. });
  316. // 获取故障详情
  317. const getFaultDetailData = async (id) => {
  318. await getFaultDetail({
  319. id: id,
  320. })
  321. .then((res) => {
  322. console.log("getFaultDetailData", res.data);
  323. const { data } = res;
  324. // ifDeal,needHelp, isStop从true/false转换为1/0
  325. data.ifDeal = data.ifDeal ? 1 : 0;
  326. data.needHelp = data.needHelp ? 1 : 0;
  327. data.isStop = data.isStop ? 1 : 0;
  328. (data.picList = data.pic
  329. ? [
  330. {
  331. url: data.pic,
  332. },
  333. ]
  334. : []),
  335. console.log("get---data", data);
  336. // 如果存在审批人,则获取审批人信息
  337. if (data.approvalId) {
  338. getApprovalList();
  339. }
  340. maintain.value = data;
  341. })
  342. .catch((err) => {});
  343. };
  344. // 选择设备
  345. const deviceSingleRef = ref(null);
  346. const selectedDevices = ref([]);
  347. const onAddDevice = () => {
  348. deviceSingleRef.value.open();
  349. };
  350. const onChooseDevice = (data) => {
  351. console.log("onChooseDevice", data);
  352. maintain.value.deviceId = data.id;
  353. maintain.value.deptId = data.deptId;
  354. maintain.value.deviceCode = data.deviceCode;
  355. maintain.value.deviceName = data.deviceName;
  356. console.log("onChooseDevice-maintain", maintain.value);
  357. };
  358. // 上传图片
  359. const upload = async (event) => {
  360. for (const path of event.tempFilePaths) {
  361. maintain.value.pic = (await uploadFile(path)).data;
  362. }
  363. };
  364. // 故障是否已解决
  365. const ifDealChange = (value) => {
  366. console.log("ifDealChange", value);
  367. maintain.value.ifDeal = value;
  368. if (value == 0) {
  369. maintain.value.needHelp = 1;
  370. } else {
  371. maintain.value.needHelp = 0;
  372. }
  373. };
  374. // 故障是否需要帮助
  375. const needHelpChange = (value) => {
  376. maintain.value.needHelp = value;
  377. if (value == 1) {
  378. maintain.value.ifDeal = 0;
  379. } else {
  380. maintain.value.ifDeal = 1;
  381. }
  382. };
  383. // 审批人列表
  384. const approvalList = ref([]);
  385. const getApprovalList = async () => {
  386. const res = await getFailureApprovalList();
  387. approvalList.value = res.data.map((item) => ({
  388. value: item.id,
  389. text: item.nickname,
  390. }));
  391. };
  392. // 本地搜索
  393. const localSearchRef = ref(null);
  394. // 打开本地搜索
  395. const openLocalSearch = (list, propKey, title) => {
  396. localSearchRef.value.open({
  397. list,
  398. propKey,
  399. title,
  400. choosed: maintain.value[propKey],
  401. });
  402. };
  403. // 本地搜索确认选择
  404. const onChooseLocalSearch = (propKey, item) => {
  405. console.log("🚀 ~ onChooseLocalSearch ~ propKey, item:", propKey, item);
  406. // 根据propKey设置maintain的值
  407. maintain.value[propKey] = item.value;
  408. };
  409. const faultFormRef = ref(null);
  410. const maintainBaseRules = ref({
  411. deviceName: {
  412. rules: [
  413. {
  414. required: true,
  415. errorMessage: `${t("operation.PleaseSelect")}${t("device.deviceName")}`,
  416. },
  417. ],
  418. },
  419. ifDeal: {
  420. rules: [
  421. {
  422. required: true,
  423. errorMessage: `${t("operation.PleaseSelect")}${t(
  424. "workOrder.isSolved"
  425. )}`,
  426. },
  427. ],
  428. },
  429. needHelp: {
  430. rules: [
  431. {
  432. required: true,
  433. errorMessage: `${t("operation.PleaseSelect")}${t(
  434. "workOrder.Needassistance"
  435. )}`,
  436. },
  437. ],
  438. },
  439. failureSystem: {
  440. rules: [
  441. {
  442. required: true,
  443. errorMessage: `${t("operation.PleaseFillIn")}${t("fault.faultSystem")}`,
  444. },
  445. ],
  446. },
  447. failureTime: {
  448. rules: [
  449. {
  450. required: true,
  451. errorMessage: `${t("operation.PleaseSelect")}${t("fault.faultTime")}`,
  452. },
  453. ],
  454. },
  455. dealTime: {
  456. rules: [
  457. {
  458. required: false,
  459. errorMessage: `${t("operation.PleaseSelect")}${t(
  460. "fault.faultResolutionTime"
  461. )}`,
  462. },
  463. ],
  464. },
  465. solution: {
  466. rules: [
  467. {
  468. required: false,
  469. errorMessage: `${t("operation.PleaseFillIn")}${t("fault.solution")}`,
  470. },
  471. ],
  472. },
  473. approvalId: {
  474. rules: [
  475. {
  476. required: false,
  477. errorMessage: `${t("operation.PleaseSelect")}${t(
  478. "workOrder.approver"
  479. )}`,
  480. },
  481. ],
  482. },
  483. });
  484. // 动态计算校验规则
  485. const maintainRules = computed(() => {
  486. const rules = JSON.parse(JSON.stringify(maintainBaseRules.value));
  487. // 根据是否解决动态调整规则
  488. if (maintain.value.ifDeal === 0) {
  489. // 未解决:解决时间 解决办法非必填
  490. rules.dealTime.rules[0].required = false;
  491. rules.solution.rules[0].required = false;
  492. // 未解决:审批人必填
  493. rules.approvalId.rules[0].required = true;
  494. } else {
  495. // 已解决:故障时间 解决时间 解决办法必填
  496. rules.dealTime.rules[0].required = true;
  497. rules.solution.rules[0].required = true;
  498. // 已解决:审批人非必填
  499. rules.approvalId.rules[0].required = false;
  500. }
  501. return rules;
  502. });
  503. // 监听是否解决数据变化,触发规则更新和校验重置
  504. watch(
  505. () => maintain.value.ifDeal,
  506. (newVal, oldVal) => {
  507. console.log("是否解决变更:", oldVal, "->", newVal);
  508. // 是否解决为否, 获取审批人列表
  509. if (newVal == 0) {
  510. getApprovalList();
  511. }
  512. nextTick(() => {
  513. // 重置相关字段的值和校验状态
  514. resetFieldsByTypeChange(newVal, oldVal);
  515. });
  516. }
  517. );
  518. // 根据是否解决变更重置字段
  519. const resetFieldsByTypeChange = (newType, oldType) => {
  520. // 如果是否解决没有变化或不是初始化阶段,则不执行重置
  521. if (newType === oldType && oldType !== undefined) return;
  522. // 清空故障解决时间和解决办法
  523. if (newType == 0) {
  524. maintain.value.dealTime = "";
  525. maintain.value.solution = "";
  526. // 重置审批人
  527. maintain.value.approvalId = "";
  528. }
  529. // 重置表单校验状态
  530. faultFormRef.value?.resetFields(["dealTime", "solution", "approvalId"]);
  531. };
  532. const formSubmit = async (formEl) => {
  533. if (!formEl) return;
  534. await formEl
  535. .validate()
  536. .then((res) => {
  537. console.log("success", res);
  538. // 当是否解决为是时,故障解决时间不能早于故障时间
  539. if (maintain.value.ifDeal === 1) {
  540. if (maintain.value.dealTime < maintain.value.failureTime) {
  541. uni.showToast({
  542. title: t("fault.timeNotBeEarlier"),
  543. icon: "none",
  544. });
  545. return;
  546. }
  547. }
  548. // 新建参数用于提交
  549. const submitMaintain = {
  550. ...maintain.value,
  551. // 是否解决,是否协助,是否停机更换成true/false
  552. ifDeal: maintain.value.ifDeal ? true : false,
  553. needHelp: maintain.value.needHelp ? true : false,
  554. ifStop: maintain.value.ifStop ? true : false,
  555. };
  556. // 删picList
  557. delete submitMaintain.picList;
  558. console.log("submitMaintain", submitMaintain);
  559. updateFault({
  560. ...submitMaintain,
  561. })
  562. .then((res) => {
  563. console.log("updateFault", res);
  564. if (res.code == 0) {
  565. uni.showToast({
  566. title: t("operation.success"),
  567. icon: "success",
  568. });
  569. uni.navigateBack();
  570. } else {
  571. uni.showToast({
  572. title: res.msg,
  573. icon: "none",
  574. });
  575. }
  576. })
  577. .catch((err) => {
  578. console.log("err", err);
  579. });
  580. })
  581. .catch((err) => {
  582. console.log("err", err);
  583. });
  584. };
  585. onMounted(() => {
  586. // 监听子页面提交的事件
  587. console.log("onMounted");
  588. // uni.$on('multiple-devide-submit', (data) => {
  589. // console.log('接收到子页面数据:', data);
  590. // selectedDevices.value = data
  591. // onDeviceBomList()
  592. // });
  593. });
  594. onBeforeUnmount(() => {
  595. // 移除监听
  596. console.log("onBeforeUnmount");
  597. // uni.$off('multiple-devide-submit');
  598. });
  599. onLoad((option) => {
  600. console.log("onLoad", option);
  601. getFaultDetailData(option.id);
  602. });
  603. onReady(() => {
  604. // 设置自定义表单校验规则,必须在节点渲染完毕后执行
  605. // this.$refs.customForm.setRules(this.customRules)
  606. });
  607. onBackPress((options) => {
  608. // options.from 值为 'navigateBack' 时,表示返回是由 uni.navigateBack() 方法调用触发的
  609. // options.from 值为 'navigator' 时,表示返回是由导航栏返回按钮或物理返回键触发的
  610. console.log("返回触发来源:", options.from);
  611. });
  612. </script>
  613. <style lang="scss" scoped>
  614. @import "@/style/work-order-detail.scss";
  615. </style>