@koishi-ce/client 1.0.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 (121) hide show
  1. package/app/assets/logo.png +0 -0
  2. package/app/home/home.vue +51 -0
  3. package/app/home/index.ts +18 -0
  4. package/app/home/welcome.en-US.yml +9 -0
  5. package/app/home/welcome.vue +111 -0
  6. package/app/home/welcome.zh-CN.yml +9 -0
  7. package/app/index.html +13 -0
  8. package/app/index.scss +64 -0
  9. package/app/index.ts +32 -0
  10. package/app/layout/header.vue +187 -0
  11. package/app/layout/index.ts +15 -0
  12. package/app/layout/layout.vue +194 -0
  13. package/app/layout/menu-item.vue +60 -0
  14. package/app/settings/index.ts +39 -0
  15. package/app/settings/settings.vue +82 -0
  16. package/app/settings/theme.vue +123 -0
  17. package/app/shims.d.ts +1 -0
  18. package/app/status/index.ts +21 -0
  19. package/app/status/loading.vue +23 -0
  20. package/app/status/status.vue +56 -0
  21. package/app/styles/element.scss +217 -0
  22. package/app/styles/hc.scss +35 -0
  23. package/app/styles/index.scss +140 -0
  24. package/app/styles/index.ts +30 -0
  25. package/app/styles/layout.scss +92 -0
  26. package/app/theme/activity/button.vue +97 -0
  27. package/app/theme/activity/index.vue +119 -0
  28. package/app/theme/activity/item.vue +185 -0
  29. package/app/theme/activity/separator.vue +163 -0
  30. package/app/theme/activity/utils.ts +27 -0
  31. package/app/theme/blank.vue +24 -0
  32. package/app/theme/index.ts +37 -0
  33. package/app/theme/index.vue +34 -0
  34. package/app/theme/menu/index.vue +26 -0
  35. package/app/theme/menu/menu-item.vue +58 -0
  36. package/app/theme/menu/menu.vue +45 -0
  37. package/app/theme/status.vue +45 -0
  38. package/app/tsconfig.json +15 -0
  39. package/client/components/chat/image.vue +20 -0
  40. package/client/components/chat/overlay.vue +231 -0
  41. package/client/components/chat/utils.ts +6 -0
  42. package/client/components/common/index.ts +11 -0
  43. package/client/components/common/k-button.vue +127 -0
  44. package/client/components/common/k-hint.vue +62 -0
  45. package/client/components/common/k-tab.vue +50 -0
  46. package/client/components/dynamic.vue +61 -0
  47. package/client/components/icons/activity/default.vue +6 -0
  48. package/client/components/icons/activity/ellipsis.vue +6 -0
  49. package/client/components/icons/activity/home.vue +13 -0
  50. package/client/components/icons/activity/moon.vue +6 -0
  51. package/client/components/icons/activity/settings.vue +6 -0
  52. package/client/components/icons/activity/sun.vue +6 -0
  53. package/client/components/icons/index.ts +133 -0
  54. package/client/components/icons/style.scss +3 -0
  55. package/client/components/icons/svg/arrow-left.vue +6 -0
  56. package/client/components/icons/svg/arrow-right.vue +6 -0
  57. package/client/components/icons/svg/box-open.vue +6 -0
  58. package/client/components/icons/svg/check-full.vue +6 -0
  59. package/client/components/icons/svg/chevron-down.vue +6 -0
  60. package/client/components/icons/svg/chevron-left.vue +6 -0
  61. package/client/components/icons/svg/chevron-right.vue +6 -0
  62. package/client/components/icons/svg/chevron-up.vue +6 -0
  63. package/client/components/icons/svg/clipboard-list.vue +6 -0
  64. package/client/components/icons/svg/edit.vue +6 -0
  65. package/client/components/icons/svg/exclamation-full.vue +6 -0
  66. package/client/components/icons/svg/expand.vue +6 -0
  67. package/client/components/icons/svg/file-archive.vue +6 -0
  68. package/client/components/icons/svg/filter.vue +6 -0
  69. package/client/components/icons/svg/github.vue +6 -0
  70. package/client/components/icons/svg/gitlab.vue +6 -0
  71. package/client/components/icons/svg/info-full.vue +6 -0
  72. package/client/components/icons/svg/koishi.vue +6 -0
  73. package/client/components/icons/svg/link.vue +6 -0
  74. package/client/components/icons/svg/paper-plane.vue +6 -0
  75. package/client/components/icons/svg/question-empty.vue +6 -0
  76. package/client/components/icons/svg/redo.vue +6 -0
  77. package/client/components/icons/svg/search-minus.vue +6 -0
  78. package/client/components/icons/svg/search-plus.vue +6 -0
  79. package/client/components/icons/svg/search.vue +6 -0
  80. package/client/components/icons/svg/star-empty.vue +6 -0
  81. package/client/components/icons/svg/star-full.vue +6 -0
  82. package/client/components/icons/svg/start.vue +6 -0
  83. package/client/components/icons/svg/tag.vue +6 -0
  84. package/client/components/icons/svg/times-full.vue +6 -0
  85. package/client/components/icons/svg/tools.vue +6 -0
  86. package/client/components/icons/svg/undo.vue +6 -0
  87. package/client/components/icons/svg/user.vue +6 -0
  88. package/client/components/index.ts +75 -0
  89. package/client/components/layout/card.vue +69 -0
  90. package/client/components/layout/content.vue +37 -0
  91. package/client/components/layout/empty.vue +41 -0
  92. package/client/components/layout/index.ts +15 -0
  93. package/client/components/layout/tab-group.vue +45 -0
  94. package/client/components/layout/tab-item.vue +35 -0
  95. package/client/components/link.ts +39 -0
  96. package/client/components/perms.vue +73 -0
  97. package/client/components/slot.ts +95 -0
  98. package/client/context.ts +143 -0
  99. package/client/data.ts +178 -0
  100. package/client/index.ts +76 -0
  101. package/client/plugins/action.ts +251 -0
  102. package/client/plugins/i18n.ts +43 -0
  103. package/client/plugins/loader.ts +154 -0
  104. package/client/plugins/router.ts +278 -0
  105. package/client/plugins/setting.ts +217 -0
  106. package/client/plugins/theme.ts +134 -0
  107. package/client/shims.d.ts +55 -0
  108. package/client/tsconfig.json +15 -0
  109. package/client/utils.ts +36 -0
  110. package/global.d.ts +24 -0
  111. package/lib/bin.d.ts +1 -0
  112. package/lib/bin.mjs +112 -0
  113. package/lib/client-CaTn_gVG.mjs +125 -0
  114. package/lib/index.d.ts +20 -0
  115. package/lib/index.mjs +2 -0
  116. package/lib/src-Bxzzi1Rx.mjs +160 -0
  117. package/lib/yaml-UzQbvquH.mjs +23 -0
  118. package/package.json +66 -0
  119. package/src/bin.ts +61 -0
  120. package/src/index.ts +280 -0
  121. package/src/yaml.ts +22 -0
