appsnbcbweicheng 1.2.25 → 1.2.27
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/Calendar.vue +679 -0
- package/readme.md +2 -0
- package/public/AssetClassConfiguration.vue +0 -578
- package/public/EventInterpretation.vue +0 -1067
- package/public/FundInterpretation.vue +0 -765
- package/public/FundManagerInterpretation.vue +0 -759
- package/public/InstitutionViewpoint.vue +0 -731
- package/public/InstitutionViewpointCreate.vue +0 -612
- package/public/MonthlyAssetSectorEventInterpretation.vue +0 -637
- package/public/SectorAnalysisViewpointSummary.vue +0 -731
- package/public/SectorAnalysisViewpointSummaryCreate.vue +0 -612
- package/public/ShelfRules.vue +0 -400
|
@@ -1,578 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<el-dialog
|
|
3
|
-
title="资产板块列表"
|
|
4
|
-
:visible.sync="dialogVisible"
|
|
5
|
-
width="900px"
|
|
6
|
-
:close-on-click-modal="false"
|
|
7
|
-
append-to-body
|
|
8
|
-
custom-class="asset-config-dialog"
|
|
9
|
-
>
|
|
10
|
-
<div class="asset-config-container">
|
|
11
|
-
<!-- Left Panel: Asset Classes -->
|
|
12
|
-
<div class="left-panel">
|
|
13
|
-
<div class="panel-header">
|
|
14
|
-
<el-button type="primary" size="small" icon="el-icon-plus" @click="addAssetClass">
|
|
15
|
-
新增资产类别
|
|
16
|
-
</el-button>
|
|
17
|
-
</div>
|
|
18
|
-
<div class="asset-list" @dragover.prevent>
|
|
19
|
-
<div
|
|
20
|
-
v-for="(item, index) in localAssetClasses"
|
|
21
|
-
:key="item.tempId || item.id"
|
|
22
|
-
class="asset-item"
|
|
23
|
-
:class="{ active: selectedAssetId === (item.tempId || item.id) }"
|
|
24
|
-
draggable="true"
|
|
25
|
-
@dragstart="onDragStart($event, index)"
|
|
26
|
-
@dragover="onDragOver($event, index)"
|
|
27
|
-
@drop="onDrop($event, index)"
|
|
28
|
-
@click="selectAssetClass(item)"
|
|
29
|
-
>
|
|
30
|
-
<div class="asset-content">
|
|
31
|
-
<template v-if="item.isEditing">
|
|
32
|
-
<el-input
|
|
33
|
-
v-model="item.editName"
|
|
34
|
-
size="mini"
|
|
35
|
-
ref="assetInput"
|
|
36
|
-
@blur="finishEditAsset(item, index)"
|
|
37
|
-
@keyup.enter.native="$event.target.blur()"
|
|
38
|
-
/>
|
|
39
|
-
</template>
|
|
40
|
-
<template v-else>
|
|
41
|
-
<span class="asset-name">{{ item.name }}</span>
|
|
42
|
-
</template>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<!-- Sort button always visible -->
|
|
46
|
-
<div class="asset-actions-always">
|
|
47
|
-
<i class="el-icon-sort action-icon drag-handle" title="排序"></i>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<!-- Actions shown when selected -->
|
|
51
|
-
<div
|
|
52
|
-
class="asset-actions"
|
|
53
|
-
v-if="selectedAssetId === (item.tempId || item.id) && !item.isEditing"
|
|
54
|
-
>
|
|
55
|
-
<i
|
|
56
|
-
class="el-icon-edit action-icon"
|
|
57
|
-
title="编辑"
|
|
58
|
-
@click.stop="startEditAsset(item)"
|
|
59
|
-
></i>
|
|
60
|
-
<i
|
|
61
|
-
class="el-icon-delete action-icon"
|
|
62
|
-
title="删除"
|
|
63
|
-
@click.stop="deleteAssetClass(index)"
|
|
64
|
-
></i>
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
|
|
70
|
-
<!-- Right Panel: Sectors -->
|
|
71
|
-
<div class="right-panel">
|
|
72
|
-
<div class="panel-header right-header">
|
|
73
|
-
<span class="sector-count">包含板块 ({{ currentSectors.length }})</span>
|
|
74
|
-
<el-button
|
|
75
|
-
type="primary"
|
|
76
|
-
size="small"
|
|
77
|
-
icon="el-icon-plus"
|
|
78
|
-
:disabled="!selectedAssetId"
|
|
79
|
-
@click="addSector"
|
|
80
|
-
>
|
|
81
|
-
新增板块
|
|
82
|
-
</el-button>
|
|
83
|
-
</div>
|
|
84
|
-
<div class="sector-grid">
|
|
85
|
-
<div
|
|
86
|
-
v-for="(sector, index) in currentSectors"
|
|
87
|
-
:key="sector.tempId || sector.id"
|
|
88
|
-
class="sector-item"
|
|
89
|
-
>
|
|
90
|
-
<div class="sector-content">
|
|
91
|
-
<template v-if="sector.isEditing">
|
|
92
|
-
<el-input
|
|
93
|
-
v-model="sector.editName"
|
|
94
|
-
size="mini"
|
|
95
|
-
ref="sectorInput"
|
|
96
|
-
@blur="finishEditSector(sector, index)"
|
|
97
|
-
@keyup.enter.native="$event.target.blur()"
|
|
98
|
-
/>
|
|
99
|
-
</template>
|
|
100
|
-
<template v-else>
|
|
101
|
-
<span class="sector-name">{{ sector.name }}</span>
|
|
102
|
-
</template>
|
|
103
|
-
</div>
|
|
104
|
-
<div class="sector-actions" v-if="!sector.isEditing">
|
|
105
|
-
<i
|
|
106
|
-
class="el-icon-edit action-icon"
|
|
107
|
-
title="编辑"
|
|
108
|
-
@click.stop="startEditSector(sector)"
|
|
109
|
-
></i>
|
|
110
|
-
<i
|
|
111
|
-
class="el-icon-delete action-icon"
|
|
112
|
-
title="删除"
|
|
113
|
-
@click.stop="deleteSector(index)"
|
|
114
|
-
></i>
|
|
115
|
-
</div>
|
|
116
|
-
</div>
|
|
117
|
-
</div>
|
|
118
|
-
<div v-if="!selectedAssetId" class="empty-tip">请先选择一个资产类别</div>
|
|
119
|
-
</div>
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<span slot="footer" class="dialog-footer">
|
|
123
|
-
<el-button size="small" @click="handleCancel">取 消</el-button>
|
|
124
|
-
<el-button type="primary" size="small" @click="handleConfirm">确 认</el-button>
|
|
125
|
-
</span>
|
|
126
|
-
</el-dialog>
|
|
127
|
-
</template>
|
|
128
|
-
|
|
129
|
-
<script>
|
|
130
|
-
export default {
|
|
131
|
-
name: 'AssetClassConfiguration',
|
|
132
|
-
props: {
|
|
133
|
-
visible: {
|
|
134
|
-
type: Boolean,
|
|
135
|
-
default: false,
|
|
136
|
-
},
|
|
137
|
-
initialData: {
|
|
138
|
-
type: Array,
|
|
139
|
-
default: () => [],
|
|
140
|
-
},
|
|
141
|
-
},
|
|
142
|
-
data() {
|
|
143
|
-
return {
|
|
144
|
-
localAssetClasses: [],
|
|
145
|
-
selectedAssetId: null,
|
|
146
|
-
draggedIndex: null,
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
computed: {
|
|
150
|
-
dialogVisible: {
|
|
151
|
-
get() {
|
|
152
|
-
return this.visible
|
|
153
|
-
},
|
|
154
|
-
set(val) {
|
|
155
|
-
this.$emit('update:visible', val)
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
currentAsset() {
|
|
159
|
-
return this.localAssetClasses.find(item => (item.tempId || item.id) === this.selectedAssetId)
|
|
160
|
-
},
|
|
161
|
-
currentSectors() {
|
|
162
|
-
return this.currentAsset ? this.currentAsset.sectors : []
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
watch: {
|
|
166
|
-
visible(val) {
|
|
167
|
-
if (val) {
|
|
168
|
-
// Transform flat list to hierarchical structure
|
|
169
|
-
// Flat structure: { assetName, assetType, assetStatus, sortOrder }
|
|
170
|
-
// We assume input list contains only relevant items (or we filter by assetStatus=0)
|
|
171
|
-
|
|
172
|
-
const groups = {}
|
|
173
|
-
const sortedInput = [...this.initialData].sort((a, b) => a.sortOrder - b.sortOrder)
|
|
174
|
-
|
|
175
|
-
sortedInput.forEach(item => {
|
|
176
|
-
if (item.assetStatus === 1) return // Skip invalid items
|
|
177
|
-
|
|
178
|
-
const catName = item.assetName
|
|
179
|
-
if (!groups[catName]) {
|
|
180
|
-
groups[catName] = {
|
|
181
|
-
name: catName,
|
|
182
|
-
sectors: [],
|
|
183
|
-
minSortOrder: item.sortOrder,
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (item.assetType && item.assetType.trim() !== '') {
|
|
188
|
-
groups[catName].sectors.push({
|
|
189
|
-
name: item.assetType,
|
|
190
|
-
sortOrder: item.sortOrder,
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
// Convert to array and sort by minSortOrder (preserve category order)
|
|
196
|
-
this.localAssetClasses = Object.values(groups)
|
|
197
|
-
//.sort((a, b) => a.minSortOrder - b.minSortOrder) // Already sorted by input order roughly, but let's be safe
|
|
198
|
-
// Actually, since we iterate sortedInput, the order of creation in groups object implies order.
|
|
199
|
-
// But Object.values order is not guaranteed in all JS engines (though mostly yes).
|
|
200
|
-
// Let's rely on array mapping if possible, or just sort.
|
|
201
|
-
.sort((a, b) => a.minSortOrder - b.minSortOrder)
|
|
202
|
-
.map((g, index) => ({
|
|
203
|
-
id: null, // No persistent ID for category in flat mode, rely on name
|
|
204
|
-
tempId: 'cat_' + index + '_' + Date.now(),
|
|
205
|
-
name: g.name,
|
|
206
|
-
editName: g.name,
|
|
207
|
-
isEditing: false,
|
|
208
|
-
sectors: g.sectors.map((s, sIndex) => ({
|
|
209
|
-
id: null,
|
|
210
|
-
tempId: 'sec_' + index + '_' + sIndex + '_' + Date.now(),
|
|
211
|
-
name: s.name,
|
|
212
|
-
editName: s.name,
|
|
213
|
-
isEditing: false,
|
|
214
|
-
})),
|
|
215
|
-
}))
|
|
216
|
-
|
|
217
|
-
// Select first one by default if exists
|
|
218
|
-
if (this.localAssetClasses.length > 0) {
|
|
219
|
-
this.selectedAssetId = this.localAssetClasses[0].tempId
|
|
220
|
-
} else {
|
|
221
|
-
this.selectedAssetId = null
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
methods: {
|
|
227
|
-
// Asset Class Methods
|
|
228
|
-
addAssetClass() {
|
|
229
|
-
const newId = 'new_' + Date.now()
|
|
230
|
-
const newAsset = {
|
|
231
|
-
tempId: newId,
|
|
232
|
-
id: null, // New item
|
|
233
|
-
name: '',
|
|
234
|
-
editName: '',
|
|
235
|
-
isEditing: true,
|
|
236
|
-
sectors: [],
|
|
237
|
-
}
|
|
238
|
-
this.localAssetClasses.push(newAsset)
|
|
239
|
-
this.selectedAssetId = newId
|
|
240
|
-
this.$nextTick(() => {
|
|
241
|
-
const inputs = this.$refs.assetInput
|
|
242
|
-
if (inputs && inputs.length > 0) {
|
|
243
|
-
const lastInput = inputs[inputs.length - 1]
|
|
244
|
-
if (lastInput) lastInput.focus()
|
|
245
|
-
}
|
|
246
|
-
})
|
|
247
|
-
},
|
|
248
|
-
selectAssetClass(item) {
|
|
249
|
-
this.selectedAssetId = item.tempId || item.id
|
|
250
|
-
},
|
|
251
|
-
startEditAsset(item) {
|
|
252
|
-
item.editName = item.name
|
|
253
|
-
item.isEditing = true
|
|
254
|
-
this.$nextTick(() => {
|
|
255
|
-
const el = this.$el.querySelector('.asset-item.active .el-input__inner')
|
|
256
|
-
if (el) el.focus()
|
|
257
|
-
})
|
|
258
|
-
},
|
|
259
|
-
finishEditAsset(item) {
|
|
260
|
-
if (!item.editName.trim()) {
|
|
261
|
-
item.name = item.editName
|
|
262
|
-
item.isEditing = false
|
|
263
|
-
} else {
|
|
264
|
-
item.name = item.editName
|
|
265
|
-
item.isEditing = false
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
deleteAssetClass(index) {
|
|
269
|
-
const item = this.localAssetClasses[index]
|
|
270
|
-
const isSelected = (item.tempId || item.id) === this.selectedAssetId
|
|
271
|
-
|
|
272
|
-
this.$confirm('确定删除该资产类别及其下所有板块吗?', '提示', {
|
|
273
|
-
confirmButtonText: '确定',
|
|
274
|
-
cancelButtonText: '取消',
|
|
275
|
-
type: 'warning',
|
|
276
|
-
})
|
|
277
|
-
.then(() => {
|
|
278
|
-
this.localAssetClasses.splice(index, 1)
|
|
279
|
-
if (isSelected) {
|
|
280
|
-
if (this.localAssetClasses.length > 0) {
|
|
281
|
-
this.selectedAssetId =
|
|
282
|
-
this.localAssetClasses[0].tempId || this.localAssetClasses[0].id
|
|
283
|
-
} else {
|
|
284
|
-
this.selectedAssetId = null
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
})
|
|
288
|
-
.catch(() => {})
|
|
289
|
-
},
|
|
290
|
-
|
|
291
|
-
// Drag and Drop for Asset Classes
|
|
292
|
-
onDragStart(event, index) {
|
|
293
|
-
this.draggedIndex = index
|
|
294
|
-
event.dataTransfer.effectAllowed = 'move'
|
|
295
|
-
},
|
|
296
|
-
onDragOver(event) {
|
|
297
|
-
event.preventDefault()
|
|
298
|
-
},
|
|
299
|
-
onDrop(event, index) {
|
|
300
|
-
event.preventDefault()
|
|
301
|
-
if (this.draggedIndex !== null && this.draggedIndex !== index) {
|
|
302
|
-
const item = this.localAssetClasses.splice(this.draggedIndex, 1)[0]
|
|
303
|
-
this.localAssetClasses.splice(index, 0, item)
|
|
304
|
-
}
|
|
305
|
-
this.draggedIndex = null
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
// Sector Methods
|
|
309
|
-
addSector() {
|
|
310
|
-
if (!this.currentAsset) return
|
|
311
|
-
const newSector = {
|
|
312
|
-
tempId: 'sec_' + Date.now(),
|
|
313
|
-
id: null,
|
|
314
|
-
name: '',
|
|
315
|
-
editName: '',
|
|
316
|
-
isEditing: true,
|
|
317
|
-
}
|
|
318
|
-
this.currentAsset.sectors.push(newSector)
|
|
319
|
-
this.$nextTick(() => {
|
|
320
|
-
const sectorInputs = this.$refs.sectorInput
|
|
321
|
-
if (sectorInputs && sectorInputs.length) {
|
|
322
|
-
sectorInputs[sectorInputs.length - 1].focus()
|
|
323
|
-
}
|
|
324
|
-
})
|
|
325
|
-
},
|
|
326
|
-
startEditSector(sector) {
|
|
327
|
-
sector.editName = sector.name
|
|
328
|
-
sector.isEditing = true
|
|
329
|
-
this.$nextTick(() => {
|
|
330
|
-
const sectorInputs = this.$refs.sectorInput
|
|
331
|
-
if (sectorInputs && sectorInputs.length) {
|
|
332
|
-
sectorInputs[sectorInputs.length - 1].focus()
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
},
|
|
336
|
-
finishEditSector(sector) {
|
|
337
|
-
sector.name = sector.editName
|
|
338
|
-
sector.isEditing = false
|
|
339
|
-
},
|
|
340
|
-
deleteSector(index) {
|
|
341
|
-
if (!this.currentAsset) return
|
|
342
|
-
this.$confirm('确定删除该板块吗?', '提示', {
|
|
343
|
-
confirmButtonText: '确定',
|
|
344
|
-
cancelButtonText: '取消',
|
|
345
|
-
type: 'warning',
|
|
346
|
-
})
|
|
347
|
-
.then(() => {
|
|
348
|
-
this.currentAsset.sectors.splice(index, 1)
|
|
349
|
-
})
|
|
350
|
-
.catch(() => {})
|
|
351
|
-
},
|
|
352
|
-
|
|
353
|
-
// Dialog Actions
|
|
354
|
-
handleCancel() {
|
|
355
|
-
this.dialogVisible = false
|
|
356
|
-
},
|
|
357
|
-
handleConfirm() {
|
|
358
|
-
// Convert hierarchical structure back to flat list
|
|
359
|
-
// Flat structure: { assetName, assetType, assetStatus, sortOrder }
|
|
360
|
-
|
|
361
|
-
const flatList = []
|
|
362
|
-
let globalSortOrder = 1
|
|
363
|
-
|
|
364
|
-
this.localAssetClasses.forEach(asset => {
|
|
365
|
-
const assetName = asset.name ? asset.name.trim() : ''
|
|
366
|
-
if (!assetName) return // Skip empty asset names
|
|
367
|
-
|
|
368
|
-
const validSectors = asset.sectors.filter(s => s.name && s.name.trim() !== '')
|
|
369
|
-
|
|
370
|
-
if (validSectors.length === 0) {
|
|
371
|
-
// Asset class with no sectors
|
|
372
|
-
flatList.push({
|
|
373
|
-
assetName: assetName,
|
|
374
|
-
assetType: '',
|
|
375
|
-
assetStatus: 0,
|
|
376
|
-
sortOrder: globalSortOrder++,
|
|
377
|
-
})
|
|
378
|
-
} else {
|
|
379
|
-
validSectors.forEach(sector => {
|
|
380
|
-
flatList.push({
|
|
381
|
-
assetName: assetName,
|
|
382
|
-
assetType: sector.name,
|
|
383
|
-
assetStatus: 0,
|
|
384
|
-
sortOrder: globalSortOrder++,
|
|
385
|
-
})
|
|
386
|
-
})
|
|
387
|
-
}
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
this.$emit('confirm', flatList)
|
|
391
|
-
this.dialogVisible = false
|
|
392
|
-
},
|
|
393
|
-
},
|
|
394
|
-
}
|
|
395
|
-
</script>
|
|
396
|
-
|
|
397
|
-
<style lang="scss" scoped>
|
|
398
|
-
.asset-config-container {
|
|
399
|
-
display: flex;
|
|
400
|
-
height: 500px;
|
|
401
|
-
border: 1px solid #dcdfe6;
|
|
402
|
-
border-radius: 4px;
|
|
403
|
-
|
|
404
|
-
.left-panel {
|
|
405
|
-
width: 20%;
|
|
406
|
-
border-right: 1px solid #dcdfe6;
|
|
407
|
-
display: flex;
|
|
408
|
-
flex-direction: column;
|
|
409
|
-
|
|
410
|
-
.panel-header {
|
|
411
|
-
padding: 10px;
|
|
412
|
-
border-bottom: 1px solid #ebeef5;
|
|
413
|
-
text-align: center;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
.asset-list {
|
|
417
|
-
flex: 1;
|
|
418
|
-
overflow-y: auto;
|
|
419
|
-
padding: 10px 0;
|
|
420
|
-
|
|
421
|
-
.asset-item {
|
|
422
|
-
padding: 8px 10px;
|
|
423
|
-
cursor: pointer;
|
|
424
|
-
display: flex;
|
|
425
|
-
justify-content: space-between;
|
|
426
|
-
align-items: center;
|
|
427
|
-
transition: background-color 0.2s;
|
|
428
|
-
|
|
429
|
-
&:hover {
|
|
430
|
-
background-color: #f5f7fa;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
&.active {
|
|
434
|
-
background-color: #e6f1fc;
|
|
435
|
-
color: #409eff;
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
.asset-content {
|
|
439
|
-
flex: 1;
|
|
440
|
-
overflow: hidden;
|
|
441
|
-
text-overflow: ellipsis;
|
|
442
|
-
white-space: nowrap;
|
|
443
|
-
margin-right: 5px;
|
|
444
|
-
|
|
445
|
-
.asset-name {
|
|
446
|
-
font-size: 14px;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
.asset-actions-always {
|
|
451
|
-
display: flex;
|
|
452
|
-
align-items: center;
|
|
453
|
-
margin-left: 5px;
|
|
454
|
-
|
|
455
|
-
.action-icon {
|
|
456
|
-
font-size: 14px;
|
|
457
|
-
color: #909399;
|
|
458
|
-
cursor: move;
|
|
459
|
-
padding: 2px;
|
|
460
|
-
|
|
461
|
-
&:hover {
|
|
462
|
-
color: #409eff;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
.asset-actions {
|
|
468
|
-
display: flex;
|
|
469
|
-
align-items: center;
|
|
470
|
-
gap: 4px;
|
|
471
|
-
margin-left: 5px;
|
|
472
|
-
|
|
473
|
-
.action-icon {
|
|
474
|
-
font-size: 14px;
|
|
475
|
-
color: #909399;
|
|
476
|
-
cursor: pointer;
|
|
477
|
-
padding: 2px;
|
|
478
|
-
|
|
479
|
-
&:hover {
|
|
480
|
-
color: #409eff;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
&.drag-handle {
|
|
484
|
-
cursor: move;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
.right-panel {
|
|
493
|
-
width: 80%;
|
|
494
|
-
display: flex;
|
|
495
|
-
flex-direction: column;
|
|
496
|
-
|
|
497
|
-
.panel-header {
|
|
498
|
-
padding: 10px 20px;
|
|
499
|
-
border-bottom: 1px solid #ebeef5;
|
|
500
|
-
display: flex;
|
|
501
|
-
justify-content: space-between;
|
|
502
|
-
align-items: center;
|
|
503
|
-
|
|
504
|
-
.sector-count {
|
|
505
|
-
font-size: 14px;
|
|
506
|
-
color: #606266;
|
|
507
|
-
font-weight: bold;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
.sector-grid {
|
|
512
|
-
flex: 1;
|
|
513
|
-
overflow-y: auto;
|
|
514
|
-
padding: 20px;
|
|
515
|
-
display: flex;
|
|
516
|
-
flex-wrap: wrap;
|
|
517
|
-
align-content: flex-start;
|
|
518
|
-
gap: 15px;
|
|
519
|
-
|
|
520
|
-
.sector-item {
|
|
521
|
-
width: calc((100% - 30px) / 3); // 3 items per row, 15px gap * 2 = 30px
|
|
522
|
-
height: 40px;
|
|
523
|
-
border: 1px solid #dcdfe6;
|
|
524
|
-
border-radius: 4px;
|
|
525
|
-
display: flex;
|
|
526
|
-
align-items: center;
|
|
527
|
-
padding: 0 10px;
|
|
528
|
-
box-sizing: border-box;
|
|
529
|
-
justify-content: space-between;
|
|
530
|
-
transition: all 0.2s;
|
|
531
|
-
|
|
532
|
-
&:hover {
|
|
533
|
-
border-color: #409eff;
|
|
534
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
.sector-content {
|
|
538
|
-
flex: 1;
|
|
539
|
-
margin-right: 5px;
|
|
540
|
-
overflow: hidden;
|
|
541
|
-
|
|
542
|
-
.sector-name {
|
|
543
|
-
font-size: 14px;
|
|
544
|
-
white-space: nowrap;
|
|
545
|
-
overflow: hidden;
|
|
546
|
-
text-overflow: ellipsis;
|
|
547
|
-
display: block;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
.sector-actions {
|
|
552
|
-
display: flex;
|
|
553
|
-
gap: 5px;
|
|
554
|
-
|
|
555
|
-
.action-icon {
|
|
556
|
-
font-size: 14px;
|
|
557
|
-
color: #909399;
|
|
558
|
-
cursor: pointer;
|
|
559
|
-
|
|
560
|
-
&:hover {
|
|
561
|
-
color: #409eff;
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
.empty-tip {
|
|
569
|
-
flex: 1;
|
|
570
|
-
display: flex;
|
|
571
|
-
justify-content: center;
|
|
572
|
-
align-items: center;
|
|
573
|
-
color: #909399;
|
|
574
|
-
font-size: 14px;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
</style>
|