@skyfox2000/webui 1.3.3 → 1.3.5
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/lib/assets/modules/{file-upload-D4Pqs8h3.js → file-upload-C0twqMV5.js} +1 -1
- package/lib/assets/modules/{index-V1j9haWy.js → index-C4CryM-R.js} +1 -1
- package/lib/assets/modules/index-CKJIxasX.js +333 -0
- package/lib/assets/modules/{index-CSnwbbQT.js → index-D1XAa1Uo.js} +2 -2
- package/lib/assets/modules/{menuTabs-e8XoJN7m.js → menuTabs-BrYQa4UO.js} +2 -2
- package/lib/assets/modules/{toolIcon-BSF7eiPf.js → toolIcon-B-g9pyE4.js} +1 -1
- package/lib/assets/modules/{uploadList-DA4TRDWR.js → uploadList-0f2FA_5s.js} +490 -455
- package/lib/assets/modules/{uploadList-Bcf7g1bf.js → uploadList-DCWRIxPJ.js} +4 -4
- package/lib/components/content/table/index.vue.d.ts +95 -4
- package/lib/es/AceEditor/index.js +3 -3
- package/lib/es/BasicLayout/index.js +3 -3
- package/lib/es/Error403/index.js +1 -1
- package/lib/es/Error404/index.js +1 -1
- package/lib/es/ExcelForm/index.js +339 -202
- package/lib/es/UploadForm/index.js +4 -4
- package/lib/index.d.ts +3 -2
- package/lib/typings/option.d.ts +2 -2
- package/lib/utils/excel-view.d.ts +25 -0
- package/lib/utils/form-csv.d.ts +18 -0
- package/lib/utils/form-excel.d.ts +2 -13
- package/lib/utils/options.d.ts +2 -2
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +897 -871
- package/package.json +2 -2
- package/src/components/common/loading/index.vue +1 -1
- package/src/components/content/dialog/excelForm.vue +386 -107
- package/src/components/content/table/index.vue +9 -6
- package/src/components/form/autoComplete/index.vue +9 -3
- package/src/components/form/cascader/index.vue +8 -6
- package/src/index.ts +25 -2
- package/src/typings/option.d.ts +2 -2
- package/src/utils/excel-view.ts +340 -0
- package/src/utils/form-csv.ts +55 -0
- package/src/utils/form-excel.ts +59 -192
- package/src/utils/options.ts +80 -22
- package/src/utils/table.ts +15 -2
- package/vite.config.ts +0 -1
- package/lib/assets/modules/form-excel-D1vXB4c4.js +0 -235
package/src/utils/form-excel.ts
CHANGED
|
@@ -7,23 +7,9 @@ import message from 'vue-m-message';
|
|
|
7
7
|
import { ValidateRule } from '@/typings/form';
|
|
8
8
|
import { validMessages } from './form-validate';
|
|
9
9
|
import { UploadFile } from '@/typings/upload';
|
|
10
|
+
import { toExcel, type ExcelMarkInfo } from './excel-view';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
* Excel数据处理需要标记的单元格
|
|
13
|
-
*/
|
|
14
|
-
export type ExcelMarkCell = {
|
|
15
|
-
row: number;
|
|
16
|
-
col: number;
|
|
17
|
-
color?: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Excel标记类型
|
|
22
|
-
*/
|
|
23
|
-
export type ExcelMarkInfo = {
|
|
24
|
-
markCells: ExcelMarkCell[];
|
|
25
|
-
markHeaders?: string[];
|
|
26
|
-
};
|
|
12
|
+
// ExcelMarkCell 和 ExcelMarkInfo 类型已移至 excel-view.ts 统一管理
|
|
27
13
|
|
|
28
14
|
/**
|
|
29
15
|
* 处理Excel文件的通用函数,用于提取表头和数据
|
|
@@ -133,31 +119,23 @@ export const processExcelFile = async (excelBuffer: ArrayBuffer) => {
|
|
|
133
119
|
};
|
|
134
120
|
|
|
135
121
|
/**
|
|
136
|
-
*
|
|
122
|
+
* 创建带错误标记的Excel预览
|
|
137
123
|
* @param excelBuffer 原始Excel文件的ArrayBuffer
|
|
138
|
-
* @param markInfo
|
|
139
|
-
* @
|
|
124
|
+
* @param markInfo 标记信息
|
|
125
|
+
* @param fileName 文件名
|
|
126
|
+
* @returns 标记后的Excel预览结果
|
|
140
127
|
*/
|
|
141
|
-
export const
|
|
142
|
-
|
|
143
|
-
markInfo: ExcelMarkInfo,
|
|
144
|
-
): Promise<{
|
|
145
|
-
hasError: boolean;
|
|
146
|
-
errBlob?: Blob;
|
|
147
|
-
}> => {
|
|
148
|
-
const ExcelJS = await import('exceljs');
|
|
149
|
-
// 处理Excel文件
|
|
128
|
+
export const createMarkedExcelView = async (excelBuffer: ArrayBuffer, markInfo: ExcelMarkInfo, fileName: string) => {
|
|
129
|
+
// 处理Excel文件获取数据
|
|
150
130
|
const excelData = await processExcelFile(excelBuffer);
|
|
151
|
-
if (!excelData)
|
|
152
|
-
|
|
153
|
-
const { worksheet, headers: originalHeaders } = excelData;
|
|
154
|
-
const { markCells, markHeaders } = markInfo;
|
|
155
|
-
|
|
156
|
-
if (markCells.length === 0 && (!markHeaders || markHeaders.length === 0)) {
|
|
157
|
-
return { hasError: false }; // 没有需要标记的内容
|
|
131
|
+
if (!excelData) {
|
|
132
|
+
return { success: false, error: 'Excel文件处理失败' };
|
|
158
133
|
}
|
|
159
134
|
|
|
160
|
-
|
|
135
|
+
const { headers: originalHeaders, excelRows } = excelData;
|
|
136
|
+
const { markHeaders } = markInfo;
|
|
137
|
+
|
|
138
|
+
// 处理缺失字段,添加到表头
|
|
161
139
|
const headers = [...originalHeaders];
|
|
162
140
|
if (markHeaders && markHeaders.length > 0) {
|
|
163
141
|
markHeaders.forEach((field) => {
|
|
@@ -167,158 +145,18 @@ export const createMarkedExcelBlob = async (
|
|
|
167
145
|
});
|
|
168
146
|
}
|
|
169
147
|
|
|
170
|
-
//
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// 创建错误单元格位置的查询表,用于快速检查
|
|
178
|
-
const cellMarkMap = new Map<string, string>();
|
|
179
|
-
markCells.forEach(({ row, col, color }) => {
|
|
180
|
-
const cellKey = `${row}-${col}`;
|
|
181
|
-
cellMarkMap.set(cellKey, color || 'FFFF0000'); // 默认红色
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// 复制列宽并应用于新工作表
|
|
185
|
-
for (let i = 0; i < headers.length; i++) {
|
|
186
|
-
const column = newWorksheet.getColumn(i + 1);
|
|
187
|
-
|
|
188
|
-
if (i < worksheet.columnCount && i < originalHeaders.length) {
|
|
189
|
-
const originalCol = worksheet.getColumn(i + 1);
|
|
190
|
-
if (originalCol && originalCol.width) {
|
|
191
|
-
column.width = originalCol.width;
|
|
192
|
-
} else {
|
|
193
|
-
column.width = defaultColumnWidth;
|
|
194
|
-
}
|
|
195
|
-
} else {
|
|
196
|
-
column.width = defaultColumnWidth;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// 复制表头行
|
|
201
|
-
const headerRow = newWorksheet.getRow(1);
|
|
202
|
-
headers.forEach((header, index) => {
|
|
203
|
-
const headerCell = headerRow.getCell(index + 1);
|
|
204
|
-
headerCell.value = header;
|
|
205
|
-
|
|
206
|
-
const isOriginalHeader = index < originalHeaders.length;
|
|
207
|
-
if (isOriginalHeader && index < worksheet.columnCount) {
|
|
208
|
-
// 复制原表头样式
|
|
209
|
-
const originalCell = worksheet.getRow(1).getCell(index + 1);
|
|
210
|
-
|
|
211
|
-
// 复制样式
|
|
212
|
-
if (originalCell.style) headerCell.style = JSON.parse(JSON.stringify(originalCell.style));
|
|
213
|
-
if (originalCell.font) headerCell.font = JSON.parse(JSON.stringify(originalCell.font));
|
|
214
|
-
if (originalCell.alignment) headerCell.alignment = JSON.parse(JSON.stringify(originalCell.alignment));
|
|
215
|
-
if (originalCell.border) headerCell.border = JSON.parse(JSON.stringify(originalCell.border));
|
|
216
|
-
if (originalCell.numFmt) headerCell.numFmt = originalCell.numFmt;
|
|
217
|
-
if (originalCell.fill) headerCell.fill = JSON.parse(JSON.stringify(originalCell.fill));
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// 仅标记缺失的表头字段,不标记数据重复的表头
|
|
221
|
-
if (markHeaders && markHeaders.includes(header) && !isOriginalHeader) {
|
|
222
|
-
headerCell.fill = {
|
|
223
|
-
type: 'pattern',
|
|
224
|
-
pattern: 'solid',
|
|
225
|
-
fgColor: { argb: 'FFFF0000' }, // 红色背景
|
|
226
|
-
};
|
|
227
|
-
|
|
228
|
-
// 添加白色文字
|
|
229
|
-
headerCell.font = {
|
|
230
|
-
name: 'Arial',
|
|
231
|
-
size: 10,
|
|
232
|
-
bold: true,
|
|
233
|
-
color: { argb: 'FFFFFFFF' }, // 白色文字
|
|
234
|
-
};
|
|
148
|
+
// 扩展数据行以匹配新的表头长度
|
|
149
|
+
const rows = excelRows.map((row) => {
|
|
150
|
+
const newRow = [...row];
|
|
151
|
+
// 为新增的表头字段添加空值
|
|
152
|
+
while (newRow.length < headers.length) {
|
|
153
|
+
newRow.push(null);
|
|
235
154
|
}
|
|
155
|
+
return newRow;
|
|
236
156
|
});
|
|
237
|
-
headerRow.commit();
|
|
238
|
-
|
|
239
|
-
// 处理数据行
|
|
240
|
-
worksheet.eachRow((row, rowNumber) => {
|
|
241
|
-
if (rowNumber > 1) {
|
|
242
|
-
// 跳过表头行
|
|
243
|
-
const newRow = newWorksheet.getRow(rowNumber);
|
|
244
|
-
|
|
245
|
-
// 使用表头长度来循环每个单元格
|
|
246
|
-
for (let colIndex = 0; colIndex < headers.length; colIndex++) {
|
|
247
|
-
const newCell = newRow.getCell(colIndex + 1);
|
|
248
|
-
const isOriginalHeader = colIndex < originalHeaders.length;
|
|
249
|
-
|
|
250
|
-
if (isOriginalHeader && colIndex < worksheet.columnCount) {
|
|
251
|
-
// 对原始数据中存在的列
|
|
252
|
-
const originalCell = row.getCell(colIndex + 1);
|
|
253
|
-
|
|
254
|
-
// 复制值
|
|
255
|
-
newCell.value = originalCell.value;
|
|
256
|
-
|
|
257
|
-
// 处理对象类型的单元格值,确保正确显示
|
|
258
|
-
if (newCell.value !== null && newCell.value !== undefined && typeof newCell.value === 'object') {
|
|
259
|
-
// 对于RichText,保留原格式
|
|
260
|
-
if (
|
|
261
|
-
!('richText' in newCell.value) &&
|
|
262
|
-
!('formula' in newCell.value) &&
|
|
263
|
-
!('hyperlink' in newCell.value) &&
|
|
264
|
-
!(newCell.value instanceof Date)
|
|
265
|
-
) {
|
|
266
|
-
// 尝试转换为字符串显示
|
|
267
|
-
try {
|
|
268
|
-
if ('text' in newCell.value && typeof newCell.value.text === 'string') {
|
|
269
|
-
newCell.value = newCell.value.text;
|
|
270
|
-
} else {
|
|
271
|
-
// 其他对象类型尝试JSON序列化
|
|
272
|
-
newCell.value = JSON.stringify(newCell.value);
|
|
273
|
-
}
|
|
274
|
-
} catch {
|
|
275
|
-
// 如果转换失败,使用toString
|
|
276
|
-
newCell.value = String(newCell.value);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
157
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (originalCell.font) newCell.font = JSON.parse(JSON.stringify(originalCell.font));
|
|
284
|
-
if (originalCell.alignment) newCell.alignment = JSON.parse(JSON.stringify(originalCell.alignment));
|
|
285
|
-
if (originalCell.border) newCell.border = JSON.parse(JSON.stringify(originalCell.border));
|
|
286
|
-
if (originalCell.numFmt) newCell.numFmt = originalCell.numFmt;
|
|
287
|
-
if (originalCell.fill) newCell.fill = JSON.parse(JSON.stringify(originalCell.fill));
|
|
288
|
-
|
|
289
|
-
// 检查是否为需要标记的单元格
|
|
290
|
-
const cellKey = `${rowNumber}-${colIndex + 1}`;
|
|
291
|
-
if (cellMarkMap.has(cellKey)) {
|
|
292
|
-
// 设置背景颜色
|
|
293
|
-
newCell.fill = {
|
|
294
|
-
type: 'pattern',
|
|
295
|
-
pattern: 'solid',
|
|
296
|
-
fgColor: { argb: cellMarkMap.get(cellKey) },
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
} else {
|
|
300
|
-
// 为新增列设置空值
|
|
301
|
-
newCell.value = null;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// 复制行属性
|
|
306
|
-
if (row.height) newRow.height = row.height;
|
|
307
|
-
if (row.outlineLevel) newRow.outlineLevel = row.outlineLevel;
|
|
308
|
-
|
|
309
|
-
newRow.commit();
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
// 生成Excel文件Buffer
|
|
314
|
-
const excelOutput = await newWorkbook.xlsx.writeBuffer();
|
|
315
|
-
|
|
316
|
-
// 创建Blob对象
|
|
317
|
-
const excelBlob = new Blob([excelOutput], {
|
|
318
|
-
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
return { hasError: true, errBlob: excelBlob };
|
|
158
|
+
// 调用excel-view的方法生成带标记的Excel
|
|
159
|
+
return await toExcel({ headers, rows }, fileName, markInfo);
|
|
322
160
|
};
|
|
323
161
|
|
|
324
162
|
/**
|
|
@@ -374,11 +212,24 @@ export const validateExcel = async (
|
|
|
374
212
|
color: 'FFFF0000', // 红色
|
|
375
213
|
}));
|
|
376
214
|
|
|
377
|
-
//
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
215
|
+
// 使用excel-view统一创建标记Excel
|
|
216
|
+
const markResult = await createMarkedExcelView(
|
|
217
|
+
excelBuffer,
|
|
218
|
+
{
|
|
219
|
+
markCells,
|
|
220
|
+
markHeaders: missingFields,
|
|
221
|
+
},
|
|
222
|
+
'validation_errors.xlsx',
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
if (markResult.success && markResult.blobUrl) {
|
|
226
|
+
// 从blob URL创建blob对象
|
|
227
|
+
const response = await fetch(markResult.blobUrl);
|
|
228
|
+
const errBlob = await response.blob();
|
|
229
|
+
return { hasError: true, errBlob };
|
|
230
|
+
} else {
|
|
231
|
+
return { hasError: true };
|
|
232
|
+
}
|
|
382
233
|
}
|
|
383
234
|
|
|
384
235
|
return { hasError: false }; // 没有错误时返回null
|
|
@@ -522,8 +373,24 @@ export const checkExcelDuplicates = async (
|
|
|
522
373
|
});
|
|
523
374
|
});
|
|
524
375
|
|
|
525
|
-
//
|
|
526
|
-
|
|
376
|
+
// 使用excel-view统一创建标记Excel
|
|
377
|
+
const markResult = await createMarkedExcelView(
|
|
378
|
+
excelBuffer,
|
|
379
|
+
{
|
|
380
|
+
markCells,
|
|
381
|
+
markHeaders: missingDuplicateFields,
|
|
382
|
+
},
|
|
383
|
+
'duplicate_errors.xlsx',
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
if (markResult.success && markResult.blobUrl) {
|
|
387
|
+
// 从blob URL创建blob对象
|
|
388
|
+
const response = await fetch(markResult.blobUrl);
|
|
389
|
+
const errBlob = await response.blob();
|
|
390
|
+
return { hasError: true, errBlob };
|
|
391
|
+
} else {
|
|
392
|
+
return { hasError: true };
|
|
393
|
+
}
|
|
527
394
|
}
|
|
528
395
|
|
|
529
396
|
return { hasError: false }; // 没有重复数据
|
package/src/utils/options.ts
CHANGED
|
@@ -179,25 +179,77 @@ const queryOptions = <T>(
|
|
|
179
179
|
|
|
180
180
|
/**
|
|
181
181
|
* 获取选中的选项对象或对象数组
|
|
182
|
+
* - 支持单选或者多选
|
|
183
|
+
* - 支持子级选项
|
|
182
184
|
* @param values 当前选择的值
|
|
183
185
|
* @param options 所有选项对象数组
|
|
186
|
+
* @param keepChildren 是否保留子选项,默认为 true
|
|
184
187
|
* @returns 选中的选项对象或对象数组
|
|
185
188
|
*/
|
|
186
189
|
export const getSelectedValues = (
|
|
187
190
|
values: undefined | string | number | (string | number | undefined)[],
|
|
188
191
|
options: OptionItemProps[],
|
|
192
|
+
keepChildren?: boolean,
|
|
189
193
|
): OptionItemProps | OptionItemProps[] | undefined => {
|
|
190
194
|
// 如果 values 为 undefined,直接返回 undefined
|
|
191
195
|
if (values === undefined) return undefined;
|
|
192
196
|
|
|
197
|
+
// 深拷贝选项以确保数据隔离
|
|
198
|
+
const deepCloneOption = (option: OptionItemProps): OptionItemProps => {
|
|
199
|
+
const cloned = { ...option };
|
|
200
|
+
if (keepChildren && option.children && option.children.length > 0) {
|
|
201
|
+
cloned.children = option.children.map((child: OptionItemProps) => deepCloneOption(child));
|
|
202
|
+
} else {
|
|
203
|
+
delete cloned.children;
|
|
204
|
+
}
|
|
205
|
+
return cloned;
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// 递归查找匹配的选项
|
|
209
|
+
const findMatchedOptions = (
|
|
210
|
+
searchValues: (string | number | undefined)[],
|
|
211
|
+
searchOptions: OptionItemProps[],
|
|
212
|
+
): OptionItemProps[] => {
|
|
213
|
+
const matched: OptionItemProps[] = [];
|
|
214
|
+
|
|
215
|
+
for (const option of searchOptions) {
|
|
216
|
+
// 检查当前选项是否匹配
|
|
217
|
+
if (searchValues.includes(option.value)) {
|
|
218
|
+
matched.push(deepCloneOption(option));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// 递归检查子选项
|
|
222
|
+
if (option.children && option.children.length > 0) {
|
|
223
|
+
const childMatched = findMatchedOptions(searchValues, option.children);
|
|
224
|
+
matched.push(...childMatched);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return matched;
|
|
229
|
+
};
|
|
230
|
+
|
|
193
231
|
// 如果 values 是数组,返回所有匹配的选项对象数组
|
|
194
232
|
if (Array.isArray(values)) {
|
|
195
|
-
return
|
|
233
|
+
return findMatchedOptions(values, options);
|
|
196
234
|
}
|
|
197
235
|
// 如果 values 是单个值,返回匹配的单个选项对象
|
|
198
236
|
else {
|
|
199
|
-
|
|
237
|
+
const matched = findMatchedOptions([values], options);
|
|
238
|
+
return matched.length > 0 ? matched[0] : undefined;
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* 获取选中的选项文字内容
|
|
244
|
+
* @param selectedValues 选中的选项对象或对象数
|
|
245
|
+
* @returns 选中的选项文字内容
|
|
246
|
+
*/
|
|
247
|
+
export const getSelectedLabels = (selectedValues: OptionItemProps | OptionItemProps[] | undefined): string[] => {
|
|
248
|
+
if (selectedValues === undefined) return [];
|
|
249
|
+
if (Array.isArray(selectedValues)) {
|
|
250
|
+
return selectedValues.map((option) => option.label);
|
|
200
251
|
}
|
|
252
|
+
return [selectedValues.label];
|
|
201
253
|
};
|
|
202
254
|
|
|
203
255
|
// 辅助函数:根据路径设置值
|
|
@@ -216,7 +268,10 @@ const setNestedValue = (obj: Record<string, any>, path: string, value: any) => {
|
|
|
216
268
|
|
|
217
269
|
/**
|
|
218
270
|
* 将选中的值根据 outFields 映射到 formData 上
|
|
219
|
-
* @param formData
|
|
271
|
+
* @param formData 需要更新的数据对
|
|
272
|
+
* 输出字段转换控制
|
|
273
|
+
* - Key:目的字段,支持 "." 嵌套
|
|
274
|
+
* - Value:源字段,支持模板 ${} 或者 ${index} 或者 ${index}.${key}
|
|
220
275
|
* @param outFields 输出字段转换映射关系
|
|
221
276
|
* @param selectedValues 选中的选项对象或对象数组
|
|
222
277
|
*/
|
|
@@ -235,12 +290,28 @@ export const outFormDataFields = (
|
|
|
235
290
|
|
|
236
291
|
// 如果 selectedValues 是数组
|
|
237
292
|
if (Array.isArray(selectedValues)) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
293
|
+
Object.entries(outFields).forEach(([targetKey, sourceKey]) => {
|
|
294
|
+
// 必须是 ${index} 或者 ${index}.${key},否则输出错误并跳过
|
|
295
|
+
const reg = /^\$\{\d+\}/;
|
|
296
|
+
// 第一个必须是 ${index},否则输出错误并跳过
|
|
297
|
+
if (reg.test(sourceKey)) {
|
|
298
|
+
try {
|
|
299
|
+
const index = parseInt(sourceKey.match(/\$\{(\d+)\}/)?.[1] ?? '0');
|
|
300
|
+
const targetValue = selectedValues[index];
|
|
301
|
+
const restKey = sourceKey.replace(/\$\{\d+\}\./, '');
|
|
302
|
+
if (restKey && targetValue) {
|
|
303
|
+
const value = parseFieldTemplate(restKey, targetValue);
|
|
304
|
+
setNestedValue(formData, targetKey, value);
|
|
305
|
+
} else {
|
|
306
|
+
setNestedValue(formData, targetKey, targetValue);
|
|
307
|
+
}
|
|
308
|
+
} catch (error) {
|
|
309
|
+
console.error('outFields 格式错误:' + sourceKey, '必须是 ${index} 或者 ${index}.${key}');
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
312
|
+
console.error('outFields 格式错误:' + sourceKey, '必须是 ${index} 或者 ${index}.${key}');
|
|
313
|
+
}
|
|
314
|
+
});
|
|
244
315
|
}
|
|
245
316
|
// 如果 selectedValues 是单个对象
|
|
246
317
|
else {
|
|
@@ -320,16 +391,3 @@ export const onOptionChanged = (
|
|
|
320
391
|
}
|
|
321
392
|
return selectedValues;
|
|
322
393
|
};
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* 获取选中的选项文字内容
|
|
326
|
-
* @param selectedValues 选中的选项对象或对象数
|
|
327
|
-
* @returns 选中的选项文字内容
|
|
328
|
-
*/
|
|
329
|
-
export const getSelectedLabels = (selectedValues: OptionItemProps | OptionItemProps[] | undefined): string[] => {
|
|
330
|
-
if (selectedValues === undefined) return [];
|
|
331
|
-
if (Array.isArray(selectedValues)) {
|
|
332
|
-
return selectedValues.map((option) => option.label);
|
|
333
|
-
}
|
|
334
|
-
return [selectedValues.label];
|
|
335
|
-
};
|
package/src/utils/table.ts
CHANGED
|
@@ -25,8 +25,9 @@ interface TableColumn {
|
|
|
25
25
|
*/
|
|
26
26
|
export const filterColumns = (columns: TableColumn[], toolCtl?: boolean) => {
|
|
27
27
|
const userInfoStore = useUserInfo();
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
// 检查是否存在enabled:false的列
|
|
29
|
+
// 并且设置没有权限的列为enabled:false
|
|
30
|
+
const enabledColumns = columns.filter((column) => {
|
|
30
31
|
// 角色权限检查
|
|
31
32
|
if (column.role && !userInfoStore.hasRole(column.role)) {
|
|
32
33
|
return false;
|
|
@@ -37,6 +38,18 @@ export const filterColumns = (columns: TableColumn[], toolCtl?: boolean) => {
|
|
|
37
38
|
return false;
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
if (column.enabled === false) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (typeof column.enabled === 'function') {
|
|
46
|
+
return column.enabled();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
return enabledColumns.filter((column) => {
|
|
40
53
|
if (!toolCtl) {
|
|
41
54
|
// 可见性检查
|
|
42
55
|
if (column.visible === false) {
|
package/vite.config.ts
CHANGED
|
@@ -47,7 +47,6 @@ export default defineConfig(({ mode }: ConfigEnv) => {
|
|
|
47
47
|
'@': path.resolve('./src'),
|
|
48
48
|
'@skyfox2000/fapi': path.resolve('../502417_fapi'),
|
|
49
49
|
'@skyfox2000/microbase': path.resolve('../502424_MicroBase'),
|
|
50
|
-
'@skyfox2000/webbase': path.resolve('../502428_WebBase'),
|
|
51
50
|
},
|
|
52
51
|
extensions: ['.js', '.ts', '.vue', 'json'],
|
|
53
52
|
},
|