@oinone/kunlun-vue-admin-base 6.4.0 → 6.4.1

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.
@@ -6,6 +6,7 @@ declare const _default: import("vue").DefineComponent<{
6
6
  }, {
7
7
  visible: import("vue").Ref<boolean>;
8
8
  icon: import("vue").ComputedRef<"oinone-fullscreen-exit-outlined" | "oinone-fullscreen-outlined">;
9
+ tooltipTitle: import("vue").ComputedRef<string>;
9
10
  onChange: () => void;
10
11
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:value" | "change")[], "update:value" | "change", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
11
12
  value: {
@@ -40,11 +40,13 @@ export declare class QuickFillWidget extends BaseElementWidget {
40
40
  * 确认提交,校验excel数据
41
41
  */
42
42
  onSure(headers: TableFieldOption[], rows: StandardString[][]): Promise<void>;
43
+ protected setRowValue(rowValue: Record<string, StandardString>, relationObjects: Record<string, ActiveRecord>, fieldName: string, cell: string): void;
43
44
  /**
44
45
  * 继续提交
45
46
  */
46
47
  onSubmit(): void;
47
48
  protected get fillValueFieldMapping(): [string, string][];
49
+ protected lastCells: Record<string, any> | undefined;
48
50
  /**
49
51
  * 将表格数据,填充到excel中
50
52
  */
@@ -69,8 +71,8 @@ export declare class QuickFillWidget extends BaseElementWidget {
69
71
  /**
70
72
  * 调接口校验excel数据
71
73
  */
72
- validateExcelValue(headers: TableFieldOption[], values: string): Promise<QuickFillResponse>;
73
- protected findModelField(fields: QuickFillField[], header: TableFieldOption): {
74
+ validateExcelValue(headers: TableFieldOption[], values: Record<string, StandardString>[], keepValues: Record<string, StandardString>[]): Promise<QuickFillResponse>;
75
+ protected findModelField(fields: QuickFillField[], data: string): {
74
76
  fieldWidget?: undefined;
75
77
  field?: undefined;
76
78
  } | {
@@ -9,4 +9,5 @@ export interface TableFieldOption {
9
9
  value: string;
10
10
  readonly: boolean;
11
11
  field: string;
12
+ originField: string;
12
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oinone/kunlun-vue-admin-base",
3
- "version": "6.4.0",
3
+ "version": "6.4.1",
4
4
  "main": "index.ts",
5
5
  "scripts": {
6
6
  "prebuild": "rimraf dist",
@@ -14,13 +14,13 @@
14
14
  "doc": "typedoc --out docs src/index.ts"
15
15
  },
16
16
  "dependencies": {
17
- "@oinone/kunlun-vue-admin-layout": "6.4.0",
18
- "@oinone/kunlun-vue-router": "6.4.0",
19
- "@oinone/kunlun-vue-ui": "6.4.0",
20
- "@oinone/kunlun-vue-ui-antd": "6.4.0",
21
- "@oinone/kunlun-vue-ui-common": "6.4.0",
22
- "@oinone/kunlun-vue-ui-el": "6.4.0",
23
- "@oinone/kunlun-vue-widget": "6.4.0",
17
+ "@oinone/kunlun-vue-admin-layout": "6.4.1",
18
+ "@oinone/kunlun-vue-router": "6.4.1",
19
+ "@oinone/kunlun-vue-ui": "6.4.1",
20
+ "@oinone/kunlun-vue-ui-antd": "6.4.1",
21
+ "@oinone/kunlun-vue-ui-common": "6.4.1",
22
+ "@oinone/kunlun-vue-ui-el": "6.4.1",
23
+ "@oinone/kunlun-vue-widget": "6.4.1",
24
24
  "@wangeditor/editor": "5.1.23",
25
25
  "@wangeditor/editor-for-vue": "5.1.11",
26
26
  "@wangeditor/plugin-upload-attachment": "1.1.0",
@@ -866,8 +866,9 @@ export class BaseTableWidget<
866
866
  }
867
867
  keyboardConfig.left = keyboardConfig.left || { key: 'Tab', shift: true, desc: '向左移动单元格' };
868
868
  keyboardConfig.right = keyboardConfig.right || { key: 'Tab', desc: '向右移动单元格' };
869
- keyboardConfig.up = keyboardConfig.up || { key: 'Enter', ctrl: true, shift: true, desc: '向上移动单元格' };
870
- keyboardConfig.down = keyboardConfig.down || { key: 'Enter', ctrl: true, desc: '向下移动单元格' };
869
+ // fixme @zbh 20251218 暂未实现
870
+ // keyboardConfig.up = keyboardConfig.up || { key: 'Enter', ctrl: true, shift: true, desc: '向上移动单元格' };
871
+ // keyboardConfig.down = keyboardConfig.down || { key: 'Enter', ctrl: true, desc: '向下移动单元格' };
871
872
  keyboardConfig.enter = keyboardConfig.enter || { key: 'Enter', desc: '提交数据' };
872
873
  keyboardConfig.cancel = keyboardConfig.cancel || { key: 'Esc', desc: '取消编辑' };
873
874
  return keyboardConfig;
@@ -1324,6 +1325,7 @@ export class BaseTableWidget<
1324
1325
  }))
1325
1326
  );
1326
1327
  } else {
1328
+ (this.tableInstance?.getSortColumns() || []).forEach((v) => this.tableInstance?.clearSort(v.field));
1327
1329
  this.tableInstance?.sort([]);
1328
1330
  }
1329
1331
  });
