sohelp-eleplus 1.1.26 → 1.1.28

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.
Files changed (205) hide show
  1. package/components.js +1 -0
  2. package/icons/flag/README.md +2 -2
  3. package/icons/flag/index.js +0 -1
  4. package/package.json +1 -1
  5. package/sohelp-ace-editor/README.md +32 -42
  6. package/sohelp-ace-editor/index.vue +166 -156
  7. package/sohelp-api-doc/README.md +36 -0
  8. package/sohelp-api-doc/index.vue +160 -0
  9. package/sohelp-application-select/README.md +9 -7
  10. package/sohelp-application-select/index.vue +10 -13
  11. package/sohelp-autocode/README.md +14 -26
  12. package/sohelp-calendar-view/README.md +9 -7
  13. package/sohelp-calendar-view/index.vue +10 -9
  14. package/sohelp-card/README.md +15 -17
  15. package/sohelp-card/index.vue +1 -1
  16. package/sohelp-card-view/README.md +9 -7
  17. package/sohelp-card-view/index.vue +10 -9
  18. package/sohelp-condition/README.md +29 -49
  19. package/sohelp-condition/index.vue +2 -1
  20. package/sohelp-country-select/README.md +15 -123
  21. package/sohelp-country-select/index.vue +1 -1
  22. package/sohelp-cry-input/README.md +19 -195
  23. package/sohelp-cry-input/index.vue +6 -2
  24. package/sohelp-date/README.md +12 -15
  25. package/sohelp-datetime/README.md +15 -17
  26. package/sohelp-datetime-picker/README.md +18 -18
  27. package/sohelp-datetime-picker/index.vue +11 -4
  28. package/sohelp-datetime-range/README.md +20 -23
  29. package/sohelp-demo-block/README.md +43 -0
  30. package/sohelp-demo-block/index.vue +229 -0
  31. package/sohelp-dict/README.md +28 -23
  32. package/sohelp-dict/index.vue +17 -17
  33. package/sohelp-drawer/README.md +28 -26
  34. package/sohelp-drop-card/README.md +29 -28
  35. package/sohelp-drop-card/index.vue +0 -1
  36. package/sohelp-dyn-select/README.md +31 -16
  37. package/sohelp-dyn-select/index.vue +65 -67
  38. package/sohelp-dyn-tree/README.md +26 -20
  39. package/sohelp-dyn-tree/index.vue +2 -2
  40. package/sohelp-dyn-tree-select/README.md +28 -19
  41. package/sohelp-dyn-tree-select/index.vue +23 -7
  42. package/sohelp-entity-form/README.md +65 -30
  43. package/sohelp-entity-form/index.vue +3 -2
  44. package/sohelp-entity-grid/README.md +13 -11
  45. package/sohelp-entity-grid/index.vue +1 -1
  46. package/sohelp-file-upload/README.md +25 -27
  47. package/sohelp-file-upload/index.vue +1 -1
  48. package/sohelp-filter-scheme/README.md +34 -30
  49. package/sohelp-filter-scheme/index.vue +2 -2
  50. package/sohelp-grid/README.md +52 -33
  51. package/sohelp-grid/index.vue +41 -39
  52. package/sohelp-grid/js/SohelpGridConfig.js +3 -3
  53. package/sohelp-grid/js/useSohelpGridConfig.js +4 -6
  54. package/sohelp-grid-select/README.md +32 -27
  55. package/sohelp-grid-select/index.vue +6 -5
  56. package/sohelp-grid-view/README.md +51 -22
  57. package/sohelp-grid-view-select/README.md +33 -25
  58. package/sohelp-grid-view-select/index.vue +2 -1
  59. package/sohelp-group-view/README.md +14 -4
  60. package/sohelp-group-view/index.vue +10 -9
  61. package/sohelp-icon-select/README.md +14 -12
  62. package/sohelp-image-upload/README.md +27 -27
  63. package/sohelp-image-upload/index.vue +2 -2
  64. package/sohelp-import/README.md +25 -24
  65. package/sohelp-input/README.md +27 -11
  66. package/sohelp-input/index.vue +15 -2
  67. package/sohelp-input-tag/README.md +53 -0
  68. package/sohelp-input-tag/index.vue +337 -0
  69. package/sohelp-modal/README.md +42 -16
  70. package/sohelp-modal/index.vue +21 -4
  71. package/sohelp-modal-select/README.md +745 -0
  72. package/sohelp-modal-select/index.vue +705 -0
  73. package/sohelp-module/README.md +24 -13
  74. package/sohelp-number-input/README.md +15 -8
  75. package/sohelp-number-input/index.vue +3 -0
  76. package/sohelp-number-range/README.md +22 -12
  77. package/sohelp-number-range/index.vue +3 -11
  78. package/sohelp-org-modal-select/README.md +47 -0
  79. package/sohelp-org-modal-select/index.vue +411 -0
  80. package/sohelp-org-select/README.md +23 -10
  81. package/sohelp-org-select/index.vue +41 -24
  82. package/sohelp-org-tree/README.md +19 -7
  83. package/sohelp-org-tree/index.vue +1 -2
  84. package/sohelp-org-tree-select/README.md +22 -11
  85. package/sohelp-org-tree-select/index.vue +1 -2
  86. package/sohelp-org-user-tree/README.md +19 -7
  87. package/sohelp-org-user-tree/index.vue +1 -2
  88. package/sohelp-org-user-tree-select/README.md +8 -3
  89. package/sohelp-org-user-tree-select/index.vue +8 -7
  90. package/sohelp-page/README.md +20 -11
  91. package/sohelp-page/index.vue +1 -1
  92. package/sohelp-pagination/README.md +14 -6
  93. package/sohelp-pagination/index.vue +1 -1
  94. package/sohelp-power/README.md +34 -19
  95. package/sohelp-power/index.vue +2 -2
  96. package/sohelp-pro-form/README.md +64 -21
  97. package/sohelp-pro-layout/README.md +10 -4
  98. package/sohelp-pro-layout/index.vue +8 -7
  99. package/sohelp-pro-table/README.md +30 -6
  100. package/sohelp-process/README.md +26 -13
  101. package/sohelp-process/index.vue +6 -6
  102. package/sohelp-rate/README.md +24 -12
  103. package/sohelp-rate/index.vue +5 -1
  104. package/sohelp-relation/README.md +10 -4
  105. package/sohelp-relation/index.vue +8 -7
  106. package/sohelp-relation-modal-select/README.md +41 -0
  107. package/sohelp-relation-modal-select/index.vue +70 -0
  108. package/sohelp-rich-text/README.md +29 -11
  109. package/sohelp-rich-text/index.vue +21 -20
  110. package/sohelp-richtext/README.md +12 -2
  111. package/sohelp-richtext/index.vue +8 -6
  112. package/sohelp-role-modal-select/README.md +45 -0
  113. package/sohelp-role-modal-select/index.vue +111 -0
  114. package/sohelp-role-select/README.md +18 -10
  115. package/sohelp-role-select/index.vue +36 -27
  116. package/sohelp-search/README.md +12 -4
  117. package/sohelp-search/index.vue +2 -2
  118. package/sohelp-search-pro-form/README.md +15 -1
  119. package/sohelp-search-pro-form/index.vue +2 -1
  120. package/sohelp-select/README.md +31 -30
  121. package/sohelp-select/index.vue +79 -84
  122. package/sohelp-split-panel/README.md +17 -18
  123. package/sohelp-switch/README.md +21 -19
  124. package/sohelp-switch/index.vue +34 -33
  125. package/sohelp-table/README.md +35 -27
  126. package/sohelp-table/index.vue +110 -109
  127. package/sohelp-table-select/README.md +55 -0
  128. package/sohelp-tenant-select/README.md +19 -18
  129. package/sohelp-tenant-select/index.vue +105 -109
  130. package/sohelp-text/README.md +16 -10
  131. package/sohelp-text/index.vue +5 -5
  132. package/sohelp-textarea-input/README.md +19 -12
  133. package/sohelp-time/README.md +11 -10
  134. package/sohelp-tree/README.md +24 -19
  135. package/sohelp-tree/index.vue +21 -23
  136. package/sohelp-tree-select/README.md +23 -10
  137. package/sohelp-user-modal-select/README.md +739 -0
  138. package/sohelp-user-modal-select/index.vue +87 -0
  139. package/sohelp-user-select/README.md +26 -15
  140. package/sohelp-user-select/index.vue +6 -2
  141. package/sohelp-user-tag/README.md +5 -7
  142. package/sohelp-user-tag/index.vue +8 -8
  143. package/sohelp-user-tree/README.md +5 -8
  144. package/sohelp-user-tree/index.vue +8 -7
  145. package/sohelp-vform-drawer/README.md +36 -18
  146. package/sohelp-vform-drawer/index.vue +2 -2
  147. package/sohelp-vform-eleplus/README.md +33 -31
  148. package/sohelp-vform-eleplus/index.vue +2 -2
  149. package/sohelp-vform-eleplus/tinymce/langs/zh_CN.js +461 -461
  150. package/sohelp-vform-eleplus/tinymce/langs/zh_TW.js +418 -418
  151. package/sohelp-vform-eleplus/tinymce/skins/content/dark/content.css +72 -72
  152. package/sohelp-vform-eleplus/tinymce/skins/content/dark/content.min.css +7 -7
  153. package/sohelp-vform-eleplus/tinymce/skins/content/default/content.css +67 -67
  154. package/sohelp-vform-eleplus/tinymce/skins/content/default/content.min.css +7 -7
  155. package/sohelp-vform-eleplus/tinymce/skins/content/document/content.css +72 -72
  156. package/sohelp-vform-eleplus/tinymce/skins/content/document/content.min.css +7 -7
  157. package/sohelp-vform-eleplus/tinymce/skins/content/writer/content.css +68 -68
  158. package/sohelp-vform-eleplus/tinymce/skins/content/writer/content.min.css +7 -7
  159. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.css +732 -732
  160. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.inline.css +726 -726
  161. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.inline.min.css +7 -7
  162. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.min.css +7 -7
  163. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.mobile.css +29 -29
  164. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/content.mobile.min.css +7 -7
  165. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.css +3047 -3047
  166. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.min.css +7 -7
  167. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.mobile.css +673 -673
  168. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.mobile.min.css +7 -7
  169. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.shadowdom.css +37 -37
  170. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide/skin.shadowdom.min.css +7 -7
  171. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.css +714 -714
  172. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.inline.css +726 -726
  173. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.inline.min.css +7 -7
  174. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.min.css +7 -7
  175. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.mobile.css +29 -29
  176. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/content.mobile.min.css +7 -7
  177. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.css +3047 -3047
  178. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.min.css +7 -7
  179. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.mobile.css +673 -673
  180. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.mobile.min.css +7 -7
  181. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.shadowdom.css +37 -37
  182. package/sohelp-vform-eleplus/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css +7 -7
  183. package/sohelp-vform-modal/README.md +36 -18
  184. package/sohelp-vform-modal/index.vue +2 -2
  185. package/sohelp-vform-select/README.md +9 -7
  186. package/sohelp-vform-select/index.vue +8 -7
  187. package/sohelp-vxe-grid/DefaultGridOptions.js +5 -3
  188. package/sohelp-vxe-grid/DefaultProps.js +0 -1
  189. package/sohelp-vxe-grid/README.md +540 -35
  190. package/sohelp-vxe-grid/SohelpGridConfig.js +8 -6
  191. package/sohelp-vxe-grid/index.vue +141 -94
  192. package/sohelp-vxe-grid-select/README.md +41 -26
  193. package/sohelp-vxe-table/README.md +23 -20
  194. package/sohelp-vxe-table/index.vue +5 -4
  195. package/sohelp-workflow/README.md +21 -17
  196. package/sohelp-workflow/index.vue +25 -22
  197. package/sohelp-workflow-drawer/README.md +41 -28
  198. package/sohelp-workflow-drawer/components/table.vue +7 -1
  199. package/sohelp-workflow-drawer/index.vue +86 -71
  200. package/sohelp-workflow-drawer/js/index.js +15 -13
  201. package/style/index.scss +0 -0
  202. package/utils/safe-eval.js +89 -0
  203. package/sohelp-dyn-select/props.js +0 -67
  204. package/sohelp-user-select/index.vue~ +0 -53
  205. package/sohelp-user-select/props.js +0 -71
