work.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. <template>
  2. <view class="content">
  3. <up-form :model="form" labelWidth="70" ref="uFormRef" disabled>
  4. <block v-if="workpresetjson.questionedit != 0 && workpresetjson.questionoption">
  5. <up-form-item label="故障类型" prop="itemtype" :required="workpresetjson.questionedit == 11">
  6. <view class="options-box">
  7. <view class="option" :class="form.itemtype == item.value ? 'active' : ''"
  8. v-for="item in questionoption" :key="item.value"
  9. @click="clickRadio(item.value, 'itemtype')">
  10. {{ item.value }}
  11. </view>
  12. </view>
  13. </up-form-item>
  14. <up-form-item label="问题编辑" prop="questionedit" :required="workpresetjson.questionedit == 11">
  15. <up-textarea :disabled="data.status == 1" v-model="form.questionedit" placeholder="问题编辑" autoHeight
  16. height="20" />
  17. </up-form-item>
  18. </block>
  19. <up-form-item v-if="workpresetjson.passcheck != 0" label="合格确认" prop="passcheck"
  20. :required="workpresetjson.passcheck == 11">
  21. <view class="options-box">
  22. <view class="option" :class="form.passcheck == item.value ? 'active' : ''" v-for="item in [
  23. { value: '1', name: '正常' },
  24. { value: '0', name: '异常' }]" :key="item.value" @click="clickRadio(item.value, 'passcheck')">
  25. {{ item.name }}
  26. </view>
  27. </view>
  28. </up-form-item>
  29. <view v-if="workpresetjson.additem != 0">
  30. <up-form-item label="是否更换配件" prop="oldtitems" :required="workpresetjson.additem == 11">
  31. <view class="options-box">
  32. <view class="option" :class="form.additem == item.value ? 'active' : ''" v-for="item in [
  33. { value: '1', name: '是' },
  34. { value: '0', name: '否' }]" :key="item.value" @click="clickRadio(item.value, 'additem')">
  35. {{ item.name }}
  36. </view>
  37. </view>
  38. </up-form-item>
  39. <up-form-item label="配件清单" v-if="form.additem == 1" prop="items" required>
  40. <view>
  41. <accList :list="data.oldtitems" size="small" />
  42. <view class="add" hover-class="navigator-hover" @click="toAddItem">
  43. 去添加
  44. </view>
  45. </view>
  46. </up-form-item>
  47. </view>
  48. <up-form-item v-if="workpresetjson.confirm != 0" label="确认信息" prop="confirm"
  49. :required="workpresetjson.confirm == 11">
  50. <view class="options-box">
  51. <view class="option" :class="form.confirm == item ? 'active' : ''"
  52. v-for="(item) in workpresetjson.confirm_options" :key="item"
  53. @click="clickRadio(item, 'confirm')">
  54. {{ item }}
  55. </view>
  56. </view>
  57. </up-form-item>
  58. <up-form-item v-if="workpresetjson.amountpay != 0" label="费用支付" prop="amountpay"
  59. :required="workpresetjson.amountpay == 11">
  60. <up-input :disabled="data.status == 1" v-model="form.amountpay" type="number" placeholder="费用支付">
  61. <template #suffix>
  62. </template>
  63. </up-input>
  64. </up-form-item>
  65. <up-form-item v-if="workpresetjson.fileupload != 0" label="拍照" prop="fileupload"
  66. :required="rules.fileupload[0].required">
  67. <My_upload :disabled="data.status == 1" ref="upload" :fileList="data.attinfos"
  68. @uploadCallback="uploadCallback" />
  69. </up-form-item>
  70. <up-form-item v-if="workpresetjson.textedit != 0" label="文字说明" prop="textedit"
  71. :required="rules.textedit[0].required">
  72. <up-textarea :disabled="data.status == 1" v-model="form.textedit" placeholder="文字说明" autoHeight
  73. height="20" />
  74. </up-form-item>
  75. </up-form>
  76. <view class="but-box" v-if="data.status != '1'">
  77. <view class="but-box-item" @click="save">
  78. <My-button :customStyle="{
  79. 'background-color': '#FFFFFF',
  80. 'color': '#3874F6',
  81. height: '80rpx',
  82. }" text="保存" :disabled="loading" :loading="loading1" />
  83. </view>
  84. <view class="but-box-item" @click="submit">
  85. <My-button :customStyle="{
  86. height: '80rpx',
  87. }" text="完成" :disabled="loading1" :loading="loading" />
  88. </view>
  89. </view>
  90. <view style="height: 50px;" />
  91. </view>
  92. </template>
  93. <script setup>
  94. import { ref, reactive, getCurrentInstance } from 'vue';
  95. import { onLoad } from '@dcloudio/uni-app';
  96. import accList from "../select/accessoriesList.vue";
  97. const { $Http } = getCurrentInstance().proxy;
  98. const uFormRef = ref(null);
  99. const upload = ref(null);
  100. // 去添加配件
  101. function toAddItem() {
  102. if (data.status == '1') return;
  103. wx.navigateTo({
  104. url: '/pages/select/accessories?list=' + JSON.stringify(data.oldtitems || []),
  105. });
  106. $Http.selectAcc = (res) => {
  107. data.oldtitems = res;
  108. form.oldtitems = data.oldtitems.length ? '1' : '';
  109. uni.navigateBack();
  110. delete $Http.selectAcc
  111. }
  112. }
  113. const form = reactive({
  114. textedit: '', // 上传文本
  115. confirm: "", // 确认信息
  116. itemtype: "", // 故障类型
  117. questionedit: "", // 问题编辑
  118. additem: "", // 是否更换配件
  119. passcheck: "", //合格确认 异常时 文字和图片必填
  120. amountpay: "", // 费用支付
  121. fileupload: "", // 上传图片
  122. oldtitems: "",//配件
  123. });
  124. let keys = {
  125. textedit: 'textcontent', // 文本内容
  126. amountpay: 'amount', // 费用支付
  127. confirm: 'confirm_value', // 确认信息
  128. itemtype: "questionoption",
  129. questionedit: "questionedit",
  130. passcheck: "passcheck",
  131. }
  132. // keys 与 form 互相转换字段
  133. let formToContent = (form) => {
  134. let content = {};
  135. for (let key in keys) {
  136. if (form[key]) {
  137. content[keys[key]] = form[key];
  138. }
  139. }
  140. return content;
  141. }
  142. let data = {
  143. attinfos: []
  144. };
  145. let workpresetjson = reactive({});
  146. let rules = reactive({
  147. textedit: [
  148. { required: false, message: '请输入说明', trigger: 'blur' }
  149. ],
  150. fileupload: [
  151. { required: false, message: '请上传图片', trigger: 'change' }
  152. ],
  153. });
  154. const questionoption = ref([]);
  155. onLoad(() => {
  156. data = reactive($Http.data);
  157. delete $Http.data;
  158. for (let key in keys) {
  159. if (data[keys[key]]) {
  160. form[key] = data[keys[key]];
  161. }
  162. }
  163. form.fileupload = data.attinfos.length ? '1' : '';
  164. wx.setNavigationBarTitle({
  165. title: data.title,
  166. })
  167. workpresetjson = Object.assign(workpresetjson, data.workpresetjson);
  168. if (workpresetjson.additem) {
  169. console.log("data", data)
  170. data.oldtitems = data.detail[0].oldtitems.map(item => {
  171. item.imageUrl = item.attinfos.length ? $Http.getSpecifiedImage(item.attinfos[0]) : ''
  172. return item;
  173. });;
  174. form.oldtitems = data.oldtitems.length ? '1' : '';
  175. form.additem = form.oldtitems.length ? '1' : '';
  176. }
  177. rules = Object.assign(rules, {
  178. textedit: [
  179. { required: workpresetjson.textedit == 11, message: '请输入说明', trigger: 'blur' },
  180. { min: 2, max: 500, message: '长度在 2 到 500 个字符', trigger: 'blur' }
  181. ],
  182. confirm: [
  183. { required: workpresetjson.confirm == 11, message: '请选择确认信息', trigger: 'change' }
  184. ],
  185. itemtype: [
  186. { required: workpresetjson.questionedit == 11, message: '请选择故障类型', trigger: 'change' }
  187. ],
  188. questionedit: [
  189. { required: workpresetjson.questionedit == 11, message: '请输入问题编辑', trigger: 'blur' },
  190. { min: 2, max: 500, message: '长度在 2 到 500 个字符', trigger: 'blur' }
  191. ],
  192. additem: [
  193. { required: workpresetjson.additem == 11, message: '请选择是否更换配件', trigger: 'change' }
  194. ],
  195. passcheck: [
  196. { required: workpresetjson.passcheck == 11, message: '请选择合格确认', trigger: 'change' }
  197. ],
  198. amountpay: [
  199. { required: workpresetjson.amountpay == 11, message: '请输入费用支付', trigger: 'blur' },
  200. { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的金额', trigger: 'blur' }
  201. ],
  202. fileupload: [
  203. { required: workpresetjson.fileupload == 11, message: '请上传图片', trigger: 'change' }
  204. ],
  205. })
  206. setTimeout(() => {
  207. if (data.passcheck == '0') {
  208. rules.textedit[0].required = true;
  209. rules.fileupload[0].required = true;
  210. }
  211. uFormRef.value.setRules(rules);
  212. });
  213. if (workpresetjson.questionoption) $Http.getClass(workpresetjson.questionoption).then(res => {
  214. questionoption.value = res.data;
  215. if (res.code !== 1) return uni.showToast({ title: res.msg, icon: 'none' });
  216. })
  217. });
  218. // 保存
  219. const loading = ref(false);
  220. const loading1 = ref(false);
  221. function submit() {
  222. if (loading.value) return;
  223. if (upload.value.isUploading()) return;
  224. uFormRef.value.validate().then(valid => {
  225. if (valid) {
  226. let content = {
  227. "sa_workorderid": data.sa_workorderid,
  228. "sa_workorder_nodeid": data.sa_workorder_nodeid,
  229. isconfirm: 1,
  230. ...formToContent(form),
  231. traintitem: from.additem ? data.oldtitems.map(v => {
  232. return {
  233. itemid: v.itemid,
  234. itemname: v.itemname,
  235. model: v.model,
  236. price: v.price,
  237. qty: v.qty || v.packageqty || 1,
  238. }
  239. }) : []
  240. };
  241. uni.showModal({
  242. title: '提示',
  243. content: '是否确定完成工序?完成后将无法再次编辑。',
  244. confirmText: '完成',
  245. success: function (res) {
  246. if (res.confirm) {
  247. loading.value = true;
  248. $Http.basic({
  249. "id": "20230209094203",
  250. "sa_workorderid": data.sa_workorderid,
  251. "sa_workorder_nodeid": data.sa_workorder_nodeid,
  252. content
  253. }).then(res => {
  254. loading.value = false;
  255. console.log("提交工单", res);
  256. if (res.code == 1) {
  257. loading.value = true;
  258. upload.value.saveFileLinks('sa_workorder_node', data.sa_workorder_nodeid).then((s) => {
  259. loading.value = false;
  260. setTimeout(() => {
  261. uni.navigateBack()
  262. }, 800);
  263. })
  264. }
  265. uni.showToast({ title: res.code !== 1 ? res.msg : "提交成功", icon: 'none', mask: res.code == 1 });
  266. }).catch(err => {
  267. loading.value = false;
  268. console.error("提交工单失败", err);
  269. uni.showToast({ title: '提交失败,请稍后重试', icon: 'none' });
  270. });
  271. }
  272. }
  273. });
  274. }
  275. })
  276. }
  277. function save() {
  278. if (loading1.value) return;
  279. if (upload.value.isUploading()) return;
  280. let content = {
  281. "sa_workorderid": data.sa_workorderid,
  282. "sa_workorder_nodeid": data.sa_workorder_nodeid,
  283. isconfirm: 0,
  284. ...formToContent(form),
  285. traintitem: data.oldtitems.map(v => {
  286. return {
  287. itemid: v.itemid,
  288. itemname: v.itemname,
  289. model: v.model,
  290. price: v.price,
  291. qty: v.qty || v.packageqty || 1,
  292. }
  293. })
  294. };
  295. loading1.value = true;
  296. $Http.basic({
  297. "id": "20230209094203",
  298. "sa_workorderid": data.sa_workorderid,
  299. "sa_workorder_nodeid": data.sa_workorder_nodeid,
  300. content
  301. }).then(res => {
  302. loading1.value = false;
  303. console.log("保存工单", res);
  304. if (res.code == 1) {
  305. loading1.value = true;
  306. upload.value.saveFileLinks('sa_workorder_node', data.sa_workorder_nodeid).then((s) => {
  307. loading1.value = false;
  308. })
  309. }
  310. uni.showToast({ title: res.code !== 1 ? res.msg : "保存成功", icon: 'none' });
  311. }).catch(err => {
  312. loading1.value = false;
  313. console.error("保存工单失败", err);
  314. uni.showToast({ title: '保存失败,请稍后重试', icon: 'none' });
  315. });
  316. }
  317. function clickRadio(value, key) {
  318. if (data.status == '1') return;
  319. form[key] = form[key] == value ? "" : value;
  320. if (key == 'passcheck') {
  321. if (value == '0') {
  322. rules.textedit[0].required = true;
  323. rules.fileupload[0].required = true;
  324. } else {
  325. rules.textedit[0].required = workpresetjson.textedit == 11;
  326. rules.fileupload[0].required = workpresetjson.fileupload == 11;
  327. }
  328. uFormRef.value.setRules(rules);
  329. } else if (key == 'additem') {
  330. if (value == '1') {
  331. rules.oldtitems = [{ required: true, message: '请选择配件清单', trigger: 'change' }];
  332. } else {
  333. delete rules.oldtitems;
  334. }
  335. uFormRef.value.setRules(rules);
  336. }
  337. }
  338. function uploadCallback(list) {
  339. console.log("上传回调", list);
  340. form.fileupload = list.fileList.length ? '1' : '';
  341. console.log("form", form)
  342. }
  343. </script>
  344. <style lang="scss" scoped>
  345. .content {
  346. width: 100vw;
  347. padding: 20px;
  348. box-sizing: border-box;
  349. min-height: 100vh;
  350. background: #fff;
  351. .picker {
  352. width: 100%;
  353. // border-bottom: 1px solid #dadbde;
  354. font-size: 32rpx;
  355. color: #606266;
  356. padding: 9px;
  357. border-radius: 8rpx;
  358. }
  359. .title {
  360. font-size: 34rpx;
  361. color: #4773EE;
  362. margin: 20rpx 0;
  363. font-weight: bold;
  364. }
  365. .options-box {
  366. position: relative;
  367. top: -6rpx;
  368. display: flex;
  369. flex-wrap: wrap;
  370. width: 100%;
  371. box-sizing: border-box;
  372. .option {
  373. border: 1px solid #dadbde;
  374. border-radius: 8rpx;
  375. padding: 10rpx 20rpx;
  376. margin-right: 18rpx;
  377. margin-top: 12rpx;
  378. transition: background-color 0.3s, color 0.3s, border-color 0.3s;
  379. text-align: center;
  380. min-width: 80rpx;
  381. }
  382. .active {
  383. background: #006EF7;
  384. color: #fff;
  385. border-color: #006EF7;
  386. }
  387. }
  388. .but-box {
  389. display: flex;
  390. align-items: center;
  391. justify-content: space-around;
  392. margin-top: 40rpx;
  393. .but-box-item {
  394. width: 45%;
  395. }
  396. }
  397. }
  398. </style>