@@ -1,12 +1,13 @@
1
1
  <template>
2
2
  <div class="default-view-control-item default-view-control-full-screen">
3
- <oio-tooltip v-model:visible="visible" placement="bm" :title="$translate('全屏')">
3
+ <oio-tooltip v-model:visible="visible" placement="bm" :title="tooltipTitle">
4
4
  <oio-icon size="16" :icon="icon" @click="onChange" />
5
5
  </oio-tooltip>
6
6
  </div>
7
7
  </template>
8
8
 
9
9
  <script lang="ts">
10
+ import { translateValueByKey } from '@oinone/kunlun-engine';
10
11
  import { OioIcon, OioTooltip } from '@oinone/kunlun-vue-ui-antd';
11
12
  import { computed, defineComponent, ref } from 'vue';
12
13
 
@@ -29,6 +30,13 @@ export default defineComponent({
29
30
  return props.value ? 'oinone-fullscreen-exit-outlined' : 'oinone-fullscreen-outlined';
30
31
  });
31
32
 
33
+ const tooltipTitle = computed(() => {
34
+ if (props.value) {
35
+ return translateValueByKey('取消全屏');
36
+ }
37
+ return translateValueByKey('全屏');
38
+ });
39
+
32
40
  const onChange = () => {
33
41
  visible.value = false;
34
42
  emit('update:value', !props.value);
@@ -38,6 +46,7 @@ export default defineComponent({
38
46
  return {
39
47
  visible,
40
48
  icon,
49
+ tooltipTitle,
41
50
  onChange
42
51
  };
43
52
  }
@@ -25,7 +25,7 @@
25
25
  }}</oio-button>
26
26
  <a-divider type="vertical" />
27
27
  <a-popconfirm
28
- v-if="item.dataSource !== 'SYSTEM' && hasDeleteGroupAction"
28
+ v-if="item.source === 'MANUAL' && hasDeleteGroupAction"
29
29
  placement="topLeft"
30
30
  :ok-text="$translate('确定')"
31
31
  :cancel-text="$translate('取消')"
@@ -72,7 +72,7 @@
72
72
  <div>
73
73
  {{ title }}
74
74
  <span style="position: absolute; right: 0; color: var(--oio-icon-color)">
75
- >{{ data.menuName }}/{{ data.displayValue }}</span
75
+ {{ data.menuName }}/{{ data.displayValue }}</span
76
76
  >
77
77
  </div>
78
78
  </template>
@@ -146,9 +146,9 @@ import {
146
146
  } from '@oinone/kunlun-vue-ui-antd';
147
147
  import { computed, defineEmits, defineProps, ref, watch, withDefaults } from 'vue';
148
148
  import { IPermission } from '../../permission/type';
149
+ import { ActionPermissionNode, AnyPermissionNode } from '../../types';
149
150
  import { queryActionsByMenu, queryGroupData } from '../service';
