w-web-perm 1.1.12 → 1.1.13

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.
Files changed (124) hide show
  1. package/README.md +158 -123
  2. package/dist/css/app.f09c7433.css +1 -0
  3. package/dist/index.tmp +1 -1
  4. package/dist/js/app-legacy.8af87052.js +1 -0
  5. package/dist/js/app.8af87052.js +1 -0
  6. package/dist/js/{chunk-vendors.3e9e3ef1.js → chunk-vendors-legacy.ece5a361.js} +1 -1
  7. package/dist/js/{chunk-vendors-legacy.3e9e3ef1.js → chunk-vendors.ece5a361.js} +1 -1
  8. package/dist/w-web-perm.umd.js +2 -2
  9. package/dist/w-web-perm.umd.js.map +1 -1
  10. package/docs/WWebPerm.html +84 -4
  11. package/docs/global.html +23023 -1125
  12. package/docs/index.html +2 -2
  13. package/docs/server_WWebPerm.mjs.html +232 -32
  14. package/docs/server_cascadeWrite.mjs.html +225 -0
  15. package/docs/server_dataChannel.mjs.html +2 -2
  16. package/docs/server_keyCheck.mjs.html +353 -0
  17. package/docs/server_lockSave.mjs.html +2 -2
  18. package/docs/server_maskLog.mjs.html +2 -2
  19. package/docs/server_procCore.mjs.html +180 -41
  20. package/docs/server_staLogs_resolveShellWorker.mjs.html +2 -2
  21. package/docs/server_syncKeep.mjs.html +311 -0
  22. package/docs/server_tools_authRefsAudit.mjs.html +247 -0
  23. package/docs/server_tools_authRefsClean.mjs.html +335 -0
  24. package/docs/server_tools_fromTools.mjs.html +797 -0
  25. package/docs/server_tools_isMain.mjs.html +103 -0
  26. package/docs/server_tools_nameDupReport.mjs.html +280 -0
  27. package/docs/server_validateRows.mjs.html +2 -2
  28. package/docs/server_wrapInjected.mjs.html +3 -3
  29. package/docs/src_fetchJson.mjs.html +2 -2
  30. package/docs/src_js_cvKpToArr.mjs.html +2 -2
  31. package/docs/src_js_cvKpToObj.mjs.html +44 -33
  32. package/docs/src_js_draftSync.mjs.html +142 -0
  33. package/docs/src_js_eachOwn.mjs.html +3 -3
  34. package/docs/src_js_editorRefRows.mjs.html +356 -0
  35. package/docs/src_js_externalRows.mjs.html +338 -0
  36. package/docs/src_js_externalUi.mjs.html +230 -0
  37. package/docs/src_js_findRefRows.mjs.html +107 -0
  38. package/docs/src_js_findTouchedDup.mjs.html +150 -0
  39. package/docs/src_js_fmtLossyMsg.mjs.html +2 -2
  40. package/docs/src_js_fromAudit.mjs.html +489 -0
  41. package/docs/src_js_getAddImpact.mjs.html +269 -0
  42. package/docs/src_js_getAuthWarn.mjs.html +463 -0
  43. package/docs/src_js_getCascadePreview.mjs.html +258 -0
  44. package/docs/src_js_getDelRefCount.mjs.html +210 -0
  45. package/docs/src_js_getEffMode.mjs.html +92 -0
  46. package/docs/src_js_getKpLossy.mjs.html +47 -52
  47. package/docs/src_js_getNameErrs.mjs.html +266 -0
  48. package/docs/src_js_getOwn.mjs.html +3 -3
  49. package/docs/src_js_getPropKey.mjs.html +109 -0
  50. package/docs/src_js_getRuleEnable.mjs.html +2 -2
  51. package/docs/src_js_isAuthMode.mjs.html +4 -4
  52. package/docs/src_js_joinNames.mjs.html +2 -2
  53. package/docs/src_js_legendFit.mjs.html +2 -2
  54. package/docs/src_js_pairRowsToSnapshot.mjs.html +156 -0
  55. package/docs/src_js_refAudit.mjs.html +359 -0
  56. package/docs/src_js_refCascade.mjs.html +572 -0
  57. package/docs/src_js_relDialogSend.mjs.html +199 -0
  58. package/docs/src_js_rowDigest.mjs.html +265 -0
  59. package/docs/src_plugins_dataReloadGuard.mjs.html +109 -0
  60. package/docs/src_plugins_reuseDeletedIds.mjs.html +2 -2
  61. package/docs/src_plugins_submitGuard.mjs.html +2 -2
  62. package/g_authRefsClean.mjs +79 -0
  63. package/g_fixFromType.mjs +92 -0
  64. package/g_initialData.mjs +3 -3
  65. package/g_purgeFrom.mjs +127 -0
  66. package/package.json +1 -1
  67. package/server/WWebPerm.mjs +230 -30
  68. package/server/cascadeWrite.mjs +153 -0
  69. package/server/keyCheck.mjs +281 -0
  70. package/server/procCore.mjs +178 -39
  71. package/server/procLang.mjs +270 -3
  72. package/server/syncKeep.mjs +239 -0
  73. package/server/tools/authRefsAudit.mjs +175 -0
  74. package/server/tools/authRefsClean.mjs +263 -0
  75. package/server/tools/fromTools.mjs +725 -0
  76. package/server/tools/isMain.mjs +31 -0
  77. package/server/tools/nameDupReport.mjs +208 -0
  78. package/server/wrapInjected.mjs +1 -1
  79. package/src/components/LayoutContentGrups.vue +396 -75
  80. package/src/components/LayoutContentPemis.vue +395 -75
  81. package/src/components/LayoutContentTargets.vue +261 -25
  82. package/src/components/LayoutContentUsers.vue +334 -97
  83. package/src/components/VeCgrups.vue +88 -129
  84. package/src/components/VeCpemis.vue +86 -129
  85. package/src/components/VeCrules.vue +15 -5
  86. package/src/components/VeGrupBlngUsers.vue +202 -89
  87. package/src/components/VePemiBlngGrups.vue +209 -99
  88. package/src/js/cvKpToObj.mjs +42 -31
  89. package/src/js/draftSync.mjs +70 -0
  90. package/src/js/eachOwn.mjs +1 -1
  91. package/src/js/editorRefRows.mjs +284 -0
  92. package/src/js/externalRows.mjs +266 -0
  93. package/src/js/externalUi.mjs +158 -0
  94. package/src/js/findRefRows.mjs +35 -0
  95. package/src/js/findTouchedDup.mjs +78 -0
  96. package/src/js/fromAudit.mjs +417 -0
  97. package/src/js/getAddImpact.mjs +197 -0
  98. package/src/js/getAuthWarn.mjs +391 -0
  99. package/src/js/getCascadePreview.mjs +186 -0
  100. package/src/js/getDelRefCount.mjs +138 -0
  101. package/src/js/getEffMode.mjs +20 -0
  102. package/src/js/getKpLossy.mjs +44 -49
  103. package/src/js/getNameErrs.mjs +194 -0
  104. package/src/js/getOwn.mjs +1 -1
  105. package/src/js/getPropKey.mjs +37 -0
  106. package/src/js/isAuthMode.mjs +2 -2
  107. package/src/js/pairRowsToSnapshot.mjs +84 -0
  108. package/src/js/refAudit.mjs +287 -0
  109. package/src/js/refCascade.mjs +500 -0
  110. package/src/js/relDialogSend.mjs +127 -0
  111. package/src/js/rowDigest.mjs +193 -0
  112. package/src/plugins/dataReloadGuard.mjs +37 -0
  113. package/src/plugins/mShare.mjs +144 -140
  114. package/src/plugins/mUI.mjs +3 -8
  115. package/src/schema/tables/users.mjs +152 -152
  116. package/dist/css/app.6918ec45.css +0 -1
  117. package/dist/js/app-legacy.7cb7e394.js +0 -1
  118. package/dist/js/app.7cb7e394.js +0 -1
  119. package/docs/src_js_getKeyOrderLost.mjs.html +0 -121
  120. package/docs/src_js_getKpWriteLost.mjs.html +0 -100
  121. package/docs/src_js_keepKeyOrder.mjs.html +0 -139
  122. package/src/js/getKeyOrderLost.mjs +0 -49
  123. package/src/js/getKpWriteLost.mjs +0 -28
  124. package/src/js/keepKeyOrder.mjs +0 -67
