n20-common-lib 2.22.43 → 2.22.45
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
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
<div class="n20-date-picker" :class="{ 'has-long-term': showLongTerm }">
|
|
3
|
+
<el-date-picker
|
|
4
|
+
ref="date-picker"
|
|
5
|
+
class="n20-date-editor"
|
|
6
|
+
:class="{ 'has-value': clearable && value }"
|
|
7
|
+
v-bind="$attrs"
|
|
8
|
+
:value="value"
|
|
9
|
+
:clearable="clearable"
|
|
10
|
+
:disabled="datePickerDisabled"
|
|
11
|
+
v-on="listeners"
|
|
12
|
+
/>
|
|
13
|
+
<el-checkbox
|
|
14
|
+
v-if="showLongTerm"
|
|
15
|
+
v-model="longTermC"
|
|
16
|
+
class="n20-date-picker__long-term"
|
|
17
|
+
:disabled="checkboxDisabled"
|
|
18
|
+
>
|
|
19
|
+
{{ longTermLabel | $lc }}
|
|
20
|
+
</el-checkbox>
|
|
21
|
+
</div>
|
|
11
22
|
</template>
|
|
12
23
|
|
|
13
24
|
<script>
|
|
25
|
+
const LONG_TERM_DATE = new Date(9999, 11, 31, 23, 59, 59)
|
|
26
|
+
|
|
14
27
|
export default {
|
|
15
28
|
name: 'DatePicker',
|
|
16
29
|
props: {
|
|
@@ -21,7 +34,139 @@ export default {
|
|
|
21
34
|
clearable: {
|
|
22
35
|
type: Boolean,
|
|
23
36
|
default: true
|
|
37
|
+
},
|
|
38
|
+
showLongTerm: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
default: false
|
|
41
|
+
},
|
|
42
|
+
longTerm: {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: false
|
|
45
|
+
},
|
|
46
|
+
longTermLabel: {
|
|
47
|
+
type: String,
|
|
48
|
+
default: '长期'
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
computed: {
|
|
52
|
+
listeners() {
|
|
53
|
+
return Object.assign({}, this.$listeners, {
|
|
54
|
+
input: (val) => {
|
|
55
|
+
this.$emit('input', val)
|
|
56
|
+
if (this.longTerm) {
|
|
57
|
+
this.$emit('update:long-term', false)
|
|
58
|
+
this.$emit('changeLongTerm', {
|
|
59
|
+
longTerm: false,
|
|
60
|
+
value: val
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
},
|
|
66
|
+
longTermC: {
|
|
67
|
+
get() {
|
|
68
|
+
return this.longTerm
|
|
69
|
+
},
|
|
70
|
+
set(val) {
|
|
71
|
+
this.handleLongTermChange(val)
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
datePickerDisabled() {
|
|
75
|
+
return this.longTerm || this.isDisabled
|
|
76
|
+
},
|
|
77
|
+
checkboxDisabled() {
|
|
78
|
+
return this.isDisabled
|
|
79
|
+
},
|
|
80
|
+
isDisabled() {
|
|
81
|
+
return this.$attrs.disabled === '' || this.$attrs.disabled === true || this.$attrs.disabled === 'disabled'
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
methods: {
|
|
85
|
+
handleLongTermChange(val) {
|
|
86
|
+
this.$emit('update:long-term', val)
|
|
87
|
+
|
|
88
|
+
if (val) {
|
|
89
|
+
const longTermValue = this.getLongTermValue()
|
|
90
|
+
this.$emit('input', longTermValue)
|
|
91
|
+
this.$emit('change', longTermValue)
|
|
92
|
+
this.$emit('changeLongTerm', {
|
|
93
|
+
longTerm: true,
|
|
94
|
+
value: longTermValue
|
|
95
|
+
})
|
|
96
|
+
} else {
|
|
97
|
+
const currentValue = this.getCurrentValue()
|
|
98
|
+
this.$emit('input', currentValue)
|
|
99
|
+
this.$emit('change', currentValue)
|
|
100
|
+
this.$emit('changeLongTerm', {
|
|
101
|
+
longTerm: false,
|
|
102
|
+
value: currentValue
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
getLongTermValue() {
|
|
107
|
+
return this.getDateValue(LONG_TERM_DATE)
|
|
108
|
+
},
|
|
109
|
+
getCurrentValue() {
|
|
110
|
+
return this.getDateValue(new Date())
|
|
111
|
+
},
|
|
112
|
+
getDateValue(date) {
|
|
113
|
+
const valueFormat = this.$attrs['value-format']
|
|
114
|
+
|
|
115
|
+
if (valueFormat === 'timestamp') {
|
|
116
|
+
return date.getTime()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!valueFormat) {
|
|
120
|
+
return new Date(date.getTime())
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const year = date.getFullYear() + ''
|
|
124
|
+
const month = this.padDateValue(date.getMonth() + 1)
|
|
125
|
+
const day = this.padDateValue(date.getDate())
|
|
126
|
+
const hours = this.padDateValue(date.getHours())
|
|
127
|
+
const minutes = this.padDateValue(date.getMinutes())
|
|
128
|
+
const seconds = this.padDateValue(date.getSeconds())
|
|
129
|
+
|
|
130
|
+
return valueFormat
|
|
131
|
+
.replace(/yyyy/g, year)
|
|
132
|
+
.replace(/YYYY/g, year)
|
|
133
|
+
.replace(/MM/g, month)
|
|
134
|
+
.replace(/dd/g, day)
|
|
135
|
+
.replace(/DD/g, day)
|
|
136
|
+
.replace(/HH/g, hours)
|
|
137
|
+
.replace(/hh/g, hours)
|
|
138
|
+
.replace(/mm/g, minutes)
|
|
139
|
+
.replace(/ss/g, seconds)
|
|
140
|
+
},
|
|
141
|
+
padDateValue(value) {
|
|
142
|
+
return value > 9 ? value + '' : '0' + value
|
|
24
143
|
}
|
|
25
144
|
}
|
|
26
145
|
}
|
|
27
146
|
</script>
|
|
147
|
+
|
|
148
|
+
<style scoped>
|
|
149
|
+
.n20-date-picker {
|
|
150
|
+
display: inline-block;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.n20-date-picker > .n20-date-editor {
|
|
154
|
+
width: 100%;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.n20-date-picker.has-long-term {
|
|
158
|
+
display: inline-flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.n20-date-picker.has-long-term > .n20-date-editor {
|
|
163
|
+
flex: 1;
|
|
164
|
+
width: auto;
|
|
165
|
+
min-width: 0;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.n20-date-picker__long-term {
|
|
169
|
+
margin-left: 8px;
|
|
170
|
+
white-space: nowrap;
|
|
171
|
+
}
|
|
172
|
+
</style>
|
|
@@ -32,15 +32,11 @@
|
|
|
32
32
|
:height="height"
|
|
33
33
|
border
|
|
34
34
|
@selection-change="(selection) => (selectionList = selection)"
|
|
35
|
+
@sort-change="onSortChange"
|
|
35
36
|
>
|
|
36
37
|
<slot name="selection-column">
|
|
37
38
|
<el-table-column type="selection" width="50" align="center" />
|
|
38
39
|
</slot>
|
|
39
|
-
<el-table-column :label="'排序' | $lc" width="50" align="center">
|
|
40
|
-
<template slot-scope="{ row }">
|
|
41
|
-
<i class="n20-icon-tuodong file-upload-table__drag-handle" :data-row-key="row[keys.rowKey]"></i>
|
|
42
|
-
</template>
|
|
43
|
-
</el-table-column>
|
|
44
40
|
<template v-if="dataPorp.slotHeader">
|
|
45
41
|
<el-table-column
|
|
46
42
|
v-for="item in dataPorp.slotHeader"
|
|
@@ -77,7 +73,7 @@
|
|
|
77
73
|
</div>
|
|
78
74
|
</slot>
|
|
79
75
|
</el-table-column>
|
|
80
|
-
<el-table-column :label="'附件名称' | $lc" :prop="keys.name">
|
|
76
|
+
<el-table-column :label="'附件名称' | $lc" :prop="keys.name" sortable="custom">
|
|
81
77
|
<slot slot="header" slot-scope="scope" name="name-header" :column="scope.column">{{ '附件名称' | $lc }}</slot>
|
|
82
78
|
<slot slot-scope="{ row }" name="name" :row="row">
|
|
83
79
|
<span v-if="readonly">{{ row[keys.name] ? row[keys.name].replace(/\.[A-z0-9]+$/, '') : '' }}</span>
|
|
@@ -272,7 +268,7 @@
|
|
|
272
268
|
:close-on-click-modal="false"
|
|
273
269
|
:destroy-on-open="true"
|
|
274
270
|
>
|
|
275
|
-
<el-select v-model="bathType" class="m-b-s" clearable @change="handleBathChange">
|
|
271
|
+
<el-select v-model="bathType" class="m-b-s w-100p" clearable @change="handleBathChange">
|
|
276
272
|
<el-option
|
|
277
273
|
v-for="item in typeOptions"
|
|
278
274
|
:key="item.type"
|
|
@@ -292,7 +288,7 @@
|
|
|
292
288
|
:multiple="true"
|
|
293
289
|
:show-file-list="true"
|
|
294
290
|
:action="apiPrefix ? apiPrefix + action : action"
|
|
295
|
-
:data="fileData"
|
|
291
|
+
:data="_batchFileData || fileData"
|
|
296
292
|
:headers="headers"
|
|
297
293
|
:accept="fileAccept"
|
|
298
294
|
:size="fileSize"
|
|
@@ -322,7 +318,6 @@ import aiCheckDialog from './aiCheckDialog.vue'
|
|
|
322
318
|
import getJsonc from '../../assets/getJsonc.js'
|
|
323
319
|
import _axios from 'axios'
|
|
324
320
|
import dayjs from 'dayjs'
|
|
325
|
-
import Sortable from 'sortablejs'
|
|
326
321
|
import XEUtils from 'xe-utils'
|
|
327
322
|
|
|
328
323
|
import 'viewerjs/dist/viewer.css'
|
|
@@ -507,7 +502,8 @@ export default {
|
|
|
507
502
|
previewSameOrg: false,
|
|
508
503
|
seeRow: {},
|
|
509
504
|
officeStatus: false,
|
|
510
|
-
|
|
505
|
+
// 批量上传使用的文件数据(避免直接修改计算属性)
|
|
506
|
+
_batchFileData: null
|
|
511
507
|
}
|
|
512
508
|
},
|
|
513
509
|
computed: {
|
|
@@ -550,63 +546,31 @@ export default {
|
|
|
550
546
|
},
|
|
551
547
|
immediate: true,
|
|
552
548
|
deep: true
|
|
553
|
-
},
|
|
554
|
-
tableKey() {
|
|
555
|
-
this.initSortable()
|
|
556
549
|
}
|
|
557
550
|
},
|
|
558
551
|
mounted() {
|
|
559
552
|
this.getConfiguration()
|
|
560
|
-
this.initSortable()
|
|
561
|
-
},
|
|
562
|
-
beforeDestroy() {
|
|
563
|
-
this.destroySortable()
|
|
564
553
|
},
|
|
565
554
|
methods: {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
if (!$tbody) {
|
|
572
|
-
return
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
this.sortable = Sortable.create($tbody, {
|
|
576
|
-
handle: '.file-upload-table__drag-handle',
|
|
577
|
-
ghostClass: 'file-upload-table__sortable-ghost',
|
|
578
|
-
setData(dataTransfer) {
|
|
579
|
-
dataTransfer.setData('Text', '')
|
|
580
|
-
},
|
|
581
|
-
onEnd: ({ oldIndex, newIndex }) => {
|
|
582
|
-
if (
|
|
583
|
-
oldIndex === newIndex ||
|
|
584
|
-
oldIndex === undefined ||
|
|
585
|
-
newIndex === undefined ||
|
|
586
|
-
oldIndex < 0 ||
|
|
587
|
-
newIndex < 0
|
|
588
|
-
) {
|
|
589
|
-
return
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
const targetRow = this.tableData.splice(oldIndex, 1)[0]
|
|
593
|
-
if (!targetRow) {
|
|
594
|
-
return
|
|
595
|
-
}
|
|
596
|
-
this.tableData.splice(newIndex, 0, targetRow)
|
|
597
|
-
this.$emit('sort', this.tableData.slice())
|
|
598
|
-
this.saveFileSort().catch(() => {
|
|
599
|
-
this.$message.error($lc('附件排序保存失败'))
|
|
600
|
-
})
|
|
601
|
-
}
|
|
602
|
-
})
|
|
603
|
-
})
|
|
604
|
-
},
|
|
605
|
-
destroySortable() {
|
|
606
|
-
if (this.sortable) {
|
|
607
|
-
this.sortable.destroy()
|
|
608
|
-
this.sortable = null
|
|
555
|
+
// 点击附件名称表头排序(替代原拖动排序)
|
|
556
|
+
onSortChange({ prop, order }) {
|
|
557
|
+
// 仅处理附件名称列;order 为 null(取消排序)时不处理
|
|
558
|
+
if (prop !== this.keys.name || !order) {
|
|
559
|
+
return
|
|
609
560
|
}
|
|
561
|
+
const nameKey = this.keys.name
|
|
562
|
+
// 与显示一致:去除扩展名后再比较
|
|
563
|
+
const stripName = (v) => (v == null ? '' : String(v).replace(/\.[A-z0-9]+$/, ''))
|
|
564
|
+
const dir = order === 'ascending' ? 1 : -1
|
|
565
|
+
const sorted = [...this.tableData].sort(
|
|
566
|
+
(a, b) => stripName(a[nameKey]).localeCompare(stripName(b[nameKey]), 'zh-CN', { numeric: true }) * dir
|
|
567
|
+
)
|
|
568
|
+
// 原地更新 tableData(沿用现有 splice 修改 prop 数组的模式)
|
|
569
|
+
this.tableData.splice(0, this.tableData.length, ...sorted)
|
|
570
|
+
this.$emit('sort', this.tableData.slice())
|
|
571
|
+
this.saveFileSort().catch(() => {
|
|
572
|
+
this.$message.error($lc('附件排序保存失败'))
|
|
573
|
+
})
|
|
610
574
|
},
|
|
611
575
|
async saveFileSort() {
|
|
612
576
|
const sortList = this.tableData
|
|
@@ -783,20 +747,32 @@ export default {
|
|
|
783
747
|
if (bu) return bu(file)
|
|
784
748
|
},
|
|
785
749
|
handleBathChange() {
|
|
786
|
-
|
|
750
|
+
// 创建新的文件数据对象,避免直接修改计算属性
|
|
751
|
+
let fileData = this.fileData || {}
|
|
752
|
+
let dto = JSON.parse(fileData.data || '{}')
|
|
787
753
|
dto[this.keys.type] = this.bathType
|
|
788
|
-
this.
|
|
754
|
+
this._batchFileData = {
|
|
755
|
+
...fileData,
|
|
756
|
+
data: JSON.stringify(dto)
|
|
757
|
+
}
|
|
789
758
|
},
|
|
790
759
|
batchUploadFn() {
|
|
791
760
|
let $uploadwrap = this.$refs['upload-batch']
|
|
792
|
-
|
|
793
|
-
if (fileList.length !== 0 && fileList.every((f) => f.status === 'success')) {
|
|
794
|
-
this.visibleBatch = false
|
|
795
|
-
}
|
|
761
|
+
// 直接提交上传,关闭对话框的逻辑在 batchSuccess 回调中处理
|
|
796
762
|
$uploadwrap.submit()
|
|
797
763
|
},
|
|
798
764
|
batchSuccess(response, file, fileList) {
|
|
799
|
-
|
|
765
|
+
// 创建完整的行对象,初始化状态字段
|
|
766
|
+
let row = {
|
|
767
|
+
id: 'n' + Math.random(),
|
|
768
|
+
[this.keys.name]: '',
|
|
769
|
+
[this.keys.type]: this.bathType,
|
|
770
|
+
[this.keys.time]: '',
|
|
771
|
+
[this.keys.user]: JSON.parse(sessionStorage.getItem('userInfo')).uname,
|
|
772
|
+
_percent: 0,
|
|
773
|
+
_status: undefined,
|
|
774
|
+
_typeDisabled: false
|
|
775
|
+
}
|
|
800
776
|
this.tableData.splice(0, 0, row)
|
|
801
777
|
this.$nextTick(() => {
|
|
802
778
|
this.onSuccessFn(response, file, fileList, row)
|
|
@@ -954,13 +930,8 @@ export default {
|
|
|
954
930
|
let FD = new FormData()
|
|
955
931
|
FD.append(opt.filename, opt.file)
|
|
956
932
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
data = window._fileData
|
|
960
|
-
delete window._fileData
|
|
961
|
-
} else {
|
|
962
|
-
data = opt.data
|
|
963
|
-
}
|
|
933
|
+
// 优先使用 opt.data,其次使用 this.fileData,移除全局变量 window._fileData 的使用
|
|
934
|
+
let data = opt.data || this.fileData
|
|
964
935
|
|
|
965
936
|
if (data) {
|
|
966
937
|
let dto = JSON.parse(data.data)
|
|
@@ -1034,7 +1005,7 @@ export default {
|
|
|
1034
1005
|
_percent = 99
|
|
1035
1006
|
_status = 'error'
|
|
1036
1007
|
} else {
|
|
1037
|
-
_percent =
|
|
1008
|
+
_percent = 100
|
|
1038
1009
|
_status = 'success'
|
|
1039
1010
|
}
|
|
1040
1011
|
setTimeout(() => {
|
|
@@ -1091,21 +1062,4 @@ export default {
|
|
|
1091
1062
|
right: 46px;
|
|
1092
1063
|
top: 10px;
|
|
1093
1064
|
}
|
|
1094
|
-
|
|
1095
|
-
.file-upload-table__drag-handle {
|
|
1096
|
-
display: inline-block;
|
|
1097
|
-
color: #909399;
|
|
1098
|
-
font-size: 16px;
|
|
1099
|
-
cursor: move;
|
|
1100
|
-
}
|
|
1101
|
-
|
|
1102
|
-
.file-upload-table__drag-handle:hover {
|
|
1103
|
-
color: #606266;
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
.file-upload-table__sortable-ghost {
|
|
1107
|
-
opacity: 0.8;
|
|
1108
|
-
color: #fff !important;
|
|
1109
|
-
background: #42b983 !important;
|
|
1110
|
-
}
|
|
1111
1065
|
</style>
|