@@ -1,38 +1,51 @@
1
- # SohelpWorkflowDrawer
1
+ # SohelpWorkflowDrawer 工作流审批抽屉
2
2
 
3
- A drawer component for displaying workflow details, processing approvals, and viewing history.
3
+ 基于 `ele-drawer` 封装的工作流审批详情抽屉组件,包含表单、流程图、表格和时间轴四个 Tab 页,支持同意、拒绝、委派、加签、减签等审批操作。
4
4
 
5
- ## Props
6
-
7
- | Name | Type | Default | Description |
8
- | :--- | :--- | :--- | :--- |
9
- | `modelValue` | `Boolean` | - | Controls the visibility of the drawer. |
10
- | `data` | `Object` | - | Requires `{ id, refid }` to fetch workflow details. |
11
- | `showOpera` | `Boolean` | `true` | Whether to show operation buttons (Agree, Reject, etc.). |
12
-
13
- ## Events
14
-
15
- | Name | Parameters | Description |
16
- | :--- | :--- | :--- |
17
- | `update:modelValue` | `(visible)` | Updates the visibility state. |
18
- | `reload` | - | Triggered when an operation is completed successfully. |
19
- | `close` | - | Triggered when the drawer is closed. |
20
-
21
- ## Methods
22
-
23
- | Name | Description |
24
- | :--- | :--- |
25
- | `show(params)` | Opens the drawer with the given parameters. |
26
- | `close()` | Closes the drawer. |
27
-
28
- ## Usage
5
+ ## 基础用法
29
6
 
