inspectionValue.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. <template>
  2. <view class="inspectionValue">
  3. <scroll-view scroll-y class="body">
  4. <uni-forms ref="baseForm" :model="formValues" :rules="rules" class="form" label-position="top">
  5. <template v-for="(item, index) of baseFormData" :key="index">
  6. <!-- 下拉 -->
  7. <uni-forms-item v-if="item.type === '1'" class="formItem" :required="item.required" :name="item.key">
  8. <template v-slot:label>
  9. <view class="customLabelWrap">
  10. <text :class="{'is-required': item.required}">*</text><text class="customLabel">{{item.name}}</text><text v-if="item.isException" class="customLabel red">&nbsp;异</text>
  11. </view>
  12. </template>
  13. <uni-data-picker :placeholder="'请选择' + item.name" :popup-title="'请选择' + item.name" :localdata="item.list" v-model="formValues[item.key]" @change="changeForm()">
  14. </uni-data-picker>
  15. </uni-forms-item>
  16. <!-- 单选 -->
  17. <uni-forms-item v-if="item.type === '2'" class="formItem" :required="item.required" :name="item.key">
  18. <template v-slot:label>
  19. <view class="customLabelWrap">
  20. <text :class="{'is-required': item.required}">*</text><text class="customLabel">{{item.name}}</text><text v-if="item.isException" class="customLabel red">&nbsp;异</text>
  21. </view>
  22. </template>
  23. <uni-data-checkbox v-model="formValues[item.key]" @change="changeForm()" :localdata="item.list" />
  24. </uni-forms-item>
  25. <!-- 多选 -->
  26. <uni-forms-item v-if="item.type === '3'" class="formItem" :required="item.required" :name="item.key">
  27. <template v-slot:label>
  28. <view class="customLabelWrap">
  29. <text :class="{'is-required': item.required}">*</text><text class="customLabel">{{item.name}}</text><text v-if="item.isException" class="customLabel red">&nbsp;异</text>
  30. </view>
  31. </template>
  32. <uni-data-checkbox v-model="formValues[item.key]" @change="changeForm()" multiple :localdata="item.list" />
  33. </uni-forms-item>
  34. <!-- 数字 -->
  35. <uni-forms-item v-if="item.type === '4'" class="formItem" :required="item.required" :name="item.key">
  36. <template v-slot:label>
  37. <view class="customLabelWrap">
  38. <text :class="{'is-required': item.required}">*</text><text class="customLabel">{{item.name}}</text><text v-if="item.isException" class="customLabel red">&nbsp;异</text>
  39. </view>
  40. </template>
  41. <uni-number-box v-model="formValues[item.key]" @change="changeForm()" :min="-9999" :max="9999" :placeholder="'请输入' + item.name"></uni-number-box>
  42. </uni-forms-item>
  43. <!-- 单行 -->
  44. <uni-forms-item v-if="item.type === '5' && item.isException" class="formItem" :label="item.name" :required="item.required" :name="item.key">
  45. <uni-easyinput style="padding-top: 8px;" v-model="formValues[item.key]" :placeholder="'请输入' + item.name" />
  46. </uni-forms-item>
  47. <!-- 多行 -->
  48. <uni-forms-item v-if="item.type === '6' && item.isException" class="formItem" :label="item.name" :required="item.required" :name="item.key">
  49. <uni-easyinput type="textarea" v-model="formValues[item.key]" :placeholder="'请输入' + item.name" />
  50. </uni-forms-item>
  51. <!-- 图片上传 -->
  52. <uni-forms-item v-if="item.type === '7' && item.isException" class="formItem" :label="item.name" :required="item.required" :name="item.key">
  53. <DsFilePicker :extra="item.id" :inspectionExecuteId="inspectionExecuteId" :ref="(el) => itemRefs[item.id] = el"></DsFilePicker>
  54. </uni-forms-item>
  55. <!-- 分割线 -->
  56. <view class="detail_head" v-if="item.type === '8'">
  57. <text class="title">{{ item.name }}</text>
  58. </view>
  59. </template>
  60. </uni-forms>
  61. </scroll-view>
  62. <view class="foot_common_btns">
  63. <button @click="goBack" type="default" class="cancelButton btn">返回</button>
  64. <button @click="submit" type="default" class="primaryButton btn">保存</button>
  65. </view>
  66. </view>
  67. </template>
  68. <script setup>
  69. import fromPairs from 'lodash-es/fromPairs'
  70. import keyBy from 'lodash-es/keyBy'
  71. import DsFilePicker from '@/components/DsFilePicker.vue';
  72. import { ref, reactive, nextTick } from 'vue'
  73. import { onLoad } from '@dcloudio/uni-app'
  74. import { api_addModel, api_getDictionary } from "@/http/api.js"
  75. import { defaultColor } from '@/static/js/theme.js'
  76. import { useSetTitle } from '@/share/useSetTitle.js'
  77. import { useMakePhoneCall } from '@/share/useMakePhoneCall.js'
  78. import { useGoBack } from '@/share/useGoBack.js'
  79. import { useLoginUserStore } from '@/stores/loginUser'
  80. import { useInspectionValueStore } from '@/stores/inspectionValue'
  81. import { forIn } from 'lodash-es';
  82. import { useIncidentBuildStore } from '@/stores/incidentBuild'
  83. import { useUploadFile } from '@/share/useUploadFile.js'
  84. useSetTitle();
  85. const loginUserStore = useLoginUserStore();
  86. const { goBack } = useGoBack();
  87. const inspectionValueStore = useInspectionValueStore();
  88. const incidentBuildStore = useIncidentBuildStore();
  89. const { uploadFile } = useUploadFile();
  90. // 主题颜色
  91. const primaryColor = ref(defaultColor)
  92. // 所有页码数据
  93. const formPageList = reactive([]);
  94. // 故障来源列表
  95. const defaultSourceValue = ref();
  96. // 表单
  97. const baseForm = ref()
  98. // 图片上传ref数组
  99. const itemRefs = ref({});
  100. const inspectionExecuteId = ref()
  101. // 数据-原始
  102. const dataInfo = reactive({})
  103. // 数据-检验
  104. const rules = reactive({})
  105. // 数据-填写值
  106. const formValues = reactive({})
  107. // 表单数据-渲染
  108. // 下拉框 1
  109. // 单选 2
  110. // 多选 3
  111. // 数值 4
  112. // 单行文本 5
  113. // 多行文本 6
  114. // 照片上传 7
  115. // 分割线 8
  116. const baseFormData = reactive([
  117. // { type: 1, name: '', value: '', list: [], required: false, checkType: 0, valueMin: '', valueMax: '', },
  118. // { type: 2, name: '', value: '', list: [], required: false, checkType: 0, valueMin: '', valueMax: '', },
  119. // { type: 3, name: '', value: [], list: [], required: false, checkType: 0, valueMin: '', valueMax: '', },
  120. // { type: 4, name: '', value: '', list: [], required: false, checkType: 0, valueMin: '', valueMax: '', },
  121. // { type: 5, name: '', value: '', list: [], required: false, checkType: 0, valueMin: '', valueMax: '', },
  122. // { type: 6, name: '', value: '', list: [], required: false, checkType: 0, valueMin: '', valueMax: '', },
  123. // { type: 7, name: '', value: [], list: [], required: false, checkType: 0, valueMin: '', valueMax: '', },
  124. ])
  125. // 修改
  126. function changeForm(){
  127. handleData(true);
  128. }
  129. // 跳转巡检列表
  130. function toInspectionExecute(){
  131. inspectionValueStore.clearInspectionValueData();
  132. uni.reLaunch({
  133. url: `/pages/inspection/inspectionExecute/inspectionExecute`
  134. })
  135. }
  136. // 获取故障来源列表
  137. function getSources(){
  138. let postData = {
  139. "key": 'incident_source',
  140. "type": "list",
  141. };
  142. api_getDictionary(postData).then(res => {
  143. res = res || [];
  144. let discover = res.find(v => v.value === 'inspection');
  145. if(discover){
  146. defaultSourceValue.value = discover.id;
  147. }
  148. })
  149. }
  150. // 跳转新建事件
  151. function toBuildIncident(res){
  152. let imgList = Object.values(itemRefs.value).filter(Boolean);
  153. let repairImgList = [];
  154. if(imgList.length){
  155. let firstOne = baseFormData.find(v => v.type == '7');
  156. let index = imgList.findIndex(v => v.extra == firstOne.id);
  157. repairImgList = index > -1 ? imgList[index].baseFormData.handlerImgList : [];
  158. }
  159. let incidentData = {
  160. place: res.inspectionNode.floorDTO,
  161. houseNumber: res.inspectionNode.address,
  162. source: defaultSourceValue.value,
  163. description: res.inspectionValuesList.filter(v => v.exception == 1).map(v => `${v.name}填写值为${v.valuex ? v.valuex : (v.formItemConfigList ? v.formItemConfigList.map(vv => vv.name).join(',') : '')}`).join(';'),
  164. requester: loginUserStore.loginUser.user,
  165. branch: loginUserStore.loginUser.user.currentHospital.parent ? loginUserStore.loginUser.user.currentHospital.parent.id : loginUserStore.loginUser.user.currentHospital.id,
  166. contacts: loginUserStore.loginUser.user.name,
  167. contactsInformation: loginUserStore.loginUser.user.phone,
  168. category: res.inspectionForm.categoryDTO,
  169. department: res.inspectionForm.repairDeptDTO,
  170. priority: res.inspectionForm.priorityDTO,
  171. repairImgList,
  172. inspectionTaskId: inspectionExecuteId.value,
  173. }
  174. console.log(repairImgList, 'repairImgList')
  175. console.log(incidentData, 'incidentData')
  176. incidentBuildStore.setIncidentBuildData(incidentData, 'buildIncident');
  177. inspectionValueStore.clearInspectionValueData();
  178. uni.navigateTo({
  179. url: `/pages/buildIncident/buildIncident?type=inspection`
  180. })
  181. }
  182. // 报修图片
  183. function repairOrderImg(imgObj, incidentId){
  184. return uploadFile(imgObj, 'wechatRequesterIncident', incidentId, incidentId)
  185. }
  186. // 保存
  187. function submit(){
  188. console.log(itemRefs.value);
  189. console.log(formValues);
  190. console.log(baseFormData);
  191. // 处理图片上传检验问题
  192. Object.values(itemRefs.value).forEach(v => {
  193. if(v && v.baseFormData.handlerImgList.length){
  194. baseFormData.forEach(vv => {
  195. if(vv.id == v.extra){
  196. formValues[vv.key] = v.inspectionExecuteId;
  197. vv.value = v.inspectionExecuteId;
  198. }
  199. })
  200. }
  201. })
  202. nextTick(() => {
  203. baseForm.value.validate().then(res => {
  204. console.log('success', res);
  205. uni.showLoading({
  206. title: "加载中",
  207. mask: true,
  208. });
  209. console.log(formValues);
  210. let imgList = Object.values(itemRefs.value).filter(Boolean);
  211. let repairImgList = [];
  212. if(imgList.length){
  213. let firstOne = baseFormData.find(v => v.type == '7');
  214. let index = imgList.findIndex(v => v.extra == firstOne.id);
  215. repairImgList = index > -1 ? imgList[index].baseFormData.handlerImgList : [];
  216. }
  217. let postData = {
  218. account: loginUserStore.loginUser.user.account,
  219. valuesList: [],
  220. inspectionPhotos: repairImgList.length ? repairImgList : undefined,
  221. };
  222. // baseFormData
  223. for(let key in formValues){
  224. let obj = baseFormData.find(v => v.key === key);
  225. if(!((obj.type === '5' && !obj.isException) || (obj.type === '6' && !obj.isException) || (obj.type === '7' && !obj.isException))){
  226. let name = obj.name;
  227. let itemId = obj.id;
  228. let _formPageList = dataInfo.inspectionFormDTO?.formPageList || [];
  229. _formPageList = _formPageList.map(v => v.formItemList).flat();
  230. let formItem = _formPageList.find(v => v.id === itemId);
  231. postData.valuesList.push({
  232. taskId: inspectionExecuteId.value,
  233. nodeId: dataInfo.id,
  234. formId: dataInfo.inspectionFormDTO.id,
  235. itemId: formItem.id,
  236. pageId: formItem.pageId,
  237. orders: formItem.orders,
  238. name,
  239. valuex: (formItem.type.value === '1' || formItem.type.value === '2' || formItem.type.value === '3') ? '' : formValues[key].toString(),
  240. configIds: (formItem.type.value === '1' || formItem.type.value === '2' || formItem.type.value === '3') ? formValues[key].toString() : undefined,
  241. hosId: dataInfo.inspectionFormDTO.hosId,
  242. })
  243. }
  244. }
  245. console.log(postData);
  246. console.log(itemRefs.value);
  247. // return;
  248. api_addModel(postData).then((res) => {
  249. uni.hideLoading();
  250. if (res.status == 200) {
  251. Object.values(itemRefs.value).forEach(v => {
  252. v && v.uploadFn();
  253. })
  254. if(res.exception){
  255. // 异常
  256. if(res.inspectionForm.createOrder == 1){
  257. // 是否自动生成维修单
  258. uni.showModal({
  259. title: '提示',
  260. content: `巡检提交成功,您巡检有产生异常;系统自动生成工单:${res.incidentSign}`,
  261. showCancel: false,
  262. confirmText: '返回巡检列表',
  263. success: (res) => {
  264. if (res.confirm) {
  265. toInspectionExecute();
  266. }
  267. }
  268. });
  269. // 上传图片到故障工单
  270. let requestList = [];
  271. repairImgList.map((imgObj) => {
  272. let repairOrderImg$ = repairOrderImg(imgObj, res.incidentId);
  273. requestList.push(repairOrderImg$);
  274. })
  275. Promise.all(requestList).then(resList => {})
  276. } else if(res.inspectionForm.showOrder == 1){
  277. // 是否显示生成维修单
  278. uni.showModal({
  279. title: '提示',
  280. content: '巡检提交成功,您巡检有产生异常,是否生成维修单',
  281. confirmText: '生成维修单',
  282. cancelText: '返回巡检列表',
  283. success: (result) => {
  284. if (result.confirm) {
  285. toBuildIncident(res);
  286. } else if (result.cancel) {
  287. toInspectionExecute();
  288. }
  289. }
  290. });
  291. } else {
  292. uni.showToast({
  293. icon: 'none',
  294. title: "巡检提交成功,有异常",
  295. duration: 2000,
  296. mask: true,
  297. })
  298. setTimeout(() => {
  299. toInspectionExecute();
  300. }, 2000)
  301. }
  302. }else{
  303. // 无异常
  304. uni.showToast({
  305. icon: 'none',
  306. title: "巡检提交成功,无异常",
  307. duration: 2000,
  308. mask: true,
  309. })
  310. setTimeout(() => {
  311. toInspectionExecute();
  312. }, 2000)
  313. }
  314. } else if(res.status == 555){
  315. // 自动生成维修单失败
  316. uni.showModal({
  317. title: '提示',
  318. content: '巡检提交成功,您巡检有产生异常;系统自动生成工单失败,请手动建单',
  319. confirmText: '生成维修单',
  320. cancelText: '返回巡检列表',
  321. success: (result) => {
  322. if (result.confirm) {
  323. toBuildIncident(res);
  324. } else if (result.cancel) {
  325. toInspectionExecute();
  326. }
  327. }
  328. });
  329. } else {
  330. uni.showToast({
  331. icon: 'none',
  332. title: res.msg || '请求数据失败!'
  333. });
  334. }
  335. });
  336. }).catch(err => {
  337. console.log('err', err);
  338. })
  339. })
  340. }
  341. // 处理数据
  342. function handleData(isException = false){
  343. // 目前只取第一页
  344. let firstPage = formPageList[0]?.formItemList || [];
  345. firstPage = firstPage.filter( v => v.display === 1);
  346. firstPage = firstPage.map((v, i) => {
  347. let value = '';
  348. v.formItemConfigList = v.formItemConfigList || [];
  349. // value
  350. if(v.type.value === '3'){
  351. // 多选
  352. let arr = v.formItemConfigList.filter(v => v.checkDefault === 1);
  353. value = arr.length ? arr.map(v => v.id) : [];
  354. console.log('多选', value)
  355. } else if(v.type.value === '7'){
  356. // 图片
  357. value = [];
  358. } else if(v.type.value === '1' || v.type.value === '2') {
  359. // 单选或下拉
  360. let defaultValue = v.formItemConfigList.find(v => v.checkDefault === 1);
  361. value = defaultValue ? defaultValue.id : '';
  362. console.log('单选或下拉', value)
  363. } else{
  364. // 其他
  365. value = v.defaultValue;
  366. }
  367. return {
  368. id: v.id,
  369. key: `field${i}`,
  370. type: v.type.value,
  371. name: v.name,
  372. value: isException ? formValues[`field${i}`] : value,
  373. list: v.formItemConfigList ? v.formItemConfigList.map(v => ({text: v.name, value: v.id, checkException: v.checkException, uncheckException: v.uncheckException})) : [],
  374. required: v.required === 1,
  375. checkType: v.checkType,
  376. showError: v.showError,
  377. orders: v.orders,
  378. valueMin: v.checkType === 2 ? v.valueLow : ( v.checkType === 1 ? (v.valuex - v.valueGap) : undefined),
  379. valueMax: v.checkType === 2 ? v.valueUp : ( v.checkType === 1 ? (v.valuex + v.valueGap) : undefined),
  380. }
  381. });
  382. let firstPageBottom = firstPage.filter(v => v.type === '5' || v.type === '6' || v.type === '7');
  383. firstPage = firstPage.filter(v => v.type !== '5' && v.type !== '6' && v.type !== '7');
  384. // 其他项
  385. if(!isException){
  386. console.log(firstPage, 'firstPage')
  387. console.log(formValues, 'formValues')
  388. console.log(isException, 'isException')
  389. firstPage.forEach(v => {
  390. // 下拉,单选
  391. if(v.type === '1' || v.type === '2'){
  392. let obj = v.list.find(vv => v.value === vv.value);
  393. v.isException = obj ? obj.checkException === 1 : false;
  394. } else if(v.type === '3'){
  395. // 多选
  396. v.isException = v.list.some(vv => {
  397. if(v.value.includes(vv.value)){
  398. return vv.checkException === 1;
  399. }else{
  400. return false;
  401. }
  402. })
  403. } else if(v.type === '4'){
  404. v.isException = (v.value < v.valueMin) || (v.value > v.valueMax);
  405. }
  406. })
  407. }else{
  408. firstPage.forEach(v => {
  409. if(v.type === '1' || v.type === '2'){
  410. // 下拉,单选
  411. let obj = v.list.find(vv => v.value === vv.value);
  412. v.isException = obj ? obj.checkException === 1 : false;
  413. } else if(v.type === '3'){
  414. // 多选
  415. v.isException = v.list.some(vv => {
  416. if(v.value.includes(vv.value)){
  417. return vv.checkException === 1;
  418. }else{
  419. return false;
  420. }
  421. })
  422. } else if(v.type === '4'){
  423. // 数值
  424. v.isException = (formValues[v.key] < v.valueMin) || (formValues[v.key] > v.valueMax);
  425. }
  426. })
  427. }
  428. // 单行|多行|图片上传
  429. let someIsException = firstPage.filter(v => v.type !== '8').some(v => v.isException);
  430. console.log('someIsException=>', someIsException)
  431. firstPageBottom.forEach(v => {
  432. console.log('v.showError=>', v.showError)
  433. v.isException = (v.showError === 1 && someIsException) || v.showError === 0;
  434. })
  435. firstPage = firstPage.concat(firstPageBottom).sort((a, b) => a.orders - b.orders);
  436. console.log('firstPage=>', firstPage);
  437. Object.assign(baseFormData, firstPage);
  438. console.log('baseFormData=>', baseFormData);
  439. Object.assign(formValues, fromPairs(firstPage.filter(v => v.type !== '8').map(v => ([v.key, v.value]))));
  440. console.log('formValues=>', formValues);
  441. let rulesObj = keyBy(firstPage.filter(v => v.type !== '8'), 'key');
  442. console.log(rulesObj)
  443. for(let key in rulesObj){
  444. rulesObj[key] = {
  445. rules: [
  446. { required: rulesObj[key].required, errorMessage: `${rulesObj[key].name}不能为空` }
  447. ]
  448. }
  449. }
  450. Object.assign(rules, rulesObj);
  451. console.log('rules=>', rules);
  452. }
  453. onLoad((option) => {
  454. getSources();
  455. inspectionExecuteId.value = +option.inspectionExecuteId;
  456. // 巡检项
  457. if(inspectionValueStore.inspectionValue.data){
  458. Object.assign(dataInfo, inspectionValueStore.inspectionValue.data);
  459. Object.assign(formPageList, dataInfo.inspectionFormDTO?.formPageList || []);
  460. handleData()
  461. }
  462. })
  463. </script>
  464. <style lang="scss" scoped>
  465. .customLabelWrap{
  466. .is-required{
  467. color: #dd524d;
  468. font-weight: bold;
  469. margin-top: 8rpx;
  470. }
  471. }
  472. ::v-deep .uni-modal__btn_primary{
  473. color: $uni-primary!important;
  474. }
  475. .inspectionValue{
  476. height: 100%;
  477. display: flex;
  478. flex-direction: column;
  479. justify-content: space-between;
  480. .body{
  481. box-sizing: border-box;
  482. flex: 1;
  483. min-height: 0;
  484. padding-bottom: 24rpx;
  485. .formItem{
  486. padding: 32rpx 24rpx 0;
  487. margin-bottom: 0;
  488. }
  489. ::v-deep .uni-forms-item__label{
  490. width: auto!important;
  491. padding: 0!important;
  492. height: auto!important;
  493. align-items: flex-start!important;
  494. }
  495. .detail_head{
  496. padding: 24rpx;
  497. border-top: 1rpx solid #D2D2D2;
  498. border-bottom: 1rpx solid #D2D2D2;
  499. display: flex;
  500. justify-content: space-between;
  501. align-items: center;
  502. margin-top: 24rpx;
  503. &:first-of-type{
  504. border-top: none;
  505. margin-top: 0;
  506. }
  507. .title{
  508. font-size: 26rpx;
  509. color: $uni-primary;
  510. padding-left: 18rpx;
  511. position: relative;
  512. &:before{
  513. content: '';
  514. width: 8rpx;
  515. height: 25rpx;
  516. background-color: $uni-primary;
  517. position: absolute;
  518. left: 0;
  519. top: 50%;
  520. transform: translateY(-50%);
  521. }
  522. }
  523. }
  524. }
  525. }
  526. </style>