@xmszm/core 0.0.1

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 (45) hide show
  1. package/dist/index.cjs +2 -0
  2. package/dist/index.mjs +2145 -0
  3. package/dist/style.css +1 -0
  4. package/docs/components/dataform.md +61 -0
  5. package/docs/components/datatable.md +77 -0
  6. package/docs/components/dialog.md +78 -0
  7. package/docs/components/options.md +55 -0
  8. package/docs/components/query.md +49 -0
  9. package/docs/components/utils.md +56 -0
  10. package/docs/guide/demo.md +213 -0
  11. package/docs/guide/quickstart.md +77 -0
  12. package/docs/index.md +25 -0
  13. package/docs/usage.md +61 -0
  14. package/examples/demo.vue +224 -0
  15. package/package.json +64 -0
  16. package/src/dialog/commonDialog.jsx +230 -0
  17. package/src/dialog/style/commonDialog.less +40 -0
  18. package/src/dialog/utils/dialog.js +82 -0
  19. package/src/enum/options.js +3 -0
  20. package/src/enum/sort.jsx +31 -0
  21. package/src/form/DataForm.vue +125 -0
  22. package/src/image/ImagesUpload.vue +268 -0
  23. package/src/image/SvgIcon.vue +30 -0
  24. package/src/index.js +46 -0
  25. package/src/list/useList.jsx +99 -0
  26. package/src/options/Options.jsx +338 -0
  27. package/src/options/defaultOptions.jsx +580 -0
  28. package/src/options/options.md +77 -0
  29. package/src/plugin/vite/initRouteMeta.js +54 -0
  30. package/src/query/CommonQuery.vue +272 -0
  31. package/src/store/utils/index.js +6 -0
  32. package/src/table/DataTable.vue +315 -0
  33. package/src/table/FilterDialog.vue +157 -0
  34. package/src/table/opr/DataColumnCollet.jsx +127 -0
  35. package/src/table/opr/useDataColumn.jsx +196 -0
  36. package/src/table/opr/useDataColumnButton.jsx +56 -0
  37. package/src/table/opr/useDataColumnPop.jsx +57 -0
  38. package/src/table/test.md +248 -0
  39. package/src/table/utils/ellipsis.js +22 -0
  40. package/src/utils/array.js +26 -0
  41. package/src/utils/auth.js +118 -0
  42. package/src/utils/object.js +32 -0
  43. package/src/utils/time.js +7 -0
  44. package/src/utils/upload.js +46 -0
  45. package/types/index.d.ts +67 -0
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .filter-box[data-v-2aba8b9e]{padding:20px;margin:-16px -28px -20px;box-sizing:border-box}.filter-main[data-v-2aba8b9e]{display:flex;align-content:flex-start;flex-wrap:wrap;min-height:500px;max-height:700px;overflow-y:auto;row-gap:20px;padding:0 0 15px;box-sizing:border-box}.filter-main .filter-item[data-v-2aba8b9e]{--info-color: var(--e0ecc754);--n-border-checked: 1px solid var(--info-color) !important;--n-border-focus: 1px solid var(--info-color) !important;--n-color-checked: var(--info-color) !important;--n-box-shadow-focus: 0 0 0 2px #6a1f7403 !important;width:calc(100% / 3)}.filter-footer[data-v-2aba8b9e]{display:flex;justify-content:space-between;align-items:center}.filter-footer .submit-btn[data-v-2aba8b9e]{width:80px}[data-v-8fbdfcbb] .n-data-table-tr--summary{position:sticky;bottom:0;left:0;right:0;z-index:2}[data-v-8fbdfcbb] .n-data-table-tr--summary .n-data-table-td--summary{border-top:1px solid var(--n-merged-border-color)}.upload-box[data-v-54e2cc87]{width:auto}.upload-box[data-v-54e2cc87] .n-upload-file-list.n-upload-file-list--grid{display:flex;flex-wrap:wrap}.upload-box[data-v-54e2cc87] .n-upload-file.n-upload-file--image-card-type{width:var(--image-w);height:var(--image-h)}.upload-box[data-v-54e2cc87] .n-upload-file.n-upload-file--image-card-type .n-image img{object-fit:var(--image-mode)!important}.upload-box[data-v-54e2cc87] .n-upload-trigger--image-card{width:var(--image-w);height:var(--image-h)}.upload-box[data-v-54e2cc87] .n-upload-file--error-status:not(:hover) .n-upload-file-info,.upload-box[data-v-54e2cc87] .n-upload-file--info-status:not(:hover) .n-upload-file-info{position:relative}.upload-box[data-v-54e2cc87] .n-upload-file--error-status:not(:hover) .n-upload-file-info:after,.upload-box[data-v-54e2cc87] .n-upload-file--info-status:not(:hover) .n-upload-file-info:after{content:"";position:absolute;top:0;left:0;right:0;bottom:0;z-index:5;display:block;background-color:#0006}.upload-box[data-v-54e2cc87] .n-upload-file--error-status:not(:hover):after{font-size:12px;white-space:nowrap;content:"上传失败~";position:absolute;color:#ffffffbf;top:50%;left:50%;transform:translate(-50%,-50%);z-index:5;display:block}.upload-box[data-v-54e2cc87] .n-upload-file--info-status:not(:hover):after{font-size:12px;white-space:nowrap;content:"加载中~";position:absolute;color:#ffffffbf;top:50%;left:50%;transform:translate(-50%,-50%);z-index:5;display:block}.svg-icon[data-v-9dbe5f10]{width:inherit;height:inherit;fill:currentColor;vertical-align:middle}.core-dialog-main,.core-dialog-content{box-sizing:border-box;display:flex;align-items:flex-start}.core-dialog-main{min-height:300px}.core-dialog .n-dialog__content{overflow-y:auto;margin:10px -28px 0;box-sizing:border-box;flex:1;border-top:1px solid #91919147;border-bottom:1px solid #91919147;padding:28px}.core-dialog .n-dialog__action{padding:20px 0 0;box-sizing:border-box}.core-dialog-read .n-dialog__content{border-bottom:unset}.select-text[data-v-a0acb8e2]{min-width:100px;max-width:240px;text-align:center}.select-line-text[data-v-a0acb8e2]{text-align:center;white-space:nowrap;display:inline}
@@ -0,0 +1,61 @@
1
+ ---
2
+ title: DataForm
3
+ ---
4
+
5
+ 配置式表单组件,依赖 `Options` 渲染字段,并自动生成校验规则。
6
+
7
+ ## 基础用法
8
+ ```vue
9
+ <script setup>
10
+ import { ref } from 'vue'
11
+ import { DataForm } from 'core'
12
+
13
+ const model = ref({})
14
+ const options = [
15
+ { key: 'name', label: '名称', way: 'input', required: true },
16
+ {
17
+ key: 'type',
18
+ label: '类型',
19
+ way: 'select',
20
+ options: [{ label: 'A', value: 'a' }],
21
+ required: true,
22
+ },
23
+ ]
24
+ </script>
25
+
26
+ <template>
27
+ <DataForm v-model:value="model" :options="options" />
28
+ </template>
29
+ ```
30
+
31
+ ## Props
32
+ - `options: Array` 表单项配置,透传给 `Options`。
33
+ - `value (v-model:value): Object` 表单数据。
34
+ - `read: boolean` 只读模式。
35
+ - `labelField: string` 默认 `label`,决定 label 字段名。
36
+ - `formProps: Object` 透传给 `naive-ui` `NForm`。
37
+ - `formItemProps: Object` 透传给每个 `NFormItem`。
38
+ - `dialog: boolean` 在弹窗场景下使用时自动附加样式。
39
+ - `rules: Object` 自定义校验规则;不传则根据 `options` 自动生成。
40
+
41
+ ## Options 关键字段
42
+ - `key` 必填,字段键名。支持数组键用于区间。
43
+ - `label` 显示文本。
44
+ - `way` 字段类型,默认 `input`。常用:`select`、`date`、`dateRange`、`time`、`radio`、`switch`、`uploadFile`、`image`、`dataTable` 等。
45
+ - `options / enum` 选择类数据。`enum` 会通过 `ObjectToArray` 转数组。
46
+ - `props` 透传到具体控件(如 `NInput`、`NSelect`)。
47
+ - `formItemProps` 透传到 `NFormItem`,可控制 label、样式、校验反馈等。
48
+ - `required / rule / message` 影响自动校验。
49
+ - `render` 自定义渲染,优先级最高。
50
+
51
+ ## 方法(defineExpose)
52
+ - `formRef` Naive UI `NForm` 实例引用。
53
+ - `getRule()` 获取自动生成的 rules。
54
+ - `valid(keyCode?: string[])` 返回 Promise,支持按键位校验。
55
+ - `confirm(fn)` 触发校验后执行回调。
56
+
57
+ ## 场景提示
58
+ - 自动校验逻辑由 `initRules` 提供,`required`/`rule`/`message` 会影响生成结果。
59
+ - 若需要动态选项,可在 `options` 内传入函数或 `ref`,组件内部会自动解包。
60
+ - 弹窗模式结合 `commonDialogMethod` 使用最少代码完成「表单 + 弹窗 + 校验 + 提交」。
61
+
@@ -0,0 +1,77 @@
1
+ ---
2
+ title: DataTable
3
+ ---
4
+
5
+ 基于 `naive-ui` `n-data-table` 的增强组件,提供列筛选、操作列、排序、虚拟滚动与省略。
6
+
7
+ ## 基础用法
8
+ ```vue
9
+ <script setup>
10
+ import { ref } from 'vue'
11
+ import { DataTable } from 'core'
12
+
13
+ const columns = [
14
+ { title: '名称', key: 'name', width: 160 },
15
+ { title: '类型', key: 'type', width: 120 },
16
+ ]
17
+ const data = ref([
18
+ { name: '苹果', type: '水果' },
19
+ { name: '可乐', type: '饮品' },
20
+ ])
21
+ </script>
22
+
23
+ <template>
24
+ <DataTable :data="data" :columns="columns" />
25
+ </template>
26
+ ```
27
+
28
+ ## Props(常用)
29
+ - `data: Array` 数据源。
30
+ - `columns: Array` 列定义,支持 `label`/`title`、`key`、`width`、`ellipsis`、`sorter` 等。
31
+ - `pagination: Object | null` 透传 `n-data-table` 分页。
32
+ - `oprColumns: Object | null` 右侧操作列配置。
33
+ - `selectColumns: Object | null` 选择列。
34
+ - `defaultColumns: Array` 默认可见列键。
35
+ - `summaryColumns: Function` 汇总行。
36
+ - `isFilter: boolean` 是否启用列筛选。
37
+ - `isEllipsis: boolean` 默认开启省略,使用内置 `ellipsis` tooltip。
38
+ - `virtual: boolean` 虚拟滚动,默认数据量大时自动开启。
39
+
40
+ ## 排序(orderEnum 内置工具)
41
+ `orderEnum` 专为 `DataTable` 列排序提供,离开表格场景单独调用无意义。
42
+
43
+ 用法示例(结合后端查询参数与分页刷新):
44
+ ```js
45
+ import { orderEnum } from 'core'
46
+
47
+ const listQuery = reactive({ sortFieldName: '', desc: false })
48
+ const pageState = {
49
+ fetchData: () => loadTableData(listQuery),
50
+ }
51
+
52
+ const columns = [
53
+ {
54
+ title: '创建时间',
55
+ key: 'createdAt',
56
+ width: 180,
57
+ sorter: (listQueryParam, pageStateParam, key) => {
58
+ // 选择升序/降序/默认时会进入这里
59
+ orderEnum.ascend.fn(listQueryParam, key) // 设置排序字段与方向
60
+ pageStateParam.fetchData() // 重新拉取数据
61
+ },
62
+ },
63
+ ]
64
+ ```
65
+
66
+ ## 列筛选弹窗
67
+ - 设定 `isFilter=true` 时,右上角会出现“筛选字段”按钮。
68
+ - 弹窗使用 `FilterDialog` 组件记录用户选择,结果存储于 `localStorage`,Key 为 `filter_key + 路由全路径`。
69
+
70
+ ## 省略
71
+ - 默认对列开启 `ellipsis`,使用 `core/table/utils/ellipsis` 配置 tooltip 样式。
72
+ - 可通过列的 `ellipsisProp` 自定义。
73
+
74
+ ## 操作列
75
+ - 可搭配 `createActionColumnJsx` 快速生成操作列,或直接传入 `oprColumns`。
76
+ - `useDataColumnButton` / `useDataColumnPop` 组合了按钮与二次确认的通用场景。
77
+
@@ -0,0 +1,78 @@
1
+ ---
2
+ title: commonDialogMethod
3
+ ---
4
+
5
+ 将表单、弹窗与动作按钮整合的快捷方法,底层使用 `$dialog` 与 `DataForm`。
6
+
7
+ ## 基础用法(用函数包裹触发)
8
+ `commonDialogMethod` 调用即会创建并打开弹窗,推荐用一个函数包裹,在需要时再触发:
9
+ ```js
10
+ import { commonDialogMethod } from 'core'
11
+
12
+ function openEditDialog(row) {
13
+ const { cancel, model } = commonDialogMethod(
14
+ {
15
+ title: '编辑',
16
+ options: [
17
+ { key: 'name', label: '名称', way: 'input', required: true },
18
+ { key: 'type', label: '类型', way: 'select', options: [{ label: 'A', value: 'a' }] },
19
+ ],
20
+ valueData: row,
21
+ interfaceFn: async (data, { close }) => {
22
+ await save(data)
23
+ close()
24
+ },
25
+ },
26
+ {
27
+ style: { width: '520px' },
28
+ },
29
+ )
30
+ return { cancel, model }
31
+ }
32
+
33
+ // 需要时再调用
34
+ openEditDialog(currentRow)
35
+ ```
36
+
37
+ ## 参数(主要)
38
+ - `title / noTitle / titleFull`:标题配置。
39
+ - `options: Array` 表单项,直接传给 `DataForm`。
40
+ - `mode` 与 `modeEnum`:内置 `create/add/edit/view/import/export/delete/copy/none`,`view` 会自动只读。
41
+ - `labelField`:默认 `label`。
42
+ - `isNo`:内容最小高度控制。
43
+ - `formProps`、`contentStyle`:透传 `DataForm`。
44
+ - `action`:自定义底部按钮数组或函数;不传则使用默认“取消 / 确定”。
45
+ - `actionProps`:NSpace/按钮样式补充。
46
+ - `interfaceFn`:点击默认“确定”时执行,入参 `(model, { close, hideLoading })`。
47
+ - `interfaceFnCancel`:点击默认“取消”时执行。
48
+ - `read / isRead`:只读模式。
49
+
50
+ ## 返回值
51
+ - `cancel()` 关闭弹窗。
52
+ - `setValue(v, key?)` 设置表单数据。
53
+ - `model` 响应式数据快照。
54
+ - `modeEnum` 默认模式枚举。
55
+
56
+ ## 自定义动作
57
+ ```js
58
+ commonDialogMethod({
59
+ action: [
60
+ { label: '关闭', mode: 'cancel' },
61
+ {
62
+ label: '提交',
63
+ valid: true, // 会执行 DataForm 校验
64
+ loading: true, // 自动切换 loading
65
+ async onClick({ model, cancel }) {
66
+ await save(model)
67
+ cancel()
68
+ },
69
+ },
70
+ ],
71
+ })
72
+ ```
73
+
74
+ ## 小贴士
75
+ - 表单校验委托给 `DataForm`,`valid: true` 时自动调用 `formRef.valid()`。
76
+ - 只读场景可用 `mode: 'view'`,或直接传 `read: true`。
77
+ - 若需要自定义 header,可传 `titleFull` 为渲染函数。
78
+
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: Options(动态项渲染)
3
+ ---
4
+
5
+ `Options` 负责根据配置渲染具体表单项,可单独使用,也被 `DataForm` 组合。
6
+
7
+ ## 基础用法
8
+ ```vue
9
+ <script setup>
10
+ import { ref } from 'vue'
11
+ import { Options } from 'core'
12
+
13
+ const model = ref({})
14
+ const formRef = ref()
15
+ const option = [
16
+ { key: 'name', label: '名称', way: 'input', required: true },
17
+ { key: 'age', label: '年龄', way: 'inputNumber', props: { min: 0 } },
18
+ {
19
+ key: 'tags',
20
+ label: '标签',
21
+ way: 'select',
22
+ props: { multiple: true },
23
+ options: [{ label: 'A', value: 'a' }],
24
+ },
25
+ ]
26
+ </script>
27
+
28
+ <template>
29
+ <Options v-model:value="model" :option="option" :form-ref="formRef" />
30
+ </template>
31
+ ```
32
+
33
+ ## Props
34
+ - `option: Array` 字段配置。
35
+ - `value (v-model:value): Object` 数据对象。
36
+ - `read: boolean` 只读模式。
37
+ - `labelField` / `valueField`:默认取全局常量 `globalLabelField` / `globalValueField`。
38
+ - `formRef`: 供内部校验、重置使用。
39
+ - `formProps`: 透传给外层布局。
40
+ - `style`: 根容器样式。
41
+
42
+ ## 配置字段说明
43
+ - `way`: 控件类型(input/select/date/time/dateRange/radio/switch/uploadFile/image/dataTable/button 等)。
44
+ - `default / prefix / suffix`: 支持函数或对象,组合渲染布局。
45
+ - `props`: 透传控件的属性,支持函数,入参包含 `formRef`、`setValue`。
46
+ - `formItemProps`: 透传 `NFormItem`,可控制 label/反馈/样式。
47
+ - `render`: 完全自定义渲染。
48
+ - `isRender`: 布尔或函数,控制是否渲染该项。
49
+ - `enum`: 对象形式的枚举,将被转换为数组。
50
+
51
+ ## Tips
52
+ - `options` 内的函数会收到当前表单值与 formRef,可做动态显隐、联动控制。
53
+ - 只读模式会在大多数字段内回显文本,而不渲染输入控件。
54
+ - `labelSuffix`/`labelSuffixProps` 支持传入图标(示例使用 `SvgIcon`)。
55
+
@@ -0,0 +1,49 @@
1
+ ---
2
+ title: CommonQuery
3
+ ---
4
+
5
+ 查询表单组件,基于 `DataForm` 封装,支持自动提交/重置按钮。
6
+
7
+ ## 基础用法
8
+ ```vue
9
+ <script setup>
10
+ import { ref } from 'vue'
11
+ import { CommonQuery } from 'core'
12
+
13
+ const query = ref({})
14
+ const options = [
15
+ { key: 'keyword', label: '关键词', way: 'input' },
16
+ { key: 'type', label: '类型', way: 'select', options: [{ label: 'A', value: 'a' }] },
17
+ ]
18
+
19
+ function onSubmit() {
20
+ // 根据 query.value 触发列表请求
21
+ }
22
+ </script>
23
+
24
+ <template>
25
+ <CommonQuery v-model:query="query" :options="options" @submit="onSubmit" />
26
+ </template>
27
+ ```
28
+
29
+ ## Props
30
+ - `options: Array` 查询项配置,规则同 `Options`。
31
+ - `query (v-model:query): Object` 查询对象。
32
+ - `inlineText: boolean` 布局控制。
33
+ - `selectCount: number` 默认 1。
34
+ - `type: string` 按钮类型(传给 `NButton`)。
35
+ - `noButton: boolean` 隐藏底部按钮区。
36
+ - `btn: string[]` 默认 `['reset', 'search']`。
37
+ - `size: string` 传入控件尺寸。
38
+ - `isRead: boolean` 只读。
39
+
40
+ ## 事件
41
+ - `update:query` 双向绑定。
42
+ - `submit` 点击搜索或回车触发(内置 500ms 防抖)。
43
+ - `reset` 重置查询模型。
44
+
45
+ ## 特性
46
+ - 默认监听全局 Enter 键以触发搜索。
47
+ - 为 `input`/`select` 自动绑定 `onUpdateValue`,输入即触发防抖搜索,可通过 `props.onUpdateValue` 自定义。
48
+ - `formProps` 默认关闭校验反馈,适合轻量搜索区域。
49
+
@@ -0,0 +1,56 @@
1
+ ---
2
+ title: 工具与常量
3
+ ---
4
+
5
+ ## 操作列 / 排序 / 省略
6
+
7
+ ### createActionColumnJsx
8
+ 快速生成表格操作列。
9
+
10
+ ```js
11
+ import { createActionColumnJsx } from 'core'
12
+
13
+ const oprColumn = createActionColumnJsx(
14
+ [
15
+ { label: '查看', onClick: (row) => view(row) },
16
+ { label: '删除', mode: 'pop', onClick: (row) => remove(row) },
17
+ ],
18
+ { fixed: 'right' },
19
+ { max: 3 }, // collectParams:超过数量折叠
20
+ )
21
+ ```
22
+
23
+ ### orderEnum(表格内部用)
24
+ - 来源:`src/enum/sort.jsx`,通过 `DataTable` 列的 `sorter` 使用。
25
+ - 功能:提供升序/降序/默认三态的图标与处理函数,修改 `listQuery` 的排序字段并配合重新拉取数据。
26
+ - 注意:离开 `DataTable` 排序场景单独调用无意义;详细示例见 `DataTable` 文档中的排序段落。
27
+
28
+ ### ellipsis
29
+ 表格省略 tooltip 配置:
30
+ ```js
31
+ import { ellipsis } from 'core/table/utils/ellipsis'
32
+ ```
33
+
34
+ ## 上传工具
35
+ ```js
36
+ import { registryUpload, customUpload, getFileUrl } from 'core'
37
+
38
+ registryUpload((config) => axios.request(config)) // 注册实际上传实现
39
+ await customUpload({ url: '/upload', data: file })
40
+ const url = getFileUrl('/path/to/file', 200) // 拼接 OSS 样式
41
+ ```
42
+
43
+ ## 权限与路由
44
+ - `useAuthPermission(...routeNames)` / `useApiConfig(...routeNames)`:读取路由 meta 中的 `auth` / `api`。
45
+ - `cellectChildenPermission(route)`:合并子路由权限到父节点。
46
+ - `initRouteMeta(routes, base?)`:补全 `meta.title`、`meta.permission`、`sourceFullPath` 等。
47
+ - `handleParams(str, map)`:替换路径参数。
48
+
49
+ ## 数据工具
50
+ - `toArray(value)`:非数组包装成数组。
51
+ - `ArrayToObject(arr, { labelField, valueField })`:数组转对象映射。
52
+ - `ObjectToArray(obj, { labelField, valueField })`:对象转数组。
53
+
54
+ ## 类型
55
+ 库内提供 `types/index.d.ts`,涵盖组件、方法与工具的基础类型,可在 TS 项目中直接获得提示。
56
+
@@ -0,0 +1,213 @@
1
+ ---
2
+ title: 示例 Demo 说明
3
+ ---
4
+
5
+ ## 本地预览 Demo
6
+
7
+ 项目内提供 `examples/demo.vue`,包含 `DataForm`、`DataTable`、`commonDialogMethod` 的最小示例。
8
+
9
+ ### 运行方式
10
+
11
+ 1) 确认已安装依赖:
12
+ ```bash
13
+ npm install
14
+ ```
15
+
16
+ 2) 在你的宿主工程中引入该组件文件(或复制内容),确保存在以下 alias:
17
+ ```js
18
+ // vite / webpack 示例
19
+ resolve: {
20
+ alias: {
21
+ '@': path.resolve(__dirname, 'src'),
22
+ core: path.resolve(__dirname, 'src'),
23
+ },
24
+ }
25
+ ```
26
+
27
+ 3) 在页面中引用 `examples/demo.vue`,即可直接运行。
28
+
29
+ ## 预览文档站点
30
+
31
+ 项目内已配置 VitePress:
32
+
33
+ ```bash
34
+ npm run docs:dev # 本地启动文档
35
+ npm run docs:build # 生成静态文档
36
+ npm run docs:preview # 预览打包产物
37
+ ```
38
+
39
+ 生成的静态文件位于 `.vitepress/dist`,可部署到 GitHub Pages / 其他静态托管服务。
40
+
41
+ ## 小贴士
42
+ - 需要更多自定义场景,可在 `examples/` 下新增页面,并在文档中添加入口链接。
43
+ - 若使用 GitHub Actions 部署,可直接在构建步骤运行 `npm run docs:build` 后推送 `.vitepress/dist`。
44
+
45
+ ## 标准后台列表页示例
46
+ 典型布局:头部筛选区 + 操作区 + 内容表格区(含弹窗操作)。`DataTable` 本身是 flex 元素,会在容器内自适应填满。
47
+
48
+ ```vue
49
+ <script setup lang="jsx">
50
+ import AddButton from '@/components/button/AddButton.jsx'
51
+ import { useNaivePage } from '@/use/useNaivePage'
52
+ import { onMounted, ref } from 'vue'
53
+ import {
54
+ commonDialogMethod,
55
+ CommonQuery,
56
+ createActionColumnJsx,
57
+ DataTable,
58
+ } from 'core'
59
+
60
+ // 列表数据与查询管理
61
+ const { pageState, listQuery } = useNaivePage(() => {
62
+ listQuery.desc = true
63
+ // 示例:请求数据
64
+ // fetchList(listQuery)
65
+ // .then(res => {
66
+ // pageState.data = res.data.records
67
+ // pageState.itemCount = res.data.total
68
+ // })
69
+ // .finally(pageState.hideLoading)
70
+ })
71
+
72
+ // 头部查询项
73
+ const keyQuery = [
74
+ { label: '名称1', key: 'name1', queryType: 'likeQuery' },
75
+ { label: '名称2', key: 'name2', queryType: 'likeQuery' },
76
+ { label: '名称3', key: 'name3', queryType: 'likeQuery' },
77
+ ]
78
+
79
+ // 表格列与操作列
80
+ const columns = []
81
+ const defaultColumns = []
82
+ const selectColumns = { type: 'selection', width: '40px' }
83
+ const opr = createActionColumnJsx([
84
+ {
85
+ label: '编辑',
86
+ type: 'primary',
87
+ onClick: row => onAdd(row),
88
+ },
89
+ {
90
+ label: '删除',
91
+ type: 'error',
92
+ mode: 'pop',
93
+ onClick: (row) => {
94
+ // del(row.id).then(() => pageState.fetchData())
95
+ },
96
+ },
97
+ ])
98
+
99
+ // 弹窗新增/编辑
100
+ function onAdd(row = null, mode = 'add') {
101
+ commonDialogMethod({
102
+ title: '示例弹窗',
103
+ mode,
104
+ options: [], // 这里填入 DataForm 配置
105
+ valueData: { ...row },
106
+ interfaceFn: (data, { close }) => {
107
+ // save(data).then(() => { pageState.fetchData(); close() })
108
+ },
109
+ })
110
+ }
111
+
112
+ // 导出示例
113
+ const exportLoading = ref(false)
114
+ function onExport() {
115
+ exportLoading.value = true
116
+ // exportApi(listQuery).finally(() => (exportLoading.value = false))
117
+ }
118
+
119
+ onMounted(() => pageState.fetchData())
120
+ </script>
121
+
122
+ <template>
123
+ <div class="page-box">
124
+ <!-- 头部筛选 -->
125
+ <n-card class="page-head">
126
+ <CommonQuery
127
+ :query="listQuery"
128
+ :options="keyQuery"
129
+ @submit="pageState.search()"
130
+ @reset="pageState.reset()"
131
+ />
132
+ </n-card>
133
+
134
+ <!-- 操作区 -->
135
+ <n-space justify="space-between">
136
+ <n-space>
137
+ <AddButton @click="onAdd()">新增</AddButton>
138
+ <n-button type="primary" :loading="exportLoading" @click="onExport">
139
+ 导出
140
+ </n-button>
141
+ </n-space>
142
+ </n-space>
143
+
144
+ <!-- 内容表格区 -->
145
+ <div class="page-main">
146
+ <DataTable
147
+ :data="pageState.data"
148
+ :pagination="pageState"
149
+ :columns="columns"
150
+ :opr-columns="opr"
151
+ :default-columns="defaultColumns"
152
+ :row-key="row => row?.id"
153
+ :select-columns="selectColumns"
154
+ :loading="pageState.loading"
155
+ />
156
+ </div>
157
+ </div>
158
+ </template>
159
+
160
+ <style scoped lang="less">
161
+ .page-head {
162
+ border-radius: 8px;
163
+ background-color: #fff;
164
+ box-sizing: border-box;
165
+ display: flex;
166
+ flex-direction: column;
167
+ row-gap: 20px;
168
+ }
169
+
170
+ .page-main {
171
+ flex: 0 1 auto;
172
+ background-color: #fff;
173
+ border-radius: 8px;
174
+ padding: 20px;
175
+ box-sizing: border-box;
176
+ display: flex;
177
+ height: 100%;
178
+ flex-direction: column;
179
+ row-gap: 10px;
180
+
181
+ .n-data-table {
182
+ .n-data-table-th {
183
+ background-color: #f7f8fa;
184
+ border-right: 1px solid var(--n-merged-border-color);
185
+ white-space: break-spaces;
186
+ }
187
+ .n-data-table-th--last {
188
+ border-right: 1px solid transparent;
189
+ }
190
+ .n-data-table-td--last-row {
191
+ border-bottom: 1px solid var(--n-merged-border-color);
192
+ }
193
+ }
194
+ }
195
+
196
+ .page-box {
197
+ display: flex;
198
+ flex-direction: column;
199
+ height: calc(100vh - 120px); // 可按实际头/标签高度调整
200
+ margin: -16px;
201
+ padding: 24px;
202
+ box-sizing: border-box;
203
+ overflow: hidden;
204
+ row-gap: 20px;
205
+ }
206
+ </style>
207
+ ```
208
+
209
+ > 说明:
210
+ > - `.page-box / .page-head / .page-main` 可抽成全局布局样式复用。
211
+ > - `DataTable` 是 flex 元素,会在容器内自适应填满;容器需设置高度或弹性布局。
212
+ > - 示例中的接口调用、列配置、表单 options 需按业务填充。
213
+
@@ -0,0 +1,77 @@
1
+ ---
2
+ title: 快速开始
3
+ ---
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install core
9
+ ```
10
+
11
+ 同时请在项目中安装(或确保已存在)以下 peer 依赖(版本可按你项目统一):
12
+
13
+ - vue 3.x
14
+ - naive-ui
15
+ - vue-router
16
+ - dayjs
17
+ - lodash-es
18
+ - @vicons/ionicons5
19
+
20
+ > 若项目使用 `@` 路径别名,请确认在构建/运行配置中存在相同的 alias。
21
+
22
+ ## 引入与基本使用
23
+
24
+ ```vue
25
+ <script setup>
26
+ import { ref } from 'vue'
27
+ import { DataForm, DataTable, commonDialogMethod } from 'core'
28
+ import 'core/dist/style.css' // 如需默认样式
29
+
30
+ const formValue = ref({})
31
+ const formOptions = [
32
+ { key: 'name', label: '名称', way: 'input', required: true },
33
+ { key: 'type', label: '类型', way: 'select', options: [{ label: 'A', value: 'a' }] },
34
+ ]
35
+
36
+ const tableColumns = [
37
+ { title: '名称', key: 'name', width: 160 },
38
+ { title: '类型', key: 'type', width: 100 },
39
+ ]
40
+ const tableData = ref([{ name: '示例', type: 'a' }])
41
+
42
+ function openDialog() {
43
+ commonDialogMethod({
44
+ title: '示例弹窗',
45
+ options: formOptions,
46
+ valueData: { name: '张三' },
47
+ interfaceFn: async () => {
48
+ // 这里提交数据
49
+ },
50
+ })
51
+ }
52
+ </script>
53
+
54
+ <template>
55
+ <div class="p-16">
56
+ <DataForm v-model:value="formValue" :options="formOptions" />
57
+ <DataTable :data="tableData" :columns="tableColumns" style="margin-top: 12px" />
58
+ <button @click="openDialog">打开弹窗</button>
59
+ </div>
60
+ </template>
61
+ ```
62
+
63
+ ## 目录结构建议
64
+
65
+ ```
66
+ docs/ # VitePress 文档
67
+ examples/demo.vue # 可运行的最小示例
68
+ src/ # 组件与工具源码
69
+ types/ # 类型定义
70
+ ```
71
+
72
+ ## 常见问题
73
+
74
+ - 找不到 `@/utils/...`:请在宿主项目配置 `@` 别名或提供对应实现。
75
+ - 样式缺失:如需库内 less 默认样式,确保引入 `core/dist/style.css`。
76
+ - TS 类型:库内已内置 `types/index.d.ts`,可直接获得基础提示。
77
+