@@ -0,0 +1,217 @@
1
+ :root {
2
+ --el-text-color-regular: var(--fg1);
3
+ --el-text-color-primary: var(--fg2);
4
+ --el-input-text-color: var(--fg1);
5
+ --el-border-color: var(--k-color-border);
6
+ --el-border-color-light: var(--k-color-border-light);
7
+ --el-border-color-lighter: var(--k-color-divider);
8
+ --el-border-color-extra-light: var(--k-color-divider-light);
9
+ --el-border-color-hover: var(--active);
10
+ --el-color-primary: var(--k-color-primary);
11
+ --el-color-success: var(--k-color-success);
12
+ --el-color-warning: var(--k-color-warning);
13
+ --el-color-danger: var(--k-color-danger);
14
+ --el-color-primary-light-9: var(--k-hover-bg);
15
+ --el-color-white: var(--bg0);
16
+ --el-color-black: var(--fg1);
17
+ --el-bg-color: var(--bg0);
18
+ --el-bg-color-overlay: var(--bg0);
19
+ --el-fill-color-blank: transparent;
20
+ --el-disabled-bg-color: var(--card-bg);
21
+ --el-fill-color: var(--card-bg);
22
+ --el-fill-color-light: var(--k-hover-bg);
23
+ }
24
+
25
+ .el-input-number, .el-popper {
26
+ --el-fill-color-light: transparent;
27
+ }
28
+
29
+ .el-input-number__decrease:hover, .el-input-number__increase:hover {
30
+ background-color: var(--bg1);
31
+ }
32
+
33
+ .el-dropdown-menu {
34
+ background-color: var(--el-color-white);
35
+ }
36
+
37
+ .el-dropdown__popper.el-popper[role=tooltip] {
38
+ background-color: var(--el-color-white);
39
+ }
40
+
41
+ .el-dropdown-menu__item.is-disabled {
42
+ pointer-events: none;
43
+ }
44
+
45
+ .el-dropdown-menu__item--divided {
46
+ &:first-child, &:last-child {
47
+ display: none;
48
+ }
49
+ }
50
+
51
+ .el-input__wrapper,
52
+ .el-input-number__decrease,
53
+ .el-input-number__increase,
54
+ .el-checkbox__label {
55
+ transition: var(--color-transition);
56
+ }
57
+
58
+ .el-input__prefix-inner, .el-input__suffix-inner {
59
+ align-items: center;
60
+ }
61
+
62
+ .el-loading-mask {
63
+ background-color: var(--loading-mask-bg);
64
+ transition: 0.3s ease;
65
+ }
66
+
67
+ .el-radio {
68
+ height: 1.2rem;
69
+ }
70
+
71
+ .el-radio__label {
72
+ --el-color-primary: var(--active);
73
+ padding-top: 1px;
74
+ }
75
+
76
+ .el-scrollbar__bar {
77
+ z-index: 500;
78
+ }
79
+
80
+ html .el-switch {
81
+ --el-switch-on-color: var(--k-fill-normal);
82
+ }
83
+
84
+ .el-button {
85
+ --el-button-hover-bg-color: var(--k-button-hover-bg);
86
+ --el-button-hover-border-color: var(--k-color-active);
87
+ transition: var(--color-transition);
88
+ }
89
+
90
+ .el-button--primary {
91
+ --el-button-hover-text-color: var(--k-color-active);
92
+ }
93
+
94
+ .el-switch__core .el-switch__action,
95
+ .el-slider__button {
96
+ --el-color-white: var(--bg2);
97
+ }
98
+
99
+ html.dark .el-popper.is-dark {
100
+ color: var(--fg1);
101
+ background-color: var(--bg1);
102
+ border: 1px solid var(--k-color-border);
103
+ box-shadow: var(--k-card-shadow);
104
+ transition: var(--color-transition);
105
+
106
+ .el-popper__arrow::before {
107
+ border: 1px solid var(--k-color-border);
108
+ background: var(--bg1);
109
+ transition: var(--color-transition);
110
+ }
111
+ }
112
+
113
+ .right-adjacent {
114
+ &.el-button, &.el-select .el-input__wrapper {
115
+ border-top-right-radius: 0;
116
+ border-bottom-right-radius: 0;
117
+ }
118
+
119
+ &:hover, &:focus {
120
+ + .left-adjacent::before {
121
+ content: '';
122
+ position: absolute;
123
+ top: 0;
124
+ bottom: 0;
125
+ left: 0;
126
+ border-left: 1px solid #c6e2ff;
127
+ z-index: 1;
128
+ }
129
+ }
130
+ }
131
+
132
+ .left-adjacent {
133
+ margin-left: -1px;
134
+
135
+ &.el-button, &.el-select .el-input__wrapper {
136
+ border-top-left-radius: 0;
137
+ border-bottom-left-radius: 0;
138
+ }
139
+ }
140
+
141
+ .el-overlay-dialog {
142
+ display: flex;
143
+ flex-direction: column;
144
+ justify-content: center;
145
+ align-items: center;
146
+
147
+ .el-dialog {
148
+ margin: 0;
149
+ min-width: 480px;
150
+ }
151
+
152
+ @media screen and (max-width: 768px) {
153
+ justify-content: flex-end;
154
+
155
+ .el-dialog {
156
+ width: 100%;
157
+ min-width: unset;
158
+ }
159
+ }
160
+ }
161
+
162
+ .el-table__body-wrapper,
163
+ .el-table__footer-wrapper,
164
+ .el-table__header-wrapper {
165
+ --el-table-tr-bg-color: var(--el-fill-color-blank);
166
+ --el-table-header-bg-color: var(--el-fill-color-blank);
167
+ --el-table-row-hover-bg-color: var(--bg2);
168
+ tr {
169
+ td,
170
+ th {
171
+ &.hover-row {
172
+ background-color: var(--el-table-row-hover-bg-color);
173
+ }
174
+ &.el-table-fixed-column--left,
175
+ &.el-table-fixed-column--right {
176
+ background-color: var(--el-table-tr-bg-color);
177
+ }
178
+ &.el-table-fixed-column--left:is(th),
179
+ &.el-table-fixed-column--right:is(th) {
180
+ background-color: var(--el-table-header-bg-color);
181
+ }
182
+ &.is-first-column,
183
+ &.is-last-column {
184
+ &.el-table-fixed-column--left {
185
+ &::before {
186
+ box-shadow: inset 10px 0 10px -10px var(--bg0);
187
+ }
188
+ }
189
+ &.el-table-fixed-column--right {
190
+ &::before {
191
+ box-shadow: inset -10px 0 10px -10px var(--bg0);
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+ }
198
+
199
+ .flex, .grid {
200
+ > .el-button + .el-button {
201
+ margin-left: 0;
202
+ }
203
+ }
204
+
205
+ .el-cascader-panel {
206
+ .el-checkbox.is-disabled {
207
+ visibility: hidden;
208
+ }
209
+ }
210
+
211
+ .el-select.frameless {
212
+ .el-input .el-input__wrapper {
213
+ --el-input-height: 1rem;
214
+ box-shadow: none !important;
215
+ padding: 0 !important;
216
+ }
217
+ }
@@ -0,0 +1,35 @@
1
+ :root, .theme-root.light {
2
+ &[theme=hc-light] {
3
+ --bg0: white;
4
+ --bg1: white;
5
+ --bg2: white;
6
+ --bg3: white;
7
+
8
+ --fg0: black;
9
+ --fg1: black;
10
+ --fg2: black;
11
+ --fg3: black;
12
+
13
+ --k-card-border: black;
14
+ --k-color-border: black;
15
+ --k-color-divider: black;
16
+ }
17
+ }
18
+
19
+ :root, .theme-root.dark {
20
+ &[theme=hc-dark] {
21
+ --bg0: black;
22
+ --bg1: black;
23
+ --bg2: black;
24
+ --bg3: black;
25
+
26
+ --fg0: white;
27
+ --fg1: white;
28
+ --fg2: white;
29
+ --fg3: white;
30
+
31
+ --k-card-border: white;
32
+ --k-color-border: white;
33
+ --k-color-divider: white;
34
+ }
35
+ }
@@ -0,0 +1,140 @@
1
+ @use 'sass:color';
2
+ @use './layout.scss';
3
+ @use './element.scss';
4
+ @use './hc.scss';
5
+
6
+ $black: #000000;
7
+ $white: #ffffff;
8
+
9
+ :root, .theme-root.light {
10
+ --bg0: #ffffff;
11
+ --bg1: #f9f9fa;
12
+ --bg2: #f0f0f2;
13
+ --bg3: #e3e3e5;
14
+
15
+ --fg0: #000000;
16
+ --fg1: rgba(40, 40, 44);
17
+ --fg2: rgba(40, 40, 44, .7);
18
+ --fg3: rgba(40, 40, 44, .4);
19
+
20
+ --hover-inset: 0 0 2px inset #0002;
21
+
22
+ --k-card-bg: var(--bg0);
23
+ --k-card-border: var(--k-card-bg);
24
+ --k-card-shadow: 0 4px 8px -4px rgb(0 0 0 / 15%);
25
+ --k-menu-bg: var(--bg0);
26
+ --k-main-bg: var(--bg0);
27
+ --k-side-bg: var(--bg1);
28
+ --k-page-bg: var(--bg0);
29
+ --k-hover-bg: var(--bg3);
30
+ --k-activity-bg: var(--bg2);
31
+
32
+ --k-color-border: #c8c9cc;
33
+ --k-color-divider: #e0e4e8;
34
+ --k-color-disabled: #909399;
35
+
36
+ --k-text-dark: var(--fg1);
37
+ --k-text-normal: var(--fg2);
38
+ --k-text-light: var(--fg3);
39
+ --k-text-active: var(--k-color-primary);
40
+
41
+ --loading-mask-bg: #f2f3f5bf;
42
+
43
+ @mixin apply-color($name, $base) {
44
+ --k-color-#{$name}: #{$base};
45
+ --k-color-#{$name}-shade: #{color.mix($base, $black, 90%)};
46
+ --k-color-#{$name}-tint: #{color.mix($base, $white, 80%)};
47
+ --k-color-#{$name}-fade: #{color.adjust($base, $alpha: -0.9)};
48
+ }
49
+
50
+ @include apply-color(primary, #409eff);
51
+ @include apply-color(secondary, #909399);
52
+ @include apply-color(success, #67c23a);
53
+ @include apply-color(warning, #e49400);
54
+ @include apply-color(danger, #f56c6c);
55
+ @include apply-color(info, #909399);
56
+ }
57
+
58
+ html.dark, .theme-root.dark {
59
+ --bg0: #000000;
60
+ --bg1: #1e1e20;
61
+ --bg2: #252529;
62
+ --bg3: #313136;
63
+
64
+ --fg0: #ffffff;
65
+ --fg1: rgba(255, 255, 245, .9);
66
+ --fg2: rgba(255, 255, 245, .6);
67
+ --fg3: rgba(255, 255, 245, .4);
68
+
69
+ --k-card-bg: var(--bg2);
70
+ --k-card-border: var(--k-color-divider);
71
+ --k-card-shadow: 0 4px 8px -4px rgb(0 0 0 / 15%);
72
+ --k-menu-bg: var(--bg0);
73
+ --k-main-bg: var(--bg3);
74
+ --k-side-bg: var(--bg2);
75
+ --k-page-bg: var(--bg2);
76
+ --k-hover-bg: var(--bg3);
77
+ --k-activity-bg: var(--bg1);
78
+
79
+ --k-color-border: rgba(82, 82, 89, .8);
80
+ --k-color-divider: rgba(82, 82, 89, .5);
81
+ --k-color-disabled: #909399;
82
+
83
+ --k-text-dark: var(--fg1);
84
+ --k-text-normal: var(--fg2);
85
+ --k-text-light: var(--fg3);
86
+ --k-text-active: var(--k-text-dark);
87
+
88
+ --loading-mask-bg: #202225bf;
89
+
90
+ @mixin apply-color($name, $base) {
91
+ --k-color-#{$name}: #{$base};
92
+ --k-color-#{$name}-shade: #{color.mix($base, $black, 80%)};
93
+ --k-color-#{$name}-tint: #{color.mix($base, $white, 90%)};
94
+ --k-color-#{$name}-fade: #{color.adjust($base, $alpha: -0.9)};
95
+ }
96
+
97
+ @include apply-color(primary, #7459ff);
98
+ @include apply-color(secondary, #4f545c);
99
+ @include apply-color(success, #3ba55e);
100
+ @include apply-color(warning, #f9af1b);
101
+ @include apply-color(danger, #ff595a);
102
+ @include apply-color(info, #4f545c);
103
+ }
104
+
105
+ :root {
106
+ // transitions
107
+ --color-transition: color 0.3s ease, border-color 0.3s ease, background-color 0.3s ease, box-shadow 0.3s ease, opacity 0.3s ease;
108
+
109
+ // fonts
110
+ --font-family: PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
111
+ --font-family-code: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
112
+
113
+ // fallback
114
+ --k-color-border-dark: var(--k-color-border);
115
+ --k-color-border-light: var(--k-color-divider);
116
+ --k-color-divider-dark: var(--k-color-divider);
117
+ --k-color-divider-light: var(--k-color-divider);
118
+
119
+ --k-fill-normal: var(--k-color-primary);
120
+ --k-fill-disabled: var(--k-color-disabled);
121
+
122
+ --k-menu-shadow: var(--k-card-shadow);
123
+
124
+ --k-button-hover-bg: var(--bg1);
125
+
126
+ // compatibility
127
+ --border: var(--k-color-border);
128
+ --divider: var(--k-color-divider);
129
+ --page-bg: var(--k-page-bg);
130
+ --hover-bg: var(--k-hover-bg);
131
+ --card-bg: var(--k-card-bg);
132
+ --card-shadow: var(--k-card-shadow);
133
+ --success: var(--k-color-success);
134
+ --error: var(--k-color-danger);
135
+ --danger: var(--k-color-danger);
136
+ --warning: var(--k-color-warning);
137
+ --active: var(--k-color-primary);
138
+ --primary: var(--k-color-primary);
139
+ --k-color-active: var(--active);
140
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 全局样式插件:引入 app 级 SCSS,并注册四套内置主题
3
+ * (默认 / 高对比 × 明亮 / 暗色),供主题选择器列出与切换。
4
+ */
5
+
6
+ import type { Context } from "@koishi-ce/client";
7
+
8
+ import "./index.scss";
9
+
10
+ export default function (ctx: Context) {
11
+ ctx.theme({
12
+ id: "default-light",
13
+ name: "Default Light",
14
+ });
15
+
16
+ ctx.theme({
17
+ id: "default-dark",
18
+ name: "Default Dark",
19
+ });
20
+
21
+ ctx.theme({
22
+ id: "hc-light",
23
+ name: "High Contrast Light",
24
+ });
25
+
26
+ ctx.theme({
27
+ id: "hc-dark",
28
+ name: "High Contrast Dark",
29
+ });
30
+ }
@@ -0,0 +1,92 @@
1
+ :root {
2
+ --aside-width: 17.5rem;
3
+ --activity-width: 4rem;
4
+ --activity-padding: 0.5rem;
5
+ --activity-marker-width: 4px;
6
+ --activity-marker-height: 1.75rem;
7
+ --activity-icon-size: 1.5rem;
8
+ --header-height: 3rem;
9
+ --footer-height: 1.75rem;
10
+
11
+ --card-margin: 2rem;
12
+ --card-padding-vertical: 1.5rem;
13
+ --card-padding-horizontal: 1.5rem;
14
+
15
+ @media screen and (max-width: 768px) {
16
+ --aside-width: 17rem;
17
+ --activity-width: 3.5rem;
18
+ --activity-padding: 0.25rem;
19
+ --activity-icon-size: 1.375rem;
20
+ --card-margin: 1.5rem;
21
+ --card-padding-vertical: 1rem;
22
+ --card-padding-horizontal: 1rem;
23
+ }
24
+
25
+ @media screen and (max-width: 480px) {
26
+ --card-margin: 1rem;
27
+ --card-padding-vertical: 0.75rem;
28
+ --card-padding-horizontal: 0.875rem;
29
+ }
30
+
31
+ @media screen and (max-width: 384px) {
32
+ --aside-width: calc(100vw - 2 * var(--activity-width));
33
+ }
34
+ }
35
+
36
+ .layout-left {
37
+ .el-tree {
38
+ margin-top: 0.5rem;
39
+ user-select: none;
40
+ line-height: 2.25rem;
41
+ }
42
+
43
+ .el-tree-node__expand-icon {
44
+ margin-left: 8px;
45
+ }
46
+
47
+ .el-tree-node {
48
+ &:focus:not(:hover):not(.is-active) > .el-tree-node__content {
49
+ background-color: unset;
50
+ }
51
+
52
+ &.is-disabled > .el-tree-node__content .label {
53
+ color: var(--k-text-light);
54
+ }
55
+
56
+ &.is-active > .el-tree-node__content {
57
+ background-color: var(--k-tree-bg-active, var(--k-hover-bg));
58
+ color: var(--active);
59
+ }
60
+ }
61
+
62
+ .el-tree-node__content {
63
+ line-height: 2rem;
64
+ height: 2rem;
65
+ transition: var(--color-transition);
66
+
67
+ .label {
68
+ font-size: 14px;
69
+ flex: 1 1 auto;
70
+ margin-right: 0.5rem;
71
+ }
72
+ }
73
+ }
74
+
75
+ .k-tab-menu-item {
76
+ display: block;
77
+ position: relative;
78
+ cursor: pointer;
79
+ user-select: none;
80
+ color: var(--k-text-light);
81
+ transition: var(--color-transition);
82
+
83
+ &:hover {
84
+ color: var(--k-text-dark);
85
+ background-color: var(--k-hover-bg);
86
+ }
87
+
88
+ &.active {
89
+ font-weight: bolder;
90
+ color: var(--active);
91
+ }
92
+ }
@@ -0,0 +1,97 @@
1
+ <!--
2
+ 活动栏单个图标按钮,也是拖拽排序的拖拽源:
3
+ 拖起时向 dataTransfer 写入 "activity:<id>" 文本供落点组件识别。
4
+ 无 id 的项(如溢出组的 "..." 图标)渲染为不可点击的 span。
5
+ -->
6
+ <template>
7
+ <component
8
+ :is="data.id ? 'k-activity-link' : 'span'"
9
+ class="activity-button"
10
+ draggable="true"
11
+ :id="data.id"
12
+ :class="{ 'dragging': isDragging }"
13
+ @dragstart="handleDragStart"
14
+ @dragend="handleDragEnd">
15
+ <k-icon class="activity-button-icon" :name="data.icon"></k-icon>
16
+ </component>
17
+ </template>
18
+
19
+ <script lang="ts" setup>
20
+ import type { Activity } from "@koishi-ce/client";
21
+ import { ref } from "vue";
22
+
23
+ const props = defineProps<{
24
+ data: Activity;
25
+ }>();
26
+
27
+ const isDragging = ref(false);
28
+
29
+ function handleDragStart(event: DragEvent) {
30
+ isDragging.value = true;
31
+ // 约定的拖拽协议:以 "activity:" 前缀 + 活动 id 标识被拖动的活动项
32
+ event.dataTransfer.setData("text/plain", `activity:${props.data.id}`);
33
+ }
34
+
35
+ function handleDragEnd(event: DragEvent) {
36
+ isDragging.value = false;
37
+ }
38
+ </script>
39
+
40
+ <style lang="scss" scoped>
41
+
42
+ .activity-button {
43
+ height: calc(var(--activity-width) - 2 * var(--activity-padding));
44
+ display: flex;
45
+ justify-content: center;
46
+ align-items: center;
47
+ position: relative;
48
+ transition: var(--color-transition);
49
+ color: var(--k-text-light);
50
+ border-radius: var(--activity-padding);
51
+ cursor: pointer;
52
+
53
+ .activity-button-icon {
54
+ height: var(--activity-icon-size);
55
+ pointer-events: none;
56
+ }
57
+
58
+ &:hover, &.dragging {
59
+ color: var(--k-text-dark);
60
+ background-color: var(--k-hover-bg);
61
+ }
62
+
63
+ &.active {
64
+ color: var(--k-text-active);
65
+ }
66
+
67
+ .badge {
68
+ position: absolute;
69
+ border-radius: 1rem;
70
+ color: #ffffff;
71
+ background-color: var(--k-color-danger);
72
+ top: 50%;
73
+ right: 1.5rem;
74
+ transform: translateY(-50%);
75
+ line-height: 1;
76
+ padding: 4px 8px;
77
+ font-size: 0.75rem;
78
+ font-weight: bolder;
79
+ transition: var(--color-transition);
80
+ }
81
+
82
+ &.is-group {
83
+ &::before {
84
+ content: "";
85
+ position: absolute;
86
+ right: 0;
87
+ bottom: 4px;
88
+ width: 0;
89
+ height: 0;
90
+ border: 4px solid;
91
+ border-color: transparent transparent transparent currentColor;
92
+ transition: var(--color-transition);
93
+ }
94
+ }
95
+ }
96
+
97
+ </style>