buildIncident.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. <template>
  2. <view class="buildIncident">
  3. <scroll-view scroll-y class="body">
  4. <view class="form_item">
  5. <view class="title select"><text class="required newicon newicon-bitian"></text>院区:</view>
  6. <uni-data-select class="value" v-model="incidentData.branch" :localdata="dataInfo.branchList" :clear="false" placeholder="请选择院区" :class="{formRed: isSubmit && !incidentData.branch}" @change="changeBranch"></uni-data-select>
  7. </view>
  8. <view class="form_item">
  9. <view class="title"><text class="required newicon newicon-bitian"></text>报修科室:</view>
  10. <view class="value category" @click="selectDepartment">
  11. <text class="categoryName ellipsis-multiline">{{incidentData.department ? incidentData.department.dept : ''}}</text>
  12. <text class="newicon newicon-weibiaoti2010104"></text>
  13. </view>
  14. </view>
  15. <view class="form_item">
  16. <view class="title select"><text class="required newicon newicon-bitian transparent"></text>报修人:</view>
  17. <uni-data-select readonly class="value" v-model="incidentData.requester" :localdata="dataInfo.requesterList" placeholder="请选择报修人"></uni-data-select>
  18. </view>
  19. <view class="form_item">
  20. <view class="title select"><text class="required newicon newicon-bitian transparent"></text>联系人:</view>
  21. <uni-easyinput class="value" v-model="incidentData.contacts" placeholder="请输入联系人" />
  22. </view>
  23. <view class="form_item">
  24. <view class="title select"><text class="required newicon newicon-bitian"></text>联系电话:</view>
  25. <uni-easyinput class="value" v-model="incidentData.contactsInformation" placeholder="请输入联系电话" :class="{formRed: isSubmit && !incidentData.contactsInformation.trim()}" />
  26. </view>
  27. <view class="form_item">
  28. <view class="title"><text class="required newicon newicon-bitian transparent"></text>楼栋楼层:</view>
  29. <view class="value category" @click="selectAreaPlace">
  30. <text class="categoryName ellipsis-multiline">{{incidentData.place ? incidentData.place.area.area + ' ' + incidentData.place.place : ''}}</text>
  31. <text class="newicon newicon-weibiaoti2010104"></text>
  32. </view>
  33. </view>
  34. <view class="form_item">
  35. <view class="title select"><text class="required newicon newicon-bitian transparent"></text>详细地址:</view>
  36. <uni-easyinput class="value" v-model="incidentData.houseNumber" placeholder="请输入详细地址" />
  37. </view>
  38. <view class="form_item">
  39. <view class="title"><text class="required newicon newicon-bitian"></text>故障现象:</view>
  40. <view class="value category" @click="selectCategory">
  41. <text class="categoryName ellipsis-multiline">{{incidentData.category ? incidentData.category.mutiCategory : ''}}</text>
  42. <text class="newicon newicon-weibiaoti2010104"></text>
  43. </view>
  44. </view>
  45. <view class="form_item">
  46. <view class="title select"><text class="required newicon newicon-bitian"></text>故障来源:</view>
  47. <uni-data-select readonly class="value" v-model="incidentData.source" :localdata="dataInfo.sourceList" placeholder="请选择故障来源" :class="{formRed: isSubmit && !incidentData.source}"></uni-data-select>
  48. </view>
  49. <view class="form_item">
  50. <view class="title select"><text class="required newicon newicon-bitian"></text>优先级:</view>
  51. <uni-data-select placement="top" readonly class="value" v-model="incidentData.priority" :localdata="dataInfo.priorityList" placeholder="请选择优先级" :class="{formRed: isSubmit && !incidentData.priority}"></uni-data-select>
  52. </view>
  53. <view class="form_item column">
  54. <view class="title select"><text class="required newicon newicon-bitian"></text>故障描述:</view>
  55. <uni-easyinput class="value" type="textarea" v-model="incidentData.description" placeholder="请输入故障描述" :class="{formRed: isSubmit && !incidentData.description.trim()}" />
  56. </view>
  57. <view class="form_item_column">
  58. <view class="form_item">
  59. <view class="title"><text class="required newicon newicon-bitian transparent"></text>报修图片:</view>
  60. <view class="value">
  61. <uni-file-picker ref="handlerImgRef" v-model="incidentData.repairImgList" limit="3" @success="handlerImgSuccess" @fail="handlerImgFail" @select="handlerImgSelect" @delete="handlerImgDelete"></uni-file-picker>
  62. </view>
  63. </view>
  64. <view class="form_item">
  65. <view class="title transparent"><text class="required newicon newicon-bitian transparent"></text>报修图片:</view>
  66. <view class="value">
  67. <text class="imgTips ellipsis">(支持JPG/PNG格式图片,单张大小10M以内)</text>
  68. </view>
  69. </view>
  70. </view>
  71. </scroll-view>
  72. <view class="foot_common_btns">
  73. <button @click="goBack" type="default" class="cancelButton btn">返回</button>
  74. <button @click="submit" type="default" class="primaryButton btn">下一步</button>
  75. </view>
  76. </view>
  77. </template>
  78. <script setup>
  79. import { ref, reactive } from 'vue'
  80. import { onLoad } from '@dcloudio/uni-app'
  81. import { api_user, api_branch, api_getDictionary, api_incidentTask } from "@/http/api.js"
  82. import { defaultColor } from '@/static/js/theme.js'
  83. import { useSetTitle } from '@/share/useSetTitle.js'
  84. import { useGoBack } from '@/share/useGoBack.js'
  85. import { useLoginUserStore } from '@/stores/loginUser'
  86. import { useIncidentBuildStore } from '@/stores/incidentBuild'
  87. import { useUploadFile } from '@/share/useUploadFile.js'
  88. useSetTitle();
  89. const loginUserStore = useLoginUserStore();
  90. const incidentBuildStore = useIncidentBuildStore();
  91. const { uploadFile } = useUploadFile();
  92. const { goBack } = useGoBack();
  93. // 主题颜色
  94. const primaryColor = ref(defaultColor)
  95. // 工单对象
  96. const incidentData = reactive({
  97. "deleteFlag": 0,
  98. "duty": undefined,
  99. "department": undefined,
  100. "contactsInformation": '',
  101. "contacts": '',
  102. "branch": undefined,
  103. "area": undefined,
  104. "place": undefined,
  105. "houseNumber": '',
  106. "category": undefined,
  107. "priority": undefined,
  108. "source": undefined,
  109. "title": '',
  110. "description": '',
  111. "repairType": undefined,
  112. "requester":undefined,
  113. "acceptUser": loginUserStore.loginUser.user,
  114. repairImgList: [],//报修图片列表
  115. })
  116. // 报修图片
  117. const handlerImgRef = ref(null)
  118. // 数据
  119. const dataInfo = reactive({
  120. branchList: [], //院区列表
  121. requesterList: [], //报修人列表
  122. sourceList: [], //故障来源列表
  123. priorityList: [], //优先级列表
  124. })
  125. // 是否提交
  126. const isSubmit = ref(false)
  127. // 上传报修图片成功
  128. function handlerImgSuccess(e){
  129. incidentData.repairImgList.forEach(v => {
  130. v.url = v.path;
  131. })
  132. console.log(incidentData.repairImgList);
  133. }
  134. // 上传报修图片失败
  135. function handlerImgFail(e){
  136. incidentData.repairImgList.forEach(v => {
  137. v.url = v.path;
  138. })
  139. console.log(incidentData.repairImgList);
  140. }
  141. // 选择上传图片
  142. function handlerImgSelect(e){
  143. incidentData.repairImgList = incidentData.repairImgList.concat(e.tempFiles);
  144. console.log(incidentData.repairImgList);
  145. }
  146. // 删除上传图片
  147. function handlerImgDelete(e){
  148. incidentData.repairImgList = incidentData.repairImgList.filter(v => e.tempFile.uuid != v.uuid);
  149. console.log(incidentData.repairImgList);
  150. }
  151. // 选择故障现象
  152. function selectCategory(){
  153. incidentBuildStore.setIncidentBuildData(incidentData, 'buildIncident');
  154. uni.navigateTo({
  155. url: `/pages/categoryOne/categoryOne`
  156. })
  157. }
  158. // 选择楼栋楼层
  159. function selectAreaPlace(){
  160. incidentBuildStore.setIncidentBuildData(incidentData, 'buildIncident');
  161. uni.navigateTo({
  162. url: `/pages/searchArea/searchArea`
  163. })
  164. }
  165. // 跳转到搜索报修科室
  166. function selectDepartment(){
  167. incidentBuildStore.setIncidentBuildData(incidentData, 'buildIncident');
  168. uni.navigateTo({
  169. url: `/pages/searchDept/searchDept`
  170. })
  171. }
  172. // 获取院区列表
  173. function getBranchs(){
  174. uni.showLoading({
  175. title: "加载中",
  176. mask: true,
  177. });
  178. let postData = {
  179. "idx": 0,
  180. "sum": 9999,
  181. };
  182. api_branch(postData).then(res => {
  183. uni.hideLoading();
  184. if(res.status == 200){
  185. res.list = res.list || [];
  186. dataInfo.branchList = res.list.map(v => ({
  187. text: v.hosName,
  188. value: v.id,
  189. }));
  190. if(!incidentBuildStore.incidentBuild.data){
  191. if(loginUserStore.loginUser.user.duty){
  192. // 当前的所属责任科室
  193. incidentData.branch = loginUserStore.loginUser.user.duty.branch;
  194. }else if(loginUserStore.loginUser.user.branch){
  195. // 当前的所属院区
  196. incidentData.branch = loginUserStore.loginUser.user.branch.id;
  197. }
  198. }
  199. }else{
  200. uni.showToast({
  201. icon: 'none',
  202. title: res.msg || '请求数据失败!'
  203. });
  204. }
  205. })
  206. }
  207. // 获取报修人列表
  208. function getRequesters(){
  209. uni.showLoading({
  210. title: "加载中",
  211. mask: true,
  212. });
  213. let postData = {
  214. "idx": 0,
  215. "sum": 9999,
  216. "user": {
  217. "engineer": undefined,
  218. }
  219. };
  220. api_user(postData).then(res => {
  221. uni.hideLoading();
  222. if(res.status == 200){
  223. res.list = res.list || [];
  224. dataInfo.requesterList = res.list.map(v => ({
  225. text: v.name,
  226. value: v.id,
  227. }));
  228. }else{
  229. uni.showToast({
  230. icon: 'none',
  231. title: res.msg || '请求数据失败!'
  232. });
  233. }
  234. })
  235. }
  236. // 获取故障来源列表
  237. function getSources(){
  238. uni.showLoading({
  239. title: "加载中",
  240. mask: true,
  241. });
  242. let postData = {
  243. "key": 'incident_source',
  244. "type": "list",
  245. };
  246. api_getDictionary(postData).then(res => {
  247. uni.hideLoading();
  248. res = res || [];
  249. dataInfo.sourceList = res.map(v => ({
  250. text: v.name,
  251. value: v.id,
  252. key: v.value,
  253. }));
  254. let discover = dataInfo.sourceList.find(v => v.key === 'discover');
  255. if(discover){
  256. incidentData.source = discover.value;
  257. }
  258. })
  259. }
  260. // 获取优先级列表
  261. function getPrioritys(){
  262. uni.showLoading({
  263. title: "加载中",
  264. mask: true,
  265. });
  266. let postData = {
  267. "key": 'incident_priority',
  268. "type": "list",
  269. };
  270. api_getDictionary(postData).then(res => {
  271. uni.hideLoading();
  272. res = res || [];
  273. dataInfo.priorityList = res.map(v => ({
  274. text: v.name,
  275. value: v.id,
  276. }));
  277. })
  278. }
  279. // 选择院区
  280. function changeBranch(){
  281. incidentData.department = undefined;
  282. incidentData.contactsInformation = '';
  283. incidentData.place = undefined;
  284. incidentData.houseNumber = undefined;
  285. }
  286. // 处理提交事件
  287. function handlerOrder(){
  288. let postData = {
  289. incident: dataInfo.incidentData,
  290. }
  291. postData.incident.handleDescription = dataInfo.handleDescription;
  292. postData.incident.handleCategory = {id: dataInfo.handleCategory};
  293. postData.incident.closecode = {id: dataInfo.closecode};
  294. postData.incident.category = dataInfo.category;
  295. postData.incident.synergetic = dataInfo.synergetic;
  296. return api_incidentTask('accept', postData);
  297. }
  298. // 报修图片
  299. function handlerOrderImg(imgObj){
  300. return uploadFile(imgObj, 'incident', dataInfo.incidentId)
  301. }
  302. // 提交
  303. function submit(){
  304. isSubmit.value = true;
  305. console.log(dataInfo);
  306. if(!incidentData.branch){
  307. uni.showToast({
  308. icon: 'none',
  309. title: '请选择院区'
  310. });
  311. return;
  312. }
  313. if(!incidentData.department){
  314. uni.showToast({
  315. icon: 'none',
  316. title: '请选择报修科室'
  317. });
  318. return;
  319. }
  320. if(!incidentData.contactsInformation.trim()){
  321. uni.showToast({
  322. icon: 'none',
  323. title: '请填写联系电话'
  324. });
  325. return;
  326. }
  327. if(!incidentData.category){
  328. uni.showToast({
  329. icon: 'none',
  330. title: '请选择故障现象'
  331. });
  332. return;
  333. }
  334. if(!incidentData.source){
  335. uni.showToast({
  336. icon: 'none',
  337. title: '请选择故障来源'
  338. });
  339. return;
  340. }
  341. if(!incidentData.priority){
  342. uni.showToast({
  343. icon: 'none',
  344. title: '请选择优先级'
  345. });
  346. return;
  347. }
  348. if(!incidentData.description.trim()){
  349. uni.showToast({
  350. icon: 'none',
  351. title: '请填写故障描述'
  352. });
  353. return;
  354. }
  355. console.log(incidentData);
  356. // 处理责任科室
  357. if(incidentData.category.branchType == 1){
  358. // 分院区
  359. if(incidentData.branch){
  360. let dutyConfig = incidentData.category.branchUserGroups.find(v=>v.branchId == incidentData.branch);
  361. if(dutyConfig && dutyConfig.dutyId && dutyConfig.dutyName){
  362. incidentData.duty = {id:dutyConfig.dutyId,dept:dutyConfig.dutyName};
  363. }else{
  364. incidentData.duty = undefined;
  365. }
  366. }else{
  367. incidentData.duty = undefined;
  368. }
  369. }else{
  370. // 不分院区
  371. incidentData.duty = incidentData.category.dutyDepartment;
  372. }
  373. incidentData.title = incidentData.category.category;
  374. incidentBuildStore.setIncidentBuildData(incidentData, 'buildIncident');
  375. uni.navigateTo({
  376. url: '/pages/assign/assign'
  377. })
  378. }
  379. onLoad((option) => {
  380. if(incidentBuildStore.incidentBuild.data){
  381. Object.assign(incidentData, incidentBuildStore.incidentBuild.data);
  382. // 修改报修科室,则回显楼栋,楼层,详细地址,联系电话
  383. if(!incidentData.place){
  384. incidentData.place = incidentData.department ? incidentData.department.place : undefined;
  385. }
  386. if(!incidentData.houseNumber){
  387. incidentData.houseNumber = incidentData.department ? incidentData.department.address : '';
  388. }
  389. if(!incidentData.contactsInformation){
  390. incidentData.contactsInformation = incidentData.department ? incidentData.department.phone : '';
  391. }
  392. }
  393. getBranchs();
  394. getRequesters();
  395. getSources();
  396. getPrioritys();
  397. })
  398. </script>
  399. <style lang="scss" scoped>
  400. .buildIncident{
  401. height: 100%;
  402. display: flex;
  403. flex-direction: column;
  404. justify-content: space-between;
  405. .body{
  406. padding: 0 24rpx;
  407. box-sizing: border-box;
  408. flex: 1;
  409. min-height: 0;
  410. .form_item{
  411. display: flex;
  412. align-items: center;
  413. padding-top: 24rpx;
  414. min-height: 86rpx;
  415. &.column{
  416. height: auto;
  417. flex-direction: column;
  418. align-items: flex-start;
  419. .title{
  420. margin-right: 0;
  421. }
  422. .value{
  423. margin-top: 10rpx;
  424. padding-left: 20rpx;
  425. box-sizing: border-box;
  426. }
  427. .tips{
  428. padding: 24rpx;
  429. text-align: center;
  430. font-size: 22rpx;
  431. color: #909399;
  432. width: 100%;
  433. box-sizing: border-box;
  434. }
  435. }
  436. .title{
  437. font-size: 26rpx;
  438. display: flex;
  439. align-items: center;
  440. margin-right: 12rpx;
  441. flex-shrink: 0;
  442. &.select{
  443. width: calc(5em + 20rpx);
  444. }
  445. }
  446. .value{
  447. width: 100%;
  448. &.category{
  449. width: 100%;
  450. display: flex;
  451. justify-content: space-between;
  452. align-items: center;
  453. .categoryName{
  454. font-size: 26rpx;
  455. color: #555;
  456. flex: 1;
  457. }
  458. .newicon-weibiaoti2010104{
  459. color: $uni-primary;
  460. margin-left: 24rpx;
  461. }
  462. }
  463. .imgTips{
  464. color: #909399;
  465. font-size: 22rpx;
  466. }
  467. }
  468. }
  469. }
  470. }
  471. </style>