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.
- package/README.md +158 -123
- package/dist/css/app.f09c7433.css +1 -0
- package/dist/index.tmp +1 -1
- package/dist/js/app-legacy.8af87052.js +1 -0
- package/dist/js/app.8af87052.js +1 -0
- package/dist/js/{chunk-vendors.3e9e3ef1.js → chunk-vendors-legacy.ece5a361.js} +1 -1
- package/dist/js/{chunk-vendors-legacy.3e9e3ef1.js → chunk-vendors.ece5a361.js} +1 -1
- package/dist/w-web-perm.umd.js +2 -2
- package/dist/w-web-perm.umd.js.map +1 -1
- package/docs/WWebPerm.html +84 -4
- package/docs/global.html +23023 -1125
- package/docs/index.html +2 -2
- package/docs/server_WWebPerm.mjs.html +232 -32
- package/docs/server_cascadeWrite.mjs.html +225 -0
- package/docs/server_dataChannel.mjs.html +2 -2
- package/docs/server_keyCheck.mjs.html +353 -0
- package/docs/server_lockSave.mjs.html +2 -2
- package/docs/server_maskLog.mjs.html +2 -2
- package/docs/server_procCore.mjs.html +180 -41
- package/docs/server_staLogs_resolveShellWorker.mjs.html +2 -2
- package/docs/server_syncKeep.mjs.html +311 -0
- package/docs/server_tools_authRefsAudit.mjs.html +247 -0
- package/docs/server_tools_authRefsClean.mjs.html +335 -0
- package/docs/server_tools_fromTools.mjs.html +797 -0
- package/docs/server_tools_isMain.mjs.html +103 -0
- package/docs/server_tools_nameDupReport.mjs.html +280 -0
- package/docs/server_validateRows.mjs.html +2 -2
- package/docs/server_wrapInjected.mjs.html +3 -3
- package/docs/src_fetchJson.mjs.html +2 -2
- package/docs/src_js_cvKpToArr.mjs.html +2 -2
- package/docs/src_js_cvKpToObj.mjs.html +44 -33
- package/docs/src_js_draftSync.mjs.html +142 -0
- package/docs/src_js_eachOwn.mjs.html +3 -3
- package/docs/src_js_editorRefRows.mjs.html +356 -0
- package/docs/src_js_externalRows.mjs.html +338 -0
- package/docs/src_js_externalUi.mjs.html +230 -0
- package/docs/src_js_findRefRows.mjs.html +107 -0
- package/docs/src_js_findTouchedDup.mjs.html +150 -0
- package/docs/src_js_fmtLossyMsg.mjs.html +2 -2
- package/docs/src_js_fromAudit.mjs.html +489 -0
- package/docs/src_js_getAddImpact.mjs.html +269 -0
- package/docs/src_js_getAuthWarn.mjs.html +463 -0
- package/docs/src_js_getCascadePreview.mjs.html +258 -0
- package/docs/src_js_getDelRefCount.mjs.html +210 -0
- package/docs/src_js_getEffMode.mjs.html +92 -0
- package/docs/src_js_getKpLossy.mjs.html +47 -52
- package/docs/src_js_getNameErrs.mjs.html +266 -0
- package/docs/src_js_getOwn.mjs.html +3 -3
- package/docs/src_js_getPropKey.mjs.html +109 -0
- package/docs/src_js_getRuleEnable.mjs.html +2 -2
- package/docs/src_js_isAuthMode.mjs.html +4 -4
- package/docs/src_js_joinNames.mjs.html +2 -2
- package/docs/src_js_legendFit.mjs.html +2 -2
- package/docs/src_js_pairRowsToSnapshot.mjs.html +156 -0
- package/docs/src_js_refAudit.mjs.html +359 -0
- package/docs/src_js_refCascade.mjs.html +572 -0
- package/docs/src_js_relDialogSend.mjs.html +199 -0
- package/docs/src_js_rowDigest.mjs.html +265 -0
- package/docs/src_plugins_dataReloadGuard.mjs.html +109 -0
- package/docs/src_plugins_reuseDeletedIds.mjs.html +2 -2
- package/docs/src_plugins_submitGuard.mjs.html +2 -2
- package/g_authRefsClean.mjs +79 -0
- package/g_fixFromType.mjs +92 -0
- package/g_initialData.mjs +3 -3
- package/g_purgeFrom.mjs +127 -0
- package/package.json +1 -1
- package/server/WWebPerm.mjs +230 -30
- package/server/cascadeWrite.mjs +153 -0
- package/server/keyCheck.mjs +281 -0
- package/server/procCore.mjs +178 -39
- package/server/procLang.mjs +270 -3
- package/server/syncKeep.mjs +239 -0
- package/server/tools/authRefsAudit.mjs +175 -0
- package/server/tools/authRefsClean.mjs +263 -0
- package/server/tools/fromTools.mjs +725 -0
- package/server/tools/isMain.mjs +31 -0
- package/server/tools/nameDupReport.mjs +208 -0
- package/server/wrapInjected.mjs +1 -1
- package/src/components/LayoutContentGrups.vue +396 -75
- package/src/components/LayoutContentPemis.vue +395 -75
- package/src/components/LayoutContentTargets.vue +261 -25
- package/src/components/LayoutContentUsers.vue +334 -97
- package/src/components/VeCgrups.vue +88 -129
- package/src/components/VeCpemis.vue +86 -129
- package/src/components/VeCrules.vue +15 -5
- package/src/components/VeGrupBlngUsers.vue +202 -89
- package/src/components/VePemiBlngGrups.vue +209 -99
- package/src/js/cvKpToObj.mjs +42 -31
- package/src/js/draftSync.mjs +70 -0
- package/src/js/eachOwn.mjs +1 -1
- package/src/js/editorRefRows.mjs +284 -0
- package/src/js/externalRows.mjs +266 -0
- package/src/js/externalUi.mjs +158 -0
- package/src/js/findRefRows.mjs +35 -0
- package/src/js/findTouchedDup.mjs +78 -0
- package/src/js/fromAudit.mjs +417 -0
- package/src/js/getAddImpact.mjs +197 -0
- package/src/js/getAuthWarn.mjs +391 -0
- package/src/js/getCascadePreview.mjs +186 -0
- package/src/js/getDelRefCount.mjs +138 -0
- package/src/js/getEffMode.mjs +20 -0
- package/src/js/getKpLossy.mjs +44 -49
- package/src/js/getNameErrs.mjs +194 -0
- package/src/js/getOwn.mjs +1 -1
- package/src/js/getPropKey.mjs +37 -0
- package/src/js/isAuthMode.mjs +2 -2
- package/src/js/pairRowsToSnapshot.mjs +84 -0
- package/src/js/refAudit.mjs +287 -0
- package/src/js/refCascade.mjs +500 -0
- package/src/js/relDialogSend.mjs +127 -0
- package/src/js/rowDigest.mjs +193 -0
- package/src/plugins/dataReloadGuard.mjs +37 -0
- package/src/plugins/mShare.mjs +144 -140
- package/src/plugins/mUI.mjs +3 -8
- package/src/schema/tables/users.mjs +152 -152
- package/dist/css/app.6918ec45.css +0 -1
- package/dist/js/app-legacy.7cb7e394.js +0 -1
- package/dist/js/app.7cb7e394.js +0 -1
- package/docs/src_js_getKeyOrderLost.mjs.html +0 -121
- package/docs/src_js_getKpWriteLost.mjs.html +0 -100
- package/docs/src_js_keepKeyOrder.mjs.html +0 -139
- package/src/js/getKeyOrderLost.mjs +0 -49
- package/src/js/getKpWriteLost.mjs +0 -28
- package/src/js/keepKeyOrder.mjs +0 -67
|
@@ -126,6 +126,17 @@
|
|
|
126
126
|
|
|
127
127
|
</div>
|
|
128
128
|
|
|
129
|
+
<!-- 資料已被更新提示(R-PRINCIPLE-00 原則 7): 開框後他人或外部同步改了群組表, 本視窗之草稿與基準維持開框時之版本、不重建, 存檔將被伺服端拒收; 以 v-for 渲染(無提示時不渲染任何節點) -->
|
|
130
|
+
<div
|
|
131
|
+
v-for="ks in (staleNotice ? 1 : 0)"
|
|
132
|
+
:key="`stale-${ks}`"
|
|
133
|
+
data-fmid="pemi-blng-grups-banner-stale"
|
|
134
|
+
style="padding:5px 15px; border-top:1px solid #ddd; background:#FFE0B2; color:#444; font-size:0.8rem; overflow-wrap:anywhere;"
|
|
135
|
+
>
|
|
136
|
+
<img style="vertical-align:sub; width:16px; height:16px; margin-right:4px;" :src="$ui.getIcon('warning')" />
|
|
137
|
+
<span>{{ $t('staleDraftNoticeDialog') }}</span>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
129
140
|
</div>
|
|
130
141
|
|
|
131
142
|
<template
|
|
@@ -140,16 +151,32 @@
|
|
|
140
151
|
:opt="opt"
|
|
141
152
|
>
|
|
142
153
|
<template v-slot:cell-render="props">
|
|
154
|
+
<!-- 警告圖示: 該列群組之 cpemis 有衝突時於「所屬權限名稱」儲存格最左顯示, 理由與版面同 VeGrupBlngUsers 該處註解(無警告者與修前同一節點) -->
|
|
155
|
+
<div
|
|
156
|
+
style="display:flex; align-items:center; height:100%;"
|
|
157
|
+
v-if="props.key==='pemisNames' && props.row.warnText"
|
|
158
|
+
>
|
|
159
|
+
<span style="flex:0 0 auto; display:flex; align-items:center;" :title="props.row.warnText"><img style="vertical-align:sub; width:16px; height:16px; margin-right:4px;" :src="$ui.getIcon('warning')" /></span>
|
|
160
|
+
<RelationChips
|
|
161
|
+
style="flex:1 1 auto;"
|
|
162
|
+
:items="props.row.pemis"
|
|
163
|
+
:editable="isEditable"
|
|
164
|
+
:popupTitle="$t('belongPemisNames')"
|
|
165
|
+
:tooltipAll="$t('chipsShowAll')"
|
|
166
|
+
:labelContent="'modeSelect'"
|
|
167
|
+
@input="(item)=>{showVePemiBlngGrupsToggleItemModeByName(props.row.name, item, props.row.id)}"
|
|
168
|
+
></RelationChips>
|
|
169
|
+
</div>
|
|
143
170
|
<RelationChips
|
|
144
|
-
v-if="props.key==='pemisNames'"
|
|
171
|
+
v-else-if="props.key==='pemisNames'"
|
|
145
172
|
:items="props.row.pemis"
|
|
146
173
|
:editable="isEditable"
|
|
147
174
|
:popupTitle="$t('belongPemisNames')"
|
|
148
175
|
:tooltipAll="$t('chipsShowAll')"
|
|
149
176
|
:labelContent="'modeSelect'"
|
|
150
|
-
@input="(item)=>{showVePemiBlngGrupsToggleItemModeByName(props.row.name, item)}"
|
|
177
|
+
@input="(item)=>{showVePemiBlngGrupsToggleItemModeByName(props.row.name, item, props.row.id)}"
|
|
151
178
|
></RelationChips>
|
|
152
|
-
<input v-else-if="props.key==='enable'" type="checkbox" :checked="props.value === 'y'" @click="showVePemiBlngGrupsToggleItemEnableByName(props.row.name)" :disabled="!isEditable" />
|
|
179
|
+
<input v-else-if="props.key==='enable'" type="checkbox" :checked="props.value === 'y'" @click="showVePemiBlngGrupsToggleItemEnableByName(props.row.name, props.row.id)" :disabled="!isEditable" />
|
|
153
180
|
<span v-else>{{ props.value }}</span>
|
|
154
181
|
</template>
|
|
155
182
|
</WAggridVue>
|
|
@@ -181,7 +208,6 @@ import size from 'lodash-es/size.js'
|
|
|
181
208
|
import filter from 'lodash-es/filter.js'
|
|
182
209
|
import join from 'lodash-es/join.js'
|
|
183
210
|
import sortBy from 'lodash-es/sortBy.js'
|
|
184
|
-
import isEqual from 'lodash-es/isEqual.js'
|
|
185
211
|
import cloneDeep from 'lodash-es/cloneDeep.js'
|
|
186
212
|
import genPm from 'wsemi/src/genPm.mjs'
|
|
187
213
|
import haskey from 'wsemi/src/haskey.mjs'
|
|
@@ -192,8 +218,13 @@ import eachOwn from '../js/eachOwn.mjs'
|
|
|
192
218
|
import getOwn from '../js/getOwn.mjs'
|
|
193
219
|
import cvKpToObj from '../js/cvKpToObj.mjs'
|
|
194
220
|
import getKpLossy from '../js/getKpLossy.mjs'
|
|
195
|
-
import getKpWriteLost from '../js/getKpWriteLost.mjs'
|
|
196
221
|
import fmtLossyMsg from '../js/fmtLossyMsg.mjs'
|
|
222
|
+
import pairRowsToSnapshot from '../js/pairRowsToSnapshot.mjs'
|
|
223
|
+
import { makeBaseline } from '../js/rowDigest.mjs'
|
|
224
|
+
import { isDraftStale } from '../js/draftSync.mjs'
|
|
225
|
+
import { makeRowStates, getChangedIdx, buildRowsSend } from '../js/relDialogSend.mjs'
|
|
226
|
+
import { getRefState, getRawModeMap, putRefEntry } from '../js/editorRefRows.mjs'
|
|
227
|
+
import { getRefWarns, getRefWarnText } from '../js/getAuthWarn.mjs'
|
|
197
228
|
import WDialog from 'w-component-vue/src/components/WDialog.vue'
|
|
198
229
|
import WButtonCircle from 'w-component-vue/src/components/WButtonCircle.vue'
|
|
199
230
|
import WAggridVue from 'w-aggrid-vue/src/components/WAggridVue.vue'
|
|
@@ -233,9 +264,16 @@ export default {
|
|
|
233
264
|
firstSetting: true,
|
|
234
265
|
isEditable: false,
|
|
235
266
|
isModified: false,
|
|
267
|
+
ownSaving: false, //本視窗自己之存檔已送出(成功後視窗隨即關閉): 自己之寫入所致之推播(grups 表更新)不是「他人更新」, watch 不得據以提示; 每次 show() 歸零, 存檔失敗時歸零
|
|
236
268
|
|
|
237
269
|
pemi: null,
|
|
238
270
|
|
|
271
|
+
//baseline, rowStates: 開框(show)時綁定之草稿基準(F-26, R-BASELINE-01), 之後 store 推播變新不更新, 每次 show() 重新綁定;
|
|
272
|
+
//baseline 為草稿所依據之那份群組列之逐列內容指紋, 存檔隨 updateGrups 第 2 參送伺服端; rowStates 為開框時各列之歸屬狀態, 存檔時判定使用者有無變更該列
|
|
273
|
+
baseline: null,
|
|
274
|
+
rowStates: null,
|
|
275
|
+
staleNotice: false, //有未存編輯時收到推播、且群組表已異於本視窗載入時之基準(R-PRINCIPLE-00 原則 7): true 時顯示「資料已被更新」提示; 每次 show() 歸零
|
|
276
|
+
|
|
239
277
|
items: [],
|
|
240
278
|
itemsCheck: [],
|
|
241
279
|
opt: null,
|
|
@@ -265,6 +303,17 @@ export default {
|
|
|
265
303
|
}
|
|
266
304
|
|
|
267
305
|
},
|
|
306
|
+
watch: {
|
|
307
|
+
//store 之群組表被推播更新(整表以新陣列取代): 本視窗不重建(草稿與基準維持開框時之版本, 見 show()). 此刻有未存編輯者, 若表已異於載入時之基準(任一列內容不同或列增刪; 僅 order/伺服器管理欄不同不算)
|
|
308
|
+
//即顯示「資料已被更新」提示, 存檔時由伺服端以表雜湊拒收(saveStale); 無未存編輯者維持原行為(靜默, 存檔時才由伺服端拒收). 唯讀檢視無存檔, 不提示
|
|
309
|
+
grups: function(rows) {
|
|
310
|
+
let vo = this
|
|
311
|
+
if (!vo.bShow || !vo.isEditable || !vo.isModified || vo.ownSaving || !Array.isArray(vo.baseline)) {
|
|
312
|
+
return
|
|
313
|
+
}
|
|
314
|
+
vo.staleNotice = isDraftStale({ keys: vo.$ds.grups.keys, rows, baseline: vo.baseline })
|
|
315
|
+
},
|
|
316
|
+
},
|
|
268
317
|
computed: {
|
|
269
318
|
|
|
270
319
|
syncState: function() {
|
|
@@ -548,6 +597,23 @@ export default {
|
|
|
548
597
|
return rows
|
|
549
598
|
},
|
|
550
599
|
|
|
600
|
+
getDisplayRows: function() {
|
|
601
|
+
let vo = this
|
|
602
|
+
|
|
603
|
+
//cmp
|
|
604
|
+
let cmp = get(vo, '$refs.rftable')
|
|
605
|
+
// console.log('cmp', cmp)
|
|
606
|
+
|
|
607
|
+
//getDisplayData 只回傳顯示中之欄位(name/enable/pemisNames), 不含 id; 批次勾選須以 id 定位列(群組表可有歷史同名), 故另以 ag-grid api 取篩選排序後之完整列(含 id), 同 VeGrupBlngUsers
|
|
608
|
+
let api = cmp.getApi()
|
|
609
|
+
let rows = []
|
|
610
|
+
api.forEachNodeAfterFilterAndSort((node) => {
|
|
611
|
+
rows.push(node.data)
|
|
612
|
+
})
|
|
613
|
+
|
|
614
|
+
return rows
|
|
615
|
+
},
|
|
616
|
+
|
|
551
617
|
fltKpPemi: function(kp) {
|
|
552
618
|
// console.log('fltKpPemi', kp)
|
|
553
619
|
|
|
@@ -579,8 +645,12 @@ export default {
|
|
|
579
645
|
//items
|
|
580
646
|
let items = map(grups, (g) => {
|
|
581
647
|
|
|
582
|
-
//kpPemi
|
|
583
|
-
let kpPemi =
|
|
648
|
+
//kpPemi, 空字串(新增列之 funNew 預設值)與壞 JSON 視為空容器, 同 VeCpemis/清單頁/伺服端(R-REL-PARSE-01: 任一列解碼失敗不得使對話框打不開)
|
|
649
|
+
let kpPemi = Object.create(null)
|
|
650
|
+
try {
|
|
651
|
+
kpPemi = cvKpToObj(JSON5.parse(g.cpemis), { hasMode: true })
|
|
652
|
+
}
|
|
653
|
+
catch (err) {}
|
|
584
654
|
// console.log(g.name, 'kpPemi', kpPemi)
|
|
585
655
|
|
|
586
656
|
//fltKpPemi
|
|
@@ -594,16 +664,12 @@ export default {
|
|
|
594
664
|
eachOwn(kpPemi, (v, k) => {
|
|
595
665
|
// console.log(k, 'v', v)
|
|
596
666
|
|
|
597
|
-
//
|
|
598
|
-
let
|
|
599
|
-
if (
|
|
667
|
+
//st, 此為使用者cpemis內設定, 可為y或n, 僅提取y, 再判斷此使用者是否有使用此pemi; 與伺服端同解讀(getRefState, 理由同 VeGrupBlngUsers.genItems)
|
|
668
|
+
let st = getRefState(v)
|
|
669
|
+
if (st.enable !== 'y') {
|
|
600
670
|
return true //跳出換下一個
|
|
601
671
|
}
|
|
602
|
-
// console.log(k, '
|
|
603
|
-
|
|
604
|
-
//_mode
|
|
605
|
-
let _mode = get(v, 'mode', '')
|
|
606
|
-
// console.log(k, '_mode', _mode)
|
|
672
|
+
// console.log(k, 'st', st)
|
|
607
673
|
|
|
608
674
|
//b, 使用者是否擁有指定權限群組
|
|
609
675
|
let b = k === pemi.name
|
|
@@ -612,14 +678,15 @@ export default {
|
|
|
612
678
|
//mode, isActive
|
|
613
679
|
if (b) {
|
|
614
680
|
enable = 'y'
|
|
615
|
-
mode =
|
|
681
|
+
mode = st.mode //使用使用者給予cpemis內指定權限群組之合併權限模式
|
|
616
682
|
// console.log('使用使用者給予cpemis內指定權限群組之合併權限模式 pemi', pemi)
|
|
617
683
|
}
|
|
618
684
|
|
|
619
|
-
//push
|
|
685
|
+
//push, 僅供 RelationChips 顯示(name/mode/enable); 存檔不讀本陣列(doSave 以 putRefEntry 自快照字串只改本權限一項)
|
|
620
686
|
pemis.push({
|
|
621
687
|
name: k,
|
|
622
|
-
|
|
688
|
+
mode: st.mode,
|
|
689
|
+
isActive: 'y',
|
|
623
690
|
enable: b ? 'y' : 'n', //給render使用
|
|
624
691
|
})
|
|
625
692
|
|
|
@@ -631,13 +698,19 @@ export default {
|
|
|
631
698
|
pemisNames = join(pemisNames, ' ')
|
|
632
699
|
// console.log(g.name, 'pemisNames', pemisNames)
|
|
633
700
|
|
|
701
|
+
//warnText: 該群組 cpemis 之衝突提示(理由同 VeGrupBlngUsers.genItems; revRows 不回寫本欄, 警告反映開啟時之已儲存資料)
|
|
702
|
+
let resWarn = getRefWarns(g.cpemis, vo.pemis)
|
|
703
|
+
let warnText = resWarn.hasWarn ? getRefWarnText(resWarn, vo.$t, 'warnKindPemi') : ''
|
|
704
|
+
|
|
634
705
|
return {
|
|
706
|
+
id: g.id, //列識別: 存檔時以 id(並驗 name)配對存檔當下之群組快照, 不以列索引(R-REL-PAIR-01)
|
|
635
707
|
name: g.name,
|
|
636
708
|
pemisNames,
|
|
637
709
|
mode,
|
|
638
710
|
enable,
|
|
639
711
|
// kpPemi,
|
|
640
712
|
pemis,
|
|
713
|
+
warnText,
|
|
641
714
|
}
|
|
642
715
|
})
|
|
643
716
|
// console.log(g.name, 'items', items)
|
|
@@ -662,11 +735,20 @@ export default {
|
|
|
662
735
|
let rows = get(vo, 'opt.rows', [])
|
|
663
736
|
// console.log('rows', rows)
|
|
664
737
|
|
|
738
|
+
//以列身分(id)配對: 對話框之列 ↔ 目前 store 中同一個群組(R-REL-PAIR-01; 不得以列索引配對——store 於對話框開啟期間可被更新〔他人增刪、改 order〕而錯位), 並驗 name 相同(改名視為過期)
|
|
739
|
+
//krs, grupsRev: 對話框有列且 store 仍存在之群組(grupsRev[k] 即第 krs[k] 列所配到者; 配對不到者不更新其顯示, 存檔時由 doSave 整次拒存)
|
|
740
|
+
let { krs, matched: grupsRev } = pairRowsToSnapshot(rows, grups, { verifyKeys: ['name'] })
|
|
741
|
+
|
|
665
742
|
//grups
|
|
666
|
-
grups = map(
|
|
743
|
+
grups = map(grupsRev, (g, kg) => {
|
|
744
|
+
let row = get(rows, krs[kg], {})
|
|
667
745
|
|
|
668
|
-
//kpPemi
|
|
669
|
-
let kpPemi =
|
|
746
|
+
//kpPemi, 空字串與壞 JSON 視為空容器(R-REL-PARSE-01)
|
|
747
|
+
let kpPemi = Object.create(null)
|
|
748
|
+
try {
|
|
749
|
+
kpPemi = cvKpToObj(JSON5.parse(g.cpemis), { hasMode: true })
|
|
750
|
+
}
|
|
751
|
+
catch (err) {}
|
|
670
752
|
// console.log(g.name, 'kpPemi', kpPemi)
|
|
671
753
|
|
|
672
754
|
//fltKpPemi
|
|
@@ -674,7 +756,7 @@ export default {
|
|
|
674
756
|
// console.log(g.name, 'kpPemi(fltKpPemi)', kpPemi)
|
|
675
757
|
|
|
676
758
|
//mode
|
|
677
|
-
let mode = get(
|
|
759
|
+
let mode = get(row, 'mode', '')
|
|
678
760
|
if (mode !== 'OR' && mode !== 'AND') {
|
|
679
761
|
console.log(`非預期: mode應該皆已指定不應觸發`, mode)
|
|
680
762
|
mode = 'OR'
|
|
@@ -682,7 +764,7 @@ export default {
|
|
|
682
764
|
// console.log(g.name, 'mode', mode)
|
|
683
765
|
|
|
684
766
|
//enable
|
|
685
|
-
let enable = get(
|
|
767
|
+
let enable = get(row, 'enable', '')
|
|
686
768
|
if (enable !== 'y' && enable !== 'n') {
|
|
687
769
|
console.log(`非預期: enable應該皆已指定不應觸發`, enable)
|
|
688
770
|
enable = 'n'
|
|
@@ -715,8 +797,8 @@ export default {
|
|
|
715
797
|
let items = vo.genItems(pemi, grups)
|
|
716
798
|
// console.log('items', items)
|
|
717
799
|
|
|
718
|
-
//update pemisNames, pemis
|
|
719
|
-
each(items, (r,
|
|
800
|
+
//update pemisNames, pemis, items 與 krs 同序(item k 對應對話框第 krs[k] 列)
|
|
801
|
+
each(items, (r, k) => {
|
|
720
802
|
// name: g.name,
|
|
721
803
|
// pemisNames,
|
|
722
804
|
// mode,
|
|
@@ -724,6 +806,7 @@ export default {
|
|
|
724
806
|
// pemis,
|
|
725
807
|
|
|
726
808
|
//set
|
|
809
|
+
let kr = krs[k]
|
|
727
810
|
set(vo, `opt.rows[${kr}].pemisNames`, r.pemisNames)
|
|
728
811
|
set(vo, `opt.rows[${kr}].pemis`, r.pemis)
|
|
729
812
|
// console.log('vo.opt.rows[kr]', cloneDeep(vo.opt.rows[kr]))
|
|
@@ -735,8 +818,8 @@ export default {
|
|
|
735
818
|
|
|
736
819
|
},
|
|
737
820
|
|
|
738
|
-
showVePemiBlngGrupsToggleItemModeByName: function(name, mode) {
|
|
739
|
-
// console.log('showVePemiBlngGrupsToggleItemModeByName', name, mode)
|
|
821
|
+
showVePemiBlngGrupsToggleItemModeByName: function(name, mode, id) {
|
|
822
|
+
// console.log('showVePemiBlngGrupsToggleItemModeByName', name, mode, id)
|
|
740
823
|
|
|
741
824
|
let vo = this
|
|
742
825
|
|
|
@@ -749,11 +832,11 @@ export default {
|
|
|
749
832
|
//rows
|
|
750
833
|
let rows = get(vo, 'opt.rows', [])
|
|
751
834
|
|
|
752
|
-
//find
|
|
835
|
+
//find, 有 id 以 id 找列(群組表可有歷史同名〔外部同步〕, 以 name 會改到第一個同名群組、存檔依 id 寫入錯列; 同 VeGrupBlngUsers); 未給 id 之既有 $dg 呼叫端維持以 name 找
|
|
753
836
|
let r = null
|
|
754
837
|
let kr = null
|
|
755
838
|
each(rows, (v, k) => {
|
|
756
|
-
if (get(v, 'name', '') === name) {
|
|
839
|
+
if (isestr(id) ? get(v, 'id', '') === id : get(v, 'name', '') === name) {
|
|
757
840
|
r = v
|
|
758
841
|
kr = k
|
|
759
842
|
return false //跳出
|
|
@@ -782,8 +865,8 @@ export default {
|
|
|
782
865
|
|
|
783
866
|
},
|
|
784
867
|
|
|
785
|
-
showVePemiBlngGrupsToggleItemEnableByName: function(name) {
|
|
786
|
-
// console.log('showVePemiBlngGrupsToggleItemEnableByName', name)
|
|
868
|
+
showVePemiBlngGrupsToggleItemEnableByName: function(name, id) {
|
|
869
|
+
// console.log('showVePemiBlngGrupsToggleItemEnableByName', name, id)
|
|
787
870
|
|
|
788
871
|
let vo = this
|
|
789
872
|
|
|
@@ -796,11 +879,11 @@ export default {
|
|
|
796
879
|
//rows
|
|
797
880
|
let rows = get(vo, 'opt.rows', [])
|
|
798
881
|
|
|
799
|
-
//find
|
|
882
|
+
//find, 理由同 showVePemiBlngGrupsToggleItemModeByName: 有 id 以 id 找列
|
|
800
883
|
let r = null
|
|
801
884
|
let kr = null
|
|
802
885
|
each(rows, (v, k) => {
|
|
803
|
-
if (get(v, 'name', '') === name) {
|
|
886
|
+
if (isestr(id) ? get(v, 'id', '') === id : get(v, 'name', '') === name) {
|
|
804
887
|
r = v
|
|
805
888
|
kr = k
|
|
806
889
|
return false //跳出
|
|
@@ -839,21 +922,21 @@ export default {
|
|
|
839
922
|
let rows = get(vo, 'opt.rows', [])
|
|
840
923
|
// console.log('rows', rows)
|
|
841
924
|
|
|
842
|
-
//kpRow
|
|
925
|
+
//kpRow, 以群組 id 為鍵(群組表可有歷史同名, 以 name 會使同名者互相錯位、存檔依 id 寫入錯列; 同 VeGrupBlngUsers)
|
|
843
926
|
let kpRow = Object.create(null)
|
|
844
927
|
each(rows, (r, kr) => {
|
|
845
|
-
kpRow[r.
|
|
928
|
+
kpRow[r.id] = kr
|
|
846
929
|
})
|
|
847
930
|
|
|
848
|
-
//rowsEff
|
|
849
|
-
let rowsEff = vo.
|
|
931
|
+
//rowsEff, 篩選排序後之完整列(含 id; getDisplayData 不含 id)
|
|
932
|
+
let rowsEff = vo.getDisplayRows()
|
|
850
933
|
// console.log('rowsEff', rowsEff)
|
|
851
934
|
|
|
852
935
|
//toggle
|
|
853
936
|
each(rowsEff, (r) => {
|
|
854
937
|
|
|
855
938
|
//kr
|
|
856
|
-
let kr = kpRow[r.
|
|
939
|
+
let kr = kpRow[r.id]
|
|
857
940
|
|
|
858
941
|
//set
|
|
859
942
|
set(vo, `opt.rows[${kr}].enable`, 'y')
|
|
@@ -878,21 +961,21 @@ export default {
|
|
|
878
961
|
let rows = get(vo, 'opt.rows', [])
|
|
879
962
|
// console.log('rows', rows)
|
|
880
963
|
|
|
881
|
-
//kpRow
|
|
964
|
+
//kpRow, 以群組 id 為鍵(群組表可有歷史同名, 以 name 會使同名者互相錯位、存檔依 id 寫入錯列; 同 VeGrupBlngUsers)
|
|
882
965
|
let kpRow = Object.create(null)
|
|
883
966
|
each(rows, (r, kr) => {
|
|
884
|
-
kpRow[r.
|
|
967
|
+
kpRow[r.id] = kr
|
|
885
968
|
})
|
|
886
969
|
|
|
887
|
-
//rowsEff
|
|
888
|
-
let rowsEff = vo.
|
|
970
|
+
//rowsEff, 篩選排序後之完整列(含 id; getDisplayData 不含 id)
|
|
971
|
+
let rowsEff = vo.getDisplayRows()
|
|
889
972
|
// console.log('rowsEff', rowsEff)
|
|
890
973
|
|
|
891
974
|
//toggle
|
|
892
975
|
each(rowsEff, (r) => {
|
|
893
976
|
|
|
894
977
|
//kr
|
|
895
|
-
let kr = kpRow[r.
|
|
978
|
+
let kr = kpRow[r.id]
|
|
896
979
|
|
|
897
980
|
//set
|
|
898
981
|
set(vo, `opt.rows[${kr}].enable`, 'n')
|
|
@@ -917,21 +1000,21 @@ export default {
|
|
|
917
1000
|
let rows = get(vo, 'opt.rows', [])
|
|
918
1001
|
// console.log('rows', rows)
|
|
919
1002
|
|
|
920
|
-
//kpRow
|
|
1003
|
+
//kpRow, 以群組 id 為鍵(群組表可有歷史同名, 以 name 會使同名者互相錯位、存檔依 id 寫入錯列; 同 VeGrupBlngUsers)
|
|
921
1004
|
let kpRow = Object.create(null)
|
|
922
1005
|
each(rows, (r, kr) => {
|
|
923
|
-
kpRow[r.
|
|
1006
|
+
kpRow[r.id] = kr
|
|
924
1007
|
})
|
|
925
1008
|
|
|
926
|
-
//rowsEff
|
|
927
|
-
let rowsEff = vo.
|
|
1009
|
+
//rowsEff, 篩選排序後之完整列(含 id; getDisplayData 不含 id)
|
|
1010
|
+
let rowsEff = vo.getDisplayRows()
|
|
928
1011
|
// console.log('rowsEff', rowsEff)
|
|
929
1012
|
|
|
930
1013
|
//toggle
|
|
931
1014
|
each(rowsEff, (r) => {
|
|
932
1015
|
|
|
933
1016
|
//kr
|
|
934
|
-
let kr = kpRow[r.
|
|
1017
|
+
let kr = kpRow[r.id]
|
|
935
1018
|
|
|
936
1019
|
//enable
|
|
937
1020
|
let _enable = get(r, 'enable', 'n')
|
|
@@ -951,16 +1034,19 @@ export default {
|
|
|
951
1034
|
|
|
952
1035
|
},
|
|
953
1036
|
|
|
954
|
-
saveGrups: async function(rows) {
|
|
955
|
-
// console.log('method saveGrups', rows)
|
|
1037
|
+
saveGrups: async function(rows, baseline) {
|
|
1038
|
+
// console.log('method saveGrups', rows, baseline)
|
|
956
1039
|
|
|
957
1040
|
let vo = this
|
|
958
1041
|
|
|
959
1042
|
//3) updateGrups, 各自 catch + okX 旗標短路 (canonical 五段結構; 空清單檢查已上移至 doSave core())
|
|
1043
|
+
//第 2 參 { baseline }: 開框時綁定之草稿基準(由 doSave 於流程開頭取得並傳入, 不於此讀 vo.baseline——存檔進行中若再次 show() 會換成新草稿之基準); 伺服端比對「本次將寫入之列」之庫內版本, 草稿之後被改過即整次拒收 saveStale(失敗路徑沿用下方 catch 顯示語系文字)
|
|
960
1044
|
let okSave = false
|
|
961
|
-
|
|
1045
|
+
vo.ownSaving = true //自己之寫入所致之推播不提示(成功路徑維持至視窗關閉; show() 歸零)
|
|
1046
|
+
await vo.$fapi.updateGrups(rows, { baseline })
|
|
962
1047
|
.then(() => { okSave = true })
|
|
963
1048
|
.catch(async (err) => {
|
|
1049
|
+
vo.ownSaving = false //失敗(含 saveStale 被拒): 視窗仍開著, 恢復監看
|
|
964
1050
|
vo.$ui.updateLoading(false) //showCheckYes 前關 loading(modal 阻斷期間避免 loading 疊在底下)
|
|
965
1051
|
await vo.$dg.showCheckYes(`${vo.$t('grupSaveGrupsFail')}: ${vo.$tErr(err)}`)
|
|
966
1052
|
})
|
|
@@ -1002,6 +1088,10 @@ export default {
|
|
|
1002
1088
|
|
|
1003
1089
|
let vo = this
|
|
1004
1090
|
|
|
1091
|
+
//pmDlg: 本次存檔流程所屬之對話框 promise(外審 sol R2): 存檔進行中(如 await delay)若再次 show() 開啟另一權限, vo.pm 會被換成新視窗之 promise,
|
|
1092
|
+
//舊流程完成時只能 resolve 自己的 promise、且不得關閉新視窗(見下方 .then)
|
|
1093
|
+
let pmDlg = vo.pm
|
|
1094
|
+
|
|
1005
1095
|
async function core(unlockBtn) {
|
|
1006
1096
|
|
|
1007
1097
|
//1) 事先檢測 (所有同步檢查在開 loading 之前, 空清單不應先閃 loading); 訊息框前以 unlockBtn() 釋放儲存鈕之 promiseUnlock 鎖:
|
|
@@ -1014,14 +1104,39 @@ export default {
|
|
|
1014
1104
|
return
|
|
1015
1105
|
}
|
|
1016
1106
|
|
|
1107
|
+
//草稿基準與開框時各列之歸屬狀態(F-26, R-BASELINE-01): 於流程開頭(任何 await 之前)取得並以區域變數持有——存檔進行中若再次 show() 會把 vo.baseline/vo.rowStates 換成新草稿之值, 舊草稿之列不可配新草稿之基準
|
|
1108
|
+
let baseline = cloneDeep(vo.baseline)
|
|
1109
|
+
let rowStates = vo.rowStates
|
|
1110
|
+
|
|
1111
|
+
//pemiName: 被編輯之權限名稱, 同樣於流程開頭(任何 await 之前)取得——等待後才讀 vo.pemi.name 會讀到新開啟之實體, 把舊草稿之歸屬寫成指派新實體(外審 sol R2)
|
|
1112
|
+
let pemiName = get(vo, 'pemi.name', '')
|
|
1113
|
+
|
|
1017
1114
|
//1b) 無法無損表示之授權資料(R-AUTH-LOSSY-01, 主控複審 R4): 該列群組之 cpemis 含物件形式無法無損表示之格(getKpLossy)者, 本對話框不得改寫其字串——
|
|
1018
1115
|
//本對話框所管之歸屬/模式有變更 → 整次儲存拒絕並點名(原子, 其餘列亦不寫); 未變更 → 該列字串逐字元不動(見下方 kpLossyIdx)
|
|
1019
1116
|
//群組列之快照只取這一次: 有損檢查之值即下方寫入之值(外審 sol#2: 兩次讀取之間 store 可能被伺服器推送更新, 檢查與寫入看到不同資料)
|
|
1020
1117
|
let grups = cloneDeep(vo.grups)
|
|
1118
|
+
|
|
1119
|
+
//1a) 以列身分(id, 並驗 name)配對快照(R-REL-PAIR-01, 主控 run02 F-24): 修前以開框時的列索引取快照列, store 於對話框開啟期間被更新(他人增刪、改 order)時關聯寫到另一個群組;
|
|
1120
|
+
//對話框有列所對應的群組已被刪除或改名者 → 整次拒存(原子, 不寫任何列)並提示重新整理, 不得退而配到其他列
|
|
1121
|
+
let { pairs, missing } = pairRowsToSnapshot(rows, grups, { verifyKeys: ['name'] })
|
|
1122
|
+
if (size(missing) > 0) {
|
|
1123
|
+
unlockBtn()
|
|
1124
|
+
await vo.$dg.showCheckYes(fmtLossyMsg(vo.$t('relationRowsStale'), map(missing, 'name')))
|
|
1125
|
+
return false
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
//1a2) 使用者於本次編輯相對「開框時」有變更之列(F-26, S4; 外審 B.1): 對話框之列是開框時之草稿值, 他人於開框後改過而使用者未碰之列, 不得以草稿值改寫(覆蓋他人之變更);
|
|
1129
|
+
//故只有 kpChanged 之列才對存檔當下快照之字串套用變更(下方 putRefEntry), 其餘列(含開框後新增而不在對話框內者)一律原樣帶回存檔當下 store 之版本(逐字不動), 亦不納入下方有損檢查
|
|
1130
|
+
let kpChanged = getChangedIdx(rows, rowStates)
|
|
1131
|
+
|
|
1021
1132
|
let kpLossyIdx = Object.create(null)
|
|
1133
|
+
let kpRawModes = Object.create(null) //列索引 → 該列快照字串之限制項原始 mode(getRawModeMap), 供下方 putRefEntry 寫回未改之限制項
|
|
1022
1134
|
let lossyNames = []
|
|
1023
1135
|
each(rows, (r, kr) => {
|
|
1024
|
-
|
|
1136
|
+
if (kpChanged[kr] !== true) {
|
|
1137
|
+
return true //使用者未變更: 原樣帶回, 不檢查有損亦不需 rawModeMap
|
|
1138
|
+
}
|
|
1139
|
+
let g = pairs[kr]
|
|
1025
1140
|
let kpRaw = null
|
|
1026
1141
|
try {
|
|
1027
1142
|
kpRaw = JSON5.parse(get(g, 'cpemis', ''))
|
|
@@ -1029,11 +1144,12 @@ export default {
|
|
|
1029
1144
|
catch (err) {
|
|
1030
1145
|
return true //無法解析者交由下方原流程處理
|
|
1031
1146
|
}
|
|
1147
|
+
kpRawModes[kr] = getRawModeMap(kpRaw)
|
|
1032
1148
|
if (size(getKpLossy(kpRaw)) === 0) {
|
|
1033
1149
|
return true //跳出換下一個
|
|
1034
1150
|
}
|
|
1035
1151
|
kpLossyIdx[kr] = true
|
|
1036
|
-
let p = getOwn(cvKpToObj(kpRaw, { hasMode: true }),
|
|
1152
|
+
let p = getOwn(cvKpToObj(kpRaw, { hasMode: true }), pemiName, null)
|
|
1037
1153
|
let was = get(p, 'isActive', '') === 'y'
|
|
1038
1154
|
let wasMode = was ? get(p, 'mode', '') : ''
|
|
1039
1155
|
let now = get(r, 'enable', '') === 'y'
|
|
@@ -1056,63 +1172,44 @@ export default {
|
|
|
1056
1172
|
|
|
1057
1173
|
//grups: 沿用 1b 之快照(見上)
|
|
1058
1174
|
|
|
1059
|
-
//
|
|
1060
|
-
let
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
//g
|
|
1064
|
-
let g = get(grups, kr, {})
|
|
1175
|
+
//kpNewCpemis: 列索引 → 該列新 cpemis 字串; 只收「使用者有變更(kpChanged)、非有損、且 putRefEntry 判定本項確有變更」者, 其餘一律不收(由 buildRowsSend 原樣帶回)
|
|
1176
|
+
let kpNewCpemis = Object.create(null)
|
|
1177
|
+
each(rows, (r, kr) => {
|
|
1065
1178
|
|
|
1066
|
-
|
|
1067
|
-
if (kpLossyIdx[kr] === true) {
|
|
1068
|
-
return
|
|
1179
|
+
//使用者未變更之列(kpChanged)與有損列(kpLossyIdx): 歸屬未變更, 字串逐字元不動
|
|
1180
|
+
if (kpChanged[kr] !== true || kpLossyIdx[kr] === true) {
|
|
1181
|
+
return true //跳出換下一個
|
|
1069
1182
|
}
|
|
1070
1183
|
|
|
1184
|
+
//g, 以列身分配對之快照列(見 1a)
|
|
1185
|
+
let g = pairs[kr]
|
|
1186
|
+
|
|
1071
1187
|
//cpemis
|
|
1072
1188
|
let cpemis = get(g, 'cpemis', '')
|
|
1073
1189
|
|
|
1074
|
-
//kpPemi
|
|
1075
|
-
let kpPemi =
|
|
1190
|
+
//kpPemi, 空字串與壞 JSON 視為空容器(R-REL-PARSE-01)
|
|
1191
|
+
let kpPemi = Object.create(null)
|
|
1192
|
+
try {
|
|
1193
|
+
kpPemi = cvKpToObj(JSON5.parse(cpemis), { hasMode: true })
|
|
1194
|
+
}
|
|
1195
|
+
catch (err) {}
|
|
1076
1196
|
// console.log('kpGrup', kpGrup)
|
|
1077
1197
|
|
|
1078
|
-
//
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
//kpPemiNew
|
|
1198
|
+
//kpPemiNew: 只改本權限對應之一項(依列之 enable/mode), 其餘引用項(含懸空、名稱 ''、mode 缺/非法、停用項、純量值)原樣保留, 授權效果不變(putRefEntry; 理由同 VeGrupBlngUsers.doSave)
|
|
1199
|
+
//本項未變更 → 回 false, 字串逐字元不動; 其餘項中之限制項寫回原始 mode(kpRawModes[kr]; 理由同 VeGrupBlngUsers.doSave)
|
|
1082
1200
|
let kpPemiNew = Object.create(null)
|
|
1083
|
-
if (
|
|
1084
|
-
each(pemis, (p) => {
|
|
1085
|
-
if (p.isActive === 'y') {
|
|
1086
|
-
kpPemiNew[p.name] = {
|
|
1087
|
-
mode: p.mode,
|
|
1088
|
-
isActive: p.isActive,
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
})
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
//check
|
|
1095
|
-
if (!isEqual(kpPemi, kpPemiNew)) {
|
|
1096
|
-
|
|
1097
|
-
//欲寫出之鍵序被 JS 屬性序改變而使有效 AND 項易位(如新啟用整數式名稱之 AND 權限) → 授權會改變, 不寫出(外審 minimax#2)
|
|
1098
|
-
if (size(getKpWriteLost(kpPemi, kpPemiNew)) > 0) { //預期序由 kpPemi(解碼後之原資料)與 kpPemiNew 於函數內導出——不可用本處已套用 JS 屬性序之物件序(外審 minimax 第二輪#1)
|
|
1099
|
-
lostRows.push(get(g, 'name', ''))
|
|
1100
|
-
return g
|
|
1101
|
-
}
|
|
1201
|
+
if (putRefEntry(kpPemiNew, kpPemi, pemiName, get(r, 'enable', ''), get(r, 'mode', ''), kpRawModes[kr])) {
|
|
1102
1202
|
|
|
1103
|
-
//cpemis
|
|
1104
|
-
|
|
1203
|
+
//cpemis(鍵序無關授權, R-AUTH-MERGE-00 第 4 條: 不需保留原鍵序, 亦無整數式名稱易位之拒存)
|
|
1204
|
+
kpNewCpemis[kr] = JSON.stringify(kpPemiNew)
|
|
1105
1205
|
|
|
1106
1206
|
}
|
|
1107
1207
|
|
|
1108
|
-
return g
|
|
1109
1208
|
})
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
}
|
|
1115
|
-
console.log('grupsNew', grupsNew)
|
|
1209
|
+
|
|
1210
|
+
//grupsNew: 送出之整表=存檔當下 store 快照(grups)之全部列、依其 order 序(F-26 c0, S4): 修前只送「對話框之列」, 開框後他人/外部同步新增之列被伺服端整表 diff 刪除;
|
|
1211
|
+
//只有 kpNewCpemis 之列換其 cpemis 一欄, 其餘列(使用者未變更者、有損列、開框後新增而不在對話框內者)與快照同一物件、逐字不動(帶回存檔當下 store 版本以免誤刪/誤改他人之列; 但載入基準仍是開框時之版本, 伺服端表級比對〔R-BASELINE-01, run11〕會因開框後他人之任何變更而整次拒收 saveStale)
|
|
1212
|
+
let grupsNew = buildRowsSend(grups, pairs, kpNewCpemis, 'cpemis')
|
|
1116
1213
|
|
|
1117
1214
|
// //check
|
|
1118
1215
|
// if (size(grupsNew) === 0) {
|
|
@@ -1120,7 +1217,7 @@ export default {
|
|
|
1120
1217
|
// }
|
|
1121
1218
|
|
|
1122
1219
|
//saveGrups, 失敗時回 false: 失敗提示已由 saveGrups 顯示, 此處不關閉對話框(保留未存變更供重按儲存)
|
|
1123
|
-
let okSave = await vo.saveGrups(grupsNew)
|
|
1220
|
+
let okSave = await vo.saveGrups(grupsNew, baseline)
|
|
1124
1221
|
if (!okSave) {
|
|
1125
1222
|
return false
|
|
1126
1223
|
}
|
|
@@ -1139,10 +1236,12 @@ export default {
|
|
|
1139
1236
|
}
|
|
1140
1237
|
|
|
1141
1238
|
//resolve
|
|
1142
|
-
|
|
1239
|
+
pmDlg.resolve(rows)
|
|
1143
1240
|
|
|
1144
1241
|
//hide
|
|
1145
|
-
vo.
|
|
1242
|
+
if (vo.pm === pmDlg) { //期間若已 show() 開啟另一視窗, 舊流程不得關閉新視窗
|
|
1243
|
+
vo.bShow = false
|
|
1244
|
+
}
|
|
1146
1245
|
|
|
1147
1246
|
})
|
|
1148
1247
|
.catch((err) => {
|
|
@@ -1188,6 +1287,8 @@ export default {
|
|
|
1188
1287
|
|
|
1189
1288
|
//default
|
|
1190
1289
|
vo.isModified = false
|
|
1290
|
+
vo.staleNotice = false
|
|
1291
|
+
vo.ownSaving = false
|
|
1191
1292
|
|
|
1192
1293
|
//isEditable, pemi
|
|
1193
1294
|
let isEditable = get(msg, 'isEditable', false)
|
|
@@ -1199,13 +1300,22 @@ export default {
|
|
|
1199
1300
|
//grups
|
|
1200
1301
|
let grups = cloneDeep(vo.grups)
|
|
1201
1302
|
|
|
1303
|
+
//baseline(F-26, R-BASELINE-01; 外審 B.1): 於生成 items 之同一處, 以 items 所依據之那份群組列(grups)計算並綁定為本次草稿之載入基準; 之後 store 推播變新不得更新它
|
|
1304
|
+
//(存檔當下才由最新 store 取基準, 證明的是「store 新」而非「待存之編輯內容新」), 每次 show() 重新綁定. 欄位口徑與伺服端同一(vo.$ds.grups.keys 經 rowDigest.makeBaseline)
|
|
1305
|
+
let baseline = makeBaseline(grups, vo.$ds.grups.keys)
|
|
1306
|
+
|
|
1202
1307
|
//items
|
|
1203
1308
|
let items = vo.genItems(pemi, grups)
|
|
1204
1309
|
|
|
1310
|
+
//rowStates: 開框時各列之歸屬狀態(須在任何切換操作前由 items 記下; opt.rows 與 items 為同一份陣列, 切換會就地改 enable/mode), 供存檔時判定使用者有無變更該列
|
|
1311
|
+
let rowStates = makeRowStates(items)
|
|
1312
|
+
|
|
1205
1313
|
//save
|
|
1206
1314
|
vo.isEditable = isEditable
|
|
1207
1315
|
vo.pemi = pemi
|
|
1208
1316
|
vo.items = items
|
|
1317
|
+
vo.baseline = baseline
|
|
1318
|
+
vo.rowStates = rowStates
|
|
1209
1319
|
|
|
1210
1320
|
//genOpt
|
|
1211
1321
|
vo.genOpt()
|