diff --git a/plugins/frontend/client/client/components/icons/index.ts b/plugins/frontend/client/client/components/icons/index.ts
index e8de71aa28..b0b549673e 100644
--- a/plugins/frontend/client/client/components/icons/index.ts
+++ b/plugins/frontend/client/client/components/icons/index.ts
@@ -17,6 +17,7 @@ import Cog from './svg/cog.vue'
import CommentsFull from './svg/comments-full.vue'
import Database from './svg/database.vue'
import Diagram from './svg/diagram.vue'
+import Edit from './svg/edit.vue'
import ExclamationFull from './svg/exclamation-full.vue'
import Expand from './svg/expand.vue'
import External from './svg/external.vue'
@@ -77,6 +78,7 @@ register('cog', Cog)
register('comments-full', CommentsFull)
register('database', Database)
register('diagram', Diagram)
+register('edit', Edit)
register('exclamation-full', ExclamationFull)
register('expand', Expand)
register('external', External)
diff --git a/plugins/frontend/client/client/components/icons/svg/edit.vue b/plugins/frontend/client/client/components/icons/svg/edit.vue
new file mode 100644
index 0000000000..d473c33efb
--- /dev/null
+++ b/plugins/frontend/client/client/components/icons/svg/edit.vue
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/frontend/manager/client/bots/index.vue b/plugins/frontend/manager/client/bots/index.vue
index b9d8b6f1d8..5557ab7933 100644
--- a/plugins/frontend/manager/client/bots/index.vue
+++ b/plugins/frontend/manager/client/bots/index.vue
@@ -46,6 +46,7 @@ watch(() => store.bots, () => {
section.page-bots {
> aside {
width: 20rem;
+ max-width: unset;
.add {
font-size: 1.15rem;
diff --git a/plugins/frontend/manager/client/settings/index.vue b/plugins/frontend/manager/client/settings/index.vue
index 3f2c2b1f2f..08a5ad3af2 100644
--- a/plugins/frontend/manager/client/settings/index.vue
+++ b/plugins/frontend/manager/client/settings/index.vue
@@ -3,13 +3,11 @@
-
-
-
-
-
-
-
+
+
+
+
+
diff --git a/plugins/frontend/manager/client/settings/plugin.vue b/plugins/frontend/manager/client/settings/plugin.vue
index 40ae0b55fc..fae09e5aae 100644
--- a/plugins/frontend/manager/client/settings/plugin.vue
+++ b/plugins/frontend/manager/client/settings/plugin.vue
@@ -11,8 +11,10 @@
- {{ data.shortname }}
- ({{ data.workspace ? '工作区' : data.version }})
+ {{ data.shortname }}
+
+ @
+
停用插件
@@ -83,7 +85,7 @@
import { send, store, clone, router } from '@koishijs/client'
import { computed, ref, watch } from 'vue'
import { getMixedMeta } from '../utils'
-import { envMap, Tree } from './utils'
+import { envMap, Tree, setPath } from './utils'
import KDepLink from './dep-link.vue'
const props = defineProps<{
@@ -96,6 +98,23 @@ watch(() => props.current.config, (value) => {
config.value = clone(value)
}, { immediate: true })
+const alias = ref()
+
+watch(() => props.current.alias, (value) => {
+ alias.value = value
+}, { immediate: true })
+
+function updateAlias() {
+ if (alias.value === props.current.alias) return
+ props.current.alias = alias.value
+ send('manager/alias', props.current.path, alias.value)
+ const oldPath = props.current.path
+ const segments = oldPath.split('/')
+ const oldKey = segments.pop()
+ segments.push(oldKey.split(':', 1)[0] + (alias.value ? ':' : '') + alias.value)
+ setPath(oldPath, segments.join('/'))
+}
+
const name = computed(() => {
const { label, target: temporary } = props.current
const shortname = temporary || label
@@ -138,6 +157,20 @@ function execute(event: 'unload' | 'reload') {
text-decoration: underline;
}
}
+
+ .config-header .alias {
+ font-size: 1.15rem;
+ color: var(--fg3);
+ user-select: none;
+
+ input {
+ font-size: inherit;
+ border: none;
+ outline: none;
+ color: var(--fg3);
+ padding: 0;
+ }
+ }
}
diff --git a/plugins/frontend/manager/client/settings/tree.vue b/plugins/frontend/manager/client/settings/tree.vue
index 5d4fed5302..0b57b0d1ce 100644
--- a/plugins/frontend/manager/client/settings/tree.vue
+++ b/plugins/frontend/manager/client/settings/tree.vue
@@ -34,7 +34,7 @@
import { ref, computed, onActivated, nextTick, watch } from 'vue'
import { send } from '@koishijs/client'
-import { Tree, plugins } from './utils'
+import { Tree, plugins, setPath } from './utils'
const props = defineProps<{
modelValue: string
@@ -88,11 +88,7 @@ function handleDrop(source: Node, target: Node, position: 'before' | 'after' | '
const segments1 = oldPath.split('/')
const segments2 = ctxPath ? ctxPath.split('/') : []
segments2.push(segments1.pop())
- const newPath = source.data.path = segments2.join('/')
- if (oldPath === newPath) return
- plugins.value.paths[newPath] = plugins.value.paths[oldPath]
- delete plugins.value.paths[oldPath]
- emits('update:modelValue', newPath)
+ setPath(oldPath, segments2.join('/'))
}
function getClass(tree: Tree) {
diff --git a/plugins/frontend/manager/client/settings/utils.ts b/plugins/frontend/manager/client/settings/utils.ts
index 70c345b45b..f730876d3b 100644
--- a/plugins/frontend/manager/client/settings/utils.ts
+++ b/plugins/frontend/manager/client/settings/utils.ts
@@ -2,7 +2,7 @@ import { Dict } from 'koishi'
import { computed } from 'vue'
import { PackageJson } from '@koishijs/market'
import { MarketProvider } from '@koishijs/plugin-manager'
-import { store } from '@koishijs/client'
+import { router, store } from '@koishijs/client'
import { getMixedMeta } from '../utils'
import {} from '@koishijs/cli'
@@ -98,6 +98,7 @@ export const envMap = computed(() => {
export interface Tree {
id: string
+ alias?: string
label: string
path: string
config?: any
@@ -121,7 +122,8 @@ function getTree(prefix: string, plugins: any): Tree[] {
node.path = prefix + key
node.children = getTree(node.path + '/', config)
} else {
- node.label = key.split(':')[0]
+ node.label = key.split(':', 1)[0]
+ node.alias = key.slice(node.label.length + 1)
node.path = prefix + key
}
node.id = node.path
@@ -157,3 +159,12 @@ export const plugins = computed(() => {
traverse(root)
return { data: [root], paths, expanded }
})
+
+export function setPath(oldPath: string, newPath: string) {
+ if (oldPath === newPath) return
+ const tree = plugins.value.paths[oldPath]
+ tree.path = newPath
+ plugins.value.paths[newPath] = tree
+ delete plugins.value.paths[oldPath]
+ router.replace('/plugins/' + newPath)
+}
diff --git a/plugins/frontend/manager/src/writer.ts b/plugins/frontend/manager/src/writer.ts
index 3871db5f86..77e695f491 100644
--- a/plugins/frontend/manager/src/writer.ts
+++ b/plugins/frontend/manager/src/writer.ts
@@ -9,6 +9,7 @@ declare module '@koishijs/plugin-console' {
'manager/reload'(path: string, config: any, key?: string): void
'manager/unload'(path: string, config: any, key?: string): void
'manager/group'(path: string): void
+ 'manager/alias'(path: string, alias: string): void
'manager/meta'(path: string, config: any): void
'manager/bot-update'(id: string, adapter: string, config: any): void
'manager/bot-remove'(id: string): void
@@ -55,7 +56,7 @@ class ConfigWriter extends DataService {
this.reloadApp(config)
}, { authority: 4 })
- for (const key of ['teleport', 'reload', 'unload', 'group', 'meta'] as const) {
+ for (const key of ['teleport', 'reload', 'unload', 'group', 'meta', 'alias'] as const) {
ctx.console.addListener(`manager/${key}`, this[key].bind(this), { authority: 4 })
}
@@ -92,6 +93,22 @@ class ConfigWriter extends DataService {
return [runtime, name] as const
}
+ alias(path: string, alias: string) {
+ const [runtime, oldKey] = this.resolve(path)
+ const config = runtime.config[oldKey]
+ let newKey = oldKey.split(':', 1)[0] + (alias ? ':' : '') + alias
+ const record = runtime[Symbol.for('koishi.loader.record')]
+ const fork = record[oldKey]
+ if (fork) {
+ delete record[oldKey]
+ record[newKey] = fork
+ } else {
+ newKey = '~' + newKey
+ }
+ rename(runtime.config, oldKey, newKey, config)
+ this.loader.writeConfig()
+ }
+
meta(path: string, config: any) {
const [runtime, name] = this.resolve(path)
const target = path ? runtime.config[name] : runtime.config
@@ -151,7 +168,7 @@ class ConfigWriter extends DataService {
this.loader.writeConfig()
}
- locate(name: string, runtime: Plugin.Runtime) {
+ private locate(name: string, runtime: Plugin.Runtime) {
for (const key in runtime.config) {
const value = runtime.config[key]
const fork = runtime[Symbol.for('koishi.loader.record')][key]