30
7
  ```vue
31
8
  <template>
32
9
  <sohelp-workflow-drawer
33
10
  v-model="visible"
34
- :data="{ id: '123', refid: 'flow_abc' }"
35
- @reload="refreshList"
11
+ :data="rowData"
12
+ @reload="reloadTable"
13
+ @close="onClose"
14
+ ref="drawerRef"
36
15
  />
37
16
  </template>
17
+
18
+ <script setup>
19
+ import { ref } from 'vue';
20
+ const visible = ref(false);
21
+ const rowData = ref({ id: '', refid: '' });
22
+ const drawerRef = ref(null);
23
+ const reloadTable = () => { /* 刷新列表 */ };
24
+ const onClose = () => { /* 关闭回调 */ };
25
+
26
+ // 通过 expose 方法打开
27
+ drawerRef.value?.show({ id: '123', refid: 'myRefId' });
28
+ </script>
38
29
  ```
30
+
31
+ ## 属性 (Props)
32
+
33
+ | 属性名 | 类型 | 默认值 | 必填 | 说明 |
34
+ | --- | --- | --- | --- | --- |
35
+ | modelValue (v-model) | Boolean | - | 否 | 控制抽屉显示/隐藏 |
36
+ | data | Object | - | 否 | 审批数据对象,需包含 `id` 和 `refid` |
37
+
38
+ ## 事件 (Events)
39
+
40
+ | 事件名 | 回调参数 | 说明 |
41
+ | --- | --- | --- |
42
+ | update:modelValue | `value: Boolean` | 抽屉显示状态变化 |
43
+ | update:data | `value: Object` | 数据更新 |
44
+ | opera | - | 操作事件 |
45
+ | reload | - | 审批完成后请求刷新列表 |
46
+ | close | - | 抽屉关闭时触发 |
47
+
48
+ ## 公开方法 (Expose)
49
+
50
+ - `show(params)` - 打开抽屉并设置数据,`params` 需含 `id` 和 `refid`
51
+ - `close()` - 关闭抽屉
@@ -16,7 +16,13 @@
16
16
  <template #actorList="{ row }">
