af-mobile-client-vue3 1.3.58 → 1.3.60
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/package.json +1 -1
- package/public/favicon.svg +4 -4
- package/scripts/verifyCommit.js +19 -19
- package/src/components/core/ImageUploader/index.vue +7 -3
- package/src/components/data/UserDetail/types.ts +1 -1
- package/src/components/data/XForm/index.vue +5 -1
- package/src/components/data/XFormGroup/doc/DeviceForm.vue +1 -1
- package/src/components/data/XFormGroup/doc/UserForm.vue +1 -1
- package/src/components/data/XFormItem/index.vue +12 -6
- package/src/components/data/XReportGrid/XAddReport/index.ts +1 -1
- package/src/components/data/XReportGrid/XReportDemo.vue +33 -33
- package/src/components/data/XReportGrid/XReportDrawer/index.ts +1 -1
- package/src/components/data/XReportGrid/print.js +184 -184
- package/src/components/data/XTag/index.vue +10 -10
- package/src/components/layout/TabBarLayout/index.vue +40 -40
- package/src/font-style/PingFangSC-Medium.subset.woff2 +0 -0
- package/src/font-style/PingFangSC-Semibold.subset.woff2 +0 -0
- package/src/hooks/useCommon.ts +9 -9
- package/src/plugins/AppData.ts +38 -38
- package/src/router/invoiceRoutes.ts +33 -33
- package/src/services/api/common.ts +109 -109
- package/src/services/api/manage.ts +8 -8
- package/src/services/api/search.ts +16 -16
- package/src/services/restTools.ts +56 -56
- package/src/services/v3Api.ts +11 -11
- package/src/stores/modules/homeApp/README.md +124 -0
- package/src/utils/authority-utils.ts +84 -84
- package/src/utils/crypto.ts +39 -39
- package/src/utils/runEvalFunction.ts +13 -13
- package/src/views/component/EvaluateRecordView/index.vue +40 -40
- package/src/views/component/XCellDetailView/index.vue +217 -217
- package/src/views/component/XCellListView/index.vue +133 -92
- package/src/views/component/XFormGroupView/index.vue +22 -8
- package/src/views/component/XFormView/index.vue +3 -2
- package/src/views/component/XReportFormIframeView/index.vue +47 -47
- package/src/views/component/XReportFormView/index.vue +13 -13
- package/src/views/component/XSignatureView/index.vue +50 -50
- package/src/views/component/notice.vue +46 -46
- package/src/views/component/topNav.vue +36 -36
- package/src/views/invoiceShow/index.vue +61 -61
- package/src/views/user/login/index.vue +22 -22
- package/vite.config.ts +1 -1
package/src/services/v3Api.ts
CHANGED
|
@@ -9,7 +9,7 @@ function getLeafNodes(nodes) {
|
|
|
9
9
|
if (node.children && node.children.length) {
|
|
10
10
|
// 递归处理子节点并合并结果
|
|
11
11
|
leaves.push(...getLeafNodes(node.children))
|
|
12
|
-
}
|
|
12
|
+
}
|
|
13
13
|
else {
|
|
14
14
|
// 当前节点是叶子节点时,直接加入结果
|
|
15
15
|
leaves.push(node)
|
|
@@ -45,7 +45,7 @@ function getLeafNodesByCondition(type, nodes, parent = null) {
|
|
|
45
45
|
}
|
|
46
46
|
// 递归处理子节点
|
|
47
47
|
leaves.push(...getLeafNodesByCondition(type, node.children, updatedParent))
|
|
48
|
-
}
|
|
48
|
+
}
|
|
49
49
|
else if (isValidNode) {
|
|
50
50
|
// 无子节点但符合条件时,直接加入叶子节点列表
|
|
51
51
|
if (node.resourcetype === 'organization') {
|
|
@@ -53,7 +53,7 @@ function getLeafNodesByCondition(type, nodes, parent = null) {
|
|
|
53
53
|
...node,
|
|
54
54
|
name: parent ? `${node.name}-${parent}` : node.name,
|
|
55
55
|
})
|
|
56
|
-
}
|
|
56
|
+
}
|
|
57
57
|
else if (node.resourcetype === 'department' && !nodeArray.includes(node.name)) {
|
|
58
58
|
// console.log('数组',nodeArray.includes(node.name))
|
|
59
59
|
leaves.push({
|
|
@@ -86,16 +86,16 @@ function getResData(params, toCallback) {
|
|
|
86
86
|
const data = { userId: params.userid, roleName: params.roleName }
|
|
87
87
|
if (params.source === '获取分公司') {
|
|
88
88
|
runLogic('getOrgBySearch', data, 'af-system').then(res => toCallback(res))
|
|
89
|
-
}
|
|
89
|
+
}
|
|
90
90
|
else if (params.source === '获取部门') {
|
|
91
91
|
runLogic('getDepBySearch', data, 'af-system').then(res => toCallback(res))
|
|
92
|
-
}
|
|
92
|
+
}
|
|
93
93
|
else if (params.source === '获取人员') {
|
|
94
94
|
runLogic('getUserBySearch', data, 'af-system').then(res => toCallback(res))
|
|
95
|
-
}
|
|
95
|
+
}
|
|
96
96
|
else if (params.source === '根据角色获取人员') {
|
|
97
97
|
runLogic('getUserBySearchRole', data, 'af-system').then(res => toCallback(res))
|
|
98
|
-
}
|
|
98
|
+
}
|
|
99
99
|
else {
|
|
100
100
|
return search(params).then(res => toCallback(res))
|
|
101
101
|
}
|
|
@@ -107,15 +107,15 @@ export async function searchToOption(params, callback) {
|
|
|
107
107
|
if (res[0].children && res[0].children.length) {
|
|
108
108
|
if (res[0].children[0].children) {
|
|
109
109
|
callback(transformData(res[0].children[0].children))
|
|
110
|
-
}
|
|
110
|
+
}
|
|
111
111
|
else {
|
|
112
112
|
callback(transformData(res[0].children))
|
|
113
113
|
}
|
|
114
|
-
}
|
|
114
|
+
}
|
|
115
115
|
else {
|
|
116
116
|
callback(res[0].children)
|
|
117
117
|
}
|
|
118
|
-
}
|
|
118
|
+
}
|
|
119
119
|
else {
|
|
120
120
|
callback(res)
|
|
121
121
|
}
|
|
@@ -129,7 +129,7 @@ export async function searchToListOption(params, callback) {
|
|
|
129
129
|
if (params.source.includes('人员')) {
|
|
130
130
|
// console.log('ren---------',res)
|
|
131
131
|
callback(transformData(getLeafNodes(res)))
|
|
132
|
-
}
|
|
132
|
+
}
|
|
133
133
|
else {
|
|
134
134
|
const type = params.source.includes('公司') ? 'organization' : 'department'
|
|
135
135
|
// console.log('bumenpgonngsi',res)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# HomeApp Store 使用说明
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
`useHomeAppStore` 是一个专门用于管理首页应用列表的 Pinia store,与 `useSettingStore` 配合使用。
|
|
5
|
+
|
|
6
|
+
## 特性
|
|
7
|
+
- 独立管理 `homeAppList` 数据
|
|
8
|
+
- 提供完整的 CRUD 操作
|
|
9
|
+
- 与 setting store 自动同步数据
|
|
10
|
+
- 支持类型安全的 TypeScript 接口
|
|
11
|
+
|
|
12
|
+
## 基本使用
|
|
13
|
+
|
|
14
|
+
### 1. 导入和使用
|
|
15
|
+
```typescript
|
|
16
|
+
import { useHomeAppStore } from '@/stores'
|
|
17
|
+
|
|
18
|
+
const homeAppStore = useHomeAppStore()
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. 获取应用列表
|
|
22
|
+
```typescript
|
|
23
|
+
// 获取所有应用
|
|
24
|
+
const apps = homeAppStore.getHomeAppList()
|
|
25
|
+
|
|
26
|
+
// 直接访问响应式数据
|
|
27
|
+
const apps = homeAppStore.homeAppList
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 3. 添加应用
|
|
31
|
+
```typescript
|
|
32
|
+
homeAppStore.addHomeApp({
|
|
33
|
+
id: 'new-app',
|
|
34
|
+
name: '新应用',
|
|
35
|
+
icon: '/icon.png',
|
|
36
|
+
url: 'https://example.com',
|
|
37
|
+
description: '应用描述'
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 4. 更新应用
|
|
42
|
+
```typescript
|
|
43
|
+
homeAppStore.updateHomeApp('app-id', {
|
|
44
|
+
name: '更新后的名称',
|
|
45
|
+
description: '新的描述'
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 5. 删除应用
|
|
50
|
+
```typescript
|
|
51
|
+
homeAppStore.removeHomeApp('app-id')
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 6. 清空列表
|
|
55
|
+
```typescript
|
|
56
|
+
homeAppStore.clearHomeAppList()
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 数据同步
|
|
60
|
+
|
|
61
|
+
### 自动同步
|
|
62
|
+
- 当 `useSettingStore.init()` 被调用时,`homeAppList` 会自动同步到 `useHomeAppStore`
|
|
63
|
+
- 无需手动同步,数据会自动保持一致
|
|
64
|
+
|
|
65
|
+
### 手动同步
|
|
66
|
+
```typescript
|
|
67
|
+
import { useSettingStore, useHomeAppStore } from '@/stores'
|
|
68
|
+
|
|
69
|
+
const settingStore = useSettingStore()
|
|
70
|
+
const homeAppStore = useHomeAppStore()
|
|
71
|
+
|
|
72
|
+
// 手动同步数据
|
|
73
|
+
homeAppStore.setHomeAppList(settingStore.getSetting()?.homeAppList || [])
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 在组件中使用
|
|
77
|
+
|
|
78
|
+
### Vue 组件示例
|
|
79
|
+
```vue
|
|
80
|
+
<template>
|
|
81
|
+
<div class="home-apps">
|
|
82
|
+
<div
|
|
83
|
+
v-for="app in homeAppStore.homeAppList"
|
|
84
|
+
:key="app.id"
|
|
85
|
+
class="app-item"
|
|
86
|
+
@click="openApp(app)"
|
|
87
|
+
>
|
|
88
|
+
<img :src="app.icon" :alt="app.name" />
|
|
89
|
+
<span>{{ app.name }}</span>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
</template>
|
|
93
|
+
|
|
94
|
+
<script setup lang="ts">
|
|
95
|
+
import { useHomeAppStore } from '@/stores'
|
|
96
|
+
|
|
97
|
+
const homeAppStore = useHomeAppStore()
|
|
98
|
+
|
|
99
|
+
function openApp(app) {
|
|
100
|
+
// 处理应用点击
|
|
101
|
+
window.open(app.url, '_blank')
|
|
102
|
+
}
|
|
103
|
+
</script>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 注意事项
|
|
107
|
+
|
|
108
|
+
1. **初始化顺序**:确保先调用 `useSettingStore.init()`,再使用 `useHomeAppStore`
|
|
109
|
+
2. **数据一致性**:两个 store 中的数据会自动保持同步
|
|
110
|
+
3. **类型安全**:使用 TypeScript 接口确保类型安全
|
|
111
|
+
4. **响应式**:所有数据都是响应式的,可以直接在模板中使用
|
|
112
|
+
|
|
113
|
+
## 接口定义
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
export interface HomeApp {
|
|
117
|
+
id: string // 应用唯一标识
|
|
118
|
+
name: string // 应用名称
|
|
119
|
+
icon: string // 应用图标
|
|
120
|
+
url: string // 应用链接
|
|
121
|
+
description?: string // 应用描述(可选)
|
|
122
|
+
[key: string]: any // 其他属性
|
|
123
|
+
}
|
|
124
|
+
```
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 判断是否有路由的权限
|
|
3
|
-
* @param authority 路由权限配置
|
|
4
|
-
* @param permissions 用户权限集合
|
|
5
|
-
*/
|
|
6
|
-
function hasPermission(authority: any, permissions: any): boolean {
|
|
7
|
-
let required: string = '*'
|
|
8
|
-
if (typeof authority === 'string')
|
|
9
|
-
required = authority
|
|
10
|
-
else if (Array.isArray(authority))
|
|
11
|
-
required = authority.toString()
|
|
12
|
-
else if (typeof authority === 'object')
|
|
13
|
-
required = authority.permission
|
|
14
|
-
|
|
15
|
-
return required === '*' || hasAnyItem(required, permissions, (r, t) => !!(r === t || r === t.id))
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 判断是否有路由需要的角色
|
|
20
|
-
* @param authority 路由权限配置
|
|
21
|
-
* @param roles 用户角色集合
|
|
22
|
-
*/
|
|
23
|
-
function hasRole(authority, roles) {
|
|
24
|
-
let required
|
|
25
|
-
if (typeof authority === 'object')
|
|
26
|
-
required = authority.role
|
|
27
|
-
|
|
28
|
-
return authority === '*' || hasAnyItem(required, roles, (r, t) => !!(r === t || r === t.id))
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* 判断目标数组是否有所需元素
|
|
33
|
-
* @param {string | string[]}required 所需元素,数组或单个元素
|
|
34
|
-
* @param {string[] | object[]} source 目标数组
|
|
35
|
-
* @param {Function} filter 匹配条件
|
|
36
|
-
* (r: String, s: String|Object) => boolean
|
|
37
|
-
*/
|
|
38
|
-
function hasAnyItem(required, source, filter): boolean {
|
|
39
|
-
if (!required)
|
|
40
|
-
return false
|
|
41
|
-
|
|
42
|
-
const checkedList = Array.isArray(required) ? required : [required]
|
|
43
|
-
return !!source.find(s => checkedList.find(r => filter(r, s)))
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* 路由权限校验
|
|
48
|
-
* @param route 路由
|
|
49
|
-
* @param permissions 用户权限集合
|
|
50
|
-
* @param roles 用户角色集合
|
|
51
|
-
*/
|
|
52
|
-
function hasAuthority(route, permissions, roles) {
|
|
53
|
-
// TODO 此处判断可能有问题
|
|
54
|
-
if (!route.meta.pAuthorities)
|
|
55
|
-
return true
|
|
56
|
-
|
|
57
|
-
const authorities = [...route.meta.pAuthorities, route.meta.authority]
|
|
58
|
-
for (const authority of authorities) {
|
|
59
|
-
if (!hasPermission(authority, permissions) && !hasRole(authority, roles))
|
|
60
|
-
return false
|
|
61
|
-
}
|
|
62
|
-
return true
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 根据权限配置过滤菜单数据
|
|
67
|
-
* @param menuData
|
|
68
|
-
* @param permissions
|
|
69
|
-
* @param roles
|
|
70
|
-
*/
|
|
71
|
-
function filterMenu(menuData, permissions, roles) {
|
|
72
|
-
return menuData.filter((menu) => {
|
|
73
|
-
if (menu.meta && menu.meta.invisible === undefined) {
|
|
74
|
-
if (!hasAuthority(menu, permissions, roles))
|
|
75
|
-
return false
|
|
76
|
-
}
|
|
77
|
-
if (menu.children && menu.children.length > 0)
|
|
78
|
-
menu.children = filterMenu(menu.children, permissions, roles)
|
|
79
|
-
|
|
80
|
-
return true
|
|
81
|
-
})
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export { filterMenu, hasAuthority }
|
|
1
|
+
/**
|
|
2
|
+
* 判断是否有路由的权限
|
|
3
|
+
* @param authority 路由权限配置
|
|
4
|
+
* @param permissions 用户权限集合
|
|
5
|
+
*/
|
|
6
|
+
function hasPermission(authority: any, permissions: any): boolean {
|
|
7
|
+
let required: string = '*'
|
|
8
|
+
if (typeof authority === 'string')
|
|
9
|
+
required = authority
|
|
10
|
+
else if (Array.isArray(authority))
|
|
11
|
+
required = authority.toString()
|
|
12
|
+
else if (typeof authority === 'object')
|
|
13
|
+
required = authority.permission
|
|
14
|
+
|
|
15
|
+
return required === '*' || hasAnyItem(required, permissions, (r, t) => !!(r === t || r === t.id))
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 判断是否有路由需要的角色
|
|
20
|
+
* @param authority 路由权限配置
|
|
21
|
+
* @param roles 用户角色集合
|
|
22
|
+
*/
|
|
23
|
+
function hasRole(authority, roles) {
|
|
24
|
+
let required
|
|
25
|
+
if (typeof authority === 'object')
|
|
26
|
+
required = authority.role
|
|
27
|
+
|
|
28
|
+
return authority === '*' || hasAnyItem(required, roles, (r, t) => !!(r === t || r === t.id))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 判断目标数组是否有所需元素
|
|
33
|
+
* @param {string | string[]}required 所需元素,数组或单个元素
|
|
34
|
+
* @param {string[] | object[]} source 目标数组
|
|
35
|
+
* @param {Function} filter 匹配条件
|
|
36
|
+
* (r: String, s: String|Object) => boolean
|
|
37
|
+
*/
|
|
38
|
+
function hasAnyItem(required, source, filter): boolean {
|
|
39
|
+
if (!required)
|
|
40
|
+
return false
|
|
41
|
+
|
|
42
|
+
const checkedList = Array.isArray(required) ? required : [required]
|
|
43
|
+
return !!source.find(s => checkedList.find(r => filter(r, s)))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 路由权限校验
|
|
48
|
+
* @param route 路由
|
|
49
|
+
* @param permissions 用户权限集合
|
|
50
|
+
* @param roles 用户角色集合
|
|
51
|
+
*/
|
|
52
|
+
function hasAuthority(route, permissions, roles) {
|
|
53
|
+
// TODO 此处判断可能有问题
|
|
54
|
+
if (!route.meta.pAuthorities)
|
|
55
|
+
return true
|
|
56
|
+
|
|
57
|
+
const authorities = [...route.meta.pAuthorities, route.meta.authority]
|
|
58
|
+
for (const authority of authorities) {
|
|
59
|
+
if (!hasPermission(authority, permissions) && !hasRole(authority, roles))
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 根据权限配置过滤菜单数据
|
|
67
|
+
* @param menuData
|
|
68
|
+
* @param permissions
|
|
69
|
+
* @param roles
|
|
70
|
+
*/
|
|
71
|
+
function filterMenu(menuData, permissions, roles) {
|
|
72
|
+
return menuData.filter((menu) => {
|
|
73
|
+
if (menu.meta && menu.meta.invisible === undefined) {
|
|
74
|
+
if (!hasAuthority(menu, permissions, roles))
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
if (menu.children && menu.children.length > 0)
|
|
78
|
+
menu.children = filterMenu(menu.children, permissions, roles)
|
|
79
|
+
|
|
80
|
+
return true
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { filterMenu, hasAuthority }
|
package/src/utils/crypto.ts
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import AesEncryptJS from 'crypto-js'
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
/**
|
|
5
|
-
* AES加密
|
|
6
|
-
*
|
|
7
|
-
* @param word
|
|
8
|
-
* @param encryKey
|
|
9
|
-
*/
|
|
10
|
-
AESEncrypt(word: string, encryKey: string): string {
|
|
11
|
-
const key = AesEncryptJS.enc.Utf8.parse(encryKey)
|
|
12
|
-
const srcs = AesEncryptJS.enc.Utf8.parse(word)
|
|
13
|
-
const encrypted = AesEncryptJS.AES.encrypt(srcs, key, {
|
|
14
|
-
mode: AesEncryptJS.mode.ECB,
|
|
15
|
-
padding: AesEncryptJS.pad.Pkcs7,
|
|
16
|
-
})
|
|
17
|
-
return encrypted.toString()
|
|
18
|
-
},
|
|
19
|
-
/**
|
|
20
|
-
* AES解密
|
|
21
|
-
*
|
|
22
|
-
* @param word
|
|
23
|
-
* @param encryKey
|
|
24
|
-
*/
|
|
25
|
-
AESDecrypt(word: string, encryKey: string): any {
|
|
26
|
-
const key = AesEncryptJS.enc.Utf8.parse(encryKey)
|
|
27
|
-
const decrypt = AesEncryptJS.AES.decrypt(word, key, {
|
|
28
|
-
mode: AesEncryptJS.mode.ECB,
|
|
29
|
-
padding: AesEncryptJS.pad.Pkcs7,
|
|
30
|
-
})
|
|
31
|
-
const ret = AesEncryptJS.enc.Utf8.stringify(decrypt).toString()
|
|
32
|
-
try {
|
|
33
|
-
return JSON.parse(ret)
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
return ret
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
}
|
|
1
|
+
import AesEncryptJS from 'crypto-js'
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
/**
|
|
5
|
+
* AES加密
|
|
6
|
+
*
|
|
7
|
+
* @param word
|
|
8
|
+
* @param encryKey
|
|
9
|
+
*/
|
|
10
|
+
AESEncrypt(word: string, encryKey: string): string {
|
|
11
|
+
const key = AesEncryptJS.enc.Utf8.parse(encryKey)
|
|
12
|
+
const srcs = AesEncryptJS.enc.Utf8.parse(word)
|
|
13
|
+
const encrypted = AesEncryptJS.AES.encrypt(srcs, key, {
|
|
14
|
+
mode: AesEncryptJS.mode.ECB,
|
|
15
|
+
padding: AesEncryptJS.pad.Pkcs7,
|
|
16
|
+
})
|
|
17
|
+
return encrypted.toString()
|
|
18
|
+
},
|
|
19
|
+
/**
|
|
20
|
+
* AES解密
|
|
21
|
+
*
|
|
22
|
+
* @param word
|
|
23
|
+
* @param encryKey
|
|
24
|
+
*/
|
|
25
|
+
AESDecrypt(word: string, encryKey: string): any {
|
|
26
|
+
const key = AesEncryptJS.enc.Utf8.parse(encryKey)
|
|
27
|
+
const decrypt = AesEncryptJS.AES.decrypt(word, key, {
|
|
28
|
+
mode: AesEncryptJS.mode.ECB,
|
|
29
|
+
padding: AesEncryptJS.pad.Pkcs7,
|
|
30
|
+
})
|
|
31
|
+
const ret = AesEncryptJS.enc.Utf8.stringify(decrypt).toString()
|
|
32
|
+
try {
|
|
33
|
+
return JSON.parse(ret)
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return ret
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
export function executeStrFunction(funcString, args) {
|
|
2
|
-
// 使用 eval 执行传入的函数字符串
|
|
3
|
-
// eslint-disable-next-line no-eval
|
|
4
|
-
return eval(`(${funcString})`)(...args)
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function executeStrFunctionByContext(context, fnStr, args) {
|
|
8
|
-
// 使用 new Function 创建函数,并绑定 context 作为 this
|
|
9
|
-
// eslint-disable-next-line no-new-func
|
|
10
|
-
const fn = new Function(`return (${fnStr});`)()
|
|
11
|
-
// 使用 bind 绑定 context,并立即调用
|
|
12
|
-
return fn.bind(context)(...args)
|
|
13
|
-
}
|
|
1
|
+
export function executeStrFunction(funcString, args) {
|
|
2
|
+
// 使用 eval 执行传入的函数字符串
|
|
3
|
+
// eslint-disable-next-line no-eval
|
|
4
|
+
return eval(`(${funcString})`)(...args)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function executeStrFunctionByContext(context, fnStr, args) {
|
|
8
|
+
// 使用 new Function 创建函数,并绑定 context 作为 this
|
|
9
|
+
// eslint-disable-next-line no-new-func
|
|
10
|
+
const fn = new Function(`return (${fnStr});`)()
|
|
11
|
+
// 使用 bind 绑定 context,并立即调用
|
|
12
|
+
return fn.bind(context)(...args)
|
|
13
|
+
}
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import XCellList from '@af-mobile-client-vue3/components/data/XCellList/index.vue'
|
|
3
|
-
import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
Icon as VanIcon,
|
|
7
|
-
} from 'vant'
|
|
8
|
-
import { ref } from 'vue'
|
|
9
|
-
|
|
10
|
-
const configName = ref('get_evaluate_by_id')
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<template>
|
|
14
|
-
<NormalDataLayout title="评价纪录">
|
|
15
|
-
<template #layout_header_row_right_col>
|
|
16
|
-
<VanIcon class="header_row_icon" name="filter-o" />
|
|
17
|
-
</template>
|
|
18
|
-
<template #layout_content>
|
|
19
|
-
<XCellList :config-name="configName" id-key="t_id" service-name="af-revenue" />
|
|
20
|
-
</template>
|
|
21
|
-
</NormalDataLayout>
|
|
22
|
-
</template>
|
|
23
|
-
|
|
24
|
-
<style scoped lang="less">
|
|
25
|
-
.header_row_icon {
|
|
26
|
-
font-size: 18px;
|
|
27
|
-
}
|
|
28
|
-
//.van-tabs {
|
|
29
|
-
// display: flex;
|
|
30
|
-
// flex-flow: column;
|
|
31
|
-
// height: 100%;
|
|
32
|
-
//}
|
|
33
|
-
//:deep(.van-tabs__content) {
|
|
34
|
-
// flex: 1;
|
|
35
|
-
//}
|
|
36
|
-
//:deep(.van-tab__panel) {
|
|
37
|
-
// height: 100%;
|
|
38
|
-
// max-height: 100vh;
|
|
39
|
-
//}
|
|
40
|
-
</style>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import XCellList from '@af-mobile-client-vue3/components/data/XCellList/index.vue'
|
|
3
|
+
import NormalDataLayout from '@af-mobile-client-vue3/components/layout/NormalDataLayout/index.vue'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Icon as VanIcon,
|
|
7
|
+
} from 'vant'
|
|
8
|
+
import { ref } from 'vue'
|
|
9
|
+
|
|
10
|
+
const configName = ref('get_evaluate_by_id')
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<template>
|
|
14
|
+
<NormalDataLayout title="评价纪录">
|
|
15
|
+
<template #layout_header_row_right_col>
|
|
16
|
+
<VanIcon class="header_row_icon" name="filter-o" />
|
|
17
|
+
</template>
|
|
18
|
+
<template #layout_content>
|
|
19
|
+
<XCellList :config-name="configName" id-key="t_id" service-name="af-revenue" />
|
|
20
|
+
</template>
|
|
21
|
+
</NormalDataLayout>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<style scoped lang="less">
|
|
25
|
+
.header_row_icon {
|
|
26
|
+
font-size: 18px;
|
|
27
|
+
}
|
|
28
|
+
//.van-tabs {
|
|
29
|
+
// display: flex;
|
|
30
|
+
// flex-flow: column;
|
|
31
|
+
// height: 100%;
|
|
32
|
+
//}
|
|
33
|
+
//:deep(.van-tabs__content) {
|
|
34
|
+
// flex: 1;
|
|
35
|
+
//}
|
|
36
|
+
//:deep(.van-tab__panel) {
|
|
37
|
+
// height: 100%;
|
|
38
|
+
// max-height: 100vh;
|
|
39
|
+
//}
|
|
40
|
+
</style>
|