web-component-gallery 2.2.33 → 2.2.35

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.
@@ -0,0 +1,278 @@
1
+ <template>
2
+ <!-- 列表形式穿梭框 -->
3
+ <div class="TransferTable">
4
+ <div class="TransferTable__Search" v-if="searchSetting && searchSetting.length">
5
+ <Search
6
+ v-model="searchForm"
7
+ :formSetting="searchSetting"
8
+ @handleSearch="handleSearch"
9
+ @handleReset="handleReset"
10
+ />
11
+ </div>
12
+ <div class="TransferTable__Content">
13
+ <div class="TransferTable__Left">
14
+ <Table
15
+ v-bind="{
16
+ datas: listDatasA,
17
+ columns,
18
+ paginationParams: listPaginationA,
19
+ rowSelection: {
20
+ selectedRowKeys: selectedKeys,
21
+ onChange: selectedRecords,
22
+ getCheckboxProps: record => ({
23
+ props: {
24
+ disabled: isRecordDisabled(record)
25
+ }
26
+ })
27
+ }
28
+ }"
29
+ @pageSizeChange="(pagination) => (listPaginationA = pagination, onListPageAHandler())"
30
+ >
31
+ <span class="Table__Name" slot="ATableTitle">{{title}}列表</span>
32
+ <template #action="{customProps, index}">
33
+ <Button
34
+ v-for="(op, i) in operateSetting"
35
+ :key="i"
36
+ type="link"
37
+ :disabled="shouldDisableButton(op, customProps)"
38
+ @click="handleTableAction(op.code, customProps)"
39
+ >
40
+ {{ op.title }}
41
+ </Button>
42
+ </template>
43
+ </Table>
44
+ </div>
45
+
46
+ <div class="TransferTable__Right">
47
+ <Table
48
+ v-bind="{
49
+ datas: listDatasB,
50
+ columns,
51
+ paginationParams: listPaginationB,
52
+ rowSelection: {
53
+ selectedRowKeys: selectedKeys,
54
+ onChange: selectedRecords,
55
+ getCheckboxProps: record => ({
56
+ props: {
57
+ disabled: isRecordDisabled(record)
58
+ }
59
+ })
60
+ }
61
+ }"
62
+ @pageSizeChange="(pagination) => (listPaginationB = pagination, onListPageBHandler())"
63
+ >
64
+ <span class="Table__Name" slot="ATableTitle">已选{{title}}列表</span>
65
+ <template #action="{customProps, index}">
66
+ <Button
67
+ v-for="(op, i) in operateSetting"
68
+ :key="i"
69
+ type="link"
70
+ :disabled="shouldDisableButton(op, customProps)"
71
+ @click="handleTableAction(op.code, customProps)"
72
+ >
73
+ {{ op.title }}
74
+ </Button>
75
+ </template>
76
+ </Table>
77
+ </div>
78
+
79
+ </div>
80
+ </div>
81
+ </template>
82
+
83
+ <script>
84
+
85
+ import { Button } from 'ant-design-vue'
86
+ import { Search, Table } from '../index'
87
+ import { chunkArray } from '../../utils/Utils'
88
+
89
+ export default {
90
+ name: 'TransferTable',
91
+ components: {
92
+ Search,
93
+ Table,
94
+ Button
95
+ },
96
+ props: {
97
+ // 列表名称
98
+ title: {
99
+ type: String,
100
+ default: '人员'
101
+ },
102
+ // 双向绑定的已选记录
103
+ value: {
104
+ type: Array,
105
+ default: () => ([])
106
+ },
107
+ // 列表项
108
+ columns: Array,
109
+ // 支持传递额外参数
110
+ extraParams: {
111
+ type: Object,
112
+ default: () => ({})
113
+ },
114
+ // 搜索项
115
+ searchSetting: Array,
116
+ // 操作配置
117
+ operateSetting: Array,
118
+ // 分页接口(A表数据获取)
119
+ onListPageHandler: {
120
+ type: Function,
121
+ required: true
122
+ },
123
+ // 已经保存到数据库的记录ID列表
124
+ savedRecordIds: {
125
+ type: Array,
126
+ default: () => ([])
127
+ }
128
+ },
129
+ data() {
130
+ return {
131
+ // 搜索条件
132
+ searchForm: {},
133
+ selectedKeys: [],
134
+
135
+ // A表格(待选区)
136
+ listDatasA: [],
137
+ listPaginationA: {
138
+ current: 1,
139
+ size: 10,
140
+ total: 0
141
+ },
142
+
143
+ // B表格(已选区)
144
+ listDatasB: [],
145
+ listPaginationB: {
146
+ current: 1,
147
+ size: 10,
148
+ total: 0
149
+ }
150
+ }
151
+ },
152
+ computed: {
153
+ // 使用计算属性实现双向绑定
154
+ selectedRecordsB: {
155
+ get() {
156
+ return this.value
157
+ },
158
+ set(val) {
159
+ this.$emit('input', val)
160
+ }
161
+ }
162
+ },
163
+ watch: {
164
+ // 当搜索条件变化时重置左表
165
+ searchForm: {
166
+ handler() {
167
+ this.resetLeftTable()
168
+ },
169
+ deep: true
170
+ },
171
+ selectedRecordsB: {
172
+ handler() {
173
+ this.onListPageBHandler()
174
+ },
175
+ deep: true
176
+ }
177
+ },
178
+ mounted() {
179
+ this.onListPageAHandler()
180
+ },
181
+ methods: {
182
+ // 列表操作处理
183
+ handleTableAction(name, record) {
184
+ this.$postM({
185
+ name,
186
+ method: 'modalOpen',
187
+ params: record
188
+ })
189
+ },
190
+ handleReset() {
191
+ this.searchForm = {}
192
+ this.handleSearch()
193
+ },
194
+ handleSearch() {
195
+ this.listPagination = {
196
+ current: 1,
197
+ size: 10,
198
+ total: 0
199
+ }
200
+ this.onListPageHandler()
201
+ },
202
+ // 获取左侧表格数据
203
+ async onListPageAHandler() {
204
+ const params = {
205
+ ...this.listPaginationA,
206
+ ...this.extraParams,
207
+ ...this.searchForm
208
+ }
209
+ try {
210
+ const { total, records } = await this.onListPageHandler(params)
211
+ this.listDatasA = records
212
+ this.listPaginationA = {
213
+ ...this.listPaginationA,
214
+ total
215
+ }
216
+ } catch(err) {
217
+ console.error('获取待选人员失败:', err)
218
+ }
219
+ },
220
+
221
+ // 获取右侧表格数据(从已选记录中分页)
222
+ onListPageBHandler() {
223
+ try {
224
+ const chunks = chunkArray(this.selectedRecordsB, this.listPaginationB.size)
225
+ this.listDatasB = chunks[this.listPaginationB.current - 1] || []
226
+ this.listPaginationB = {
227
+ ...this.listPaginationB,
228
+ total: this.selectedRecordsB.length
229
+ }
230
+
231
+ // 同步选中状态
232
+ this.selectedKeys = this.selectedRecordsB.map(r => r.id)
233
+ } catch(err) {
234
+ console.error('更新已选列表失败:', err)
235
+ }
236
+ },
237
+
238
+ // 取消 / 选择当前行
239
+ selectedRecords(selectedKey, selectedRecord) {
240
+ const currentIds = new Set(this.selectedRecordsB.map(r => r.id))
241
+ const newIds = new Set(selectedKey)
242
+
243
+ this.selectedRecordsB = newIds.size > currentIds.size
244
+ ? [...this.selectedRecordsB, ...selectedRecord.filter(r =>
245
+ newIds.has(r.id) && !currentIds.has(r.id)
246
+ )]
247
+ : this.selectedRecordsB.filter(r => newIds.has(r.id))
248
+ },
249
+
250
+ // 重置左表到第一页
251
+ async resetLeftTable() {
252
+ this.listPaginationA.current = 1
253
+ await this.onListPageAHandler()
254
+ },
255
+
256
+ // 检查记录是否已被保存(需要禁用)
257
+ isRecordDisabled(record) {
258
+ return this.savedRecordIds.includes(record.id)
259
+ },
260
+
261
+ // 判断按钮是否应该禁用
262
+ shouldDisableButton(operation, record) {
263
+ // 如果没有设置 savedRecordIds,则不禁用任何按钮
264
+ if (!this.savedRecordIds || this.savedRecordIds.length === 0) {
265
+ return false
266
+ }
267
+
268
+ // 如果该操作明确设置为不禁用已保存记录,则返回 false
269
+ if (operation.disableSaved === false) {
270
+ return false
271
+ }
272
+
273
+ // 默认情况下,已保存的记录相关操作按钮会被禁用
274
+ return this.isRecordDisabled(record)
275
+ }
276
+ }
277
+ }
278
+ </script>
@@ -0,0 +1 @@
1
+ require('./index.less');
@@ -0,0 +1,20 @@
1
+ @import '~ant-design-vue/lib/style/themes/default.less';
2
+ @import '../../style/mixins.less';
3
+
4
+ .TransferTable {
5
+ flex: 1;
6
+ .flex-layout(column, @padding-xs 0);
7
+
8
+ &__Search {
9
+ }
10
+
11
+ &__Content {
12
+ flex: 1;
13
+ .flex-layout(@flexGap: 0 @padding-xs);
14
+ }
15
+
16
+ &__Left,
17
+ &__Right {
18
+ height: 100%;
19
+ }
20
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-component-gallery",
3
- "version": "2.2.33",
3
+ "version": "2.2.35",
4
4
  "description": "基础vue、antdvue、less实现的私有组件库",
5
5
  "main": "dist/index.umd.js",
6
6
  "files": [
package/utils/Utils.js CHANGED
@@ -2,12 +2,28 @@ import message from 'ant-design-vue/es/message'
2
2
  import { verifyIPStr } from './Validate'
3
3
  import { findNthOccurrence } from './Filter'
4
4
 
5
+
5
6
  /**
6
- * 下载文件
7
- * response: 文档流
8
- * name: 文件名称
7
+ * 数据分块工具函数
8
+ * @param {Array} arr - 源数组
9
+ * @param {number} size - 分块大小
10
+ * @returns {Array} 分块后的数组
9
11
  */
12
+ export function chunkArray(arr, size) {
13
+ const result = []
14
+ for (let i = 0; i < arr.length; i += size) {
15
+ result.push(arr.slice(i, i + size))
16
+ }
17
+ return result
18
+ }
10
19
 
20
+ /**
21
+ * 下载文件
22
+ * @param {Blob} response - 文档流
23
+ * @param {string} name - 文件名称
24
+ * @param {string} type - 文件类型
25
+ * @returns {void}
26
+ */
11
27
  export function downLoadFn( response, name, type = "application/vnd.ms-excel" ) {
12
28
 
13
29
  let reader = new FileReader()
@@ -1,57 +0,0 @@
1
- const tinycolor = require('tinycolor2')
2
-
3
- const hueStep = 2
4
- const saturationStep = 16
5
- const saturationStep2 = 5
6
- const brightnessStep1 = 5
7
- const brightnessStep2 = 15
8
- const lightColorCount = 5
9
- const darkColorCount = 4
10
-
11
- const getHue = (hsv, i, isLight) => {
12
- let hue = hsv.h >= 60 && hsv.h <= 240
13
- ? isLight ? hsv.h - hueStep * i : hsv.h + hueStep * i
14
- : isLight ? hsv.h + hueStep * i : hsv.h - hueStep * i
15
-
16
- hue < 0
17
- ? hue += 360
18
- : hue >= 360 && (hue -= 360)
19
-
20
- return Math.round(hue)
21
- }
22
-
23
- const getSaturation = (hsv, i, isLight) => {
24
- let saturation = isLight
25
- ? Math.round(hsv.s * 100) - saturationStep * i
26
- : (
27
- i === darkColorCount
28
- ? Math.round(hsv.s * 100) + saturationStep
29
- : Math.round(hsv.s * 100) + saturationStep2 * i
30
- )
31
-
32
- if (saturation > 100) saturation = 100
33
- if (isLight && i === lightColorCount && saturation > 10) saturation = 10
34
- if (saturation < 6) saturation = 6
35
-
36
- return Math.round(saturation)
37
- }
38
-
39
- const getValue = (hsv, i, isLight) => {
40
- if (isLight) return Math.round(hsv.v * 100) + brightnessStep1 * i
41
- return Math.round(hsv.v * 100) - brightnessStep2 * i
42
- }
43
-
44
- // 颜色调色板生成器
45
- module.exports = (color, index) => {
46
- const isLight = index <= 6
47
- const hsv = tinycolor(color).toHsv()
48
- const i = isLight
49
- ? lightColorCount + 1 - index
50
- : index - lightColorCount - 1
51
-
52
- return tinycolor({
53
- h: getHue(hsv, i, isLight),
54
- s: getSaturation(hsv, i, isLight),
55
- v: getValue(hsv, i, isLight)
56
- }).toHexString()
57
- }