vue2-client 1.19.78 → 1.19.80
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/docs//345/211/215/347/253/257/344/270/232/345/212/241/351/200/273/350/276/221/344/275/277/347/224/250/350/257/264/346/230/216.md +23 -5
- package/package.json +1 -1
- package/src/base-client/components/common/XFormTable/XFormTable.vue +22 -0
- package/src/base-client/components/common/XFormTable/demo.vue +2 -10
- package/src/base-client/components/common/XReport/print.js +186 -186
- package/src/base-client/components/common/XTable/ExportExcel.vue +8 -4
- package/src/base-client/components/common/XTable/XTable.vue +7 -2
- package/src/base-client/plugins/FrontLogicPlugin.js +19 -0
- package/src/base-client/plugins/index.js +2 -0
- package/src/expression/core/Program.js +10 -10
- package/src/expression/instances/LogicConsole.js +41 -0
- package/src/expression/ts/core/Program.ts +11 -11
- package/src/expression/ts/instances/LogicConsole.ts +18 -1
- package/src/logic/LogicRunner.js +3 -2
- package/src/logic/plugins/common/HttpTools.js +48 -0
- package/src/logic/plugins/index.js +3 -1
- package/src/logic/ts/LogicRunner.ts +3 -2
- package/src/router/async/router.map.js +1 -1
- package/src/utils/logger.js +3 -0
- package/src/utils/map-utils.js +47 -47
|
@@ -6,10 +6,25 @@
|
|
|
6
6
|
|
|
7
7
|
## 一、运行方式
|
|
8
8
|
|
|
9
|
-
### 1.
|
|
9
|
+
### 1. 全局调用:`this.$runFrontLogic(logicName, param)`(推荐在配置脚本中使用)
|
|
10
|
+
|
|
11
|
+
通过 Vue 插件注册,**任意组件**及**配置中的可执行脚本**(如报表的 `dataProcessScript`、按钮的 `customFunction`)内均可使用,无需 import。
|
|
12
|
+
|
|
13
|
+
- 返回 **Promise**,可 `.then()` / `.catch()` 处理结果或错误。
|
|
14
|
+
- 插件在 base-client 中注册,使用 `Vue.use(Plugins)` 的应用自动具备该能力。
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
// 例如在 dataProcessScript、customFunction 等配置脚本中(this 为当前组件)
|
|
18
|
+
var c = (data && data.patientComplaint != null) ? data.patientComplaint : ''
|
|
19
|
+
this.$runFrontLogic('aiDiagnosesCoverDataProcess', { patientComplaint: c, proxy: this }).catch(function (e) {
|
|
20
|
+
if (this.$message && this.$message.warn) this.$message.warn('执行失败,请稍后重试')
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### 2. 按配置名执行:`LogicRunner.run(logicName, param)`
|
|
10
25
|
|
|
11
26
|
- 从后端/配置中心按 `logicName` 拉取逻辑内容(与后端 Logic 同源的配置),在前端执行。
|
|
12
|
-
- 执行时自动注入插件:`data`(即本次传入的 `param`)、`log`、`ENV`、`logic`、`dateTools`、`vueTools`。
|
|
27
|
+
- 执行时自动注入插件:`data`(即本次传入的 `param`)、`log`、`ENV`、`logic`、`dateTools`、`vueTools`、`http`。
|
|
13
28
|
- 适合逻辑内容放在配置里、由界面传入「当前组件 / 响应式数据」的场景。
|
|
14
29
|
|
|
15
30
|
```javascript
|
|
@@ -22,7 +37,7 @@ const result = await LogicRunner.run('testVueLogic', {
|
|
|
22
37
|
})
|
|
23
38
|
```
|
|
24
39
|
|
|
25
|
-
###
|
|
40
|
+
### 3. 直接执行表达式字符串:`LogicRunner.runExpression(source, params)`
|
|
26
41
|
|
|
27
42
|
- 不拉取配置,直接执行一段表达式字符串。
|
|
28
43
|
- `params` 即脚本内的入参(通常包含 `data` 等),无默认插件,需调用方自己构造。
|
|
@@ -50,6 +65,7 @@ const result = await LogicRunner.runExpression(expression, {
|
|
|
50
65
|
| `logic` | LogicRunner 自身,可再调 `logic.run(其他逻辑名, 参数)`(会再拉配置执行)。 |
|
|
51
66
|
| `dateTools` | 日期工具,与后端 dateTools 用法一致。 |
|
|
52
67
|
| `vueTools` | 前端专用:`vueTools.getComponent(vueRef, componentName)`,等价于 `vueRef.$refs[componentName]`,用于按 ref 名取子组件。 |
|
|
68
|
+
| `http` | 请求插件(返回 Promise):`http.post(url, body)`、`http.get(url, params)`。返回值为响应体(response.data),执行器会自动等待 Promise 完成后再继续,可在 Logic 中直接写 `res = http.post('/api/xxx', { key: value })` 再使用 `res.xxx`。 |
|
|
53
69
|
|
|
54
70
|
在**直接执行表达式**(`runExpression`)时,没有默认插件,完全由第二个参数 `params` 提供,例如把当前表单数据放进 `params.WF_FORM`,脚本里用 `data.WF_FORM` 访问(若 params 里 key 为 `data` 且值为该对象)。
|
|
55
71
|
|
|
@@ -62,8 +78,9 @@ const result = await LogicRunner.runExpression(expression, {
|
|
|
62
78
|
- **条件**:`条件 : 结果 , 默认值`,无 if/else,用逗号接默认值。
|
|
63
79
|
- **循环**:用数组的 `each`,例如 `data.xxx.each( row = row + 1 )`,其中 `row` 表示当前项。
|
|
64
80
|
- **JSON**:支持 `{ key: value }`、`[ a, b ]`。
|
|
65
|
-
-
|
|
81
|
+
- **字符串插值**:仅支持双引号字符串,字符串内用 `"现在是{dateTools.getNow2()}"` 形式嵌入表达式(不再支持 `$...$` 形式的字符串)。`$` 可作为标识符的一部分使用,与普通字母一致,例如 `data.$runFrontLogic(...)`。
|
|
66
82
|
- 其他:`return`、`try/catch/finally`、`validate { ... }`、`assert`、lambda `=> { }` 等,与后端一致。
|
|
83
|
+
- **异步请求**:表达式语法不支持 `await`,需使用返回 Promise 的插件方法。`http.post(url, body)`、`http.get(url, params)` 返回 Promise,执行器会在调用处自动等待完成并把结果赋给左侧变量,例如:`res = http.post('/hai-api/suggest-by-complaint', { chief_complaint: data.c }), sug = res.suggestions, ...`。
|
|
67
84
|
|
|
68
85
|
更完整的语法见 `src/expression/core/Program.js`(解析)和 `src/expression/TestExpression.js`(大量表达式示例)。
|
|
69
86
|
|
|
@@ -128,9 +145,10 @@ const result = await LogicRunner.runExpression(expression, {
|
|
|
128
145
|
|
|
129
146
|
| 内容 | 路径 |
|
|
130
147
|
|------|------|
|
|
148
|
+
| **前端 Logic Vue 插件** | `src/base-client/plugins/FrontLogicPlugin.js`(注册 `$runFrontLogic`) |
|
|
131
149
|
| 运行器 | `src/logic/LogicRunner.js` |
|
|
132
150
|
| 表达式解析与执行 | `src/expression/ExpressionRunner.js`、`src/expression/core/Program.js`、`src/expression/core/Expression.js` |
|
|
133
|
-
| 前端插件 | `src/logic/plugins/index.js`、`src/logic/plugins/common/VueTools.js`、`src/logic/plugins/common/DateTools.js` |
|
|
151
|
+
| 前端插件 | `src/logic/plugins/index.js`、`src/logic/plugins/common/VueTools.js`、`src/logic/plugins/common/DateTools.js`、`src/logic/plugins/common/HttpTools.js` |
|
|
134
152
|
| 页面示例 | `src/pages/LogicCallExample/index.vue` |
|
|
135
153
|
| 工作流表达式示例 | `src/pages/WorkflowDetail/WorkflowPageDetail/WorkFlowHandle.vue`(`evaluateExpression`) |
|
|
136
154
|
| 表达式语法用例 | `src/expression/TestExpression.js` |
|
package/package.json
CHANGED
|
@@ -1135,6 +1135,28 @@ export default {
|
|
|
1135
1135
|
*/
|
|
1136
1136
|
handleProgressUpdated (data, record, dataIndex) {
|
|
1137
1137
|
this.$emit('progressUpdated', data, record, dataIndex)
|
|
1138
|
+
},
|
|
1139
|
+
async beforeExportSetHeaders() {
|
|
1140
|
+
const hasListener = !!this.$listeners?.beforeExportSetHeaders
|
|
1141
|
+
|
|
1142
|
+
if (!hasListener) return []
|
|
1143
|
+
|
|
1144
|
+
const result = await new Promise(resolve => {
|
|
1145
|
+
this.$emit('beforeExport', resolve)
|
|
1146
|
+
})
|
|
1147
|
+
|
|
1148
|
+
// 字符串 → 包装成数组
|
|
1149
|
+
if (typeof result === 'string') {
|
|
1150
|
+
return [result]
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
// 数组 → 原样返回
|
|
1154
|
+
if (Array.isArray(result)) {
|
|
1155
|
+
return result
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// 其他情况 → 兜底为空数组
|
|
1159
|
+
return []
|
|
1138
1160
|
}
|
|
1139
1161
|
},
|
|
1140
1162
|
action: {
|
|
@@ -3,15 +3,7 @@
|
|
|
3
3
|
<x-form-table
|
|
4
4
|
title="示例表单"
|
|
5
5
|
:queryParamsName="queryParamsName"
|
|
6
|
-
|
|
7
|
-
:externalSelectedRowKeys="selectedKeys"
|
|
8
|
-
@action="action"
|
|
9
|
-
@selectRow="selectRow"
|
|
10
|
-
@columnClick="columnClick"
|
|
11
|
-
@ceshi="ceshi"
|
|
12
|
-
@rowDblClick="rowDblClick"
|
|
13
|
-
:defaultPageSize="5"
|
|
14
|
-
serviceName="af-revenue"
|
|
6
|
+
serviceName="af-linepatrol"
|
|
15
7
|
ref="xFormTable"
|
|
16
8
|
></x-form-table>
|
|
17
9
|
</a-card>
|
|
@@ -28,7 +20,7 @@ export default {
|
|
|
28
20
|
data() {
|
|
29
21
|
return {
|
|
30
22
|
// 查询配置文件名
|
|
31
|
-
queryParamsName: '
|
|
23
|
+
queryParamsName: 't_subhighpressure_pipelineCRUD',
|
|
32
24
|
// 查询配置左侧tree
|
|
33
25
|
xTreeConfigName: 'addressType',
|
|
34
26
|
// 新增表单固定值
|
|
@@ -1,186 +1,186 @@
|
|
|
1
|
-
// print.js
|
|
2
|
-
|
|
3
|
-
export function printElement (elementToPrint) {
|
|
4
|
-
// 创建一个新的浏览器窗口
|
|
5
|
-
const printWindow = window.open('', '_blank', 'height=1024,width=768')
|
|
6
|
-
// 设置新窗口的文档内容
|
|
7
|
-
printWindow.document.write(`
|
|
8
|
-
<html>
|
|
9
|
-
<head>
|
|
10
|
-
<title>Print</title>
|
|
11
|
-
<style>
|
|
12
|
-
@page {
|
|
13
|
-
size: auto;
|
|
14
|
-
margin: 0mm;
|
|
15
|
-
}
|
|
16
|
-
html, body {
|
|
17
|
-
margin: 0;
|
|
18
|
-
padding: 0;
|
|
19
|
-
width: 100%;
|
|
20
|
-
height: 100%;
|
|
21
|
-
}
|
|
22
|
-
#print-container {
|
|
23
|
-
display: none
|
|
24
|
-
}
|
|
25
|
-
.img{
|
|
26
|
-
width: 95%;
|
|
27
|
-
height: 180px;
|
|
28
|
-
object-fit: cover;
|
|
29
|
-
}
|
|
30
|
-
.reportMain {
|
|
31
|
-
text-align: center;
|
|
32
|
-
margin: 0 auto;
|
|
33
|
-
font-size: 16px;
|
|
34
|
-
color: #000;
|
|
35
|
-
background-color: #fff;
|
|
36
|
-
padding: 15px;
|
|
37
|
-
border-radius: 8px;
|
|
38
|
-
|
|
39
|
-
.reportTitle {
|
|
40
|
-
font-weight: bold;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.subTitle {
|
|
44
|
-
display: flex;
|
|
45
|
-
justify-content: space-between;
|
|
46
|
-
margin-bottom: 1%;
|
|
47
|
-
|
|
48
|
-
.subTitleItems {
|
|
49
|
-
max-width: 30%;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.inputsDiv {
|
|
54
|
-
display: flex;
|
|
55
|
-
justify-content: space-between;
|
|
56
|
-
.inputsDivItem {
|
|
57
|
-
display: flex;
|
|
58
|
-
align-items: center;
|
|
59
|
-
padding: 0 4px;
|
|
60
|
-
white-space: nowrap;
|
|
61
|
-
.inputsDivItemLabel {
|
|
62
|
-
padding: 0 4px;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
.reportTable {
|
|
68
|
-
width: 100%;
|
|
69
|
-
border-collapse: collapse;
|
|
70
|
-
table-layout:fixed;
|
|
71
|
-
word-break:break-all;
|
|
72
|
-
text-align: center;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
.reportMainForDisplay {
|
|
76
|
-
text-align: center;
|
|
77
|
-
margin: 10% auto;
|
|
78
|
-
font-size: 16px;
|
|
79
|
-
color: #000;
|
|
80
|
-
background-color: #fff;
|
|
81
|
-
padding: 15px;
|
|
82
|
-
border-radius: 8px;
|
|
83
|
-
|
|
84
|
-
.reportTitle {
|
|
85
|
-
font-weight: bold;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.subTitle {
|
|
89
|
-
display: flex;
|
|
90
|
-
justify-content: space-between;
|
|
91
|
-
|
|
92
|
-
.subTitleItems {
|
|
93
|
-
max-width: 30%;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.inputsDiv {
|
|
98
|
-
display: flex;
|
|
99
|
-
justify-content: space-around;
|
|
100
|
-
.inputsDivItem {
|
|
101
|
-
display: flex;
|
|
102
|
-
align-items: center;
|
|
103
|
-
padding: 0 4px;
|
|
104
|
-
white-space: nowrap;
|
|
105
|
-
.inputsDivItemLabel {
|
|
106
|
-
padding: 0 4px;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.reportTable {
|
|
112
|
-
width: 100%;
|
|
113
|
-
border-collapse: collapse;
|
|
114
|
-
table-layout:fixed;
|
|
115
|
-
word-break:break-all;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
.reportMainNoPadding {
|
|
119
|
-
text-align: center;
|
|
120
|
-
margin: 0 auto;
|
|
121
|
-
font-size: 16px;
|
|
122
|
-
color: #000;
|
|
123
|
-
background-color: #fff;
|
|
124
|
-
border-radius: 8px;
|
|
125
|
-
|
|
126
|
-
.reportTitle {
|
|
127
|
-
font-weight: bold;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.subTitle {
|
|
131
|
-
display: flex;
|
|
132
|
-
justify-content: space-between;
|
|
133
|
-
|
|
134
|
-
.subTitleItems {
|
|
135
|
-
max-width: 30%;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.inputsDiv {
|
|
140
|
-
display: flex;
|
|
141
|
-
justify-content: space-between;
|
|
142
|
-
.inputsDivItem {
|
|
143
|
-
display: flex;
|
|
144
|
-
align-items: center;
|
|
145
|
-
padding: 0 4px;
|
|
146
|
-
white-space: nowrap;
|
|
147
|
-
.inputsDivItemLabel {
|
|
148
|
-
padding: 0 4px;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.reportTable {
|
|
154
|
-
width: 100%;
|
|
155
|
-
border-collapse: collapse;
|
|
156
|
-
table-layout:fixed;
|
|
157
|
-
word-break:break-all;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
.tools{
|
|
161
|
-
position: fixed;
|
|
162
|
-
right: 2%;
|
|
163
|
-
text-align: right;
|
|
164
|
-
width: 60%;
|
|
165
|
-
cursor: pointer;
|
|
166
|
-
.toolsItem{
|
|
167
|
-
width: 15%;
|
|
168
|
-
margin-right: 3%;
|
|
169
|
-
display: inline-block;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
</style>
|
|
173
|
-
</head>
|
|
174
|
-
<body>
|
|
175
|
-
<!-- 将需要打印的元素内容复制到新窗口中 -->
|
|
176
|
-
${elementToPrint.innerHTML}
|
|
177
|
-
</body>
|
|
178
|
-
</html>
|
|
179
|
-
`)
|
|
180
|
-
// 延迟执行打印,以确保新窗口的内容已加载完成
|
|
181
|
-
printWindow.document.close() // 关闭文档流,确保内容完全加载
|
|
182
|
-
setTimeout(() => {
|
|
183
|
-
printWindow.print() // 调用打印方法
|
|
184
|
-
printWindow.close()
|
|
185
|
-
}, 500) // 延迟500毫秒后执行打印
|
|
186
|
-
}
|
|
1
|
+
// print.js
|
|
2
|
+
|
|
3
|
+
export function printElement (elementToPrint) {
|
|
4
|
+
// 创建一个新的浏览器窗口
|
|
5
|
+
const printWindow = window.open('', '_blank', 'height=1024,width=768')
|
|
6
|
+
// 设置新窗口的文档内容
|
|
7
|
+
printWindow.document.write(`
|
|
8
|
+
<html>
|
|
9
|
+
<head>
|
|
10
|
+
<title>Print</title>
|
|
11
|
+
<style>
|
|
12
|
+
@page {
|
|
13
|
+
size: auto;
|
|
14
|
+
margin: 0mm;
|
|
15
|
+
}
|
|
16
|
+
html, body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
padding: 0;
|
|
19
|
+
width: 100%;
|
|
20
|
+
height: 100%;
|
|
21
|
+
}
|
|
22
|
+
#print-container {
|
|
23
|
+
display: none
|
|
24
|
+
}
|
|
25
|
+
.img{
|
|
26
|
+
width: 95%;
|
|
27
|
+
height: 180px;
|
|
28
|
+
object-fit: cover;
|
|
29
|
+
}
|
|
30
|
+
.reportMain {
|
|
31
|
+
text-align: center;
|
|
32
|
+
margin: 0 auto;
|
|
33
|
+
font-size: 16px;
|
|
34
|
+
color: #000;
|
|
35
|
+
background-color: #fff;
|
|
36
|
+
padding: 15px;
|
|
37
|
+
border-radius: 8px;
|
|
38
|
+
|
|
39
|
+
.reportTitle {
|
|
40
|
+
font-weight: bold;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.subTitle {
|
|
44
|
+
display: flex;
|
|
45
|
+
justify-content: space-between;
|
|
46
|
+
margin-bottom: 1%;
|
|
47
|
+
|
|
48
|
+
.subTitleItems {
|
|
49
|
+
max-width: 30%;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.inputsDiv {
|
|
54
|
+
display: flex;
|
|
55
|
+
justify-content: space-between;
|
|
56
|
+
.inputsDivItem {
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
padding: 0 4px;
|
|
60
|
+
white-space: nowrap;
|
|
61
|
+
.inputsDivItemLabel {
|
|
62
|
+
padding: 0 4px;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.reportTable {
|
|
68
|
+
width: 100%;
|
|
69
|
+
border-collapse: collapse;
|
|
70
|
+
table-layout:fixed;
|
|
71
|
+
word-break:break-all;
|
|
72
|
+
text-align: center;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
.reportMainForDisplay {
|
|
76
|
+
text-align: center;
|
|
77
|
+
margin: 10% auto;
|
|
78
|
+
font-size: 16px;
|
|
79
|
+
color: #000;
|
|
80
|
+
background-color: #fff;
|
|
81
|
+
padding: 15px;
|
|
82
|
+
border-radius: 8px;
|
|
83
|
+
|
|
84
|
+
.reportTitle {
|
|
85
|
+
font-weight: bold;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.subTitle {
|
|
89
|
+
display: flex;
|
|
90
|
+
justify-content: space-between;
|
|
91
|
+
|
|
92
|
+
.subTitleItems {
|
|
93
|
+
max-width: 30%;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.inputsDiv {
|
|
98
|
+
display: flex;
|
|
99
|
+
justify-content: space-around;
|
|
100
|
+
.inputsDivItem {
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
padding: 0 4px;
|
|
104
|
+
white-space: nowrap;
|
|
105
|
+
.inputsDivItemLabel {
|
|
106
|
+
padding: 0 4px;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.reportTable {
|
|
112
|
+
width: 100%;
|
|
113
|
+
border-collapse: collapse;
|
|
114
|
+
table-layout:fixed;
|
|
115
|
+
word-break:break-all;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
.reportMainNoPadding {
|
|
119
|
+
text-align: center;
|
|
120
|
+
margin: 0 auto;
|
|
121
|
+
font-size: 16px;
|
|
122
|
+
color: #000;
|
|
123
|
+
background-color: #fff;
|
|
124
|
+
border-radius: 8px;
|
|
125
|
+
|
|
126
|
+
.reportTitle {
|
|
127
|
+
font-weight: bold;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.subTitle {
|
|
131
|
+
display: flex;
|
|
132
|
+
justify-content: space-between;
|
|
133
|
+
|
|
134
|
+
.subTitleItems {
|
|
135
|
+
max-width: 30%;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.inputsDiv {
|
|
140
|
+
display: flex;
|
|
141
|
+
justify-content: space-between;
|
|
142
|
+
.inputsDivItem {
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: center;
|
|
145
|
+
padding: 0 4px;
|
|
146
|
+
white-space: nowrap;
|
|
147
|
+
.inputsDivItemLabel {
|
|
148
|
+
padding: 0 4px;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.reportTable {
|
|
154
|
+
width: 100%;
|
|
155
|
+
border-collapse: collapse;
|
|
156
|
+
table-layout:fixed;
|
|
157
|
+
word-break:break-all;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
.tools{
|
|
161
|
+
position: fixed;
|
|
162
|
+
right: 2%;
|
|
163
|
+
text-align: right;
|
|
164
|
+
width: 60%;
|
|
165
|
+
cursor: pointer;
|
|
166
|
+
.toolsItem{
|
|
167
|
+
width: 15%;
|
|
168
|
+
margin-right: 3%;
|
|
169
|
+
display: inline-block;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
</style>
|
|
173
|
+
</head>
|
|
174
|
+
<body>
|
|
175
|
+
<!-- 将需要打印的元素内容复制到新窗口中 -->
|
|
176
|
+
${elementToPrint.innerHTML}
|
|
177
|
+
</body>
|
|
178
|
+
</html>
|
|
179
|
+
`)
|
|
180
|
+
// 延迟执行打印,以确保新窗口的内容已加载完成
|
|
181
|
+
printWindow.document.close() // 关闭文档流,确保内容完全加载
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
printWindow.print() // 调用打印方法
|
|
184
|
+
printWindow.close()
|
|
185
|
+
}, 500) // 延迟500毫秒后执行打印
|
|
186
|
+
}
|
|
@@ -27,7 +27,9 @@ export default {
|
|
|
27
27
|
// 选中的查询条件字段名
|
|
28
28
|
selectedQueryConditions: [],
|
|
29
29
|
// 查询条件的 labelData 数据
|
|
30
|
-
queryLabelData: null
|
|
30
|
+
queryLabelData: null,
|
|
31
|
+
// 自定义表头行数据
|
|
32
|
+
customHeaders: [],
|
|
31
33
|
}
|
|
32
34
|
},
|
|
33
35
|
inject: ['tableContext', 'getFormLabelData'],
|
|
@@ -63,10 +65,11 @@ export default {
|
|
|
63
65
|
},
|
|
64
66
|
methods: {
|
|
65
67
|
// 导出选中或本页数据
|
|
66
|
-
handleExport (type, title) {
|
|
68
|
+
handleExport (type, title, customHeaders = []) {
|
|
67
69
|
this.modalTitle = '选择导出列'
|
|
68
70
|
this.exportFileName = title || '查询导出'
|
|
69
71
|
this.type = 'export'
|
|
72
|
+
this.customHeaders = customHeaders
|
|
70
73
|
this.handle(type)
|
|
71
74
|
},
|
|
72
75
|
// 打印选中或本页数据
|
|
@@ -74,6 +77,7 @@ export default {
|
|
|
74
77
|
this.modalTitle = '选择打印数据列'
|
|
75
78
|
this.type = 'print'
|
|
76
79
|
this.printData = printData
|
|
80
|
+
this.customHeaders = []
|
|
77
81
|
this.handle(type)
|
|
78
82
|
},
|
|
79
83
|
handle (type) {
|
|
@@ -88,7 +92,6 @@ export default {
|
|
|
88
92
|
// 获取查询条件的 labelData,并默认全部选中
|
|
89
93
|
if (this.getFormLabelData) {
|
|
90
94
|
this.queryLabelData = this.getFormLabelData()
|
|
91
|
-
console.log('>>>> this.queryLabelData: ', JSON.stringify(this.queryLabelData))
|
|
92
95
|
// 默认全部选中所有查询条件字段(根据 labels 数组的索引)
|
|
93
96
|
if (this.queryLabelData && this.queryLabelData.labels && this.queryLabelData.labels.length > 0) {
|
|
94
97
|
this.selectedQueryConditions = this.queryLabelData.labels.map((_, index) => index)
|
|
@@ -225,6 +228,7 @@ export default {
|
|
|
225
228
|
const fileNamePrefix = this.exportFileName || '查询导出'
|
|
226
229
|
const name = `${fileNamePrefix}_${dateTime}`
|
|
227
230
|
const queryData = this.buildDisplayText(this.queryLabelData?.labelData, this.queryLabelData?.labels, this.selectedQueryConditions)
|
|
231
|
+
this.customHeaders.push(queryData)
|
|
228
232
|
const param = {
|
|
229
233
|
queryParamsName: this.tableContext.queryParamsName,
|
|
230
234
|
queryParams: this.tableContext.queryParams,
|
|
@@ -233,7 +237,7 @@ export default {
|
|
|
233
237
|
form: conditionParams,
|
|
234
238
|
userId: this.tableContext.currUser.id,
|
|
235
239
|
fileName: name,
|
|
236
|
-
|
|
240
|
+
headerData: this.customHeaders
|
|
237
241
|
}
|
|
238
242
|
exportData(param, this.tableContext.serviceName).then(res => {
|
|
239
243
|
this.closeModal()
|
|
@@ -1397,8 +1397,13 @@ export default {
|
|
|
1397
1397
|
const indexColumn = this.tableColumns.find(i => i?.slotType === 'index')
|
|
1398
1398
|
return indexColumn ? indexColumn.dataIndex : this.tableColumns[0].dataIndex
|
|
1399
1399
|
},
|
|
1400
|
-
handleExport
|
|
1401
|
-
this
|
|
1400
|
+
async handleExport(type) {
|
|
1401
|
+
const formTable = this.getSelf && this.getSelf()
|
|
1402
|
+
let customHeaders = []
|
|
1403
|
+
if (formTable && typeof formTable.beforeExportSetHeaders === 'function') {
|
|
1404
|
+
customHeaders = await formTable.beforeExportSetHeaders()
|
|
1405
|
+
}
|
|
1406
|
+
this.$refs.exportExcel.handleExport(type, this.title, customHeaders)
|
|
1402
1407
|
},
|
|
1403
1408
|
handlePrint (type) {
|
|
1404
1409
|
const printData = {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 前端业务逻辑插件
|
|
3
|
+
* 将「运行前端 Logic 表达式」注册为 Vue 全局方法,可在任意组件或配置脚本中调用。
|
|
4
|
+
* 使用方式:
|
|
5
|
+
* - 在组件中:this.$runFrontLogic('logicName', { key: value })
|
|
6
|
+
* - 返回 Promise,可 .then() / .catch()
|
|
7
|
+
*/
|
|
8
|
+
import LogicRunner from '@vue2-client/logic/LogicRunner'
|
|
9
|
+
|
|
10
|
+
const runFrontLogic = (logicName, param) => LogicRunner.run(logicName, param)
|
|
11
|
+
|
|
12
|
+
const FrontLogicPlugin = {
|
|
13
|
+
install (Vue) {
|
|
14
|
+
Vue.$runFrontLogic = runFrontLogic
|
|
15
|
+
Vue.prototype.$runFrontLogic = runFrontLogic
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default FrontLogicPlugin
|
|
@@ -4,6 +4,7 @@ import getConfig from '@vue2-client/base-client/plugins/Config'
|
|
|
4
4
|
import moment from '@vue2-client/base-client/plugins/moment'
|
|
5
5
|
import recording from '@vue2-client/base-client/plugins/Recording'
|
|
6
6
|
import ComponentRegistryPlugin from '@vue2-client/base-client/plugins/ComponentRegistryPlugin'
|
|
7
|
+
import FrontLogicPlugin from '@vue2-client/base-client/plugins/FrontLogicPlugin'
|
|
7
8
|
|
|
8
9
|
import VueI18nPlugin from './i18n-extend'
|
|
9
10
|
import AuthorityPlugin from './authority-plugin'
|
|
@@ -20,6 +21,7 @@ const Plugins = {
|
|
|
20
21
|
Vue.use(TabsPagePlugin)
|
|
21
22
|
Vue.use(recording)
|
|
22
23
|
Vue.use(ComponentRegistryPlugin)
|
|
24
|
+
Vue.use(FrontLogicPlugin)
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
export default Plugins
|
|
@@ -16,7 +16,7 @@ export default class Program {
|
|
|
16
16
|
*/
|
|
17
17
|
tokens = []
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* 字符串处理环节堆栈,双引号进入字符串处理环节,“{}”中间部分脱离字符串处理环节
|
|
20
20
|
*/
|
|
21
21
|
inStrings = []
|
|
22
22
|
|
|
@@ -340,7 +340,7 @@ export default class Program {
|
|
|
340
340
|
} else if (t.getType() === TokenType.Oper && t.getValue() === '[') {
|
|
341
341
|
// JSON array
|
|
342
342
|
return this.JsonArray()
|
|
343
|
-
} else if (t.getType() === TokenType.Oper &&
|
|
343
|
+
} else if (t.getType() === TokenType.Oper && t.getValue() === '"') {
|
|
344
344
|
// String concatenation sequence
|
|
345
345
|
return this.StringUnion()
|
|
346
346
|
} else if (t.getType() === TokenType.Int || t.getType() === TokenType.Double || t.getType() === TokenType.Bool) {
|
|
@@ -559,7 +559,7 @@ export default class Program {
|
|
|
559
559
|
let value
|
|
560
560
|
if (name.getType() === TokenType.Identy) {
|
|
561
561
|
value = name.getValue()
|
|
562
|
-
} else if (name.getType() === TokenType.Oper &&
|
|
562
|
+
} else if (name.getType() === TokenType.Oper && name.getValue() === '"') {
|
|
563
563
|
const expression = this.StringUnion().children[1]
|
|
564
564
|
value = expression.value
|
|
565
565
|
} else {
|
|
@@ -772,10 +772,10 @@ export default class Program {
|
|
|
772
772
|
// If in string state, process the string
|
|
773
773
|
if (this.inString) {
|
|
774
774
|
const startPos = this.pos
|
|
775
|
-
while (hasKeyword && value !== '{' && value !== '}' && value !== '
|
|
775
|
+
while (hasKeyword && value !== '{' && value !== '}' && value !== '"') {
|
|
776
776
|
if (value === '\\') {
|
|
777
777
|
const nextStrValue = this.SOURCE.charAt(this.pos + 1)
|
|
778
|
-
if (this.pos + 1 < this.SOURCE_LENGTH && ['{', '}', '"', '
|
|
778
|
+
if (this.pos + 1 < this.SOURCE_LENGTH && ['{', '}', '"', '\\'].includes(nextStrValue)) {
|
|
779
779
|
this.pos++
|
|
780
780
|
} else {
|
|
781
781
|
break
|
|
@@ -798,7 +798,7 @@ export default class Program {
|
|
|
798
798
|
.replace(/\\"/g, '"')
|
|
799
799
|
.replace('\\\\', '\\'), sPos)
|
|
800
800
|
|
|
801
|
-
if (hasKeyword &&
|
|
801
|
+
if (hasKeyword && value === '"') {
|
|
802
802
|
this.pos++
|
|
803
803
|
}
|
|
804
804
|
return t
|
|
@@ -863,9 +863,9 @@ export default class Program {
|
|
|
863
863
|
const str = this.SOURCE.substring(oldPos, this.pos)
|
|
864
864
|
return new Token(TokenType.Int, parseInt(str, 10), sPos)
|
|
865
865
|
}
|
|
866
|
-
} else if ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || value === '_' || /[\u4e00-\u9fa5]/.test(value)) {
|
|
866
|
+
} else if ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || value === '_' || value === '$' || /[\u4e00-\u9fa5]/.test(value)) {
|
|
867
867
|
const oldPos = this.pos
|
|
868
|
-
while (hasKeyword && ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || (value >= '0' && value <= '9') || value === '_' || /[\u4e00-\u9fa5]/.test(value))) {
|
|
868
|
+
while (hasKeyword && ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || (value >= '0' && value <= '9') || value === '_' || value === '$' || /[\u4e00-\u9fa5]/.test(value))) {
|
|
869
869
|
this.pos++
|
|
870
870
|
if (this.pos < this.SOURCE_LENGTH) {
|
|
871
871
|
value = this.SOURCE.charAt(this.pos)
|
|
@@ -907,8 +907,8 @@ export default class Program {
|
|
|
907
907
|
this.pos += 1
|
|
908
908
|
}
|
|
909
909
|
return new Token(TokenType.Oper, str, sPos)
|
|
910
|
-
} else if ('()[],;.:@{}"
|
|
911
|
-
if (value === '
|
|
910
|
+
} else if ('()[],;.:@{}"'.includes(value)) {
|
|
911
|
+
if (value === '"') {
|
|
912
912
|
this.inStrings.push(false)
|
|
913
913
|
this.inString = true
|
|
914
914
|
} else if ((value === '{' || value === '}') && this.inStrings.length) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// 自定义 Console 类
|
|
2
|
+
// 与 Vue 实例的 logger 对齐:支持按路径配置开关、输出前缀;业务逻辑中 log.xx 使用 Expression 序列化
|
|
2
3
|
import Expression from '../core/Expression'
|
|
4
|
+
import { isLogEnabled } from '@vue2-client/utils/logger'
|
|
3
5
|
|
|
4
6
|
export default class LogicConsole {
|
|
5
7
|
constructor () {
|
|
@@ -16,6 +18,20 @@ export default class LogicConsole {
|
|
|
16
18
|
return LogicConsole.instance
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
/**
|
|
22
|
+
* 带路径与配置检查的输出(供 createLogger 使用)
|
|
23
|
+
* @param {string} level - 'log' | 'debug' | 'info' | 'warn' | 'error'
|
|
24
|
+
* @param {string} logPath - 日志路径,如 'logic.xxx'
|
|
25
|
+
* @param {*[]} args - 参数,会经 convert 序列化
|
|
26
|
+
*/
|
|
27
|
+
_output (level, logPath, ...args) {
|
|
28
|
+
if (!isLogEnabled(logPath)) return
|
|
29
|
+
const prefix = `log[${logPath}]:`
|
|
30
|
+
const newArgs = this.convert(args)
|
|
31
|
+
const consoleMethod = console[level] || console.log
|
|
32
|
+
consoleMethod(prefix, ...newArgs)
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
debug (...args) {
|
|
20
36
|
const newArgs = this.convert(args)
|
|
21
37
|
console.debug(...newArgs)
|
|
@@ -36,6 +52,31 @@ export default class LogicConsole {
|
|
|
36
52
|
console.error(...newArgs)
|
|
37
53
|
}
|
|
38
54
|
|
|
55
|
+
/** 与 Vue logger 一致:log 对应 console.log */
|
|
56
|
+
log (...args) {
|
|
57
|
+
const newArgs = this.convert(args)
|
|
58
|
+
console.log(...newArgs)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 创建带路径的 logger,与 Vue 实例的 logger 行为一致:
|
|
63
|
+
* 从 logger.config.js / config.js 读取配置按路径开关,输出带 log[path]: 前缀,参数经 Expression 序列化。
|
|
64
|
+
* 业务逻辑中应使用此方法传入 logicName,便于按 logic 控制日志。
|
|
65
|
+
* @param {string} logPath - 日志路径,如 'logic.aiDiagnosis' 或 'logic.xxx'
|
|
66
|
+
* @returns {{ log: Function, debug: Function, info: Function, warn: Function, error: Function }}
|
|
67
|
+
*/
|
|
68
|
+
static createLogger (logPath) {
|
|
69
|
+
const path = typeof logPath === 'string' && logPath ? logPath : 'logic'
|
|
70
|
+
const instance = LogicConsole.getInstance()
|
|
71
|
+
return {
|
|
72
|
+
log: (...args) => instance._output('log', path, ...args),
|
|
73
|
+
debug: (...args) => instance._output('debug', path, ...args),
|
|
74
|
+
info: (...args) => instance._output('info', path, ...args),
|
|
75
|
+
warn: (...args) => instance._output('warn', path, ...args),
|
|
76
|
+
error: (...args) => instance._output('error', path, ...args),
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
39
80
|
convert (args) {
|
|
40
81
|
return args.map(obj => {
|
|
41
82
|
return Expression.toJSONString(obj)
|
|
@@ -17,7 +17,7 @@ export default class Program {
|
|
|
17
17
|
*/
|
|
18
18
|
private readonly tokens: Token[] = [];
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* 字符串处理环节堆栈,双引号进入字符串处理环节,“{}”中间部分脱离字符串处理环节
|
|
21
21
|
*/
|
|
22
22
|
private readonly inStrings: boolean[] = [];
|
|
23
23
|
|
|
@@ -343,7 +343,7 @@ export default class Program {
|
|
|
343
343
|
} else if (t.getType() === TokenType.Oper && t.getValue() === "[") {
|
|
344
344
|
// JSON array
|
|
345
345
|
return this.JsonArray();
|
|
346
|
-
} else if (t.getType() === TokenType.Oper &&
|
|
346
|
+
} else if (t.getType() === TokenType.Oper && t.getValue() === "\"") {
|
|
347
347
|
// String concatenation sequence
|
|
348
348
|
return this.StringUnion();
|
|
349
349
|
} else if (t.getType() === TokenType.Int || t.getType() === TokenType.Double || t.getType() === TokenType.Bool) {
|
|
@@ -562,7 +562,7 @@ export default class Program {
|
|
|
562
562
|
let value: string;
|
|
563
563
|
if (name.getType() === TokenType.Identy) {
|
|
564
564
|
value = <string>name.getValue();
|
|
565
|
-
} else if (name.getType() === TokenType.Oper &&
|
|
565
|
+
} else if (name.getType() === TokenType.Oper && name.getValue() === "\"") {
|
|
566
566
|
let expression: Expression = this.StringUnion().children[1] as Expression;
|
|
567
567
|
value = <string>expression.value;
|
|
568
568
|
} else {
|
|
@@ -775,10 +775,10 @@ export default class Program {
|
|
|
775
775
|
// If in string state, process the string
|
|
776
776
|
if (this.inString) {
|
|
777
777
|
let startPos = this.pos;
|
|
778
|
-
while (hasKeyword && value !== '{' && value !== '}' && value !== '
|
|
778
|
+
while (hasKeyword && value !== '{' && value !== '}' && value !== '\"') {
|
|
779
779
|
if (value === '\\') {
|
|
780
780
|
const nextStrValue = this.SOURCE.charAt(this.pos + 1);
|
|
781
|
-
if (this.pos + 1 < this.SOURCE_LENGTH && ['{', '}', '\"', '
|
|
781
|
+
if (this.pos + 1 < this.SOURCE_LENGTH && ['{', '}', '\"', '\\'].includes(nextStrValue)) {
|
|
782
782
|
this.pos++;
|
|
783
783
|
} else {
|
|
784
784
|
break;
|
|
@@ -801,7 +801,7 @@ export default class Program {
|
|
|
801
801
|
.replace(/\\"/g, '"')
|
|
802
802
|
.replace("\\\\", "\\"), sPos);
|
|
803
803
|
|
|
804
|
-
if (hasKeyword &&
|
|
804
|
+
if (hasKeyword && value === '\"') {
|
|
805
805
|
this.pos++;
|
|
806
806
|
}
|
|
807
807
|
return t;
|
|
@@ -868,10 +868,10 @@ export default class Program {
|
|
|
868
868
|
}
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
-
// Handle identifier tokens
|
|
872
|
-
else if ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || value === '_' || /[\u4e00-\u9fa5]/.test(value)) {
|
|
871
|
+
// Handle identifier tokens (including $ as in $runFrontLogic)
|
|
872
|
+
else if ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || value === '_' || value === '$' || /[\u4e00-\u9fa5]/.test(value)) {
|
|
873
873
|
const oldPos = this.pos;
|
|
874
|
-
while (hasKeyword && ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || (value >= '0' && value <= '9') || value === '_' || /[\u4e00-\u9fa5]/.test(value))) {
|
|
874
|
+
while (hasKeyword && ((value >= 'a' && value <= 'z') || (value >= 'A' && value <= 'Z') || (value >= '0' && value <= '9') || value === '_' || value === '$' || /[\u4e00-\u9fa5]/.test(value))) {
|
|
875
875
|
this.pos++;
|
|
876
876
|
if (this.pos < this.SOURCE_LENGTH) {
|
|
877
877
|
value = this.SOURCE.charAt(this.pos);
|
|
@@ -925,8 +925,8 @@ export default class Program {
|
|
|
925
925
|
}
|
|
926
926
|
|
|
927
927
|
// Single character operators like parentheses, commas, etc.
|
|
928
|
-
else if ('()[],;.:@{}"
|
|
929
|
-
if (value === '
|
|
928
|
+
else if ('()[],;.:@{}"'.includes(value)) {
|
|
929
|
+
if (value === '\"') {
|
|
930
930
|
this.inStrings.push(false);
|
|
931
931
|
this.inString = true;
|
|
932
932
|
} else if ((value === '{' || value === '}') && this.inStrings.length) {
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
// 自定义 Console
|
|
1
|
+
// 自定义 Console 类(与 Vue 实例 logger 对齐:支持按路径配置、前缀;业务逻辑中 log.xx 使用 Expression 序列化)
|
|
2
|
+
export interface ILogicLogger {
|
|
3
|
+
log: (...args: any[]) => void
|
|
4
|
+
debug: (...args: any[]) => void
|
|
5
|
+
info: (...args: any[]) => void
|
|
6
|
+
warn: (...args: any[]) => void
|
|
7
|
+
error: (...args: any[]) => void
|
|
8
|
+
}
|
|
9
|
+
|
|
2
10
|
export default class LogicConsole {
|
|
3
11
|
|
|
4
12
|
public debug(...args: any[]): void {
|
|
@@ -21,6 +29,15 @@ export default class LogicConsole {
|
|
|
21
29
|
console.error(...newArgs);
|
|
22
30
|
}
|
|
23
31
|
|
|
32
|
+
/**
|
|
33
|
+
* 创建带路径的 logger,与 Vue 实例的 logger 行为一致(配置开关、前缀)。
|
|
34
|
+
* 实际实现见 LogicConsole.js;此处仅为类型声明与兜底。
|
|
35
|
+
*/
|
|
36
|
+
public static createLogger(logPath: string): ILogicLogger {
|
|
37
|
+
const noop = () => {}
|
|
38
|
+
return { log: noop, debug: noop, info: noop, warn: noop, error: noop }
|
|
39
|
+
}
|
|
40
|
+
|
|
24
41
|
private convert(args: any[]): any[] {
|
|
25
42
|
return args.map(arg => {
|
|
26
43
|
if (typeof arg === 'object' && arg !== null && typeof arg.toString === 'function') {
|
package/src/logic/LogicRunner.js
CHANGED
|
@@ -34,11 +34,12 @@ export default class LogicRunner {
|
|
|
34
34
|
throw new ServiceException('Logic资源' + logicName + '未找到', 400)
|
|
35
35
|
}
|
|
36
36
|
const paramStr = Expression.toJSONString(param)
|
|
37
|
-
|
|
37
|
+
const logicLog = LogicConsole.createLogger('logic.' + logicName)
|
|
38
|
+
logicLog.info(`执行Logic[${logicName}],params: ${paramStr}`)
|
|
38
39
|
// 附加用户注册的对象到业务逻辑中
|
|
39
40
|
const plugins = {}
|
|
40
41
|
plugins.data = param
|
|
41
|
-
plugins.log =
|
|
42
|
+
plugins.log = logicLog
|
|
42
43
|
plugins.ENV = result.$globalProp
|
|
43
44
|
plugins.logic = this
|
|
44
45
|
Object.assign(plugins, Plugins.default)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 前端 Logic 用 HTTP 请求插件。
|
|
3
|
+
* 提供 post、get 方法,均返回 Promise,供表达式执行器在调用处自动等待。
|
|
4
|
+
* 使用项目统一的 request/restTools,走 axios 拦截器与认证。
|
|
5
|
+
*/
|
|
6
|
+
import { post as postRequest, get as getRequest } from '@vue2-client/services/api/restTools'
|
|
7
|
+
|
|
8
|
+
export default class HttpTools {
|
|
9
|
+
static instance
|
|
10
|
+
|
|
11
|
+
constructor () {
|
|
12
|
+
if (HttpTools.instance) {
|
|
13
|
+
return HttpTools.instance
|
|
14
|
+
}
|
|
15
|
+
HttpTools.instance = this
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static getInstance () {
|
|
19
|
+
if (!HttpTools.instance) {
|
|
20
|
+
HttpTools.instance = new HttpTools()
|
|
21
|
+
}
|
|
22
|
+
return HttpTools.instance
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* POST 请求,返回 Promise<响应体>(即 response.data)
|
|
27
|
+
* @param {string} url 请求地址,如 '/hai-api/suggest-by-complaint' 或 '/api/af-his/logic/xxx'
|
|
28
|
+
* @param {Object} body 请求体(JSON),会作为 request body 发送
|
|
29
|
+
* @param {Object} [config] 可选,axios 配置,如 { dedupe: false }
|
|
30
|
+
* @returns {Promise<*>} 解析为响应体(通常为 JSON 对象)
|
|
31
|
+
*/
|
|
32
|
+
post (url, body, config) {
|
|
33
|
+
return postRequest(url, body || {}, config)
|
|
34
|
+
.then(res => res && res.data !== undefined ? res.data : res)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* GET 请求,返回 Promise<响应体>(即 response.data)
|
|
39
|
+
* @param {string} url 请求地址
|
|
40
|
+
* @param {Object} [params] 查询参数
|
|
41
|
+
* @param {Object} [config] 可选,axios 配置
|
|
42
|
+
* @returns {Promise<*>} 解析为响应体
|
|
43
|
+
*/
|
|
44
|
+
get (url, params, config) {
|
|
45
|
+
return getRequest(url, params, config)
|
|
46
|
+
.then(res => res && res.data !== undefined ? res.data : res)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import DateTools from '@vue2-client/logic/plugins/common/DateTools'
|
|
2
2
|
import VueTools from '@vue2-client/logic/plugins/common/VueTools'
|
|
3
|
+
import HttpTools from '@vue2-client/logic/plugins/common/HttpTools'
|
|
3
4
|
|
|
4
5
|
export default {
|
|
5
6
|
dateTools: DateTools.getInstance(),
|
|
6
|
-
vueTools: VueTools.getInstance()
|
|
7
|
+
vueTools: VueTools.getInstance(),
|
|
8
|
+
http: HttpTools.getInstance()
|
|
7
9
|
}
|
|
@@ -35,11 +35,12 @@ export default class LogicRunner {
|
|
|
35
35
|
if (source == null) {
|
|
36
36
|
throw new ServiceException("Logic资源" + logicName + "未找到", 400)
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
const logicLog = LogicConsole.createLogger('logic.' + logicName)
|
|
39
|
+
logicLog.info("执行Logic[{}],params: {}", logicName, param)
|
|
39
40
|
// 附加用户注册的对象到业务逻辑中
|
|
40
41
|
const plugins = new JSONObject();
|
|
41
42
|
plugins.put("data", param);
|
|
42
|
-
plugins.put("log",
|
|
43
|
+
plugins.put("log", logicLog);
|
|
43
44
|
plugins.put("logic", LogicRunner.prototype);
|
|
44
45
|
return LogicRunner.runExpression(source, plugins);
|
|
45
46
|
}
|
|
@@ -95,7 +95,7 @@ routerResource.XReportView = () => import('@vue2-client/pages/XReportView')
|
|
|
95
95
|
|
|
96
96
|
routerResource.XReportGrid = () => import('@vue2-client/base-client/components/common/XReportGrid/XReportDemo')
|
|
97
97
|
|
|
98
|
-
routerResource.XTab = () => import('@vue2-client/base-client/components/common/
|
|
98
|
+
routerResource.XTab = () => import('@vue2-client/base-client/components/common/XFormTable/demo.vue')
|
|
99
99
|
routerResource.addressManage = () => import('@vue2-client/base-client/components/common/XFormTable/demo.vue')
|
|
100
100
|
// 大屏界面, 放行登录
|
|
101
101
|
routerResource.bigDashboard = () => import('@vue2-client/pages/dashboard/index.vue')
|
package/src/utils/logger.js
CHANGED
|
@@ -98,6 +98,8 @@ function isLogEnabled(logPath) {
|
|
|
98
98
|
const prefix = pattern.slice(0, -2)
|
|
99
99
|
return logPath.startsWith(prefix + '.') || logPath === prefix
|
|
100
100
|
}
|
|
101
|
+
// 全局通配
|
|
102
|
+
if (pattern === '*') return true
|
|
101
103
|
return false
|
|
102
104
|
})
|
|
103
105
|
}
|
|
@@ -152,3 +154,4 @@ function logger(logPath) {
|
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
export default logger
|
|
157
|
+
export { isLogEnabled }
|
package/src/utils/map-utils.js
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
|
-
import AMapLoader from '@amap/amap-jsapi-loader'
|
|
2
|
-
let Amap
|
|
3
|
-
async function GetGDMap (secretKey, key) {
|
|
4
|
-
if (!Amap) {
|
|
5
|
-
window._AMapSecurityConfig = {
|
|
6
|
-
securityJsCode: secretKey
|
|
7
|
-
}
|
|
8
|
-
// 解决高德地图加载报错 ---> 禁止多种API加载方式混用
|
|
9
|
-
AMapLoader.reset()
|
|
10
|
-
Amap = await AMapLoader.load({
|
|
11
|
-
key: key, // 申请好的Web端开发者Key,首次调用 load 时必填
|
|
12
|
-
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
|
13
|
-
plugins: ['AMap.IndexCluster', 'AMP.MarkerCluster', 'AMap.InfoWindow', 'AMap.HeatMap', 'AMap.HawkEye', 'AMap.DistrictSearch',
|
|
14
|
-
'AMap.ToolBar', 'AMap.Geolocation', 'AMap.MouseTool',
|
|
15
|
-
'AMap.Geocoder', 'AMap.MarkerClusterer', 'AMap.AutoComplete', 'AMap.Scale'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
|
16
|
-
AMapUI: {
|
|
17
|
-
version: '1.1', // AMapUI 缺省 1.1
|
|
18
|
-
plugins: ['misc/PositionPicker'] // 需要加载的 AMapUI ui插件
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
return Amap
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async function getGDMap (address) {
|
|
26
|
-
new (await GetGDMap()).Geocoder({
|
|
27
|
-
radius: 500 // 范围,默认:500
|
|
28
|
-
}).getLocation(address, function (status, result) {
|
|
29
|
-
if (status === 'complete' && result.geocodes.length) {
|
|
30
|
-
return ({ lng: result.geocodes[0].location.lng, lat: result.geocodes[0].location.lat })
|
|
31
|
-
} else {
|
|
32
|
-
// eslint-disable-next-line prefer-promise-reject-errors
|
|
33
|
-
throw new Error('根据经纬度查询地址失败')
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function GetLocation (address) {
|
|
39
|
-
return new Promise((resolve, reject) => {
|
|
40
|
-
try {
|
|
41
|
-
resolve(getGDMap(address))
|
|
42
|
-
} catch (e) {
|
|
43
|
-
reject(e)
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
}
|
|
47
|
-
export { GetGDMap, GetLocation }
|
|
1
|
+
import AMapLoader from '@amap/amap-jsapi-loader'
|
|
2
|
+
let Amap
|
|
3
|
+
async function GetGDMap (secretKey, key) {
|
|
4
|
+
if (!Amap) {
|
|
5
|
+
window._AMapSecurityConfig = {
|
|
6
|
+
securityJsCode: secretKey
|
|
7
|
+
}
|
|
8
|
+
// 解决高德地图加载报错 ---> 禁止多种API加载方式混用
|
|
9
|
+
AMapLoader.reset()
|
|
10
|
+
Amap = await AMapLoader.load({
|
|
11
|
+
key: key, // 申请好的Web端开发者Key,首次调用 load 时必填
|
|
12
|
+
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
|
|
13
|
+
plugins: ['AMap.IndexCluster', 'AMP.MarkerCluster', 'AMap.InfoWindow', 'AMap.HeatMap', 'AMap.HawkEye', 'AMap.DistrictSearch',
|
|
14
|
+
'AMap.ToolBar', 'AMap.Geolocation', 'AMap.MouseTool',
|
|
15
|
+
'AMap.Geocoder', 'AMap.MarkerClusterer', 'AMap.AutoComplete', 'AMap.Scale'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
|
|
16
|
+
AMapUI: {
|
|
17
|
+
version: '1.1', // AMapUI 缺省 1.1
|
|
18
|
+
plugins: ['misc/PositionPicker'] // 需要加载的 AMapUI ui插件
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
return Amap
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function getGDMap (address) {
|
|
26
|
+
new (await GetGDMap()).Geocoder({
|
|
27
|
+
radius: 500 // 范围,默认:500
|
|
28
|
+
}).getLocation(address, function (status, result) {
|
|
29
|
+
if (status === 'complete' && result.geocodes.length) {
|
|
30
|
+
return ({ lng: result.geocodes[0].location.lng, lat: result.geocodes[0].location.lat })
|
|
31
|
+
} else {
|
|
32
|
+
// eslint-disable-next-line prefer-promise-reject-errors
|
|
33
|
+
throw new Error('根据经纬度查询地址失败')
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function GetLocation (address) {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
try {
|
|
41
|
+
resolve(getGDMap(address))
|
|
42
|
+
} catch (e) {
|
|
43
|
+
reject(e)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
export { GetGDMap, GetLocation }
|