@done-coding/admin-core 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/es/bridge/badge.mjs +0 -1
  2. package/es/bridge/route.mjs +4 -1
  3. package/es/components/app-layout/AppHeader.vue.mjs +1 -1
  4. package/es/components/app-layout/AppHeader.vue2.mjs +2 -2
  5. package/es/components/app-layout/AppPage.vue.mjs +1 -1
  6. package/es/components/app-layout/AppPage.vue2.mjs +7 -7
  7. package/es/components/app-layout/app-page-geometry.mjs +2 -2
  8. package/es/components/display/BadgeMark.vue.mjs +1 -1
  9. package/es/components/display/BadgeMark.vue2.mjs +25 -15
  10. package/es/components/display/TabsHeader.vue.mjs +1 -1
  11. package/es/components/display/TabsHeader.vue2.mjs +1 -1
  12. package/es/components/display/TabsMain.vue.mjs +1 -1
  13. package/es/components/display/use-badge-mask.mjs +2 -3
  14. package/es/components/display/use-badge.mjs +36 -39
  15. package/es/components/form/FormMain.vue.mjs +1 -1
  16. package/es/components/form/FormSearch.vue.mjs +1 -1
  17. package/es/components/menu/MenuItemSub.vue.mjs +2 -2
  18. package/es/components/menu/MenuTree.vue.mjs +3 -3
  19. package/es/components/view-layout/ViewLayout.vue.mjs +1 -1
  20. package/es/components/view-layout/ViewLayout.vue2.mjs +1 -1
  21. package/es/config/badge-attr.mjs +6 -0
  22. package/es/hooks/use-theme-apply.mjs +48 -0
  23. package/es/index.mjs +3 -0
  24. package/es/style.css +97 -78
  25. package/es/utils/dom.mjs +12 -2
  26. package/package.json +2 -2
  27. package/src/bridge/docs/README.md +27 -2
  28. package/src/components/app-layout/docs/README-AppPage.md +1 -1
  29. package/src/components/display/docs/README-BadgeMark.md +24 -1
  30. package/src/components/page-layout/docs/README-AppPageListDetailLayout.md +1 -1
  31. package/src/components/view-layout/docs/README-ViewLayout.md +8 -2
  32. package/types/bridge/badge.d.ts +44 -7
  33. package/types/components/app-layout/app-page-geometry.d.ts +9 -2
  34. package/types/components/display/BadgeMark.vue.d.ts +5 -2
  35. package/types/components/display/use-badge.d.ts +40 -7
  36. package/types/config/badge-attr.d.ts +26 -0
  37. package/types/config/index.d.ts +1 -0
  38. package/types/hooks/menus-dispatch.d.ts +1 -0
  39. package/types/injectInfo.json.d.ts +1 -1
  40. package/types/types/route.d.ts +8 -0
  41. package/types/utils/dom.d.ts +10 -4
@@ -1,6 +1,5 @@
1
1
  import { shallowRef, readonly } from "vue";
2
2
  const BADGE_MASK_KINDS = [
3
- "wip",
4
3
  "locked"
5
4
  ];
