vue2-client 1.18.28 → 1.18.30
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/assets/c__Users_QXLL_AppData_Roaming_Cursor_User_workspaceStorage_4fb3d7e3441d32bc6f2c7358b4188b48_images_e8c132e6dde513250d7f9721712df1f8-f1522a08-1aa0-4866-b4e5-b34cf2e21109.png +0 -0
- package/docs/HChart/351/205/215/347/275/256/346/226/207/346/241/243.md +2347 -0
- package/package.json +1 -1
- package/src/base-client/components/common/HIS/HButtons/HButtons.vue +1 -0
- package/src/base-client/components/common/HIS/HTab/HTab.vue +6 -4
- package/src/base-client/components/his/HChart/HChart.vue +35 -9
- package/src/pages/userInfoDetailManage/uploadFilesHistory/index.vue +159 -159
package/package.json
CHANGED
|
@@ -154,7 +154,8 @@ defineExpose({
|
|
|
154
154
|
border-radius: 6px 6px 0 0;
|
|
155
155
|
color: #5D5C5C;
|
|
156
156
|
font-weight: bold;
|
|
157
|
-
width: 134px;
|
|
157
|
+
min-width: 134px;
|
|
158
|
+
width: auto;
|
|
158
159
|
font-size: 18px;
|
|
159
160
|
line-height: 26px;
|
|
160
161
|
font-family: "Source Han Sans";
|
|
@@ -162,17 +163,18 @@ defineExpose({
|
|
|
162
163
|
height: 32px;
|
|
163
164
|
text-align: center;
|
|
164
165
|
margin: 0 !important;
|
|
165
|
-
padding: 0 !important;
|
|
166
|
+
padding: 0 12px !important;
|
|
166
167
|
}
|
|
167
168
|
.ant-tabs-tab-active {
|
|
168
169
|
background-color: #0057FE;
|
|
169
170
|
color: #ffffff;
|
|
170
|
-
width: 134px;
|
|
171
|
+
min-width: 134px;
|
|
172
|
+
width: auto;
|
|
171
173
|
line-height: 26px;
|
|
172
174
|
height: 32px;
|
|
173
175
|
text-align: center;
|
|
174
176
|
margin: 0 !important;
|
|
175
|
-
padding: 0 !important;
|
|
177
|
+
padding: 0 12px !important;
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
180
|
|
|
@@ -274,12 +274,24 @@ const resolveStaticDataset = (config) => {
|
|
|
274
274
|
return scoped
|
|
275
275
|
}
|
|
276
276
|
let scopedDataset = dataset
|
|
277
|
+
// 先处理时间粒度筛选(radioFilter),因为 dataset 的第一层可能是时间粒度
|
|
278
|
+
const filterKeys = [
|
|
279
|
+
selectedFilterValue.value,
|
|
280
|
+
radioFilterConfig.value?.defaultValue
|
|
281
|
+
].filter(Boolean)
|
|
282
|
+
if (filterKeys.length) {
|
|
283
|
+
const filterScoped = pickByKeys(dataset, filterKeys, true)
|
|
284
|
+
if (Array.isArray(filterScoped)) return filterScoped
|
|
285
|
+
if (filterScoped && typeof filterScoped === 'object') scopedDataset = filterScoped
|
|
286
|
+
}
|
|
287
|
+
if (Array.isArray(scopedDataset)) return scopedDataset
|
|
288
|
+
// 再处理级联筛选或侧边列表筛选
|
|
277
289
|
if (isCascadeMode.value) {
|
|
278
290
|
const cascadeKeys = cascadeColumns.value
|
|
279
291
|
.map(column => column.field && selectedCascadeValues.value[column.field])
|
|
280
292
|
.filter(value => value !== undefined && value !== null && value !== '')
|
|
281
293
|
if (cascadeKeys.length) {
|
|
282
|
-
const cascadeScoped = pickNestedByKeys(
|
|
294
|
+
const cascadeScoped = pickNestedByKeys(scopedDataset, cascadeKeys)
|
|
283
295
|
if (Array.isArray(cascadeScoped)) return cascadeScoped
|
|
284
296
|
if (cascadeScoped && typeof cascadeScoped === 'object') scopedDataset = cascadeScoped
|
|
285
297
|
}
|
|
@@ -289,18 +301,32 @@ const resolveStaticDataset = (config) => {
|
|
|
289
301
|
sideListConfig.value?.defaultValue
|
|
290
302
|
].filter(Boolean)
|
|
291
303
|
if (listKeys.length) {
|
|
292
|
-
|
|
304
|
+
// 优先在已按时间粒度过滤后的 scopedDataset 中取
|
|
305
|
+
const listScoped = pickByKeys(scopedDataset, listKeys, true)
|
|
293
306
|
if (Array.isArray(listScoped)) return listScoped
|
|
294
|
-
if (listScoped && typeof listScoped === 'object')
|
|
307
|
+
if (listScoped && typeof listScoped === 'object') {
|
|
308
|
+
// 在侧边列表命中的作用域内,再次按时间粒度过滤(处理 { dept: { week: [...] } } 场景)
|
|
309
|
+
let scopedAfterList = listScoped
|
|
310
|
+
if (filterKeys.length) {
|
|
311
|
+
const filterScopedInner = pickByKeys(scopedAfterList, filterKeys, true)
|
|
312
|
+
if (Array.isArray(filterScopedInner)) return filterScopedInner
|
|
313
|
+
if (filterScopedInner && typeof filterScopedInner === 'object') scopedAfterList = filterScopedInner
|
|
314
|
+
}
|
|
315
|
+
scopedDataset = scopedAfterList
|
|
316
|
+
} else {
|
|
317
|
+
// 如果时间粒度在第二层(如 { dept: { week: [...] } }),尝试反向嵌套取值
|
|
318
|
+
const nestedOrder = pickNestedByKeys(dataset, [...listKeys, ...filterKeys])
|
|
319
|
+
if (Array.isArray(nestedOrder)) return nestedOrder
|
|
320
|
+
if (nestedOrder && typeof nestedOrder === 'object') scopedDataset = nestedOrder
|
|
321
|
+
else {
|
|
322
|
+
const reverseNested = pickNestedByKeys(dataset, [...filterKeys, ...listKeys])
|
|
323
|
+
if (Array.isArray(reverseNested)) return reverseNested
|
|
324
|
+
if (reverseNested && typeof reverseNested === 'object') scopedDataset = reverseNested
|
|
325
|
+
}
|
|
326
|
+
}
|
|
295
327
|
}
|
|
296
328
|
}
|
|
297
329
|
if (Array.isArray(scopedDataset)) return scopedDataset
|
|
298
|
-
const filterKeys = [
|
|
299
|
-
selectedFilterValue.value,
|
|
300
|
-
radioFilterConfig.value?.defaultValue
|
|
301
|
-
].filter(Boolean)
|
|
302
|
-
const filterScoped = pickByKeys(scopedDataset, filterKeys, false)
|
|
303
|
-
if (Array.isArray(filterScoped)) return filterScoped
|
|
304
330
|
const firstArray = pickFirstArray(scopedDataset)
|
|
305
331
|
if (Array.isArray(firstArray)) return firstArray
|
|
306
332
|
}
|
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div>
|
|
3
|
-
<div class="filter-bar">
|
|
4
|
-
<a-date-picker v-model="upload_date" placeholder="上传日期" @change="selfSearch" />
|
|
5
|
-
<a-select
|
|
6
|
-
style="width: 200px;"
|
|
7
|
-
v-model="fusetype"
|
|
8
|
-
:options="fusetypes"
|
|
9
|
-
placeholder="分类"
|
|
10
|
-
@change="selfSearch"
|
|
11
|
-
allow-clear />
|
|
12
|
-
<a-button type="primary" @click="selfSearch">查询</a-button>
|
|
13
|
-
</div>
|
|
14
|
-
<a-list bordered>
|
|
15
|
-
<a-list-item v-for="item in files" :key="item.days">
|
|
16
|
-
<div class="file-group">
|
|
17
|
-
<h4>{{ item.days }}</h4>
|
|
18
|
-
<div class="file-items">
|
|
19
|
-
<div v-for="file in item.arrays" :key="file.id" class="file-card">
|
|
20
|
-
<img :src="getFileUrl(file.f_downloadpath)" class="file-image" v-if="file.f_filetype.includes('jpg') || file.f_filetype.includes('png')" @click="openPreview(file.f_downloadpath)" style="cursor:pointer" />
|
|
21
|
-
<p>上传时间: {{ file.f_uploaddate }}</p>
|
|
22
|
-
<p>操作员: {{ file.f_username }}</p>
|
|
23
|
-
<p>分类: {{ file.fusetype }}</p>
|
|
24
|
-
<p>说明: {{ file.fremarks }}</p>
|
|
25
|
-
<a :href="getFileUrl(file.f_downloadpath)" target="_blank">预览</a>
|
|
26
|
-
<a-button v-if="isDelete === '1'" @click="delet(file.id)">删除</a-button>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
</a-list-item>
|
|
31
|
-
</a-list>
|
|
32
|
-
<ImagePreview :src="previewImg" :visible="previewVisible" @close="previewVisible = false" />
|
|
33
|
-
</div>
|
|
34
|
-
</template>
|
|
35
|
-
|
|
36
|
-
<script>
|
|
37
|
-
import { post } from '@vue2-client/services/api'
|
|
38
|
-
import { del } from '@vue2-client/services/api/restTools'
|
|
39
|
-
import ImagePreview from './ImagePreview.vue'
|
|
40
|
-
export default {
|
|
41
|
-
props: {
|
|
42
|
-
currUserInfo: {
|
|
43
|
-
type: Object,
|
|
44
|
-
default: () => undefined
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
components: { ImagePreview },
|
|
48
|
-
data () {
|
|
49
|
-
return {
|
|
50
|
-
upload_date: null,
|
|
51
|
-
fusetype: null,
|
|
52
|
-
files: [],
|
|
53
|
-
fusetypes: [],
|
|
54
|
-
isDelete: '0',
|
|
55
|
-
previewVisible: false,
|
|
56
|
-
previewImg: ''
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
methods: {
|
|
60
|
-
async getfusetypes () {
|
|
61
|
-
this.fusetypes = [{ label: '全部', value: '' }]
|
|
62
|
-
const res = await post('/api/af-revenue/logic/getFileUseType', {})
|
|
63
|
-
this.fusetypes.push(...res.map(item => ({ label: item.fusetype, value: item.fusetype })))
|
|
64
|
-
},
|
|
65
|
-
async getFiles () {
|
|
66
|
-
if (!this.currUserInfo) return
|
|
67
|
-
this.files = []
|
|
68
|
-
let condition = `f_blobid = '${this.currUserInfo.f_userinfo_id}'`
|
|
69
|
-
if (this.upload_date) {
|
|
70
|
-
condition += ` and CONVERT(VARCHAR(100), f_uploaddate, 23) = '${this.upload_date}'`
|
|
71
|
-
}
|
|
72
|
-
if (this.fusetype) {
|
|
73
|
-
condition += ` and fusetype = '${this.fusetype}'`
|
|
74
|
-
}
|
|
75
|
-
const res = await post('/api/af-revenue/logic/getAllFiles', { data: { condition } })
|
|
76
|
-
this.files = res.days.map(day => ({
|
|
77
|
-
days: day.uploadday,
|
|
78
|
-
arrays: res.array.filter(file => file.uploadday === day.uploadday)
|
|
79
|
-
}))
|
|
80
|
-
},
|
|
81
|
-
async delet (fileId) {
|
|
82
|
-
await del('api/af-revenue/entity/save/t_files', { id: fileId }, { resolveMsg: '删除成功', rejectMsg: '删除失败' })
|
|
83
|
-
this.getFiles()
|
|
84
|
-
},
|
|
85
|
-
selfSearch () {
|
|
86
|
-
this.getFiles()
|
|
87
|
-
},
|
|
88
|
-
openPreview (src) {
|
|
89
|
-
this.previewImg = this.getFileUrl(src)
|
|
90
|
-
this.previewVisible = true
|
|
91
|
-
},
|
|
92
|
-
getFileUrl (path) {
|
|
93
|
-
if (!path) return ''
|
|
94
|
-
|
|
95
|
-
console.log('原始路径:', path)
|
|
96
|
-
|
|
97
|
-
// 获取当前域名和端口
|
|
98
|
-
const baseUrl = `${window.location.protocol}//${window.location.host}`
|
|
99
|
-
|
|
100
|
-
// 如果是本地文件路径,转换为新的转发路径
|
|
101
|
-
if (path.match(/^[A-Za-z]:[\/\\]/)) {
|
|
102
|
-
// 提取文件名
|
|
103
|
-
const fileName = path.split(/[/\\]/).pop()
|
|
104
|
-
const newUrl = `${baseUrl}/rs/image/file/${fileName}`
|
|
105
|
-
console.log('转换后路径:', newUrl)
|
|
106
|
-
return newUrl
|
|
107
|
-
}
|
|
108
|
-
// 如果已经是HTTP路径,直接返回
|
|
109
|
-
if (path.startsWith('http')) {
|
|
110
|
-
console.log('HTTP路径,直接返回:', path)
|
|
111
|
-
return path
|
|
112
|
-
}
|
|
113
|
-
// 如果是相对路径,添加域名前缀
|
|
114
|
-
if (path.startsWith('/resource/')) {
|
|
115
|
-
const newUrl = `${baseUrl}${path}`
|
|
116
|
-
console.log('相对路径转换:', newUrl)
|
|
117
|
-
return newUrl
|
|
118
|
-
}
|
|
119
|
-
console.log('其他路径,直接返回:', path)
|
|
120
|
-
return path
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
mounted () {
|
|
124
|
-
if (this.$login.r.includes('上传附件删除')) {
|
|
125
|
-
this.isDelete = '1'
|
|
126
|
-
}
|
|
127
|
-
this.getFiles()
|
|
128
|
-
this.getfusetypes()
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
</script>
|
|
132
|
-
|
|
133
|
-
<style scoped>
|
|
134
|
-
.filter-bar {
|
|
135
|
-
display: flex;
|
|
136
|
-
gap: 10px;
|
|
137
|
-
margin-bottom: 15px;
|
|
138
|
-
}
|
|
139
|
-
.file-group {
|
|
140
|
-
margin-bottom: 15px;
|
|
141
|
-
}
|
|
142
|
-
.file-items {
|
|
143
|
-
display: flex;
|
|
144
|
-
flex-wrap: wrap;
|
|
145
|
-
gap: 10px;
|
|
146
|
-
}
|
|
147
|
-
.file-card {
|
|
148
|
-
border: 1px solid #ddd;
|
|
149
|
-
padding: 10px;
|
|
150
|
-
border-radius: 5px;
|
|
151
|
-
width: 200px;
|
|
152
|
-
}
|
|
153
|
-
.file-image {
|
|
154
|
-
width: 100%; /* 让图片填充整个容器 */
|
|
155
|
-
height: 150px; /* 调整高度 */
|
|
156
|
-
object-fit: cover; /* 保持图片比例,填充整个区域 */
|
|
157
|
-
border-radius: 5px; /* 圆角边框 */
|
|
158
|
-
}
|
|
159
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div class="filter-bar">
|
|
4
|
+
<a-date-picker v-model="upload_date" placeholder="上传日期" @change="selfSearch" />
|
|
5
|
+
<a-select
|
|
6
|
+
style="width: 200px;"
|
|
7
|
+
v-model="fusetype"
|
|
8
|
+
:options="fusetypes"
|
|
9
|
+
placeholder="分类"
|
|
10
|
+
@change="selfSearch"
|
|
11
|
+
allow-clear />
|
|
12
|
+
<a-button type="primary" @click="selfSearch">查询</a-button>
|
|
13
|
+
</div>
|
|
14
|
+
<a-list bordered>
|
|
15
|
+
<a-list-item v-for="item in files" :key="item.days">
|
|
16
|
+
<div class="file-group">
|
|
17
|
+
<h4>{{ item.days }}</h4>
|
|
18
|
+
<div class="file-items">
|
|
19
|
+
<div v-for="file in item.arrays" :key="file.id" class="file-card">
|
|
20
|
+
<img :src="getFileUrl(file.f_downloadpath)" class="file-image" v-if="file.f_filetype.includes('jpg') || file.f_filetype.includes('png')" @click="openPreview(file.f_downloadpath)" style="cursor:pointer" />
|
|
21
|
+
<p>上传时间: {{ file.f_uploaddate }}</p>
|
|
22
|
+
<p>操作员: {{ file.f_username }}</p>
|
|
23
|
+
<p>分类: {{ file.fusetype }}</p>
|
|
24
|
+
<p>说明: {{ file.fremarks }}</p>
|
|
25
|
+
<a :href="getFileUrl(file.f_downloadpath)" target="_blank">预览</a>
|
|
26
|
+
<a-button v-if="isDelete === '1'" @click="delet(file.id)">删除</a-button>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</a-list-item>
|
|
31
|
+
</a-list>
|
|
32
|
+
<ImagePreview :src="previewImg" :visible="previewVisible" @close="previewVisible = false" />
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script>
|
|
37
|
+
import { post } from '@vue2-client/services/api'
|
|
38
|
+
import { del } from '@vue2-client/services/api/restTools'
|
|
39
|
+
import ImagePreview from './ImagePreview.vue'
|
|
40
|
+
export default {
|
|
41
|
+
props: {
|
|
42
|
+
currUserInfo: {
|
|
43
|
+
type: Object,
|
|
44
|
+
default: () => undefined
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
components: { ImagePreview },
|
|
48
|
+
data () {
|
|
49
|
+
return {
|
|
50
|
+
upload_date: null,
|
|
51
|
+
fusetype: null,
|
|
52
|
+
files: [],
|
|
53
|
+
fusetypes: [],
|
|
54
|
+
isDelete: '0',
|
|
55
|
+
previewVisible: false,
|
|
56
|
+
previewImg: ''
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
methods: {
|
|
60
|
+
async getfusetypes () {
|
|
61
|
+
this.fusetypes = [{ label: '全部', value: '' }]
|
|
62
|
+
const res = await post('/api/af-revenue/logic/getFileUseType', {})
|
|
63
|
+
this.fusetypes.push(...res.map(item => ({ label: item.fusetype, value: item.fusetype })))
|
|
64
|
+
},
|
|
65
|
+
async getFiles () {
|
|
66
|
+
if (!this.currUserInfo) return
|
|
67
|
+
this.files = []
|
|
68
|
+
let condition = `f_blobid = '${this.currUserInfo.f_userinfo_id}'`
|
|
69
|
+
if (this.upload_date) {
|
|
70
|
+
condition += ` and CONVERT(VARCHAR(100), f_uploaddate, 23) = '${this.upload_date}'`
|
|
71
|
+
}
|
|
72
|
+
if (this.fusetype) {
|
|
73
|
+
condition += ` and fusetype = '${this.fusetype}'`
|
|
74
|
+
}
|
|
75
|
+
const res = await post('/api/af-revenue/logic/getAllFiles', { data: { condition } })
|
|
76
|
+
this.files = res.days.map(day => ({
|
|
77
|
+
days: day.uploadday,
|
|
78
|
+
arrays: res.array.filter(file => file.uploadday === day.uploadday)
|
|
79
|
+
}))
|
|
80
|
+
},
|
|
81
|
+
async delet (fileId) {
|
|
82
|
+
await del('api/af-revenue/entity/save/t_files', { id: fileId }, { resolveMsg: '删除成功', rejectMsg: '删除失败' })
|
|
83
|
+
this.getFiles()
|
|
84
|
+
},
|
|
85
|
+
selfSearch () {
|
|
86
|
+
this.getFiles()
|
|
87
|
+
},
|
|
88
|
+
openPreview (src) {
|
|
89
|
+
this.previewImg = this.getFileUrl(src)
|
|
90
|
+
this.previewVisible = true
|
|
91
|
+
},
|
|
92
|
+
getFileUrl (path) {
|
|
93
|
+
if (!path) return ''
|
|
94
|
+
|
|
95
|
+
console.log('原始路径:', path)
|
|
96
|
+
|
|
97
|
+
// 获取当前域名和端口
|
|
98
|
+
const baseUrl = `${window.location.protocol}//${window.location.host}`
|
|
99
|
+
|
|
100
|
+
// 如果是本地文件路径,转换为新的转发路径
|
|
101
|
+
if (path.match(/^[A-Za-z]:[\/\\]/)) {
|
|
102
|
+
// 提取文件名
|
|
103
|
+
const fileName = path.split(/[/\\]/).pop()
|
|
104
|
+
const newUrl = `${baseUrl}/rs/image/file/${fileName}`
|
|
105
|
+
console.log('转换后路径:', newUrl)
|
|
106
|
+
return newUrl
|
|
107
|
+
}
|
|
108
|
+
// 如果已经是HTTP路径,直接返回
|
|
109
|
+
if (path.startsWith('http')) {
|
|
110
|
+
console.log('HTTP路径,直接返回:', path)
|
|
111
|
+
return path
|
|
112
|
+
}
|
|
113
|
+
// 如果是相对路径,添加域名前缀
|
|
114
|
+
if (path.startsWith('/resource/')) {
|
|
115
|
+
const newUrl = `${baseUrl}${path}`
|
|
116
|
+
console.log('相对路径转换:', newUrl)
|
|
117
|
+
return newUrl
|
|
118
|
+
}
|
|
119
|
+
console.log('其他路径,直接返回:', path)
|
|
120
|
+
return path
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
mounted () {
|
|
124
|
+
if (this.$login.r.includes('上传附件删除')) {
|
|
125
|
+
this.isDelete = '1'
|
|
126
|
+
}
|
|
127
|
+
this.getFiles()
|
|
128
|
+
this.getfusetypes()
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
</script>
|
|
132
|
+
|
|
133
|
+
<style scoped>
|
|
134
|
+
.filter-bar {
|
|
135
|
+
display: flex;
|
|
136
|
+
gap: 10px;
|
|
137
|
+
margin-bottom: 15px;
|
|
138
|
+
}
|
|
139
|
+
.file-group {
|
|
140
|
+
margin-bottom: 15px;
|
|
141
|
+
}
|
|
142
|
+
.file-items {
|
|
143
|
+
display: flex;
|
|
144
|
+
flex-wrap: wrap;
|
|
145
|
+
gap: 10px;
|
|
146
|
+
}
|
|
147
|
+
.file-card {
|
|
148
|
+
border: 1px solid #ddd;
|
|
149
|
+
padding: 10px;
|
|
150
|
+
border-radius: 5px;
|
|
151
|
+
width: 200px;
|
|
152
|
+
}
|
|
153
|
+
.file-image {
|
|
154
|
+
width: 100%; /* 让图片填充整个容器 */
|
|
155
|
+
height: 150px; /* 调整高度 */
|
|
156
|
+
object-fit: cover; /* 保持图片比例,填充整个区域 */
|
|
157
|
+
border-radius: 5px; /* 圆角边框 */
|
|
158
|
+
}
|
|
159
|
+
</style>
|