@@ -25,6 +25,16 @@
25
25
  @domresize="resizeHead"
26
26
  >
27
27
 
28
+ <!-- 無法掛在任何一列之警告: 理由同 VeCgrups 該處註解(R-PRINCIPLE-00 f) -->
29
+ <div
30
+ style="padding:10px 15px; font-size:0.8rem; color:#F57C00; display:flex; align-items:center;"
31
+ :title="lossyHintTitle"
32
+ v-if="lossyHint"
33
+ >
34
+ <img style="flex:0 0 auto; width:16px; height:16px; margin-right:4px;" :src="$ui.getIcon('warning')" />
35
+ <span>{{ lossyHint }}</span>
36
+ </div>
37
+
28
38
  <!-- 功能區 -->
29
39
  <div
30
40
  style="padding:5px; background:#fff; display:flex; align-items:center;"
@@ -127,7 +137,11 @@
127
137
  :opt="opt"
128
138
  >
129
139
  <template v-slot:cell-render="props">
130
- <span v-if="props.key==='name'">{{ props.value }}</span>
140
+ <template v-if="props.key==='name'">
141
+ <!-- 警告圖示: 理由同 VeCgrups 該處註解(無警告者與修前同一節點) -->
142
+ <span :title="props.row.warnText" v-if="props.row.warnText"><img style="vertical-align:sub; width:16px; height:16px; margin-right:4px;" :src="$ui.getIcon('warning')" />{{ props.value }}</span>
143
+ <span v-else>{{ props.value }}</span>
144
+ </template>
131
145
  <!-- flex 置中容器: 理由同 VeCgrups 該處註解 -->
