@oneflowui/ui 0.4.4 → 0.5.0
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.
- package/README.en.md +1 -1
- package/README.md +70 -0
- package/dist/components/database/DatabaseView.vue.d.ts +171 -0
- package/dist/components/database/DatabaseView.vue.js +7 -0
- package/dist/components/database/DatabaseView.vue2.js +774 -0
- package/dist/components/database/index.d.ts +2 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/useDatabaseView.d.ts +138 -0
- package/dist/composables/useDatabaseView.js +388 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +178 -173
- package/dist/style.css +1 -1
- package/dist/tests/database-view.integration.spec.d.ts +1 -0
- package/package.json +17 -17
package/README.en.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/@oneflowui/ui)
|
|
5
5
|
[](https://github.com/qixi54/oneui/blob/main/LICENSE)
|
|
6
6
|
|
|
7
|
-
A **Vue 3 + TypeScript**
|
|
7
|
+
A **Vue 3 + TypeScript** UI library for building task management and productivity applications. It now includes a page-level `DatabaseView` solution on top of the component layer.
|
|
8
8
|
|
|
9
9
|
> [中文文档](./README.md)
|
|
10
10
|
|
package/README.md
CHANGED
|
@@ -97,6 +97,76 @@ import '@oneflowui/ui/styles'
|
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
100
|
+
## 页面级方案
|
|
101
|
+
|
|
102
|
+
当前已经支持直接从包里接入页面级入口:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { DatabaseView, useDatabaseView } from '@oneflowui/ui'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`DatabaseView` 负责统一页面容器,`useDatabaseView` 负责页面状态编排。`dev` app 也已经接入这条链路,
|
|
109
|
+
用于证明 `local/provider` 双模式、视图切换、selected record 与 detail workspace 可以在同一页面层里闭环。
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
const view = useDatabaseView({
|
|
113
|
+
mode: 'provider',
|
|
114
|
+
schemaSource,
|
|
115
|
+
dataSource,
|
|
116
|
+
actions: {
|
|
117
|
+
onFetch,
|
|
118
|
+
onRefresh,
|
|
119
|
+
onUpdateRecord,
|
|
120
|
+
onCreateRecord,
|
|
121
|
+
onDeleteRecord,
|
|
122
|
+
onSaveView,
|
|
123
|
+
onSchemaChange,
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 模式
|
|
129
|
+
|
|
130
|
+
- `local` 模式:外部直接传 `schema + records + view`,页面只负责筛选、排序、切视图和展示状态,不触发远程请求。
|
|
131
|
+
- `provider` 模式:外部传入数据获取/刷新能力,页面 shell 只消费 provider 返回的 `schema / records / views`,不绑定具体后端实现。
|
|
132
|
+
|
|
133
|
+
### actions 契约
|
|
134
|
+
|
|
135
|
+
页面级方案只回传动作,不在组件内部写死业务逻辑。常见契约如下:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
type DatabaseViewActions = {
|
|
139
|
+
onFetch?: (params: { viewId: string }) => Promise<void> | void
|
|
140
|
+
onRefresh?: () => Promise<void> | void
|
|
141
|
+
onUpdateRecord?: (recordId: string, patch: Record<string, unknown>) => Promise<void> | void
|
|
142
|
+
onCreateRecord?: (record: Record<string, unknown>) => Promise<void> | void
|
|
143
|
+
onDeleteRecord?: (recordId: string) => Promise<void> | void
|
|
144
|
+
onSaveView?: (viewId: string, payload: Record<string, unknown>) => Promise<void> | void
|
|
145
|
+
onSchemaChange?: (payload: Record<string, unknown>) => Promise<void> | void
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
如果接入的是 `provider` 模式,建议把 `onFetch` / `onRefresh` 作为必配项;如果接入的是 `local` 模式,则重点只需要保证 `onUpdateRecord`、`onCreateRecord`、`onDeleteRecord` 和 `onSaveView` 这几类页面动作可回传。
|
|
150
|
+
|
|
151
|
+
### Selected record / detail workspace
|
|
152
|
+
|
|
153
|
+
当前 dev app 已经把“选中记录 -> detail workspace”这条链路接起来了:点击 table / kanban / gallery / timeline 中的条目,会把当前记录送入详情工作区,再由 `DetailLayout`、`PropPanel`、`CommentItem` 这组组件展示主内容、属性和活动记录。
|
|
154
|
+
|
|
155
|
+
这证明页面级方案已经具备“列表视图 + 选中态 + 详情工作区”的最小闭环,并且可以作为业务页面底座直接接入。
|
|
156
|
+
|
|
157
|
+
### 已支持 / 暂未支持
|
|
158
|
+
|
|
159
|
+
| 已支持 | 暂未支持 |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `local/provider` 两种模式的页面壳层接入 | 真实 provider 数据闭环、权限与持久化策略 |
|
|
162
|
+
| `normal / loading / empty / error` 四态透传 | 写操作的最终落库与回滚编排 |
|
|
163
|
+
| `table / kanban / gallery / timeline` 多视图切换 | 可编辑 detail workspace 的最终保存、ACL、schema 管理后台 |
|
|
164
|
+
| `search / filter / sort / group / save-view / load-view` 工具栏契约 | 远程视图保存、跨端同步与更重的页面编排 |
|
|
165
|
+
| `schema + records + viewConfig` 数据驱动 | 业务应用侧自定义的 provider 适配层 |
|
|
166
|
+
| `selected record -> detail workspace` 页面链路 | detail 编辑后的最终提交、乐观更新、冲突处理 |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
100
170
|
## 组件一览
|
|
101
171
|
|
|
102
172
|
| 分类 | 组件 |
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Component } from 'vue';
|
|
2
|
+
import { DatabaseViewActions as ViewDatabaseActions, DatabaseViewMode, DatabaseSchemaEvent, DatabaseViewProvider as ViewDatabaseProvider } from '../../composables/useDatabaseView';
|
|
3
|
+
import { FilterLogic } from '../../composables/useTableFilter';
|
|
4
|
+
import { DataRecord, TableColumn, TableSchema, ViewConfig } from '../../types';
|
|
5
|
+
export interface DatabaseViewViewTab {
|
|
6
|
+
value: string;
|
|
7
|
+
label: string;
|
|
8
|
+
icon?: string | Component;
|
|
9
|
+
}
|
|
10
|
+
export type DatabaseViewSchemaEvent = DatabaseSchemaEvent;
|
|
11
|
+
export interface DatabaseViewActions extends ViewDatabaseActions<DataRecord> {
|
|
12
|
+
onViewChange?: (payload: {
|
|
13
|
+
tableId: string;
|
|
14
|
+
view: ViewConfig;
|
|
15
|
+
}) => void | Promise<void>;
|
|
16
|
+
onViewLoad?: (payload: {
|
|
17
|
+
tableId: string;
|
|
18
|
+
viewId: string;
|
|
19
|
+
}) => void | Promise<void>;
|
|
20
|
+
onViewSave?: (payload: {
|
|
21
|
+
tableId: string;
|
|
22
|
+
viewId: string;
|
|
23
|
+
name: string;
|
|
24
|
+
}) => void | Promise<void>;
|
|
25
|
+
onRecordChange?: (payload: {
|
|
26
|
+
tableId: string;
|
|
27
|
+
recordId: string;
|
|
28
|
+
startDate?: string;
|
|
29
|
+
endDate?: string;
|
|
30
|
+
}) => void | Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
export interface DatabaseViewUiOptions {
|
|
33
|
+
enableFieldManagement?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface DatabaseViewProps {
|
|
36
|
+
tableId?: string;
|
|
37
|
+
mode?: DatabaseViewMode;
|
|
38
|
+
schema?: TableSchema | null;
|
|
39
|
+
records?: DataRecord[];
|
|
40
|
+
views?: ViewConfig[];
|
|
41
|
+
provider?: ViewDatabaseProvider<DataRecord>;
|
|
42
|
+
defaultView?: ViewConfig;
|
|
43
|
+
currentViewId?: string;
|
|
44
|
+
initialViewId?: string;
|
|
45
|
+
selectedRecordId?: string | null;
|
|
46
|
+
initialSelectedRecordId?: string | null;
|
|
47
|
+
searchKeyword?: string;
|
|
48
|
+
loading?: boolean;
|
|
49
|
+
error?: string | Error | null;
|
|
50
|
+
viewTabs?: DatabaseViewViewTab[];
|
|
51
|
+
actions?: DatabaseViewActions;
|
|
52
|
+
ui?: DatabaseViewUiOptions;
|
|
53
|
+
showToolbar?: boolean;
|
|
54
|
+
showViewSwitch?: boolean;
|
|
55
|
+
showFilter?: boolean;
|
|
56
|
+
showSort?: boolean;
|
|
57
|
+
showGroup?: boolean;
|
|
58
|
+
showColumns?: boolean;
|
|
59
|
+
showSearch?: boolean;
|
|
60
|
+
readonly?: boolean;
|
|
61
|
+
pageSize?: number;
|
|
62
|
+
autoLoad?: boolean;
|
|
63
|
+
}
|
|
64
|
+
declare const _default: import('vue').DefineComponent<DatabaseViewProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
65
|
+
sort: (args_0: string) => any;
|
|
66
|
+
add: () => any;
|
|
67
|
+
group: (args_0: string | null) => any;
|
|
68
|
+
"row-click": (args_0: unknown) => any;
|
|
69
|
+
"cell-edit": (args_0: {
|
|
70
|
+
rowId: string;
|
|
71
|
+
fieldId: string;
|
|
72
|
+
value: unknown;
|
|
73
|
+
}) => any;
|
|
74
|
+
"schema-add-field": (args_0: string) => any;
|
|
75
|
+
"schema-rename-field": (args_0: {
|
|
76
|
+
fieldId: string;
|
|
77
|
+
newName: string;
|
|
78
|
+
}) => any;
|
|
79
|
+
"schema-change-field-type": (args_0: {
|
|
80
|
+
fieldId: string;
|
|
81
|
+
newType: string;
|
|
82
|
+
}) => any;
|
|
83
|
+
"schema-hide-field": (args_0: string) => any;
|
|
84
|
+
"schema-delete-field": (args_0: string) => any;
|
|
85
|
+
"schema-duplicate-field": (args_0: string) => any;
|
|
86
|
+
"update:columns": (args_0: TableColumn[]) => any;
|
|
87
|
+
"update:searchKeyword": (args_0: string) => any;
|
|
88
|
+
"update:filterLogic": (args_0: FilterLogic) => any;
|
|
89
|
+
"save-view": (args_0: string) => any;
|
|
90
|
+
"load-view": (args_0: string) => any;
|
|
91
|
+
"card-click": (args_0: unknown) => any;
|
|
92
|
+
"record-change": (args_0: {
|
|
93
|
+
recordId: string;
|
|
94
|
+
startDate?: string;
|
|
95
|
+
endDate?: string;
|
|
96
|
+
}) => any;
|
|
97
|
+
"update:records": (args_0: DataRecord[]) => any;
|
|
98
|
+
"add-column": () => any;
|
|
99
|
+
"update:currentViewId": (args_0: string) => any;
|
|
100
|
+
"update:selectedRecordId": (args_0: string | null) => any;
|
|
101
|
+
"select-record": (args_0: DataRecord | null) => any;
|
|
102
|
+
refresh: () => any;
|
|
103
|
+
}, string, import('vue').PublicProps, Readonly<DatabaseViewProps> & Readonly<{
|
|
104
|
+
onSort?: ((args_0: string) => any) | undefined;
|
|
105
|
+
onAdd?: (() => any) | undefined;
|
|
106
|
+
onGroup?: ((args_0: string | null) => any) | undefined;
|
|
107
|
+
"onRow-click"?: ((args_0: unknown) => any) | undefined;
|
|
108
|
+
"onCell-edit"?: ((args_0: {
|
|
109
|
+
rowId: string;
|
|
110
|
+
fieldId: string;
|
|
111
|
+
value: unknown;
|
|
112
|
+
}) => any) | undefined;
|
|
113
|
+
"onSchema-add-field"?: ((args_0: string) => any) | undefined;
|
|
114
|
+
"onSchema-rename-field"?: ((args_0: {
|
|
115
|
+
fieldId: string;
|
|
116
|
+
newName: string;
|
|
117
|
+
}) => any) | undefined;
|
|
118
|
+
"onSchema-change-field-type"?: ((args_0: {
|
|
119
|
+
fieldId: string;
|
|
120
|
+
newType: string;
|
|
121
|
+
}) => any) | undefined;
|
|
122
|
+
"onSchema-hide-field"?: ((args_0: string) => any) | undefined;
|
|
123
|
+
"onSchema-delete-field"?: ((args_0: string) => any) | undefined;
|
|
124
|
+
"onSchema-duplicate-field"?: ((args_0: string) => any) | undefined;
|
|
125
|
+
"onUpdate:columns"?: ((args_0: TableColumn[]) => any) | undefined;
|
|
126
|
+
"onUpdate:searchKeyword"?: ((args_0: string) => any) | undefined;
|
|
127
|
+
"onUpdate:filterLogic"?: ((args_0: FilterLogic) => any) | undefined;
|
|
128
|
+
"onSave-view"?: ((args_0: string) => any) | undefined;
|
|
129
|
+
"onLoad-view"?: ((args_0: string) => any) | undefined;
|
|
130
|
+
"onCard-click"?: ((args_0: unknown) => any) | undefined;
|
|
131
|
+
"onRecord-change"?: ((args_0: {
|
|
132
|
+
recordId: string;
|
|
133
|
+
startDate?: string;
|
|
134
|
+
endDate?: string;
|
|
135
|
+
}) => any) | undefined;
|
|
136
|
+
"onUpdate:records"?: ((args_0: DataRecord[]) => any) | undefined;
|
|
137
|
+
"onAdd-column"?: (() => any) | undefined;
|
|
138
|
+
"onUpdate:currentViewId"?: ((args_0: string) => any) | undefined;
|
|
139
|
+
"onUpdate:selectedRecordId"?: ((args_0: string | null) => any) | undefined;
|
|
140
|
+
"onSelect-record"?: ((args_0: DataRecord | null) => any) | undefined;
|
|
141
|
+
onRefresh?: (() => any) | undefined;
|
|
142
|
+
}>, {
|
|
143
|
+
mode: DatabaseViewMode;
|
|
144
|
+
error: string | Error | null;
|
|
145
|
+
showFilter: boolean;
|
|
146
|
+
showGroup: boolean;
|
|
147
|
+
showSort: boolean;
|
|
148
|
+
showSearch: boolean;
|
|
149
|
+
actions: DatabaseViewActions;
|
|
150
|
+
readonly: boolean;
|
|
151
|
+
pageSize: number;
|
|
152
|
+
records: DataRecord[];
|
|
153
|
+
schema: TableSchema | null;
|
|
154
|
+
viewTabs: DatabaseViewViewTab[];
|
|
155
|
+
searchKeyword: string;
|
|
156
|
+
showViewSwitch: boolean;
|
|
157
|
+
showColumns: boolean;
|
|
158
|
+
loading: boolean;
|
|
159
|
+
tableId: string;
|
|
160
|
+
views: ViewConfig[];
|
|
161
|
+
provider: ViewDatabaseProvider<DataRecord>;
|
|
162
|
+
defaultView: ViewConfig;
|
|
163
|
+
currentViewId: string;
|
|
164
|
+
initialViewId: string;
|
|
165
|
+
selectedRecordId: string | null;
|
|
166
|
+
initialSelectedRecordId: string | null;
|
|
167
|
+
ui: DatabaseViewUiOptions;
|
|
168
|
+
showToolbar: boolean;
|
|
169
|
+
autoLoad: boolean;
|
|
170
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
171
|
+
export default _default;
|