17
17
  <div style="display: flex; gap: 5px; flex-wrap: wrap">
18
18
  <span v-for="item in row?.actorList" :key="item.actor_id">
19
- <vxe-tag status="primary">{{ item.actor_name }}</vxe-tag>
19
+ <vxe-tag status="primary">{{ item?.actor_name }}</vxe-tag>
20
+ </span>
21
+ </div>
22
+
23
+ <div style="display: flex; gap: 5px; flex-wrap: wrap" v-if="row.type != 'done'">
24
+ <span v-for="item in row?.assigneeList" :key="item.actor_id">
25
+ <vxe-tag status="info">{{ item?.name }}</vxe-tag>
20
26
  </span>
21
27
  </div>
22
28
  </template>
@@ -63,23 +63,44 @@
63
63
 
64
64
  <template #footer>
65
65
  <el-button @click="userModal = false">取消</el-button>
66
- <el-button type="primary" @click="saveByUser(todoType, users)" v-loading="loading" :disabled="!users.length"
66
+ <el-button
67
+ type="primary"
68
+ @click="saveByUser(todoType, users)"
69
+ v-loading="loading"
70
+ :disabled="!users.length"
67
71
  >{{ moreOption[todoType] }}
68
72
  </el-button>
69
73
  </template>
70
74
  </ele-modal>
71
75
 
72
76
  <template #footer>
73
- <el-button plain size="small" @click="updateModelValue(false)">关闭</el-button>
74
- <span v-if="showOpera">
75
- <el-button type="primary" size="small" @click="openModal('agree')" v-permission="'todo.wf.agree'"
76
- >同意</el-button
77
+ <el-button plain size="small" @click="updateModelValue(false)"
78
+ >关闭</el-button
79
+ >
80
+ <span v-if="showOpera && data">
81
+ <el-button
82
+ v-permission="refidPrefix + 'workflow.agree'"
83
+ type="primary"
84
+ size="small"
85
+ @click="openModal('agree')"
77
86
  >
78
- <el-button type="danger" size="small" @click="openModal('reject')" v-permission="'todo.wf.reject'"
79
- >拒绝</el-button
87
+ 同意
88
+ </el-button>
89
+ <el-button
90
+ v-permission="refidPrefix + 'workflow.reject'"
91
+ type="danger"
92
+ size="small"
93
+ @click="openModal('reject')"
94
+ >
95
+ 拒绝
96
+ </el-button>
97
+ <ele-dropdown
98
+ v-if="getMore.length > 0"
99
+ trigger="click"
100
+ :items="getMore"
101
+ @command="onOperate"
80
102
  >
81
- <ele-dropdown trigger="click" :items="getMore" @command="onOperate($event)" v-if="getMore.length > 0">
82
- <el-button plain="" size="small" title="更多" :icon="MoreFilled"></el-button>
103
+ <el-button size="small" :icon="MoreFilled" title="更多" />
83
104
  </ele-dropdown>
