haiwei-ui 1.3.1 → 1.3.3

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.
@@ -58,6 +58,52 @@ Http.prototype.put = (url, params, config) => {
58
58
  return axios.put(url, params, config)
59
59
  }
60
60
 
61
+ /**
62
+ * 通用文件上传接口
63
+ * @param {string} url - 上传接口URL
64
+ * @param {File|Blob} file - 要上传的文件对象
65
+ * @param {string} [fieldName='file'] - 文件字段名称,默认为'file'
66
+ * @param {Object} [formData={}] - 额外的表单数据
67
+ * @param {Object} [config={}] - 额外的axios配置
68
+ * @returns {Promise} 返回Promise对象
69
+ * @example
70
+ * // 基本使用
71
+ * $http.upload('/api/upload', file)
72
+ *
73
+ * // 自定义字段名和额外参数
74
+ * $http.upload('/api/upload', file, 'avatar', { userId: 123 })
75
+ *
76
+ * // 完整配置
77
+ * $http.upload('/api/upload', file, 'document', { category: 'pdf' }, {
78
+ * onUploadProgress: progressEvent => {
79
+ * const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
80
+ * console.log(`上传进度: ${percentCompleted}%`)
81
+ * }
82
+ * })
83
+ */
84
+ Http.prototype.upload = (url, file, fieldName = 'file', formData = {}, config = {}) => {
85
+ // 创建FormData对象
86
+ const data = new FormData()
87
+
88
+ // 添加文件
89
+ data.append(fieldName, file)
90
+
91
+ // 添加额外的表单数据
92
+ Object.keys(formData).forEach(key => {
93
+ data.append(key, formData[key])
94
+ })
95
+
96
+ // 合并配置,设置Content-Type为multipart/form-data
97
+ const config_ = Object.assign({}, config, {
98
+ headers: {
99
+ 'Content-Type': 'multipart/form-data',
100
+ ...config.headers
101
+ }
102
+ })
103
+
104
+ return axios.post(url, data, config_)
105
+ }
106
+
61
107
  Http.prototype.download = (url, params, config) => {
62
108
  const config_ = Object.assign({ responseType: 'blob' }, config, {
63
109
  // 参数
@@ -74,17 +120,21 @@ Http.prototype.download = (url, params, config) => {
74
120
  }
75
121
 
76
122
  Http.prototype.preview = (url, params, config) => {
77
- const config_ = Object.assign({ responseType: 'blob', headers: { preview: true } }, config, {
78
- // 参数
79
- params,
80
- // 修改参数序列化方法
81
- paramsSerializer: p => {
82
- // 使用逗号分隔参数
83
- return qs.stringify(p, {
84
- allowDots: true
85
- })
123
+ const config_ = Object.assign(
124
+ { responseType: 'blob', headers: { preview: true } },
125
+ config,
126
+ {
127
+ // 参数
128
+ params,
129
+ // 修改参数序列化方法
130
+ paramsSerializer: p => {
131
+ // 使用逗号分隔参数
132
+ return qs.stringify(p, {
133
+ allowDots: true
134
+ })
135
+ }
86
136
  }
87
- })
137
+ )
88
138
  return axios.get(url, config_)
89
139
  }
90
140
 
@@ -121,12 +171,12 @@ if (!window.$http) window.$http = new Http()
121
171
 
122
172
  // 消息提醒显示时长(ms)
123
173
  const messageDuration = 1500
124
- //是否显示了账户在其他地方登录的提示框
174
+ // 是否显示了账户在其他地方登录的提示框
125
175
  let showLoginOnOtherPlaces = false
126
176
 
127
- //处理文件下载请求
177
+ // 处理文件下载请求
128
178
  const handleDownload = response => {
129
- //如果返回的是application/json,则表示返回的是json,没有要下载的问题,可能是逻辑处理失败
179
+ // 如果返回的是application/json,则表示返回的是json,没有要下载的问题,可能是逻辑处理失败
130
180
  if (response.data.type === 'application/json') {
131
181
  var reader = new FileReader()
132
182
  reader.onload = e => {
@@ -158,12 +208,12 @@ const handleDownload = response => {
158
208
  fileName = decodeURI(cd.split("''")[1])
159
209
  }
160
210
 
161
- //如果文件名不存在,则使用时间戳
211
+ // 如果文件名不存在,则使用时间戳
162
212
  if (!fileName) {
163
213
  fileName = dayjs().format('YYYYMMDDHHMMSSS')
164
214
  }
165
215
 
166
- //通过模拟a标签点击事件下载文件
216
+ // 通过模拟a标签点击事件下载文件
167
217
  const link = document.createElement('a')
168
218
  link.href = url
169
219
  link.setAttribute('download', fileName)
@@ -172,7 +222,7 @@ const handleDownload = response => {
172
222
  document.body.removeChild(link)
173
223
  }
174
224
 
175
- //刷新令牌
225
+ // 刷新令牌
176
226
  const refreshToken = () => {
177
227
  let t = token.get()
178
228
  if (t && t.refreshToken) {
@@ -279,9 +329,9 @@ export default config => {
279
329
  case 401:
280
330
  return refreshToken()
281
331
  .then(data => {
282
- //重新初始化令牌
332
+ // 重新初始化令牌
283
333
  store.commit('app/token/init', data)
284
- //重新发一起一次上次的的请求
334
+ // 重新发一起一次上次的的请求
285
335
  error.config.headers.Authorization = 'Bearer ' + data.accessToken
286
336
  return axios.request(error.config)
287
337
  })
@@ -309,7 +359,7 @@ export default config => {
309
359
  )
310
360
  break
311
361
  case 622:
312
- //单账户登录功能
362
+ // 单账户登录功能
313
363
  if (!showLoginOnOtherPlaces) {
314
364
  showLoginOnOtherPlaces = true
315
365
  MessageBox.confirm('账户已在别处登录, 请重新登录~', '提示', {
@@ -352,4 +402,4 @@ export default config => {
352
402
  return Promise.reject(error)
353
403
  }
354
404
  )
355
- }
405
+ }
@@ -1,227 +0,0 @@
1
- <template>
2
- <!--工具栏-->
3
- <section class="nm-list-querybar">
4
- <nm-form ref="normalForm" class="nm-list-querybar-normal" :model="model_" :rules="rules" :size="fontSize" :inline="true">
5
- <slot />
6
- <el-form-item v-if="!noSearch">
7
- <nm-button type="primary" @click="query" :icon="!noSearchButtonIcon ? 'search' : ''" text="查询" />
8
- </el-form-item>
9
- <el-form-item v-if="!noReset">
10
- <nm-button type="info" @click="reset" :icon="!noSearchButtonIcon ? 'refresh' : ''" text="重置" />
11
- </el-form-item>
12
- <el-form-item v-if="exportEnabled" v-nm-has="exportBtnCode">
13
- <nm-button type="primary" @click="onExport" icon="export" text="导出" />
14
- </el-form-item>
15
- <el-form-item v-if="advanced_.enabled">
16
- <nm-button ref="showAdvnacedBtn" type="warning" @click="onAdvancedClick">
17
- 高级查询
18
- <i class="el-icon--right" :class="[showAdvanced ? 'el-icon-arrow-up' : 'el-icon-arrow-down']"></i>
19
- </nm-button>
20
- </el-form-item>
21
- <!--自定义按钮插槽-->
22
- <el-form-item>
23
- <slot name="buttons" />
24
- </el-form-item>
25
- </nm-form>
26
-
27
- <!--高级查询框-->
28
- <transition name="el-zoom-in-top">
29
- <section ref="advancedBox" class="nm-list-querybar-advanced" v-if="advanced_.enabled" v-show="showAdvanced" :style="advancedStyle">
30
- <nm-box page header footer title="高级查询" icon="search">
31
- <template v-slot:toolbar>
32
- <nm-button icon="close" @click="showAdvanced = false" />
33
- </template>
34
- <!--查询条件-->
35
- <nm-form ref="advancedForm" :model="model_" :rules="rules" :label-width="advanced_.labelWidth" :inline="advanced_.inline">
36
- <slot name="advanced" />
37
- </nm-form>
38
- <template v-slot:footer>
39
- <!--查询按钮-->
40
- <nm-button type="primary" @click="query" text="查询" :icon="!noSearchButtonIcon ? 'search' : ''" />
41
- <!--重置按钮-->
42
- <nm-button type="info" @click="reset" text="重置" :icon="!noSearchButtonIcon ? 'refresh' : ''" />
43
- </template>
44
- </nm-box>
45
- <div ref="arrow" class="advanced-arrow" />
46
- </section>
47
- </transition>
48
- </section>
49
- </template>
50
- <script>
51
- const defaultAdvanced = {
52
- // 是否开启
53
- enabled: false,
54
- // 宽度
55
- width: '400px',
56
- // 高度
57
- height: '',
58
- // 表单标签宽度
59
- labelWidth: '100px',
60
- // 内联表单
61
- inline: false
62
- }
63
- export default {
64
- data() {
65
- return {
66
- // 是否显示高级查询
67
- showAdvanced: false,
68
- // 动态计算的高度
69
- dynamicHeight: ''
70
- }
71
- },
72
- props: {
73
- /** 输入框的宽度 */
74
- inputWidth: {
75
- type: String,
76
- default: '160px'
77
- },
78
- /** 查询模型 */
79
- model: Object,
80
- /** 验证规则 */
81
- rules: Object,
82
- /** 高级查询属性 */
83
- advanced: Object,
84
- /** 不显示按钮图标 */
85
- noSearchButtonIcon: Boolean,
86
- /** 不需要查询 */
87
- noSearch: Boolean,
88
- /**不显示查询按钮 */
89
- noReset: Boolean,
90
- /**显示导出按钮 */
91
- exportEnabled: Boolean,
92
- /**导出按钮权限编码 */
93
- exportBtnCode: String
94
- },
95
- computed: {
96
- model_() {
97
- return this.model || {}
98
- },
99
- /** 高级查询设置 */
100
- advanced_() {
101
- const ad = this.$_.merge({}, defaultAdvanced, this.advanced)
102
- ad.enabled = ad.enabled && !this.noSearch
103
- return ad
104
- },
105
- /** 高级查询框样式 */
106
- advancedStyle() {
107
- return {
108
- width: this.advanced_.width,
109
- height: this.advanced_.height || this.dynamicHeight
110
- }
111
- }
112
- },
113
- methods: {
114
- query() {
115
- this.$parent.page.index = 1
116
- this.$parent.query()
117
- // 如果高级查询框显示,重新计算高度
118
- if (this.showAdvanced && !this.advanced_.height) {
119
- this.$nextTick(() => {
120
- this.calculateAdvancedHeight()
121
- })
122
- }
123
- },
124
- /** 表单重置 */
125
- reset() {
126
- if (this.$refs.normalForm) {
127
- this.$refs.normalForm.reset()
128
- }
129
- if (this.$refs.advancedForm) {
130
- this.$refs.advancedForm.reset()
131
- }
132
- this.$emit('reset')
133
- },
134
- validate(action) {
135
- return this.$refs.normalForm.validate(action)
136
- },
137
- /** 计算高级查询框高度 */
138
- calculateAdvancedHeight() {
139
- if (!this.$refs.advancedBox) return
140
-
141
- const $box = this.$refs.advancedBox
142
- const boxHeader = $box.querySelector('.nm-box-header')?.offsetHeight || 0
143
- const boxFooter = $box.querySelector('.nm-box-footer')?.offsetHeight || 0
144
- const form = $box.querySelector('.nm-form')
145
- if (!form) return
146
-
147
- let boxHeight = form.offsetHeight + boxHeader + boxFooter + 20
148
- if (!this.advanced_.inline) {
149
- boxHeight += 20
150
- }
151
- $box.style.height = boxHeight + 'px'
152
- // 保存动态计算的高度,避免后续样式被覆盖
153
- this.dynamicHeight = boxHeight + 'px'
154
- },
155
-
156
- /** 高级查询按钮点击事件 */
157
- onAdvancedClick() {
158
- this.showAdvanced = !this.showAdvanced
159
-
160
- if (this.showAdvanced) {
161
- this.$nextTick(() => {
162
- let $box = this.$refs.advancedBox
163
- let $arrow = this.$refs.arrow
164
- const boxWidth = $box.offsetWidth
165
- const { x, y, width, height } = this.$refs.showAdvnacedBtn.$el.getBoundingClientRect()
166
- let left = x + width / 2 - $box.offsetWidth / 2
167
- // 判断右侧有没有超出页面
168
- if (left + boxWidth > document.body.offsetWidth) {
169
- left = document.body.offsetWidth - boxWidth - 20
170
- // 计算箭头的位置
171
- $arrow.style.left = x - left - 10 + width / 2 + 'px'
172
- } else {
173
- // 计算箭头的位置
174
- $arrow.style.left = $box.offsetWidth / 2 + 'px'
175
- }
176
-
177
- $box.style.left = left + 'px'
178
- $box.style.top = y + height + 14 + 'px'
179
-
180
- // 设置高度
181
- if (!this.advanced_.height) {
182
- this.calculateAdvancedHeight()
183
- }
184
- })
185
- }
186
- },
187
- onExport() {
188
- this.$parent.triggerExport()
189
- },
190
- /** 设置输入框宽度 */
191
- setInputWidths(formRef) {
192
- if (!this.inputWidth || !formRef || !formRef.$el) return
193
-
194
- let inputs = formRef.$el.querySelectorAll('.el-input__inner')
195
- if (inputs) {
196
- for (let i = 0; i < inputs.length; i++) {
197
- const input = inputs[i]
198
- // 检查是否有data-width属性,如果有则使用该值,否则使用inputWidth
199
- const customWidth = input.getAttribute('data-width')
200
- input.style.width = customWidth || this.inputWidth
201
- }
202
- }
203
- }
204
- },
205
- mounted() {
206
- this.$nextTick(() => {
207
- this.$refs.normalForm.$el.addEventListener('keydown', e => {
208
- if (e.keyCode === 13) {
209
- this.query()
210
- }
211
- })
212
- // 设置普通查询栏输入框宽度
213
- this.setInputWidths(this.$refs.normalForm)
214
- })
215
- },
216
- watch: {
217
- showAdvanced(newVal) {
218
- if (newVal && this.$refs.advancedForm) {
219
- // 高级查询框显示时,设置其中的输入框宽度
220
- this.$nextTick(() => {
221
- this.setInputWidths(this.$refs.advancedForm)
222
- })
223
- }
224
- }
225
- }
226
- }
227
- </script>