index.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. <template>
  2. <view class="dynamicModel-list-v">
  3. <!-- 批量删除顶部弹窗 -->
  4. <view class="u-flex top-btn" :class="slide2" v-show="selectItems.length">
  5. <view class="button-left" @click.stop="cancel">
  6. <p class="u-m-t-10 u-font-28">{{$t('common.cancelText')}}</p>
  7. </view>
  8. <view class="button-center">
  9. <p class="u-m-t-10 u-font-28">{{$t('component.jnpf.common.selected')}}({{selectItems.length}})</p>
  10. </view>
  11. <view class="button-right u-m-t-12" @click.stop="checkAll">
  12. <p class="icon-ym icon-ym-app-checkAll " :style="{'color':this.checkedAll ? '#0293fc' : '#303133'}">
  13. </p>
  14. </view>
  15. </view>
  16. <!-- 排序 -->
  17. <view class="head-warp com-dropdown">
  18. <u-dropdown class="u-dropdown" ref="uDropdown" @open="showTop = true" @close="showTop = false">
  19. <u-dropdown-item :title="$t('app.apply.sort')" :options="sortOptions">
  20. <view class="screen-box">
  21. <view class="screen-list" v-if="sortOptions.length">
  22. <view class="u-p-l-20 u-p-r-20 list">
  23. <scroll-view scroll-y="true" style="height: 100%;">
  24. <u-cell-group :border="false">
  25. <u-cell-item @click="cellClick(item)" :arrow="false" :title="item.label"
  26. v-for="(item, index) in sortOptions" :key="index" :title-style="{
  27. color: sortValue.includes(item.value) ? '#2979ff' : '#606266' }">
  28. <u-icon v-if="sortValue.includes(item.value)" name="checkbox-mark"
  29. color="#2979ff" size="32" />
  30. </u-cell-item>
  31. </u-cell-group>
  32. </scroll-view>
  33. </view>
  34. </view>
  35. <JnpfEmpty v-else></JnpfEmpty>
  36. <view class="buttom-actions" v-if="sortOptions.length">
  37. <u-button class="buttom-btn" @click="handleSortReset">{{$t('common.cleanText')}}</u-button>
  38. <u-button class="buttom-btn" type="primary" @click="handleSortSearch">
  39. {{$t('common.okText')}}
  40. </u-button>
  41. </view>
  42. </view>
  43. </u-dropdown-item>
  44. <!-- 筛选 -->
  45. <u-dropdown-item :title="$t('app.apply.screen')">
  46. <view class="screen-box u-flex-col">
  47. <view class="screen-list" v-if="showParser && searchFormConf.length">
  48. <view class="u-p-l-20 u-p-r-20 list">
  49. <scroll-view scroll-y="true" style="height: 100%;">
  50. <Parser :formConf="searchFormConf" :searchFormData="searchFormData"
  51. :webType="config.webType" ref="searchForm" @submit="sumbitSearchForm" />
  52. </scroll-view>
  53. </view>
  54. <view class="u-flex screen-btn" v-if="showParser && searchFormConf.length">
  55. <text @click="handleReset" class="btn btn1">{{$t('common.resetText')}}</text>
  56. <text @click="handleSearch" class="btn btn2">{{$t('common.searchText')}}</text>
  57. </view>
  58. </view>
  59. <JnpfEmpty v-else></JnpfEmpty>
  60. </view>
  61. </u-dropdown-item>
  62. </u-dropdown>
  63. </view>
  64. <view class="u-m-b-20">
  65. <u-tabs :list="tabList" v-model="tabActiveKey" font-size="28" @change="onTabChange" height="80"
  66. name="fullName" v-show="showTabs">
  67. </u-tabs>
  68. </view>
  69. <!-- 列表 -->
  70. <view class="list-warp">
  71. <mescroll-uni ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
  72. :down="downOption" :up="upOption" :bottombar="false"
  73. :top="(columnData.tabConfig && columnData.tabConfig.on && tabList.length) ? 190 : 100">
  74. <list ref="list" :list="list" :columnList="columnList" :config="config" :actionOptions="actionOptions"
  75. @relationFormClick="relationFormClick" @goDetail="goDetail" @handleMoreClick="handleMoreClick"
  76. @handleClick="handleClick" :showSelect="isShowBatch.length" :checkedAll="checkedAll"
  77. @selectCheckbox="selectCheckbox" :isMoreBtn="isMoreBtn" :customBtnsList="columnData.customBtnsList">
  78. </list>
  79. </mescroll-uni>
  80. </view>
  81. <view v-if="!showTop">
  82. <!-- 新增按钮 -->
  83. <view v-if="config.webType !=4">
  84. <view class="com-addBtn"
  85. v-if="isPreview||(permission.btnPermission && permission.btnPermission.includes('btn_add'))"
  86. @click="addPage()">
  87. <u-icon name="plus" size="48" color="#fff" />
  88. </view>
  89. </view>
  90. </view>
  91. <u-select :list="listInnerBtn" v-model="showMoreBtn" @confirm="selectBtnconfirm" />
  92. <u-select :list="bottomCustomBtnsList[1]" v-model="showBottomMoreBtn" @confirm="bottomBtnConfirm" />
  93. <!-- 批量操作底部弹窗 -->
  94. <view class="u-flex bottom-btn" :class="isShowBatch?.length==1? 'bottom-btn-one ':'bottom-btn-multiple'"
  95. v-if="(isShowBatch.length && list.length) || (bottomCustomBtnsList && bottomCustomBtnsList[0].length)">
  96. <view class="button-preIcon" @click.stop="handleBottomMoreClick('down')"
  97. v-if="bottomCustomBtnsList[1].length">
  98. <u-icon name="more-dot-fill" class="u-m-b-8" size="34"></u-icon>
  99. <p class="u-font-24">{{$t('common.moreText')}}</p>
  100. </view>
  101. <!-- 自定义按钮 -->
  102. <view class="button-preIcon" v-for="(item,i) in bottomCustomBtnsList[0]" :key="i"
  103. @click="bottomBtnConfirm(item)">
  104. <p class="btn-icon u-m-b-8" :class="item.event.btnIcon">
  105. </p>
  106. <p class="u-m-t-8 u-font-22 u-line-1">{{item.label}}</p>
  107. </view>
  108. <!-- 批量删除 -->
  109. <view class="button-preIcon" @click.stop="batchDelete" v-if="isBatchRemove && list.length">
  110. <p class="icon-ym icon-ym-app-delete u-m-b-8"></p>
  111. <p class="u-m-t-10 u-font-22">{{$t('common.batchDelText')}}</p>
  112. </view>
  113. </view>
  114. </view>
  115. </template>
  116. <script>
  117. import {
  118. useBaseStore
  119. } from '@/store/modules/base'
  120. const baseStore = useBaseStore()
  121. import list from './list.vue'
  122. import resources from '@/libs/resources.js'
  123. import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
  124. import bulkOperationMixin from "../../bulkOperationMixin.js";
  125. import jnpf from "@/utils/jnpf";
  126. import Parser from '../parser/index.vue'
  127. import {
  128. getModelList,
  129. deteleModel,
  130. getModelInfo,
  131. launchFlow
  132. } from '@/api/apply/visualDev'
  133. import {
  134. getDataInterfaceRes
  135. } from '@/api/common'
  136. import deepClone from '../../../../../uni_modules/vk-uview-ui/libs/function/deepClone';
  137. import {
  138. useDefineSetting
  139. } from '@/utils/useDefineSetting';
  140. export default {
  141. mixins: [MescrollMixin, bulkOperationMixin],
  142. props: ['config', 'modelId', 'isPreview', 'title', 'menuId'],
  143. components: {
  144. Parser,
  145. list
  146. },
  147. data() {
  148. return {
  149. tabActiveKey: 0,
  150. tabList: [],
  151. tabQueryJson: {},
  152. sortValue: [],
  153. downOption: {
  154. use: true,
  155. auto: false
  156. },
  157. upOption: {
  158. page: {
  159. num: 0,
  160. size: 10,
  161. time: null
  162. },
  163. empty: {
  164. use: true,
  165. icon: resources.message.nodata,
  166. tip: this.$t('common.noData'),
  167. fixed: true
  168. },
  169. textNoMore: this.$t('app.apply.noMoreData'),
  170. },
  171. list: [],
  172. listQuery: {
  173. sidx: '',
  174. keyword: '',
  175. queryJson: ''
  176. },
  177. actionOptions: [],
  178. showParser: false,
  179. columnData: {},
  180. columnList: [],
  181. sortList: [],
  182. sortOptions: [],
  183. searchList: [],
  184. searchFormConf: [],
  185. permission: {},
  186. selectListIndex: 0,
  187. showBottomMoreBtn: false,
  188. showMoreBtn: false,
  189. properties: {},
  190. flowId: '',
  191. key: +new Date(),
  192. userInfo: {},
  193. searchFormData: {},
  194. enableFunc: {},
  195. selectItems: [],
  196. listInnerBtn: [],
  197. listTopBtn: [],
  198. useDefine: useDefineSetting()
  199. }
  200. },
  201. created() {
  202. this.init()
  203. },
  204. computed: {
  205. showBatchOperate() {
  206. return this.list.length && (this.isBatchRemove || this.listTopBtn.length)
  207. },
  208. isBatchRemove() {
  209. return this.columnData.btnsList.find(item => item.value === "batchRemove" && item.show)
  210. },
  211. showTabs() {
  212. return this.columnData?.tabConfig?.on && this.tabList.length
  213. },
  214. /* 底部自定义按钮 */
  215. bottomCustomBtnsList() {
  216. if (this.listTopBtn.length <= 3) return [this.listTopBtn, []];
  217. const firstArray = this.listTopBtn.slice(0, 3);
  218. const secondArray = this.listTopBtn.slice(3);
  219. return [firstArray, secondArray];
  220. },
  221. getRowKey() {
  222. return this.config.webType == 4 && this.columnData.viewKey ? this.columnData.viewKey : 'id'
  223. },
  224. isMoreBtn() {
  225. return this.columnData?.customBtnsList?.some(item => item.event?.btnType === 2);
  226. },
  227. isShowBatch() {
  228. const list = this.filterEmpty([this.isBatchRemove, ...this.bottomCustomBtnsList])
  229. return list.filter(i => i !== undefined)
  230. },
  231. customBtnsList() {
  232. return this.columnData?.customBtnsList?.some(item => item.event?.btnType === 1);
  233. }
  234. },
  235. methods: {
  236. filterEmpty(arr) {
  237. return arr.filter(item => {
  238. // 处理数组情况
  239. if (Array.isArray(item)) return item.length > 0;
  240. // 处理对象情况
  241. if (typeof item === 'object' && item !== null) return Object.keys(item).length > 0;
  242. // 其他情况保留
  243. return true;
  244. });
  245. },
  246. selectCheckbox(data) {
  247. this.selectItems = data
  248. },
  249. init() {
  250. this.userInfo = uni.getStorageSync('userInfo') || {};
  251. this.properties = this.config.flowTemplateJson ? JSON.parse(this.config.flowTemplateJson).properties : {};
  252. let columnDataStr = this.config?.appColumnData || '[]';
  253. try {
  254. this.columnData = JSON.parse(columnDataStr);
  255. } catch (e) {
  256. this.columnData = [];
  257. }
  258. this.permission = this.$permission.getPermission(this.columnData, this.menuId, this.jnpf.getScriptFunc);
  259. this.enableFunc = this.permission.enableFunc;
  260. this.upOption.page.size = this.columnData.hasPage ? this.columnData.pageSize : 1000000;
  261. this.setDefaultQuery();
  262. this.columnList = this.permission.columnPermission || [];
  263. this.columnData.customBtnsList = this.permission.customBtnsPermission || [];
  264. this.columnData.customBtnsList.map((o) => {
  265. if (o.labelI18nCode) o.label = this.$t(o.labelI18nCode)
  266. })
  267. this.setBtns()
  268. this.columnList = this.transformColumnList(this.columnList)
  269. this.columnList.map((o) => {
  270. if (o.labelI18nCode) o.label = this.$t(o.labelI18nCode)
  271. // if (o.jnpfKey != 'table' && o.label.length > 4) o.label = o.label.substring(0, 4)
  272. })
  273. this.sortList = this.columnList.filter(o => o.sortable)
  274. this.getTabList();
  275. this.handleSearchList()
  276. this.handleSortList()
  277. this.handleDeleteBtn()
  278. this.key = +new Date()
  279. },
  280. setBtns() {
  281. const buttons = {
  282. inner: [],
  283. top: []
  284. };
  285. this.columnData.customBtnsList.forEach(item => {
  286. const key = item.event.position === 2 ? 'top' : 'inner';
  287. buttons[key].push(item);
  288. });
  289. this.listInnerBtn = buttons.inner;
  290. this.listTopBtn = buttons.top;
  291. },
  292. upCallback(page) {
  293. if (this.isPreview == '1') return this.mescroll.endSuccess(0, false);
  294. const query = {
  295. currentPage: page.num,
  296. pageSize: page.size,
  297. menuId: this.menuId,
  298. modelId: this.modelId,
  299. ...this.listQuery
  300. }
  301. getModelList(this.modelId, query, {
  302. load: page.num == 1
  303. }).then(res => {
  304. this.selectItems = []
  305. this.$nextTick(() => {
  306. this.$refs.list.handleCheckAll()
  307. })
  308. this.showParser = true
  309. if (page.num == 1) this.list = [];
  310. this.mescroll.endSuccess(res.data.list.length);
  311. const list = res.data.list.map((o, i) => ({
  312. checked: false,
  313. index: i,
  314. ...o
  315. }));
  316. this.list = this.list.concat(list);
  317. this.$nextTick(() => {
  318. if (this.columnData.funcs && this.columnData.funcs.afterOnload) this
  319. .setTableLoadFunc()
  320. })
  321. if (!this.selectItems.length || !this.list.length) this.cancel()
  322. }).catch((err) => {
  323. this.mescroll.endByPage(0, 0);
  324. this.mescroll.endErr();
  325. })
  326. },
  327. //获取标签面板数据、设置标签面板默认值
  328. async getTabList() {
  329. this.tabList = [];
  330. if (!this.columnData.tabConfig) return;
  331. const list = this.columnData.columnOptions.filter(o => o.__vModel__ == this.columnData.tabConfig
  332. .relationField) || [];
  333. if (list?.length) {
  334. this.columnData.tabConfig?.hasAllTab && this.tabList.push({
  335. fullName: '全部',
  336. id: undefined
  337. });
  338. if (list[0].__config__.dataType == 'dictionary' && list[0].__config__.dictionaryType) {
  339. const data = await baseStore.getDicDataSelector(list[0].__config__.dictionaryType) || [];
  340. const options = list[0].props.value == 'enCode' ? data.map(o => ({
  341. ...o,
  342. id: o.enCode
  343. })) : data;
  344. this.tabList = [...this.tabList, ...options];
  345. } else {
  346. this.tabList = [...this.tabList, ...list[0].options];
  347. }
  348. }
  349. this.tabActiveKey = 0;
  350. this.onTabChange(this.tabActiveKey)
  351. },
  352. onTabChange(val) {
  353. const {
  354. hasAllTab,
  355. relationField
  356. } = this.columnData.tabConfig;
  357. const currentTab = this.tabList[val];
  358. // 合并条件判断
  359. const shouldSetRelation = !hasAllTab || val !== 0;
  360. this.tabActiveKey = val;
  361. this.tabQueryJson = shouldSetRelation ? {
  362. [relationField]: currentTab.id
  363. } : {};
  364. // 使用可选链操作符和空对象兜底
  365. const search = this.$refs.searchForm?.allCondition() || {};
  366. this.listQuery.queryJson = JSON.stringify({
  367. ...search,
  368. ...this.tabQueryJson
  369. });
  370. this.initData();
  371. },
  372. handleSearchForm(data) {
  373. let newData = {};
  374. for (let key in data) {
  375. if (data.hasOwnProperty(key)) {
  376. if (typeof data[key] === 'object' && data[key] !== null) {
  377. for (let innerKey in data[key]) {
  378. if (data[key].hasOwnProperty(innerKey)) {
  379. let newKey = `${key}-${innerKey}`;
  380. newData[newKey] = data[key][innerKey];
  381. }
  382. }
  383. } else {
  384. newData[key] = data[key];
  385. }
  386. }
  387. }
  388. return newData
  389. },
  390. sumbitSearchForm(data) {
  391. let queryJson = data || {}
  392. this.searchFormData = data
  393. // 标签面板查询
  394. if (this.columnData.tabConfig && this.columnData.tabConfig.on) {
  395. this.tabQueryJson = {
  396. [this.columnData.tabConfig.relationField]: this.tabList[this.tabActiveKey]?.id
  397. };
  398. queryJson = {
  399. ...queryJson,
  400. ...this.tabQueryJson
  401. }
  402. }
  403. this.listQuery.queryJson = JSON.stringify(queryJson) !== '{}' ? JSON.stringify(queryJson) : ''
  404. this.$refs.uDropdown.close();
  405. this.$nextTick(() => {
  406. this.list = [];
  407. this.mescroll.resetUpScroll();
  408. })
  409. },
  410. // 处理启用规则
  411. customEnableRule(data, funcName) {
  412. // #ifdef MP-WEIXIN
  413. return true
  414. // #endif
  415. // #ifndef MP-WEIXIN
  416. let func = this.enableFunc[funcName]
  417. if (!func) return false
  418. let res = func.call(this, {
  419. row: data,
  420. rowIndex: data.index,
  421. onlineUtils: this.jnpf.onlineUtils,
  422. })
  423. return res
  424. // #endif
  425. },
  426. handleDeleteBtn() {
  427. if (this.config.webType == 4) return
  428. const actionOptions = this.columnData.columnBtnsList.filter(o => o.value == 'remove' && o.show)
  429. this.actionOptions = actionOptions.map(o => ({
  430. ...o,
  431. //#ifdef MP-WEIXIN
  432. text: o.labelI18nCode ? this.$t(o.labelI18nCode) : o.label,
  433. //#endif
  434. //#ifndef MP-WEIXIN
  435. text: o.labelI18nCode ? this.$t(o.labelI18nCode, o.label) : o.label,
  436. //#endif
  437. style: {
  438. backgroundColor: '#dd524d'
  439. }
  440. }))
  441. },
  442. handleSearchList() {
  443. this.searchList = (this.$u.deepClone(this.columnData.searchList) || []).filter(o => !o.noShow)
  444. for (let i = 0; i < this.searchList.length; i++) {
  445. const item = this.searchList[i]
  446. if (item.labelI18nCode) {
  447. item.label = this.$t(item.labelI18nCode)
  448. item.placeholder = this.$t(item.labelI18nCode)
  449. }
  450. const config = item.__config__
  451. const now = new Date()
  452. jnpf.setSearchDefaultValue(item, now)
  453. if (item.value != null && item.value != '' && item.value != []) {
  454. this.searchFormData[item.id] = item.value;
  455. }
  456. if (this.config.webType == 4) config.label = item.label
  457. }
  458. if (Object.keys(this.searchFormData).length) this.listQuery.queryJson = JSON.stringify(this.searchFormData)
  459. if (this.searchList.some(o => o.isKeyword)) {
  460. const keywordItem = {
  461. id: 'jnpfKeyword',
  462. fullName: '关键词',
  463. prop: 'jnpfKeyword',
  464. label: this.$t('common.keyword'),
  465. jnpfKey: 'input',
  466. clearable: true,
  467. placeholder: '请输入',
  468. value: undefined,
  469. __config__: {
  470. jnpfKey: 'input'
  471. },
  472. };
  473. this.searchList.unshift(keywordItem);
  474. }
  475. if (this.config.enableFlow && this.searchList.length) {
  476. const flowStateItem = {
  477. id: 'jnpfFlowState',
  478. fullName: '状态',
  479. prop: 'jnpfFlowState',
  480. label: '状态',
  481. jnpfKey: 'select',
  482. placeholder: '请选择状态',
  483. value: undefined,
  484. options: this.useDefine.flowStatusList,
  485. __config__: {
  486. jnpfKey: 'select',
  487. },
  488. };
  489. this.searchList.push(flowStateItem);
  490. }
  491. this.searchFormConf = this.$u.deepClone(this.searchList)
  492. },
  493. handleSortList() {
  494. this.sortOptions = [];
  495. const sortList = this.sortList
  496. for (let i = 0; i < sortList.length; i++) {
  497. let ascItem = {
  498. label: sortList[i].label + ' ' + this.$t('app.apply.ascendingOrder'),
  499. value: sortList[i].prop,
  500. sidx: sortList[i].prop,
  501. sort: 'asc'
  502. }
  503. let descItem = {
  504. label: sortList[i].label + ' ' + this.$t('app.apply.descendingOrder'),
  505. value: '-' + sortList[i].prop,
  506. sidx: sortList[i].prop,
  507. sort: 'desc'
  508. }
  509. this.sortOptions.push(ascItem, descItem)
  510. }
  511. },
  512. transformColumnList(columnList) {
  513. let list = []
  514. for (let i = 0; i < columnList.length; i++) {
  515. const e = columnList[i];
  516. if (!e.prop.includes('-')) {
  517. e.option = null
  518. list.push(e)
  519. } else {
  520. let prop = e.prop.split('-')[0]
  521. let vModel = e.prop.split('-')[1]
  522. let label = e.label.split('-')[0]
  523. let childLabel = e.label.replace(label + '-', '');
  524. if (e.fullNameI18nCode && Array.isArray(e.fullNameI18nCode) && e.fullNameI18nCode[0]) {
  525. label = this.$t(e.fullNameI18nCode[0], label);
  526. }
  527. let newItem = {
  528. align: "center",
  529. jnpfKey: "table",
  530. prop,
  531. label,
  532. children: []
  533. }
  534. e.vModel = vModel
  535. e.childLabel = e.labelI18nCode ? this.$t(e.labelI18nCode) : childLabel;
  536. if (!list.some(o => o.prop === prop)) list.push(newItem)
  537. for (let i = 0; i < list.length; i++) {
  538. if (list[i].prop === prop) {
  539. e.option = null
  540. list[i].children.push(e)
  541. break
  542. }
  543. }
  544. }
  545. }
  546. return list
  547. },
  548. setDefaultQuery() {
  549. const defaultSortConfig = (this.columnData.defaultSortConfig || []).map(o =>
  550. (o.sort === 'desc' ? '-' : '') + o.field);
  551. this.listQuery.sidx = defaultSortConfig.join(',')
  552. },
  553. setTableLoadFunc() {
  554. const JNPFTable = this.$refs.tableRef
  555. const parameter = {
  556. data: this.list,
  557. tableRef: JNPFTable,
  558. onlineUtils: this.jnpf.onlineUtils,
  559. }
  560. const func = this.jnpf.getScriptFunc.call(this, this.columnData.funcs.afterOnload)
  561. if (!func) return
  562. func.call(this, parameter)
  563. },
  564. //删除操作
  565. handleClick(index) {
  566. const item = this.list[index]
  567. if (!this.permission.btnPermission.includes('btn_remove')) return this.$u.toast("未开启删除权限")
  568. if (!this.customEnableRule(item, 'remove')) return this.$u.toast("没有删除权限")
  569. let txt = '流程处于暂停状态,不可操作'
  570. if ([1, 2, 3, 4, 6, 7, 8].includes(item.flowState)) txt = '流程已受理,无法删除'
  571. uni.showModal({
  572. title: '提示',
  573. content: '删除后数据无法恢复',
  574. success: (res) => {
  575. if (res.confirm) {
  576. if (this.config.enableFlow == 1 && ![0, 9].includes(item.flowState)) {
  577. this.$u.toast(txt)
  578. return
  579. }
  580. let data = {
  581. flowId: this.config.flowId,
  582. ids: [item.id]
  583. }
  584. deteleModel(data, this.modelId).then(res => {
  585. this.$u.toast(res.msg)
  586. this.list.splice(index, 1)
  587. this.mescroll.resetUpScroll()
  588. })
  589. }
  590. }
  591. })
  592. },
  593. //底部更多按钮
  594. handleBottomMoreClick(type) {
  595. this.showBottomMoreBtn = true
  596. },
  597. //更多按钮弹窗
  598. handleMoreClick(index) {
  599. this.selectListIndex = index
  600. this.showMoreBtn = true
  601. },
  602. //底部按钮操作
  603. bottomBtnConfirm(e) {
  604. if (Array.isArray(e) && e.length) {
  605. const index = this.bottomCustomBtnsList[1].findIndex(item => item.value === e[0].value);
  606. const item = this.bottomCustomBtnsList[1][index];
  607. if (!this.selectItems.length && item.event.dataRequired) {
  608. return this.$u.toast('请选择一条数据')
  609. }
  610. if (item.event && item.event.btnType === 3) this.handleBottomBtnInterface(item.event);
  611. if (item.event.btnType == 2) this.handleScriptFunc(item.event, this.selectItems)
  612. if (item.event.btnType == 4) this.handleLaunchFlow(item, this.selectItems)
  613. } else {
  614. if (!this.selectItems.length && e.event.dataRequired) {
  615. return this.$u.toast('请选择一条数据')
  616. }
  617. // 当e是一个对象且包含event属性时
  618. if (e.event.btnType == 2) this.handleScriptFunc(e.event, this.selectItems)
  619. if (e.event.btnType === 3) this.handleBottomBtnInterface(e.event);
  620. if (e.event.btnType == 4) this.handleLaunchFlow(e, this.selectItems)
  621. }
  622. },
  623. //底部自定义按钮接口操作
  624. handleBottomBtnInterface(item) {
  625. const selectedItemsCopy = [...this.selectItems];
  626. const webType = this.config.webType;
  627. let data = {
  628. items: selectedItemsCopy,
  629. webType
  630. };
  631. const handlerInterface = (data) => {
  632. let query = {
  633. paramList: this.jnpf.getBatchParamList(item.templateJson, data) || [],
  634. }
  635. getDataInterfaceRes(item.interfaceId, query).then(res => {
  636. uni.showToast({
  637. title: res.msg,
  638. icon: 'none'
  639. })
  640. })
  641. }
  642. if (!item.useConfirm) return handlerInterface(data)
  643. uni.showModal({
  644. title: this.$t('common.tipTitle'),
  645. content: item.confirmTitle || '确认执行此操作?',
  646. showCancel: true,
  647. confirmText: '确定',
  648. success: function(res) {
  649. if (res.confirm) {
  650. handlerInterface(data)
  651. }
  652. }
  653. });
  654. },
  655. // 自定义按钮事件
  656. selectBtnconfirm(e) {
  657. var i = this.columnData.customBtnsList.findIndex((item) => {
  658. return item.value == e[0].value
  659. })
  660. const item = this.columnData.customBtnsList[i]
  661. const row = this.list[this.selectListIndex]
  662. const index = this.selectListIndex
  663. // 自定义启用规则判断
  664. if (!this.customEnableRule(row, item.value)) return this.$u.toast('没有' + item.label + '权限')
  665. if (item.event.btnType == 1) this.handlePopup(item.event, row)
  666. if (item.event.btnType == 2) this.handleScriptFunc(item.event, row, index)
  667. if (item.event.btnType == 3) this.handleInterface(item.event, row)
  668. if (item.event.btnType == 4) this.handleLaunchFlow(item, [row])
  669. },
  670. //自定义按钮发起流程
  671. handleLaunchFlow(item, records) {
  672. const data = deepClone(item.event.launchFlow)
  673. let dataList = [];
  674. for (let i = 0; i < records.length; i++) {
  675. dataList.push(this.jnpf.getLaunchFlowParamList(data.transferList, records[i], this.getRowKey));
  676. }
  677. const query = {
  678. template: data.flowId,
  679. btnCode: item.value,
  680. currentUser: data.currentUser,
  681. customUser: data.customUser,
  682. initiator: data.initiator,
  683. hasPermission: data.hasPermission,
  684. dataList,
  685. };
  686. launchFlow(query, this.modelId).then(res => {
  687. this.$u.toast(res.msg)
  688. });
  689. },
  690. //自定义按钮弹窗操作
  691. handlePopup(item, row) {
  692. this.handleListen()
  693. let data = {
  694. config: item,
  695. modelId: this.modelId,
  696. id: this.config.webType == 4 ? '' : row[this.getRowKey],
  697. isPreview: this.isPreview,
  698. row: this.config.webType == 4 ? row : '',
  699. }
  700. data = encodeURIComponent(JSON.stringify(data))
  701. uni.navigateTo({
  702. url: '/pages/apply/customBtn/index?data=' + data
  703. })
  704. },
  705. //自定义按钮JS操作
  706. handleScriptFunc(item, row, index) {
  707. const parameter = {
  708. data: row,
  709. index,
  710. refresh: this.initData,
  711. onlineUtils: this.jnpf.onlineUtils,
  712. }
  713. const func = this.jnpf.getScriptFunc.call(this, item.func)
  714. if (!func) return
  715. func.call(this, parameter)
  716. },
  717. //自定义按钮接口操作
  718. handleInterface(item, row) {
  719. const handlerData = () => {
  720. getModelInfo(this.modelId, row[this.getModelInfo]).then(res => {
  721. const dataForm = res.data || {};
  722. if (!dataForm.data) return;
  723. const data = {
  724. ...JSON.parse(dataForm.data),
  725. id: row[this.getModelInfo]
  726. };
  727. handlerInterface(data);
  728. })
  729. }
  730. const handlerInterface = (data) => {
  731. let query = {
  732. paramList: this.jnpf.getParamList(item.templateJson, {
  733. ...data,
  734. id: row[this.getRowKey]
  735. }, this.getRowKey) || [],
  736. }
  737. getDataInterfaceRes(item.interfaceId, query).then(res => {
  738. uni.showToast({
  739. title: res.msg,
  740. icon: 'none'
  741. })
  742. if (item.isRefresh) this.initData();
  743. })
  744. }
  745. const handleFun = () => {
  746. this.config.webType == '4' ? handlerInterface(row) : handlerData();
  747. };
  748. if (!item.useConfirm) return handleFun()
  749. uni.showModal({
  750. title: '提示',
  751. content: item.confirmTitle || '确认执行此操作',
  752. success: (res) => {
  753. if (!res.cancel) handleFun()
  754. }
  755. })
  756. },
  757. initData() {
  758. this.list = [];
  759. this.$nextTick(() => {
  760. this.mescroll.resetUpScroll();
  761. })
  762. },
  763. search() {
  764. if (this.isPreview == '1') return
  765. this.searchTimer && clearTimeout(this.searchTimer)
  766. this.searchTimer = setTimeout(() => {
  767. this.list = [];
  768. this.mescroll.resetUpScroll();
  769. }, 300)
  770. },
  771. handleListen() {
  772. uni.$off('refresh')
  773. uni.$on('refresh', () => {
  774. this.list = [];
  775. this.mescroll.resetUpScroll();
  776. })
  777. },
  778. addPage() {
  779. this.handleListen()
  780. this.jumPage({}, '')
  781. },
  782. jumPage(item, btnType) {
  783. if (!item.id && !item.flowState) btnType = 'btn_add'
  784. if (this.config.enableFlow == 1) {
  785. if (item.id) {
  786. if (!this.permission.btnPermission.includes('btn_edit') && item.flowState == 3) return
  787. if (!this.permission.btnPermission.includes('btn_detail') && ![0, 8, 9].includes(item
  788. .flowState))
  789. return
  790. }
  791. let opType = '-1'
  792. if (![0, 8, 9].includes(item.flowState) && btnType != 'btn_add') opType = 0
  793. const config = {
  794. id: item.flowTaskId || item.id || '',
  795. flowId: this.config.flowId,
  796. opType,
  797. status: item.flowState || '',
  798. isPreview: this.isPreview,
  799. taskId: item.flowTaskId || item.id,
  800. isFlow: 0,
  801. }
  802. uni.navigateTo({
  803. url: '/pages/workFlow/flowBefore/index?config=' +
  804. this.jnpf.base64.encode(JSON.stringify(config))
  805. })
  806. } else {
  807. const type = btnType == 'btn_detail' ? 'detail' : 'form'
  808. const currentMenu = encodeURIComponent(JSON.stringify(this.permission.formPermission))
  809. let btnType_ = this.permission.btnPermission.includes('btn_edit') ? 'btn_edit' : 'btn_add'
  810. let enableEdit = this.customEnableRule(item, 'edit')
  811. let labelS = {}
  812. for (let i = 0; i < this.columnData.columnBtnsList.length; i++) {
  813. const item = this.columnData.columnBtnsList[i]
  814. if (item.value == 'edit') {
  815. labelS[btnType_] = item.labelI18nCode ? this.$t(item.labelI18nCode) : item.label
  816. }
  817. }
  818. const config = {
  819. currentMenu,
  820. btnType: btnType_,
  821. list: this.list,
  822. modelId: this.modelId,
  823. menuId: this.menuId,
  824. isPreview: this.isPreview,
  825. id: item.id || '',
  826. index: item.index,
  827. enableEdit,
  828. labelS
  829. }
  830. const url = '/pages/apply/dynamicModel/' + type + '?config=' +
  831. this.jnpf.base64.encode(JSON.stringify(config))
  832. uni.navigateTo({
  833. url: url
  834. })
  835. }
  836. },
  837. goDetail(item) {
  838. if (this.config.webType == 4) return
  839. this.handleListen()
  840. let hasDetail = this.permission.btnPermission.includes('btn_detail')
  841. let hasEdit = this.permission.btnPermission.includes('btn_edit')
  842. if (!hasDetail && !hasEdit) return
  843. if (hasDetail) {
  844. if (this.customEnableRule(item, 'detail')) {
  845. return this.jumPage(item, 'btn_detail')
  846. }
  847. if (this.customEnableRule(item, 'edit')) {
  848. return this.jumPage(item, 'btn_edit')
  849. }
  850. } else {
  851. if (this.customEnableRule(item, 'edit')) {
  852. return this.jumPage(item, 'btn_edit')
  853. }
  854. }
  855. },
  856. cellClick(item) {
  857. if (this.isPreview == '1') return this.$u.toast('功能预览不支持排序')
  858. const findIndex = this.sortValue.findIndex(o => o === item.value);
  859. if (findIndex < 0) {
  860. const findLikeIndex = this.sortValue.findIndex(o => o.indexOf(item.sidx) > -1);
  861. if (findLikeIndex > -1) this.sortValue.splice(findLikeIndex, 1)
  862. this.sortValue.push(item.value)
  863. } else {
  864. this.sortValue.splice(findIndex, 1)
  865. }
  866. },
  867. handleReset() {
  868. this.searchFormData = {}
  869. const list = ['datePicker', 'timePicker', 'inputNumber', 'calculate', 'cascader', 'usersSelect']
  870. for (let i = 0; i < this.searchList.length; i++) {
  871. const item = this.searchList[i]
  872. const config = item.__config__
  873. let defaultValue = item.searchMultiple || list.includes(config.jnpfKey) ? [] : undefined
  874. if (config.isFromParam) defaultValue = undefined
  875. config.defaultValue = defaultValue
  876. this.searchFormData[item.id] = item.value || defaultValue
  877. }
  878. this.searchFormConf = JSON.parse(JSON.stringify(this.searchList))
  879. },
  880. handleSearch() {
  881. if (this.isPreview == '1') return this.$u.toast('功能预览不支持检索')
  882. this.$refs.searchForm && this.$refs.searchForm.submitForm()
  883. },
  884. relationFormClick(item, column) {
  885. let vModel = column.vModel ? column.vModel : column.__vModel__
  886. let model_id = column.modelId
  887. let config = {
  888. modelId: model_id,
  889. isPreview: true,
  890. id: item[vModel + '_id'],
  891. sourceRelationForm: true,
  892. noShowBtn: 1,
  893. noDataLog: 1,
  894. propsValue: column.propsValue
  895. }
  896. const url =
  897. '/pages/apply/dynamicModel/detail?config=' + this.jnpf.base64.encode(JSON.stringify(config))
  898. uni.navigateTo({
  899. url: url
  900. })
  901. },
  902. handleSortReset() {
  903. this.sortValue = []
  904. },
  905. handleSortSearch() {
  906. if (this.sortValue.length) {
  907. this.listQuery.sidx = this.sortValue.join(',')
  908. } else {
  909. this.setDefaultQuery()
  910. }
  911. this.$refs.uDropdown.close();
  912. this.$nextTick(() => {
  913. this.list = [];
  914. this.mescroll.resetUpScroll();
  915. })
  916. }
  917. }
  918. }
  919. </script>
  920. <style lang="scss">
  921. page {
  922. background-color: #f0f2f6;
  923. height: 100%;
  924. /* #ifdef MP-ALIPAY */
  925. position: absolute;
  926. top: 0;
  927. left: 0;
  928. width: 100%;
  929. /* #endif */
  930. }
  931. :deep(.u-cell) {
  932. padding: 0rpx;
  933. height: 112rpx;
  934. }
  935. </style>