feat: config management page
参数配置页:纯键值 CRUD,复用 ty-crud + JSON Schema 零新组件。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
1df44fd57e
commit
16b512a3f1
112
src/pages/system/config/index.vue
Normal file
112
src/pages/system/config/index.vue
Normal file
@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<ty-crud
|
||||
entity-name="配置"
|
||||
:columns="columns"
|
||||
:search-schema="searchSchema"
|
||||
:form-schema="formSchema"
|
||||
:list="list"
|
||||
:create="create"
|
||||
:update="update"
|
||||
:remove="remove"
|
||||
id-key="id"
|
||||
name-key="key"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { JsonSchema, PageQuery, PageResult, TableColumn } from '@/types/crud'
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{ prop: 'key', label: '键名', minWidth: 160 },
|
||||
{ prop: 'value', label: '值', minWidth: 220 },
|
||||
{ prop: 'remark', label: '备注', minWidth: 160 },
|
||||
{ prop: 'createdAt', label: '创建时间', width: 160, type: 'datetime' },
|
||||
]
|
||||
|
||||
const searchSchema: JsonSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
key: { type: 'string', title: '键名', placeholder: '请输入键名' },
|
||||
value: { type: 'string', title: '值', placeholder: '请输入值' },
|
||||
},
|
||||
}
|
||||
|
||||
const formSchema: JsonSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
key: { type: 'string', title: '键名', placeholder: '请输入键名', minLength: 1 },
|
||||
value: { type: 'string', title: '值', format: 'textarea', placeholder: '请输入值' },
|
||||
remark: { type: 'string', title: '备注', placeholder: '请输入备注' },
|
||||
},
|
||||
required: ['key'],
|
||||
}
|
||||
|
||||
// ---- 占位数据(后续对接后端时替换为 http 调用)----
|
||||
interface ConfigRow {
|
||||
id: string
|
||||
key: string
|
||||
value: string
|
||||
remark: string
|
||||
createdAt: number
|
||||
}
|
||||
|
||||
const now = Date.now()
|
||||
const day = 24 * 60 * 60 * 1000
|
||||
const configs: ConfigRow[] = [
|
||||
{ id: '1', key: 'sys.name', value: '投云系统管理平台', remark: '系统名称', createdAt: now - 30 * day },
|
||||
{ id: '2', key: 'sys.theme', value: '#2E7FA3', remark: '默认主题色', createdAt: now - 20 * day },
|
||||
{ id: '3', key: 'sys.copyright', value: '云南投云科技有限公司', remark: '版权信息', createdAt: now - 10 * day },
|
||||
{ id: '4', key: 'sys.pageSize', value: '10', remark: '默认分页大小', createdAt: now - 5 * day },
|
||||
{ id: '5', key: 'sys.captcha', value: 'true', remark: '是否开启验证码', createdAt: now - 1 * day },
|
||||
]
|
||||
|
||||
let seq = 0
|
||||
const nextId = () => `c-${Date.now()}-${++seq}`
|
||||
|
||||
function delay<T>(fn: () => T, ms = 300): Promise<T> {
|
||||
return new Promise((resolve) => setTimeout(() => resolve(fn()), ms))
|
||||
}
|
||||
|
||||
const list = (query: PageQuery): Promise<PageResult<Record<string, any>>> =>
|
||||
delay(() => {
|
||||
const { page, pageSize, key, value } = query
|
||||
const filtered = configs.filter((c) => {
|
||||
if (key && !c.key.includes(String(key))) return false
|
||||
if (value && !c.value.includes(String(value))) return false
|
||||
return true
|
||||
})
|
||||
const start = (page - 1) * pageSize
|
||||
return {
|
||||
list: filtered.slice(start, start + pageSize) as unknown as Record<string, any>[],
|
||||
total: filtered.length,
|
||||
page,
|
||||
pageSize,
|
||||
}
|
||||
})
|
||||
|
||||
const create = (data: Record<string, any>): Promise<unknown> =>
|
||||
delay(() => {
|
||||
configs.unshift({
|
||||
id: nextId(),
|
||||
key: data.key,
|
||||
value: data.value ?? '',
|
||||
remark: data.remark ?? '',
|
||||
createdAt: Date.now(),
|
||||
})
|
||||
return null
|
||||
})
|
||||
|
||||
const update = (id: string, data: Record<string, any>): Promise<unknown> =>
|
||||
delay(() => {
|
||||
const c = configs.find((x) => x.id === id)
|
||||
if (c) Object.assign(c, data)
|
||||
return null
|
||||
})
|
||||
|
||||
const remove = (id: string): Promise<unknown> =>
|
||||
delay(() => {
|
||||
const i = configs.findIndex((x) => x.id === id)
|
||||
if (i >= 0) configs.splice(i, 1)
|
||||
return null
|
||||
})
|
||||
</script>
|
||||
File diff suppressed because one or more lines are too long
13
typed-router.d.ts
vendored
13
typed-router.d.ts
vendored
@ -44,6 +44,13 @@ declare module 'vue-router/auto-routes' {
|
||||
Record<never, never>,
|
||||
| never
|
||||
>,
|
||||
'/system/config/': RouteRecordInfo<
|
||||
'/system/config/',
|
||||
'/system/config',
|
||||
Record<never, never>,
|
||||
Record<never, never>,
|
||||
| never
|
||||
>,
|
||||
'/system/user/': RouteRecordInfo<
|
||||
'/system/user/',
|
||||
'/system/user',
|
||||
@ -82,6 +89,12 @@ declare module 'vue-router/auto-routes' {
|
||||
views:
|
||||
| never
|
||||
}
|
||||
'src/pages/system/config/index.vue': {
|
||||
routes:
|
||||
| '/system/config/'
|
||||
views:
|
||||
| never
|
||||
}
|
||||
'src/pages/system/user/index.vue': {
|
||||
routes:
|
||||
| '/system/user/'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user