flowForm.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. <template>
  2. <view class="flowBefore-v">
  3. <div class="flow-urgent-value" :style="{'background-color':flowUrgentList[selectflowUrgent.extra].bgColor}"
  4. @click="handleShowSelect">
  5. <span :style="{'color':flowUrgentList[selectflowUrgent.extra].color}">{{selectflowUrgent.label}}</span>
  6. </div>
  7. <view class="flowBefore-box">
  8. <view class="scroll-v" scroll-y>
  9. <childForm ref="child" :config="config" @eventReceiver="eventReceiver" v-if="!loading"
  10. @setBtnLoad="setBtnLoad" :key="childFormKey" />
  11. <ErrorForm @submitErrorForm="submitErrorForm" ref="ErrorForm" />
  12. <RecordTimeList :progressList="progressList" :taskInfo="taskInfo" v-if="getShowExtraPanel"
  13. :commentList="commentList" :taskId="config.opType==0 ? config.id:config.taskId" ref="RecordTimeList"
  14. :hasComment="hasComment">
  15. </RecordTimeList>
  16. </view>
  17. </view>
  18. <u-select :list="flowUrgentList" v-model="showFlowUrgent" @confirm="seltConfirm"
  19. :default-value="defaultValue" />
  20. <uni-popup mode="bottom" ref="reduceApprover" background-color='#fff'>
  21. <view class="approverContent">
  22. <view class="notice-warp">
  23. <view class="u-flex close-icon">
  24. <u-icon name="close" size="32" @click="hideReduceApprover" color="#93969c"></u-icon>
  25. </view>
  26. <view class="search-box">
  27. <u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
  28. :show-action="false" @change="getAddSignUserList" bg-color="#f0f2f6" shape="square" />
  29. </view>
  30. </view>
  31. <view class="popup">
  32. <view v-for="(item, index) in signUserIdList" :key="index" v-if="signUserIdList.length"
  33. class="list-box">
  34. <view class="u-flex item">
  35. <view class="u-flex" style="flex: 1;">
  36. <u-avatar :src="define.baseURL+item.headIcon"></u-avatar>
  37. <view class="u-m-l-10">
  38. <view>{{item.fullName}}</view>
  39. <view>{{item.organize}}</view>
  40. </view>
  41. </view>
  42. <view class="" @click="deleteReduce(item.id)">
  43. <u-icon name="trash" size="32" color="#93969c"></u-icon>
  44. </view>
  45. </view>
  46. </view>
  47. <NoData v-else backgroundColor="#fff"></NoData>
  48. </view>
  49. </view>
  50. </uni-popup>
  51. </view>
  52. </template>
  53. <script>
  54. import NoData from '@/components/noData'
  55. import {
  56. Create,
  57. Update
  58. } from '@/api/workFlow/workFlowForm'
  59. import {
  60. FlowTask,
  61. Audit,
  62. Reject,
  63. Transfer,
  64. saveAudit,
  65. saveAssist,
  66. AddSignUserIdList,
  67. ReduceApprover,
  68. Candidates,
  69. RejectList,
  70. FreeApprover,
  71. launchRecall,
  72. auditRecall,
  73. cancel,
  74. SignFor,
  75. Transact,
  76. sendBack,
  77. back,
  78. Assist
  79. } from '@/api/workFlow/flowBefore'
  80. import {
  81. Revoke,
  82. Press
  83. } from '@/api/workFlow/flowLaunch'
  84. import {
  85. createModel,
  86. updateModel
  87. } from '@/api/apply/visualDev'
  88. import {
  89. createComment
  90. } from '@/api/workFlow/flowEngine'
  91. import {
  92. checkInfo
  93. } from '@/api/message.js'
  94. import resources from '@/libs/resources.js'
  95. import childForm from './form.vue'
  96. import RecordTimeList from '../components/RecordTimeList'
  97. import ErrorForm from '../components/ErrorForm'
  98. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  99. import {
  100. useUserStore
  101. } from '@/store/modules/user'
  102. export default {
  103. mixins: [MescrollMixin],
  104. components: {
  105. childForm,
  106. ErrorForm,
  107. RecordTimeList,
  108. NoData
  109. },
  110. data() {
  111. return {
  112. childFormKey: +new Date(),
  113. todoBtnList: [],
  114. signUserIdList: [],
  115. keyword: '',
  116. formLoding: false,
  117. loading: false,
  118. taskInfo: {},
  119. backNodeList: [],
  120. btnInfo: [],
  121. nodeList: [],
  122. handleStatus: 1,
  123. downOption: {
  124. use: true,
  125. auto: true
  126. },
  127. upOption: {
  128. page: {
  129. num: 0,
  130. size: 20,
  131. time: null
  132. },
  133. empty: {
  134. use: true,
  135. icon: resources.message.nodata,
  136. tip: this.$t('common.noData'),
  137. fixed: true,
  138. top: "300rpx",
  139. },
  140. textNoMore: this.$t('app.apply.noMoreData'),
  141. },
  142. isComment: false,
  143. isSummary: false,
  144. show: false,
  145. config: {},
  146. currentView: '',
  147. formData: {},
  148. flowFormInfo: {},
  149. flowTemplateInfo: {},
  150. flowTaskNodeList: [],
  151. flowTemplateJson: [],
  152. recordList: [],
  153. properties: {},
  154. flowStatus: '',
  155. btnLoading: false,
  156. commentList: [],
  157. processId: "",
  158. candidateList: [],
  159. summaryType: 0,
  160. title: '',
  161. selectflowUrgent: {
  162. extra: '0',
  163. label: '普通',
  164. value: 1,
  165. },
  166. showFlowUrgent: false,
  167. defaultValue: [0],
  168. flowUrgent: 1,
  169. flowUrgentList: [{
  170. label: '普通',
  171. color: '#409EFF',
  172. bgColor: '#e5f3fe',
  173. value: 1,
  174. extra: '0'
  175. },
  176. {
  177. label: '重要',
  178. color: '#E6A23C',
  179. bgColor: '#fef6e5',
  180. value: 2,
  181. extra: '1'
  182. },
  183. {
  184. label: '紧急',
  185. color: '#F56C6C',
  186. bgColor: '#fee5e5',
  187. value: 3,
  188. extra: '2'
  189. },
  190. ],
  191. hasComment: false,
  192. progressList: []
  193. };
  194. },
  195. computed: {
  196. baseURL() {
  197. return this.define.baseURL
  198. },
  199. getShowExtraPanel() {
  200. return this.config.opType != '-1' && !this.loading
  201. }
  202. },
  203. methods: {
  204. init(data) {
  205. this.config = data
  206. this.config.origin = 'scan'
  207. this.processId = this.config.id
  208. /**
  209. * opType
  210. * -1 - 我发起的新建/编辑
  211. * 0 - 我发起的详情
  212. * 1 - 待办事宜
  213. * 2 - 已办事宜
  214. * 3 - 抄送事宜
  215. */
  216. this.getBeforeInfo(this.config)
  217. },
  218. handlePreviewImage(url) {
  219. // #ifdef H5
  220. uni.previewImage({
  221. urls: [url],
  222. current: url,
  223. success: () => {},
  224. fail: () => {
  225. uni.showToast({
  226. title: '预览图片失败',
  227. icon: 'none'
  228. });
  229. }
  230. });
  231. // #endif
  232. },
  233. getBeforeInfo() {
  234. let config = this.config;
  235. this.formData.flowId = config.flowId;
  236. this.loading = true;
  237. const query = {
  238. flowId: config.flowId, // 流程大Id
  239. opType: config.opType == 2 ? 3 : config.opType, //特殊:待办点击开始办理需要跳到在办页面
  240. };
  241. if (config.opType != "-1" && config.opType != '0') query.operatorId = config.operatorId;
  242. FlowTask(config?.taskId || config?.id || 0, query).then((res) => {
  243. this.flowInfo = res.data.flowInfo || {};
  244. this.formInfo = res.data.formInfo || {};
  245. this.taskInfo = res.data.taskInfo || {};
  246. this.btnInfo = res.data.btnInfo || [];
  247. this.progressList = res.data.progressList || [];
  248. config.formOperates = res.data.formOperates || [];
  249. config.formType = this.formInfo.type
  250. const fullName =
  251. config.opType == "-1" ?
  252. this.flowInfo.fullName :
  253. this.taskInfo.fullName;
  254. config.fullName = fullName;
  255. this.title = this.flowInfo.fullName;
  256. this.thisStep = this.taskInfo.thisStep || "";
  257. if (config.status !== 0 && config.status !== 3) {
  258. this.title = this.thisStep ?
  259. config.fullName + "/" + this.thisStep :
  260. config.fullName;
  261. }
  262. config.type = this.flowInfo.type;
  263. config.draftData = res.data.draftData || null;
  264. config.formData = res.data.formData || {};
  265. config.formEnCode = this.formInfo.enCode;
  266. this.nodeList = res.data.nodeList || [];
  267. this.properties = res.data.nodeProperties || {};
  268. this.recordList = (res.data.recordList || []).reverse();
  269. config.formConf = this.formInfo.formData;
  270. this.hasComment = this.flowInfo.flowNodes.global.hasComment;
  271. this.loading = false;
  272. this.formLoding = true;
  273. uni.setNavigationBarTitle({
  274. title: this.flowInfo.fullName,
  275. });
  276. if (config.formRecords && config.title) {
  277. uni.setNavigationBarTitle({
  278. title: config.title,
  279. });
  280. }
  281. this.flowUrgent = this.taskInfo.flowUrgent || 1;
  282. const getSelectInfo = () => {
  283. var obj = {
  284. value: this.flowUrgent,
  285. extra: "0",
  286. label: "普通",
  287. };
  288. this.flowUrgentList.forEach((e, i) => {
  289. if (e.value == this.flowUrgent) {
  290. obj.extra = i;
  291. obj.label = e.label;
  292. }
  293. });
  294. return obj;
  295. };
  296. this.selectflowUrgent = getSelectInfo();
  297. if (config.opType != "-1" && config.opType != "3") config.readonly =
  298. true;
  299. config.formOperates = [];
  300. if (config.opType == 0) {
  301. if (this.properties && this.properties && this.properties.formOperates) config
  302. .formOperates = this.properties.formOperates || [];
  303. } else {
  304. config.formOperates = res.data.formOperates || [];
  305. }
  306. setTimeout(() => {
  307. this.$nextTick(() => {
  308. if (!this.$refs.child || !this.$refs.child.$refs.form) {
  309. uni.showToast({
  310. title: "暂无此流程表单",
  311. icon: "none",
  312. complete: () => {
  313. setTimeout(() => {
  314. uni.navigateBack();
  315. }, 1500);
  316. },
  317. });
  318. return;
  319. }
  320. this.$refs.child.$refs.form.init(config)
  321. });
  322. }, 100);
  323. this.config = config;
  324. });
  325. }
  326. }
  327. }
  328. </script>
  329. <style lang="scss">
  330. page {
  331. background-color: #f0f2f6;
  332. height: 100%;
  333. }
  334. .flow-urgent-value {
  335. position: fixed;
  336. top: var(--window-top);
  337. width: 100%;
  338. z-index: 99;
  339. display: flex;
  340. align-items: center;
  341. justify-content: center;
  342. height: 60rpx;
  343. font-size: 28rpx;
  344. }
  345. .flowBefore-v {
  346. display: flex;
  347. flex-direction: column;
  348. margin-top: 60rpx;
  349. .workFlowTitle {
  350. width: 100%;
  351. padding: 0 32rpx 32rpx 32rpx;
  352. background-color: #FFFFFF;
  353. font-size: 32rpx;
  354. font-weight: 700;
  355. white-space: pre-wrap;
  356. text-align: left;
  357. }
  358. .flowBefore-box {
  359. height: 100%;
  360. flex: 1;
  361. display: flex;
  362. flex-direction: column;
  363. overflow: hidden;
  364. padding-bottom: 3.3rem;
  365. .sticky-box {
  366. z-index: 500;
  367. }
  368. }
  369. .swiper-box {
  370. height: 100vh;
  371. }
  372. .swiper-item {
  373. flex: 1;
  374. flex-direction: row;
  375. }
  376. .scroll-v {
  377. flex: 1;
  378. /* #ifndef MP-ALIPAY */
  379. flex-direction: column;
  380. /* #endif */
  381. width: 100%;
  382. height: 100%;
  383. }
  384. .flowStatus {
  385. position: absolute;
  386. top: 90rpx;
  387. right: 0;
  388. border: 0;
  389. margin: 20rpx;
  390. opacity: 0.7;
  391. z-index: 999;
  392. image {
  393. width: 200rpx;
  394. }
  395. }
  396. .discuss_btn {
  397. background-color: #fff;
  398. position: fixed;
  399. bottom: 0;
  400. display: flex;
  401. width: 100%;
  402. // height: 88rpx;
  403. // box-shadow: 0 -2rpx 8rpx #e1e5ec;
  404. z-index: 20;
  405. .custom-style {
  406. background-color: #2979ff;
  407. color: #FFFFFF;
  408. width: 100%;
  409. border-radius: 0 !important;
  410. &::after {
  411. border: none !important;
  412. }
  413. }
  414. .content {
  415. padding: 24rpx;
  416. text-align: center;
  417. .confrim-btn {
  418. display: flex;
  419. flex-direction: row;
  420. .send {
  421. flex: 1;
  422. background-color: #2979ff;
  423. color: #FFFFFF;
  424. }
  425. .cancel {
  426. flex: 1;
  427. }
  428. }
  429. }
  430. }
  431. }
  432. .approverContent {
  433. height: 1000rpx;
  434. overflow-y: scroll;
  435. padding: 0 20rpx;
  436. .notice-warp {
  437. top: 0;
  438. height: 5.6rem;
  439. .close-icon {
  440. height: 60rpx;
  441. padding: 10rpx 20rpx;
  442. justify-content: flex-end;
  443. }
  444. }
  445. .popup {
  446. margin-top: 5.65rem;
  447. .list-box {
  448. .item {
  449. border-bottom: 1rpx solid #f0f0f0;
  450. padding: 20rpx 0;
  451. }
  452. }
  453. }
  454. }
  455. .nodeList-v {
  456. background-color: #fff;
  457. }
  458. .record-v {
  459. padding: 32rpx 32rpx 10rpx;
  460. background-color: #fff;
  461. }
  462. .discuss_box {
  463. .discuss_list {
  464. .time_button {
  465. padding-left: 110rpx;
  466. margin-top: 20rpx;
  467. padding-right: 10rpx;
  468. }
  469. .discuss_txt {
  470. width: 100%;
  471. justify-content: space-between;
  472. .discuss_txt_left {
  473. .uName {
  474. margin-left: 8px;
  475. font-size: 14px;
  476. font-family: PingFang SC;
  477. line-height: 17rpx;
  478. .replyText {
  479. margin-left: 8px;
  480. }
  481. }
  482. }
  483. .del {
  484. color: red;
  485. margin-left: 20px;
  486. }
  487. .reply {
  488. margin-left: 20px;
  489. }
  490. }
  491. .discuss_content {
  492. font-size: 12px;
  493. padding-left: 70rpx;
  494. .img_box {
  495. margin: 40rpx 0;
  496. }
  497. }
  498. }
  499. }
  500. .comment-creator-time {
  501. font-size: 12px;
  502. color: #999999;
  503. font-family: PingFang SC;
  504. line-height: 17rpx;
  505. }
  506. .comment-content-color {
  507. color: #606266;
  508. }
  509. .comment-header-color {
  510. color: #303133;
  511. }
  512. </style>