t20-common-lib 0.10.9 → 0.11.0
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
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<DraggableFab
|
|
4
4
|
v-if="showConfigBtn"
|
|
5
5
|
title="配置显示列"
|
|
6
|
-
@click="
|
|
6
|
+
@click="showColumnConfig"
|
|
7
7
|
/>
|
|
8
8
|
|
|
9
9
|
<div v-for="panel in panels" :key="panel.key">
|
|
@@ -37,16 +37,28 @@
|
|
|
37
37
|
</template>
|
|
38
38
|
</N20-expandable-pane>
|
|
39
39
|
</div>
|
|
40
|
+
<DynamicDescriptionsConfig
|
|
41
|
+
ref="showColumn"
|
|
42
|
+
:dialogVisible.sync="showColumnVisible"
|
|
43
|
+
:check-columns="checkedColumns"
|
|
44
|
+
:columns="allColumns"
|
|
45
|
+
:columns-groups="columnGroups"
|
|
46
|
+
:auto-save="!!pageId"
|
|
47
|
+
:page-id="pageId"
|
|
48
|
+
@setColumns="handleSetColumns"
|
|
49
|
+
/>
|
|
40
50
|
</div>
|
|
41
51
|
</template>
|
|
42
52
|
|
|
43
53
|
<script>
|
|
44
54
|
import DraggableFab from '../../draggable-fab/src/main.vue'
|
|
55
|
+
import DynamicDescriptionsConfig from '../../dynamic-descriptions-config/src/main.vue'
|
|
45
56
|
|
|
46
57
|
export default {
|
|
47
58
|
name: 'DynamicDescriptions',
|
|
48
59
|
components: {
|
|
49
|
-
DraggableFab
|
|
60
|
+
DraggableFab,
|
|
61
|
+
DynamicDescriptionsConfig
|
|
50
62
|
},
|
|
51
63
|
props: {
|
|
52
64
|
panels: {
|
|
@@ -60,6 +72,98 @@ export default {
|
|
|
60
72
|
showConfigBtn: {
|
|
61
73
|
type: Boolean,
|
|
62
74
|
default: true
|
|
75
|
+
},
|
|
76
|
+
pageId: {
|
|
77
|
+
type: String,
|
|
78
|
+
default: ''
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
data() {
|
|
82
|
+
return {
|
|
83
|
+
showColumnVisible: false,
|
|
84
|
+
checkedColumns: []
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
created() {
|
|
88
|
+
this.checkedColumns = this.allColumns || []
|
|
89
|
+
},
|
|
90
|
+
mounted() {
|
|
91
|
+
if (this.pageId) {
|
|
92
|
+
this.getColumns()
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
computed: {
|
|
96
|
+
columnGroups() {
|
|
97
|
+
return this.panels.map(p => ({
|
|
98
|
+
groupId: p.key,
|
|
99
|
+
groupName: p.title,
|
|
100
|
+
type: p.type
|
|
101
|
+
}))
|
|
102
|
+
},
|
|
103
|
+
allColumns() {
|
|
104
|
+
let cols = []
|
|
105
|
+
this.panels.forEach(panel => {
|
|
106
|
+
const items = panel.fields || panel.columns || []
|
|
107
|
+
items.forEach(item => {
|
|
108
|
+
let isVisible = true
|
|
109
|
+
if (typeof item.visible === 'function') {
|
|
110
|
+
isVisible = item.visible(this.formData)
|
|
111
|
+
} else if (typeof item.visible === 'boolean') {
|
|
112
|
+
isVisible = item.visible
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (isVisible) {
|
|
116
|
+
cols.push({
|
|
117
|
+
...item,
|
|
118
|
+
groupId: panel.key,
|
|
119
|
+
sourceGroup: panel.key,
|
|
120
|
+
configLabel: item.label
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
return cols
|
|
126
|
+
},
|
|
127
|
+
processedFormData() {
|
|
128
|
+
const newFormData = JSON.parse(JSON.stringify(this.formData))
|
|
129
|
+
|
|
130
|
+
// Ensure target groups exist in newFormData for object types
|
|
131
|
+
this.displayPanels.forEach(p => {
|
|
132
|
+
if (p.type === 'object' && !newFormData[p.key]) {
|
|
133
|
+
newFormData[p.key] = {}
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
this.checkedColumns.forEach(col => {
|
|
138
|
+
// Only handle object fields that have moved to a different group
|
|
139
|
+
if (col.sourceGroup && col.groupId && col.sourceGroup !== col.groupId) {
|
|
140
|
+
// We assume sourceGroup refers to a key in formData
|
|
141
|
+
if (this.formData[col.sourceGroup]) {
|
|
142
|
+
const val = this.formData[col.sourceGroup][col.prop]
|
|
143
|
+
// Assign to the new location so the component can find it
|
|
144
|
+
if (newFormData[col.groupId]) {
|
|
145
|
+
newFormData[col.groupId][col.prop] = val
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
return newFormData
|
|
152
|
+
},
|
|
153
|
+
displayPanels() {
|
|
154
|
+
return this.panels.map(panel => {
|
|
155
|
+
const panelItems = this.checkedColumns.filter(col => col.groupId === panel.key)
|
|
156
|
+
|
|
157
|
+
if (panelItems.length === 0) return null
|
|
158
|
+
|
|
159
|
+
const newPanel = { ...panel }
|
|
160
|
+
if (panel.type === 'object') {
|
|
161
|
+
newPanel.fields = panelItems
|
|
162
|
+
} else {
|
|
163
|
+
newPanel.columns = panelItems
|
|
164
|
+
}
|
|
165
|
+
return newPanel
|
|
166
|
+
}).filter(p => p !== null)
|
|
63
167
|
}
|
|
64
168
|
},
|
|
65
169
|
methods: {
|
|
@@ -215,6 +319,24 @@ export default {
|
|
|
215
319
|
window.removeEventListener('mousemove', this.onDrag)
|
|
216
320
|
window.removeEventListener('mouseup', this.stopDrag)
|
|
217
321
|
},
|
|
322
|
+
getColumns() {
|
|
323
|
+
this.$refs.showColumn.getColumns().then((list) => {
|
|
324
|
+
if (list && list.length > 0) {
|
|
325
|
+
this.checkedColumns = list
|
|
326
|
+
} else {
|
|
327
|
+
this.checkedColumns = this.allColumns
|
|
328
|
+
}
|
|
329
|
+
})
|
|
330
|
+
},
|
|
331
|
+
showColumnConfig() {
|
|
332
|
+
if (!this.checkedColumns || this.checkedColumns.length === 0) {
|
|
333
|
+
this.checkedColumns = [...this.allColumns]
|
|
334
|
+
}
|
|
335
|
+
this.showColumnVisible = true
|
|
336
|
+
},
|
|
337
|
+
handleSetColumns(newColumns) {
|
|
338
|
+
this.checkedColumns = newColumns
|
|
339
|
+
}
|
|
218
340
|
}
|
|
219
341
|
}
|
|
220
342
|
</script>
|
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-dialog
|
|
3
|
+
:visible.sync="visible"
|
|
4
|
+
:title="title"
|
|
5
|
+
width="900px"
|
|
6
|
+
:close-on-click-modal="false"
|
|
7
|
+
append-to-body
|
|
8
|
+
custom-class="local-show-column-dialog"
|
|
9
|
+
>
|
|
10
|
+
<div class="dialog-content">
|
|
11
|
+
<!-- Left Side: Checkboxes -->
|
|
12
|
+
<div class="left-panel">
|
|
13
|
+
<div class="panel-header">
|
|
14
|
+
<span>可选字段</span>
|
|
15
|
+
<el-link type="primary" :underline="false" @click="selectAll" class="header-action">全选</el-link>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="panel-body">
|
|
18
|
+
<div v-for="group in columnsGroups" :key="group.groupId" class="group-section">
|
|
19
|
+
<div class="group-title">{{ group.groupName }}</div>
|
|
20
|
+
<div class="group-items">
|
|
21
|
+
<el-checkbox
|
|
22
|
+
v-for="col in getGroupColumns(group.groupId)"
|
|
23
|
+
:key="col.prop"
|
|
24
|
+
:label="col.label"
|
|
25
|
+
:value="isChecked(col)"
|
|
26
|
+
@change="(val) => handleCheckChange(val, col)"
|
|
27
|
+
>
|
|
28
|
+
{{ col.label }}
|
|
29
|
+
</el-checkbox>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<!-- Right Side: Draggable Hierarchy -->
|
|
36
|
+
<div class="right-panel">
|
|
37
|
+
<div class="panel-header">
|
|
38
|
+
<span>当前选定项 (可拖拽排序)</span>
|
|
39
|
+
<el-link type="primary" :underline="false" @click="clearAll" class="header-action">清空</el-link>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="panel-body">
|
|
42
|
+
<div v-for="group in localGroups" :key="group.groupId" class="drag-group-section">
|
|
43
|
+
<div class="group-title-bar">
|
|
44
|
+
<span class="font-bold">{{ group.groupName }}</span>
|
|
45
|
+
<span class="count-badge">{{ group.children.length }}</span>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<draggable
|
|
49
|
+
v-model="group.children"
|
|
50
|
+
:group="getDragGroup(group)"
|
|
51
|
+
animation="200"
|
|
52
|
+
class="drag-area"
|
|
53
|
+
ghost-class="ghost"
|
|
54
|
+
>
|
|
55
|
+
<div v-for="element in group.children" :key="element.prop" class="drag-item">
|
|
56
|
+
<div class="item-content">
|
|
57
|
+
<i class="el-icon-rank drag-handle"></i>
|
|
58
|
+
<span class="item-label" :title="element.label">{{ element.configLabel || element.label }}</span>
|
|
59
|
+
</div>
|
|
60
|
+
<i class="el-icon-close close-btn" @click="removeColumn(element)"></i>
|
|
61
|
+
</div>
|
|
62
|
+
</draggable>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<span slot="footer" class="dialog-footer">
|
|
69
|
+
<el-button @click="visible = false">取 消</el-button>
|
|
70
|
+
<el-button type="primary" @click="confirm">确 定</el-button>
|
|
71
|
+
</span>
|
|
72
|
+
</el-dialog>
|
|
73
|
+
</template>
|
|
74
|
+
|
|
75
|
+
<script>
|
|
76
|
+
import draggable from 'vuedraggable'
|
|
77
|
+
import request from '@/utils/request'
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
export default {
|
|
81
|
+
name: 'DynamicDescriptionsConfig',
|
|
82
|
+
components: { draggable },
|
|
83
|
+
props: {
|
|
84
|
+
dialogVisible: Boolean,
|
|
85
|
+
title: { type: String, default: '配置显示列' },
|
|
86
|
+
columns: { type: Array, default: () => [] },
|
|
87
|
+
checkColumns: { type: Array, default: () => [] },
|
|
88
|
+
columnsGroups: { type: Array, default: () => [] },
|
|
89
|
+
pageId: { type: String, default: undefined },
|
|
90
|
+
autoSave: { type: Boolean, default: false },
|
|
91
|
+
labelKey: { type: String, default: 'label' },
|
|
92
|
+
isFilter: { type: Boolean, default: false },
|
|
93
|
+
isExport: { type: Boolean, default: false }
|
|
94
|
+
},
|
|
95
|
+
data() {
|
|
96
|
+
return {
|
|
97
|
+
localGroups: [],
|
|
98
|
+
userNo: sessionStorage.getItem('userNo')
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
computed: {
|
|
102
|
+
visible: {
|
|
103
|
+
get() { return this.dialogVisible },
|
|
104
|
+
set(val) { this.$emit('update:dialogVisible', val) }
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
watch: {
|
|
108
|
+
dialogVisible(val) {
|
|
109
|
+
if (val) {
|
|
110
|
+
this.init()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
methods: {
|
|
115
|
+
init() {
|
|
116
|
+
// Initialize local structure
|
|
117
|
+
this.localGroups = this.columnsGroups.map(g => ({
|
|
118
|
+
...g,
|
|
119
|
+
children: []
|
|
120
|
+
}))
|
|
121
|
+
|
|
122
|
+
// Populate with checkColumns based on their CURRENT groupId (or original if matching)
|
|
123
|
+
// Note: checkColumns may contain items with updated groupIds from previous drags
|
|
124
|
+
this.checkColumns.forEach(col => {
|
|
125
|
+
// Try to find the group this column currently claims to belong to
|
|
126
|
+
let group = this.localGroups.find(g => g.groupId === col.groupId)
|
|
127
|
+
|
|
128
|
+
// If not found (rare, or config changed), fallback to original define in 'columns'
|
|
129
|
+
if (!group) {
|
|
130
|
+
const originalDef = this.columns.find(c => c.prop === col.prop)
|
|
131
|
+
if (originalDef) {
|
|
132
|
+
group = this.localGroups.find(g => g.groupId === originalDef.groupId)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (group) {
|
|
137
|
+
group.children.push({ ...col })
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
},
|
|
141
|
+
getGroupColumns(groupId) {
|
|
142
|
+
return this.columns.filter(c => c.groupId === groupId)
|
|
143
|
+
},
|
|
144
|
+
isChecked(col) {
|
|
145
|
+
for (const group of this.localGroups) {
|
|
146
|
+
if (group.children.some(child => child.prop === col.prop)) return true
|
|
147
|
+
}
|
|
148
|
+
return false
|
|
149
|
+
},
|
|
150
|
+
handleCheckChange(val, col) {
|
|
151
|
+
if (val) {
|
|
152
|
+
// Find original group to add to
|
|
153
|
+
const targetGroup = this.localGroups.find(g => g.groupId === col.groupId)
|
|
154
|
+
if (targetGroup) {
|
|
155
|
+
targetGroup.children.push({ ...col })
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
// Remove from wherever it is
|
|
159
|
+
for (const group of this.localGroups) {
|
|
160
|
+
const idx = group.children.findIndex(child => child.prop === col.prop)
|
|
161
|
+
if (idx !== -1) {
|
|
162
|
+
group.children.splice(idx, 1)
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
removeColumn(col) {
|
|
169
|
+
this.handleCheckChange(false, col)
|
|
170
|
+
},
|
|
171
|
+
getDragGroup(group) {
|
|
172
|
+
// Object groups share the 'object-groups' name allowing transfer
|
|
173
|
+
// Array groups are isolated with unique names
|
|
174
|
+
if (group.type === 'object') {
|
|
175
|
+
return 'object-groups'
|
|
176
|
+
}
|
|
177
|
+
return 'group-' + group.groupId
|
|
178
|
+
},
|
|
179
|
+
selectAll() {
|
|
180
|
+
this.localGroups.forEach(g => g.children = [])
|
|
181
|
+
this.columns.forEach(col => {
|
|
182
|
+
const group = this.localGroups.find(g => g.groupId === col.groupId)
|
|
183
|
+
if(group) group.children.push({...col})
|
|
184
|
+
})
|
|
185
|
+
},
|
|
186
|
+
clearAll() {
|
|
187
|
+
this.localGroups.forEach(g => g.children = [])
|
|
188
|
+
},
|
|
189
|
+
confirm() {
|
|
190
|
+
const result = []
|
|
191
|
+
this.localGroups.forEach(group => {
|
|
192
|
+
group.children.forEach(child => {
|
|
193
|
+
// Update groupId to reflect the current group
|
|
194
|
+
result.push({
|
|
195
|
+
...child,
|
|
196
|
+
groupId: group.groupId
|
|
197
|
+
})
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
if (!this.isExport && this.autoSave) {
|
|
202
|
+
this.saveColumns(result)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
this.$emit('setColumns', result)
|
|
206
|
+
this.visible = false
|
|
207
|
+
},
|
|
208
|
+
saveColumns(list) {
|
|
209
|
+
let columns = saveTransform(list, this.labelKey, this.isFilter)
|
|
210
|
+
request({
|
|
211
|
+
url: '/bems/prod_1.0/user/pageHabit',
|
|
212
|
+
method: 'post',
|
|
213
|
+
data: {
|
|
214
|
+
userNo: this.userNo,
|
|
215
|
+
pageId: this.pageId,
|
|
216
|
+
showStructure: JSON.stringify(columns)
|
|
217
|
+
},
|
|
218
|
+
loading: false
|
|
219
|
+
})
|
|
220
|
+
},
|
|
221
|
+
getColumns(pageId) {
|
|
222
|
+
return getColumns(pageId || this.pageId, this.userNo, this.columns, this.labelKey)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function saveTransform(list, labelKey, isFilter) {
|
|
228
|
+
let listN = []
|
|
229
|
+
if (!isFilter) {
|
|
230
|
+
list.forEach((c) => {
|
|
231
|
+
const extra = c.groupId ? { groupId: c.groupId } : {}
|
|
232
|
+
if (c.prop && !c.children && !c.isNew && !c.width) {
|
|
233
|
+
listN.push({ _colKey: 'prop', _colVal: c.prop, ...extra })
|
|
234
|
+
} else if (c.type && ['selection', 'index', 'expand'].includes(c.type)) {
|
|
235
|
+
listN.push({ _colKey: 'type', _colVal: c.type, ...extra })
|
|
236
|
+
} else {
|
|
237
|
+
let sFn = false
|
|
238
|
+
for (let k in c) {
|
|
239
|
+
if (typeof c[k] === 'function') sFn = true
|
|
240
|
+
}
|
|
241
|
+
if (sFn && c[labelKey]) {
|
|
242
|
+
listN.push({ _colKey: labelKey, _colVal: c[labelKey], ...extra })
|
|
243
|
+
} else {
|
|
244
|
+
listN.push(c)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
} else {
|
|
249
|
+
list.forEach((c) => {
|
|
250
|
+
if (c.value) {
|
|
251
|
+
listN.push({ _colKey: 'value', _colVal: c.value })
|
|
252
|
+
} else if (c.startValue) {
|
|
253
|
+
listN.push({ _colKey: 'startValue', _colVal: c.startValue })
|
|
254
|
+
} else if (c.startDate) {
|
|
255
|
+
listN.push({ _colKey: 'startDate', _colVal: c.startDate })
|
|
256
|
+
} else {
|
|
257
|
+
listN.push(c)
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
return listN
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function getTransform(list, columnsT, labelKey = 'label') {
|
|
265
|
+
let columns = []
|
|
266
|
+
list.forEach((d) => {
|
|
267
|
+
if (typeof d === 'string') {
|
|
268
|
+
let column = columnsT.find((c) => c[labelKey] === d)
|
|
269
|
+
column && columns.push(column)
|
|
270
|
+
} else if (typeof d === 'object') {
|
|
271
|
+
if (d._colKey) {
|
|
272
|
+
let column = columnsT.find((c) => c[d._colKey] === d._colVal)
|
|
273
|
+
if (column) {
|
|
274
|
+
let newCol = { ...column }
|
|
275
|
+
if (d.groupId) {
|
|
276
|
+
newCol.groupId = d.groupId
|
|
277
|
+
}
|
|
278
|
+
columns.push(newCol)
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
columns.push(d)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
return columns
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function getColumns(pageId, userNo, columnsT, labelKey = 'label') {
|
|
289
|
+
return new Promise((resolve, reject) => {
|
|
290
|
+
request({
|
|
291
|
+
url: '/bems/prod_1.0/user/pageHabit/list',
|
|
292
|
+
method: 'post',
|
|
293
|
+
data: {
|
|
294
|
+
userNo: userNo,
|
|
295
|
+
pageId: pageId
|
|
296
|
+
},
|
|
297
|
+
loading: false
|
|
298
|
+
})
|
|
299
|
+
.then((res) => {
|
|
300
|
+
const data = res.data || res
|
|
301
|
+
if (data) {
|
|
302
|
+
let _data = data
|
|
303
|
+
if (typeof data === 'string') {
|
|
304
|
+
try {
|
|
305
|
+
_data = JSON.parse(data)
|
|
306
|
+
} catch(e) { console.error(e) }
|
|
307
|
+
}
|
|
308
|
+
if (_data && _data.length > 0) {
|
|
309
|
+
let columns = getTransform(_data, columnsT, labelKey)
|
|
310
|
+
return resolve(columns)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return resolve(null)
|
|
314
|
+
})
|
|
315
|
+
.catch((err) => {
|
|
316
|
+
reject(err)
|
|
317
|
+
})
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
</script>
|
|
321
|
+
|
|
322
|
+
<style scoped lang="scss">
|
|
323
|
+
.dialog-content {
|
|
324
|
+
display: flex;
|
|
325
|
+
height: 500px;
|
|
326
|
+
border: 1px solid #dcdfe6;
|
|
327
|
+
border-radius: 4px;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.left-panel, .right-panel {
|
|
331
|
+
flex: 1;
|
|
332
|
+
display: flex;
|
|
333
|
+
flex-direction: column;
|
|
334
|
+
overflow: hidden;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.left-panel {
|
|
338
|
+
border-right: 1px solid #dcdfe6;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.panel-header {
|
|
342
|
+
padding: 10px 15px;
|
|
343
|
+
background-color: #f5f7fa;
|
|
344
|
+
border-bottom: 1px solid #ebeef5;
|
|
345
|
+
font-weight: bold;
|
|
346
|
+
display: flex;
|
|
347
|
+
justify-content: space-between;
|
|
348
|
+
align-items: center;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.panel-body {
|
|
352
|
+
flex: 1;
|
|
353
|
+
overflow-y: auto;
|
|
354
|
+
padding: 10px;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.header-action {
|
|
358
|
+
font-size: 12px;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.group-section {
|
|
362
|
+
margin-bottom: 15px;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.group-title {
|
|
366
|
+
font-weight: bold;
|
|
367
|
+
margin-bottom: 8px;
|
|
368
|
+
color: #303133;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.group-items {
|
|
372
|
+
display: flex;
|
|
373
|
+
flex-direction: column;
|
|
374
|
+
.el-checkbox {
|
|
375
|
+
margin-left: 0 !important;
|
|
376
|
+
margin-bottom: 5px;
|
|
377
|
+
margin-right: 0;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.drag-group-section {
|
|
382
|
+
margin-bottom: 15px;
|
|
383
|
+
border: 1px dashed #e4e7ed;
|
|
384
|
+
border-radius: 4px;
|
|
385
|
+
padding: 5px;
|
|
386
|
+
|
|
387
|
+
&:hover {
|
|
388
|
+
border-color: #409EFF;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
.group-title-bar {
|
|
393
|
+
display: flex;
|
|
394
|
+
justify-content: space-between;
|
|
395
|
+
padding: 5px 10px;
|
|
396
|
+
background: #fafafa;
|
|
397
|
+
margin-bottom: 5px;
|
|
398
|
+
border-radius: 2px;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.font-bold {
|
|
402
|
+
font-weight: 600;
|
|
403
|
+
color: #606266;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.count-badge {
|
|
407
|
+
color: #909399;
|
|
408
|
+
font-size: 12px;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.drag-area {
|
|
412
|
+
min-height: 40px;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.drag-item {
|
|
416
|
+
display: flex;
|
|
417
|
+
align-items: center;
|
|
418
|
+
justify-content: space-between;
|
|
419
|
+
padding: 6px 10px;
|
|
420
|
+
background-color: #fff;
|
|
421
|
+
border: 1px solid #ebeef5;
|
|
422
|
+
margin-bottom: 4px;
|
|
423
|
+
border-radius: 4px;
|
|
424
|
+
cursor: move;
|
|
425
|
+
transition: all 0.2s;
|
|
426
|
+
|
|
427
|
+
&:hover {
|
|
428
|
+
border-color: #c6e2ff;
|
|
429
|
+
background-color: #ecf5ff;
|
|
430
|
+
|
|
431
|
+
.close-btn {
|
|
432
|
+
opacity: 1;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.item-content {
|
|
438
|
+
display: flex;
|
|
439
|
+
align-items: center;
|
|
440
|
+
overflow: hidden;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.drag-handle {
|
|
444
|
+
color: #909399;
|
|
445
|
+
margin-right: 8px;
|
|
446
|
+
cursor: move;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.item-label {
|
|
450
|
+
font-size: 13px;
|
|
451
|
+
color: #606266;
|
|
452
|
+
white-space: nowrap;
|
|
453
|
+
overflow: hidden;
|
|
454
|
+
text-overflow: ellipsis;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.close-btn {
|
|
458
|
+
color: #f56c6c;
|
|
459
|
+
cursor: pointer;
|
|
460
|
+
opacity: 0;
|
|
461
|
+
transition: opacity 0.2s;
|
|
462
|
+
padding: 2px;
|
|
463
|
+
|
|
464
|
+
&:hover {
|
|
465
|
+
background-color: #fef0f0;
|
|
466
|
+
border-radius: 50%;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.ghost {
|
|
471
|
+
opacity: 0.5;
|
|
472
|
+
background: #c8ebfb;
|
|
473
|
+
}
|
|
474
|
+
</style>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import { Message } from 'element-ui'
|
|
3
|
+
function randomString(num) {
|
|
4
|
+
num = num || 32
|
|
5
|
+
var t = ''
|
|
6
|
+
t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
|
|
7
|
+
|
|
8
|
+
const a = t.length
|
|
9
|
+
let n = ''
|
|
10
|
+
for (let i = 0; i < num; i++) n += t.charAt(Math.floor(Math.random() * a))
|
|
11
|
+
return n
|
|
12
|
+
}
|
|
13
|
+
// 创建 axios 实例
|
|
14
|
+
const service = axios.create({
|
|
15
|
+
baseURL: '/',
|
|
16
|
+
timeout: 10000 // 设置请求超时时间
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// 请求拦截器
|
|
20
|
+
service.interceptors.request.use(
|
|
21
|
+
config => {
|
|
22
|
+
// 可在此处添加认证头,例如 Token
|
|
23
|
+
const token = sessionStorage.getItem('token')
|
|
24
|
+
if (token) {
|
|
25
|
+
config.headers = {
|
|
26
|
+
Authorization: `Bearer ${token}`,
|
|
27
|
+
charset: 'utf-8',
|
|
28
|
+
lang: 'zh_CN',
|
|
29
|
+
timestamp: Date.now(),
|
|
30
|
+
requestKey: randomString(16),
|
|
31
|
+
OperationDesc: 'yYarJp'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
return config
|
|
36
|
+
},
|
|
37
|
+
error => {
|
|
38
|
+
// 对请求错误做些什么
|
|
39
|
+
console.error('Request Error:', error) // for debug
|
|
40
|
+
return Promise.reject(error)
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
// 响应拦截器
|
|
45
|
+
service.interceptors.response.use(
|
|
46
|
+
/**
|
|
47
|
+
* 如果您想获取诸如 http 头或状态之类的 http 信息
|
|
48
|
+
* 请返回 response => response
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 通过自定义代码确定请求状态
|
|
53
|
+
* 这里只是一个例子
|
|
54
|
+
* 您也可以通过 HTTP 状态码来判断状态
|
|
55
|
+
*/
|
|
56
|
+
response => {
|
|
57
|
+
const res = response.data
|
|
58
|
+
|
|
59
|
+
// 后端自定义的成功码不为 200 或 0,则判定为错误。
|
|
60
|
+
if (res.code !== 200 && res.code !== 0) {
|
|
61
|
+
Message({
|
|
62
|
+
message: res.msg || 'Error',
|
|
63
|
+
type: 'error',
|
|
64
|
+
duration: 5 * 1000
|
|
65
|
+
})
|
|
66
|
+
return Promise.reject(new Error(res.msg || 'Error'))
|
|
67
|
+
} else {
|
|
68
|
+
// 成功则直接返回数据
|
|
69
|
+
return res
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
error => {
|
|
73
|
+
// 处理 HTTP 网络错误
|
|
74
|
+
console.error('Response Error:', error) // for debug
|
|
75
|
+
Message({
|
|
76
|
+
message: error.message,
|
|
77
|
+
type: 'error',
|
|
78
|
+
duration: 5 * 1000
|
|
79
|
+
})
|
|
80
|
+
return Promise.reject(error)
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
export default service
|