From b5d95c95d88238961ebd26bc0b59df32ff342c53 Mon Sep 17 00:00:00 2001 From: liuyun Date: Sun, 11 Oct 2026 10:44:06 +0800 Subject: [PATCH] feat: dictionary & organization management pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 字典管理:左右分栏主从布局,20 个字典类型,el-scrollbar 滚动 - 组织管理:树形表格 + 上级组织 tree-select,级联删除下级 - ty-table 新增树形支持(row-key/tree-props/default-expand-all) - ty-form 新增 tree-select 控件(format/treeData/treeProps) - JsonSchemaProperty 扩展 tree-select 相关字段 Co-Authored-By: Claude Opus 4.8 --- components.d.ts | 8 + src/components/ty-form.vue | 16 ++ src/components/ty-table.vue | 12 + src/pages/system/dict/index.vue | 402 ++++++++++++++++++++++++++++++++ src/pages/system/org/index.vue | 388 ++++++++++++++++++++++++++++++ src/types/crud.ts | 6 +- stats.html | 2 +- typed-router.d.ts | 26 +++ 8 files changed, 858 insertions(+), 2 deletions(-) create mode 100644 src/pages/system/dict/index.vue create mode 100644 src/pages/system/org/index.vue diff --git a/components.d.ts b/components.d.ts index 33b3ec1..7c084f3 100644 --- a/components.d.ts +++ b/components.d.ts @@ -23,6 +23,7 @@ declare module 'vue' { ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] + ElEmpty: typeof import('element-plus/es')['ElEmpty'] ElForm: typeof import('element-plus/es')['ElForm'] ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElInput: typeof import('element-plus/es')['ElInput'] @@ -40,7 +41,10 @@ declare module 'vue' { ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + ElTabPane: typeof import('element-plus/es')['ElTabPane'] + ElTabs: typeof import('element-plus/es')['ElTabs'] ElTag: typeof import('element-plus/es')['ElTag'] + ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] Icon: typeof import('./src/components/icon/icon.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] @@ -76,6 +80,7 @@ declare global { const ElDropdown: typeof import('element-plus/es')['ElDropdown'] const ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] const ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] + const ElEmpty: typeof import('element-plus/es')['ElEmpty'] const ElForm: typeof import('element-plus/es')['ElForm'] const ElFormItem: typeof import('element-plus/es')['ElFormItem'] const ElInput: typeof import('element-plus/es')['ElInput'] @@ -93,7 +98,10 @@ declare global { const ElSwitch: typeof import('element-plus/es')['ElSwitch'] const ElTable: typeof import('element-plus/es')['ElTable'] const ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + const ElTabPane: typeof import('element-plus/es')['ElTabPane'] + const ElTabs: typeof import('element-plus/es')['ElTabs'] const ElTag: typeof import('element-plus/es')['ElTag'] + const ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] const Icon: typeof import('./src/components/icon/icon.vue')['default'] const RouterLink: typeof import('vue-router')['RouterLink'] const RouterView: typeof import('vue-router')['RouterView'] diff --git a/src/components/ty-form.vue b/src/components/ty-form.vue index 8ce5b34..76d5705 100644 --- a/src/components/ty-form.vue +++ b/src/components/ty-form.vue @@ -22,6 +22,22 @@ /> + + @@ -75,6 +78,12 @@ const props = withDefaults( pageSizes?: number[] /** 操作列宽度。 */ actionsWidth?: number | string + /** 树形数据的行唯一键。 */ + rowKey?: string + /** 树形结构字段映射。 */ + treeProps?: Record + /** 是否默认展开所有树节点。 */ + defaultExpandAll?: boolean }>(), { loading: false, @@ -84,6 +93,9 @@ const props = withDefaults( pageSize: 10, pageSizes: () => [10, 20, 50], actionsWidth: 200, + rowKey: 'id', + treeProps: () => ({ children: 'children' }), + defaultExpandAll: false, }, ) diff --git a/src/pages/system/dict/index.vue b/src/pages/system/dict/index.vue new file mode 100644 index 0000000..2b2c3a7 --- /dev/null +++ b/src/pages/system/dict/index.vue @@ -0,0 +1,402 @@ + + + + + diff --git a/src/pages/system/org/index.vue b/src/pages/system/org/index.vue new file mode 100644 index 0000000..e666748 --- /dev/null +++ b/src/pages/system/org/index.vue @@ -0,0 +1,388 @@ + + + + + diff --git a/src/types/crud.ts b/src/types/crud.ts index 5166e2a..75442bb 100644 --- a/src/types/crud.ts +++ b/src/types/crud.ts @@ -9,7 +9,7 @@ export interface JsonSchemaProperty { title?: string description?: string /** 格式化:password/email/textarea 等。 */ - format?: 'password' | 'email' | 'textarea' | 'date' | 'datetime' + format?: 'password' | 'email' | 'textarea' | 'date' | 'datetime' | 'tree-select' /** 枚举值(渲染为下拉)。 */ enum?: (string | number | boolean)[] /** 枚举显示名(与 enum 一一对应)。 */ @@ -26,6 +26,10 @@ export interface JsonSchemaProperty { placeholder?: string /** 控件宽度(如 '160px');缺省时搜索行内默认 200px、弹窗表单默认 100%。 */ width?: string + /** format=tree-select 时的树数据([{ label, value, children }])。 */ + treeData?: Record[] + /** format=tree-select 时的树字段映射。 */ + treeProps?: { label?: string; value?: string; children?: string } } /** JSON Schema 对象(表单 schema)。 */ diff --git a/stats.html b/stats.html index 9591460..acf2dc2 100644 --- a/stats.html +++ b/stats.html @@ -4930,7 +4930,7 @@ var drawChart = (function (exports) {