@koishi-ce/client 1.0.3 → 1.0.4

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 (40) hide show
  1. package/app/home/welcome.vue +12 -6
  2. package/app/index.ts +8 -2
  3. package/app/layout/header.vue +12 -4
  4. package/app/layout/layout.vue +4 -1
  5. package/app/layout/menu-item.vue +3 -1
  6. package/app/settings/settings.vue +6 -4
  7. package/app/settings/theme.vue +4 -1
  8. package/app/status/loading.vue +4 -1
  9. package/app/theme/activity/button.vue +4 -1
  10. package/app/theme/activity/index.vue +12 -4
  11. package/app/theme/activity/item.vue +18 -4
  12. package/app/theme/activity/separator.vue +44 -12
  13. package/app/theme/index.ts +5 -1
  14. package/app/theme/index.vue +3 -1
  15. package/app/theme/menu/menu-item.vue +10 -4
  16. package/app/theme/menu/menu.vue +9 -4
  17. package/client/components/chat/overlay.vue +30 -8
  18. package/client/components/common/k-hint.vue +3 -1
  19. package/client/components/dynamic.vue +2 -1
  20. package/client/components/icons/index.ts +7 -2
  21. package/client/components/index.ts +8 -2
  22. package/client/components/link.ts +5 -2
  23. package/client/components/perms.vue +22 -5
  24. package/client/components/slot.ts +19 -4
  25. package/client/context.ts +12 -4
  26. package/client/data.ts +57 -26
  27. package/client/index.ts +2 -1
  28. package/client/plugins/action.ts +46 -13
  29. package/client/plugins/loader.ts +67 -45
  30. package/client/plugins/router.ts +34 -11
  31. package/client/plugins/setting.ts +45 -12
  32. package/client/plugins/theme.ts +21 -6
  33. package/client/utils.ts +7 -2
  34. package/lib/bin.mjs +3 -3
  35. package/lib/{client-CaTn_gVG.mjs → client-C97iYPCr.mjs} +1 -1
  36. package/lib/index.mjs +1 -1
  37. package/lib/{src-DXaM1Kgh.mjs → src-BOakssV3.mjs} +2 -2
  38. package/package.json +3 -3
  39. package/src/bin.ts +10 -3
  40. package/src/index.ts +59 -15
