@liujitcn/kratos-admin-core 0.0.47 → 0.0.49
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 +6 -0
- package/dist/package/declarations/src/format.d.ts +1 -1
- package/dist/package/declarations/src/utils/proTable.d.ts +2 -12
- package/dist/package/declarations/src/utils/tableColumn.d.ts +10 -0
- package/dist/package/declarations/src/utils/utils.d.ts +2 -0
- package/dist/package/src/components/ProTable/components/TableColumn.vue +147 -4
- package/dist/package/src/components/ProTable/index.vue +2 -2
- package/dist/package/src/format.ts +1 -1
- package/dist/package/src/utils/proTable.ts +3 -53
- package/dist/package/src/utils/tableColumn.ts +22 -0
- package/dist/package/src/utils/utils.ts +9 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -177,3 +177,9 @@ pnpm --filter @liujitcn/kratos-admin-core type:check
|
|
|
177
177
|
pnpm --filter @liujitcn/kratos-admin-core build:package
|
|
178
178
|
pnpm --filter @liujitcn/kratos-admin-core pack
|
|
179
179
|
```
|
|
180
|
+
|
|
181
|
+
时间列的对齐方式由页面通过 `align` 显式配置,ProTable 不按时间字段名称判断;修改时间列使用 `align: "center"` 居中显示。
|
|
182
|
+
|
|
183
|
+
ProTable 的 `cellType: "actions"` 操作列按当前行的 `hidden` 过滤按钮,优先展示使用 `common.action.edit`、`common.action.delete` 文案的编辑、删除操作;可见按钮超过三项时,其余操作收入“更多”菜单。未配置或无权限的编辑、删除不会补充显示,菜单保留图标、禁用状态和点击参数;自定义 render 或插槽不参与折叠。
|
|
184
|
+
|
|
185
|
+
操作列默认固定在右侧。配置式操作列(`cellType: "actions"`)根据当前页实际展示按钮和表头的最大宽度自适应,计入翻译文案、图标和间距,随语言、字体和行权限变化重新测量,最小宽度为 `80px`;折叠菜单内的按钮不参与测量。自定义 render 或插槽操作列仍默认 `160px`。页面可通过 `width` 或 `minWidth` 覆盖自动宽度,通过 `fixed: "left"` 调整固定位置,或通过 `fixed: false` 取消固定。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { formatJson, formatSrc, normalizeRichTextMediaPaths, normalizeStaticAssetPath } from "./utils/utils";
|
|
1
|
+
export { formatDateTime, formatJson, formatSrc, normalizeRichTextMediaPaths, normalizeStaticAssetPath } from "./utils/utils";
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EnumProps } from "../components/ProTable/interface";
|
|
2
|
+
export { resolveTableColumnAlign, type TableAlign } from "./tableColumn";
|
|
2
3
|
/** 字典值输出给表格枚举时的目标类型。 */
|
|
3
4
|
type DictValueType = "number" | "string";
|
|
4
5
|
/** 表格批量操作支持的主键类型。 */
|
|
5
6
|
type SelectedId = string | number;
|
|
6
|
-
/** 表格单元格支持的对齐方式。 */
|
|
7
|
-
export type TableAlign = "left" | "center" | "right";
|
|
8
7
|
/** 表格分页入参。 */
|
|
9
8
|
type PageRequestParams = Record<string, any> & {
|
|
10
9
|
/** 当前页码。 */
|
|
@@ -19,14 +18,6 @@ type NormalizedPageRequest<T extends PageRequestParams> = T & {
|
|
|
19
18
|
/** 接口请求每页条数。 */
|
|
20
19
|
page_size: number;
|
|
21
20
|
};
|
|
22
|
-
/**
|
|
23
|
-
* 根据列语义和当前表格数据解析单元格对齐方式。
|
|
24
|
-
*
|
|
25
|
-
* 显式 align 始终优先;数据表映射按文本左对齐,字典、静态枚举及预置状态列居中,
|
|
26
|
-
* 金额列和纯数字列右对齐,其余内容左对齐。空表时会先按列语义返回默认值,
|
|
27
|
-
* 数据加载后由响应式表格重新解析。
|
|
28
|
-
*/
|
|
29
|
-
export declare function resolveTableColumnAlign(column: ColumnProps, rows?: Record<string, any>[]): TableAlign;
|
|
30
21
|
/**
|
|
31
22
|
* 将字典缓存转换为 ProTable 搜索枚举数据。
|
|
32
23
|
*/
|
|
@@ -41,4 +32,3 @@ export declare function buildPageRequest<T extends PageRequestParams>(params: T)
|
|
|
41
32
|
* 统一整理表格多选和单条操作产生的 ID 集合。
|
|
42
33
|
*/
|
|
43
34
|
export declare function normalizeSelectedIds(selected?: SelectedId | SelectedId[]): SelectedId[];
|
|
44
|
-
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ColumnProps } from "../components/ProTable/interface";
|
|
2
|
+
/** 表格单元格支持的对齐方式。 */
|
|
3
|
+
export type TableAlign = "left" | "center" | "right";
|
|
4
|
+
/**
|
|
5
|
+
* 根据列显式配置和组件类型解析单元格对齐方式。
|
|
6
|
+
*
|
|
7
|
+
* 显式 align 始终优先;选择列、状态列和图片列默认居中,金额列默认右对齐,
|
|
8
|
+
* 字典与枚举列默认居中。普通字段不根据字段名或实际数据猜测,默认左对齐。
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveTableColumnAlign(column: ColumnProps): TableAlign;
|
|
@@ -6,6 +6,8 @@ export declare function formatJson(str: string): string;
|
|
|
6
6
|
* 将后端分单位金额转换为元字符串。
|
|
7
7
|
*/
|
|
8
8
|
export declare function formatPrice(price?: number): string;
|
|
9
|
+
/** 将时间值格式化为统一的本地日期时间文本。 */
|
|
10
|
+
export declare function formatDateTime(value?: string | number | Date): string;
|
|
9
11
|
/**
|
|
10
12
|
* 按静态资源域名补齐图片地址。
|
|
11
13
|
*/
|
|
@@ -3,8 +3,19 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup lang="ts" name="TableColumn">
|
|
6
|
-
import { h, inject, isProxy, markRaw, ref, toRaw, useSlots } from "vue";
|
|
7
|
-
import {
|
|
6
|
+
import { h, inject, isProxy, markRaw, onUnmounted, ref, toRaw, useSlots, withDirectives } from "vue";
|
|
7
|
+
import type { ObjectDirective } from "vue";
|
|
8
|
+
import {
|
|
9
|
+
ElButton,
|
|
10
|
+
ElDropdown,
|
|
11
|
+
ElDropdownItem,
|
|
12
|
+
ElDropdownMenu,
|
|
13
|
+
ElImage,
|
|
14
|
+
ElSwitch,
|
|
15
|
+
ElTableColumn,
|
|
16
|
+
ElTag,
|
|
17
|
+
ElText
|
|
18
|
+
} from "element-plus";
|
|
8
19
|
import DictLabel from "../../../components/Dict/DictLabel.vue";
|
|
9
20
|
import { ColumnProps, HeaderRenderScope, RenderScope, TableActionProps } from "../../../components/ProTable/interface";
|
|
10
21
|
import type { TableAlign } from "../../../utils/proTable";
|
|
@@ -21,6 +32,57 @@ const slots = useSlots();
|
|
|
21
32
|
|
|
22
33
|
const enumMap = inject("enumMap", ref(new Map()));
|
|
23
34
|
|
|
35
|
+
const actionWidths = ref(new Map<string, number>());
|
|
36
|
+
const measuredCells = new Map<HTMLElement, string>();
|
|
37
|
+
let resizeObserver: ResizeObserver | undefined;
|
|
38
|
+
let measureFrame = 0;
|
|
39
|
+
|
|
40
|
+
/** 合并当前列所有可见行和表头的实际宽度,支持语言、字体和权限变化。 */
|
|
41
|
+
const scheduleActionMeasurement = () => {
|
|
42
|
+
cancelAnimationFrame(measureFrame);
|
|
43
|
+
measureFrame = requestAnimationFrame(() => {
|
|
44
|
+
const widths = new Map<string, number>();
|
|
45
|
+
measuredCells.forEach((key, element) => {
|
|
46
|
+
if (!element.isConnected || !element.getClientRects().length) return;
|
|
47
|
+
const cell = element.closest(".cell");
|
|
48
|
+
if (!cell) return;
|
|
49
|
+
const style = getComputedStyle(cell);
|
|
50
|
+
const width = Math.ceil(
|
|
51
|
+
element.getBoundingClientRect().width + parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + 2
|
|
52
|
+
);
|
|
53
|
+
widths.set(key, Math.max(widths.get(key) ?? 80, width));
|
|
54
|
+
});
|
|
55
|
+
if (widths.size !== actionWidths.value.size || [...widths].some(([key, width]) => actionWidths.value.get(key) !== width)) {
|
|
56
|
+
actionWidths.value = widths;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/** 观察渲染后的操作内容,避免按字符个数估算不同语言的文本宽度。 */
|
|
62
|
+
const measureActionContent: ObjectDirective<HTMLElement, string> = {
|
|
63
|
+
mounted(element, binding) {
|
|
64
|
+
measuredCells.set(element, binding.value);
|
|
65
|
+
resizeObserver ??= new ResizeObserver(scheduleActionMeasurement);
|
|
66
|
+
resizeObserver.observe(element);
|
|
67
|
+
scheduleActionMeasurement();
|
|
68
|
+
},
|
|
69
|
+
updated(element, binding) {
|
|
70
|
+
measuredCells.set(element, binding.value);
|
|
71
|
+
scheduleActionMeasurement();
|
|
72
|
+
},
|
|
73
|
+
unmounted(element) {
|
|
74
|
+
measuredCells.delete(element);
|
|
75
|
+
resizeObserver?.unobserve(element);
|
|
76
|
+
scheduleActionMeasurement();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
onUnmounted(() => {
|
|
81
|
+
resizeObserver?.disconnect();
|
|
82
|
+
cancelAnimationFrame(measureFrame);
|
|
83
|
+
measuredCells.clear();
|
|
84
|
+
});
|
|
85
|
+
|
|
24
86
|
/**
|
|
25
87
|
* 透传给 Element Plus 前移除图标组件上的响应式代理,避免 Vue 对组件对象发出性能告警。
|
|
26
88
|
*/
|
|
@@ -166,18 +228,23 @@ const renderMoneyCell = (item: ColumnProps, scope: RenderScope<any>) => {
|
|
|
166
228
|
};
|
|
167
229
|
|
|
168
230
|
/**
|
|
169
|
-
*
|
|
231
|
+
* 渲染操作按钮列,优先展示编辑、删除,超过三项时将其他操作折叠。
|
|
170
232
|
*/
|
|
171
233
|
const renderActionsCell = (item: ColumnProps, scope: RenderScope<any>) => {
|
|
172
234
|
if (!item.actions?.length) return "--";
|
|
173
235
|
const visibleActions = item.actions.filter(action => !getBooleanValue(action.hidden, scope));
|
|
174
236
|
if (!visibleActions.length) return "--";
|
|
175
|
-
|
|
237
|
+
const primaryLabels = [t("common.action.edit"), t("common.action.delete")];
|
|
238
|
+
const primaryActions = primaryLabels.flatMap(label => visibleActions.filter(action => action.label === label));
|
|
239
|
+
const otherActions = visibleActions.filter(action => !primaryLabels.includes(action.label));
|
|
240
|
+
const inlineActions = visibleActions.length > 3 ? primaryActions : [...primaryActions, ...otherActions];
|
|
241
|
+
const buttons = inlineActions.map((action: TableActionProps) => {
|
|
176
242
|
const params = resolveColumnParams(action.params, scope);
|
|
177
243
|
return h(
|
|
178
244
|
ElButton,
|
|
179
245
|
{
|
|
180
246
|
key: action.label,
|
|
247
|
+
size: "small",
|
|
181
248
|
type: action.type ?? "primary",
|
|
182
249
|
link: action.link ?? true,
|
|
183
250
|
icon: normalizeActionIcon(action.icon),
|
|
@@ -187,6 +254,41 @@ const renderActionsCell = (item: ColumnProps, scope: RenderScope<any>) => {
|
|
|
187
254
|
{ default: () => action.label }
|
|
188
255
|
);
|
|
189
256
|
});
|
|
257
|
+
if (visibleActions.length > 3 && otherActions.length)
|
|
258
|
+
buttons.push(
|
|
259
|
+
h(
|
|
260
|
+
ElDropdown,
|
|
261
|
+
{ trigger: "click", placement: "bottom-end", size: "small" },
|
|
262
|
+
{
|
|
263
|
+
default: () =>
|
|
264
|
+
h(ElButton, { type: "primary", link: true, size: "small", icon: ArrowDown }, () => t("common.action.more")),
|
|
265
|
+
dropdown: () =>
|
|
266
|
+
h(ElDropdownMenu, null, () =>
|
|
267
|
+
otherActions.map(action => {
|
|
268
|
+
const disabled = getBooleanValue(action.disabled, scope);
|
|
269
|
+
const params = resolveColumnParams(action.params, scope);
|
|
270
|
+
return h(
|
|
271
|
+
ElDropdownItem,
|
|
272
|
+
{
|
|
273
|
+
key: action.label,
|
|
274
|
+
icon: normalizeActionIcon(action.icon),
|
|
275
|
+
disabled,
|
|
276
|
+
style: disabled ? undefined : { color: `var(--el-color-${action.type ?? "primary"})` },
|
|
277
|
+
onClick: () => {
|
|
278
|
+
if (!disabled) action.onClick(scope, params);
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
() => action.label
|
|
282
|
+
);
|
|
283
|
+
})
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
const content = h("span", { class: "pro-table-actions" }, buttons);
|
|
289
|
+
return item.width == null && item.minWidth == null
|
|
290
|
+
? withDirectives(content, [[measureActionContent, item.prop ?? item.label ?? ""]])
|
|
291
|
+
: content;
|
|
190
292
|
};
|
|
191
293
|
|
|
192
294
|
/** 渲染默认表头标题,避免窄列换行并保留完整标题提示。 */
|
|
@@ -213,12 +315,23 @@ const renderPresetCell = (item: ColumnProps, scope: RenderScope<any>) => {
|
|
|
213
315
|
}
|
|
214
316
|
};
|
|
215
317
|
|
|
318
|
+
/** 渲染表格列,为操作列提供自适应宽度和右侧固定默认值。 */
|
|
216
319
|
const RenderTableColumn = (item: ColumnProps) => {
|
|
217
320
|
if (!item.isShow) return null;
|
|
321
|
+
const isActionColumn = item.cellType === "actions" || item.prop === "operation";
|
|
322
|
+
const autoActionWidth = item.cellType === "actions" && !item.render && !(item.prop && slots[handleProp(item.prop)]);
|
|
218
323
|
return h(
|
|
219
324
|
ElTableColumn,
|
|
220
325
|
{
|
|
221
326
|
...item,
|
|
327
|
+
width:
|
|
328
|
+
item.width ??
|
|
329
|
+
(isActionColumn && item.minWidth == null
|
|
330
|
+
? autoActionWidth
|
|
331
|
+
? (actionWidths.value.get(item.prop ?? item.label ?? "") ?? 80)
|
|
332
|
+
: 160
|
|
333
|
+
: undefined),
|
|
334
|
+
fixed: item.fixed ?? (isActionColumn ? "right" : undefined),
|
|
222
335
|
align: item.align ?? props.resolveAlign?.(item) ?? "left",
|
|
223
336
|
showOverflowTooltip: item.showOverflowTooltip ?? item.prop !== "operation"
|
|
224
337
|
},
|
|
@@ -235,9 +348,39 @@ const RenderTableColumn = (item: ColumnProps) => {
|
|
|
235
348
|
header: (scope: HeaderRenderScope<any>) => {
|
|
236
349
|
if (item.headerRender) return item.headerRender(scope);
|
|
237
350
|
if (item.prop && slots[`${handleProp(item.prop)}Header`]) return slots[`${handleProp(item.prop)}Header`]!(scope);
|
|
351
|
+
if (autoActionWidth && item.width == null && item.minWidth == null) {
|
|
352
|
+
return withDirectives(h("span", { class: "pro-table-action-header" }, item.label), [
|
|
353
|
+
[measureActionContent, item.prop ?? item.label ?? ""]
|
|
354
|
+
]);
|
|
355
|
+
}
|
|
238
356
|
return renderHeaderLabel(item);
|
|
239
357
|
}
|
|
240
358
|
}
|
|
241
359
|
);
|
|
242
360
|
};
|
|
243
361
|
</script>
|
|
362
|
+
|
|
363
|
+
<style lang="scss">
|
|
364
|
+
// 操作容器在函数式列的插槽中生成,不带本组件的 scopeId,使用专属类名限定样式。
|
|
365
|
+
.pro-table-actions {
|
|
366
|
+
display: inline-flex;
|
|
367
|
+
flex-wrap: nowrap;
|
|
368
|
+
gap: 4px;
|
|
369
|
+
align-items: center;
|
|
370
|
+
width: max-content;
|
|
371
|
+
vertical-align: middle;
|
|
372
|
+
white-space: nowrap;
|
|
373
|
+
.el-button {
|
|
374
|
+
margin-left: 0;
|
|
375
|
+
}
|
|
376
|
+
.el-dropdown {
|
|
377
|
+
display: inline-flex;
|
|
378
|
+
align-items: center;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
.pro-table-action-header {
|
|
382
|
+
display: inline-block;
|
|
383
|
+
width: max-content;
|
|
384
|
+
white-space: nowrap;
|
|
385
|
+
}
|
|
386
|
+
</style>
|
|
@@ -266,8 +266,8 @@ const processTableData = computed(() => {
|
|
|
266
266
|
);
|
|
267
267
|
});
|
|
268
268
|
|
|
269
|
-
/** 解析 ProTable
|
|
270
|
-
const resolveColumnAlign = (column: ColumnProps) => resolveTableColumnAlign(column
|
|
269
|
+
/** 解析 ProTable 列对齐方式,普通字段不根据字段名或行数据推断。 */
|
|
270
|
+
const resolveColumnAlign = (column: ColumnProps) => resolveTableColumnAlign(column);
|
|
271
271
|
|
|
272
272
|
/** 数据加载完成后按传入行 Key 恢复多选状态,用于页面重建后的选择态续接。 */
|
|
273
273
|
function restoreSelectedRows() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { formatJson, formatSrc, normalizeRichTextMediaPaths, normalizeStaticAssetPath } from "./utils/utils";
|
|
1
|
+
export { formatDateTime, formatJson, formatSrc, normalizeRichTextMediaPaths, normalizeStaticAssetPath } from "./utils/utils";
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EnumProps } from "../components/ProTable/interface";
|
|
2
2
|
import type { OptionBaseDictResponse_BaseDictItem } from "../rpc/system/admin/v1/base_dict";
|
|
3
3
|
import { useDictStoreHook } from "../stores/modules/dict";
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
export { resolveTableColumnAlign, type TableAlign } from "./tableColumn";
|
|
5
6
|
|
|
6
7
|
/** 字典值输出给表格枚举时的目标类型。 */
|
|
7
8
|
type DictValueType = "number" | "string";
|
|
8
9
|
/** 表格批量操作支持的主键类型。 */
|
|
9
10
|
type SelectedId = string | number;
|
|
10
11
|
|
|
11
|
-
/** 表格单元格支持的对齐方式。 */
|
|
12
|
-
export type TableAlign = "left" | "center" | "right";
|
|
13
|
-
|
|
14
12
|
/** 表格分页入参。 */
|
|
15
13
|
type PageRequestParams = Record<string, any> & {
|
|
16
14
|
/** 当前页码。 */
|
|
@@ -27,54 +25,6 @@ type NormalizedPageRequest<T extends PageRequestParams> = T & {
|
|
|
27
25
|
page_size: number;
|
|
28
26
|
};
|
|
29
27
|
|
|
30
|
-
/**
|
|
31
|
-
* 获取表格行的列值,支持点号分隔的多级字段。
|
|
32
|
-
*/
|
|
33
|
-
function getTableCellValue(row: Record<string, any>, prop: string) {
|
|
34
|
-
return prop.split(".").reduce((value, key) => (value == null ? undefined : value[key]), row as any);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 判断值是否为可用于数值对齐的 Number 类型。
|
|
39
|
-
*/
|
|
40
|
-
function isPureNumber(value: unknown) {
|
|
41
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* 判断枚举是否来自数据表映射,远程函数和响应式选项都属于动态数据映射。
|
|
46
|
-
*/
|
|
47
|
-
function isDataTableEnum(enumValue: ColumnProps["enum"]) {
|
|
48
|
-
return typeof enumValue === "function" || isRef(enumValue);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 根据列语义和当前表格数据解析单元格对齐方式。
|
|
53
|
-
*
|
|
54
|
-
* 显式 align 始终优先;数据表映射按文本左对齐,字典、静态枚举及预置状态列居中,
|
|
55
|
-
* 金额列和纯数字列右对齐,其余内容左对齐。空表时会先按列语义返回默认值,
|
|
56
|
-
* 数据加载后由响应式表格重新解析。
|
|
57
|
-
*/
|
|
58
|
-
export function resolveTableColumnAlign(column: ColumnProps, rows: Record<string, any>[] = []): TableAlign {
|
|
59
|
-
if (column.align === "left" || column.align === "center" || column.align === "right") return column.align;
|
|
60
|
-
|
|
61
|
-
const centeredTypes: TypeProps[] = ["selection", "radio", "index", "expand", "sort"];
|
|
62
|
-
if (centeredTypes.includes(column.type as TypeProps)) return "center";
|
|
63
|
-
if (column.cellType === "actions" || column.cellType === "status" || column.cellType === "image") return "center";
|
|
64
|
-
if (column.cellType === "money") return "right";
|
|
65
|
-
if (column.dictCode || column.tag) return "center";
|
|
66
|
-
if (column.enum) return isDataTableEnum(column.enum) ? "left" : "center";
|
|
67
|
-
|
|
68
|
-
if (column.prop) {
|
|
69
|
-
const values = rows
|
|
70
|
-
.map(row => getTableCellValue(row, column.prop as string))
|
|
71
|
-
.filter(value => value !== undefined && value !== null && value !== "");
|
|
72
|
-
if (values.length && values.every(isPureNumber)) return "right";
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return "left";
|
|
76
|
-
}
|
|
77
|
-
|
|
78
28
|
/**
|
|
79
29
|
* 按配置将字典值转换为表格枚举可识别的类型。
|
|
80
30
|
*/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ColumnProps, TypeProps } from "../components/ProTable/interface";
|
|
2
|
+
|
|
3
|
+
/** 表格单元格支持的对齐方式。 */
|
|
4
|
+
export type TableAlign = "left" | "center" | "right";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 根据列显式配置和组件类型解析单元格对齐方式。
|
|
8
|
+
*
|
|
9
|
+
* 显式 align 始终优先;选择列、状态列和图片列默认居中,金额列默认右对齐,
|
|
10
|
+
* 字典与枚举列默认居中。普通字段不根据字段名或实际数据猜测,默认左对齐。
|
|
11
|
+
*/
|
|
12
|
+
export function resolveTableColumnAlign(column: ColumnProps): TableAlign {
|
|
13
|
+
if (column.align === "left" || column.align === "center" || column.align === "right") return column.align;
|
|
14
|
+
|
|
15
|
+
const centeredTypes: TypeProps[] = ["selection", "radio", "index", "expand", "sort"];
|
|
16
|
+
if (centeredTypes.includes(column.type as TypeProps)) return "center";
|
|
17
|
+
if (column.cellType === "actions" || column.cellType === "status" || column.cellType === "image") return "center";
|
|
18
|
+
if (column.cellType === "money") return "right";
|
|
19
|
+
if (column.dictCode || column.tag || column.enum) return "center";
|
|
20
|
+
|
|
21
|
+
return "left";
|
|
22
|
+
}
|
|
@@ -17,6 +17,15 @@ export function formatPrice(price?: number) {
|
|
|
17
17
|
return (price / 100).toFixed(2);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/** 将时间值格式化为统一的本地日期时间文本。 */
|
|
21
|
+
export function formatDateTime(value?: string | number | Date) {
|
|
22
|
+
if (value === undefined || value === null || value === "") return "-";
|
|
23
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
24
|
+
if (Number.isNaN(date.getTime())) return String(value);
|
|
25
|
+
const pad = (part: number) => String(part).padStart(2, "0");
|
|
26
|
+
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
/**
|
|
21
30
|
* 按静态资源域名补齐图片地址。
|
|
22
31
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liujitcn/kratos-admin-core",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.49",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "kratos-admin frontend runtime and base modules",
|
|
7
7
|
"author": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dayjs": "^1.11.21",
|
|
33
33
|
"dompurify": "^3.4.5",
|
|
34
34
|
"driver.js": "^1.3.1",
|
|
35
|
-
"echarts": "^
|
|
35
|
+
"echarts": "^6.1.0",
|
|
36
36
|
"echarts-liquidfill": "^3.1.0",
|
|
37
37
|
"element-plus": "^2.7.6",
|
|
38
38
|
"go-captcha-vue": "2.0.6",
|