saas-tenant-approve-app 0.2.44 → 0.2.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14485,8 +14485,8 @@ var component = normalizeComponent(
14485
14485
  )
14486
14486
 
14487
14487
  /* harmony default export */ var approveLine = (component.exports);
14488
- ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/approveLineAll.vue?vue&type=template&id=0171b230&scoped=true
14489
- var approveLineAllvue_type_template_id_0171b230_scoped_true_render = function render() {
14488
+ ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/approveLineAll.vue?vue&type=template&id=520f8838&scoped=true
14489
+ var approveLineAllvue_type_template_id_520f8838_scoped_true_render = function render() {
14490
14490
  var _vm = this,
14491
14491
  _c = _vm._self._c;
14492
14492
  return _c('div', {
@@ -14587,7 +14587,9 @@ var approveLineAllvue_type_template_id_0171b230_scoped_true_render = function re
14587
14587
  return _vm.addApprover(step);
14588
14588
  }
14589
14589
  }
14590
- }) : _vm._e()], 1), step.approverDtoList && step.approverDtoList.length ? _vm._l(step.approverDtoList, function (item, index2) {
14590
+ }) : _vm._e(), _vm._t("node-actions", null, {
14591
+ "step": step
14592
+ })], 2), _vm.visibleApprovers(step).length ? _vm._l(_vm.visibleApprovers(step), function (item, index2) {
14591
14593
  return _c('span', {
14592
14594
  key: item.id
14593
14595
  }, [_c('div', {
@@ -14689,9 +14691,26 @@ var approveLineAllvue_type_template_id_0171b230_scoped_true_render = function re
14689
14691
  on: {
14690
14692
  "click": _vm.agre_vis
14691
14693
  }
14692
- }, [_vm._v("同意 ")])], 1)], 1)], 1) : _vm._e()], 1);
14694
+ }, [_vm._v("同意 ")])], 1)], 1)], 1) : _vm._e(), _c('CandidatePicker', {
14695
+ attrs: {
14696
+ "candidates": _vm.rangeCandidates,
14697
+ "selected": _vm.rangeSelected,
14698
+ "single": _vm.rangeSingle,
14699
+ "required": _vm.rangeRequired
14700
+ },
14701
+ on: {
14702
+ "confirm": _vm.confirmRange
14703
+ },
14704
+ model: {
14705
+ value: _vm.rangeVisible,
14706
+ callback: function ($$v) {
14707
+ _vm.rangeVisible = $$v;
14708
+ },
14709
+ expression: "rangeVisible"
14710
+ }
14711
+ })], 1);
14693
14712
  };
14694
- var approveLineAllvue_type_template_id_0171b230_scoped_true_staticRenderFns = [];
14713
+ var approveLineAllvue_type_template_id_520f8838_scoped_true_staticRenderFns = [];
14695
14714
 
14696
14715
  // EXTERNAL MODULE: ./node_modules/qs/lib/index.js
14697
14716
  var lib = __webpack_require__(9122);
@@ -15274,6 +15293,304 @@ approveMobileTree.prototype = {
15274
15293
  };
15275
15294
 
15276
15295
  // export default approveMobileTree