@@ -45,12 +45,18 @@ const { t, setLocaleMessage } = useI18n({
45
45
 
46
46
  // 开发模式下 yml 文案改动即时热替换,无需整页刷新
47
47
  if (import.meta.hot) {
48
- import.meta.hot.accept("./welcome.zh-CN.yml", (module) => {
49
- setLocaleMessage("zh-CN", module.default);
50
- });
51
- import.meta.hot.accept("./welcome.en-US.yml", (module) => {
52
- setLocaleMessage("en-US", module.default);
53
- });
48
+ import.meta.hot.accept(
49
+ "./welcome.zh-CN.yml",
50
+ (module) => {
51
+ setLocaleMessage("zh-CN", module.default);
52
+ },
53
+ );
54
+ import.meta.hot.accept(
55
+ "./welcome.en-US.yml",
56
+ (module) => {
57
+ setLocaleMessage("en-US", module.default);
58
+ },
59
+ );
54
60
  }
55
61
  </script>
56
62
 
package/app/index.ts CHANGED
@@ -31,6 +31,12 @@ root.start();
31
31
 
32
32
  if (!global.static) {
33
33
  // global.static 为真表示纯静态构建(无后端),跳过连接
34
- const endpoint = new URL(global.endpoint, location.origin).toString();
35
- connect(root, () => new WebSocket(endpoint.replace(/^http/, "ws")));
34
+ const endpoint = new URL(
35
+ global.endpoint,
36
+ location.origin,
37
+ ).toString();
38
+ connect(
39
+ root,
40
+ () => new WebSocket(endpoint.replace(/^http/, "ws")),
41
+ );
36
42
  }
@@ -38,7 +38,10 @@
38
38
  </template>
39
39
 
40
40
  <script lang="ts" setup>
41
- import { type ActionContext, useMenu } from "@koishi-ce/client";
41
+ import {
42
+ type ActionContext,
43
+ useMenu,
44
+ } from "@koishi-ce/client";
42
45
  import { useRoute } from "vue-router";
43
46
 
44
47
  const props = defineProps<{
@@ -50,9 +53,14 @@ const props = defineProps<{
50
53
 
51
54
  // 溢出菜单按钮的点击触发器:打开 menuKey 对应的上下文菜单
52
55
  // (menuKey 为运行期字符串,这里断言为菜单键类型以复用字面量重载)
53
- const trigger = useMenu(props.menuKey as keyof ActionContext);
54
-
55
- defineEmits(["update:isLeftAsideOpen", "update:isRightAsideOpen"]);
56
+ const trigger = useMenu(
57
+ props.menuKey as keyof ActionContext,
58
+ );
59
+
60
+ defineEmits([
61
+ "update:isLeftAsideOpen",
62
+ "update:isRightAsideOpen",
63
+ ]);
56
64
 
57
65
  const route = useRoute();
58
66
  </script>
@@ -54,7 +54,10 @@
54
54
  </template>
55
55
 
56
56
  <script lang="ts" setup>
57
- import { type LegacyMenuItem, useContext } from "@koishi-ce/client";
57
+ import {
58
+ type LegacyMenuItem,
59
+ useContext,
60
+ } from "@koishi-ce/client";
58
61
  import { computed, ref, useSlots } from "vue";
59
62
  import { useRoute } from "vue-router";
60
63
  import LayoutHeader from "./header.vue";
@@ -54,7 +54,9 @@ const scope = computed(() =>
54
54
  function toValue<T>(getter: MaybeGetter<T>): T {
55
55
  if (typeof getter !== "function") return getter;
56
56
  // 收窄到 MaybeGetter 的函数分支(以作用域为参的 getter)
57
- return (getter as (current: typeof scope.value) => T)(scope.value);
57
+ return (getter as (current: typeof scope.value) => T)(
58
+ scope.value,
59
+ );
58
60
  }
59
61
 
60
62
  function trigger() {
@@ -56,10 +56,12 @@ interface Tree {
56
56
  }
57
57
 
58
58
  const data = computed(() =>
59
- Object.entries(ctx.internal.settings).map<Tree>(([id, [{ title }]]) => ({
60
- id,
61
- label: title,
62
- })),
59
+ Object.entries(ctx.internal.settings).map<Tree>(
60
+ ([id, [{ title }]]) => ({
61
+ id,
62
+ label: title,
63
+ }),
64
+ ),
63
65
  );
64
66
 
65
67
  function handleClick(tree: Tree) {
@@ -35,7 +35,10 @@
35
35
 
36
36
  <script setup lang="ts">
37
37
  import { useContext, useI18nText } from "@koishi-ce/client";
38
- import { type Schema, SchemaBase } from "@koishi-ce/components";
38
+ import {
39
+ type Schema,
40
+ SchemaBase,
41
+ } from "@koishi-ce/components";
39
42
  import { computed, type PropType } from "vue";
40
43
 
41
44
  defineProps({
@@ -22,6 +22,9 @@ const ctx = useContext();
22
22
 
23
23
  const progress = computed(() => {
24
24
  const states = Object.values(ctx.$loader.extensions);
25
- return states.filter((state) => state.done.value).length / states.length;
25
+ return (
26
+ states.filter((state) => state.done.value).length /
27
+ states.length
28
+ );
26
29
  });
27
30
  </script>
@@ -33,7 +33,10 @@ const isDragging = ref(false);
33
33
  function handleDragStart(event: DragEvent) {
34
34
  isDragging.value = true;
35
35
  // 约定的拖拽协议:以 "activity:" 前缀 + 活动 id 标识被拖动的活动项
36
- event.dataTransfer.setData("text/plain", `activity:${props.data.id}`);
36
+ event.dataTransfer.setData(
37
+ "text/plain",
38
+ `activity:${props.data.id}`,
39
+ );
37
40
  }
38
41
 
39
42
  function handleDragEnd(event: DragEvent) {
@@ -72,7 +72,9 @@ const groups = computed(() => {
72
72
  delete available[id];
73
73
  }
74
74
  }
75
- const list = Object.values(available).sort(([a], [b]) => a.order - b.order);
75
+ const list = Object.values(available).sort(
76
+ ([a], [b]) => a.order - b.order,
77
+ );
76
78
  // 放不下时:从头部取出溢出项折叠成一个组,top 位优先、同位再按 order 排,
77
79
  // 并以 "..." 图标作为该组的展示入口
78
80
  if (list.length * unit > total) {
@@ -86,11 +88,17 @@ const groups = computed(() => {
86
88
  return scale;
87
89
  })
88
90
  .flat();
89
- hidden.unshift({ icon: "activity:ellipsis" } as Activity);
91
+ hidden.unshift({
92
+ icon: "activity:ellipsis",
93
+ } as Activity);
90
94
  }
91
95
  // top 区按 order 逆序输出(order 大者靠上),bottom 区保持正序
92
- const top = list.filter(([data]) => data.position !== "bottom").reverse();
93
- const bottom = list.filter(([data]) => data.position === "bottom");
96
+ const top = list
97
+ .filter(([data]) => data.position !== "bottom")
98
+ .reverse();
99
+ const bottom = list.filter(
100
+ ([data]) => data.position === "bottom",
101
+ );
94
102
  return { top, bottom, hidden };
95
103
  });
96
104
 
@@ -38,7 +38,11 @@
38
38
  </template>
39
39
 
40
40
  <script lang="ts" setup>
41
- import { type Activity, useConfig, useMenu } from "@koishi-ce/client";
41
+ import {
42
+ type Activity,
43
+ useConfig,
44
+ useMenu,
45
+ } from "@koishi-ce/client";
42
46
  import type { Placement } from "element-plus";
43
47
  import { computed, ref, watch } from "vue";
44
48
  import { useRoute } from "vue-router";
@@ -84,13 +88,23 @@ const config = useConfig();
84
88
 
85
89
  // 原型链保留键:这类键在普通对象上会触发原型链存取器,禁止作为配置键读写
86
90
  // (id 来自拖拽事件的 dataTransfer 文本,属外部输入)
87
- const UNSAFE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
91
+ const UNSAFE_KEYS = new Set([
92
+ "__proto__",
93
+ "constructor",
94
+ "prototype",
95
+ ]);
88
96
 
89
97
  /** 取某活动的覆盖配置(不存在则创建);保留键返回一次性空对象,防原型污染。
90
98
  * 守卫须用显式字符串比较(Set.has 形式 CodeQL 无法识别为阻断) */
91
- function ensureOverride(id: string): Record<string, unknown> {
99
+ function ensureOverride(
100
+ id: string,
101
+ ): Record<string, unknown> {
92
102
  const activities = (config.value.activities ??= {});
93
- if (id === "__proto__" || id === "constructor" || id === "prototype") {
103
+ if (
104
+ id === "__proto__" ||
105
+ id === "constructor" ||
106
+ id === "prototype"
107
+ ) {
94
108
  return {};
95
109
  }
96
110
  return (activities[id] ??= {});
@@ -18,7 +18,11 @@
18
18
  </template>
19
19
 
20
20
  <script lang="ts" setup>
21
- import { type Activity, useConfig, useContext } from "@koishi-ce/client";
21
+ import {
22
+ type Activity,
23
+ useConfig,
24
+ useContext,
25
+ } from "@koishi-ce/client";
22
26
  import { type ComputedRef, inject, ref } from "vue";
23
27
 
24
28
  type Position = "top" | "bottom";
@@ -28,7 +32,9 @@ const props = defineProps<{
28
32
  position: Position;
29
33
  }>();
30
34
 
31
- const groups = inject("groups") as ComputedRef<Record<Position, Activity[][]>>;
35
+ const groups = inject("groups") as ComputedRef<
36
+ Record<Position, Activity[][]>
37
+ >;
32
38
 
33
39
  const hasDragOver = ref(false);
34
40
 
@@ -45,13 +51,23 @@ const ctx = useContext();
45
51
 
46
52
  // 原型链保留键:这类键在普通对象上会触发原型链存取器,禁止作为配置键读写
47
53
  // (id 来自拖拽事件的 dataTransfer 文本,属外部输入)
48
- const UNSAFE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
54
+ const UNSAFE_KEYS = new Set([
55
+ "__proto__",
56
+ "constructor",
57
+ "prototype",
58
+ ]);
49
59
 
50
60
  /** 取某活动的覆盖配置(不存在则创建);保留键返回一次性空对象,防原型污染。
51
61
  * 守卫须用显式字符串比较(Set.has 形式 CodeQL 无法识别为阻断) */
52
- function ensureOverride(id: string): Record<string, unknown> {
62
+ function ensureOverride(
63
+ id: string,
64
+ ): Record<string, unknown> {
53
65
  const activities = (config.value.activities ??= {});
54
- if (id === "__proto__" || id === "constructor" || id === "prototype") {
66
+ if (
67
+ id === "__proto__" ||
68
+ id === "constructor" ||
69
+ id === "prototype"
70
+ ) {
55
71
  return {};
56
72
  }
57
73
  return (activities[id] ??= {});
@@ -63,7 +79,9 @@ function handleDrop(event: DragEvent) {
63
79
  // 只响应活动栏自身的拖拽协议
64
80
  if (!text.startsWith("activity:")) return;
65
81
  const id = text.slice(9);
66
- const list = groups.value[props.position].map(([item]) => item);
82
+ const list = groups.value[props.position].map(
83
+ ([item]) => item,
84
+ );
67
85
  const oldIndex = list.findIndex((item) => item.id === id);
68
86
  // 落点即原位(含紧邻原位的前一格)时无需移动
69
87
  if (
@@ -99,10 +117,12 @@ function handleDrop(event: DragEvent) {
99
117
  // 介于两锚点之间的项按线性插值重算 order;
100
118
  // 只有一侧锚点时按步长 100 单向递增 / 递减;两侧都没有则恢复默认
101
119
  const anchorL = list.findLastIndex(
102
- (item, i) => i < index && item.order === item.options.order,
120
+ (item, i) =>
121
+ i < index && item.order === item.options.order,
103
122
  );
104
123
  const anchorR = list.findIndex(
105
- (item, i) => i > index && item.order === item.options.order,
124
+ (item, i) =>
125
+ i > index && item.order === item.options.order,
106
126
  );
107
127
  if (anchorL === -1) {
108
128
  if (anchorR === -1) {
@@ -117,24 +137,36 @@ function handleDrop(event: DragEvent) {
117
137
  } else {
118
138
  if (anchorR === -1) {
119
139
  let order = list[anchorL].options.order;
120
- for (let index = anchorL + 1; index < list.length; index++) {
140
+ for (
141
+ let index = anchorL + 1;
142
+ index < list.length;
143
+ index++
144
+ ) {
121
145
  const override = ensureOverride(list[index].id);
122
146
  override.order = order -= 100;
123
147
  }
124
148
  } else {
125
149
  let orderL = list[anchorL].options.order;
126
150
  let orderR = list[anchorR].options.order;
127
- for (let index = anchorL + 1; index < anchorR; index++) {
151
+ for (
152
+ let index = anchorL + 1;
153
+ index < anchorR;
154
+ index++
155
+ ) {
128
156
  const override = ensureOverride(list[index].id);
129
157
  override.order =
130
158
  orderL +
131
- ((orderR - orderL) * (index - anchorL)) / (anchorR - anchorL);
159
+ ((orderR - orderL) * (index - anchorL)) /
160
+ (anchorR - anchorL);
132
161
  }
133
162
  }
134
163
  }
135
164
 
136
165
  // 覆盖配置为空对象时删除该键,避免残留无意义的配置项
137
- if (!Object.keys(override).length && !UNSAFE_KEYS.has(id)) {
166
+ if (
167
+ !Object.keys(override).length &&
168
+ !UNSAFE_KEYS.has(id)
169
+ ) {
138
170
  delete config.value.activities[id];
139
171
  }
140
172
  }
@@ -8,7 +8,11 @@
8
8
  * - 注册活动栏右键菜单 "theme.activity" 及其动作(重置活动栏自定义配置)。
9
9
  */
10
10
 
11
- import { type Context, router, useConfig } from "@koishi-ce/client";
11
+ import {
12
+ type Context,
13
+ router,
14
+ useConfig,
15
+ } from "@koishi-ce/client";
12
16
  import App from "./index.vue";
13
17
 
14
18
  export default function (ctx: Context) {
@@ -33,6 +33,8 @@ const route = useRoute();
33
33
  // 否则要求 meta.activity.fields 中每个 store 字段都有数据
34
34
  const loaded = computed(() => {
35
35
  if (!route.meta.activity?.fields) return true;
36
- return route.meta.activity.fields.every((key) => store[key]);
36
+ return route.meta.activity.fields.every(
37
+ (key) => store[key],
38
+ );
37
39
  });
38
40
  </script>
@@ -21,7 +21,11 @@
21
21
  </template>
22
22
 
23
23
  <script lang="ts" setup>
24
- import { type MaybeGetter, type MenuItem, useContext } from "@koishi-ce/client";
24
+ import {
25
+ type MaybeGetter,
26
+ type MenuItem,
27
+ useContext,
28
+ } from "@koishi-ce/client";
25
29
  import { computed } from "vue";
26
30
 
27
31
  const props = defineProps<MenuItem & { prefix: string }>();
@@ -55,8 +59,10 @@ const icon = computed(() => toValue(props.icon));
55
59
  function toValue<T>(getter: MaybeGetter<T>): T {
56
60
  if (typeof getter !== "function") return getter;
57
61
  // 收窄到 MaybeGetter 的函数分支(以作用域为参的 getter)
58
- return (getter as (current: ReturnType<typeof ctx.$action.createScope>) => T)(
59
- ctx.$action.createScope(),
60
- );
62
+ return (
63
+ getter as (
64
+ current: ReturnType<typeof ctx.$action.createScope>,
65
+ ) => T
66
+ )(ctx.$action.createScope());
61
67
  }
62
68
  </script>
@@ -17,7 +17,10 @@
17
17
  </template>
18
18
 
19
19
  <script lang="ts" setup>
20
- import { type ActiveMenu, useContext } from "@koishi-ce/client";
20
+ import {
21
+ type ActiveMenu,
22
+ useContext,
23
+ } from "@koishi-ce/client";
21
24
  import { ref } from "vue";
22
25
  import MenuItem from "./menu-item.vue";
23
26
 
@@ -31,9 +34,11 @@ const el = ref<HTMLElement>();
31
34
  // 结合菜单自身渲染后的实际宽高计算定位;尚未挂载时先隐藏避免闪烁
32
35
  const getStyle = () => {
33
36
  if (!el.value) return { visibility: "hidden" };
34
- const { height, width } = el.value.getBoundingClientRect();
35
- const style: Partial<Record<"top" | "right" | "bottom" | "left", string>> =
36
- {};
37
+ const { height, width } =
38
+ el.value.getBoundingClientRect();
39
+ const style: Partial<
40
+ Record<"top" | "right" | "bottom" | "left", string>
41
+ > = {};
37
42
  if (props.relative.right + width > window.innerWidth) {
38
43
  style.right = `${window.innerWidth - props.relative.left}px`;
39
44
  } else {
@@ -42,7 +42,13 @@
42
42
  </template>
43
43
 
44
44
  <script lang="ts" setup>
45
- import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue";
45
+ import {
46
+ computed,
47
+ onBeforeUnmount,
48
+ onMounted,
49
+ ref,
50
+ watch,
51
+ } from "vue";
46
52
  import { shared } from "./utils";
47
53
 
48
54
  // 用户手动调整的缩放与旋转量(复原即回到 1 / 0)
@@ -58,7 +64,9 @@ const transform = computed(() => {
58
64
  const siblings = computed(() => {
59
65
  if (!shared.overlayImage) return;
60
66
  const elements = Array.from(
61
- document.querySelectorAll<HTMLImageElement>(".chat-image"),
67
+ document.querySelectorAll<HTMLImageElement>(
68
+ ".chat-image",
69
+ ),
62
70
  );
63
71
  const index = elements.indexOf(shared.overlayImage);
64
72
  return {
@@ -69,10 +77,15 @@ const siblings = computed(() => {
69
77
 
70
78
  // 初始(适配屏幕)缩放比:按视口剩余空间把图片等比缩小,不放大
71
79
  const defaultScale = computed(() => {
72
- const { naturalHeight, naturalWidth } = shared.overlayImage;
80
+ const { naturalHeight, naturalWidth } =
81
+ shared.overlayImage;
73
82
  const maxHeight = innerHeight - paddingVertical * 2;
74
83
  const maxWidth = innerWidth - paddingHorizontal * 2;
75
- return Math.min(1, maxHeight / naturalHeight, maxWidth / naturalWidth);
84
+ return Math.min(
85
+ 1,
86
+ maxHeight / naturalHeight,
87
+ maxWidth / naturalWidth,
88
+ );
76
89
  });
77
90
 
78
91
  // 切换/关闭查看器时重置手动缩放与旋转;
@@ -96,7 +109,10 @@ function setImage(el: HTMLImageElement) {
96
109
  }
97
110
 
98
111
  /** 把大图元素摆到原图片所在的位置与尺寸(关闭时的"飞回"动画终点) */
99
- function moveToOrigin(el: HTMLImageElement, origin = shared.overlayImage) {
112
+ function moveToOrigin(
113
+ el: HTMLImageElement,
114
+ origin = shared.overlayImage,
115
+ ) {
100
116
  const { height, width } = origin;
101
117
  const { left, top } = origin.getBoundingClientRect();
102
118
  el.style.width = `${width}px`;
@@ -112,7 +128,8 @@ const paddingHorizontal = 0;
112
128
 
113
129
  /** 把图片按适配缩放比居中摆放到视口中央 */
114
130
  function moveToCenter(el: HTMLImageElement) {
115
- const { naturalHeight, naturalWidth } = shared.overlayImage;
131
+ const { naturalHeight, naturalWidth } =
132
+ shared.overlayImage;
116
133
  const scale = defaultScale.value;
117
134
  const width = naturalWidth * scale;
118
135
  const height = naturalHeight * scale;
@@ -136,13 +153,18 @@ function onKeyDown(ev: KeyboardEvent) {
136
153
  ev.preventDefault();
137
154
  if (ev.key === "ArrowUp" || ev.key === "ArrowLeft") {
138
155
  setImage(siblings.value.prev);
139
- } else if (ev.key === "ArrowDown" || ev.key === "ArrowRight") {
156
+ } else if (
157
+ ev.key === "ArrowDown" ||
158
+ ev.key === "ArrowRight"
159
+ ) {
140
160
  setImage(siblings.value.next);
141
161
  } else if (ev.key === "Escape") {
142
162
  setImage(null);
143
163
  } else if (ev.key === "Enter") {
144
164
  // 关闭并把页面滚动到原图所在位置,便于继续浏览消息
145
- shared.overlayImage.offsetParent.scrollIntoView({ behavior: "smooth" });
165
+ shared.overlayImage.offsetParent.scrollIntoView({
166
+ behavior: "smooth",
167
+ });
146
168
  setImage(null);
147
169
  }
148
170
  }
@@ -32,7 +32,9 @@ const props = defineProps({
32
32
  const emit = defineEmits(["update:modelValue"]);
33
33
 
34
34
  // modelValue 被显式传入时才呈现手型光标并响应点击(开关语义)
35
- const pointer = computed(() => props.modelValue !== undefined);
35
+ const pointer = computed(
36
+ () => props.modelValue !== undefined,
37
+ );
36
38
 
37
39
  function onClick() {
38
40
  if (!pointer.value) return;
@@ -58,7 +58,8 @@ defineEmits(["update:modelValue"]);
58
58
  // 按本地 schema 标注的名称,从服务端下发的 schema 仓库中取出完整定义;
59
59
  // 元信息做一层合并,保留本地的 meta 覆盖权
60
60
  const inner = computed(() => {
61
- const hydrated = store.schema?.[props.schema?.meta.extra?.name];
61
+ const hydrated =
62
+ store.schema?.[props.schema?.meta.extra?.name];
62
63
  return hydrated && new Schema(hydrated);
63
64
  });
64
65
  </script>
@@ -116,7 +116,10 @@ register("undo", Undo);
116
116
  register("user", User);
117
117
 
118
118
  /** 向注册表登记一个图标(markRaw 避免组件被响应式代理) */
119
- export function register(name: string, component: Component) {
119
+ export function register(
120
+ name: string,
121
+ component: Component,
122
+ ) {
120
123
  registry[name] = markRaw(component);
121
124
  }
122
125
 
@@ -129,7 +132,9 @@ export function install(app: App) {
129
132
  name: String,
130
133
  },
131
134
  render(props: { name?: string }) {
132
- const component = props.name ? registry[props.name] : undefined;
135
+ const component = props.name
136
+ ? registry[props.name]
137
+ : undefined;
133
138
  return component && h(component);
134
139
  },
135
140
  }),
@@ -15,10 +15,16 @@
15
15
  // 无法解析(无 paths),故直接相对导入工作区内该包的浏览器端入口,
16
16
  // 与构建器 collectWorkspaceAliases 的映射目标一致
17
17
 
18
- import Element, { ElLoading, ElMessage, ElMessageBox } from "element-plus";
18
+ import Element, {
19
+ ElLoading,
20
+ ElMessage,
21
+ ElMessageBox,
22
+ } from "element-plus";
19
23
  import Markdown from "marked-vue";
20
24
  import type { App } from "vue";
21
- import components, { SchemaBase } from "../../../components/client/index.ts";
25
+ import components, {
26
+ SchemaBase,
27
+ } from "../../../components/client/index.ts";
22
28
 
23
29
  import { store } from "../data";
24
30
  import ChatImage from "./chat/image.vue";
@@ -21,7 +21,9 @@ const KActivityLink = defineComponent({
21
21
  setup(props, { slots }) {
22
22
  const ctx = useContext();
23
23
  return () => {
24
- const activity = props.id ? ctx.$router.pages[props.id] : undefined;
24
+ const activity = props.id
25
+ ? ctx.$router.pages[props.id]
26
+ : undefined;
25
27
  return h(
26
28
  RouterLink,
27
29
  {
@@ -30,7 +32,8 @@ const KActivityLink = defineComponent({
30
32
  activity?.path.replace(/:.+/, "")) as string,
31
33
  },
32
34
  {
33
- default: () => slots["default"]?.() ?? activity?.name,
35
+ default: () =>
36
+ slots["default"]?.() ?? activity?.name,
34
37
  },
35
38
  );
36
39
  };
@@ -32,7 +32,10 @@
32
32
  // schemastery-vue 链接(它是 components 的依赖,Bun 隔离布局下不跨包可见)
33
33
 
34
34
  import { store } from "@koishi-ce/client";
35
- import { type Schema, SchemaBase } from "@koishi-ce/components";
35
+ import {
36
+ type Schema,
37
+ SchemaBase,
38
+ } from "@koishi-ce/components";
36
39
  import type { CascaderOption } from "element-plus";
37
40
  import { computed, type PropType } from "vue";
38
41
 
@@ -53,15 +56,29 @@ const config = SchemaBase.useModel();
53
56
  * 逐段查找/创建级联节点;中间段(还有下级时)标记为 disabled,
54
57
  * 因为 el-cascader 的父节点勾选会影响子级,而中间段并非真实权限。
55
58
  */
56
- function addNode(nodes: CascaderOption[], path: string[], prefix = "") {
59
+ function addNode(
60
+ nodes: CascaderOption[],
61
+ path: string[],
62
+ prefix = "",
63
+ ) {
57
64
  const name = path.shift();
58
- let node = nodes.find((node) => node.value === prefix + name);
65
+ let node = nodes.find(
66
+ (node) => node.value === prefix + name,
67
+ );
59
68
  if (!node) {
60
- node = { value: prefix + name, label: name, disabled: !!path.length };
69
+ node = {
70
+ value: prefix + name,
71
+ label: name,
72
+ disabled: !!path.length,
73
+ };
61
74
  nodes.push(node);
62
75
  }
63
76
  if (!path.length) return;
64
- addNode((node.children ||= []), path, `${prefix + name}:`);
77
+ addNode(
78
+ (node.children ||= []),
79
+ path,
80
+ `${prefix + name}:`,
81
+ );
65
82
  }
66
83
 
67
84
  // 由全部权限名构建级联选项树