@tachybase/plugin-field-formula 1.6.22 → 1.6.24
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.md +2 -0
- package/README.zh-CN.md +2 -0
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +4 -4
- package/dist/server/field-formula.d.ts +2 -7
- package/dist/server/field-formula.js +53 -66
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +20 -1
- package/package.json +6 -6
package/README.md
CHANGED
package/README.zh-CN.md
CHANGED
package/dist/client/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(n,r){typeof exports=="object"&&typeof module!="undefined"?r(exports,require("@tachybase/client"),require("@tachybase/schema"),require("react/jsx-runtime"),require("react"),require("@tego/client"),require("lodash"),require("react-i18next")):typeof define=="function"&&define.amd?define(["exports","@tachybase/client","@tachybase/schema","react/jsx-runtime","react","@tego/client","lodash","react-i18next"],r):(n=typeof globalThis!="undefined"?globalThis:n||self,r(n["@tachybase/plugin-field-formula"]={},n["@tachybase/client"],n["@tachybase/schema"],n.jsxRuntime,n.react,n["@tego/client"],n.lodash))})(this,function(n,r,a,s,N,g,S){"use strict";var ae=Object.defineProperty,oe=Object.defineProperties;var ue=Object.getOwnPropertyDescriptors;var C=Object.getOwnPropertySymbols;var V=Object.prototype.hasOwnProperty,_=Object.prototype.propertyIsEnumerable;var w=(n,r,a)=>r in n?ae(n,r,{enumerable:!0,configurable:!0,writable:!0,value:a}):n[r]=a,h=(n,r)=>{for(var a in r||(r={}))V.call(r,a)&&w(n,a,r[a]);if(C)for(var a of C(r))_.call(r,a)&&w(n,a,r[a]);return n},y=(n,r)=>oe(n,ue(r));var $=(n,r)=>{var a={};for(var s in n)V.call(n,s)&&r.indexOf(s)<0&&(a[s]=n[s]);if(n!=null&&C)for(var s of C(n))r.indexOf(s)<0&&_.call(n,s)&&(a[s]=n[s]);return a};var B=(n,r,a)=>new Promise((s,N)=>{var g=d=>{try{v(a.next(d))}catch(F){N(F)}},S=d=>{try{v(a.throw(d))}catch(F){N(F)}},v=d=>d.done?s(d.value):Promise.resolve(d.value).then(g,S);v((a=a.apply(n,r)).next())});const v=e=>{var b;const{value:t="",supports:i=[],useCurrentFields:o,onChange:u}=e,c=r.useCompile(),{getCollectionFields:p}=r.useCollectionManager_deprecated(),m=d(c,p,(b=o==null?void 0:o())!=null?b:[]);return s.jsx(r.Variable.TextArea,{value:t,onChange:u,scope:m})},d=(e,t,i)=>{const o=[];return i==null||i.forEach(u=>{var c,p,m,b;!["m2m","o2m"].includes(u.interface)&&["hasOne","hasMany","belongsTo","belongsToMany"].includes(u.type)&&u.uiSchema&&o.push({label:e(u.uiSchema.title),value:u.name,children:(p=(c=t(u.target))==null?void 0:c.filter(l=>l.uiSchema).map(l=>({label:l.uiSchema?e(l.uiSchema.title):"",value:l.name})))!=null?p:[]}),["hasOne","hasMany","belongsTo","belongsToMany"].includes(u.type)||o.push({label:e(u.uiSchema.title),value:u.name,children:(b=(m=t(u.target))==null?void 0:m.filter(l=>l.uiSchema).map(l=>({label:l.uiSchema?e(l.uiSchema.title):"",value:l.name})))!=null?b:[]})}),o},F={boolean:Boolean,integer:{boolean(e){return Number(e)},number(e){return e>=0?Math.floor(e):Math.ceil(e)},bigint(e){return Number(e)},string(e){const t=Number.parseInt(e,10);return Number.isNaN(t)||!Number.isFinite(t)?null:t},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},bigInt:{boolean(e){return Number(e)},number(e){return Math.floor(e>=0?Math.floor(e):Math.ceil(e))},bigint(e){return Number(e)},string(e){const t=Number.parseInt(e,10);return Number.isNaN(t)||!Number.isFinite(t)?null:t},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},double:{boolean(e){return Number(e)},number(e){return e},bigint(e){return Number(e)},string(e){const t=Number.parseFloat(e);return Number.isNaN(t)||!Number.isFinite(t)?null:t},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},decimal:{boolean(e){return Number(e)},number(e){return e},bigint(e){return e},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},string:{boolean(e){return e.toString()},number(e){return e.toString()},bigint(e){return e.toString()},string(e){return e},date(e){return e.toISOString()}},date:{boolean(e){return null},number(e){const t=new Date(e);return Number.isNaN(t.valueOf())?null:t},bigint(e){const t=new Date(Number(e));return Number.isNaN(t.valueOf())?null:t},string(e){const t=Date.parse(e);return Number.isNaN(t)?null:new Date(t)},date(e){return new Date(e)}}};function G(e,t){if(e==null)return null;let i=typeof e;i
|
|
1
|
+
(function(n,r){typeof exports=="object"&&typeof module!="undefined"?r(exports,require("@tachybase/client"),require("@tachybase/schema"),require("react/jsx-runtime"),require("react"),require("@tego/client"),require("lodash"),require("react-i18next")):typeof define=="function"&&define.amd?define(["exports","@tachybase/client","@tachybase/schema","react/jsx-runtime","react","@tego/client","lodash","react-i18next"],r):(n=typeof globalThis!="undefined"?globalThis:n||self,r(n["@tachybase/plugin-field-formula"]={},n["@tachybase/client"],n["@tachybase/schema"],n.jsxRuntime,n.react,n["@tego/client"],n.lodash))})(this,function(n,r,a,s,N,g,S){"use strict";var ae=Object.defineProperty,oe=Object.defineProperties;var ue=Object.getOwnPropertyDescriptors;var C=Object.getOwnPropertySymbols;var V=Object.prototype.hasOwnProperty,_=Object.prototype.propertyIsEnumerable;var w=(n,r,a)=>r in n?ae(n,r,{enumerable:!0,configurable:!0,writable:!0,value:a}):n[r]=a,h=(n,r)=>{for(var a in r||(r={}))V.call(r,a)&&w(n,a,r[a]);if(C)for(var a of C(r))_.call(r,a)&&w(n,a,r[a]);return n},y=(n,r)=>oe(n,ue(r));var $=(n,r)=>{var a={};for(var s in n)V.call(n,s)&&r.indexOf(s)<0&&(a[s]=n[s]);if(n!=null&&C)for(var s of C(n))r.indexOf(s)<0&&_.call(n,s)&&(a[s]=n[s]);return a};var B=(n,r,a)=>new Promise((s,N)=>{var g=d=>{try{v(a.next(d))}catch(F){N(F)}},S=d=>{try{v(a.throw(d))}catch(F){N(F)}},v=d=>d.done?s(d.value):Promise.resolve(d.value).then(g,S);v((a=a.apply(n,r)).next())});const v=e=>{var b;const{value:t="",supports:i=[],useCurrentFields:o,onChange:u}=e,c=r.useCompile(),{getCollectionFields:p}=r.useCollectionManager_deprecated(),m=d(c,p,(b=o==null?void 0:o())!=null?b:[]);return s.jsx(r.Variable.TextArea,{value:t,onChange:u,scope:m})},d=(e,t,i)=>{const o=[];return i==null||i.forEach(u=>{var c,p,m,b;!["m2m","o2m"].includes(u.interface)&&["hasOne","hasMany","belongsTo","belongsToMany"].includes(u.type)&&u.uiSchema&&o.push({label:e(u.uiSchema.title),value:u.name,children:(p=(c=t(u.target))==null?void 0:c.filter(l=>l.uiSchema).map(l=>({label:l.uiSchema?e(l.uiSchema.title):"",value:l.name})))!=null?p:[]}),["hasOne","hasMany","belongsTo","belongsToMany"].includes(u.type)||o.push({label:e(u.uiSchema.title),value:u.name,children:(b=(m=t(u.target))==null?void 0:m.filter(l=>l.uiSchema).map(l=>({label:l.uiSchema?e(l.uiSchema.title):"",value:l.name})))!=null?b:[]})}),o},F={boolean:Boolean,integer:{boolean(e){return Number(e)},number(e){return e>=0?Math.floor(e):Math.ceil(e)},bigint(e){return Number(e)},string(e){const t=Number.parseInt(e,10);return Number.isNaN(t)||!Number.isFinite(t)?null:t},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},bigInt:{boolean(e){return Number(e)},number(e){return Math.floor(e>=0?Math.floor(e):Math.ceil(e))},bigint(e){return Number(e)},string(e){const t=Number.parseInt(e,10);return Number.isNaN(t)||!Number.isFinite(t)?null:t},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},double:{boolean(e){return Number(e)},number(e){return e},bigint(e){return Number(e)},string(e){const t=Number.parseFloat(e);return Number.isNaN(t)||!Number.isFinite(t)?null:t},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},decimal:{boolean(e){return Number(e)},number(e){return e},bigint(e){return e},date(e){const t=e.valueOf();return Number.isNaN(t)?null:t}},string:{boolean(e){return e.toString()},number(e){return e.toString()},bigint(e){return e.toString()},string(e){return e},date(e){return e.toISOString()}},date:{boolean(e){return null},number(e){const t=new Date(e);return Number.isNaN(t.valueOf())?null:t},bigint(e){const t=new Date(Number(e));return Number.isNaN(t.valueOf())?null:t},string(e){const t=Date.parse(e);return Number.isNaN(t)?null:new Date(t)},date(e){return new Date(e)}}};function G(e,t){if(e==null)return null;let i=typeof e;i==="object"&&e instanceof Date&&(i="date");const o=F[t];if(!o)return null;if(typeof o=="function")return o(e);const u=o[i];return u?u(e):null}const J={boolean:r.Checkbox.ReadPretty,integer:r.InputNumber.ReadPretty,bigInt:r.InputNumber.ReadPretty,double:r.InputNumber.ReadPretty,decimal:r.InputNumber.ReadPretty,date:r.DatePicker.ReadPretty,string:r.Input.ReadPretty};function U(){const e=a.useFieldSchema(),t=r.useCollection_deprecated(),{getCollection:i,getCollectionField:o}=r.useCollectionManager_deprecated(),u=e.name.split(".");let c=t;for(let p=0;p<u.length-1;p++){const m=c.getField(u[p]);c=i(m.target)}return o(`${c.name}.${u[u.length-1]}`)}function z(e,t,i){const o=e[t];return Array.isArray(o)?o[i]:o&&typeof o=="object"?o:e}function H(e){var q,A,R;const j=e,{value:t}=j,i=$(j,["value"]),o=a.useFieldSchema(),{dataType:u,expression:c,engine:p="math.js"}=(q=U())!=null?q:{},[m,b]=N.useState(t),{evaluate:l}=g.evaluators.get(p),T=r.useFormBlockContext(),M=a.useField().path.entire,O=M==null?void 0:M.replace(`.${o.name}`,""),Z=O.split(".")[0],ee=parseInt((A=O.split("."))==null?void 0:A[1]);N.useEffect(()=>{b(t)},[t]),a.useFormEffects(()=>{a.onFormValuesChange(re=>{var k;if(o.name.indexOf(".")>=0||!(T!=null&&T.form)||(k=T.form)!=null&&k.readPretty)return;const ne=a.toJS(z(re.values,Z,ee));let f;try{f=l(c,ne),f=G(f,u)}catch(ie){f=null}f==null&&m==null&&b(f),b(f),f!==t&&e.onChange(f)})});const te=(R=J[u])!=null?R:r.Input;return s.jsx(te,y(h({},i),{value:u==="double"?g.toFixedByStep(m,e.step):m}))}const P=()=>null;P.Expression=v,P.Result=a.connect(H);const x="field-formula",K=[{dependencies:["dataType"],fulfill:{state:{display:'{{["double", "decimal"].includes($deps[0]) ? "visible" : "none"}}'}}}],D=[{dependencies:["dataType"],fulfill:{state:{display:'{{$deps[0] === "date" ? "visible" : "none"}}'}}}],{defaultProps:L,dateTimeProps:I,operators:Q}=r.interfacesProperties,W={"uiSchema.x-component-props.dateFormat":y(h({},S.cloneDeep(I["uiSchema.x-component-props.dateFormat"])),{"x-reactions":D}),"uiSchema.x-component-props.showTime":y(h({},S.cloneDeep(I["uiSchema.x-component-props.showTime"])),{"x-reactions":[...I["uiSchema.x-component-props.showTime"]["x-reactions"],...D]}),"uiSchema.x-component-props.timeFormat":h({},S.cloneDeep(I["uiSchema.x-component-props.timeFormat"]))};class X extends r.CollectionFieldInterface{constructor(){super(...arguments),this.name="formula",this.type="object",this.group="advanced",this.order=1,this.title=`{{t("Formula", { ns: "${x}" })}}`,this.icon="FunctionOutlined",this.description=`{{t("Configure and store the results of calculations between multiple field values in the same record, supporting both Math.js and Excel formula functions.", { ns: "${x}" })}}`,this.sortable=!0,this.default={type:"formula",uiSchema:{type:"string","x-component":"Formula.Result","x-component-props":{stringMode:!0,step:"1"},"x-read-pretty":!0}},this.properties=y(h(y(h({},L),{dataType:{type:"string",title:'{{t("Storage type")}}',"x-decorator":"FormItem","x-component":"Select","x-disabled":"{{ !createOnly }}",enum:[{value:"boolean",label:"Boolean"},{value:"integer",label:"Integer"},{value:"bigInt",label:"Big integer"},{value:"double",label:"Double"},{value:"string",label:"String"},{value:"date",label:"Datetime"}],required:!0,default:"double"},"uiSchema.x-component-props.addonAfter":{type:"string",title:'{{t("Suffix")}}',"x-decorator":"FormItem","x-component":"Input"},"uiSchema.x-component-props.step":{type:"string",title:'{{t("Precision")}}',"x-component":"Select","x-decorator":"FormItem",required:!0,default:"0",enum:[{value:"0",label:"1"},{value:"0.1",label:"1.0"},{value:"0.01",label:"1.00"},{value:"0.001",label:"1.000"},{value:"0.0001",label:"1.0000"},{value:"0.00001",label:"1.00000"},{value:"0.000001",label:"1.000000"},{value:"0.0000001",label:"1.0000000"},{value:"0.00000001",label:"1.00000000"},{value:"0.000000001",label:"1.000000000"},{value:"0.0000000001",label:"1.0000000000"}],"x-reactions":K}}),W),{engine:{type:"string",title:`{{t("Calculation engine", { ns: "${x}" })}}`,"x-decorator":"FormItem","x-component":"Radio.Group",enum:Array.from(g.evaluators.getEntities()).reduce((t,[i,o])=>t.concat(h({value:i},o)),[]),required:!0,default:"math.js"},expression:{type:"string",title:`{{t("Expression", { ns: "${x}" })}}`,required:!0,"x-component":"Formula.Expression","x-decorator":"FormItem","x-component-props":{supports:["checkbox","number","percent","integer","number","percent","sequence","input","textarea","email","phone","bankCard","datetime","createdAt","updatedAt","radioGroup","checkboxGroup","select","multipleSelect","m2o","o2m"],useCurrentFields:"{{ useCurrentFields }}"},"x-reactions":{dependencies:["engine"],fulfill:{schema:{description:"{{renderExpressionDescription($deps[0])}}"}}},"x-validator"(t,i,{form:o}){const{values:u}=o,{evaluate:c}=g.evaluators.get(u.engine),p=t.trim().replace(/{{\s*([^{}]+)\s*}}/g,"1");try{return c(p),""}catch(m){return r.i18n.t("Expression syntax error",{ns:x})}}}}),this.filterable={operators:Q.string},this.titleUsable=!0}}function Y(e){const t=g.evaluators.get(e);return t!=null&&t.link?s.jsxs(s.Fragment,{children:[s.jsx("span",{className:r.css`
|
|
2
2
|
&:after {
|
|
3
3
|
content: ':';
|
|
4
4
|
}
|
package/dist/externalVersion.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
"@tachybase/client": "1.6.
|
|
2
|
+
"@tachybase/client": "1.6.24",
|
|
3
3
|
"react": "18.3.1",
|
|
4
|
-
"@tego/client": "1.6.
|
|
5
|
-
"@tego/server": "1.6.
|
|
4
|
+
"@tego/client": "1.6.16",
|
|
5
|
+
"@tego/server": "1.6.16",
|
|
6
6
|
"lodash": "4.17.21",
|
|
7
7
|
"react-i18next": "16.2.1",
|
|
8
|
-
"@tachybase/schema": "1.6.
|
|
8
|
+
"@tachybase/schema": "1.6.16"
|
|
9
9
|
};
|
|
@@ -7,13 +7,8 @@ export interface FormulaFieldOptions extends BaseFieldOptions {
|
|
|
7
7
|
export declare class FormulaField extends Field {
|
|
8
8
|
get dataType(): any;
|
|
9
9
|
calculate(scope: any): any;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}) => Promise<void>;
|
|
13
|
-
calculateField: (instance: any) => Promise<void>;
|
|
14
|
-
updateFieldData: (instance: any, { transaction }: {
|
|
15
|
-
transaction: any;
|
|
16
|
-
}) => Promise<void>;
|
|
10
|
+
getCalculationScope: (instance: any, options?: any) => Promise<any>;
|
|
11
|
+
calculateField: (instance: any, options?: any) => Promise<void>;
|
|
17
12
|
bind(): void;
|
|
18
13
|
unbind(): void;
|
|
19
14
|
}
|
|
@@ -34,76 +34,61 @@ const DataTypeMap = {
|
|
|
34
34
|
class FormulaField extends import_server.Field {
|
|
35
35
|
constructor() {
|
|
36
36
|
super(...arguments);
|
|
37
|
-
this.
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
37
|
+
this.getCalculationScope = async (instance, options) => {
|
|
38
|
+
var _a, _b, _c, _d;
|
|
39
|
+
const appends = (0, import_utils.getAppendsFromExpression)(this.options.expression);
|
|
40
|
+
const instanceScope = instance.toJSON();
|
|
41
|
+
let scope = { ...instanceScope };
|
|
42
|
+
if (!appends.length) {
|
|
43
|
+
return scope;
|
|
44
|
+
}
|
|
45
|
+
const pk = this.collection.model.primaryKeyAttribute;
|
|
46
|
+
const pkValue = instance.get(pk) ?? instanceScope[pk];
|
|
47
|
+
if (pkValue) {
|
|
48
|
+
const record = await this.collection.repository.findOne({
|
|
49
|
+
filterByTk: pkValue,
|
|
50
|
+
transaction: options == null ? void 0 : options.transaction
|
|
51
|
+
});
|
|
52
|
+
if (record) {
|
|
53
|
+
scope = { ...record.toJSON(), ...instanceScope };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const append of appends) {
|
|
57
|
+
const field = this.collection.getField(append);
|
|
58
|
+
const target = (field == null ? void 0 : field.target) ?? ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.target);
|
|
59
|
+
if (!target) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const fkField = ((_b = field.options) == null ? void 0 : _b.foreignKey) ?? field.foreignKey ?? `${append}Id`;
|
|
63
|
+
const fkValue = scope[fkField];
|
|
64
|
+
if (fkValue == null) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const targetKey = ((_c = field.options) == null ? void 0 : _c.targetKey) ?? "id";
|
|
68
|
+
const relatedId = (_d = scope[append]) == null ? void 0 : _d[targetKey];
|
|
69
|
+
if (relatedId != null && `${relatedId}` === `${fkValue}`) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const targetCollection = this.database.getCollection(target);
|
|
73
|
+
if (!targetCollection) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const targetRecord = await targetCollection.repository.findOne({
|
|
77
|
+
filterByTk: fkValue,
|
|
78
|
+
transaction: options == null ? void 0 : options.transaction
|
|
79
|
+
});
|
|
80
|
+
if (targetRecord) {
|
|
81
|
+
scope[append] = targetRecord.toJSON();
|
|
57
82
|
}
|
|
58
83
|
}
|
|
84
|
+
return scope;
|
|
59
85
|
};
|
|
60
|
-
this.calculateField = async (instance) => {
|
|
86
|
+
this.calculateField = async (instance, options) => {
|
|
61
87
|
const { name } = this.options;
|
|
62
|
-
const
|
|
88
|
+
const scope = await this.getCalculationScope(instance, options);
|
|
89
|
+
const result = this.calculate(scope);
|
|
63
90
|
instance.set(name, result);
|
|
64
91
|
};
|
|
65
|
-
this.updateFieldData = async (instance, { transaction }) => {
|
|
66
|
-
if (this.collection.name !== instance.collectionName || instance.name !== this.options.name) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
this.options = Object.assign(this.options, instance.options);
|
|
70
|
-
const { name } = this.options;
|
|
71
|
-
const regex = /\{\{([^}]+)\}\}/g;
|
|
72
|
-
const variables = [];
|
|
73
|
-
let match;
|
|
74
|
-
while ((match = regex.exec(this.options.expression)) !== null) {
|
|
75
|
-
variables.push(match[1]);
|
|
76
|
-
}
|
|
77
|
-
const uniqueVariables = [...new Set(variables)];
|
|
78
|
-
const appends = uniqueVariables.map((item) => {
|
|
79
|
-
if (item.includes(".")) {
|
|
80
|
-
const parts = item.split(".");
|
|
81
|
-
parts.pop();
|
|
82
|
-
const result = parts.join(".");
|
|
83
|
-
return result;
|
|
84
|
-
}
|
|
85
|
-
return "";
|
|
86
|
-
}).filter(Boolean);
|
|
87
|
-
const records = await this.collection.repository.find({
|
|
88
|
-
order: [this.collection.model.primaryKeyAttribute],
|
|
89
|
-
transaction,
|
|
90
|
-
appends
|
|
91
|
-
});
|
|
92
|
-
for (const record of records) {
|
|
93
|
-
const scope = record.toJSON();
|
|
94
|
-
const result = this.calculate(scope);
|
|
95
|
-
await record.update(
|
|
96
|
-
{
|
|
97
|
-
[name]: result
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
transaction,
|
|
101
|
-
silent: true,
|
|
102
|
-
hooks: false
|
|
103
|
-
}
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
92
|
}
|
|
108
93
|
get dataType() {
|
|
109
94
|
const { dataType } = this.options;
|
|
@@ -112,6 +97,10 @@ class FormulaField extends import_server.Field {
|
|
|
112
97
|
calculate(scope) {
|
|
113
98
|
const { expression, engine = "math.js", dataType = "double" } = this.options;
|
|
114
99
|
const evaluate = import_server.evaluators.get(engine);
|
|
100
|
+
if (!evaluate) {
|
|
101
|
+
console.error(`Formula evaluator "${engine}" is not registered.`);
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
115
104
|
try {
|
|
116
105
|
const result = evaluate(expression, scope);
|
|
117
106
|
return (0, import_utils.toDbType)(result, dataType);
|
|
@@ -122,13 +111,11 @@ class FormulaField extends import_server.Field {
|
|
|
122
111
|
}
|
|
123
112
|
bind() {
|
|
124
113
|
super.bind();
|
|
125
|
-
this.database.on("fields.afterUpdate", this.updateFieldData);
|
|
126
114
|
this.on("beforeSave", this.calculateField);
|
|
127
115
|
}
|
|
128
116
|
unbind() {
|
|
129
117
|
super.unbind();
|
|
130
118
|
this.off("beforeSave", this.calculateField);
|
|
131
|
-
this.database.off("fields.afterUpdate", this.updateFieldData);
|
|
132
119
|
}
|
|
133
120
|
}
|
|
134
121
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -18,9 +18,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
18
18
|
var utils_exports = {};
|
|
19
19
|
__export(utils_exports, {
|
|
20
20
|
DataTypeTransformers: () => DataTypeTransformers,
|
|
21
|
+
getAppendsFromExpression: () => getAppendsFromExpression,
|
|
21
22
|
toDbType: () => toDbType
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(utils_exports);
|
|
25
|
+
function getAppendsFromExpression(expression) {
|
|
26
|
+
const regex = /\{\{([^}]+)\}\}/g;
|
|
27
|
+
const variables = [];
|
|
28
|
+
let match;
|
|
29
|
+
while ((match = regex.exec(expression)) !== null) {
|
|
30
|
+
variables.push(match[1].trim());
|
|
31
|
+
}
|
|
32
|
+
const uniqueVariables = [...new Set(variables)];
|
|
33
|
+
return uniqueVariables.map((item) => {
|
|
34
|
+
if (item.includes(".")) {
|
|
35
|
+
const parts = item.split(".");
|
|
36
|
+
parts.pop();
|
|
37
|
+
return parts.join(".");
|
|
38
|
+
}
|
|
39
|
+
return "";
|
|
40
|
+
}).filter(Boolean);
|
|
41
|
+
}
|
|
24
42
|
const DataTypeTransformers = {
|
|
25
43
|
boolean: Boolean,
|
|
26
44
|
integer: {
|
|
@@ -168,7 +186,7 @@ function toDbType(value, type) {
|
|
|
168
186
|
return null;
|
|
169
187
|
}
|
|
170
188
|
let jsType = typeof value;
|
|
171
|
-
if (jsType
|
|
189
|
+
if (jsType === "object" && value instanceof Date) {
|
|
172
190
|
jsType = "date";
|
|
173
191
|
}
|
|
174
192
|
const transformers = DataTypeTransformers[type];
|
|
@@ -184,5 +202,6 @@ function toDbType(value, type) {
|
|
|
184
202
|
// Annotate the CommonJS export names for ESM import in node:
|
|
185
203
|
0 && (module.exports = {
|
|
186
204
|
DataTypeTransformers,
|
|
205
|
+
getAppendsFromExpression,
|
|
187
206
|
toDbType
|
|
188
207
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tachybase/plugin-field-formula",
|
|
3
3
|
"displayName": "Field: Formula",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.24",
|
|
5
5
|
"description": "Configure and store the results of calculations between multiple field values in the same record, supporting both Math.js and Excel formula functions.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"Collection fields"
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"license": "Apache-2.0",
|
|
19
19
|
"main": "./dist/server/index.js",
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@tachybase/schema": "1.6.
|
|
22
|
-
"@tachybase/test": "1.6.
|
|
23
|
-
"@tego/client": "1.6.
|
|
24
|
-
"@tego/server": "1.6.
|
|
21
|
+
"@tachybase/schema": "1.6.16",
|
|
22
|
+
"@tachybase/test": "1.6.16",
|
|
23
|
+
"@tego/client": "1.6.16",
|
|
24
|
+
"@tego/server": "1.6.16",
|
|
25
25
|
"dayjs": "1.11.13",
|
|
26
26
|
"lodash": "^4.17.21",
|
|
27
27
|
"react": "18.3.1",
|
|
28
28
|
"react-i18next": "16.2.1",
|
|
29
|
-
"@tachybase/client": "1.6.
|
|
29
|
+
"@tachybase/client": "1.6.24"
|
|
30
30
|
},
|
|
31
31
|
"description.zh-CN": "可以配置并存储同一条记录的多字段值之间的计算结果,支持 Math.js 和 Excel formula functions 两种引擎",
|
|
32
32
|
"displayName.zh-CN": "数据表字段:公式"
|