workFlow.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. <template>
  2. <view class="workFlow-v">
  3. <view class="workFlow-nodata" v-show="!workflowEnabled">
  4. <view class="u-flex-col" style="align-items: center;">
  5. <u-image width="280rpx" height="280rpx" :src="emptyImg"></u-image>
  6. <text class="u-m-t-20" style="color: #909399;">该应用协同办公未开启</text>
  7. </view>
  8. </view>
  9. <view class="notice-warp" v-show="workflowEnabled" :style="{'height':noticeWarpH+'px'}">
  10. <view class="search-box">
  11. <u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
  12. :show-action="false" @change="search" bg-color="#f0f2f6" shape="square" />
  13. </view>
  14. <view class="head-tabs u-flex">
  15. <view class="head-tabs-item" @click="openPage('/pages/workFlow/flowTodo/index')">
  16. <text class="icon-ym icon-ym-flowTodo-app u-m-r-4 icon-style" />
  17. <text class="u-font-24 head-tabs-name">审批</text>
  18. <u-badge type="error" class="badge" :count="count" :absolute="true" :offset="offset">
  19. </u-badge>
  20. </view>
  21. <u-line color="#EEF0F4" style="flex: none;height: 34%;" direction="col" />
  22. <view class="head-tabs-item" @click="openPage('/pages/workFlow/schedule/index')">
  23. <text class="icon-ym icon-ym-flowDone-app u-m-r-4 icon-style" />
  24. <text class="u-font-24 head-tabs-name">日程</text>
  25. </view>
  26. <u-line color="#EEF0F4" style="flex: none;height: 34%;" direction="col" />
  27. <view class="head-tabs-item" @click="openPage('/pages/workFlow/document/index')">
  28. <text class="icon-ym icon-ym-flowCopy-app u-m-r-4 icon-style" />
  29. <text class="u-font-24 head-tabs-name">文档</text>
  30. </view>
  31. </view>
  32. </view>
  33. <mescroll-body ref="mescrollRef" @down="downCallback" :down="downOption" :sticky="false" @up="upCallback"
  34. :up="upOption" :bottombar="false" @init="mescrollInit" v-show="workflowEnabled" :top='mescrollTop'>
  35. <view class="common-block">
  36. <view class="caption u-flex">
  37. <text class="caption-left">常用流程</text>
  38. <view class="u-flex" @click="openPage('/pages/commonPage/morePage/index?type=1')">
  39. <text class="caption-right">{{$t('common.moreText')}}</text>
  40. <u-icon name="arrow-right" size="24"></u-icon>
  41. </view>
  42. </view>
  43. <view class="u-flex u-flex-wrap">
  44. <view class="item u-flex-col u-col-center" v-for="(item, i) in usualList" :key="i"
  45. @click="Jump(item, 1)">
  46. <text class="u-font-40 item-icon" :class="item.icon"
  47. :style="{ background: item.iconBackground || '#008cff' }" />
  48. <text class="u-font-24 u-line-1 item-text">{{ item.fullName }}</text>
  49. </view>
  50. <view class="item u-flex-col u-col-center" @click="moreApp">
  51. <text class="u-font-40 item-icon more">+</text>
  52. <text class="u-font-24 u-line-1 item-text">添加</text>
  53. </view>
  54. </view>
  55. </view>
  56. <view>
  57. <CommonTabs :list="categoryList" @change="change" :current="current" ref="CommonTabs"></CommonTabs>
  58. </view>
  59. <view class="workFlow-list u-m-t-20">
  60. <view class="part">
  61. <view class="caption u-line-1" v-if="list.length >= 1">
  62. {{ current === 0 ? "全部流程" : fullName }}
  63. </view>
  64. <view class="u-flex u-flex-wrap">
  65. <view class="item u-flex-col u-col-center" v-for="(child, ii) in list" :key="ii"
  66. @click="Jump(child)">
  67. <text class="u-font-40 item-icon" :class="child.icon"
  68. :style="{ background: child.iconBackground || '#008cff' }" />
  69. <text class="u-font-24 u-line-1 item-text">{{ child.fullName }}</text>
  70. </view>
  71. </view>
  72. </view>
  73. </view>
  74. </mescroll-body>
  75. <MultSelect :show="show" :list="selector" @confirm="confirm" @close="show = false" isFlow />
  76. </view>
  77. </template>
  78. <script>
  79. import {
  80. getFlowSelector,
  81. getFlowTodoCount
  82. } from "@/api/workFlow/flowEngine";
  83. import MultSelect from '@/components/MultSelect'
  84. import CommonTabs from '@/components/CommonTabs'
  85. import {
  86. getFlowUsualList
  87. } from "@/api/apply/apply.js";
  88. import resources from "@/libs/resources.js";
  89. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  90. import IndexMixin from "./mixin.js";
  91. import {
  92. useUserStore
  93. } from '@/store/modules/user'
  94. import {
  95. useBaseStore
  96. } from '@/store/modules/base'
  97. const baseStore = useBaseStore()
  98. export default {
  99. mixins: [MescrollMixin, IndexMixin],
  100. components: {
  101. MultSelect,
  102. CommonTabs
  103. },
  104. data() {
  105. return {
  106. selector: [],
  107. show: false,
  108. activeFlow: {},
  109. templateList: [],
  110. count: 0,
  111. offset: [-25, 60],
  112. usualList: [],
  113. downOption: {
  114. use: true,
  115. auto: true,
  116. },
  117. className: "",
  118. emptyImg: resources.message.nodata,
  119. upOption: {
  120. page: {
  121. num: 0,
  122. size: 50,
  123. time: null,
  124. },
  125. empty: {
  126. use: true,
  127. icon: resources.message.nodata,
  128. tip: this.$t('common.noData'),
  129. fixed: false,
  130. top: "560rpx",
  131. },
  132. textNoMore: this.$t('app.apply.noMoreData'),
  133. },
  134. keyword: "",
  135. category: "",
  136. current: 0,
  137. categoryList: [],
  138. list: [],
  139. fullName: "",
  140. loading: false,
  141. selectFlowValue: 0,
  142. enCode: "",
  143. workflowEnabled: false,
  144. noticeWarpH: 120,
  145. mescrollTop: 120
  146. };
  147. },
  148. onLoad() {
  149. uni.showLoading()
  150. const userStore = useUserStore()
  151. userStore.getCurrentUser().then((res) => {
  152. const userInfo = uni.getStorageSync('userInfo') || {}
  153. uni.hideLoading()
  154. this.workflowEnabled = !!userInfo.workflowEnabled
  155. if (!this.workflowEnabled) return
  156. uni.$on("updateUsualList", (data) => {
  157. this.getFlowUsualList();
  158. });
  159. this.getPaymentMethodOptions();
  160. this.getContentHeight()
  161. })
  162. },
  163. onUnload() {
  164. uni.$off("updateUsualList");
  165. },
  166. onShow() {
  167. this.keyword = ""
  168. const userInfo = uni.getStorageSync('userInfo') || {}
  169. this.workflowEnabled = !!userInfo.workflowEnabled
  170. this.$nextTick(() => {
  171. this.list = [];
  172. this.mescroll.resetUpScroll();
  173. if (!this.workflowEnabled) return
  174. this.setFlowTodoCount()
  175. this.getPaymentMethodOptions();
  176. })
  177. },
  178. onHide() {
  179. this.restTabs()
  180. },
  181. methods: {
  182. async getContentHeight() {
  183. const windowHeight = this.$u.sys().windowHeight;
  184. // 获取元素尺寸
  185. const [headTabs, searchBox] = await Promise.all([
  186. this.$uGetRect('.head-tabs'),
  187. this.$uGetRect('.search-box')
  188. ]);
  189. this.noticeWarpH = headTabs.height + searchBox.height
  190. this.mescrollTop = this.noticeWarpH + 10
  191. },
  192. restTabs() {
  193. this.current = 0;
  194. this.category = ""
  195. },
  196. change(i) {
  197. this.list = [];
  198. this.current = i
  199. this.category = this.categoryList[i].id || "";
  200. this.mescroll.resetUpScroll();
  201. },
  202. setFlowTodoCount() {
  203. const query = {
  204. flowCirculateType: [],
  205. flowDoneType: [],
  206. toBeReviewedType: [],
  207. }
  208. getFlowTodoCount(query).then((res) => {
  209. this.count = res.data.toBeReviewed || 0;
  210. })
  211. },
  212. openPage(path) {
  213. if (!path) return;
  214. this.restTabs()
  215. uni.navigateTo({
  216. url: path,
  217. });
  218. },
  219. upCallback(page) {
  220. this.$nextTick(() => {
  221. this.getFlowUsualList();
  222. });
  223. let query = {
  224. currentPage: page.num,
  225. pageSize: page.size,
  226. keyword: this.keyword,
  227. category: this.category == 0 ? "" : this.category,
  228. flowType: 0,
  229. };
  230. this.loading = false;
  231. getFlowSelector(query, {
  232. load: page.num == 1,
  233. }).then((res) => {
  234. let resData = res.data.list || [];
  235. this.mescroll.endSuccess(resData.length);
  236. if (page.num == 1) this.list = [];
  237. const list = resData.map((o) => ({
  238. show: false,
  239. ...o,
  240. }));
  241. this.list = this.list.concat(list);
  242. this.loading = true;
  243. }).catch(() => {
  244. this.mescroll.endErr();
  245. });
  246. },
  247. search() {
  248. this.searchTimer && clearTimeout(this.searchTimer);
  249. this.searchTimer = setTimeout(() => {
  250. this.list = [];
  251. this.mescroll.resetUpScroll();
  252. }, 300);
  253. },
  254. //获取常用
  255. getFlowUsualList() {
  256. let query = {
  257. category: 'commonFlow',
  258. flowType: 0
  259. }
  260. getFlowUsualList(query).then((res) => {
  261. let list = res.data.list.map((o) => {
  262. const objectData = o.objectData ? JSON.parse(o.objectData) : {};
  263. return {
  264. ...o,
  265. ...objectData,
  266. };
  267. });
  268. this.usualList = [...list].slice(0, 11)
  269. });
  270. },
  271. getPaymentMethodOptions() {
  272. baseStore.getDictionaryData({
  273. sort: "businessType",
  274. }).then((res) => {
  275. const firstItem = {
  276. fullName: "全部流程",
  277. id: ''
  278. }
  279. this.categoryList = [firstItem, ...(res || [])]
  280. });
  281. },
  282. moreApp() {
  283. uni.navigateTo({
  284. url: "/pages/commonPage/allApp/index?categoryList=" +
  285. encodeURIComponent(JSON.stringify(this.categoryList)),
  286. });
  287. },
  288. confirm(e) {
  289. this.activeFlow = e[0];
  290. this.Jump();
  291. },
  292. Jump(item) {
  293. const config = {
  294. id: "",
  295. flowId: item.id,
  296. opType: "-1",
  297. isFlow: 1
  298. };
  299. uni.navigateTo({
  300. url: "/pages/workFlow/flowBefore/index?config=" +
  301. this.jnpf.base64.encode(JSON.stringify(config))
  302. });
  303. }
  304. },
  305. };
  306. </script>
  307. <style lang="scss">
  308. page {
  309. background-color: #f0f2f6;
  310. }
  311. .workFlow-v {
  312. .common-block {
  313. background: #fff;
  314. margin-bottom: 20rpx;
  315. .caption {
  316. padding: 0 32rpx;
  317. line-height: 100rpx;
  318. justify-content: space-between;
  319. .caption-left {
  320. font-size: 36rpx;
  321. font-weight: bold;
  322. }
  323. .caption-right {}
  324. }
  325. .item {
  326. // margin-bottom: 32rpx;
  327. padding: 1rem 0;
  328. width: 25%;
  329. .item-icon {
  330. width: 88rpx;
  331. height: 88rpx;
  332. margin-bottom: 8rpx;
  333. line-height: 88rpx;
  334. text-align: center;
  335. border-radius: 20rpx;
  336. color: #fff;
  337. font-size: 56rpx;
  338. &.more {
  339. background: #ececec;
  340. color: #666666;
  341. font-size: 50rpx;
  342. }
  343. }
  344. .item-text {
  345. width: 100%;
  346. text-align: center;
  347. padding: 0 16rpx;
  348. }
  349. }
  350. }
  351. .notice-warp {
  352. height: 210rpx;
  353. .search-box {
  354. padding: 20rpx;
  355. }
  356. }
  357. .head-tabs {
  358. width: 100%;
  359. padding: 0 32rpx;
  360. height: 100rpx;
  361. justify-content: space-between;
  362. .head-tabs-item {
  363. width: 25%;
  364. display: flex;
  365. justify-content: center;
  366. font-size: 28rpx;
  367. color: #303133;
  368. flex-shrink: 0;
  369. position: relative;
  370. align-items: center;
  371. .icon-style {
  372. font-size: 46rpx;
  373. color: #666666;
  374. }
  375. .head-tabs-name {
  376. color: #303133;
  377. font-family: PingFang SC;
  378. }
  379. }
  380. }
  381. .workFlow-nodata {
  382. position: absolute;
  383. top: 450rpx;
  384. width: 100%;
  385. text-align: center;
  386. z-index: 100;
  387. background-color: #f0f2f6;
  388. }
  389. }
  390. </style>