sh-view 1.7.5 → 1.7.6

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,257 @@
1
+ // 上传组件通用方法
2
+
3
+ import ajax from './ajax'
4
+
5
+ export default {
6
+ props: {
7
+ modelValue: {
8
+ type: Array,
9
+ default() {
10
+ return []
11
+ }
12
+ },
13
+ action: {
14
+ type: String,
15
+ default: 'fileservice/v2/upload'
16
+ },
17
+ headers: {
18
+ type: Object,
19
+ default() {
20
+ return {}
21
+ }
22
+ },
23
+ disabled: {
24
+ type: Boolean,
25
+ default: false
26
+ },
27
+ maxSize: {
28
+ type: Number,
29
+ default: 1024 * 2 // 文件大小限制,单位 kb
30
+ },
31
+ accept: {
32
+ type: String,
33
+ default: '.doc,.docx,.xls,.xlsx,.txt,.pdf,.jpg,.jpeg,.png,.txt,.7z,.zip,.rar'
34
+ },
35
+ name: {
36
+ type: String,
37
+ default: 'file'
38
+ },
39
+ beforeUpload: {
40
+ type: Function
41
+ },
42
+ webkitdirectory: {
43
+ type: Boolean,
44
+ default: false // 是否开启选择文件夹,部分浏览器适用
45
+ },
46
+ withCredentials: {
47
+ type: Boolean,
48
+ default: false // 支持发送 cookie 凭证信息
49
+ },
50
+ paste: {
51
+ type: Boolean,
52
+ default: false // 是否支持粘贴上传文件
53
+ },
54
+ format: {
55
+ type: Array,
56
+ default() {
57
+ return []
58
+ }
59
+ },
60
+ onFormatError: {
61
+ type: Function
62
+ },
63
+ onExceededSize: {
64
+ type: Function
65
+ },
66
+ onProgress: {
67
+ type: Function,
68
+ default() {}
69
+ },
70
+ onSuccess: {
71
+ type: Function,
72
+ default() {}
73
+ },
74
+ onError: {
75
+ type: Function,
76
+ default() {}
77
+ },
78
+ onRemove: {
79
+ type: Function,
80
+ default() {}
81
+ },
82
+ onPreview: {
83
+ type: Function,
84
+ default() {}
85
+ },
86
+ onDownload: {
87
+ type: Function,
88
+ default() {}
89
+ }
90
+ },
91
+ data() {
92
+ return {
93
+ tempIndex: 1,
94
+ dragOver: false,
95
+ fileList: []
96
+ }
97
+ },
98
+ methods: {
99
+ progressConfig(file) {
100
+ return {
101
+ textInside: true,
102
+ strokeWidth: 20,
103
+ percent: parseInt(file.percentage, 10),
104
+ status: file.status
105
+ }
106
+ },
107
+ handleClick() {
108
+ if (this.disabled) return
109
+ this.$refs.input.click()
110
+ },
111
+ handleChange(e) {
112
+ const files = e.target.files
113
+ if (!files) return
114
+ this.uploadFiles(files)
115
+ this.$refs.input.value = null
116
+ },
117
+ handleStart(file) {
118
+ file.uid = Date.now() + this.tempIndex++
119
+ const _file = {
120
+ status: 'active',
121
+ name: file.name,
122
+ size: file.size,
123
+ percentage: 0,
124
+ uid: file.uid,
125
+ showProgress: true
126
+ }
127
+ this.fileList.push(_file)
128
+ },
129
+ handlePaste(e) {
130
+ if (this.disabled) return
131
+ if (this.paste) {
132
+ this.uploadFiles(e.clipboardData.files)
133
+ }
134
+ },
135
+ handleProgress(e, file) {
136
+ const _file = this.getFile(file)
137
+ this.onProgress(e, _file, this.fileList)
138
+ _file.percentage = e.percent || 0
139
+ },
140
+ handleSuccess(res, file) {
141
+ const _file = this.getFile(file)
142
+ if (_file) {
143
+ _file.status = 'success'
144
+ _file.response = res
145
+ this.emitValue()
146
+ this.onSuccess(res, _file, this.fileList)
147
+ setTimeout(() => {
148
+ _file.showProgress = false
149
+ }, 1000)
150
+ }
151
+ },
152
+ handleError(err, response, file) {
153
+ const _file = this.getFile(file)
154
+ const fileList = this.fileList
155
+ _file.status = 'wrong'
156
+ fileList.splice(fileList.indexOf(_file), 1)
157
+ this.onError(err, response, file)
158
+ },
159
+ handleRemove(file) {
160
+ const fileList = this.fileList
161
+ fileList.splice(fileList.indexOf(file), 1)
162
+ this.emitValue()
163
+ this.onRemove(file, fileList)
164
+ },
165
+ handlePreview(file) {
166
+ const fileList = this.fileList
167
+ fileList.splice(fileList.indexOf(file), 1)
168
+ this.onRemove(file, fileList)
169
+ },
170
+ handleDownload(file) {
171
+ const fileList = this.fileList
172
+ fileList.splice(fileList.indexOf(file), 1)
173
+ this.onDownload(file, fileList)
174
+ },
175
+ onDrop(e) {
176
+ this.dragOver = false
177
+ if (this.disabled) return
178
+ this.uploadFiles(e.dataTransfer.files)
179
+ },
180
+ uploadFiles(files) {
181
+ let postFiles = Array.prototype.slice.call(files)
182
+ if (!this.multiple) postFiles = postFiles.slice(0, 1)
183
+ if (postFiles.length === 0) return
184
+ postFiles.forEach(file => {
185
+ this.upload(file)
186
+ })
187
+ },
188
+ upload(file) {
189
+ if (!this.beforeUpload) {
190
+ return this.post(file)
191
+ }
192
+ const before = this.beforeUpload(file)
193
+ if (before && before.then) {
194
+ before.then(processedFile => {
195
+ if (Object.prototype.toString.call(processedFile) === '[object File]') {
196
+ this.post(processedFile)
197
+ } else {
198
+ this.post(file)
199
+ }
200
+ })
201
+ } else if (before !== false) {
202
+ this.post(file)
203
+ }
204
+ },
205
+ async post(file) {
206
+ let { headers, name, params, action, withCredentials } = this
207
+ if (this.validateFile) {
208
+ let valResult = this.validateFile(file)
209
+ if (!valResult) return
210
+ }
211
+ this.handleStart(file)
212
+ ajax({
213
+ headers: headers,
214
+ withCredentials: withCredentials,
215
+ file: file,
216
+ data: params,
217
+ filename: name,
218
+ action: action,
219
+ onProgress: e => {
220
+ this.handleProgress(e, file)
221
+ },
222
+ onSuccess: res => {
223
+ this.handleSuccess(res, file)
224
+ },
225
+ onError: (err, response) => {
226
+ this.handleError(err, response, file)
227
+ }
228
+ })
229
+ },
230
+ getFile(file) {
231
+ const fileList = this.fileList
232
+ let target
233
+ fileList.every(item => {
234
+ target = file.uid === item.uid ? item : null
235
+ return !target
236
+ })
237
+ return target
238
+ },
239
+ clearFiles() {
240
+ this.fileList = []
241
+ this.emitValue()
242
+ },
243
+ emitValue() {
244
+ let list = this.getModelValue ? this.getModelValue() : this.fileList
245
+ this.$emit('update:modelValue', list)
246
+ }
247
+ },
248
+ watch: {
249
+ modelValue: {
250
+ handler(fileList) {
251
+ this.fileList = fileList
252
+ },
253
+ immediate: true,
254
+ deep: true
255
+ }
256
+ }
257
+ }
@@ -51,38 +51,34 @@ const shMethods = {
51
51
  // 初始化
52
52
  initCreated() {
53
53
  this.initFormItems()
54
- this.initFormData()
55
54
  },
56
55
  // 初始化表单字段
57
56
  initFormData() {
58
- const that = this
59
- that.$vUtils.eachTree(that.items, item => {
57
+ const { items, data, $vUtils } = this
58
+ $vUtils.eachTree(items, item => {
60
59
  let renderProps = item.renderProps || item.itemRender?.props || {}
61
- if (!that.$vUtils.isNone(renderProps?.defaultValue) && that.$vUtils.isNone(that.$vUtils.get(that.data, item.field))) {
62
- that.$vUtils.set(that.data, item.field, renderProps.defaultValue || null)
60
+ if (!$vUtils.isNone(renderProps?.defaultValue) && $vUtils.isNone($vUtils.get(data, item.field))) {
61
+ $vUtils.set(data, item.field, renderProps.defaultValue)
63
62
  }
64
63
  })
65
64
  },
66
65
  // 初始化表单项
67
66
  initFormItems(items) {
68
- const that = this
69
- let originItems = items || that.items
70
- let formItemsArr = [] // 表单项
71
- let rules = {} // 校验规则
72
- that.generateFormItem(originItems, formItemsArr, rules)
73
- that.initEditRules(rules)
74
- that.formItems = formItemsArr
67
+ let originItems = items || this.items
68
+ let { formItemsArr, rules } = this.generateFormItem(originItems)
69
+ this.initEditRules(rules)
70
+ this.formItems = formItemsArr
75
71
  this.initFormData()
76
72
  },
77
73
  // 初始化验证规则
78
74
  initEditRules(rules) {
79
- const that = this
80
- if (rules && that.$vUtils.isPlainObject(rules)) {
75
+ const { formRules, $vUtils } = this
76
+ if (rules && $vUtils.isPlainObject(rules)) {
81
77
  Object.keys(rules).forEach(key => {
82
- if (that.formRules[key]) {
83
- that.formRules[key] = Array.from(new Set(that.formRules[key].concat(rules[key])))
78
+ if (formRules[key]) {
79
+ formRules[key] = Array.from(new Set(formRules[key].concat(rules[key])))
84
80
  } else {
85
- that.formRules[key] = rules[key]
81
+ formRules[key] = rules[key]
86
82
  }
87
83
  })
88
84
  }
@@ -102,64 +98,55 @@ const shMethods = {
102
98
  isTrue(value) {
103
99
  return String(value) === '1' || String(value).toLowerCase() === 'true'
104
100
  },
105
- // 生成全表头
106
- generateColumnsAll(columns, resultColumns = []) {
107
- columns.forEach((column, index) => {
108
- if (column.children && Array.isArray(column.children) && column.children.length) {
109
- this.generateColumnsAll(column.children, resultColumns)
110
- } else {
111
- resultColumns.push(column)
112
- }
113
- })
114
- return resultColumns
115
- },
116
101
  // 自动生成表单渲染项
117
- generateFormItem(formItems = [], itemArr = [], rules = {}) {
118
- const that = this
119
- formItems.forEach(ori => {
120
- let tar = Object.assign({}, that.itemConfigDefault, ori)
102
+ generateFormItem(items = []) {
103
+ const { itemConfigDefault, isItemTitle, titleConfigDefault, readonly, disabled, isTrue, getDefaultMessage, $vUtils } = this
104
+ let formItemsArr = []
105
+ let rules = {}
106
+ $vUtils.eachTree(items, ori => {
107
+ let tar = Object.assign({}, itemConfigDefault, ori)
121
108
  if (ori.children && ori.children.length > 0) {
122
109
  let childrenArr = []
123
- that.generateFormItem(ori.children, childrenArr, rules)
124
- if (that.isItemTitle) {
110
+ if (isItemTitle) {
125
111
  // 补入标题渲染器
126
- let groupTitleRender = Object.assign({}, that.titleConfigDefault, tar, { span: 24, field: '' })
112
+ let groupTitleRender = Object.assign({}, titleConfigDefault, tar, { span: 24, field: '' })
127
113
  delete groupTitleRender.children
128
114
  childrenArr.unshift(groupTitleRender)
129
115
  }
130
116
  tar.children = childrenArr
131
117
  if (!tar.span) tar.span = 24
132
- itemArr.push(tar)
118
+ formItemsArr.push(tar)
133
119
  } else {
134
120
  let renderConfig = {
135
121
  name: ori.renderName || '$vInput',
136
122
  props: Object.assign({}, ori.renderProps || {})
137
123
  }
138
- if (that.readonly || that.disabled) {
124
+ if (readonly || disabled) {
139
125
  renderConfig.props.disabled = true
140
126
  }
141
127
  tar.itemRender = Object.assign({}, renderConfig, ori.itemRender || {})
142
128
  // 首先提取校验配置
143
- if (that.isTrue(ori['renderRequire'])) {
129
+ if (isTrue(ori['renderRequire'])) {
144
130
  // 若配置了校验参数则走校验参数,没配置则给默认校验条件
145
131
  if (ori['requireProps'] && Array.isArray(ori['requireProps']) && ori['requireProps'].length > 0) {
146
132
  rules[ori['field']] = ori['requireProps']
147
133
  } else {
148
134
  let dataType = 'string'
149
135
  let arrayType = ['$vCheckgroup', '$vUpload', '$vTable']
150
- if (arrayType.includes(ori['renderName']) || ((ori['renderName'] === '$vSelect' || ori['renderName'] === '$vTree') && that.isTrue(renderConfig.props.multiple))) {
136
+ if (arrayType.includes(ori['renderName']) || ((ori['renderName'] === '$vSelect' || ori['renderName'] === '$vTree') && isTrue(renderConfig.props.multiple))) {
151
137
  dataType = 'array'
152
138
  }
153
- rules[ori['field']] = [{ required: true, message: that.getDefaultMessage(ori['renderName'], ori['title']), type: dataType }]
139
+ rules[ori['field']] = [{ required: true, message: getDefaultMessage(ori['renderName'], ori['title']), type: dataType }]
154
140
  }
155
141
  }
156
142
  // 表单不支持编辑渲染过滤
157
143
  let notRenderName = ['seq', 'checkbox', 'radio', '$vImg', '$vHref', '$vGlobalOption']
158
144
  if (!((ori.renderName && notRenderName.includes(ori.renderName)) || notRenderName.includes(ori.type))) {
159
- itemArr.push(tar)
145
+ formItemsArr.push(tar)
160
146
  }
161
147
  }
162
148
  })
149
+ return { formItemsArr, rules }
163
150
  }
164
151
  }
165
152
 
@@ -1,16 +1,23 @@
1
1
  <template>
2
2
  <div class="sh-list">
3
3
  <template v-if="$slots.header"><slot name="header"></slot></template>
4
- <vxe-list ref="vxeList" :data="dataSourse" :size="size" :class-name="className" :loading="loading" :height="height" :auto-resize="autoResize" :sync-resize="syncResize" :scroll-y="scrollY">
4
+ <vxe-list ref="vxeList" v-bind="listConfig">
5
5
  <template #default="{ items }">
6
6
  <sh-empty v-if="items.length === 0 && !loading" :no-data-icon="noDataIcon" :no-data-text="noDataText"></sh-empty>
7
- <Row :gutter="grid.gutter">
7
+ <Row v-if="grid" :gutter="grid.gutter">
8
8
  <Col v-for="(item, itemindex) in items" :key="itemindex" v-bind="grid">
9
9
  <div class="sh-list-item" :class="itemClassName">
10
- <slot name="item" :item="item"></slot>
10
+ <slot name="item" v-bind="item"></slot>
11
11
  </div>
12
12
  </Col>
13
13
  </Row>
14
+ <template v-else>
15
+ <template v-for="(item, itemindex) in items" :key="itemindex">
16
+ <div class="sh-list-item" :class="itemClassName">
17
+ <slot name="item" v-bind="item"></slot>
18
+ </div>
19
+ </template>
20
+ </template>
14
21
  </template>
15
22
  </vxe-list>
16
23
  <template v-if="$slots.footer"><slot name="footer"></slot></template>
@@ -67,7 +74,7 @@ export default {
67
74
  type: String
68
75
  },
69
76
  grid: {
70
- type: Object,
77
+ type: [Object, Boolean],
71
78
  default() {
72
79
  return { gutter: 0, span: 24 }
73
80
  }
@@ -84,7 +91,20 @@ export default {
84
91
  listPagerConfig: {}
85
92
  }
86
93
  },
87
- computed: {},
94
+ computed: {
95
+ listConfig() {
96
+ return {
97
+ data: this.dataSourse,
98
+ size: this.size,
99
+ className: this.className,
100
+ loading: this.loading,
101
+ height: this.height,
102
+ autoResize: this.autoResize,
103
+ syncResize: this.syncResize,
104
+ scrollY: this.scrollY
105
+ }
106
+ }
107
+ },
88
108
  watch: {
89
109
  pagerConfig: {
90
110
  handler(newvalue, oldValue) {
@@ -7,7 +7,7 @@
7
7
  v-bind="queryFormConfig"
8
8
  :items="formItems"
9
9
  :data="data"
10
- :rules="rules"
10
+ :rules="valid ? formRules : {}"
11
11
  :valid-config="validConfig"
12
12
  @submit="onFormSubmit"
13
13
  @reset="onFormReset"
@@ -88,6 +88,9 @@ export default {
88
88
  transformitem: {
89
89
  type: Boolean,
90
90
  default: true
91
+ },
92
+ valid: {
93
+ type: Boolean
91
94
  }
92
95
  },
93
96
  emits: ['submit', 'reset', 'edit-closed', 'submit-invalid', 'collapsed'],
@@ -103,6 +106,8 @@ export default {
103
106
  formOriginItems: [],
104
107
  // 表单渲染项
105
108
  formItems: [],
109
+ // 表单校验规则
110
+ formRules: {},
106
111
  // 表格高级搜索默认配置
107
112
  formConfigDefault: {
108
113
  titleWidth: 100,
@@ -138,6 +143,13 @@ export default {
138
143
  },
139
144
  deep: true,
140
145
  immediate: false
146
+ },
147
+ rules: {
148
+ handler(newvalue, oldValue) {
149
+ this.initEditRules(newvalue)
150
+ },
151
+ deep: true,
152
+ immediate: true
141
153
  }
142
154
  },
143
155
  created() {
@@ -153,54 +165,66 @@ export default {
153
165
  },
154
166
  // 初始化表单字段
155
167
  initFormData() {
156
- const that = this
157
- let formItems = that.items.filter(item => item.search && item.search !== '0')
158
- that.$vUtils.eachTree(formItems, item => {
168
+ const { items, data, $vUtils } = this
169
+ let queryItems = items.filter(item => item.search && item.search !== '0')
170
+ $vUtils.eachTree(queryItems, item => {
159
171
  let renderProps = item.renderProps || item.itemRender?.props || {}
160
- if (!that.$vUtils.has(that.data, item.field)) {
161
- that.$vUtils.set(that.data, item.field, renderProps.defaultValue || null)
172
+ if (!$vUtils.isNone(renderProps?.defaultValue) && $vUtils.isNone($vUtils.get(data, item.field))) {
173
+ $vUtils.set(data, item.field, renderProps.defaultValue)
162
174
  }
163
175
  })
164
176
  },
165
177
  // 初始化搜索表单
166
178
  initFormItems() {
167
- const that = this
168
179
  let formItemsArr = [] // 表单项
169
- let formItems = that.items.filter(item => item.search && item.search !== '0')
180
+ let formItems = this.items.filter(item => item.search && item.search !== '0')
170
181
  if (this.transformitem) {
171
- let { itemsArr, itemsRules } = that.generateFormItem(formItems)
182
+ let { itemsArr, rules } = this.generateFormItem(formItems)
172
183
  formItemsArr = itemsArr
184
+ this.initEditRules(rules)
173
185
  } else {
174
186
  formItemsArr = formItems
187
+ this.initEditRules(this.rules)
175
188
  }
176
189
  formItemsArr.forEach(item => {
177
190
  item.visible = true
178
191
  item.itemRender.props.disabled = false
179
192
  })
180
- that.formOriginItems = formItemsArr
181
- that.formItems = formItemsArr
182
- if (formItemsArr.length > that.globalConfig.formToggleNum && that.globalConfig.formToggle) {
183
- that.formToggleBtnShow = true // 显示展开全部按钮
184
- that.formBtnCollapsed(false)
193
+ this.formOriginItems = formItemsArr
194
+ this.formItems = formItemsArr
195
+ if (formItemsArr.length > this.globalConfig.formToggleNum && this.globalConfig.formToggle) {
196
+ this.formToggleBtnShow = true // 显示展开全部按钮
197
+ this.formBtnCollapsed(false)
185
198
  }
186
199
  this.initFormData()
187
200
  },
201
+ // 初始化验证规则
202
+ initEditRules(rules) {
203
+ const { formRules, $vUtils } = this
204
+ if (rules && $vUtils.isPlainObject(rules)) {
205
+ Object.keys(rules).forEach(key => {
206
+ if (formRules[key]) {
207
+ formRules[key] = Array.from(new Set(formRules[key].concat(rules[key])))
208
+ } else {
209
+ formRules[key] = rules[key]
210
+ }
211
+ })
212
+ }
213
+ },
188
214
  // 表单展开全部/收起切换事件
189
215
  formBtnCollapsed(value) {
190
- const that = this
191
- that.formCollapsed = value
192
- that.formItems = value ? that.formOriginItems : that.formOriginItems.slice(0, that.globalConfig.formToggleNum)
216
+ this.formCollapsed = value
217
+ this.formItems = value ? this.formOriginItems : this.formOriginItems.slice(0, this.globalConfig.formToggleNum)
193
218
  this.$emit('collapsed', value)
194
219
  },
195
220
  // -------- 搜索
196
221
  async onFormSubmit() {
197
- let that = this
198
- let errMap = await that.queryFormRef().validate()
199
- let data = that.data
222
+ let { data } = this
223
+ let errMap = await this.queryFormRef().validate()
200
224
  if (!errMap) {
201
- that.$emit('submit', data)
225
+ this.$emit('submit', data)
202
226
  } else {
203
- that.onFormSubmitInvalid({ data, errMap })
227
+ this.onFormSubmitInvalid({ data, errMap })
204
228
  }
205
229
  },
206
230
  // 表单重置
@@ -223,31 +247,31 @@ export default {
223
247
  },
224
248
  // 自动生成表单渲染项
225
249
  generateFormItem(items = []) {
226
- const that = this
227
250
  let itemsArr = []
228
- let itemsRules = {}
229
- that.$vUtils.mapTree(items, ori => {
230
- let tar = Object.assign({}, that.itemConfigDefault, ori)
251
+ let rules = {}
252
+ const { itemConfigDefault, readonly, disabled, isTrue, getDefaultMessage, $vUtils } = this
253
+ $vUtils.eachTree(items, ori => {
254
+ let tar = Object.assign({}, itemConfigDefault, ori)
231
255
  let renderConfig = {
232
256
  name: ori.renderName || '$vInput',
233
257
  props: Object.assign({}, ori.renderProps || {})
234
258
  }
235
- if (that.readonly || that.disabled) {
259
+ if (readonly || disabled) {
236
260
  renderConfig.props.disabled = true
237
261
  }
238
262
  tar.itemRender = Object.assign({}, renderConfig, ori.itemRender || {})
239
263
  // 首先提取校验配置
240
- if (that.isTrue(ori['renderRequire'])) {
264
+ if (isTrue(ori['renderRequire'])) {
241
265
  // 若配置了校验参数则走校验参数,没配置则给默认校验条件
242
266
  if (ori['requireProps'] && Array.isArray(ori['requireProps']) && ori['requireProps'].length > 0) {
243
- itemsRules[ori['field']] = ori['requireProps']
267
+ rules[ori['field']] = ori['requireProps']
244
268
  } else {
245
269
  let dataType = 'string'
246
270
  let arrayType = ['$vCheckgroup', '$vUpload', '$vTable']
247
- if (arrayType.includes(ori['renderName']) || ((ori['renderName'] === '$vSelect' || ori['renderName'] === '$vTree') && that.isTrue(renderConfig.props.multiple))) {
271
+ if (arrayType.includes(ori['renderName']) || ((ori['renderName'] === '$vSelect' || ori['renderName'] === '$vTree') && isTrue(renderConfig.props.multiple))) {
248
272
  dataType = 'array'
249
273
  }
250
- itemsRules[ori['field']] = [{ required: true, message: that.getDefaultMessage(ori['renderName'], ori['title']), type: dataType }]
274
+ rules[ori['field']] = [{ required: true, message: getDefaultMessage(ori['renderName'], ori['title']), type: dataType }]
251
275
  }
252
276
  }
253
277
  // 表单不支持编辑渲染过滤
@@ -256,7 +280,7 @@ export default {
256
280
  itemsArr.push(tar)
257
281
  }
258
282
  })
259
- return { itemsArr, itemsRules }
283
+ return { itemsArr, rules }
260
284
  }
261
285
  }
262
286
  }