@ctzy-web-client/data-model 1.0.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.
@@ -0,0 +1,63 @@
1
+ import DataColumn from './DataColumn';
2
+
3
+ /**
4
+ * 表单列定义
5
+ */
6
+ export default class FormColumn extends DataColumn {
7
+ /**
8
+ * @member {String} 提交的字段名称
9
+ */
10
+ submitName = '';
11
+
12
+ /**
13
+ * @param {Array<Object>} 验证规则
14
+ */
15
+ rules = [];
16
+
17
+ /**
18
+ * @param {Boolean} 是否必填
19
+ */
20
+ required = true;
21
+
22
+ // /**
23
+ // * @member {String} 字段填充时 若服务端返回 空值 NULL值时显示的内容 默认 ""
24
+ // */
25
+ // default = '';
26
+
27
+ disabled = false;
28
+
29
+ /**
30
+ * 注入
31
+ * @param {Object} options 配置
32
+ * @param {String} options.name 字段名称
33
+ * @param {String} options.title 字段标题
34
+ * @param {String} options.default 表单默认提交的值
35
+ * @param {String} options.helpMsg 表单列帮助提示
36
+ * @param {String} options.rules 字段提交时验证规则 数组等价el的表单的rule写法
37
+ * @param {Boolean} options.required 字段是否必填 默认:false
38
+ * @param {Boolean} options.visible 字段在渲染组件里是否渲染 默认:true
39
+ * @param {Object|Function|String} options.component 字段在组件里面渲染的所用到的组件,可以是组件对象,字符串,或者方法,工厂方法必然返回vnode 默认:无,
40
+ * @param {Object|Function} options.componentProps 字段在组件中渲染所需要的配置参数,如果是函数的话函数的第一个参数会返回当前数据列对象和当前行数据,此时可动态返回所需参数
41
+ *
42
+ * @returns
43
+ */
44
+ constructor(options = {}) {
45
+ super(options);
46
+ this.submitName = options?.submitName ?? this.submitName;
47
+ this.rules = options?.rules ?? this.rules;
48
+ this.required = options?.required ?? this.required;
49
+ this.disabled = options?.disabled ?? this.componentProps?.disabled ?? false;
50
+
51
+ if (this.componentProps && typeof this.componentProps === 'object') {
52
+ Reflect.deleteProperty(this.componentProps, 'disabled');
53
+ }
54
+ }
55
+
56
+ disable() {
57
+ this.disabled = true;
58
+ }
59
+
60
+ enable() {
61
+ this.disabled = false;
62
+ }
63
+ }
@@ -0,0 +1,83 @@
1
+ import DataColumn from './DataColumn';
2
+
3
+ const DEFAULT_SETTINGS = {
4
+ visible: true,
5
+ disabled: false,
6
+ };
7
+
8
+ /**
9
+ * 表格列定义
10
+ */
11
+ export default class TableColumn extends DataColumn {
12
+ /**
13
+ * @member {String} 宽度
14
+ */
15
+ width = 'auto';
16
+
17
+ formComponent = '';
18
+
19
+ /**
20
+ * @member {String} 对齐方式
21
+ */
22
+ align = 'center';
23
+
24
+ /**
25
+ * @member {String} 字段根据不同的数据类型格式化的规则:d:2,s:5,yyyy-MM-dd hh:mm:ss 默认:无
26
+ */
27
+ rule = '';
28
+
29
+ /**
30
+ * @member {String} 字符串模板 "${value}$"
31
+ */
32
+ template = '${value}';
33
+
34
+ /**
35
+ * @member {String} 字段的数据类型 number|string|image|video|audio|date|html 默认:string
36
+ */
37
+ type = 'string';
38
+
39
+ /**
40
+ * @member {Object} 设置表头的基本信息
41
+ */
42
+ settings = null;
43
+
44
+ // /**
45
+ // * @member {String} 字段填充时 若服务端返回 空值 NULL值时显示的内容 默认 "-"
46
+ // */
47
+ // default = '-';
48
+ /**
49
+ * @member {String} 设置排序
50
+ */
51
+ sortable = '';
52
+
53
+
54
+ /**
55
+ * 注入
56
+ * @param {Object} options 配置
57
+ * @param {String} options.name 字段名称
58
+ * @param {String} options.title 字段标题
59
+ * @param {String} options.default 字段填充时 若服务端返回 空值 NULL值时显示的内容 默认 "-"
60
+ * @param {String} options.width 字段在组件里面显示的宽度 默认:auto
61
+ * @param {String} options.align 字段在组件里面显示的对齐方式 默认:center
62
+ * @param {Boolean} options.visible 字段在渲染组件里是否渲染 默认:true
63
+ * @param {String} options.type 字段的数据类型 number|string|image|video|audio|date|html 默认:string
64
+ * @param {String} options.rule 字段根据不同的数据类型格式化的规则:d:2,s:5,yyyy-MM-dd hh:mm:ss 默认:无
65
+ * @param {String} options.template 字符串模板 "啊啊啊啊${value}$"
66
+ * @param {Object|Function|String} options.component 字段在组件里面渲染的所用到的组件,可以是组件对象,字符串,或者方法,工厂方法必然返回vnode 默认:无,
67
+ * @param {Object|Function} options.componentProps 字段在组件中渲染所需要的配置参数,如果是函数的话函数的第一个参数会返回当前数据列对象和当前行数据,此时可动态返回所需参数
68
+ *
69
+ * @returns
70
+ */
71
+ constructor(options = {}) {
72
+ super(options);
73
+ this.width = options?.width ?? this.width;
74
+ this.formComponent = options.formComponent ?? this.formComponent;
75
+ this.align = options?.align ?? this.align;
76
+ this.rule = options?.rule ?? this.rule;
77
+ this.template = options?.template ?? this.template;
78
+ this.type = options?.type ?? this.type;
79
+ this.default = options?.default ?? '-';
80
+ this.settings = { ...DEFAULT_SETTINGS, ...options?.settings };
81
+ this.sortable = options?.sortable ?? this.sortable;
82
+ }
83
+ }
@@ -0,0 +1,115 @@
1
+ import { Condition } from './Condition';
2
+ import { SingleCondition } from './SingleCondition';
3
+
4
+ export class CombineCondition extends Condition {
5
+ /** @type {Array<Condition|string>} */
6
+ conditions = [];
7
+
8
+ /**
9
+ * @param {string} fieldName
10
+ * @param {string} operator
11
+ * @param {any} value
12
+ * @return {SingleCondition}
13
+ * @memberof CombineCondition
14
+ */
15
+ addCondition(fieldName, operator, value) {
16
+ const condition = new SingleCondition(fieldName, operator, value);
17
+
18
+ if (this.conditions.length) {
19
+ this.conditions.push('AND');
20
+ }
21
+
22
+ this.conditions.push(condition);
23
+
24
+ return condition;
25
+ }
26
+
27
+ /**
28
+ * @param {string} fieldName
29
+ * @param {string} operator
30
+ * @param {any} value
31
+ * @return {SingleCondition}
32
+ * @memberof CombineCondition
33
+ */
34
+ addOrCondition(fieldName, operator, value) {
35
+ const condition = new SingleCondition(fieldName, operator, value);
36
+
37
+ if (this.conditions.length) {
38
+ this.conditions.push('OR');
39
+ }
40
+
41
+ this.conditions.push(condition);
42
+
43
+ return condition;
44
+ }
45
+
46
+ /**
47
+ * @param {CombineCondition} group
48
+ * @return {CombineCondition}
49
+ * @memberof CombineCondition
50
+ */
51
+ addGroup(group) {
52
+ const _group = group || new CombineCondition();
53
+
54
+ if (this.conditions.length) {
55
+ this.conditions.push('AND');
56
+ }
57
+
58
+ this.conditions.push(_group);
59
+
60
+ return _group;
61
+ }
62
+
63
+ /**
64
+ * @param {CombineCondition} group
65
+ * @return {CombineCondition}
66
+ * @memberof CombineCondition
67
+ */
68
+ addOrGroup(group) {
69
+ const _group = group || new CombineCondition();
70
+
71
+ if (this.conditions.length) {
72
+ this.conditions.push('OR');
73
+ }
74
+
75
+ this.conditions.push(_group);
76
+
77
+ return _group;
78
+ }
79
+
80
+ removeCondition(fieldName) {
81
+ let index = this.conditions.findIndex(
82
+ (condition) =>
83
+ condition instanceof SingleCondition && condition.f === fieldName
84
+ );
85
+
86
+ if (index === 0) {
87
+ this.conditions.splice(index, 1);
88
+ return;
89
+ }
90
+
91
+ this.conditions.splice(index - 1, 2);
92
+
93
+ const combineConditions = this.conditions.filter(
94
+ (condition) => condition instanceof CombineCondition
95
+ );
96
+
97
+ for (let i = combineConditions.length - 1; i >= 0; i--) {
98
+ const combineCondition = combineConditions[i];
99
+
100
+ combineCondition.removeCondition(fieldName);
101
+
102
+ if (!combineCondition.conditions.length) {
103
+ const index = this.conditions.indexOf(combineCondition);
104
+
105
+ this.conditions.splice(index, 1);
106
+ }
107
+ }
108
+ }
109
+
110
+ toJSON() {
111
+ return this.conditions.map((condition) =>
112
+ condition instanceof Condition ? condition.toJSON() : condition
113
+ );
114
+ }
115
+ }
@@ -0,0 +1,3 @@
1
+ export class Condition {
2
+
3
+ }
@@ -0,0 +1,22 @@
1
+ import { Condition } from './Condition';
2
+
3
+ export class SingleCondition extends Condition {
4
+ f = '';
5
+ o = '=';
6
+ v = '';
7
+
8
+ constructor(f, o, v) {
9
+ super();
10
+ this.f = f;
11
+ this.v = v;
12
+ this.o = o;
13
+ }
14
+
15
+ toJSON() {
16
+ return {
17
+ f: this.f,
18
+ o: this.o,
19
+ v: this.v,
20
+ };
21
+ }
22
+ }
@@ -0,0 +1,22 @@
1
+ import { CombineCondition } from './CombineCondition';
2
+ import { SingleCondition } from './SingleCondition';
3
+
4
+ export class Where extends CombineCondition {
5
+ getCondition(fieldName) {
6
+ let conditions = this.conditions.slice();
7
+
8
+ for (let i = 0; i < conditions.length; i++) {
9
+ const condition = conditions[i];
10
+
11
+ if (condition instanceof CombineCondition) {
12
+ conditions = conditions.concat(condition.conditions);
13
+ } else if (condition instanceof SingleCondition) {
14
+ if (condition.f === fieldName) {
15
+ return condition;
16
+ }
17
+ }
18
+ }
19
+
20
+ return null;
21
+ }
22
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * data model define
3
+ */
4
+ export const DATA_MODEL_DEFINE = {
5
+ table: Symbol('DATA TABLE DEFINE'),
6
+ form: Symbol('DATA FORM DEFINE'),
7
+ };
8
+
9
+ export const DATA_TABLE = "DATA_TABLE";
10
+ export const DATA_FORM = "DATA_FORM";
11
+ export const DATA_TABLE_COLUMNS = "DATA_TABLE_COLUMNS";
12
+ export const DATA_TABLE_FILTER_COLUMN = "DATA_TABLE_FILTER_COLUMN";
13
+ export const DATA_FORM_COLUMNS = "DATA_FORM_COLUMNS";
@@ -0,0 +1,35 @@
1
+ import { DATA_MODEL_DEFINE, DATA_FORM } from './constant';
2
+ import DataForm from '../abstract/DataForm';
3
+
4
+ /**
5
+ * 标识为当前模型为一个数据表单
6
+ * @param {Object} option 配置
7
+ * @param {String} option.name 表格名称
8
+ * @param {String} option.title 表格标题
9
+ * @param {String} option.primaryKey 主键字段名
10
+ * @param {String} option.primaryKey 主键字段名
11
+ * @returns
12
+ */
13
+ export default function dataForm(option) {
14
+ return function decorator(classType) {
15
+ if (classType.constructor !== Function) {
16
+ throw new Error(`@dataForm 只能用于类的注解`);
17
+ }
18
+
19
+ /**
20
+ * @type {DataForm} dataForm 对象
21
+ */
22
+ let dataForm = classType[DATA_FORM];
23
+
24
+ if (dataForm) {
25
+ return;
26
+ }
27
+
28
+ dataForm = classType[DATA_FORM] = option;
29
+
30
+ //记录映射目标
31
+ // dataForm.mapTarget = classType;
32
+ //包装的类的构造函数
33
+ return classType;
34
+ };
35
+ }
@@ -0,0 +1,38 @@
1
+ import { DATA_MODEL_DEFINE, DATA_TABLE } from './constant';
2
+ import DataTable from '../abstract/DataTable';
3
+
4
+ /**
5
+ * 标识为当前模型为一个数据表格
6
+ * @param {Object} option 配置
7
+ * @param {String} option.name 表格名称
8
+ * @param {String} option.title 表格标题
9
+ * @param {String} option.primaryKey 主键字段名
10
+ * @returns
11
+ */
12
+ export default function dataTable(option) {
13
+ return function decorator(classType) {
14
+ if (classType.constructor !== Function) {
15
+ throw new Error(`@dataTable 只能用于类的注解`);
16
+ }
17
+
18
+ /**
19
+ * @type {DataTable} dataTable对象
20
+ */
21
+ let dataTable = classType[DATA_MODEL_DEFINE.table];
22
+
23
+ if (dataTable) {
24
+ return;
25
+ // dataTable = classType[DATA_MODEL_DEFINE.table] = new DataTable(option);
26
+ // } else {
27
+ // Object.assign(dataTable, option);
28
+ }
29
+
30
+ classType[DATA_TABLE] = option;
31
+
32
+ //记录映射目标
33
+ // dataTable.mapTarget = classType;
34
+
35
+ //包装的类的构造函数
36
+ return classType;
37
+ };
38
+ }
@@ -0,0 +1,29 @@
1
+ import { DATA_TABLE_FILTER_COLUMN } from './constant';
2
+
3
+ export default function filterColumn(options) {
4
+ return function (target, key, description) {
5
+ if (
6
+ arguments.length !== 3 ||
7
+ target.constructor === Function ||
8
+ typeof description.value === 'function'
9
+ ) {
10
+ throw new Error(`@formColumn 只能使用在类的成员变量中`);
11
+ }
12
+
13
+ target.constructor[DATA_TABLE_FILTER_COLUMN] =
14
+ target.constructor[DATA_TABLE_FILTER_COLUMN] || [];
15
+
16
+ const columns = target.constructor[DATA_TABLE_FILTER_COLUMN];
17
+
18
+ options = {
19
+ name: key,
20
+ attrName: key,
21
+ closable: false,
22
+ ...options,
23
+ };
24
+
25
+ options.visible = !options.closable;
26
+
27
+ columns.push(options);
28
+ };
29
+ }
@@ -0,0 +1,60 @@
1
+ import { DATA_MODEL_DEFINE, DATA_FORM_COLUMNS } from './constant';
2
+
3
+ /**
4
+ * 描述表单字段
5
+ * @param {Object} option 配置
6
+ * @param {String} option.name 字段名称
7
+ * @param {String} option.submitName 提交字段名称,默认和字段名称一致
8
+ * @param {String} option.title 字段标题
9
+ * @param {String} option.default 数据提交的时候的默认值
10
+ * @param {Boolean} option.required 是否必填 默认是
11
+ * @param {Boolean} option.visible 字段在渲染组件里是否渲染 默认:true
12
+ * @param {Object[]} option.rules 表单验证规则 参考 https://github.com/yiminghe/async-validator
13
+ * @param {String} option.rules[].type string,number,boolean,method,regexp,integer,float,array,object,enum,date,url,hex,email,any
14
+ * @param {Boolean} option.rules[].required 是否必填
15
+ * @param {Pattern} option.rules[].pattern 正则
16
+ * @param {Function} option.rules[].validator 验证方法
17
+ * @param {String} option.rules[].message 提示消息
18
+ * @param {Number} option.rules[].len 指定长度匹配
19
+ * @param {Number} option.rules[].max 最大长度
20
+ * @param {Number} option.rules[].min 最小长度
21
+ * @param {Object|Function|String} option.component 字段在组件里面渲染的所用到的组件,可以是组件对象,字符串,或者方法,工厂方法必然返回vnode 默认:无,
22
+ * @param {Object|Function} option.componentProps 字段在组件中渲染所需要的配置参数,如果是函数的话函数的第一个参数会返回当前数据列对象和当前行数据,此时可动态返回所需参数
23
+ * @returns
24
+ */
25
+ export default function formColumn(option) {
26
+ return function (target, key, description) {
27
+ if (
28
+ arguments.length !== 3 ||
29
+ target.constructor === Function ||
30
+ typeof description.value === 'function'
31
+ ) {
32
+ throw new Error(`@formColumn 只能使用在类的成员变量中`);
33
+ }
34
+
35
+ target.constructor[DATA_FORM_COLUMNS] =
36
+ target.constructor[DATA_FORM_COLUMNS] || [];
37
+
38
+ const columns = target.constructor[DATA_FORM_COLUMNS];
39
+
40
+ columns.push({
41
+ name: key,
42
+ submitName: option.name || key,
43
+ ...option,
44
+ attrName: key,
45
+ });
46
+
47
+ // if (!dataForm) {
48
+ // target.constructor[DATA_MODEL_DEFINE.form] = dataForm = new DataForm();
49
+ // }
50
+
51
+ // dataForm.addColumn(
52
+ // new FormColumn(
53
+ // Object.assign(
54
+ // { name: key, attrName: key, submitName: option.name || key },
55
+ // option
56
+ // )
57
+ // )
58
+ // );
59
+ };
60
+ }
@@ -0,0 +1,42 @@
1
+ import { DATA_MODEL_DEFINE, DATA_TABLE_COLUMNS } from './constant';
2
+ import DataTable from '../abstract/DataTable';
3
+ import TableColumn from '../abstract/TableColumn';
4
+
5
+ /**
6
+ * 注入
7
+ * @param {Object} option 配置
8
+ * @param {String} option.name 字段名称
9
+ * @param {String} option.title 字段标题
10
+ * @param {String} option.default 字段填充时 若服务端返回 空值 NULL值时显示的内容 默认 "-"
11
+ * @param {String} option.width 字段在组件里面显示的宽度 默认:auto
12
+ * @param {String} option.align 字段在组件里面显示的对齐方式 默认:center
13
+ * @param {Boolean} option.visible 字段在渲染组件里是否渲染 默认:true
14
+ * @param {String} option.type 字段的数据类型 number|string|image|audio|date 默认:string
15
+ * @param {String} option.rule 字段根据不同的数据类型格式化的规则:d:2,s:5,yyyy-MM-dd hh:mm:ss 默认:无
16
+ * @param {Object|Function|String} option.component 字段在组件里面渲染的所用到的组件,可以是组件对象,字符串,或者方法,工厂方法必然返回vnode 默认:无,
17
+ * @param {Object|Function} option.componentProps 字段在组件中渲染所需要的配置参数,如果是函数的话函数的第一个参数会返回当前数据列对象和当前行数据,此时可动态返回所需参数
18
+ *
19
+ * @returns
20
+ */
21
+ export default function tableColumn(option) {
22
+ return function (target, key, description) {
23
+ if (
24
+ arguments.length !== 3 ||
25
+ target.constructor === Function ||
26
+ typeof description.value === 'function'
27
+ ) {
28
+ throw new Error(`@tableColumn 只能使用在类的成员变量中`);
29
+ }
30
+
31
+ target.constructor[DATA_TABLE_COLUMNS] =
32
+ target.constructor[DATA_TABLE_COLUMNS] || [];
33
+
34
+ const columns = target.constructor[DATA_TABLE_COLUMNS];
35
+
36
+ columns.push({
37
+ name: key,
38
+ attrName: key,
39
+ ...option,
40
+ });
41
+ };
42
+ }
package/src/factory.js ADDED
@@ -0,0 +1,25 @@
1
+ import { DATA_MODEL_DEFINE } from './decorator/constant.js';
2
+ import DataTable from './abstract/DataTable';
3
+ import DataForm from './abstract/dataForm';
4
+
5
+ /**
6
+ * 创建DataTable实例
7
+ * @template T
8
+ * @param {T} classType data model class
9
+ * @returns {DataTable}
10
+ */
11
+ export const createDataTable = function (classType) {
12
+ const baseDataTable = classType[DATA_MODEL_DEFINE.table];
13
+ return baseDataTable ? baseDataTable.clone() : new DataTable();
14
+ };
15
+
16
+ /**
17
+ * 创建DataForm实例
18
+ * @template T
19
+ * @param {T} classType data model class
20
+ * @returns {DataForm}
21
+ */
22
+ export const createDataForm = function (classType) {
23
+ const baseDataForm = classType[DATA_MODEL_DEFINE.form];
24
+ return baseDataForm ? baseDataForm.clone() : new dataForm();
25
+ };
package/src/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import DataTable from './abstract/DataTable';
2
+ import DataForm from './abstract/DataForm';
3
+ import { FilterPanel } from './abstract/FilterPanel';
4
+ import DataModelAdapter from './abstract/DataModelAdapter';
5
+ import dataTable from './decorator/dataTable';
6
+ import dataForm from './decorator/dataForm';
7
+ import tableColumn from './decorator/tableColumn';
8
+ import formColumn from './decorator/formColumn';
9
+ import SimpleOrm from './SimpleOrm';
10
+ import filterColumn from './decorator/filterColumn';
11
+ export * from './abstract/where/CombineCondition';
12
+ export * from './abstract/where/SingleCondition';
13
+ export * from './abstract/where/Where';
14
+ export * from './factory';
15
+ export {
16
+ SimpleOrm,
17
+ DataTable,
18
+ DataForm,
19
+ FilterPanel,
20
+ dataTable,
21
+ dataForm,
22
+ tableColumn,
23
+ formColumn,
24
+ filterColumn,
25
+ DataModelAdapter,
26
+ };
@@ -0,0 +1,16 @@
1
+ export const sortColumn = (columns, order) => {
2
+ return [...columns].sort((a, b) => {
3
+ const aIndex = order.indexOf(a.attrName);
4
+ const bIndex = order.indexOf(b.attrName);
5
+
6
+ if (aIndex === -1 && bIndex === -1) {
7
+ return 0;
8
+ }
9
+
10
+ if (aIndex !== -1 && bIndex !== -1) {
11
+ return aIndex - bIndex;
12
+ }
13
+
14
+ return aIndex === -1 ? 1 : -1;
15
+ });
16
+ };