84
105
  </span>
85
106
  </template>
@@ -87,12 +108,13 @@
87
108
  </template>
88
109
 
89
110
  <script setup>
90
- import { buttonAuth, getTodoDetail, moreOption, todoOperate } from '@/api/todo/index.js';
111
+ import { buttonAuth, getTodoDetail, moreOption, todoOperate } from './js';
112
+
91
113
  import { EleMessage } from '@/components/ele-admin-plus/components';
92
114
  import { MoreFilled } from '@element-plus/icons-vue';
93
115
  import { ElMessageBox } from 'element-plus/es';
94
116
  import { usePermission } from '@/utils/use-permission';
95
- import { computed, reactive, ref, watch } from 'vue';
117
+ import { computed, reactive, ref } from 'vue';
96
118
  import FormTab from './components/form.vue';
97
119
  import TableTab from './components/table.vue';
98
120
  import TimelineTab from './components/timeline.vue';
@@ -103,14 +125,18 @@
103
125
 
104
126
  const props = defineProps({
105
127
  modelValue: Boolean,
106
- data: Object,
107
- showOpera: {
108
- type: Boolean,
109
- default: true
110
- }
128
+ data: Object
111
129
  });
112
130
 
113
- const emit = defineEmits(['opera', 'update:data', 'update:showOpera', 'update:modelValue', 'reload', 'close']);
131
+ const showOpera = ref(false);
132
+
133
+ const emit = defineEmits([
134
+ 'opera',
135
+ 'update:data',
136
+ 'update:modelValue',
137
+ 'reload',
138
+ 'close'
139
+ ]);
114
140
 
115
141
  const tabs = reactive([
116
142
  { label: '表单', name: 'form' },
@@ -120,23 +146,26 @@
120
146
  ]);
121
147
  const active = ref('form');
122
148
  const detail = ref();
149
+ const taskData = ref(null);
123
150
 
124
151
  const todoType = ref(null);
125
152
  const userModal = ref(false);
126
- const drawerVisible = ref(false);
127
153
  const loading = ref(false);
128
154
  const users = ref([]);
129
155
 
156
+ const todoDrawerRef = ref(null);
130
157
  const approvalModalVisible = ref(false);
131
158
  const approvalData = reactive({
132
159
  id: '',
133
160
  refid: ''
134
161
  });
135
162
 
136
- /**
137
- * 显示详情
138
- * @param params
139
- */
163
+ /** refid前缀 */
164
+ const refidPrefix = computed(() => {
165
+ return props.data?.refid?.split('!')?.[0] + ':' || '';
166
+ });
167
+
168
+ /** 显示详情 */
140
169
  const show = (params = {}) => {
141
170
  emit('update:data', params);
142
171
  emit('update:modelValue', true);
@@ -147,35 +176,33 @@
147
176
  emit('update:modelValue', value);
148
177
  };
149
178
 