150
151
  import { useStore } from '../store';
151
- import { ActionPermissionNode, AnyPermissionNode } from '../../types';
152
152
  import DataPermission from './data-permission/data-permission.vue';
153
153
 
154
154
  interface ActionTreeItem {
@@ -58,7 +58,6 @@ export const queryRoleList = async (
58
58
  name
59
59
  description
60
60
  source
61
- permissionDataSource
62
61
  createDate
63
62
  writeDate
64
63
  }
@@ -91,11 +90,10 @@ export const queryGroups = async (options: { nodeType: string; resourceId: strin
91
90
  id
92
91
  name
93
92
  type
94
- dataSource
93
+ source
95
94
  active
96
95
  displayName
97
96
  comment
98
- menuName
99
97
  roles {
100
98
  code
101
99
  name
@@ -109,11 +107,10 @@ export const queryGroups = async (options: { nodeType: string; resourceId: strin
109
107
  id
110
108
  name
111
109
  type
112
- dataSource
110
+ source
113
111
  active
114
112
  displayName
115
113
  comment
116
- menuName
117
114
  roles {
118
115
  code
119
116
  name
@@ -149,15 +149,17 @@ const tableHeaderValues = ref<TableFieldOption[]>([]);
149
149
 
150
150
  // 表头下拉选项
151
151
  const selectOptions = computed(() => {
152
- const options: TableFieldOption[] = [...props.fields];
153
- options.unshift({
154
- label: '不粘贴',
155
- key: NON_CUT,
156
- value: NON_CUT,
157
- readonly: true,
158
- field: NON_CUT
159
- });
160
- return options;
152
+ return [
153
+ {
154
+ label: '不粘贴',
155
+ key: NON_CUT,
156
+ value: NON_CUT,
157
+ readonly: true,
158
+ field: NON_CUT,
159
+ originField: NON_CUT
160
+ },
161
+ ...props.fields
162
+ ];
161
163
  });
162
164
 
163
165
  // ======== 状态 =========
@@ -777,13 +779,16 @@ defineExpose({
777
779
  getTableHeaderValues() {
778
780
  const fields: TableFieldOption[] = [];
779
781
  for (const tableHeaderValue of tableHeaderValues.value) {
780
- const { value } = tableHeaderValue;
782
+ const { value, originField } = tableHeaderValue;
781
783
  if (value === NON_CUT) {
782
784
  fields.push(tableHeaderValue);
783
785
  } else {
784
786
  const target = props.fields.find((v) => v.field === value);
785
787
  if (target) {
786
- fields.push(target);
788
+ fields.push({
789
+ ...target,
790
+ originField
791
+ });
787
792
  }
788
793
  }
789
794
  }
@@ -153,7 +153,8 @@ export default defineComponent({
153
153
  key: fieldName,
154
154
  value: fieldName,
155
155
  readonly: field.readonly === true,
156
- field: fieldName
156
+ field: fieldName,
157
+ originField: fieldName
157
158
  };
158
159
  });
159
160
  if (type.value === QuickFillType.create) {
@@ -203,6 +203,7 @@ export class QuickFillWidget extends BaseElementWidget {
203
203
  @Widget.Method()
204
204
  public async onSure(headers: TableFieldOption[], rows: StandardString[][]) {
205
205
  const values = [] as Record<string, StandardString>[];
206
+ const keepValues = [] as Record<string, StandardString>[];
206
207
 
207
208
  /**
208
209
  * 将excel数据转换成提交的数据格式
@@ -212,34 +213,40 @@ export class QuickFillWidget extends BaseElementWidget {
212
213
  rows.forEach((row, rowIndex) => {
213
214
  const rowValue = {} as Record<string, StandardString>;
214
215
  const relationObjects: Record<string, ActiveRecord> = {};
216
+ const keepRowValue = {} as Record<string, StandardString>;
217
+ const keepRelationObjects: Record<string, ActiveRecord> = {};
215
218
 
216
219
  row.forEach((cell, columnIndex) => {
217
220
  if (!cell) {
218
221
  return;
219
222
  }
220
- const fieldName = headers[columnIndex]?.field;
221
- if (!fieldName) {
223
+ const header = headers[columnIndex];
224
+ if (!header) {
222
225
  return;
223
226
  }
224
- const [name1, name2] = fieldName.split('#');
225
- if (name2) {
226
- let target = relationObjects[name1];
227
- if (!target) {
228
- target = {};
229
- relationObjects[name1] = target;
230
- }
231
- target[name2] = cell;
232
- } else {
233
- rowValue[fieldName] = cell;
227
+ const { value, originField } = header;
228
+ if (value !== NON_CUT) {
229
+ this.setRowValue(rowValue, relationObjects, value, cell);
234
230
  }
231
+ this.setRowValue(
232
+ keepRowValue,
233
+ keepRelationObjects,
234
+ originField,
235
+ this.lastCells?.[`${rowIndex + 1}-${columnIndex + 1}`]
236
+ );
235
237
  });
236
238
 
237
239
  Object.entries(relationObjects).forEach(([key, value]) => {
238
240
  rowValue[key] = JSON.stringify(value);
239
241
  });
240
242
 
243
+ Object.entries(keepRelationObjects).forEach(([key, value]) => {
244
+ keepRowValue[key] = JSON.stringify(value);
245
+ });
246
+
241
247
  if (Object.keys(rowValue).length > 0) {
242
248
  values.push(rowValue);
249
+ keepValues.push(keepRowValue);
243
250
  }
244
251
  });
245
252
 
@@ -247,7 +254,7 @@ export class QuickFillWidget extends BaseElementWidget {
247
254
  * values -> 可回填的数据
248
255
  * failures -> 错误信息
249
256
  */
250
- const { values: resultValues, failures } = await this.validateExcelValue(headers, JSON.stringify(values));
257
+ const { values: resultValues, failures } = await this.validateExcelValue(headers, values, keepValues);
251
258
 
252
259
  const data = resultValues ? JSON.parse(resultValues) : [];
253
260
 
@@ -267,6 +274,25 @@ export class QuickFillWidget extends BaseElementWidget {
267
274
  }
268
275
  }
269
276
 
277
+ protected setRowValue(
278
+ rowValue: Record<string, StandardString>,
279
+ relationObjects: Record<string, ActiveRecord>,
280
+ fieldName: string,
281
+ cell: string
282
+ ) {
283
+ const [name1, name2] = fieldName.split('#');
284
+ if (name2) {
285
+ let target = relationObjects[name1];
286
+ if (!target) {
287
+ target = {};
288
+ relationObjects[name1] = target;
289
+ }
290
+ target[name2] = cell;
291
+ } else {
292
+ rowValue[fieldName] = cell;
293
+ }
294
+ }
295
+
270
296
  /**
271
297
  * 继续提交
272
298
  */
@@ -280,6 +306,8 @@ export class QuickFillWidget extends BaseElementWidget {
280
306
  return fullAddressFieldMapping;
281
307
  }
282
308
 
309
+ protected lastCells: Record<string, any> | undefined;
310
+
283
311
  /**
284
312
  * 将表格数据,填充到excel中
285
313
  */
@@ -287,6 +315,7 @@ export class QuickFillWidget extends BaseElementWidget {
287
315
  public fillValueByDataSource(): { cells?: Record<string, unknown>; rowCount?: number } {
288
316
  // 处理空数据情况
289
317
  if (!this.dataSource?.length) {
318
+ this.lastCells = undefined;
290
319
  return {
291
320
  rowCount: 0
292
321
  };
@@ -324,6 +353,7 @@ export class QuickFillWidget extends BaseElementWidget {
324
353
  });
325
354
  });
326
355
 
356
+ this.lastCells = { ...cells };
327
357
  return { cells, rowCount: this.dataSource.length };
328
358
  }
329
359
 
@@ -493,14 +523,23 @@ export class QuickFillWidget extends BaseElementWidget {
493
523
  /**
494
524
  * 调接口校验excel数据
495
525
  */
496
- public async validateExcelValue(headers: TableFieldOption[], values: string) {
526
+ public async validateExcelValue(
527
+ headers: TableFieldOption[],
528
+ values: Record<string, StandardString>[],
529
+ keepValues: Record<string, StandardString>[]
530
+ ) {
497
531
  const fields: QuickFillField[] = [];
498
- const validHeaders: TableFieldOption[] = headers.filter((v) => v.value !== NON_CUT);
499
- const keepHeaders: TableFieldOption[] = headers.filter(
500
- (v) => v.value === NON_CUT && v.field && !validHeaders.find((vv) => vv.value === v.field)
501
- );
532
+ const validHeaders: TableFieldOption[] = [];
533
+ const keepHeaders: Record<string, boolean> = {};
534
+ for (const header of headers) {
535
+ const { value, originField } = header;
536
+ if (value !== NON_CUT) {
537
+ validHeaders.push(header);
538
+ }
539
+ keepHeaders[originField] = true;
540
+ }
502
541
  for (const header of validHeaders) {
503
- const { fieldWidget, field: modelField } = this.findModelField(fields, header);
542
+ const { fieldWidget, field: modelField } = this.findModelField(fields, header.value);
504
543
  if (!modelField) {
505
544
  continue;
506
545
  }
@@ -514,26 +553,49 @@ export class QuickFillWidget extends BaseElementWidget {
514
553
  } else {
515
554
  fields.push({ field: modelField.data, required });
516
555
  }
556
+ delete keepHeaders[header.value];
517
557
  }
518
- for (const header of keepHeaders) {
519
- const { field: modelField } = this.findModelField(fields, header);
520
- if (!modelField) {
521
- continue;
558
+ if (this.type === QuickFillType.create) {
559
+ for (const [field] of Object.entries(keepHeaders)) {
560
+ const { field: modelField } = this.findModelField(fields, field);
561
+ if (!modelField) {
562
+ continue;
563
+ }
564
+ for (const value of values) {
565
+ delete value[modelField.data];
566
+ }
522
567
  }
523
- if (isRelationField(modelField)) {
524
- fields.push({
525
- field: modelField.data,
526
- validate: false,
527
- labelFields: modelField.referencesModel.labelFields
528
- });
529
- } else {
530
- fields.push({ field: modelField.data, validate: false });
568
+ } else if (this.type === QuickFillType.update) {
569
+ for (const [field] of Object.entries(keepHeaders)) {
570
+ const { field: modelField } = this.findModelField(fields, field);
571
+ if (!modelField) {
572
+ continue;
573
+ }
574
+ if (isRelationField(modelField)) {
575
+ fields.push({
576
+ field: modelField.data,
577
+ validate: false,
578
+ labelFields: modelField.referencesModel.labelFields
579
+ });
580
+ } else {
581
+ fields.push({ field: modelField.data, validate: false });
582
+ }
583
+ for (let i = 0; i < values.length; i++) {
584
+ const value = values[i];
585
+ const keepValue = keepValues[i];
586
+ const t = keepValue?.[modelField.data];
587
+ if (t) {
588
+ value[modelField.data] = t;
589
+ } else {
590
+ delete value[modelField.data];
591
+ }
592
+ }
531
593
  }
532
594
  }
533
595
  const gqlStr = await buildSingleItemParam(quickFillFields, {
534
596
  model: this.model.model,
535
597
  fields,
536
- values
598
+ values: JSON.stringify(values)
537
599
  });
538
600
 
539
601
  const body = `{
@@ -558,14 +620,7 @@ export class QuickFillWidget extends BaseElementWidget {
558
620
  return rst.data.quickFillingQuery.loadData as unknown as QuickFillResponse;
559
621
  }
560
622
 
561
- protected findModelField(fields: QuickFillField[], header: TableFieldOption) {
562
- const { value, field } = header;
563
- let data: string;
564
- if (value === NON_CUT) {
565
- data = field;
566
- } else {
567
- data = value;
568
- }
623
+ protected findModelField(fields: QuickFillField[], data: string) {
569
624
  let fieldWidget: BaseFieldWidget | undefined;
570
625
  const [name1, name2] = data.split('#');
571
626
  if (name2) {
@@ -11,4 +11,5 @@ export interface TableFieldOption {
11
11
  value: string;
12
12
  readonly: boolean;
13
13
  field: string;
14
+ originField: string;
14
15
  }
@@ -105,6 +105,7 @@ $treeMinWidth: 324px;
105
105
  }
106
106
  }
107
107
  }
108
+
108
109
  .oio-full-screen-view {
109
110
  position: fixed;
110
111
  top: 0;
@@ -123,6 +124,7 @@ $treeMinWidth: 324px;
123
124
  .ant-modal-close-x {
124
125
  top: -4px;
125
126
  }
127
+
126
128
  .ant-modal-confirm-body {
127
129
  display: flex;
128
130
  gap: var(--oio-row-gap);
@@ -143,6 +145,7 @@ $treeMinWidth: 324px;
143
145
  padding: var(--oio-padding) var(--oio-padding) var(--oio-padding) 0;
144
146
  border-bottom: 1px solid var(--oio-border-color);
145
147
  }
148
+
146
149
  & > .action-bar {
147
150
  height: auto;
148
151
  padding: var(--oio-padding);
@@ -152,6 +155,7 @@ $treeMinWidth: 324px;
152
155
  & > .oio-default-form {
153
156
  padding: var(--oio-padding);
154
157
  }
158
+
155
159
  & > .default-gallery {
156
160
  padding: var(--oio-padding);
157
161
  }
@@ -170,48 +174,63 @@ $treeMinWidth: 324px;
170
174
  border: none;
171
175
  box-shadow: none;
172
176
  }
177
+
173
178
  .oio-group-title-wrapper {
174
179
  padding: 0;
175
180
  }
176
181
 
177
182
  .oio-group-content {
178
183
  padding: var(--oio-padding) 0 0 0;
184
+
179
185
  .oio-group {
180
186
  padding: 0 var(--oio-padding);
181
187
  }
182
188
  }
189
+
190
+ &.oio-group-title-hidden {
191
+ & > .oio-group-content {
192
+ padding: var(--oio-padding);
193
+ }
194
+ }
183
195
  }
184
196
  }
185
197
 
186
198
  // 表格
187
199
  &.oio-default-table-view {
188
200
  .oio-default-view-container {
189
- .oio-group {
190
- &:last-child {
191
- .oio-group-content {
192
- padding-top: 0;
201
+ & > .oio-group {
202
+ & > .oio-group-content {
203
+ padding: var(--oio-padding) 0 0 0;
193
204
 
194
- & > .oio-row {
195
- row-gap: 0 !important;
196
- }
205
+ & > .oio-row {
206
+ row-gap: 0 !important;
197
207
  }
198
208
  }
209
+
210
+ &:last-child > .oio-group-content {
211
+ padding-top: 0;
212
+ }
199
213
  }
214
+
200
215
  .oio-default-search {
201
216
  padding: 0 var(--oio-padding) var(--oio-padding) 0;
202
217
  border-bottom: 1px solid var(--oio-border-color);
218
+
203
219
  .oio-cate-search.oio-tabs.ant-tabs-top .ant-tabs-nav .ant-tabs-tab {
204
220
  padding-top: 0;
205
221
  }
222
+
206
223
  .ant-tabs-nav-wrap,
207
224
  .oio-cate-search-second {
208
225
  padding-left: var(--oio-padding);
209
226
  }
210
227
  }
228
+
211
229
  .action-bar:not(.action-bar-inline) {
212
230
  padding: var(--oio-padding) var(--oio-padding) 0 var(--oio-padding);
213
231
  height: auto;
214
232
  }
233
+
215
234
  .default-table {
216
235
  padding: var(--oio-padding);
217
236
  }
@@ -219,6 +238,7 @@ $treeMinWidth: 324px;
219
238
  .default-tree-table {
220
239
  padding: var(--oio-padding) 0 0 var(--oio-padding);
221
240
  position: relative;
241
+
222
242
  &::after {
223
243
  content: '';
224
244
  position: absolute;
@@ -243,6 +263,7 @@ $treeMinWidth: 324px;
243
263
  // 树视图
244
264
  &.oio-default-tree-view {
245
265
  padding: var(--oio-padding);
266
+
246
267
  .oio-default-view-container .oio-group .oio-group-content {
247
268
  padding: 0;
248
269
  }