132
146
  <div
133
147
  style="display:flex; align-items:center; height:100%;"
@@ -175,14 +189,13 @@ import isEqual from 'lodash-es/isEqual.js'
175
189
  import cloneDeep from 'lodash-es/cloneDeep.js'
176
190
  import genPm from 'wsemi/src/genPm.mjs'
177
191
  import delay from 'wsemi/src/delay.mjs'
178
- import iseobj from 'wsemi/src/iseobj.mjs'
179
192
  import isestr from 'wsemi/src/isestr.mjs'
180
193
  import getOwn from '../js/getOwn.mjs'
181
194
  import cvKpToObj from '../js/cvKpToObj.mjs'
182
- import keepKeyOrder from '../js/keepKeyOrder.mjs'
183
195
  import getKpLossy from '../js/getKpLossy.mjs'
184
- import getKpWriteLost from '../js/getKpWriteLost.mjs'
185
196
  import fmtLossyMsg from '../js/fmtLossyMsg.mjs'
197
+ import { getRefState, getRefRowsExtra, getDupRowsInconsistent, getRawModeMap, putRowsToKp, getRowIdxs } from '../js/editorRefRows.mjs'
198
+ import { getRefWarns, getItemWarnText, fmtWarn } from '../js/getAuthWarn.mjs'
186
199
  import WDialog from 'w-component-vue/src/components/WDialog.vue'
187
200
  import WButtonCircle from 'w-component-vue/src/components/WButtonCircle.vue'
188
201
  import WAggridVue from 'w-aggrid-vue/src/components/WAggridVue.vue'
@@ -229,6 +242,9 @@ export default {
229
242
  itemsCheck: [],
230
243
  opt: null,
231
244
 
245
+ lossyHint: '', //無法掛在任何一列之警告文字(啟用而名稱非字串之項目), 無則 ''
246
+ lossyHintTitle: '',
247
+
232
248
  }
