semanticdb-core 1.0.53 → 1.1.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.
- package/dist/common/date.js +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/logicform/nameForPredNode.d.ts +20 -0
- package/dist/logicform/nameForPredNode.js +907 -0
- package/dist/schema/schema.utils.d.ts +28 -0
- package/dist/schema/schema.utils.js +130 -1
- package/package.json +1 -1
package/dist/common/date.js
CHANGED
|
@@ -24,7 +24,7 @@ function getSupportedTimeWindows() {
|
|
|
24
24
|
return ['second', 'minute', 'hour', 'weekday', 'day', 'week', 'month', 'quarter', 'year'];
|
|
25
25
|
}
|
|
26
26
|
function isStandardDateForm(dateValue) {
|
|
27
|
-
return typeof dateValue === 'object' && '$gte' in dateValue && '$lte' in dateValue;
|
|
27
|
+
return typeof dateValue === 'object' && dateValue !== null && '$gte' in dateValue && '$lte' in dateValue;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* year + offset形态
|
|
@@ -32,7 +32,7 @@ function isStandardDateForm(dateValue) {
|
|
|
32
32
|
* @return {Boolean}
|
|
33
33
|
*/
|
|
34
34
|
function isRelativeDateForm(dateValue) {
|
|
35
|
-
if (typeof dateValue !== 'object')
|
|
35
|
+
if (typeof dateValue !== 'object' || dateValue === null)
|
|
36
36
|
return false;
|
|
37
37
|
const complexOperators = ['$gte', '$gt', '$lte', '$lt', '$or', '$ne'];
|
|
38
38
|
for (const complexOperator of complexOperators) {
|
package/dist/index.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export { getDrilldownDimensions } from './schema/schema.utils/getDrilldownDimens
|
|
|
9
9
|
export * from './logicform/logicform';
|
|
10
10
|
export * from './logicform/logicform.utils';
|
|
11
11
|
export * from './logicform/types/query';
|
|
12
|
+
export * from './logicform/nameForPredNode';
|
|
12
13
|
export * from './custom-function/utils';
|
|
13
14
|
export * from './result/index';
|
package/dist/index.js
CHANGED
|
@@ -27,5 +27,6 @@ Object.defineProperty(exports, "getDrilldownDimensions", { enumerable: true, get
|
|
|
27
27
|
__exportStar(require("./logicform/logicform"), exports);
|
|
28
28
|
__exportStar(require("./logicform/logicform.utils"), exports);
|
|
29
29
|
__exportStar(require("./logicform/types/query"), exports);
|
|
30
|
+
__exportStar(require("./logicform/nameForPredNode"), exports);
|
|
30
31
|
__exportStar(require("./custom-function/utils"), exports);
|
|
31
32
|
__exportStar(require("./result/index"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SchemaType } from '../schema/schema';
|
|
2
|
+
import { PredItemType } from './logicform';
|
|
3
|
+
import { QueryType } from './types/query';
|
|
4
|
+
export interface ctx {
|
|
5
|
+
schemas: Record<string, SchemaType>;
|
|
6
|
+
customFunctions: Record<string, any>;
|
|
7
|
+
locale?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 给Query起名
|
|
11
|
+
*/
|
|
12
|
+
export declare const nameForQuery: (query: QueryType, schema: SchemaType, schemas: Record<string, SchemaType>) => string;
|
|
13
|
+
/**
|
|
14
|
+
* 给pred node起名, normalize阶段用到
|
|
15
|
+
* @param predNode - PredItemType
|
|
16
|
+
* @param s - schema object
|
|
17
|
+
* @param ctx - 上下文对象
|
|
18
|
+
* @returns 名称字符串
|
|
19
|
+
*/
|
|
20
|
+
export declare const nameForPredNode: (predNode: PredItemType, s: SchemaType, ctx: ctx) => string | null;
|
|
@@ -0,0 +1,907 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.nameForPredNode = exports.nameForQuery = void 0;
|
|
7
|
+
const moment_1 = __importDefault(require("moment"));
|
|
8
|
+
const schema_utils_1 = require("../schema/schema.utils");
|
|
9
|
+
const utils_1 = require("../custom-function/utils");
|
|
10
|
+
const date_1 = require("../common/date");
|
|
11
|
+
// ============== 辅助函数 ==============
|
|
12
|
+
const getPropertyName = (property) => {
|
|
13
|
+
var _a;
|
|
14
|
+
if ((_a = property === null || property === void 0 ? void 0 : property.ui) === null || _a === void 0 ? void 0 : _a.title) {
|
|
15
|
+
return property.ui.title;
|
|
16
|
+
}
|
|
17
|
+
return property.name;
|
|
18
|
+
};
|
|
19
|
+
const twToChinese = (tw) => {
|
|
20
|
+
const map = {
|
|
21
|
+
year: '年',
|
|
22
|
+
quarter: '季度',
|
|
23
|
+
month: '月',
|
|
24
|
+
week: '周',
|
|
25
|
+
day: '日',
|
|
26
|
+
hour: '点',
|
|
27
|
+
minute: '分',
|
|
28
|
+
second: '秒',
|
|
29
|
+
};
|
|
30
|
+
return map[tw];
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 中文转其他语言的简化实现
|
|
34
|
+
*/
|
|
35
|
+
const zhCNToOthers = (cnText, locale = 'zh-CN') => {
|
|
36
|
+
if (locale.toLowerCase() === 'zh-cn') {
|
|
37
|
+
return cnText;
|
|
38
|
+
}
|
|
39
|
+
if (locale.startsWith('en')) {
|
|
40
|
+
const map = {
|
|
41
|
+
'同比': 'YoY%',
|
|
42
|
+
'环比': 'MoM%',
|
|
43
|
+
'周环比': 'WoW%',
|
|
44
|
+
'季度环比': 'QoQ%',
|
|
45
|
+
'同比差值': 'YoY Diff',
|
|
46
|
+
'环比差值': 'MoM Diff',
|
|
47
|
+
'同期': 'YoY',
|
|
48
|
+
'环期': 'MoM',
|
|
49
|
+
'周环期': 'WoW',
|
|
50
|
+
'占比': '%',
|
|
51
|
+
'数量': '#',
|
|
52
|
+
'累计': 'Cumulative ',
|
|
53
|
+
'年': 'Year',
|
|
54
|
+
'季度': 'Quarter',
|
|
55
|
+
'月': 'Month',
|
|
56
|
+
'周': 'Week',
|
|
57
|
+
'星期': 'Weekday',
|
|
58
|
+
'日': 'Day',
|
|
59
|
+
'小时': 'Hour',
|
|
60
|
+
'分钟': 'Minute',
|
|
61
|
+
'秒': 'Second',
|
|
62
|
+
'均': ' Avg',
|
|
63
|
+
'每小时': 'Hourly ',
|
|
64
|
+
'每小时段': 'By Hour ',
|
|
65
|
+
'分星期': 'By Weekday ',
|
|
66
|
+
'日均': 'Daily Avg ',
|
|
67
|
+
'月均': 'Monthly Avg ',
|
|
68
|
+
'周均': 'Weekly Avg ',
|
|
69
|
+
'上期': 'Previous Period ',
|
|
70
|
+
'按农历': ' (Lunar)',
|
|
71
|
+
'按星期': ' (By Weekday)',
|
|
72
|
+
'段': ' Range',
|
|
73
|
+
};
|
|
74
|
+
return map[cnText] || cnText;
|
|
75
|
+
}
|
|
76
|
+
return cnText;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* 将相对日期转为中文问句
|
|
80
|
+
*/
|
|
81
|
+
const relativeDateToQuestion = (value) => {
|
|
82
|
+
let toAdd = '';
|
|
83
|
+
const tws = (0, date_1.getSupportedTimeWindows)().reverse();
|
|
84
|
+
for (const tw of tws) {
|
|
85
|
+
if (tw in value) {
|
|
86
|
+
const chinese = twToChinese(tw);
|
|
87
|
+
if (chinese) {
|
|
88
|
+
if (typeof value[tw] === 'object') {
|
|
89
|
+
if (value[tw].$gte && value[tw].$lte) {
|
|
90
|
+
toAdd += `${value[tw].$gte}-${value[tw].$lte}${chinese}`;
|
|
91
|
+
}
|
|
92
|
+
else if (value[tw].$in) {
|
|
93
|
+
toAdd += `${value[tw].$in.join(',')}${chinese}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
toAdd += `${value[tw]}${chinese}`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (value.$offset) {
|
|
103
|
+
if (value.$offset.year === 0) {
|
|
104
|
+
toAdd += '今年';
|
|
105
|
+
}
|
|
106
|
+
else if (value.$offset.year === -1) {
|
|
107
|
+
toAdd += '去年';
|
|
108
|
+
}
|
|
109
|
+
else if (value.$offset.year) {
|
|
110
|
+
toAdd += `${-value.$offset.year}年前`;
|
|
111
|
+
}
|
|
112
|
+
if (value.$offset.quarter === 0) {
|
|
113
|
+
toAdd += '本季度';
|
|
114
|
+
}
|
|
115
|
+
else if (value.$offset.quarter === -1) {
|
|
116
|
+
toAdd += '上季度';
|
|
117
|
+
}
|
|
118
|
+
else if (value.$offset.quarter) {
|
|
119
|
+
toAdd += `${-value.$offset.quarter}季度前`;
|
|
120
|
+
}
|
|
121
|
+
if (value.$offset.month === 0) {
|
|
122
|
+
toAdd += '本月';
|
|
123
|
+
}
|
|
124
|
+
else if (value.$offset.month === -1) {
|
|
125
|
+
toAdd += '上月';
|
|
126
|
+
}
|
|
127
|
+
else if (value.$offset.month) {
|
|
128
|
+
toAdd += `${-value.$offset.month}个月前`;
|
|
129
|
+
}
|
|
130
|
+
if (value.$offset.week === -1) {
|
|
131
|
+
toAdd += `上周`;
|
|
132
|
+
}
|
|
133
|
+
else if (value.$offset.week) {
|
|
134
|
+
toAdd += `${-value.$offset.week}周前`;
|
|
135
|
+
}
|
|
136
|
+
else if (value.$offset.week === 0) {
|
|
137
|
+
toAdd += '本周';
|
|
138
|
+
}
|
|
139
|
+
if (value.weekday) {
|
|
140
|
+
const weekdayMap = {
|
|
141
|
+
1: '周一',
|
|
142
|
+
2: '周二',
|
|
143
|
+
3: '周三',
|
|
144
|
+
4: '周四',
|
|
145
|
+
5: '周五',
|
|
146
|
+
6: '周六',
|
|
147
|
+
7: '周日',
|
|
148
|
+
};
|
|
149
|
+
toAdd += weekdayMap[value.weekday] || '';
|
|
150
|
+
}
|
|
151
|
+
if (value.$offset.day === 0) {
|
|
152
|
+
toAdd += '今天';
|
|
153
|
+
}
|
|
154
|
+
else if (value.$offset.day === -1) {
|
|
155
|
+
toAdd += '昨天';
|
|
156
|
+
}
|
|
157
|
+
else if (value.$offset.day) {
|
|
158
|
+
toAdd += `${-value.$offset.day}天前`;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return toAdd;
|
|
162
|
+
};
|
|
163
|
+
// moment的帮助函数
|
|
164
|
+
const momentGetOneIndexedMonthByLevel = (date, level) => {
|
|
165
|
+
if (level === 'month') {
|
|
166
|
+
return date.get(level) + 1;
|
|
167
|
+
}
|
|
168
|
+
if (level === 'day') {
|
|
169
|
+
return date.get('date');
|
|
170
|
+
}
|
|
171
|
+
return date.get(level);
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* 将标准日期格式转为问句
|
|
175
|
+
*/
|
|
176
|
+
const normalizedDateFormToQuestion = (date) => {
|
|
177
|
+
const start = (0, moment_1.default)(date.$gte);
|
|
178
|
+
const end = (0, moment_1.default)(date.$lte);
|
|
179
|
+
const formatter = 'YYYYMMDDHHmmss';
|
|
180
|
+
const levels = ['year', 'quarter', 'month', 'date'];
|
|
181
|
+
const processLevel = (levelIndex, baseRelativeForm = {}) => {
|
|
182
|
+
const level = levels[levelIndex];
|
|
183
|
+
if (!level)
|
|
184
|
+
return null;
|
|
185
|
+
if (start.get(level) === end.get(level)) {
|
|
186
|
+
if (start.format(formatter) === (0, moment_1.default)(start).startOf(level).format(formatter) &&
|
|
187
|
+
end.format(formatter) === (0, moment_1.default)(end).endOf(level).format(formatter)) {
|
|
188
|
+
const levelKey = level === 'date' ? 'day' : level;
|
|
189
|
+
const relativeDateForm = Object.assign(Object.assign({}, baseRelativeForm), { [levelKey]: momentGetOneIndexedMonthByLevel(start, level) });
|
|
190
|
+
if (relativeDateForm.month) {
|
|
191
|
+
delete relativeDateForm.quarter;
|
|
192
|
+
}
|
|
193
|
+
if (relativeDateForm.day) {
|
|
194
|
+
delete relativeDateForm.week;
|
|
195
|
+
}
|
|
196
|
+
return relativeDateToQuestion(relativeDateForm);
|
|
197
|
+
}
|
|
198
|
+
if (levelIndex >= levels.length) {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
const newBaseRelativeForm = Object.assign(Object.assign({}, baseRelativeForm), { [level]: momentGetOneIndexedMonthByLevel(start, level) });
|
|
202
|
+
const innerQuestion = processLevel(levelIndex + 1, newBaseRelativeForm);
|
|
203
|
+
if (innerQuestion)
|
|
204
|
+
return innerQuestion;
|
|
205
|
+
// XTD
|
|
206
|
+
if (!innerQuestion) {
|
|
207
|
+
if (start.isSame((0, moment_1.default)(start).startOf(level)) && end.isSame((0, moment_1.default)().endOf('day'))) {
|
|
208
|
+
switch (level) {
|
|
209
|
+
case 'year':
|
|
210
|
+
return 'YTD';
|
|
211
|
+
case 'quarter':
|
|
212
|
+
return 'QTD';
|
|
213
|
+
case 'month':
|
|
214
|
+
return 'MTD';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
};
|
|
222
|
+
const ret = processLevel(0, {});
|
|
223
|
+
if (ret)
|
|
224
|
+
return ret;
|
|
225
|
+
let startString = start.format('YYYY-MM-DD HH:mm:ss');
|
|
226
|
+
let endString = end.format('YYYY-MM-DD HH:mm:ss');
|
|
227
|
+
if (startString.endsWith(' 00:00:00') && endString.endsWith(' 23:59:59')) {
|
|
228
|
+
startString = startString.substring(0, 10);
|
|
229
|
+
endString = endString.substring(0, 10);
|
|
230
|
+
}
|
|
231
|
+
return `${startString}~${endString}`;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* 将相对日期格式标准化
|
|
235
|
+
*/
|
|
236
|
+
const normaliseRelativeDateForm = (value, config = {}) => {
|
|
237
|
+
if (config.startOfWeek === 'sunday') {
|
|
238
|
+
moment_1.default.locale('en');
|
|
239
|
+
}
|
|
240
|
+
let startDate = (0, moment_1.default)();
|
|
241
|
+
let endDate = (0, moment_1.default)();
|
|
242
|
+
const tws = (0, date_1.getSupportedTimeWindows)();
|
|
243
|
+
let granuality;
|
|
244
|
+
const others = {};
|
|
245
|
+
if (value.$calendar) {
|
|
246
|
+
others.$calendar = value.$calendar;
|
|
247
|
+
}
|
|
248
|
+
// 处理 $in 连续值
|
|
249
|
+
for (const [k, v] of Object.entries(value)) {
|
|
250
|
+
if (typeof v === 'object' && v && v.$in) {
|
|
251
|
+
let isContinuous = false;
|
|
252
|
+
const sorted = [...v.$in].sort((a, b) => a - b);
|
|
253
|
+
if (sorted[sorted.length - 1] - sorted[0] === sorted.length - 1) {
|
|
254
|
+
isContinuous = true;
|
|
255
|
+
}
|
|
256
|
+
if (isContinuous) {
|
|
257
|
+
value[k] = {
|
|
258
|
+
$gte: sorted[0],
|
|
259
|
+
$lte: sorted[sorted.length - 1],
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
let hasHitComplexDate = false;
|
|
265
|
+
if ('hour' in value && 'minute' in value && !('second' in value)) {
|
|
266
|
+
value.second = 0;
|
|
267
|
+
}
|
|
268
|
+
if (!('year' in value) && !('$offset' in value)) {
|
|
269
|
+
hasHitComplexDate = true;
|
|
270
|
+
if ('hour' in value && 'minute' in value && 'second' in value) {
|
|
271
|
+
others.$time = (0, moment_1.default)()
|
|
272
|
+
.hour(value.hour)
|
|
273
|
+
.minute(value.minute)
|
|
274
|
+
.second(value.second)
|
|
275
|
+
.format('HH:mm:ss');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (('year' in value || ('$offset' in value && 'year' in value.$offset)) &&
|
|
279
|
+
'day' in value &&
|
|
280
|
+
Object.keys(value).length === 2) {
|
|
281
|
+
hasHitComplexDate = true;
|
|
282
|
+
}
|
|
283
|
+
for (let index = tws.length - 1; index >= 0; index--) {
|
|
284
|
+
const tw = tws[index];
|
|
285
|
+
const valueInGran = value[tw];
|
|
286
|
+
if (tw in value) {
|
|
287
|
+
let twToSet = tw;
|
|
288
|
+
if (twToSet === 'day') {
|
|
289
|
+
twToSet = 'date';
|
|
290
|
+
}
|
|
291
|
+
else if (twToSet === 'weekday') {
|
|
292
|
+
twToSet = 'day';
|
|
293
|
+
}
|
|
294
|
+
if (!hasHitComplexDate && typeof valueInGran === 'number') {
|
|
295
|
+
granuality = tw;
|
|
296
|
+
if (twToSet === 'month') {
|
|
297
|
+
startDate.set(twToSet, valueInGran - 1);
|
|
298
|
+
endDate.set(twToSet, valueInGran - 1);
|
|
299
|
+
}
|
|
300
|
+
else if (twToSet === 'week') {
|
|
301
|
+
if (!value.month && !('$offset' in value && 'month' in value.$offset)) {
|
|
302
|
+
const twoDigitValue = `${valueInGran}`.padStart(2, '0');
|
|
303
|
+
startDate = (0, moment_1.default)(`${startDate.year()}${twoDigitValue}`, 'ggggww').startOf('week');
|
|
304
|
+
endDate = (0, moment_1.default)(startDate).endOf('week');
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
startDate.startOf('month').startOf('week');
|
|
308
|
+
endDate.startOf('month').endOf('week');
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
if ('period' in value && 'hour' in value && value.period === 'pm' && value.hour < 12) {
|
|
313
|
+
startDate.set(twToSet, valueInGran + 12);
|
|
314
|
+
endDate.set(twToSet, valueInGran + 12);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
startDate.set(twToSet, valueInGran);
|
|
318
|
+
endDate.set(twToSet, valueInGran);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
else if (!hasHitComplexDate &&
|
|
323
|
+
valueInGran.$gte &&
|
|
324
|
+
valueInGran.$lte &&
|
|
325
|
+
Object.keys(valueInGran).length === 2) {
|
|
326
|
+
granuality = tw;
|
|
327
|
+
if (twToSet === 'month') {
|
|
328
|
+
startDate.set(twToSet, valueInGran.$gte - 1);
|
|
329
|
+
endDate.set(twToSet, valueInGran.$lte - 1);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
startDate.set(twToSet, valueInGran.$gte);
|
|
333
|
+
endDate.set(twToSet, valueInGran.$lte);
|
|
334
|
+
}
|
|
335
|
+
hasHitComplexDate = true;
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
others[`$${tw}`] = valueInGran;
|
|
339
|
+
hasHitComplexDate = true;
|
|
340
|
+
if (tw === 'year') {
|
|
341
|
+
granuality = 'year';
|
|
342
|
+
if (typeof valueInGran === 'object' && valueInGran.$in) {
|
|
343
|
+
const startYear = Math.min(...valueInGran.$in);
|
|
344
|
+
const endYear = Math.max(...valueInGran.$in);
|
|
345
|
+
startDate.set('year', startYear);
|
|
346
|
+
endDate.set('year', endYear);
|
|
347
|
+
}
|
|
348
|
+
else if (typeof valueInGran === 'number') {
|
|
349
|
+
startDate.set('year', valueInGran);
|
|
350
|
+
endDate.set('year', valueInGran);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if ('$offset' in value && tw in value.$offset) {
|
|
356
|
+
if (!granuality || tws.indexOf(tw) < tws.indexOf(granuality)) {
|
|
357
|
+
granuality = tw;
|
|
358
|
+
}
|
|
359
|
+
startDate.add(value.$offset[tw], tw);
|
|
360
|
+
endDate.add(value.$offset[tw], tw);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const getMomentGran = (gran) => {
|
|
364
|
+
let momentGran = gran;
|
|
365
|
+
if (gran === 'weekday')
|
|
366
|
+
momentGran = 'day';
|
|
367
|
+
return momentGran || 'day';
|
|
368
|
+
};
|
|
369
|
+
const momentGran = getMomentGran(granuality);
|
|
370
|
+
const normed = Object.assign({ $gte: startDate.startOf(momentGran).toDate(), $lte: endDate.endOf(momentGran).toDate(), $options: Object.assign({}, value) }, others);
|
|
371
|
+
if (!granuality) {
|
|
372
|
+
delete normed.$gte;
|
|
373
|
+
delete normed.$lte;
|
|
374
|
+
}
|
|
375
|
+
if (normed.$options) {
|
|
376
|
+
delete normed.$options.$calendar;
|
|
377
|
+
}
|
|
378
|
+
moment_1.default.locale('zh-cn');
|
|
379
|
+
return normed;
|
|
380
|
+
};
|
|
381
|
+
// ============== nameForValue ==============
|
|
382
|
+
const nameForValue = (property, value, prefix) => {
|
|
383
|
+
let toAdd = '';
|
|
384
|
+
let propertyNameUsed = false;
|
|
385
|
+
if (property.primal_type === 'boolean') {
|
|
386
|
+
let negativePrefix = '';
|
|
387
|
+
if (value === true) {
|
|
388
|
+
negativePrefix = '';
|
|
389
|
+
}
|
|
390
|
+
else if (value === false) {
|
|
391
|
+
negativePrefix = '非';
|
|
392
|
+
}
|
|
393
|
+
else if (typeof value === 'object' && '$ne' in value) {
|
|
394
|
+
if (value.$ne)
|
|
395
|
+
negativePrefix = '非';
|
|
396
|
+
}
|
|
397
|
+
let booleanPredName = property.name;
|
|
398
|
+
if (booleanPredName.startsWith('是否')) {
|
|
399
|
+
booleanPredName = booleanPredName.slice(2);
|
|
400
|
+
}
|
|
401
|
+
else if (booleanPredName.startsWith('是不是')) {
|
|
402
|
+
booleanPredName = booleanPredName.slice(3);
|
|
403
|
+
}
|
|
404
|
+
toAdd = `${negativePrefix}${booleanPredName}`;
|
|
405
|
+
propertyNameUsed = true;
|
|
406
|
+
}
|
|
407
|
+
else if (property.primal_type === 'date') {
|
|
408
|
+
if ((0, date_1.isRelativeDateForm)(value) || typeof value === 'string') {
|
|
409
|
+
let postfix = '';
|
|
410
|
+
if (prefix === '大于等于') {
|
|
411
|
+
postfix = '以后';
|
|
412
|
+
}
|
|
413
|
+
else if (prefix === '小于等于') {
|
|
414
|
+
postfix = '以前';
|
|
415
|
+
}
|
|
416
|
+
if ((0, date_1.isRelativeDateForm)(value)) {
|
|
417
|
+
toAdd = relativeDateToQuestion(value);
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
toAdd = value;
|
|
421
|
+
if ((0, moment_1.default)(toAdd).format('MMDDmmss') === '01010000') {
|
|
422
|
+
toAdd = (0, moment_1.default)(toAdd).format('YYYY年');
|
|
423
|
+
}
|
|
424
|
+
else if ((0, moment_1.default)(toAdd).format('HHmmss') === '000000') {
|
|
425
|
+
toAdd = (0, moment_1.default)(toAdd).format('YYYY年MM月DD日');
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
toAdd = `${toAdd}${postfix}`;
|
|
429
|
+
}
|
|
430
|
+
else if (typeof value === 'object' && value.$options && typeof value.$options === 'string') {
|
|
431
|
+
toAdd = value.$options;
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
let low = value.$gte || value.$gt;
|
|
435
|
+
let high = value.$lte || value.$lt;
|
|
436
|
+
if (low && high) {
|
|
437
|
+
if ((0, date_1.isRelativeDateForm)(low)) {
|
|
438
|
+
if (value.$gte) {
|
|
439
|
+
low = normaliseRelativeDateForm(low).$gte;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
low = normaliseRelativeDateForm(low).$lte;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if ((0, date_1.isRelativeDateForm)(high)) {
|
|
446
|
+
if (value.$lte) {
|
|
447
|
+
high = normaliseRelativeDateForm(high).$lte;
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
high = normaliseRelativeDateForm(high).$gte;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
toAdd = normalizedDateFormToQuestion({
|
|
455
|
+
$gte: low,
|
|
456
|
+
$lte: high,
|
|
457
|
+
});
|
|
458
|
+
// $month, $year, etc...
|
|
459
|
+
const tws = (0, date_1.getSupportedTimeWindows)().reverse();
|
|
460
|
+
for (const tw of tws) {
|
|
461
|
+
if (`$${tw}` in value || tw in value) {
|
|
462
|
+
const data = value[`$${tw}`] || value[tw];
|
|
463
|
+
if (typeof data === 'object') {
|
|
464
|
+
if (data.$in) {
|
|
465
|
+
toAdd += `,${data.$in.join(',')}${twToChinese(tw)}`;
|
|
466
|
+
}
|
|
467
|
+
if (data.$gte && data.$lte) {
|
|
468
|
+
toAdd += `,${data.$gte}~${data.$lte}${twToChinese(tw)}`;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
else if (property.primal_type === 'object' && typeof value === 'boolean') {
|
|
476
|
+
if (value) {
|
|
477
|
+
toAdd = property.name;
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
toAdd = `无${property.name}`;
|
|
481
|
+
}
|
|
482
|
+
propertyNameUsed = true;
|
|
483
|
+
}
|
|
484
|
+
else if (typeof value === 'object' && '$exists' in value) {
|
|
485
|
+
if (value.$exists) {
|
|
486
|
+
toAdd = `有${property.name}`;
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
toAdd = `无${property.name}`;
|
|
490
|
+
}
|
|
491
|
+
propertyNameUsed = true;
|
|
492
|
+
}
|
|
493
|
+
else if (property.primal_type === 'object' && typeof value === 'object' && value.name) {
|
|
494
|
+
toAdd = value.name;
|
|
495
|
+
}
|
|
496
|
+
else if (typeof value !== 'object') {
|
|
497
|
+
toAdd += `${value}`;
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
console.error(`[nameForQuery]未考虑到的情况: ${JSON.stringify(value)} `);
|
|
501
|
+
}
|
|
502
|
+
return { toAdd, propertyNameUsed };
|
|
503
|
+
};
|
|
504
|
+
// ============== nameForQuery ==============
|
|
505
|
+
/**
|
|
506
|
+
* 给Query起名
|
|
507
|
+
*/
|
|
508
|
+
const nameForQuery = (query, schema, schemas) => {
|
|
509
|
+
const names = [];
|
|
510
|
+
for (const [pred, value] of Object.entries(query)) {
|
|
511
|
+
const property = (0, schema_utils_1.findPropertyByName)(schema._id, pred, schemas);
|
|
512
|
+
if (!property)
|
|
513
|
+
continue;
|
|
514
|
+
// skip agg_key
|
|
515
|
+
if (schema.agg_key && schema.agg_key.key === property.name)
|
|
516
|
+
continue;
|
|
517
|
+
const shouldNotAddPropertyName = property.primal_type === 'date' ||
|
|
518
|
+
property.is_categorical ||
|
|
519
|
+
property.is_name ||
|
|
520
|
+
property.primal_type === 'object';
|
|
521
|
+
let toAdd = '';
|
|
522
|
+
let propertyNameUsed = false;
|
|
523
|
+
if (typeof value === 'object' && value !== null) {
|
|
524
|
+
if ('schema' in value && 'query' in value) {
|
|
525
|
+
toAdd += (0, exports.nameForQuery)(value.query, schemas[value.schema], schemas);
|
|
526
|
+
}
|
|
527
|
+
else if (property.primal_type === 'date' &&
|
|
528
|
+
((0, date_1.isStandardDateForm)(value) || (0, date_1.isRelativeDateForm)(value))) {
|
|
529
|
+
const res = nameForValue(property, value);
|
|
530
|
+
toAdd = res.toAdd;
|
|
531
|
+
propertyNameUsed = res.propertyNameUsed;
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
Object.entries(value).forEach(([k, v]) => {
|
|
535
|
+
let shouldRunNameForValue = true;
|
|
536
|
+
if ('$gte' === k) {
|
|
537
|
+
toAdd += '大于等于';
|
|
538
|
+
}
|
|
539
|
+
else if ('$gt' === k) {
|
|
540
|
+
toAdd += '大于';
|
|
541
|
+
}
|
|
542
|
+
else if ('$ne' === k) {
|
|
543
|
+
toAdd += '不等于';
|
|
544
|
+
}
|
|
545
|
+
else if ('$eq' === k) {
|
|
546
|
+
toAdd += '为';
|
|
547
|
+
}
|
|
548
|
+
else if ('$lte' === k) {
|
|
549
|
+
toAdd += '小于等于';
|
|
550
|
+
}
|
|
551
|
+
else if ('$lt' === k) {
|
|
552
|
+
toAdd += '小于';
|
|
553
|
+
}
|
|
554
|
+
else if ('$exists' === k) {
|
|
555
|
+
toAdd += `${v ? (property.primal_type === 'object' ? '' : '有') : '无'}${property.name}`;
|
|
556
|
+
propertyNameUsed = true;
|
|
557
|
+
shouldRunNameForValue = false;
|
|
558
|
+
}
|
|
559
|
+
else if ('$regex' === k) {
|
|
560
|
+
propertyNameUsed = true;
|
|
561
|
+
shouldRunNameForValue = false;
|
|
562
|
+
}
|
|
563
|
+
else if ('$in' === k) {
|
|
564
|
+
toAdd = v
|
|
565
|
+
.map((vv) => {
|
|
566
|
+
return (0, exports.nameForQuery)({
|
|
567
|
+
[pred]: vv,
|
|
568
|
+
}, schema, schemas);
|
|
569
|
+
})
|
|
570
|
+
.join('或');
|
|
571
|
+
propertyNameUsed = true;
|
|
572
|
+
shouldRunNameForValue = false;
|
|
573
|
+
}
|
|
574
|
+
else if ('$nin' === k) {
|
|
575
|
+
toAdd =
|
|
576
|
+
'非' +
|
|
577
|
+
v
|
|
578
|
+
.map((vv) => {
|
|
579
|
+
return (0, exports.nameForQuery)({
|
|
580
|
+
[pred]: vv,
|
|
581
|
+
}, schema, schemas);
|
|
582
|
+
})
|
|
583
|
+
.join('且');
|
|
584
|
+
propertyNameUsed = true;
|
|
585
|
+
shouldRunNameForValue = false;
|
|
586
|
+
}
|
|
587
|
+
if (shouldRunNameForValue) {
|
|
588
|
+
const res = nameForValue(property, v, toAdd);
|
|
589
|
+
if (property.primal_type === 'date') {
|
|
590
|
+
toAdd = '';
|
|
591
|
+
}
|
|
592
|
+
toAdd += res.toAdd;
|
|
593
|
+
propertyNameUsed = res.propertyNameUsed;
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
if (!shouldNotAddPropertyName) {
|
|
600
|
+
toAdd = '为';
|
|
601
|
+
}
|
|
602
|
+
const res = nameForValue(property, value, toAdd);
|
|
603
|
+
toAdd = toAdd + res.toAdd;
|
|
604
|
+
propertyNameUsed = res.propertyNameUsed;
|
|
605
|
+
}
|
|
606
|
+
if (!shouldNotAddPropertyName && !propertyNameUsed) {
|
|
607
|
+
toAdd = `${property.name}${toAdd}`;
|
|
608
|
+
}
|
|
609
|
+
names.push(toAdd);
|
|
610
|
+
}
|
|
611
|
+
let name = '';
|
|
612
|
+
for (let i = 0; i < names.length; i++) {
|
|
613
|
+
const element = names[i];
|
|
614
|
+
if (i > 0) {
|
|
615
|
+
const prev = names[i - 1];
|
|
616
|
+
if (prev.match('\\d$') && element.match('^\\d')) {
|
|
617
|
+
name += `,${element}`;
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
if (prev.match('[a-zA-Z]$') && element.match('^[a-zA-Z]')) {
|
|
621
|
+
name += ` ${element}`;
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
name += element;
|
|
626
|
+
}
|
|
627
|
+
return name;
|
|
628
|
+
};
|
|
629
|
+
exports.nameForQuery = nameForQuery;
|
|
630
|
+
// ============== nameForPredNode ==============
|
|
631
|
+
/**
|
|
632
|
+
* 给pred node起名, normalize阶段用到
|
|
633
|
+
* @param predNode - PredItemType
|
|
634
|
+
* @param s - schema object
|
|
635
|
+
* @param ctx - 上下文对象
|
|
636
|
+
* @returns 名称字符串
|
|
637
|
+
*/
|
|
638
|
+
const nameForPredNode = (predNode, s, ctx) => {
|
|
639
|
+
var _a, _b, _c, _d;
|
|
640
|
+
const { schemas, customFunctions, locale = 'zh-CN' } = ctx;
|
|
641
|
+
if (typeof predNode !== 'object')
|
|
642
|
+
return null;
|
|
643
|
+
const schema = predNode.schema ? schemas[predNode.schema] : s;
|
|
644
|
+
let name = '';
|
|
645
|
+
// query
|
|
646
|
+
if (predNode.query) {
|
|
647
|
+
name += (0, exports.nameForQuery)(predNode.query, schema, schemas);
|
|
648
|
+
}
|
|
649
|
+
// operator
|
|
650
|
+
let useAggKey = false;
|
|
651
|
+
if (predNode.query && schema.agg_key && schema.agg_key.key in predNode.query) {
|
|
652
|
+
let keyName;
|
|
653
|
+
if (typeof predNode.query[schema.agg_key.key] === 'object' &&
|
|
654
|
+
predNode.query[schema.agg_key.key].query) {
|
|
655
|
+
keyName = Object.values(predNode.query[schema.agg_key.key].query)[0];
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
keyName = predNode.query[schema.agg_key.key];
|
|
659
|
+
}
|
|
660
|
+
useAggKey = true;
|
|
661
|
+
let onlyValue = keyName;
|
|
662
|
+
while (typeof onlyValue === 'object') {
|
|
663
|
+
onlyValue = Object.values(onlyValue)[0];
|
|
664
|
+
}
|
|
665
|
+
name += onlyValue;
|
|
666
|
+
}
|
|
667
|
+
let defaultNameCalled = false;
|
|
668
|
+
if (predNode.operator) {
|
|
669
|
+
const func = (0, utils_1.findOneCustomFunction)(predNode.schema || schema._id, predNode.operator, customFunctions);
|
|
670
|
+
if (!func) {
|
|
671
|
+
throw new Error(`未注册的函数:${predNode.operator}`);
|
|
672
|
+
}
|
|
673
|
+
let basePredName = null;
|
|
674
|
+
let baseProperty = null;
|
|
675
|
+
if (typeof predNode.pred === 'object') {
|
|
676
|
+
basePredName = (0, exports.nameForPredNode)(predNode.pred, schema, ctx);
|
|
677
|
+
}
|
|
678
|
+
else if (predNode.pred) {
|
|
679
|
+
baseProperty = (0, schema_utils_1.findPropertyByName)(schema._id, predNode.pred, schemas);
|
|
680
|
+
if (baseProperty) {
|
|
681
|
+
basePredName = getPropertyName(baseProperty);
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
basePredName = predNode.pred;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
if (predNode.by) {
|
|
688
|
+
const addNameForByItem = (byItem) => {
|
|
689
|
+
if ([
|
|
690
|
+
'$year',
|
|
691
|
+
'$quarter',
|
|
692
|
+
'$month',
|
|
693
|
+
'$week',
|
|
694
|
+
'$weekday',
|
|
695
|
+
'$day',
|
|
696
|
+
'$hour',
|
|
697
|
+
'$minute',
|
|
698
|
+
'$second',
|
|
699
|
+
].includes(byItem)) {
|
|
700
|
+
const dateLevelString = byItem.substring(1);
|
|
701
|
+
switch (dateLevelString) {
|
|
702
|
+
case 'year':
|
|
703
|
+
name += zhCNToOthers('年', locale);
|
|
704
|
+
break;
|
|
705
|
+
case 'quarter':
|
|
706
|
+
name += zhCNToOthers('季度', locale);
|
|
707
|
+
break;
|
|
708
|
+
case 'month':
|
|
709
|
+
name += zhCNToOthers('月', locale);
|
|
710
|
+
break;
|
|
711
|
+
case 'week':
|
|
712
|
+
name += zhCNToOthers('周', locale);
|
|
713
|
+
break;
|
|
714
|
+
case 'weekday':
|
|
715
|
+
name += zhCNToOthers('星期', locale);
|
|
716
|
+
break;
|
|
717
|
+
case 'day':
|
|
718
|
+
name += zhCNToOthers('日', locale);
|
|
719
|
+
break;
|
|
720
|
+
case 'hour':
|
|
721
|
+
name += zhCNToOthers('小时', locale);
|
|
722
|
+
break;
|
|
723
|
+
case 'minute':
|
|
724
|
+
name += zhCNToOthers('分钟', locale);
|
|
725
|
+
break;
|
|
726
|
+
case 'second':
|
|
727
|
+
name += zhCNToOthers('秒', locale);
|
|
728
|
+
break;
|
|
729
|
+
default:
|
|
730
|
+
throw new Error(`[nameForPred]不支持的日期级别:${dateLevelString}`);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
name += byItem;
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
if (typeof predNode.by === 'string') {
|
|
738
|
+
addNameForByItem(predNode.by);
|
|
739
|
+
}
|
|
740
|
+
else if (Array.isArray(predNode.by)) {
|
|
741
|
+
predNode.by.forEach((byItem) => addNameForByItem(byItem));
|
|
742
|
+
}
|
|
743
|
+
name += zhCNToOthers('均', locale);
|
|
744
|
+
}
|
|
745
|
+
if (func && func.defaultName) {
|
|
746
|
+
if (func.name === '$sql') {
|
|
747
|
+
name += func.defaultName(Object.assign(Object.assign({}, predNode), { schema }), locale, Object.assign(Object.assign({}, ctx), { nameForPredNode: exports.nameForPredNode }));
|
|
748
|
+
}
|
|
749
|
+
else if (func.name === '$count_recent' || func.name === '$count_repeat' || func.name === '$sql') {
|
|
750
|
+
name = func.defaultName(Object.assign(Object.assign({}, predNode), { name: basePredName, schema }), locale, Object.assign(Object.assign({}, ctx), { nameForPredNode: exports.nameForPredNode }));
|
|
751
|
+
}
|
|
752
|
+
else if (!(useAggKey && predNode.pred === ((_a = schema.agg_key) === null || _a === void 0 ? void 0 : _a.value))) {
|
|
753
|
+
name += func.defaultName(Object.assign(Object.assign(Object.assign({}, predNode), (baseProperty || {})), { name: basePredName, schema }), locale, Object.assign(Object.assign({}, ctx), { nameForPredNode: exports.nameForPredNode }));
|
|
754
|
+
}
|
|
755
|
+
defaultNameCalled = true;
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
switch (predNode.operator) {
|
|
759
|
+
case '$hour':
|
|
760
|
+
name += `${zhCNToOthers('每小时', locale)}${basePredName}`;
|
|
761
|
+
break;
|
|
762
|
+
case '$toHour':
|
|
763
|
+
name += `${zhCNToOthers('每小时段', locale)}${basePredName}`;
|
|
764
|
+
break;
|
|
765
|
+
case '$weekday':
|
|
766
|
+
name += `${zhCNToOthers('分星期', locale)}${basePredName}`;
|
|
767
|
+
break;
|
|
768
|
+
case '$day':
|
|
769
|
+
name += `${zhCNToOthers('日', locale)}${basePredName}`;
|
|
770
|
+
break;
|
|
771
|
+
case '$year':
|
|
772
|
+
name += `${zhCNToOthers('年', locale)}${basePredName}`;
|
|
773
|
+
break;
|
|
774
|
+
case '$week':
|
|
775
|
+
name += `${zhCNToOthers('周', locale)}${basePredName}`;
|
|
776
|
+
break;
|
|
777
|
+
case '$month':
|
|
778
|
+
name += `${zhCNToOthers('月', locale)}${basePredName}`;
|
|
779
|
+
break;
|
|
780
|
+
case '$quarter':
|
|
781
|
+
name += `${zhCNToOthers('季度', locale)}${basePredName}`;
|
|
782
|
+
break;
|
|
783
|
+
case '$yoy':
|
|
784
|
+
case '$mom':
|
|
785
|
+
case '$wow':
|
|
786
|
+
case '$qoq':
|
|
787
|
+
case '$yoyd':
|
|
788
|
+
case '$momd':
|
|
789
|
+
case '$sply':
|
|
790
|
+
case '$splm':
|
|
791
|
+
case '$splw': {
|
|
792
|
+
const map = {
|
|
793
|
+
$yoy: '同比',
|
|
794
|
+
$mom: '环比',
|
|
795
|
+
$wow: '周环比',
|
|
796
|
+
$qoq: '季度环比',
|
|
797
|
+
$yoyd: '同比差值',
|
|
798
|
+
$momd: '环比差值',
|
|
799
|
+
$sply: '同期',
|
|
800
|
+
$splm: '环期',
|
|
801
|
+
$splw: '周环期',
|
|
802
|
+
};
|
|
803
|
+
if (map[predNode.operator] === '环期') {
|
|
804
|
+
name += `${zhCNToOthers('上期', locale)}${basePredName}`;
|
|
805
|
+
}
|
|
806
|
+
else if (map[predNode.operator] === '同期') {
|
|
807
|
+
name += `${zhCNToOthers(map[predNode.operator], locale)}${basePredName}`;
|
|
808
|
+
}
|
|
809
|
+
else {
|
|
810
|
+
name += `${basePredName}${zhCNToOthers(map[predNode.operator], locale)}`;
|
|
811
|
+
}
|
|
812
|
+
if (predNode.params) {
|
|
813
|
+
if ((_b = predNode.params[0]) === null || _b === void 0 ? void 0 : _b.time) {
|
|
814
|
+
const timestampProp = (0, schema_utils_1.findTimestampLikeProperty)(schema);
|
|
815
|
+
if (timestampProp) {
|
|
816
|
+
name += (0, exports.nameForQuery)({
|
|
817
|
+
[timestampProp.name]: predNode.params[0].time,
|
|
818
|
+
}, schema, schemas);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (((_c = predNode.params[0]) === null || _c === void 0 ? void 0 : _c.by) === 'lunar') {
|
|
822
|
+
name += zhCNToOthers('按农历', locale);
|
|
823
|
+
}
|
|
824
|
+
else if (((_d = predNode.params[0]) === null || _d === void 0 ? void 0 : _d.by) === 'weekday') {
|
|
825
|
+
name += zhCNToOthers('按星期', locale);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
830
|
+
case '$percentage':
|
|
831
|
+
if (predNode.pred) {
|
|
832
|
+
if (typeof predNode.pred === 'object') {
|
|
833
|
+
name += (0, exports.nameForPredNode)(predNode.pred, schema, ctx);
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
name += predNode.pred;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
name += zhCNToOthers('占比', locale);
|
|
840
|
+
break;
|
|
841
|
+
case '$uniq':
|
|
842
|
+
if (predNode.pred) {
|
|
843
|
+
if (typeof predNode.pred === 'object') {
|
|
844
|
+
name += (0, exports.nameForPredNode)(predNode.pred, schema, ctx);
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
name += predNode.pred;
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
name += zhCNToOthers('数量', locale);
|
|
851
|
+
break;
|
|
852
|
+
case '$dailyavg':
|
|
853
|
+
if (locale.startsWith('en')) {
|
|
854
|
+
name += `${basePredName} daily avg`;
|
|
855
|
+
}
|
|
856
|
+
else {
|
|
857
|
+
name += `${zhCNToOthers('日均', locale)}${basePredName}`;
|
|
858
|
+
}
|
|
859
|
+
break;
|
|
860
|
+
case '$monthlyavg':
|
|
861
|
+
if (locale.startsWith('en')) {
|
|
862
|
+
name += `${basePredName} monthly avg`;
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
name += `${zhCNToOthers('月均', locale)}${basePredName}`;
|
|
866
|
+
}
|
|
867
|
+
break;
|
|
868
|
+
case '$weeklyavg':
|
|
869
|
+
if (locale.startsWith('en')) {
|
|
870
|
+
name += `${basePredName} weekly avg`;
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
name += `${zhCNToOthers('周均', locale)}${basePredName}`;
|
|
874
|
+
}
|
|
875
|
+
break;
|
|
876
|
+
case '$piecewise':
|
|
877
|
+
name += `${basePredName}${zhCNToOthers('段', locale)}`;
|
|
878
|
+
break;
|
|
879
|
+
default:
|
|
880
|
+
name += predNode.operator;
|
|
881
|
+
break;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
else if (predNode.pred) {
|
|
886
|
+
if (predNode.pred === '*') {
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
name += predNode.pred;
|
|
890
|
+
}
|
|
891
|
+
// level
|
|
892
|
+
if (!defaultNameCalled && predNode.level) {
|
|
893
|
+
name += `(${predNode.level})`;
|
|
894
|
+
}
|
|
895
|
+
// accumulate
|
|
896
|
+
if (predNode.accumulate) {
|
|
897
|
+
if (locale.startsWith('en')) {
|
|
898
|
+
// do nothing
|
|
899
|
+
}
|
|
900
|
+
else {
|
|
901
|
+
name = `${zhCNToOthers('累计', locale)}${name}`;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
// feat: name 不能有下划线
|
|
905
|
+
return name.replace(/_/g, '');
|
|
906
|
+
};
|
|
907
|
+
exports.nameForPredNode = nameForPredNode;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PropertyType } from './property';
|
|
2
2
|
import { SchemaType } from './schema';
|
|
3
|
+
import { LogicformType } from '../logicform/logicform';
|
|
3
4
|
export declare const findPropertyByType: (type: string, schema: SchemaType) => PropertyType | undefined;
|
|
4
5
|
/**
|
|
5
6
|
* Find a property by name within a specific schema
|
|
@@ -15,6 +16,12 @@ export declare const findPropertyByName: (schemaID: string, propertyName: string
|
|
|
15
16
|
* @returns The property marked as display name (is_name=true or ui.name=true) or undefined if not found
|
|
16
17
|
*/
|
|
17
18
|
export declare const findDisplayNameProperty: (schema: SchemaType) => PropertyType | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* 找到schema中的timestamp属性
|
|
21
|
+
* @param schema - The runtime schema to search in
|
|
22
|
+
* @returns The property with type 'timestamp' or undefined if not found
|
|
23
|
+
*/
|
|
24
|
+
export declare const findTimestampLikeProperty: (schema: SchemaType) => PropertyType | undefined;
|
|
18
25
|
/**
|
|
19
26
|
* 以fromSchema为基础,找到toSchema中对应的property
|
|
20
27
|
* @param propertyName
|
|
@@ -22,3 +29,24 @@ export declare const findDisplayNameProperty: (schema: SchemaType) => PropertyTy
|
|
|
22
29
|
* @param toSchema
|
|
23
30
|
*/
|
|
24
31
|
export declare const findPropertyForOtherSchema: (propertyName: string, fromSchemaID: string, toSchemaID: string, schemasDict: Record<string, SchemaType>) => PropertyType | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* 获取hierarchy指定层级的累加代码长度
|
|
34
|
+
* @param schema - The schema with hierarchy
|
|
35
|
+
* @param name - The hierarchy level name to get accumulated code length for
|
|
36
|
+
* @returns The accumulated code length up to and including the specified level
|
|
37
|
+
* @throws Error if the level name is not found in the hierarchy
|
|
38
|
+
*/
|
|
39
|
+
export declare const getHierarchyCodeLength: (schema: SchemaType, name: string) => number;
|
|
40
|
+
/**
|
|
41
|
+
* 获取从fromNode到toNode的引用链
|
|
42
|
+
* @param fromNode - 起始节点的logicform
|
|
43
|
+
* @param toNode - 目标节点的logicform
|
|
44
|
+
* @param schemas - Schema字典
|
|
45
|
+
* @returns 引用链数组或包含错误信息的对象
|
|
46
|
+
*/
|
|
47
|
+
export declare const getRefChain: (fromNode: LogicformType, toNode: LogicformType, schemas: Record<string, SchemaType>) => {
|
|
48
|
+
property: PropertyType;
|
|
49
|
+
schema?: SchemaType;
|
|
50
|
+
}[] | {
|
|
51
|
+
error: string;
|
|
52
|
+
} | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.findPropertyForOtherSchema = exports.findDisplayNameProperty = exports.findPropertyByName = exports.findPropertyByType = void 0;
|
|
3
|
+
exports.getRefChain = exports.getHierarchyCodeLength = exports.findPropertyForOtherSchema = exports.findTimestampLikeProperty = exports.findDisplayNameProperty = exports.findPropertyByName = exports.findPropertyByType = void 0;
|
|
4
4
|
const findPropertyByType = (type, schema) => {
|
|
5
5
|
return schema.properties.find((property) => property.type === type);
|
|
6
6
|
};
|
|
@@ -65,6 +65,15 @@ const findDisplayNameProperty = (schema) => {
|
|
|
65
65
|
return undefined;
|
|
66
66
|
};
|
|
67
67
|
exports.findDisplayNameProperty = findDisplayNameProperty;
|
|
68
|
+
/**
|
|
69
|
+
* 找到schema中的timestamp属性
|
|
70
|
+
* @param schema - The runtime schema to search in
|
|
71
|
+
* @returns The property with type 'timestamp' or undefined if not found
|
|
72
|
+
*/
|
|
73
|
+
const findTimestampLikeProperty = (schema) => {
|
|
74
|
+
return schema.properties.find((property) => property.type === 'timestamp');
|
|
75
|
+
};
|
|
76
|
+
exports.findTimestampLikeProperty = findTimestampLikeProperty;
|
|
68
77
|
/**
|
|
69
78
|
* 以fromSchema为基础,找到toSchema中对应的property
|
|
70
79
|
* @param propertyName
|
|
@@ -98,3 +107,123 @@ const findPropertyForOtherSchema = (propertyName, fromSchemaID, toSchemaID, sche
|
|
|
98
107
|
return undefined;
|
|
99
108
|
};
|
|
100
109
|
exports.findPropertyForOtherSchema = findPropertyForOtherSchema;
|
|
110
|
+
/**
|
|
111
|
+
* 获取hierarchy指定层级的累加代码长度
|
|
112
|
+
* @param schema - The schema with hierarchy
|
|
113
|
+
* @param name - The hierarchy level name to get accumulated code length for
|
|
114
|
+
* @returns The accumulated code length up to and including the specified level
|
|
115
|
+
* @throws Error if the level name is not found in the hierarchy
|
|
116
|
+
*/
|
|
117
|
+
const getHierarchyCodeLength = (schema, name) => {
|
|
118
|
+
if (!schema.hierarchy) {
|
|
119
|
+
throw new Error(`${schema.name}中没有hierarchy`);
|
|
120
|
+
}
|
|
121
|
+
let codeLength = 0;
|
|
122
|
+
let nameFound = false;
|
|
123
|
+
for (const hierarchyItem of schema.hierarchy) {
|
|
124
|
+
codeLength += hierarchyItem.code_length;
|
|
125
|
+
if (hierarchyItem.name === name) {
|
|
126
|
+
nameFound = true;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!nameFound)
|
|
131
|
+
throw new Error(`${schema.name}中没有此level:${name}`);
|
|
132
|
+
return codeLength;
|
|
133
|
+
};
|
|
134
|
+
exports.getHierarchyCodeLength = getHierarchyCodeLength;
|
|
135
|
+
/**
|
|
136
|
+
* 获取从fromNode到toNode的引用链
|
|
137
|
+
* @param fromNode - 起始节点的logicform
|
|
138
|
+
* @param toNode - 目标节点的logicform
|
|
139
|
+
* @param schemas - Schema字典
|
|
140
|
+
* @returns 引用链数组或包含错误信息的对象
|
|
141
|
+
*/
|
|
142
|
+
const getRefChain = (fromNode, toNode, schemas) => {
|
|
143
|
+
const getError = (p) => {
|
|
144
|
+
// granularity check
|
|
145
|
+
if (p.granularity && schemas[fromNode.schema].hierarchy) {
|
|
146
|
+
let levelLength;
|
|
147
|
+
if (fromNode.entity_id) {
|
|
148
|
+
levelLength = fromNode.entity_id.length;
|
|
149
|
+
}
|
|
150
|
+
else if (fromNode.groupby && fromNode.groupby.find((gi) => gi.level)) {
|
|
151
|
+
const levelGI = fromNode.groupby.find((gi) => gi.level);
|
|
152
|
+
if (levelGI === null || levelGI === void 0 ? void 0 : levelGI.level) {
|
|
153
|
+
levelLength = (0, exports.getHierarchyCodeLength)(schemas[fromNode.schema], levelGI.level);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (levelLength && p.granularity) {
|
|
157
|
+
// granularity check
|
|
158
|
+
const maxCodeLength = (0, exports.getHierarchyCodeLength)(schemas[fromNode.schema], p.granularity);
|
|
159
|
+
if (maxCodeLength && maxCodeLength < levelLength) {
|
|
160
|
+
return `**${schemas[toNode.schema].name}**中,**${p.name}**要求为${p.granularity}以上。暂无法回答此问题。请联系技术支持。`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
};
|
|
166
|
+
let error = null;
|
|
167
|
+
// 优先拿直接能找到的,找不到再用一个dfs来找
|
|
168
|
+
const directFound = schemas[toNode.schema].properties.find((p) => {
|
|
169
|
+
if (!p.ref)
|
|
170
|
+
return false;
|
|
171
|
+
if (p.is_supplementary)
|
|
172
|
+
return false;
|
|
173
|
+
if (getError(p))
|
|
174
|
+
return false;
|
|
175
|
+
if (p.ref !== fromNode.schema)
|
|
176
|
+
return false;
|
|
177
|
+
const constraintsWithRole = p.constraints;
|
|
178
|
+
const fromNodeWithRole = fromNode;
|
|
179
|
+
if ((constraintsWithRole === null || constraintsWithRole === void 0 ? void 0 : constraintsWithRole.role) &&
|
|
180
|
+
(fromNodeWithRole === null || fromNodeWithRole === void 0 ? void 0 : fromNodeWithRole._role) &&
|
|
181
|
+
!Object.keys(constraintsWithRole.role).every((k) => constraintsWithRole.role[k] === fromNodeWithRole._role[k])) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return true;
|
|
185
|
+
});
|
|
186
|
+
if (directFound) {
|
|
187
|
+
return [{ property: directFound }];
|
|
188
|
+
}
|
|
189
|
+
// 一个dfs
|
|
190
|
+
const fromTo = (from, to, chain = []) => {
|
|
191
|
+
// max depth
|
|
192
|
+
if (chain.length > 10)
|
|
193
|
+
return null;
|
|
194
|
+
const schema = schemas[from];
|
|
195
|
+
for (const property of schema.properties) {
|
|
196
|
+
if (property.type === 'object' && !property.is_supplementary && property.ref && schemas[property.ref]) {
|
|
197
|
+
if (chain.length > 0) {
|
|
198
|
+
const lastItem = chain[chain.length - 1];
|
|
199
|
+
if (lastItem.schema._id === schema._id && lastItem.property.name === property.name) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const newChain = [...chain, { property, schema: schemas[property.ref] }];
|
|
204
|
+
if (property.ref === to) {
|
|
205
|
+
// sanity check
|
|
206
|
+
const errorMsg = getError(property);
|
|
207
|
+
if (errorMsg) {
|
|
208
|
+
error = errorMsg;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
return newChain;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
const nestedChain = fromTo(property.ref, to, newChain);
|
|
215
|
+
if (nestedChain) {
|
|
216
|
+
return nestedChain;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
};
|
|
223
|
+
const chain = fromTo(toNode.schema, fromNode.schema);
|
|
224
|
+
if (!chain && error) {
|
|
225
|
+
return { error };
|
|
226
|
+
}
|
|
227
|
+
return chain;
|
|
228
|
+
};
|
|
229
|
+
exports.getRefChain = getRefChain;
|