15296
+ ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/CandidatePicker.vue?vue&type=template&id=3d2a46fc&scoped=true
15297
+ var CandidatePickervue_type_template_id_3d2a46fc_scoped_true_render = function render() {
15298
+ var _vm = this,
15299
+ _c = _vm._self._c;
15300
+ return _c('van-dialog', {
15301
+ attrs: {
15302
+ "value": _vm.value,
15303
+ "title": "选择人员",
15304
+ "show-cancel-button": "",
15305
+ "before-close": _vm.beforeClose
15306
+ }
15307
+ }, [_c('van-search', {
15308
+ attrs: {
15309
+ "placeholder": "搜索姓名或账号"
15310
+ },
15311
+ model: {
15312
+ value: _vm.keyword,
15313
+ callback: function ($$v) {
15314
+ _vm.keyword = $$v;
15315
+ },
15316
+ expression: "keyword"
15317
+ }
15318
+ }), _c('div', {
15319
+ staticClass: "approval-candidate-list"
15320
+ }, [_vm._l(_vm.filtered, function (person) {
15321
+ return _c('van-cell', {
15322
+ key: person.userId,
15323
+ attrs: {
15324
+ "title": person.name,
15325
+ "label": person.userId,
15326
+ "clickable": ""
15327
+ },
15328
+ on: {
15329
+ "click": function ($event) {
15330
+ return _vm.toggle(person.userId);
15331
+ }
15332
+ },
15333
+ scopedSlots: _vm._u([{
15334
+ key: "right-icon",
15335
+ fn: function () {
15336
+ return [_c('van-icon', {
15337
+ attrs: {
15338
+ "name": _vm.chosen.includes(person.userId) ? 'checked' : 'circle',
15339
+ "color": _vm.chosen.includes(person.userId) ? '#009b80' : '#ccc'
15340
+ }
15341
+ })];
15342
+ },
15343
+ proxy: true
15344
+ }], null, true)
15345
+ });
15346
+ }), !_vm.filtered.length ? _c('p', {
15347
+ staticClass: "approval-candidate-empty",
15348
+ attrs: {
15349
+ "role": "status"
15350
+ }
15351
+ }, [_vm._v("当前范围暂无可选人员")]) : _vm._e()], 2)], 1);
15352
+ };
15353
+ var CandidatePickervue_type_template_id_3d2a46fc_scoped_true_staticRenderFns = [];
15354
+
15355
+ ;// CONCATENATED MODULE: ./node_modules/vant/es/search/index.js
15356
+
15357
+
15358
+
15359
+ // Utils
15360
+
15361
+
15362
+ // Components
15363
+
15364
+ // Types
15365
+
15366
+ var search_createNamespace = createNamespace('search'),
15367
+ search_createComponent = search_createNamespace[0],
15368
+ search_bem = search_createNamespace[1],
15369
+ search_t = search_createNamespace[2];
15370
+ function Search(h, props, slots, ctx) {
15371
+ function Label() {
15372
+ if (slots.label || props.label) {
15373
+ return h("div", {
15374
+ "class": search_bem('label')
15375
+ }, [slots.label ? slots.label() : props.label]);
15376
+ }
15377
+ }
15378
+ function Action() {
15379
+ if (!props.showAction) {
15380
+ return;
15381
+ }
15382
+ function onCancel() {
15383
+ if (slots.action) {
15384
+ return;
15385
+ }
15386
+ emit(ctx, 'input', '');
15387
+ emit(ctx, 'cancel');
15388
+ }
15389
+ return h("div", {
15390
+ "class": search_bem('action'),
15391
+ "attrs": {
15392
+ "role": "button",
15393
+ "tabindex": "0"
15394
+ },
15395
+ "on": {
15396
+ "click": onCancel
15397
+ }
15398
+ }, [slots.action ? slots.action() : props.actionText || search_t('cancel')]);
15399
+ }
15400
+ var fieldData = {
15401
+ attrs: ctx.data.attrs,
15402
+ on: _extends({}, ctx.listeners, {
15403
+ keypress: function keypress(event) {
15404
+ // press enter
15405
+ if (event.keyCode === 13) {
15406
+ preventDefault(event);
15407
+ emit(ctx, 'search', props.value);
15408
+ }
15409
+ emit(ctx, 'keypress', event);
15410
+ }
15411
+ })
15412
+ };
15413
+ var inheritData = inherit(ctx);
15414
+ inheritData.attrs = undefined;
15415
+ return h("div", helper_default()([{
15416
+ "class": search_bem({
15417
+ 'show-action': props.showAction
15418
+ }),
15419
+ "style": {
15420
+ background: props.background
15421
+ }
15422
+ }, inheritData]), [slots.left == null ? void 0 : slots.left(), h("div", {
15423
+ "class": search_bem('content', props.shape)
15424
+ }, [Label(), h(field, helper_default()([{
15425
+ "attrs": {
15426
+ "type": "search",
15427
+ "border": false,
15428
+ "value": props.value,
15429
+ "leftIcon": props.leftIcon,
15430
+ "rightIcon": props.rightIcon,
15431
+ "clearable": props.clearable,
15432
+ "clearTrigger": props.clearTrigger
15433
+ },
15434
+ "scopedSlots": {
15435
+ 'left-icon': slots['left-icon'],
15436
+ 'right-icon': slots['right-icon']
15437
+ }
15438
+ }, fieldData]))]), Action()]);
15439
+ }
15440
+ Search.props = {
15441
+ value: String,
15442
+ label: String,
15443
+ rightIcon: String,
15444
+ actionText: String,
15445
+ background: String,
15446
+ showAction: Boolean,
15447
+ clearTrigger: String,
15448
+ shape: {
15449
+ type: String,
15450
+ default: 'square'
15451
+ },
15452
+ clearable: {
15453
+ type: Boolean,
15454
+ default: true
15455
+ },
15456
+ leftIcon: {
15457
+ type: String,
15458
+ default: 'search'
15459
+ }
15460
+ };
15461
+ /* harmony default export */ var search = (search_createComponent(Search));
15462
+ ;// CONCATENATED MODULE: ./src/utils/selectionScope.js
15463
+ const isCopyScope = node => node && node.type === 'copy' && node.checker && String(node.checker.isOptional) === '1' && String(node.checker.selectArea) === '2' && (Number(node.checker.scopeVersion) === 1 || (node.checker.selectedDepts || []).length > 0);
15464
+ const isScopedSelection = node => isCopyScope(node) || node && node.type === 'check' && node.checker && [7, 8].includes(Number(node.checker.type)) && String(node.checker.selectArea) === '2' && (Number(node.checker.scopeVersion) === 1 || (node.checker.selectedDepts || []).length > 0);
15465
+ function normalizeCandidates(people) {
15466
+ const unique = new Map();
15467
+ for (const person of people || []) {
15468
+ if (!person || String(person.type) === '2') continue;
15469
+ const userId = person.userId || person.id;
15470
+ if (userId) unique.set(String(userId), {
15471
+ userId: String(userId),
15472
+ name: person.name
15473
+ });
15474
+ }
15475
+ return [...unique.values()];
15476
+ }
15477
+ const isSelectableApproval = node => node && node.type === 'check' && node.checker && [7, 8, 9].includes(Number(node.checker.type));
15478
+ const hasCandidateRange = node => Boolean(node && node.selectionRestricted === true) || isScopedSelection(node);
15479
+
15480
+ // Each node is a complete selection. The immediate-node callback wins only for that node.
15481
+ function mergeOptionalSelections(edited, immediate) {
15482
+ const parse = value => typeof value === 'string' ? JSON.parse(value || '[]') : value || [];
15483
+ const next = parse(immediate);
15484
+ const replaced = new Set(next.map(person => String(person.nodeId || person.id)));
15485
+ return parse(edited).filter(person => !replaced.has(String(person.nodeId || person.id))).concat(next);
15486
+ }
15487
+ function constrainDefaults(node, people) {
15488
+ if (!node || node.approvalControlsEnabled !== true || node.selectionRestricted !== true) return people;
15489
+ const allowed = new Set(normalizeCandidates(node.selectionCandidates).map(p => p.userId));
15490
+ return normalizeCandidates(people).filter(p => allowed.has(p.userId));
15491
+ }
15492
+ const canChangeFutureApprovers = node => Boolean(node) && !(node.approvalControlsEnabled === true && (node.type !== 'check' || node.checker.lockApproverChanges === true)) && canEditApprovers(node);
15493
+ const canEditApprovers = node => isSelectableApproval(node) ? String(node.checker.editApprover) === '1' : node && node.type === 'copy' && String(node.isOptional) === '1';
15494
+ const canReduceDefaultApprovers = node => isSelectableApproval(node) && String(node.checker.editApprover) !== '1' && String(node.checker.defaultApprover) === '1' && String(node.checker.allowRemoveDefaultApprover) === '1';
15495
+ const canRemoveApprover = node => (canEditApprovers(node) || canReduceDefaultApprovers(node)) && (node.type !== 'check' || normalizeCandidates(node.list).length > 1);
15496
+ function approvalSelectionError(node, people = node.list) {
15497
+ if (!isSelectableApproval(node)) return '';
15498
+ const selected = normalizeCandidates(people);
15499
+ if (!selected.length) return '至少保留一位审批人';
15500
+ if (canEditApprovers(node) && String(node.checker.selectPersonType) === '1' && selected.length > 1) return node.name + '只可选择一个审批人';
15501
+ if (!canEditApprovers(node) && String(node.checker.defaultApprover) === '1') {
15502
+ const defaults = new Set(node.defaultApproverIds || []);
15503
+ if (selected.some(person => !defaults.has(person.userId))) return node.name + '只能保留默认审批人';
15504
+ if (!canReduceDefaultApprovers(node) && selected.length !== defaults.size) return node.name + '不允许删减默认审批人';
15505
+ }
15506
+ return '';
15507
+ }
15508
+ ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/CandidatePicker.vue?vue&type=script&lang=js
15509
+
15510
+
15511
+ /* harmony default export */ var CandidatePickervue_type_script_lang_js = ({
15512
+ name: 'CandidatePicker',
15513
+ components: {
15514
+ 'van-dialog': dialog.Component,
15515
+ 'van-search': search,
15516
+ 'van-cell': cell,
15517
+ 'van-icon': es_icon
15518
+ },
15519
+ props: {
15520
+ value: Boolean,
15521
+ candidates: Array,
15522
+ selected: Array,
15523
+ single: Boolean,
15524
+ required: Boolean
15525
+ },
15526
+ data: () => ({
15527
+ keyword: '',
15528
+ chosen: []
15529
+ }),
15530
+ computed: {
15531
+ people() {
15532
+ return normalizeCandidates(this.candidates);
15533
+ },
15534
+ filtered() {
15535
+ const text = this.keyword.trim().toLowerCase();
15536
+ return this.people.filter(p => !text || (p.name + ' ' + p.userId).toLowerCase().includes(text));
15537
+ }
15538
+ },
15539
+ watch: {
15540
+ value(open) {
15541
+ if (!open) return;
15542
+ this.keyword = '';
15543
+ const allowed = new Set(this.people.map(p => p.userId));
15544
+ this.chosen = normalizeCandidates(this.selected).map(p => p.userId).filter(id => allowed.has(id));
15545
+ if (this.single) this.chosen = this.chosen.slice(0, 1);
15546
+ }
15547
+ },
15548
+ methods: {
15549
+ toggle(id) {
15550
+ this.chosen = this.single ? [id] : this.chosen.includes(id) ? this.chosen.filter(value => value !== id) : [...this.chosen, id];
15551
+ },
15552
+ beforeClose(action, done) {
15553
+ if (action === 'confirm') {
15554
+ if (this.required && !this.chosen.length) {
15555
+ toast.fail('至少保留一位审批人');
15556
+ done(false);
15557
+ return;
15558
+ }
15559
+ this.$emit('confirm', this.people.filter(p => this.chosen.includes(p.userId)));
15560
+ }
15561
+ this.$emit('input', false);
15562
+ done();
15563
+ }
15564
+ }
15565
+ });
15566
+ ;// CONCATENATED MODULE: ./src/components/CandidatePicker.vue?vue&type=script&lang=js
15567
+ /* harmony default export */ var components_CandidatePickervue_type_script_lang_js = (CandidatePickervue_type_script_lang_js);
15568
+ ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/CandidatePicker.vue?vue&type=style&index=0&id=3d2a46fc&prod&scoped=true&lang=css
15569
+ // extracted by mini-css-extract-plugin
15570
+
15571
+ ;// CONCATENATED MODULE: ./src/components/CandidatePicker.vue?vue&type=style&index=0&id=3d2a46fc&prod&scoped=true&lang=css
15572
+
15573
+ ;// CONCATENATED MODULE: ./src/components/CandidatePicker.vue
15574
+
15575
+
15576
+
15577
+ ;
15578
+
15579
+
15580
+ /* normalize component */
15581
+
15582
+ var CandidatePicker_component = normalizeComponent(
15583
+ components_CandidatePickervue_type_script_lang_js,
15584
+ CandidatePickervue_type_template_id_3d2a46fc_scoped_true_render,
15585
+ CandidatePickervue_type_template_id_3d2a46fc_scoped_true_staticRenderFns,
15586
+ false,
15587
+ null,
15588
+ "3d2a46fc",
15589
+ null
15590
+
15591
+ )
15592
+
15593
+ /* harmony default export */ var CandidatePicker = (CandidatePicker_component.exports);
15277
15594
  ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/approveLineAll.vue?vue&type=script&lang=js