233
249
  },
234
250
  mounted: function() {
@@ -537,8 +553,8 @@ export default {
537
553
 
538
554
  let vo = this
539
555
 
540
- //check
541
- if (!isestr(name)) {
556
+ //check, 名稱 '' 為合法名稱(R-PRINCIPLE-00 f: 懸空之額外列可為 '', 須可改 mode/停用), 僅非字串者拒絕
557
+ if (typeof name !== 'string') {
542
558
  vo.$alert(`${vo.$t('cpemiEditNoName')}`, { type: 'error' })
543
559
  return
544
560
  }
@@ -546,30 +562,19 @@ export default {
546
562
  //rows
547
563
  let rows = get(vo, 'opt.rows', [])
548
564
 
549
- //find
550
- let r = null
551
- let kr = null
552
- each(rows, (v, k) => {
553
- if (get(v, 'name', '') === name) {
554
- r = v
555
- kr = k
556
- return false //跳出
557
- }
558
- })
565
+ //krs, 精確同名之全部列(getRowIdxs; 理由同 VeCgrups.showVeCgrupsToggleItemModeByName)
566
+ let krs = getRowIdxs(rows, 'name', name)
559
567
 
560
568
  //check
561
- if (!iseobj(r)) {
569
+ if (size(krs) === 0) {
562
570
  vo.$alert(`${vo.$t('cpemiEditNoTarget')}`, { type: 'error' })
563
571
  return
564
572
  }
565
573
 
566
- //mode
567
- // let mode = th.value
568
- // console.log('mode', mode)
569
-
570
574
  //set
571
- set(vo, `opt.rows[${kr}].mode`, mode)
572
- // console.log('vo.opt.rows[kr]', cloneDeep(vo.opt.rows[kr]))
575
+ each(krs, (kr) => {
576
+ set(vo, `opt.rows[${kr}].mode`, mode)
577
+ })
573
578
 
574
579
  //refresh
575
580
  vo.refresh()
@@ -584,8 +589,8 @@ export default {
584
589
 
585
590
  let vo = this
586
591
 
587
- //check
588
- if (!isestr(name)) {
592
+ //check, 名稱 '' 為合法名稱(同 showVeCpemisToggleItemModeByName)
593
+ if (typeof name !== 'string') {
589
594
  vo.$alert(`${vo.$t('cpemiEditNoName')}`, { type: 'error' })
590
595
  return
591
596
  }
@@ -593,31 +598,24 @@ export default {
593
598
  //rows
594
599
  let rows = get(vo, 'opt.rows', [])
595
600
 
596
- //find
597
- let r = null
598
- let kr = null
599
- each(rows, (v, k) => {
600
- if (get(v, 'name', '') === name) {
601
- r = v
602
- kr = k
603
- return false //跳出
604
- }
605
- })
601
+ //krs, 精確同名之全部列(理由同 showVeCpemisToggleItemModeByName)
602
+ let krs = getRowIdxs(rows, 'name', name)
606
603
 
607
604
  //check
608
- if (!iseobj(r)) {
605
+ if (size(krs) === 0) {
609
606
  vo.$alert(`${vo.$t('cpemiEditNoTarget')}`, { type: 'error' })
610
607
  return
611
608
  }
612
609
 
613
- //enable
614
- let _enable = get(r, 'enable', 'n')
610
+ //enable, 同名列狀態恆一致, 取第一列切換後套用全部
611
+ let _enable = get(rows[krs[0]], 'enable', 'n')
615
612
  let enable = _enable === 'y' ? 'n' : 'y'
616
613
  // console.log('enable', enable)
617
614
 
618
615
  //set
619
- set(vo, `opt.rows[${kr}].enable`, enable)
620
- // console.log('vo.opt.rows[kr]', cloneDeep(vo.opt.rows[kr]))
616
+ each(krs, (kr) => {
617
+ set(vo, `opt.rows[${kr}].enable`, enable)
618
+ })
621
619
 
622
620
  //refresh
623
621
  vo.refresh()
@@ -636,26 +634,15 @@ export default {
636
634
  let rows = get(vo, 'opt.rows', [])
637
635
  // console.log('rows', rows)
638
636
 
639
- //kpRow
640
- let kpRow = Object.create(null) //無原型: 鍵為使用者資料, 不得命中 constructor 等原型鍵(規則帳本 R-KEY-01)
641
- each(rows, (r, kr) => {
642
- kpRow[r.name] = kr
643
- })
644
-
645
637
  //rowsEff
646
638
  let rowsEff = vo.getDisplayData()
647
639
  // console.log('rowsEff', rowsEff)
648
640
 
649
- //toggle
641
+ //toggle, 每個顯示中之列對其精確同名之全部列一併套用(getRowIdxs; 理由同 VeCgrups.showVeCgrupsToggleItemsEnableAllYes)
650
642
  each(rowsEff, (r) => {
651
-
652
- //kr
653
- let kr = kpRow[r.name]
654
-
655
- //set
656
- set(vo, `opt.rows[${kr}].enable`, 'y')
657
- // console.log('vo.opt.rows[kr]', cloneDeep(vo.opt.rows[kr]))
658
-
643
+ each(getRowIdxs(rows, 'name', r.name), (kr) => {
644
+ set(vo, `opt.rows[${kr}].enable`, 'y')
645
+ })
659
646
  })
660
647
 
661
648
  //refresh
@@ -675,26 +662,15 @@ export default {
675
662
  let rows = get(vo, 'opt.rows', [])
676
663
  // console.log('rows', rows)
677
664
 
678
- //kpRow
679
- let kpRow = Object.create(null)
680
- each(rows, (r, kr) => {
681
- kpRow[r.name] = kr
682
- })
683
-
684
665
  //rowsEff
685
666
  let rowsEff = vo.getDisplayData()
686
667
  // console.log('rowsEff', rowsEff)
687
668
 
688
- //toggle
669
+ //toggle, 對精確同名之全部列一併套用(理由同 showVeCpemisToggleItemsEnableAllYes)
689
670
  each(rowsEff, (r) => {
690
-
691
- //kr
692
- let kr = kpRow[r.name]
693
-
694
- //set
695
- set(vo, `opt.rows[${kr}].enable`, 'n')
696
- // console.log('vo.opt.rows[kr]', cloneDeep(vo.opt.rows[kr]))
697
-
671
+ each(getRowIdxs(rows, 'name', r.name), (kr) => {
672
+ set(vo, `opt.rows[${kr}].enable`, 'n')
673
+ })
698
674
  })
699
675
 
700
676
  //refresh
@@ -714,29 +690,21 @@ export default {
714
690
  let rows = get(vo, 'opt.rows', [])
715
691
  // console.log('rows', rows)
716
692
 
717
- //kpRow
718
- let kpRow = Object.create(null)
719
- each(rows, (r, kr) => {
720
- kpRow[r.name] = kr
721
- })
722
-
723
693
  //rowsEff
724
694
  let rowsEff = vo.getDisplayData()
725
695
  // console.log('rowsEff', rowsEff)
726
696
 
727
- //toggle
697
+ //toggle, 對精確同名之全部列一併套用(理由同 showVeCpemisToggleItemsEnableAllYes; 同名列狀態一致, 各顯示列算出之反向值相同)
728
698
  each(rowsEff, (r) => {
729
699
 
730
- //kr
731
- let kr = kpRow[r.name]
732
-
733
700
  //enable
734
701
  let _enable = get(r, 'enable', 'n')
735
702
  let enable = _enable === 'y' ? 'n' : 'y'
736
703
 
737
704
  //set
738
- set(vo, `opt.rows[${kr}].enable`, enable)
739
- // console.log('vo.opt.rows[kr]', cloneDeep(vo.opt.rows[kr]))
705
+ each(getRowIdxs(rows, 'name', r.name), (kr) => {
706
+ set(vo, `opt.rows[${kr}].enable`, enable)
707
+ })
740
708
 
741
709
  })
742
710
 
@@ -805,43 +773,21 @@ export default {
805
773
  return false
806
774
  }
807
775
 
808
- //kpPemi
776
+ //同名多列(權限表之歷史同名, R-PRINCIPLE-00 d): 理由同 VeCgrups.doSave——不一致者拒存並點名, 一致者寫出一次
777
+ let namesDupBad = getDupRowsInconsistent(rows)
778
+ if (size(namesDupBad) > 0) {
779
+ vo.$ui.updateLoading(false) //showCheckYes 前關 loading(modal 阻斷期間避免 loading 疊在底下)
780
+ await vo.$dg.showCheckYes(fmtWarn(vo.$t('warnDupRowsInconsistent'), { names: namesDupBad }))
781
+ return false
782
+ }
783
+
784
+ //kpPemi: 名稱為字串之列(含名稱 '' 與懸空之額外列)皆寫出, 不得丟棄啟用中之引用(R-PRINCIPLE-00 c/f); 共用 putRowsToKp(unit-editorRows 往返不變式)
785
+ //限制項仍為開啟時之「AND、啟用」者寫回原始 mode(vo.rawModeMap; 理由同 VeCgrups.doSave)
809
786
  let kpPemi = Object.create(null)
810
- each(rows, (r) => {
811
- let name = get(r, 'name', '')
812
- let mode = get(r, 'mode', '')
813
- let enable = get(r, 'enable', '')
814
- if (!isestr(name)) {
815
- console.log(`invalid name`)
816
- return true //跳出換下一個
817
- }
818
- if (mode !== 'OR' && mode !== 'AND') {
819
- console.log(`invalid mode[${mode}]`)
820
- return true //跳出換下一個
821
- }
822
- if (!isestr(enable)) {
823
- console.log(`invalid enable`)
824
- return true //跳出換下一個
825
- }
826
- kpPemi[name] = {
827
- mode,
828
- isActive: enable,
829
- }
830
- })
787
+ putRowsToKp(kpPemi, rows, vo.rawModeMap)
831
788
  // console.log('kpPemi', kpPemi)
832
789
 
833
- //保留原鍵序(R-AUTH-ORDER-01, 主控複審 R3): 對話框為權限表序, 原字串已有之權限維持原相對順序、新增者附加於後;
834
- //伺服端 mergeRules 在沒有有效 OR 項時以第一個 AND 項為起始, 鍵序改變即改變授權
835
- let lostNames = getKpWriteLost(vo.kpOrig, kpPemi) //預期序由參考(解碼後之原資料)與欲寫出之物件於函數內導出
836
- kpPemi = keepKeyOrder(vo.kpOrig, kpPemi)
837
-
838
- //欲寫出之鍵序若被 JS 屬性序(整數式鍵恆先排)改變而使有效 AND 項之相對順序易位(如新啟用整數式名稱之 AND 權限)
839
- //→ 授權會改變, 編輯器無法在不改變授權下寫出, 拒存並顯示固定訊息(同無法無損表示, R-AUTH-LOSSY-01; 外審 minimax#2)
840
- if (size(lostNames) > 0) {
841
- vo.$ui.updateLoading(false) //showCheckYes 前關 loading
842
- await vo.$dg.showCheckYes(fmtLossyMsg(vo.$t('authLossyBlocked'), lostNames))
843
- return false
844
- }
790
+ //鍵序無關授權(R-AUTH-MERGE-00 第 4 條: 結果與項目之儲存順序、物件鍵序、陣列元素序無關), 故不需保留原鍵序, 亦無整數式名稱易位之拒存
845
791
 
846
792
  //cpemis
847
793
  let cpemis = JSON.stringify(kpPemi)
@@ -923,11 +869,13 @@ export default {
923
869
  //kpPemi, lossyNames(物件形式無法無損表示者, R-AUTH-LOSSY-01)
924
870
  let kpPemi = Object.create(null)
925
871
  let lossyNames = []
872
+ let rawModeMap = Object.create(null) //限制項之原始 mode(getRawModeMap), 存檔時未改者原樣寫回
926
873
  if (isestr(cpemis)) {
927
874
  try {
928
875
  let kpRaw = JSON5.parse(cpemis)
929
876
  kpPemi = cvKpToObj(kpRaw, { hasMode: true })
930
877
  lossyNames = getKpLossy(kpRaw)
878
+ rawModeMap = getRawModeMap(kpRaw)
931
879
  }
932
880
  catch (err) {
933
881
  console.log('cpemis', cpemis)
@@ -948,17 +896,9 @@ export default {
948
896
  let name = v.name
949
897
  // console.log('name', name)
950
898
 
951
- //mode
952
- let mode = get(p, 'mode', '')
953
- if (mode !== 'OR' && mode !== 'AND') {
954
- mode = 'OR'
955
- }
956
- // console.log('mode', mode)
957
-
958
- //enable
959
- let _enable = get(p, 'isActive', '')
960
- let enable = _enable === 'y' ? 'y' : 'n'
961
- // console.log('isActive', enable)
899
+ //mode, enable: 與伺服端同解讀(getRefState, 理由同 VeCgrups.show)
900
+ let { mode, enable } = getRefState(p)
901
+ // console.log('mode', mode, 'enable', enable)
962
902
 
963
903
  //r
964
904
  let r = {
@@ -970,17 +910,34 @@ export default {
970
910
 
971
911
  return r
972
912
  })
913
+
914
+ //額外列: 啟用中而權限表查無列之引用(懸空, 含名稱 '')各一列附於表列之後(理由同 VeCgrups.show, R-PRINCIPLE-00 c/f)
915
+ items = [...items, ...getRefRowsExtra(kpPemi, vo.pemis)]
916
+
917
+ //warnText: 各列引用之衝突提示(理由同 VeCgrups.show)
918
+ let resWarn = getRefWarns(cpemis, vo.pemis)
919
+ each(items, (r) => {
920
+ let codes = getOwn(resWarn.kpWarns, r.name, null)
921
+ if (codes !== null) {
922
+ r.warnText = getItemWarnText(codes, r.name, vo.$t, 'warnKindPemi')
923
+ }
924
+ })
973
925
  // console.log('items', items)
974
926
 
927
+ //lossyHint: 啟用而名稱非字串之項目(noName)無列可掛, 於內容區最上方提示(理由同 VeCgrups.show)
928
+ let namesNoName = resWarn.byCode.noName
929
+ vo.lossyHint = size(namesNoName) > 0 ? fmtWarn(vo.$t('warnRefNoName'), { names: namesNoName }) : ''
930
+ vo.lossyHintTitle = size(namesNoName) > 0 ? fmtLossyMsg(vo.$t('authLossyBlocked'), lossyNames) : ''
931
+
975
932
  //save
976
933
  vo.isEditable = isEditable
977
934
  vo.grup = grup
978
935
  vo.items = items
979
936
 
980
- //存檔依據(非響應式): 解碼後之原資料(保序參考)、原字串、有損名稱、開啟時之列內容
981
- vo.kpOrig = kpPemi
937
+ //存檔依據(非響應式): 原字串、有損名稱、開啟時之列內容(含額外列)
982
938
  vo.cpemisOrig = cpemis
983
939
  vo.lossyNames = lossyNames
940
+ vo.rawModeMap = rawModeMap
984
941
  vo.itemsInit = map(items, (r) => ({ name: r.name, mode: r.mode, enable: r.enable }))
985
942
 
986
943
  //genOpt
@@ -127,7 +127,11 @@
127
127
  :opt="opt"
128
128
  >
129
129
  <template v-slot:cell-render="props">
130
- <span v-if="props.key==='id'">{{ props.value }}</span>
130
+ <template v-if="props.key==='id'">
131
+ <!-- 警告圖示(R-PRINCIPLE-00 a 之提示): 僅該管理對象於原 crules 重複列且有勾有不勾時(warnText, show 時由 getRuleWarns 取得)才渲染於 ID 左側; 無警告者與修前同一節點(不預留空間) -->
132
+ <span :title="props.row.warnText" v-if="props.row.warnText"><img style="vertical-align:sub; width:16px; height:16px; margin-right:4px;" :src="$ui.getIcon('warning')" />{{ props.value }}</span>
133
+ <span v-else>{{ props.value }}</span>
134
+ </template>
131
135
  <input v-else-if="props.key==='enable'" type="checkbox" :checked="props.value === 'y'" @click="toggleItemEnableById(props.row.id)" :disabled="!isEditable" />
132
136
  <span v-else>{{ props.value }}</span>
133
137
  </template>
@@ -164,9 +168,10 @@ import genPm from 'wsemi/src/genPm.mjs'
164
168
  import delay from 'wsemi/src/delay.mjs'
165
169
  import iseobj from 'wsemi/src/iseobj.mjs'
166
170
  import isestr from 'wsemi/src/isestr.mjs'
171
+ import getOwn from '../js/getOwn.mjs'
167
172
  import getRuleEnable from '../js/getRuleEnable.mjs'
168
173
  import cvKpToObj from '../js/cvKpToObj.mjs'
169
- import keepKeyOrder from '../js/keepKeyOrder.mjs'
174
+ import { getRuleWarns, fmtWarn } from '../js/getAuthWarn.mjs'
170
175
  import WDialog from 'w-component-vue/src/components/WDialog.vue'
171
176
  import WButtonCircle from 'w-component-vue/src/components/WButtonCircle.vue'
172
177
  import WAggridVue from 'w-aggrid-vue/src/components/WAggridVue.vue'
@@ -740,8 +745,8 @@ export default {
740
745
  })
741
746
  // console.log('kpRule', kpRule)
742
747
 
743
- //保留原鍵序(R-AUTH-ORDER-01, 主控複審 R3): crules 之合併與順序無關(僅同名後者覆蓋, 解碼已等價), 與另四個編輯器統一套用使輸出穩定
744
- kpRule = keepKeyOrder(vo.kpOrig, kpRule)
748
+ //兩態(勾/不勾): 勾=y、不勾=n; 未列等同 n, 重存把「未列」寫成顯式 n 不改變授權(R-AUTH-MERGE-00 第 1 條)——不增第三種狀態
749
+ //鍵序無關授權(同條第 4 條), 不需保留原鍵序
745
750
 
746
751
  //crules
747
752
  let crules = JSON.stringify(kpRule)
@@ -828,6 +833,9 @@ export default {
828
833
  }
829
834
  // console.log('kpRule', kpRule)
830
835
 
836
+ //resRule: 原字串中同一管理對象重複列且有勾有不勾者(R-PRINCIPLE-00 a; 解碼已收嚴為 n, 與伺服端同), 供該列 ID 左側之警告圖示與 tooltip(存檔寫出顯式值即解除)
837
+ let resRule = getRuleWarns(crules)
838
+
831
839
  //items
832
840
  let items = map(vo.targets, (v) => {
833
841
  let enable = getRuleEnable(kpRule, v.id)
@@ -835,6 +843,9 @@ export default {
835
843
  id: v.id,
836
844
  enable,
837
845
  }
846
+ if (getOwn(resRule.kpConflict, v.id, false) === true) {
847
+ r.warnText = fmtWarn(vo.$t('warnRuleConflict'), { names: [v.id] })
848
+ }
838
849
  return r
839
850
  })
840
851
  // console.log('items', items)
@@ -843,7 +854,6 @@ export default {
843
854
  vo.isEditable = isEditable
844
855
  vo.pemi = pemi
845
856
  vo.items = items
846
- vo.kpOrig = kpRule //存檔依據(非響應式): 解碼後之原資料(保序參考)
847
857
 
848
858
  //genOpt
849
859
  vo.genOpt()