6
5
  function createBridgeBadgeHook(init = {}) {
@@ -11,7 +11,7 @@ const createGenerateRouteMetaRawTree = (metaDefault) => {
11
11
  } = {}) => {
12
12
  const list = [];
13
13
  routesList.forEach((route) => {
14
- const { path, children, meta } = route;
14
+ const { path, name, children, meta } = route;
15
15
  const appMeta = meta;
16
16
  if (!appMeta) {
17
17
  console.error(`路由${path}未配置meta`);
@@ -27,6 +27,9 @@ const createGenerateRouteMetaRawTree = (metaDefault) => {
27
27
  });
28
28
  const metaResolveRaw = {
29
29
  path: currentPath,
30
+ // vue-router 的 RouteRecordName = string | symbol —— symbol 不能当徽标 key,
31
+ // 也不该被下游当字符串用,故解析期就过滤掉([MUST NOT] 直接透传)。
32
+ name: typeof name === "string" ? name : void 0,
30
33
  title,
31
34
  routeLevel,
32
35
  redirectToFirstChildRoute,
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./AppHeader.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const AppHeader = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-9ff1c70b"]]);
4
+ const AppHeader = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-fe33f01b"]]);
5
5
  export {
6
6
  AppHeader as default
7
7
  };
@@ -18,7 +18,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
18
18
  },
19
19
  setup(__props) {
20
20
  useCssVars((_ctx) => ({
21
- "v0b60c1aa": themeColors.value.primaryColor
21
+ "v5a41bfe6": themeColors.value.primaryColor
22
22
  }));
23
23
  const props = __props;
24
24
  const appStore = inject(APP_LAYOUT_APP_STORE_KEY);
@@ -93,7 +93,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
93
93
  }, 1024)) : createCommentVNode("", true),
94
94
  createElementVNode("span", null, [
95
95
  createVNode(unref(BadgeMark), {
96
- badgeKey: menu.path
96
+ badgeKey: [menu.name, menu.path]
97
97
  }, {
98
98
  default: withCtx(() => [
99
99
  createTextVNode(toDisplayString(menu.title), 1)
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./AppPage.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const AppPage = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-d875cc1d"]]);
4
+ const AppPage = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-facaf577"]]);
5
5
  export {
6
6
  AppPage as default
7
7
  };
@@ -39,13 +39,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
39
39
  },
40
40
  setup(__props) {
41
41
  useCssVars((_ctx) => ({
42
- "b28df728": pageCssVars.value.top,
43
- "d4142898": pageCssVars.value.bottom,
44
- "v3063bfd0": pageCssVars.value.left,
45
- "v472ac91a": pageCssVars.value.right,
46
- "v469df1c6": pageCssVars.value.width,
47
- "c0be3aa0": pageCssVars.value.height,
48
- "v52d7da39": props.nextViewportMaxHeight
42
+ "v14c1dc69": pageCssVars.value.top,
43
+ "v6d1cb697": pageCssVars.value.bottom,
44
+ "f914311a": pageCssVars.value.left,
45
+ "v28c52fa0": pageCssVars.value.right,
46
+ "v2838584c": pageCssVars.value.width,
47
+ "v76c7ad93": pageCssVars.value.height,
48
+ "v9258c294": props.nextViewportMaxHeight
49
49
  }));
50
50
  const props = __props;
51
51
  const style = computed(() => {
@@ -63,8 +63,8 @@ function computeAppPageSlotStyles(rect, slotSizes, outerGap) {
63
63
  };
64
64
  }
65
65
  function computeAppPageSlotShimStyles() {
66
- const none = { padding: "0" };
67
- return { top: none, bottom: none, left: none, right: none };
66
+ const pad = { padding: "8px" };
67
+ return { top: pad, bottom: pad, left: pad, right: pad };
68
68
  }
69
69
  export {
70
70
  APP_PAGE_SLOT_Z_INDEX,
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./BadgeMark.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const BadgeMark = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-4116ac36"]]);
4
+ const BadgeMark = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-18853ddc"]]);
5
5
  export {
6
6
  BadgeMark as default
7
7
  };
@@ -1,7 +1,8 @@
1
- import { defineComponent, useTemplateRef, unref, openBlock, createBlock, normalizeClass, createSlots, withCtx, renderSlot, createVNode, resolveDynamicComponent } from "vue";
1
+ import { defineComponent, computed, useTemplateRef, openBlock, createBlock, unref, normalizeProps, createSlots, withCtx, renderSlot, createVNode, resolveDynamicComponent } from "vue";
2
2
  import { ElBadge, ElTooltip, ElIcon } from "element-plus";
3
- import { useBadgeResolved, useBadgeEntry } from "./use-badge.mjs";
3
+ import { useBadgeHit, badgeResolveDisplay } from "./use-badge.mjs";
4
4
  import { useBadgeMask } from "./use-badge-mask.mjs";
5
+ import { BADGE_KEY_ATTR } from "../../config/badge-attr.mjs";
5
6
  const _sfc_main = /* @__PURE__ */ defineComponent({
6
7
  __name: "BadgeMark",
7
8
  props: {
@@ -10,42 +11,51 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10
11
  },
11
12
  setup(__props) {
12
13
  const props = __props;
13
- const resolved = useBadgeResolved(() => props.badgeKey);
14
+ const hit = useBadgeHit(() => props.badgeKey);
15
+ const resolved = computed(() => {
16
+ var _a;
17
+ return badgeResolveDisplay((_a = hit.value) == null ? void 0 : _a.entry);
18
+ });
14
19
  const badgeRef = useTemplateRef("badgeRef");
15
- const entry = useBadgeEntry(() => props.badgeKey);
16
20
  useBadgeMask(
17
21
  () => {
18
22
  var _a;
19
23
  return ((_a = badgeRef.value) == null ? void 0 : _a.$el) ?? void 0;
20
24
  },
21
- () => entry.value
25
+ () => {
26
+ var _a;
27
+ return (_a = hit.value) == null ? void 0 : _a.entry;
28
+ }
22
29
  );
23
30
  return (_ctx, _cache) => {
24
- return unref(resolved) ? (openBlock(), createBlock(unref(ElBadge), {
31
+ var _a;
32
+ return resolved.value ? (openBlock(), createBlock(unref(ElBadge), normalizeProps({
25
33
  key: 0,
26
34
  ref_key: "badgeRef",
27
35
  ref: badgeRef,
28
- class: normalizeClass(["dc-badge-mark badge-mark", `badge-mark_${__props.align ?? "middle"}`]),
29
- value: unref(resolved).value,
30
- max: unref(resolved).max,
31
- type: unref(resolved).type
32
- }, createSlots({
36
+ class: ["dc-badge-mark badge-mark", `badge-mark_${__props.align ?? "middle"}`],
37
+ hidden: resolved.value.hidden,
38
+ value: resolved.value.value,
39
+ max: resolved.value.max,
40
+ type: resolved.value.type,
41
+ [unref(BADGE_KEY_ATTR) || ""]: (_a = unref(hit)) == null ? void 0 : _a.key
42
+ }), createSlots({
33
43
  default: withCtx(() => [
34
44
  renderSlot(_ctx.$slots, "default", {}, void 0, true)
35
45
  ]),
36
46
  _: 2
37
47
  }, [
38
- unref(resolved).icon ? {
48
+ resolved.value.icon ? {
39
49
  name: "content",
40
50
  fn: withCtx(() => [
41
51
  createVNode(unref(ElTooltip), {
42
- content: unref(resolved).label,
52
+ content: resolved.value.label,
43
53
  placement: "top"
44
54
  }, {
45
55
  default: withCtx(() => [
46
56
  createVNode(unref(ElIcon), { class: "badge-mark__icon" }, {
47
57
  default: withCtx(() => [
48
- (openBlock(), createBlock(resolveDynamicComponent(unref(resolved).icon)))
58
+ (openBlock(), createBlock(resolveDynamicComponent(resolved.value.icon)))
49
59
  ]),
50
60
  _: 1
51
61
  })
@@ -55,7 +65,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
55
65
  ]),
56
66
  key: "0"
57
67
  } : void 0
58
- ]), 1032, ["class", "value", "max", "type"])) : renderSlot(_ctx.$slots, "default", { key: 1 }, void 0, true);
68
+ ]), 1040, ["class", "hidden", "value", "max", "type"])) : renderSlot(_ctx.$slots, "default", { key: 1 }, void 0, true);
59
69
  };
60
70
  }
61
71
  });
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./TabsHeader.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const TabsHeader = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-14448dd1"]]);
4
+ const TabsHeader = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-2fbdd074"]]);
5
5
  export {
6
6
  TabsHeader as default
7
7
  };
@@ -17,7 +17,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
17
17
  emits: ["update:activeKey"],
18
18
  setup(__props) {
19
19
  useCssVars((_ctx) => ({
20
- "v72da80bd": unref(activeBg)
20
+ "v0fab19c0": unref(activeBg)
21
21
  }));
22
22
  const props = __props;
23
23
  const { tabs, level, variant, activeBg } = toRefs(props);
@@ -39,7 +39,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
39
39
  const { ctxRefine } = useContextDefaults({
40
40
  getProps: () => props,
41
41
  defaults: {
42
- refine: ({ parentInfo, props: rawProps }) => rawProps.refine ?? (parentInfo === SlotRegion.AppPage_Default ? true : void 0)
42
+ refine: ({ parentInfo, props: rawProps }) => rawProps.refine ?? (parentInfo === SlotRegion.AppPage_Default || parentInfo === SlotRegion.ModalConfirm_Body ? true : void 0)
43
43
  }
44
44
  });
45
45
  const parentVisualLevel = inject(TABS_MAIN_VISUAL_LEVEL, 0);
@@ -1,12 +1,11 @@
1
1
  import { watch } from "vue";
2
2
  import { ElMessage } from "element-plus";
3
3
  import { useActivated } from "../../hooks/activated.mjs";
4
+ import { BADGE_HOST_ATTR } from "../../config/badge-attr.mjs";
4
5
  import { BADGE_MASK_KINDS } from "../../bridge/badge.mjs";
5
- const BADGE_HOST_ATTR = "data-dc-badge-host";
6
6
  const BADGE_VEIL_CLASS = "dc-badge-mask__veil";
7
7
  const BADGE_MASK_DEFAULT_TIP = {
8
- locked: "请联系平台开通功能",
9
- wip: "功能正在加紧开发中"
8
+ locked: "请联系平台开通功能"
10
9
  };
11
10
  const badgeMaskKindSet = new Set(BADGE_MASK_KINDS);
12
11
  const useBadgeMask = (getAnchor, getEntry) => {
@@ -40,50 +40,47 @@ function useBadgeNow() {
40
40
  });
41
41
  return badgeNow;
42
42
  }
43
- function useBadgeEntry(getKey) {
44
- const bridge = inject(CORE_BRIDGE_KEY, void 0);
45
- const now = useBadgeNow();
46
- return computed(() => {
47
- const key = getKey();
48
- if (!key || !bridge) return void 0;
49
- const hit = bridge.badge.marks.value[key];
50
- if (!hit) return void 0;
51
- if (!hit.expireAt) return hit;
52
- if (hit.expireAt <= Math.max(now.value, Date.now())) return void 0;
53
- return hit;
54
- });
55
- }
56
- function useBadgeResolved(getKey) {
43
+ const toBadgeKeyList = (input) => {
44
+ if (!input) return [];
45
+ if (typeof input === "string") return [input];
46
+ return input.filter((key) => !!key);
47
+ };
48
+ function useBadgeHit(getKey) {
57
49
  const bridge = inject(CORE_BRIDGE_KEY, void 0);
58
50
  const now = useBadgeNow();
59
- const entry = computed(() => {
60
- const key = getKey();
61
- if (!key || !bridge) return void 0;
62
- const hit = bridge.badge.marks.value[key];
63
- if (!hit) return void 0;
64
- if (!hit.expireAt) return hit;
65
- if (hit.expireAt <= Math.max(now.value, Date.now())) return void 0;
66
- return hit;
67
- });
68
51
  return computed(() => {
69
- const hit = entry.value;
70
- if (!hit) return void 0;
71
- if (hit.kind === "count") {
72
- return { value: hit.value, max: hit.max, type: "danger" };
73
- }
74
- if (hit.kind === "custom") {
75
- return { value: hit.text, type: hit.type ?? "primary" };
52
+ if (!bridge) return void 0;
53
+ const marks = bridge.badge.marks.value;
54
+ const at = Math.max(now.value, Date.now());
55
+ for (const key of toBadgeKeyList(getKey())) {
56
+ const entry = marks[key];
57
+ if (!entry) continue;
58
+ if (entry.expireAt && entry.expireAt <= at) continue;
59
+ return { key, entry };
76
60
  }
77
- const preset = BADGE_BUILTIN_PRESET[hit.kind];
78
- return {
79
- value: preset.text,
80
- type: preset.type,
81
- icon: preset.icon,
82
- label: preset.text
83
- };
61
+ return void 0;
84
62
  });
85
63
  }
64
+ function badgeResolveDisplay(entry) {
65
+ if (!entry) return void 0;
66
+ if (entry.kind === "count") {
67
+ return { value: entry.value, max: entry.max, type: "danger" };
68
+ }
69
+ if (entry.kind === "custom") {
70
+ return { value: entry.text, type: entry.type ?? "primary" };
71
+ }
72
+ if (entry.kind === "anchor") {
73
+ return { value: "", type: "primary", hidden: true };
74
+ }
75
+ const preset = BADGE_BUILTIN_PRESET[entry.kind];
76
+ return {
77
+ value: preset.text,
78
+ type: preset.type,
79
+ icon: preset.icon,
80
+ label: preset.text
81
+ };
82
+ }
86
83
  export {
87
- useBadgeEntry,
88
- useBadgeResolved
84
+ badgeResolveDisplay,
85
+ useBadgeHit
89
86
  };
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./FormMain.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const FormMain = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-6ea6d3c8"]]);
4
+ const FormMain = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ba043bbe"]]);
5
5
  export {
6
6
  FormMain as default
7
7
  };
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./FormSearch.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const FormSearch = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-c1fe91f1"]]);
4
+ const FormSearch = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-e52f9711"]]);
5
5
  export {
6
6
  FormSearch as default
7
7
  };
@@ -23,7 +23,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
23
23
  })) : createCommentVNode("", true),
24
24
  createElementVNode("span", _hoisted_1, [
25
25
  createVNode(unref(BadgeMark), {
26
- badgeKey: __props.menu.path
26
+ badgeKey: [__props.menu.name, __props.menu.path]
27
27
  }, {
28
28
  default: withCtx(() => [
29
29
  createTextVNode(toDisplayString(__props.menu.title), 1)
@@ -55,7 +55,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
55
55
  }, 1024)) : createCommentVNode("", true),
56
56
  createElementVNode("span", null, [
57
57
  createVNode(unref(BadgeMark), {
58
- badgeKey: item.path
58
+ badgeKey: [item.name, item.path]
59
59
  }, {
60
60
  default: withCtx(() => [
61
61
  createTextVNode(toDisplayString(item.title), 1)
@@ -77,7 +77,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
77
77
  __props.groupMode && menu.children.length ? (openBlock(), createBlock(unref(ElMenuItemGroup), { key: 0 }, {
78
78
  title: withCtx(() => [
79
79
  createVNode(unref(BadgeMark), {
80
- badgeKey: menu.path
80
+ badgeKey: [menu.name, menu.path]
81
81
  }, {
82
82
  default: withCtx(() => [
83
83
  createTextVNode(toDisplayString(menu.title), 1)
@@ -108,7 +108,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
108
108
  }, 1024)) : createCommentVNode("", true),
109
109
  createElementVNode("span", null, [
110
110
  createVNode(unref(BadgeMark), {
111
- badgeKey: item.path
111
+ badgeKey: [item.name, item.path]
112
112
  }, {
113
113
  default: withCtx(() => [
114
114
  createTextVNode(toDisplayString(item.title), 1)
@@ -141,7 +141,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
141
141
  }, 1024)) : createCommentVNode("", true),
142
142
  createElementVNode("span", null, [
143
143
  createVNode(unref(BadgeMark), {
144
- badgeKey: menu.path
144
+ badgeKey: [menu.name, menu.path]
145
145
  }, {
146
146
  default: withCtx(() => [
147
147
  createTextVNode(toDisplayString(menu.title), 1)
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./ViewLayout.vue2.mjs";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.mjs";
4
- const ViewLayout = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-0507f728"]]);
4
+ const ViewLayout = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-e7dc3f12"]]);
5
5
  export {
6
6
  ViewLayout as default
7
7
  };
@@ -52,7 +52,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
52
52
  const { ctxRefine } = useContextDefaults({
53
53
  getProps: () => props,
54
54
  defaults: {
55
- refine: ({ parentInfo, props: rawProps }) => rawProps.refine ?? (parentInfo === SlotRegion.AppPage_Default || parentInfo === SlotRegion.TabsMain_Item ? true : void 0)
55
+ refine: ({ parentInfo, props: rawProps }) => rawProps.refine ?? (parentInfo === SlotRegion.AppPage_Default || parentInfo === SlotRegion.TabsMain_Item || parentInfo === SlotRegion.ModalConfirm_Body ? true : void 0)
56
56
  }
57
57
  });
58
58
  const { viewportHeightFinal, nearestScope } = useChannelViewportHeight(props);
@@ -0,0 +1,6 @@
1
+ const BADGE_HOST_ATTR = "data-dc-badge-host";
2
+ const BADGE_KEY_ATTR = "data-dc-badge-key";
3
+ export {
4
+ BADGE_HOST_ATTR,
5
+ BADGE_KEY_ATTR
6
+ };
@@ -171,6 +171,54 @@ const EP_STRUCTURAL_CSS = [
171
171
  ":root.dark .el-table {",
172
172
  " --el-table-fixed-left-column: inset 10px 0 10px -10px var(--dc-core-border-color, var(--el-border-color));",
173
173
  " --el-table-fixed-right-column: inset -10px 0 10px -10px var(--dc-core-border-color, var(--el-border-color));",
174
+ "}",
175
+ // ── 浮层描边:**接主题**,不是「补上缺失的边框」(r4jsl6 ① 的前提已实测更正)──
176
+ // 实测 EP 2.13.7:`.el-popper.is-light` / `.el-dropdown__popper.el-popper` / `.el-card`
177
+ // **本来就各带 1px 边框**(`--el-border-color-light`),暗色下 `#414243` 对 overlay
178
+ // `#1d1e1f` 也有 Δ36、看得见 —— 所以「浮层没有边界」这条不成立。
179
+ // 真正的缺口是**这些边框走 EP 固定灰、不随本仓主题**:弹窗 / 抽屉那条已改用
180
+ // `--dc-core-border-color`,浮层没跟上 ⇒ 换主题时两类浮层边框分家。此处只改 `border-color`
181
+ // ([MUST NOT] 写整条 `border`,那会连宽度 / 样式一起夺权),并**同步箭头**——
182
+ // 箭头的 `::before` 自带同色边框,只改容器会出现「框变色、箭头没变」的裂缝。
183
+ // 🔴 [MUST NOT] 把 `.el-popper.is-dark` 纳入:那是**深色气泡**(tooltip 默认档),
184
+ // 它的边框本就与自身深底同色,套上主题边框会给黑气泡镶一圈亮边。
185
+ // 🔴 [MUST NOT] 把 `.el-card` 纳入:卡片边框是常驻结构线、不是浮层边界,
186
+ // 改它等于把全站卡片加深一档 —— 那是独立的视觉决策,不该夹带进「浮层描边」。
187
+ ".el-popper.is-light,",
188
+ ".el-dropdown__popper.el-popper {",
189
+ " border-color: var(--dc-core-border-color, var(--el-border-color-light));",
190
+ "}",
191
+ ".el-popper.is-light > .el-popper__arrow::before,",
192
+ ".el-dropdown__popper.el-popper .el-popper__arrow::before {",
193
+ " border-color: var(--dc-core-border-color, var(--el-border-color-light));",
194
+ "}",
195
+ // ── 表格斑马纹加深(r4jsl6 ②)──
196
+ // EP 原值 `--el-fill-color-lighter`:亮 `#fafafa` 对面 `#ffffff` 通道差仅 **5/5/5**、
197
+ // 暗 `#1d1d1d` 对 `#141414` 仅 **9/9/9** —— 斑马纹的意义就是「长行易对齐」,Δ5 等于没做。
198
+ // 取「主题边框色按比例混进面色」而非 EP 的固定灰档:边框色**随主题自动反转**
199
+ // (亮色偏黑向 / 暗色偏白向),一份声明亮暗都成立,且换主题时跟着走
200
+ // (EP 的 `--el-fill-color*` 是固定灰,彩色主题下会显脏)。
201
+ // 40% 是实测取的:亮 Δ14/13/10、暗 Δ22/23/24 —— 暗色需要更大的差才读得出来,
202
+ // 这个比例恰好让两边观感相当。[MUST NOT] 再往上调:超过 50% 斑马纹会读成「选中行」。
203
+ ".el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell {",
204
+ " background: color-mix(in srgb, var(--dc-core-border-color, var(--el-border-color)) 40%, var(--el-bg-color));",
205
+ "}",
206
+ // ── 占位符对比(r4jsl6 ③)——**只修亮色**(工单的暗色数据已实测更正)──
207
+ // 实测:亮色 `#a8abb2` 对 `#fff` 仅 **2.30:1**,低于 WCAG AA 的 4.5:1;
208
+ // 而暗色 `#8d9095` 对面色 `#141414` 已有 **5.75:1**、对 overlay `#1d1e1f` 5.21:1,
209
+ // **本就达标** ⇒ 暗色一并加深只会让占位符抢戏。工单写的「亮暗均 2.3~2.6」是错的。
210
+ // 取值 = `color-mix(regular 60%, secondary)` → `#73767a`,对白底 **4.56:1**(刚过线),
211
+ // 与「已输入文字」`--el-text-color-regular` 的 6.11:1 仍拉得开,不会读成真值。
212
+ // 🔴 **[MUST NOT] 改 `--el-text-color-placeholder` 变量**:EP 的
213
+ // `--el-disabled-text-color: var(--el-text-color-placeholder)` ——改变量会把**禁用态**
214
+ // 一起加深,而 disabled 在 WCAG 里是**明确豁免**的,加深反而削弱「这是禁用」的语义。
215
+ // 故只打伪元素。禁用态的 EP 规则(`.el-input.is-disabled .el-input__inner::placeholder`)
216
+ // 选择器更具体,天然压过本条;`.el-date-editor` 那条同权,故显式 `:not(.is-disabled)`。
217
+ ":root:not(.dark) .el-input__inner::placeholder,",
218
+ ":root:not(.dark) .el-textarea__inner::placeholder,",
219
+ ":root:not(.dark) .el-date-editor:not(.is-disabled) .el-range-input::placeholder,",
220
+ ":root:not(.dark) .el-select__placeholder.is-transparent {",
221
+ " color: color-mix(in srgb, var(--el-text-color-regular) 60%, var(--el-text-color-secondary));",
174
222
  "}"
175
223
  ].join("\n");
176
224
  const EP_BRIDGE_CSS = [
package/es/index.mjs CHANGED
@@ -47,6 +47,7 @@ import { default as default43 } from "./components/app-layout/AppSidebar.vue.mjs
47
47
  import { default as default44 } from "./components/app-layout/AppTheme.vue.mjs";
48
48
  import { default as default45 } from "./components/misc/AutoRefresh.vue.mjs";
49
49
  import { default as default46 } from "./components/misc/AutoRefreshGroup.vue.mjs";
50
+ import { BADGE_HOST_ATTR, BADGE_KEY_ATTR } from "./config/badge-attr.mjs";
50
51
  import { BADGE_MASK_KINDS } from "./bridge/badge.mjs";
51
52
  import { default as default47 } from "./components/display/BadgeMark.vue.mjs";
52
53
  import { COLLAPSED_CLASS, swiftFormItemDivider, swiftFormItemGroup } from "./components/form/group.mjs";
@@ -150,6 +151,8 @@ export {
150
151
  default44 as AppTheme,
151
152
  default45 as AutoRefresh,
152
153
  default46 as AutoRefreshGroup,
154
+ BADGE_HOST_ATTR,
155
+ BADGE_KEY_ATTR,
153
156
  BADGE_MASK_KINDS,
154
157
  BODY_CONTENT_VIEWPORT_HEIGHT,
155
158
  BODY_CONTENT_VIEWPORT_INSET,