15278
15595
 
15279
15596
 
@@ -15281,6 +15598,8 @@ approveMobileTree.prototype = {
15281
15598
 
15282
15599
 
15283
15600
 
15601
+
15602
+
15284
15603
  /* harmony default export */ var approveLineAllvue_type_script_lang_js = ({
15285
15604
  name: "ApproveLineAll",
15286
15605
  data() {
@@ -15295,7 +15614,15 @@ approveMobileTree.prototype = {
15295
15614
  //是否登录人有权限操作 同意驳回 true:有
15296
15615
  ifBtn: true,
15297
15616
  approveList: [],
15298
- optionalList: []
15617
+ optionalList: [],
15618
+ rangeVisible: false,
15619
+ rangeCandidates: [],
15620
+ rangeSelected: [],
15621
+ rangeSingle: false,
15622
+ rangeRequired: true,
15623
+ rangeNode: null,
15624
+ rangeStep: null,
15625
+ rangeLoading: false
15299
15626
  };
15300
15627
  },
15301
15628
  props: {
@@ -15305,6 +15632,7 @@ approveMobileTree.prototype = {
15305
15632
  }
15306
15633
  },
15307
15634
  components: {
15635
+ CandidatePicker: CandidatePicker,
15308
15636
  "van-steps": steps,
15309
15637
  "van-step": step,
15310
15638
  "van-tag": tag,
@@ -15357,10 +15685,11 @@ approveMobileTree.prototype = {
15357
15685
  value: that.data.mainDeptLeader ? "是" : "否"
15358
15686
  }];
15359
15687
  }
15360
- projectCustomNodes(that.SAAS_TENANT_API, {
15688
+ return projectCustomNodes(that.SAAS_TENANT_API, {
15361
15689
  outApprove: true,
15362
15690
  uid: that.data.uid,
15363
15691
  id: that.data.id,
15692
+ projectId: that.data.projectId,
15364
15693
  aprId: that.data.aprId,
15365
15694
  formDataList: formDataList
15366
15695
  }).then(async res => {
@@ -15419,7 +15748,11 @@ approveMobileTree.prototype = {
15419
15748
  if ([7, 8, 9].includes(item.checker.type) && item.checker.defaultApprover != 1) {
15420
15749
  list = [];
15421
15750
  }
15751
+ list = constrainDefaults(item, list);
15422
15752
  return {
15753
+ selectionRestricted: item.selectionRestricted,
15754
+ selectionCandidates: item.selectionCandidates,
15755
+ approvalControlsEnabled: item.approvalControlsEnabled,
15423
15756
  id: item.id,
15424
15757
  type: item.type,
15425
15758
  name: item.name,
@@ -15433,7 +15766,7 @@ approveMobileTree.prototype = {
15433
15766
  list: this.uniqueByUserId(list)
15434
15767
  };
15435
15768
  });
15436
- Promise.all(approveList).then(res => {
15769
+ return Promise.all(approveList).then(res => {
15437
15770
  this.approveList = res;
15438
15771
  });
15439
15772
  } else {
@@ -15449,6 +15782,8 @@ approveMobileTree.prototype = {
15449
15782
  var me = this;
15450
15783
  if (me.approveList && me.approveList.length > 0) {
15451
15784
  var node = me.approveList.find(item => item.id == step.nodeId);
15785
+ if (!node) return false;
15786
+ if (node.approvalControlsEnabled === true) return me.approveStatus && canChangeFutureApprovers(node);
15452
15787
  if ([7, 8, 9].includes(node.checkertype) && node.editApprover == 1 || node.type == "copy" && node.isOptional == 1) {
15453
15788
  return true;
15454
15789
  } else {
@@ -15456,10 +15791,35 @@ approveMobileTree.prototype = {
15456
15791
  }
15457
15792
  }
15458
15793
  },
15459
- addApprover(step) {
15794
+ async addApprover(step) {
15460
15795
  let me = this;
15796
+ if (!this.ableEdit(step) || this.rangeLoading) return;
15461
15797
  if (me.approveList && me.approveList.length > 0) {
15462
15798
  var node = me.approveList.find(item => item.id == step.nodeId);
15799
+ if (hasCandidateRange(node) || [7, 8].includes(Number(node.checkertype)) && String(node.checker.selectArea) === '2' && (node.selectedPersons || []).length) {
15800
+ this.rangeLoading = true;
15801
+ try {
15802
+ const response = await queryOptionalScopeUsers(this.SAAS_TENANT_API, {
15803
+ recordId: this.data.id,
15804
+ projectId: this.data.projectId,
15805
+ aprId: this.data.aprId,
15806
+ nodeId: node.id
15807
+ });
15808
+ if (Number(response.status) !== 200 || !Array.isArray(response.result && response.result.data)) throw new Error(response.message || '读取可选范围失败');
15809
+ this.rangeCandidates = normalizeCandidates(response.result.data);
15810
+ this.rangeSelected = step.nodeType === 'copy' ? step.copyerDtoList : step.approverDtoList;
15811
+ this.rangeSingle = String(node.selectPersonType) === '1';
15812
+ this.rangeRequired = step.nodeType === 'check';
15813
+ this.rangeNode = node;
15814
+ this.rangeStep = step;
15815
+ this.rangeVisible = true;
15816
+ } catch (error) {
15817
+ toast.fail(error.message || '读取可选范围失败');
15818
+ } finally {
15819
+ this.rangeLoading = false;
15820
+ }
15821
+ return;
15822
+ }
15463
15823
  let defaultKey = [];
15464
15824
  if (step.nodeType == 'copy') {
15465
15825
  if (step.copyerDtoList && step.copyerDtoList.length) {
@@ -15533,6 +15893,24 @@ approveMobileTree.prototype = {
15533
15893
  });
15534
15894
  }
15535
15895
  },
15896
+ confirmRange(people) {
15897
+ const node = this.rangeNode,
15898
+ step = this.rangeStep;
15899
+ if (!node || !step || !this.ableEdit(step)) return;
15900
+ const list = people.map((person, sort) => ({
15901
+ userId: person.userId,
15902
+ name: person.name,
15903
+ nodeId: node.id,
15904
+ nodeName: node.name,
15905
+ nodeType: node.type,
15906
+ recordId: step.recordId,
15907
+ isApprove: '0',
15908
+ status: '1',
15909
+ sort
15910
+ }));
15911
+ if (step.nodeType === 'copy') step.copyerDtoList = list;else step.approverDtoList = list;
15912
+ this.optionalList = this.optionalList.filter(person => person.nodeId !== node.id).concat(list);
15913
+ },
15536
15914
  async getInfo() {
15537
15915
  var that = this;
15538
15916
  let formDataList = null;
@@ -15607,6 +15985,14 @@ approveMobileTree.prototype = {
15607
15985
  console.log("that.approveStatus", that.approveStatus);
15608
15986
  });
15609
15987
  },
15988
+ visibleApprovers(step) {
15989
+ const people = step.approverDtoList || [];
15990
+ if (this.data.hideReplacedPendingApprovers !== true) return people;
15991
+ // Administrative replacement retains inactive rows for audit. Hide only
15992
+ // explicitly invalid rows without an approval outcome. isApprove can be
15993
+ // set in bulk when a node closes, including for previously replaced people.
15994
+ return people.filter(person => !(String(person.status) === '0' && (person.approveStatus == null || String(person.approveStatus) === '1') && !person.approveTime && !person.result));
15995
+ },
15610
15996
  uniqueByUserId(array) {
15611
15997
  return array.filter((item, index, arr) => {
15612
15998
  return arr.findIndex(it => it.userId === item.userId) === index;
@@ -15653,6 +16039,10 @@ approveMobileTree.prototype = {
15653
16039
  });
15654
16040
  }
15655
16041
  let optional = res.optional && res.optional.length > 0 ? res.optional : that.optionalList && that.optionalList.length > 0 ? JSON.stringify(that.optionalList) : null;
16042
+ const controlsEnabled = that.approveList.some(node => node.approvalControlsEnabled === true);
16043
+ if (controlsEnabled) {
16044
+ optional = JSON.stringify(mergeOptionalSelections(that.optionalList, res.optional));
16045
+ }
15656
16046
  let formDataList = null;
15657
16047
  if (that.data.editMainDeptLeader) {
15658
16048
  formDataList = [{
@@ -15668,6 +16058,7 @@ approveMobileTree.prototype = {
15668
16058
  optional: optional,
15669
16059
  formDataList: formDataList
15670
16060
  }, res);
16061
+ if (controlsEnabled) parm.optional = optional;
15671
16062
  console.log(parm);
15672
16063
  if (!that.ifBtn) return;
15673
16064
  that.ifBtn = false;
@@ -15732,10 +16123,10 @@ approveMobileTree.prototype = {
15732
16123
  });
15733
16124
  ;// CONCATENATED MODULE: ./src/components/approveLineAll.vue?vue&type=script&lang=js
15734
16125
  /* harmony default export */ var components_approveLineAllvue_type_script_lang_js = (approveLineAllvue_type_script_lang_js);
15735
- ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/approveLineAll.vue?vue&type=style&index=0&id=0171b230&prod&scoped=true&lang=css
16126
+ ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/approveLineAll.vue?vue&type=style&index=0&id=520f8838&prod&scoped=true&lang=css
15736
16127
  // extracted by mini-css-extract-plugin
15737
16128
 
15738
- ;// CONCATENATED MODULE: ./src/components/approveLineAll.vue?vue&type=style&index=0&id=0171b230&prod&scoped=true&lang=css
16129
+ ;// CONCATENATED MODULE: ./src/components/approveLineAll.vue?vue&type=style&index=0&id=520f8838&prod&scoped=true&lang=css
15739
16130
 
15740
16131
  ;// CONCATENATED MODULE: ./src/components/approveLineAll.vue
15741
16132
 
@@ -15748,18 +16139,18 @@ approveMobileTree.prototype = {
15748
16139
 
15749
16140
  var approveLineAll_component = normalizeComponent(
15750
16141
  components_approveLineAllvue_type_script_lang_js,
15751
- approveLineAllvue_type_template_id_0171b230_scoped_true_render,
15752
- approveLineAllvue_type_template_id_0171b230_scoped_true_staticRenderFns,
16142
+ approveLineAllvue_type_template_id_520f8838_scoped_true_render,
16143
+ approveLineAllvue_type_template_id_520f8838_scoped_true_staticRenderFns,
15753
16144
  false,
15754
16145
  null,
15755
- "0171b230",
16146
+ "520f8838",
15756
16147
  null
15757
16148
 
15758
16149
  )
15759
16150
 
15760
16151
  /* harmony default export */ var approveLineAll = (approveLineAll_component.exports);
15761
- ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/selectLine.vue?vue&type=template&id=59bf336a
15762
- var selectLinevue_type_template_id_59bf336a_render = function render() {
16152
+ ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/selectLine.vue?vue&type=template&id=1aa06fdd
16153
+ var selectLinevue_type_template_id_1aa06fdd_render = function render() {
15763
16154
  var _vm = this,
15764
16155
  _c = _vm._self._c;
15765
16156
  return _c('div', {
@@ -15792,7 +16183,7 @@ var selectLinevue_type_template_id_59bf336a_render = function render() {
15792
16183
  return _vm.deleteApprover(node, per.userId);
15793
16184
  }
15794
16185
  }
15795
- }, [_vm._v(_vm._s(per.name) + " "), _vm.ableEdit(node) ? _c('van-icon', {
16186
+ }, [_vm._v(_vm._s(per.name) + " "), _vm.canRemoveApprover(node) ? _c('van-icon', {
15796
16187
  staticClass: "badge-icon",
15797
16188
  attrs: {
15798
16189
  "name": "cross"
@@ -15848,6 +16239,23 @@ var selectLinevue_type_template_id_59bf336a_render = function render() {
15848
16239
  },
15849
16240
  expression: "showdialog"
15850
16241
  }
16242
+ }, [_c('van-field', {
16243
+ attrs: {
16244
+ "placeholder": "搜索姓名或账号",
16245
+ "clearable": ""
16246
+ },
16247
+ model: {
16248
+ value: _vm.candidateKeyword,
16249
+ callback: function ($$v) {
16250
+ _vm.candidateKeyword = $$v;
16251
+ },
16252
+ expression: "candidateKeyword"
16253
+ }
16254
+ }), _c('div', {
16255
+ staticStyle: {
16256
+ "max-height": "55vh",
16257
+ "overflow": "auto"
16258
+ }
15851
16259
  }, [_vm.selectPersonType == 1 ? _c('div', [_c('van-radio-group', {
15852
16260
  model: {
15853
16261
  value: _vm.radioSelect,
@@ -15856,7 +16264,7 @@ var selectLinevue_type_template_id_59bf336a_render = function render() {
15856
16264
  },
15857
16265
  expression: "radioSelect"
15858
16266
  }
15859
- }, [_c('van-cell-group', _vm._l(_vm.personList, function (item, index) {
16267
+ }, [_c('van-cell-group', _vm._l(_vm.filteredCandidates, function (item, index) {
15860
16268
  return _c('van-cell', {
15861
16269
  key: item.userId,
15862
16270
  attrs: {
@@ -15888,7 +16296,7 @@ var selectLinevue_type_template_id_59bf336a_render = function render() {
15888
16296
  },
15889
16297
  expression: "checkBoxList"
15890
16298
  }
15891
- }, [_c('van-cell-group', _vm._l(_vm.personList, function (item, index) {
16299
+ }, [_c('van-cell-group', _vm._l(_vm.filteredCandidates, function (item, index) {
15892
16300
  return _c('van-cell', {
15893
16301
  key: item.userId,
15894
16302
  attrs: {
@@ -15897,42 +16305,30 @@ var selectLinevue_type_template_id_59bf336a_render = function render() {
15897
16305
  },
15898
16306
  on: {
15899
16307
  "click": function ($event) {
15900
- return _vm.toggle(index);
16308
+ return _vm.togglePerson(item.userId);
15901
16309
  }
15902
16310
  },
15903
16311
  scopedSlots: _vm._u([{
15904
16312
  key: "right-icon",
15905
16313
  fn: function () {
15906
16314
  return [_c('van-checkbox', {
15907
- ref: "checkboxes",
15908
- refInFor: true,
15909
16315
  attrs: {
15910
16316
  "name": item.userId
16317
+ },
16318
+ on: {
16319
+ "click": function ($event) {
16320
+ $event.stopPropagation();
16321
+ }
15911
16322
  }
15912
16323
  })];
15913
16324
  },
15914
16325
  proxy: true
15915
16326
  }], null, true)
15916
16327
  });
15917
- }), 1)], 1)], 1)])], 1);
16328
+ }), 1)], 1)], 1)])], 1)], 1);
15918
16329
  };
15919
- var selectLinevue_type_template_id_59bf336a_staticRenderFns = [];
16330
+ var selectLinevue_type_template_id_1aa06fdd_staticRenderFns = [];
15920
16331
 
15921
- ;// CONCATENATED MODULE: ./src/utils/selectionScope.js
15922
- const isCopyScope = node => node && node.type === 'copy' && node.checker && String(node.checker.isOptional) === '1' && String(node.checker.selectArea) === '2' && (Number(node.checker.scopeVersion) === 1 || (node.checker.selectedDepts || []).length > 0);
15923
- const isScopedSelection = node => isCopyScope(node) || node && node.type === 'check' && node.checker && [7, 8].includes(Number(node.checker.type)) && String(node.checker.selectArea) === '2' && (Number(node.checker.scopeVersion) === 1 || (node.checker.selectedDepts || []).length > 0);
15924
- function normalizeCandidates(people) {
15925
- const unique = new Map();
15926
- for (const person of people || []) {
15927
- if (!person || String(person.type) === '2') continue;
15928
- const userId = person.userId || person.id;
15929
- if (userId) unique.set(String(userId), {
15930
- userId: String(userId),
15931
- name: person.name
15932
- });
15933
- }
15934
- return [...unique.values()];
15935
- }
15936
16332
  ;// CONCATENATED MODULE: ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/selectLine.vue?vue&type=script&lang=js
15937
16333
 
15938
16334
 
@@ -15968,9 +16364,16 @@ function normalizeCandidates(people) {
15968
16364
  showdialog: false,
15969
16365
  selectPersonType: 1,
15970
16366
  preNode: null,
15971
- scopeLoading: false
16367
+ scopeLoading: false,
16368
+ candidateKeyword: ''
15972
16369
  };
15973
16370
  },
16371
+ computed: {
16372
+ filteredCandidates() {
16373
+ const keyword = this.candidateKeyword.trim().toLowerCase();
16374
+ return this.personList.filter(p => !keyword || (p.name + ' ' + p.userId).toLowerCase().includes(keyword));
16375
+ }
16376
+ },
15974
16377
  mounted() {
15975
16378
  if (this.data) {
15976
16379
  let keyArray = ["baseUrl", "treeUrl", "uid"];
@@ -15993,6 +16396,10 @@ function normalizeCandidates(people) {
15993
16396
  }
15994
16397
  },
15995
16398
  methods: {
16399
+ canRemoveApprover: canRemoveApprover,
16400
+ togglePerson(id) {
16401
+ this.checkBoxList = this.checkBoxList.includes(id) ? this.checkBoxList.filter(value => value !== id) : [...this.checkBoxList, id];
16402
+ },
15996
16403
  radioSelectd(item) {
15997
16404
  var me = this;
15998
16405
  console.log(item);
@@ -16011,8 +16418,12 @@ function normalizeCandidates(people) {
16011
16418
  checkdList = me.personList.filter(item => me.checkBoxList.includes(item.userId));
16012
16419
  }
16013
16420
  }
16421
+ if (me.preNode && me.preNode.type === 'check' && !checkdList.length) {
16422
+ toast.fail('至少保留一位审批人');
16423
+ return;
16424
+ }
16014
16425
  me.approveList.forEach(node => {
16015
- if (checkdList && checkdList.length > 0 && node.id == me.preNode.id) {
16426
+ if (node.id == me.preNode.id) {
16016
16427
  node.list = checkdList;
16017
16428
  }
16018
16429
  });
@@ -16037,6 +16448,7 @@ function normalizeCandidates(people) {
16037
16448
  me.personList = [];
16038
16449
  me.radioSelect = null;
16039
16450
  me.checkBoxList = [];
16451
+ me.candidateKeyword = '';
16040
16452
  },
16041
16453
  toggle(index) {
16042
16454
  console.log(index);
@@ -16119,7 +16531,12 @@ function normalizeCandidates(people) {
16119
16531
  }
16120
16532
  // Only department role holders inside the configured range may be preselected.
16121
16533
  if (isCopyScope(item)) list = scopedRoleDefaults;
16534
+ if (item.approvalControlsEnabled === true && item.selectionRestricted === true && Number(item.checker.type) === 9 && String(item.checker.defaultApprover) === '1') list = item.selectionCandidates;
16535
+ list = constrainDefaults(item, list);
16122
16536
  return {
16537
+ selectionRestricted: item.selectionRestricted,
16538
+ selectionCandidates: item.selectionCandidates,
16539
+ approvalControlsEnabled: item.approvalControlsEnabled,
16123
16540
  id: item.id,
16124
16541
  type: item.type,
16125
16542
  name: item.name,
@@ -16130,7 +16547,8 @@ function normalizeCandidates(people) {
16130
16547
  editApprover: item.checker.editApprover,
16131
16548
  selectedPersons: item.checker.selectedPersons,
16132
16549
  isOptional: item.checker.isOptional,
16133
- list: this.uniqueByUserId(list)
16550
+ list: this.uniqueByUserId(list),
16551
+ defaultApproverIds: normalizeCandidates(list).map(person => person.userId)
16134
16552
  };
16135
16553
  });
16136
16554
  Promise.all(approveList).then(res => {
@@ -16151,24 +16569,23 @@ function normalizeCandidates(people) {
16151
16569
  });
16152
16570
  },
16153
16571
  ableEdit(node) {
16154
- if ([7, 8, 9].includes(node.checkertype) && node.editApprover == 1 || node.type == "copy" && node.isOptional == 1) {
16155
- return true;
16156
- } else {
16157
- return false;
16158
- }
16572
+ return canEditApprovers(node);
16159
16573
  },
16160
16574
  async addApprover(node) {
16575
+ if (!this.ableEdit(node)) return;
16161
16576
  let me = this;
16162
- const scoped = isScopedSelection(node);
16577
+ const scoped = hasCandidateRange(node);
16163
16578
  if (me.scopeLoading) return;
16164
16579
  if (scoped || (node.checker.type == 7 || node.checker.type == 8) && node.checker.selectArea == 2 && node.checker.selectedPersons && node.checker.selectedPersons.length > 0) {
16165
- let candidates = normalizeCandidates(node.checker.selectedPersons);
16580
+ let candidates = normalizeCandidates(node.selectionRestricted === true ? node.selectionCandidates : node.checker.selectedPersons);
16166
16581
  if (scoped && (me.data.aprId || me.data.id)) {
16167
16582
  me.scopeLoading = true;
16168
16583
  try {
16169
16584
  const response = await queryOptionalScopeUsers(me.SAAS_TENANT_API, {
16170
16585
  aprId: me.data.aprId,
16171
16586
  recordId: me.data.id,
16587
+ projectId: me.data.projectId,
16588
+ deptId: me.data.deptId,
16172
16589
  nodeId: node.id
16173
16590
  });
16174
16591
  if (Number(response.status) !== 200 || !Array.isArray(response.result && response.result.data)) throw new Error(response.message || '读取可选范围失败,请重试');
@@ -16216,6 +16633,10 @@ function normalizeCandidates(people) {
16216
16633
  });
16217
16634
  myTree2.init();
16218
16635
  myTree2.submitTree(function (res) {
16636
+ if (node.type === 'check' && (!res || !res.length)) {
16637
+ toast.fail('至少保留一位审批人');
16638
+ return;
16639
+ }
16219
16640
  node.list = res.map(item => {
16220
16641
  return {
16221
16642
  userId: item.key,
@@ -16230,10 +16651,18 @@ function normalizeCandidates(people) {
16230
16651
  },
16231
16652
  deleteApprover(node, userId) {
16232
16653
  console.log("deleteApprover", node, userId);
16233
- if (!this.ableEdit(node)) return;
16654
+ if (!this.ableEdit(node) && !canReduceDefaultApprovers(node)) return;
16655
+ if (!canRemoveApprover(node)) {
16656
+ toast.fail('至少保留一位审批人');
16657
+ return;
16658
+ }
16234
16659
  dialog.confirm({
16235
16660
  title: "是否确认删除该人员?"
16236
16661
  }).then(() => {
16662
+ if (!canRemoveApprover(node)) {
16663
+ toast.fail('至少保留一位审批人');
16664
+ return;
16665
+ }
16237
16666
  node.list = node.list.filter(item => {
16238
16667
  return item.userId != userId;
16239
16668
  });
@@ -16243,6 +16672,12 @@ function normalizeCandidates(people) {
16243
16672
  let submitFlag = true;
16244
16673
  let optionalUserList = [];
16245
16674
  this.approveList.forEach(item => {
16675
+ const selectionError = approvalSelectionError(item);
16676
+ if (selectionError) {
16677
+ submitFlag = false;
16678
+ toast.fail(selectionError);
16679
+ return;
16680
+ }
16246
16681
  if (item.type === 'check' && [7, 8, 9].includes(item.checkertype)) {
16247
16682
  if (item.list && item.list.length) {
16248
16683
  if (item.selectPersonType == 1 && item.list.length > 1 && item.editApprover == 1) {
@@ -16295,10 +16730,10 @@ function normalizeCandidates(people) {
16295
16730
  });
16296
16731
  ;// CONCATENATED MODULE: ./src/components/selectLine.vue?vue&type=script&lang=js
16297
16732
  /* harmony default export */ var components_selectLinevue_type_script_lang_js = (selectLinevue_type_script_lang_js);
16298
- ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/selectLine.vue?vue&type=style&index=0&id=59bf336a&prod&lang=css
16733
+ ;// CONCATENATED MODULE: ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/selectLine.vue?vue&type=style&index=0&id=1aa06fdd&prod&lang=css
16299
16734
  // extracted by mini-css-extract-plugin
16300
16735
 
16301
- ;// CONCATENATED MODULE: ./src/components/selectLine.vue?vue&type=style&index=0&id=59bf336a&prod&lang=css
16736
+ ;// CONCATENATED MODULE: ./src/components/selectLine.vue?vue&type=style&index=0&id=1aa06fdd&prod&lang=css
16302
16737
 
16303
16738
  ;// CONCATENATED MODULE: ./src/components/selectLine.vue
16304
16739
 
@@ -16311,8 +16746,8 @@ function normalizeCandidates(people) {
16311
16746
 
16312
16747
  var selectLine_component = normalizeComponent(
16313
16748
  components_selectLinevue_type_script_lang_js,
16314
- selectLinevue_type_template_id_59bf336a_render,
16315
- selectLinevue_type_template_id_59bf336a_staticRenderFns,
16749
+ selectLinevue_type_template_id_1aa06fdd_render,
16750
+ selectLinevue_type_template_id_1aa06fdd_staticRenderFns,
16316
16751
  false,
16317
16752
  null,
16318
16753
  null,