150
- /**
151
- * 打开抽屉
152
- */
179
+ /** 打开抽屉 */
153
180
  const open = async () => {
154
- emit('update:showOpera', false);
155
181
  const { id, refid } = props.data;
156
182
  if (id && refid) {
157
183
  await getDetail({ refid, id });
158
- // //获取可审批的任务
159
- SohelpHttp.get('/engine/web/workflow/getMyTask', { refid: refid, id: id }).then((res) => {
184
+ // 获取可审批的任务
185
+ SohelpHttp.get('/engine/web/workflow/getMyTask', {
186
+ refid,
187
+ id
188
+ }).then((res) => {
160
189
  if (res.meta.success) {
161
- emit('update:showOpera', res.data?.id !== '');
190
+ taskData.value = res.data;
191
+ showOpera.value = !!res.data?.id;
192
+ } else {
193
+ EleMessage.error(res.meta?.message);
162
194
  }
163
195
  });
164
196
  }
165
197
  };
166
198
 
167
- /**
168
- * 关闭抽屉
169
- */
199
+ /** 关闭抽屉 */
170
200
  const close = () => {
171
201
  active.value = 'form';
172
202
  emit('close');
173
203
  };
174
204
 
175
- /**
176
- * 获取详情
177
- * @param params
178
- */
205
+ /** 获取详情 */
179
206
  const getDetail = async (params) => {
180
207
  loading.value = true;
181
208
  const res = await getTodoDetail(params);
@@ -187,67 +214,61 @@
187
214
  }
188
215
  };
189
216
 
190
- /**
191
- * 更多操作按钮
192
- */
217
+ /** 更多操作按钮 */
193
218
  const getMore = computed(() => {
194
219
  const exclude = ['agree', 'reject', 'batchAgree', 'batchReject', 'submit'];
195
220
  return Object.entries(moreOption)
196
- .filter(([key]) => !exclude.includes(key) && permission.hasPermission(buttonAuth[key]))
197
- ?.map(([key, value]) => ({ title: value, command: key }));
221
+ .filter(
222
+ ([key]) =>
223
+ !exclude.includes(key) &&
224
+ permission.hasPermission(refidPrefix.value + buttonAuth[key])
225
+ )
226
+ .map(([command, title]) => ({ command, title }));
198
227
  });
199
228
 
200
- /**
201
- * 同意、拒绝弹窗
202
- * @param type
203
- */
229
+ /** 同意、拒绝弹窗 */
204
230
  const openModal = (type) => {
205
231
  todoType.value = type;
206
- const id = props.data.id;
207
232
  Object.assign(approvalData, {
208
- id: id,
233
+ id: props.data.id,
209
234
  refid: props.data.refid
210
235
  });
211
236
  approvalModalVisible.value = true;
212
237
  };
213
238
 
214
- /**
215
- * 选择用户弹窗
216
- */
239
+ /** 选择用户弹窗 */
217
240
  const openUserModal = () => {
218
241
  users.value = todoType.value === 'delegate' ? '' : [];
219
242
  };
220
243
 
221
- /**
222
- * 更多操作
223
- * @param type 类型
224
- * @param row
225
- */
244
+ /** 更多操作 */
226
245
  const onOperate = (type) => {
227
246
  todoType.value = type;
228
247
 
229
248
  // 委派、加签、减签
230
249
  if (['delegate', 'addSign', 'removeSign'].includes(type)) {
231
250
  userModal.value = true;
232
- return false;
251
+ return;
233
252
  }
234
253
 
235
- let data = {
236
- taskId: props.data.taskId
254
+ const data = {
255
+ id: props.data.id,
256
+ refid: props.data.refid
237
257
  };
258
+
238
259
  // 跳转
239
260
  if (type === 'jump') {
240
- data.nodeKey = props.data.nodeKey;
261
+ data.nodeKey = props.data?.nodeKey || '';
241
262
  }
242
263
 
243
264
  ElMessageBox.confirm(`确定要${moreOption[type]}吗?`, '系统提示', {
244
265
  type: 'danger',
245
266
  draggable: false
246
267
  })
247
- .then(async () => {
268
+ .then(() => {
248
269
  save(type, data);
249
270
  })
250
- .catch((e) => {});
271
+ .catch(() => {});
251
272
  };
252
273
 
253
274
  // 更新table
@@ -256,22 +277,16 @@
256
277
  emit('reload');
257
278
  };
258
279
 
259
- /**
260
- * 委派,加签,减签保存
261
- * @param type
262
- */
280
+ /** 委派,加签,减签保存 */
263
281
  const saveByUser = (type) => {
264
282
  save(type, {
265
283
  id: props.data.id,
284
+ refid: props.data.refid,
266
285
  [type === 'delegate' ? 'userId' : 'users']: users.value
267
286
  });
268
287
  };
269
288
 
270
- /**
271
- * 保存
272
- * @param type
273
- * @param data
274
- */
289
+ /** 保存 */
275
290
  const save = (type, data) => {
276
291
  loading.value = true;
277
292
  todoOperate(type, data)
@@ -279,7 +294,7 @@
279
294
  loading.value = false;
280
295
  EleMessage.success(msg);
281
296
  done();
282
- if (type == 'agree' || type == 'reject') {
297
+ if (type === 'agree' || type === 'reject') {
283
298
  todoDrawerRef.value?.closeModal();
284
299
  }
285
300
  if (['delegate', 'addSign', 'removeSign'].includes(type)) {
@@ -15,18 +15,18 @@ export const moreOption = {
15
15
  };
16
16
 
17
17
  export const buttonAuth = {
18
- agree: 'todo.wf.agree',
19
- reject: 'todo.wf.reject',
20
- submit: 'todo.wf.submit',
21
- reclaim: 'todo.wf.reclaim',
22
- delegate: 'todo.wf.delegate',
18
+ agree: 'workflow.agree',
19
+ reject: 'workflow.reject',
20
+ submit: 'workflow.submit',
21
+ reclaim: 'workflow.reclaim',
22
+ delegate: 'workflow.delegate',
23
23
  complete: 'todo.wf.complete',
24
- addSign: 'todo.wf.add-sign',
25
- removeSign: 'todo.wf.remove-sign',
26
- jump: 'todo.wf.jump',
27
- jumpPrevious: 'todo.wf.jump-previous',
28
- jumpFirst: 'todo.wf.jump-first'
29
- }
24
+ addSign: 'workflow.add-sign',
25
+ removeSign: 'workflow.remove-sign',
26
+ jump: 'workflow.jump',
27
+ jumpPrevious: 'workflow.jump-previous',
28
+ jumpFirst: 'workflow.jump-first'
29
+ };
30
30
 
31
31
  /**
32
32
  * 待办分页列表
@@ -74,7 +74,7 @@ export async function todoOperate(type, params) {
74
74
  * @returns
75
75
  */
76
76
  export async function getTodoDetail(params) {
77
- const res = await SohelpHttp.get(`/engine/web/crud/detail`, params);
77
+ const res = await SohelpHttp.get(`/engine/web/crud/getById`, params);
78
78
  if (res.meta.success) {
79
79
  return res.data;
80
80
  }
@@ -111,7 +111,9 @@ export async function getTasks(params) {
111
111
  * 已阅
112
112
  */
113
113
  export async function readByCc(taskId) {
114
- const res = await SohelpHttp.post(`/engine/web/workflow/readByCc`, { taskId });
114
+ const res = await SohelpHttp.post(`/engine/web/workflow/readByCc`, {
115
+ taskId
116
+ });
115
117
  if (res.meta.success) {
116
118
  return res.meta.message;
117
119
  }
File without changes
@@ -0,0 +1,89 @@
1
+ /**
2
+ * 安全的数学/条件表达式求值器
3
+ * 仅支持:数字运算(+-*​/%)、比较(> < >= <= === !== == !=)、逻辑(&& || !)、属性访问(row.field)、字符串
4
+ * 不支持:函数调用、赋值、new、import、require 等危险操作
5
+ */
6
+
7
+ // 白名单:只允许标识符、点号、数字、运算符、圆括号、单/双引号字符串、空白、逗号
8
+ // 不允许:方括号[]、反引号`、花括号{}、分号;、反斜杠\(阻止unicode转义)
9
+ const SAFE_EXPR_PATTERN = /^[\w\s.'"$+\-*/%()><=!&|?:,]+$/;
10
+ // 扩展危险关键字检测,涵盖更多绕过手段
11
+ const DANGEROUS_KEYWORDS = /\b(import|require|eval|Function|constructor|prototype|__proto__|window|document|globalThis|process|fetch|XMLHttpRequest|setTimeout|setInterval|alert|confirm|prompt|atob|btoa|escape|unescape|decodeURI|encodeURI|decodeURIComponent|encodeURIComponent|this|self|top|parent|frames|location|navigator|history|screen|chrome|Proxy|Reflect|Symbol|Object|Array|String|Number|Boolean|RegExp|Date|Math|JSON|Promise|Error)\b/;
12
+ // handler 代码的危险关键字(比表达式宽松一些,允许常见的安全对象如 Math/JSON/Array 等)
13
+ const DANGEROUS_CODE_KEYWORDS = /\b(import|require|eval|Function|constructor|prototype|__proto__|window|document|globalThis|process|fetch|XMLHttpRequest|setTimeout|setInterval|alert|confirm|prompt|Proxy|Reflect|self|top|parent|frames|location|navigator|history|screen|chrome)\b/;
14
+ // 检测不安全的字符序列:方括号(属性访问绕过)、反引号(模板字符串)、unicode转义
15
+ const UNSAFE_SEQUENCES = /[\[\]`\\]/;
16
+
17
+ export function isSafeExpression(expr) {
18
+ if (!expr || typeof expr !== 'string') return false;
19
+ // 检测不安全字符序列(方括号、反引号、反斜杠)
20
+ if (UNSAFE_SEQUENCES.test(expr)) return false;
21
+ if (!SAFE_EXPR_PATTERN.test(expr)) return false;
22
+ if (DANGEROUS_KEYWORDS.test(expr)) return false;
23
+ return true;
24
+ }
25
+
26
+ function isSafeCode(code) {
27
+ if (!code || typeof code !== 'string') return false;
28
+ if (DANGEROUS_CODE_KEYWORDS.test(code)) return false;
29
+ // 在 handler 代码中也禁止 unicode 转义和反引号(防止关键字重构绕过)
30
+ if (/\\u[0-9a-fA-F]{4}/.test(code)) return false;
31
+ if (/`/.test(code)) return false;
32
+ return true;
33
+ }
34
+
35
+ /**
36
+ * 安全求值简单表达式(公式计算、条件判断)
37
+ * @param {string} expr - 表达式字符串,如 "row.price * row.qty"
38
+ * @param {Object} context - 上下文变量,如 { row: { price: 10, qty: 2 } }
39
+ * @returns {*} 计算结果
40
+ * @throws {Error} 如果表达式不安全
41
+ */
42
+ export function safeEval(expr, context = {}) {
43
+ if (!isSafeExpression(expr)) {
44
+ throw new Error(`不安全的表达式: ${expr}`);
45
+ }
46
+ const keys = Object.keys(context);
47
+ const values = Object.values(context);
48
+ try {
49
+ const func = new Function(...keys, `"use strict"; return (${expr})`);
50
+ return func(...values);
51
+ } catch (e) {
52
+ throw new Error(`表达式执行错误: ${expr} - ${e.message}`);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * 安全执行服务端配置的 handler 代码(带沙箱限制,异步)
58
+ * 仅允许访问白名单中的上下文变量
59
+ * @param {string} code - 代码字符串
60
+ * @param {string[]} paramNames - 参数名数组
61
+ * @param {*[]} contextValues - 参数值数组
62
+ * @param {Object} [thisArg] - 可选的 this 上下文
63
+ */
64
+ export function safeFunctionExec(code, paramNames, contextValues, thisArg) {
65
+ if (!code || typeof code !== 'string') return;
66
+ if (!isSafeCode(code)) {
67
+ console.warn('[安全警告] handler 代码包含危险关键字或不安全序列,已拦截:', code.substring(0, 100));
68
+ return;
69
+ }
70
+ const func = new Function(...paramNames, `"use strict"; return (async () => { ${code} })()`);
71
+ return thisArg ? func.call(thisArg, ...contextValues) : func(...contextValues);
72
+ }
73
+
74
+ /**
75
+ * 安全执行服务端配置的代码(带沙箱限制,同步)
76
+ * @param {string} code - 代码字符串
77
+ * @param {string[]} paramNames - 参数名数组
78
+ * @param {*[]} contextValues - 参数值数组
79
+ * @param {Object} [thisArg] - 可选的 this 上下文
80
+ */
81
+ export function safeFunctionExecSync(code, paramNames, contextValues, thisArg) {
82
+ if (!code || typeof code !== 'string') return;
83
+ if (!isSafeCode(code)) {
84
+ console.warn('[安全警告] handler 代码包含危险关键字或不安全序列,已拦截:', code.substring(0, 100));
85
+ return;
86
+ }
87
+ const func = new Function(...paramNames, `"use strict"; return (() => { ${code} })()`);
88
+ return thisArg ? func.call(thisArg, ...contextValues) : func(...contextValues);
89
+ }
@@ -1,67 +0,0 @@
1
- /**
2
- * 属性
3
- */
4
- export const prop = {
5
- url: {
6
- type: String,
7
- required: true
8
- },
9
-
10
- mappingFields: {
11
- type: Object,
12
- default: () => {
13
- return {
14
- label: 'label',
15
- value: 'value'
16
- };
17
- }
18
- },
19
-
20
- width: {
21
- type: String,
22
- default: '200px'
23
- },
24
-
25
- placeholder: {
26
- type: String,
27
- default: '请选择'
28
- },
29
-
30
- modelValue: {
31
- type: Array || String || Number,
32
- required: true
33
- },
34
- filterable: {
35
- type: Boolean,
36
- default: true
37
- },
38
- clearable: {
39
- type: Boolean,
40
- default: true
41
- },
42
- disabled: {
43
- type: Boolean,
44
- default: false
45
- },
46
- size: {
47
- type: String,
48
- validator: function (value) {
49
- return ['large', 'default', 'small', ''].includes(value);
50
- },
51
- default: 'default'
52
- },
53
- multiple: {
54
- type: Boolean,
55
- default: false
56
- },
57
- type: {
58
- type: String,
59
- default: 'select'
60
- }
61
- };
62
-
63
- /**
64
- * 事件
65
- */
66
-
67
- export const emit = ['update:modelValue', 'change'];
@@ -1,53 +0,0 @@
1
- <template>
2
- <div class="sohelp-user-select">
3
- <sohelp-dyn-select
4
- v-bind="$attrs"
5
- :url="url"
6
- :labelField="labelField"
7
- :valueField="valueField"
8
- :readonly="readonly"
9
- :datasource="datasource"
10
- v-model="modelValue"
11
- ></sohelp-dyn-select>
12
- </div>
13
- </template>
14
- <script setup>
15
- import SohelpDynSelect from "../sohelp-dyn-select/index.vue";
16
-
17
- const modelValue = defineModel("modelValue", { type: [String, Number, Array], default: "" });
18
-
19
- const props = defineProps({
20
- datasource: {
21
- type: [Array, Function, Promise],
22
- required: true
23
- },
24
- url: {
25
- type: String,
26
- default: "/engine/web/user/list"
27
- },
28
- labelField: {
29
- type: String,
30
- default: "user_name"
31
- },
32
- valueField: {
33
- type: String,
34
- default: "id"
35
- },
36
- readonly: {
37
- type: Boolean,
38
- default: false
39
- }
40
- });
41
- console.error(exposedMethods)
42
- // 暴露子组件特有方法
43
- defineExpose({
44
- ...exposedMethods
45
- })
46
-
47
- </script>
48
- <script>
49
- export default {
50
- name: "SohelpUserSelect"
51
- };
52
- </script>
53
- <style></style>