Skip to content

Commit

Permalink
feat(client): support dynamic schema
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed May 6, 2023
1 parent 6fb6137 commit 1ce946f
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 17 deletions.
54 changes: 54 additions & 0 deletions packages/client/client/components/dynamic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<template>
<k-schema
v-if="inner"
:modelValue="modelValue"
@update:modelValue="$emit('update:modelValue', $event)"
:schema="{ ...inner, meta: { ...inner.meta, ...schema.meta } }"
:initial="initial"
:disabled="disabled"
:prefix="prefix"
>
<template #title><slot name="title"></slot></template>
<template #prefix><slot name="prefix"></slot></template>
<template #suffix><slot name="suffix"></slot></template>
</k-schema>

<schema-base
v-else
:modelValue="modelValue"
@update:modelValue="$emit('update:modelValue', $event)"
:schema="schema"
:initial="initial"
:disabled="disabled"
:prefix="prefix"
>
<template #title><slot name="title"></slot></template>
<template #desc><slot name="desc"></slot></template>
<template #menu><slot name="menu"></slot></template>
</schema-base>
</template>

<script setup lang="ts">
import { computed, PropType } from 'vue'
import { store } from '../data'
import { Schema, SchemaBase } from '@koishijs/components'
const props = defineProps({
schema: {} as PropType<Schema>,
modelValue: {} as PropType<any>,
disabled: {} as PropType<boolean>,
prefix: {} as PropType<string>,
initial: {} as PropType<any>,
extra: {} as PropType<any>,
})
defineEmits(['update:modelValue'])
const inner = computed(() => {
const hydrated = store.schema?.[props.schema?.meta.extra?.name]
return hydrated && new Schema(hydrated)
})
</script>

7 changes: 7 additions & 0 deletions packages/client/client/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import components from '@koishijs/components'
import Element, { ElLoading, ElMessage, ElMessageBox } from 'element-plus'

import common from './common'
import Dynamic from './dynamic.vue'
import ChatImage from './chat/image.vue'
import * as icons from './icons'
import layout from './layout'
Expand All @@ -22,6 +23,12 @@ export * from '@koishijs/components'

export { icons, ChatImage }

components.extensions.add({
type: 'any',
role: 'dynamic',
component: Dynamic,
})

export default function (app: App) {
app.use(Element)
app.component('k-markdown', Markdown)
Expand Down
2 changes: 1 addition & 1 deletion packages/client/client/styles/schema.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
padding: 0 1.5rem;
}

.schema-item {
.k-schema-item {
padding: 0.5rem 1.5rem;

.header {
Expand Down
3 changes: 1 addition & 2 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
"build"
],
"dependencies": {
"@koishijs/components": "^1.0.3",
"@satorijs/element": "^2.4.1",
"@koishijs/components": "1.0.5",
"@vitejs/plugin-vue": "^4.1.0",
"@vueuse/core": "^9.13.0",
"cac": "^6.7.14",
Expand Down
25 changes: 19 additions & 6 deletions packages/components/client/k-form.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
<template>
<k-comment v-if="!validate(resolved)" type="warning">
<p>部分配置项无法正常显示,这可能并非预期行为<slot name="hint"></slot>。</p>
</k-comment>

<form class="k-form">
<slot name="prolog"></slot>
<h2 class="k-schema-header" v-if="showHeader ?? !hasTitle(resolved, true)">
<h2 class="k-schema-header" v-if="showHeader ?? !hasTitle(resolved)">
<slot name="title">基础设置</slot>
</h2>
<k-schema
Expand All @@ -22,7 +18,7 @@
<script lang="ts" setup>
import { computed, PropType } from 'vue'
import { hasTitle, Schema, validate } from 'schemastery-vue'
import { getChoices, Schema } from 'schemastery-vue'
const props = defineProps({
schema: {} as PropType<Schema>,
Expand All @@ -37,6 +33,23 @@ const resolved = computed(() => {
return props.schema && new Schema(props.schema)
})
function hasTitle(schema: Schema): boolean {
if (!schema) return true
if (schema.type === 'object') {
if (schema.meta.description) return true
const keys = Object.keys(schema.dict)
if (!keys.length) return true
return hasTitle(schema.dict[keys[0]])
} else if (schema.type === 'intersect') {
return hasTitle(schema.list[0])
} else if (schema.type === 'union') {
const choices = getChoices(schema)
return choices.length === 1 ? hasTitle(choices[0]) : false
} else {
return false
}
}
const emit = defineEmits(['update:modelValue'])
const config = computed({
Expand Down
6 changes: 3 additions & 3 deletions packages/components/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@koishijs/components",
"description": "Client components for Koishi",
"version": "1.0.3",
"version": "1.0.5",
"main": "client/index.ts",
"files": [
"client"
Expand All @@ -28,7 +28,7 @@
"vue": "^3"
},
"dependencies": {
"@satorijs/element": "^2.4.1",
"schemastery-vue": "^4.0.0"
"@satorijs/element": "^2.4.2",
"schemastery-vue": "4.1.0"
}
}
2 changes: 1 addition & 1 deletion plugins/login/client/profile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
平台用户绑定
<el-button solid @click="showDialog = true">添加</el-button>
</h2>
<div class="schema-item" v-for="({ platform, pid, bid }) in store.user.bindings">
<div class="k-schema-item" v-for="({ platform, pid, bid }) in store.user.bindings">
<div class="header">
<div class="left">{{ platform }} ({{ pid }})</div>
<div class="right">
Expand Down
4 changes: 0 additions & 4 deletions plugins/market/client/settings/modifier.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ const filter = computed({
.modifier {
margin-bottom: 2rem;
.k-schema-header {
font-size: 1.25rem;
}
}
</style>

0 comments on commit 1ce946f

Please sign in to comment.