sh-view 2.8.15 → 2.9.0

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,6 +1,6 @@
1
1
  {
2
2
  "name": "sh-view",
3
- "version": "2.8.15",
3
+ "version": "2.9.0",
4
4
  "description": "基于vxe-table二次封装,更包含Alert,Badge,Card,CodeEditor,Col,Corner,CountTo,Drawer,Empty,Form,Header,Icon,List,Loading,Modal,Noticebar,Poptip,Progress,PullRefresh,Query,Result,Row,Split,Grid,Table,Tabs,Tag,Toolbar,Tree,Upload,WaterFall,WaterMark等丰富组件库",
5
5
  "main": "packages/index.js",
6
6
  "typings": "types/index.d.ts",
@@ -32,7 +32,7 @@
32
32
  "jszip": "^3.10.1",
33
33
  "lunar-typescript": "^1.6.10",
34
34
  "popper.js": "^1.16.1",
35
- "sh-tools": "^2.2.10",
35
+ "sh-tools": "^2.2.12",
36
36
  "tinymce": "^5.10.5",
37
37
  "vue": "^3.3.4",
38
38
  "vue-masonry": "^0.16.0",
@@ -1,5 +1,5 @@
1
1
  import { computed, onBeforeMount, ref, watch } from 'vue'
2
- import { getFieldRules } from '../../sh-table/js/tableMethods'
2
+ import { formulaReplaceAll, getFieldRules } from '../../sh-table/js/tableMethods'
3
3
 
4
4
  // 表单默认配置
5
5
  const formConfigDefault = {
@@ -35,11 +35,17 @@ export default function (props, context, proxy, isForm) {
35
35
  const formRules = ref({})
36
36
 
37
37
  const formBindConfig = computed(() => {
38
+ let formulaMap = {}
39
+ $vUtils.eachTree(props.items, column => {
40
+ let rformula = $vUtils.get(column, 'renderProps.formula')
41
+ if (rformula) formulaMap[column.field] = rformula
42
+ })
38
43
  return Object.assign({ size: isForm ? 'medium' : 'small' }, formConfigDefault, props.formConfig, {
39
44
  items: formItems.value,
40
45
  data: props.data,
41
46
  rules: props.valid ? formRules.value : {},
42
- validConfig: props.validConfig
47
+ validConfig: props.validConfig,
48
+ formulaMap: formulaReplaceAll(formulaMap)
43
49
  })
44
50
  })
45
51
 
@@ -63,8 +69,8 @@ export default function (props, context, proxy, isForm) {
63
69
  }
64
70
  // 表单项编辑回调
65
71
  const onFormEditClosed = async params => {
66
- emit('edit-closed', params)
67
72
  Object.assign(props.data, params.data)
73
+ emit('edit-closed', params)
68
74
  }
69
75
  // 表单校验不通过
70
76
  const onFormSubmitInvalid = params => {
@@ -240,12 +240,10 @@ export default {
240
240
  return {}
241
241
  }
242
242
  },
243
- scrollX: {
244
- type: Object
245
- },
246
- scrollY: {
247
- type: Object
248
- },
243
+ scrollX: Object,
244
+ scrollY: Object,
245
+ params: Object,
246
+ footerData: Array,
249
247
 
250
248
  // 扩展配置
251
249
  disabled: {
@@ -171,3 +171,22 @@ export const getTransfarFields = (oriArr = [], { slots, columnObj, isSearch }) =
171
171
  })
172
172
  return { columnsArr, columnsFlatArr, formItemsArr, rules }
173
173
  }
174
+ // 递归替换嵌套依赖公式
175
+ export const formulaReplaceAll = formulaMap => {
176
+ Object.keys(formulaMap).forEach(key => {
177
+ let dowhile = true
178
+ while (dowhile) {
179
+ let regUKey = formulaMap[key].match(/\$?[a-zA-Z0-9_.]{0,}\{[A-Za-z0-9_.]{1,}\}/gi) || []
180
+ regUKey = regUKey.filter(item => item.startsWith('${') || item.startsWith('{')).map((key, keyIndex) => key.replace(/\$?{|}/gi, ''))
181
+ dowhile = !regUKey.every((keyc, indexkey) => {
182
+ if (formulaMap[keyc]) {
183
+ formulaMap[key] = formulaMap[key].replace('{' + keyc + '}', '(' + formulaMap[keyc] + ')')
184
+ return false
185
+ } else {
186
+ return true
187
+ }
188
+ })
189
+ }
190
+ })
191
+ return formulaMap
192
+ }
@@ -1,5 +1,5 @@
1
1
  import { computed, onMounted, reactive, ref, watch, nextTick } from 'vue'
2
- import { columnDefaultFilterMethod, tableFooterCompute, getTransfarFields } from './tableMethods'
2
+ import { columnDefaultFilterMethod, tableFooterCompute, getTransfarFields, formulaReplaceAll } from './tableMethods'
3
3
 
4
4
  // 记录自定义参数,传给vxe要过滤掉
5
5
  let omitProps = [
@@ -39,6 +39,7 @@ const exportAndPrintDefault = {
39
39
  isAllExpand: true,
40
40
  download: true,
41
41
  useStyle: false,
42
+ isUnit: false,
42
43
  columnFilterMethod: columnDefaultFilterMethod
43
44
  }
44
45
  const menuConfigDefault = {
@@ -129,18 +130,19 @@ export default function (props, context, proxy, isGrid) {
129
130
  return hasTree.value ? Object.assign({}, props.treeConfig) : null
130
131
  })
131
132
  const tableSeqConfig = computed(() => {
133
+ const pagerConfig = tablePagerConfig.value
134
+ const pageStart = (+pagerConfig.pageSize || 50) * ((+pagerConfig.currentPage || 1) - 1)
132
135
  return {
133
- seqMethod: ({ $table, seq, $seq, $$seq, $rowIndex }) => {
134
- const tablePage = tablePagerConfig.value.enabled
135
- if ($$seq) {
136
- return $$seq
137
- } else if (tablePage) {
138
- const pageStart = (+tablePagerConfig.value.pageSize || 50) * ((+tablePagerConfig.value.currentPage || 1) - 1)
139
- return hasTree.value && $seq ? Number(pageStart) + Number($seq) + '.' + seq : Number(pageStart) + Number(seq)
140
- } else if (hasTree.value) {
141
- return $seq ? $seq + '.' + seq : seq
136
+ seqMethod: ({ $table, seq, $rowIndex }) => {
137
+ if (pagerConfig && pagerConfig.enabled) {
138
+ if (String(seq).includes('.')) {
139
+ const seqIndex = seq.indexOf('.')
140
+ const seqStart = seq.substr(0, seqIndex)
141
+ return $vUtils.add(pageStart, seqStart) + seq.substr(seqIndex)
142
+ }
143
+ return $vUtils.add(pageStart, seq)
142
144
  }
143
- return seq === -1 ? $rowIndex + 1 : seq
145
+ return seq
144
146
  }
145
147
  }
146
148
  })
@@ -201,6 +203,11 @@ export default function (props, context, proxy, isGrid) {
201
203
  const tableBindConfig = computed(() => {
202
204
  let defaultProps = { id: `sh-table-${$route.fullPath}`, footerMethod: tableFooterMethod, footerSpanMethod: tableFooterSpanMethod }
203
205
  let tableProps = $vUtils.omit(props, (val, key) => omitProps.includes(key) || $vUtils.isNone(val))
206
+ let formulaMap = {}
207
+ $vUtils.eachTree(props.columns, column => {
208
+ let rformula = $vUtils.get(column, 'renderProps.formula')
209
+ if (rformula) formulaMap[column.field] = rformula
210
+ })
204
211
  let shProps = {
205
212
  data: tableViewData.value,
206
213
  stripe: props.stripe && !tableTreeConfig.value,
@@ -214,7 +221,8 @@ export default function (props, context, proxy, isGrid) {
214
221
  printConfig: tablePrintConfig.value,
215
222
  moneyConfig: tableMoneyConfig.value,
216
223
  moneyUnit: tableMoneyUnit.value,
217
- menuConfig: tableMenuConfig.value
224
+ menuConfig: tableMenuConfig.value,
225
+ formulaMap: formulaReplaceAll(formulaMap)
218
226
  }
219
227
  if (tableMenuConfig.value.enabled) shProps.menuConfig = tableMenuConfig.value
220
228
  return Object.assign(defaultProps, tableProps, shProps)
@@ -243,8 +251,8 @@ export default function (props, context, proxy, isGrid) {
243
251
  // 获取全部数据
244
252
  // visible为true获取视图数据
245
253
  const getFullData = params => {
246
- const { visible = false, deleteXid = false } = params || {}
247
- let fullData = tableRef.value.internalData.afterFullData
254
+ const { visible = false, deleteXid = false, datas = null } = params || {}
255
+ let fullData = datas || tableRef.value.internalData.afterFullData
248
256
  let data = $vUtils.clone(fullData, true)
249
257
  const columns = tableRef.value.getColumns()
250
258
  let rnameColumns = columns.filter(col => col.rname)
@@ -252,8 +260,14 @@ export default function (props, context, proxy, isGrid) {
252
260
  let { property, rname, rprops } = col
253
261
  data.forEach(row => {
254
262
  let cellValue = $vUtils.get(row, property)
255
- let { rvalue, rtext } = $vUtils.formatRender(cellValue, property, row, rname, rprops, proxy)
256
- $vUtils.set(row, property, visible ? rtext : rvalue)
263
+ let { rvalue, rtext } = $vUtils.formatRender(cellValue, property, row, rname, { ...rprops, commafy: false }, proxy)
264
+ if (rprops.bill && rprops.bill !== '0') {
265
+ $vUtils.set(row, property, rvalue)
266
+ } else if (visible) {
267
+ $vUtils.set(row, property, rtext)
268
+ } else {
269
+ $vUtils.set(row, property, rvalue)
270
+ }
257
271
  if (deleteXid) delete row._XID
258
272
  })
259
273
  })
@@ -262,10 +276,18 @@ export default function (props, context, proxy, isGrid) {
262
276
  // 表格打印、导出统一导出前渲染数据
263
277
  const getExportPrintDataByOption = (obj = {}, type) => {
264
278
  let { options, content } = obj
265
- let { data, columns, mode, original } = options
266
- if (!data) {
267
- options.data = mode === 'selected' ? getSelectionData() : getFullData({ visible: !original })
268
- }
279
+ let { data, columns, mode, original, isUnit } = options
280
+ let exportDatas = data
281
+ $vUtils.eachTree(columns, col => {
282
+ const { rname, rprops } = col
283
+ if (rname === '$vMoney' && isUnit && rprops.moneyOption?.label && !col.headerExportMethod && !original) {
284
+ col.headerExportMethod = () => {
285
+ return `${col.title}(${rprops.moneyOption.label})`
286
+ }
287
+ }
288
+ })
289
+ if (mode === 'selected') exportDatas = getSelectionData()
290
+ options.data = getFullData({ deleteXid: true, visible: !original, datas: exportDatas })
269
291
  return type === 'print' ? content : obj
270
292
  }
271
293
 
@@ -274,8 +296,9 @@ export default function (props, context, proxy, isGrid) {
274
296
  const { footerCalculate } = props
275
297
  let footerData = []
276
298
  let footerCalculateList = footerCalculate.calculate || []
299
+ let fullData = getFullData({ deleteXid: true, datas: data })
277
300
  footerCalculateList.forEach(computeType => {
278
- footerData.push(tableFooterCompute(columns, data, computeType, footerCalculate[computeType]))
301
+ footerData.push(tableFooterCompute(columns, fullData, computeType, footerCalculate[computeType]))
279
302
  })
280
303
  return footerData
281
304
  }
@@ -369,19 +392,6 @@ export default function (props, context, proxy, isGrid) {
369
392
  }
370
393
  // 只对 edit-config 配置时有效,单元格编辑状态下被关闭时会触发该事件
371
394
  const onEditClosed = params => {
372
- // 此操作火狐浏览器(bug(vxe):编辑后不触发渲染器的blur问题)
373
- const userAgent = navigator.userAgent
374
- if (userAgent.indexOf('Firefox') !== -1) {
375
- let { row, column } = params
376
- let editModel = $vUtils.get(column, 'params.__RowEditModelValue')
377
- if (editModel !== undefined) {
378
- if (['$vMoney'].includes(column.rname) && !$vUtils.isNone(editModel)) editModel = $vUtils.multiply(editModel, column.rprops.moneyUnit || 1)
379
- let { rvalue, rtext } = $vUtils.formatRender(editModel, column.property, row, column.rname, column.rprops, proxy, true)
380
- editModel = rvalue
381
- $vUtils.set(row, column.property, editModel)
382
- delete column.params.__RowEditModelValue
383
- }
384
- }
385
395
  emit('edit-closed', params)
386
396
  }
387
397
  // 只对 edit-config 配置时有效,单元格被激活编辑时会触发该事件
@@ -6,7 +6,7 @@
6
6
  <span v-else @click="vxeInputPrefixClick">{{ rprops.prefixText }}</span>
7
7
  </span>
8
8
  <span v-else-if="controlButton" class="control-btn before" @click="vxeControlClick(false)">-</span>
9
- <vxe-input v-model="renderValue" v-bind="rprops" :size="rsize" @change="vxeInputChange" @blur="vxeBlurCallback" @clear="vxeBlurCallback"></vxe-input>
9
+ <vxe-input v-model="renderValue" v-bind="rprops" :size="rsize" :immediate="false" @change="vxeInputChange" @blur="vxeBlurCallback" @clear="vxeBlurCallback"></vxe-input>
10
10
  <span v-if="rprops.suffixText && rform" class="suffix">
11
11
  <vxe-button v-if="suffixButton" v-bind="psButtonConfig" @click="vxeInputSuffixClick">{{ rprops.suffixText }}</vxe-button>
12
12
  <span v-else @click="vxeInputSuffixClick">{{ rprops.suffixText }}</span>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <span class="vxe-render--inner" :class="{ 'form-render': rform, 'td-render': !rform, 'td-all': rprops.bill }">
3
3
  <template v-if="redit || isEditAll">
4
- <vxe-input v-model="renderValue" type="number" v-bind="rprops" :size="rsize" @change="vxeInputChange" @blur="vxeBlurCallback" @clear="vxeBlurCallback" />
4
+ <vxe-input v-model="renderValue" type="number" v-bind="rprops" :size="rsize" :immediate="false" @change="vxeInputChange" @blur="vxeBlurCallback" @clear="vxeBlurCallback" />
5
5
  </template>
6
6
  <template v-else-if="rprops.bill">
7
7
  <template v-for="(bil, bilindex) in billGroups" :key="bilindex">
@@ -39,7 +39,7 @@ let defaultPublicProps = {
39
39
 
40
40
  // 渲染器个性化默认配置
41
41
  let defaultProps = {
42
- $vInput: { type: 'text', placeholder: '请输入', transfer: true, digits: 2, prefixType: 'text', suffixType: 'text', immediate: false },
42
+ $vInput: { type: 'text', placeholder: '请输入', transfer: true, digits: 2, prefixType: 'text', suffixType: 'text' },
43
43
  $vTextArea: { placeholder: '请输入', rows: 2, transfer: true, resize: 'none', showWordCount: true },
44
44
  $vSelect: { placeholder: '请选择', filterable: true, transfer: true, showType: 'text', tagColor: 'default', split: ',', options: [] },
45
45
  $vTree: { placeholder: '请选择', transfer: true, split: ',', nodeKey: 'id', labelField: 'label' },
@@ -73,12 +73,13 @@ const getFixedProp = (renderOpts, params) => {
73
73
  }
74
74
  })
75
75
  const contextAttrs = $grid?.context?.attrs || $table?.context?.attrs || {}
76
- if (['$vMoney'].includes(name) && contextAttrs.moneyConfig?.enabled && contextAttrs.moneyUnit && !rturnProps.bill && rturnProps.bill !== '0') {
76
+ if (['$vMoney'].includes(name) && contextAttrs.moneyConfig?.enabled && contextAttrs.moneyUnit) {
77
77
  let moneyOption = contextAttrs.moneyConfig?.options.find(item => item.value === contextAttrs.moneyUnit)
78
78
  rturnProps.moneyUnit = contextAttrs.moneyUnit
79
79
  rturnProps.moneyOption = moneyOption
80
80
  if (moneyOption && moneyOption.digits) rturnProps.digits = moneyOption.digits
81
81
  }
82
+ rturnProps.formulaMap = contextAttrs.formulaMap
82
83
  if (column) {
83
84
  column.rname = name
84
85
  column.rprops = rturnProps
@@ -27,7 +27,6 @@ export default function (props, context, proxy) {
27
27
  // 初始化数据
28
28
  const initData = () => {
29
29
  let keyValue = $vUtils.get(props.rdata, props.rkey)
30
- if (keyValue && $vUtils.isEqual(keyValue, renderValue.value)) return
31
30
  formatValueFun(keyValue)
32
31
  }
33
32
 
@@ -48,12 +47,7 @@ export default function (props, context, proxy) {
48
47
  }
49
48
  }
50
49
  // 输入框变化
51
- const vxeInputChange = async ({ value, $event }) => {
52
- // 此操作火狐浏览器(bug(vxe):编辑后不触发渲染器的blur问题)触发edit-closed,故在edit-close重新赋值
53
- if (!rform.value) {
54
- $vUtils.set(props.rparams.column, 'params.__RowEditModelValue', value)
55
- }
56
- }
50
+ const vxeInputChange = async ({ value, $event }) => {}
57
51
  // 输入框变化回调
58
52
  const vxeChangeCallBack = async ({ value, $event }) => {
59
53
  setRenderValue(value)
@@ -81,26 +75,28 @@ export default function (props, context, proxy) {
81
75
  let { rvalue, rtext } = formatValueFun(cellValue, true)
82
76
  cellValue = rvalue
83
77
  }
78
+ $vUtils.set(props.rdata, props.rkey, cellValue)
84
79
  if (rform.value) {
85
80
  let { $form } = props.rparams
86
81
  $form.context.emit('edit-closed', props.rparams)
87
82
  }
88
- $vUtils.set(props.rdata, props.rkey, cellValue)
89
83
  }
90
84
  // 格式化值formatValue
91
85
  const formatValueFun = (value, editable) => {
92
86
  if (props.rparams.type === 'footer') {
93
87
  const { items, itemIndex } = props.rparams
94
- const { moneyUnit, digits } = props.rprops
88
+ const { moneyUnit, digits, type, commafy } = props.rprops
95
89
  let footerText = items[itemIndex]
96
90
  if (props.rname === '$vMoney') footerText = $vUtils.truncate($vUtils.divide(items[itemIndex], moneyUnit), digits)
97
- if (props.rprops.commafy) footerText = $vUtils.commafy(footerText, { digits })
91
+ else if (['integer'].includes(type)) footerText = $vUtils.toInteger(footerText)
92
+ else if (['number', 'float'].includes(type)) footerText = $vUtils.truncate(footerText, digits)
93
+ if (commafy) footerText = $vUtils.commafy(footerText, { digits })
98
94
  renderValue.value = items[itemIndex]
99
95
  renderText.value = footerText
100
96
  return
101
97
  }
102
98
  const { rvalue, rtext } = $vUtils.formatRender(value, props.rkey, props.rdata, props.rname, props.rprops, proxy, editable)
103
- if (['$vMoney'].includes(props.rname)) {
99
+ if (props.rname === '$vMoney' && !props.rprops.bill && props.rprops.bill !== '0') {
104
100
  renderValue.value = rtext
105
101
  } else {
106
102
  renderValue.value = rvalue
@@ -125,12 +121,19 @@ export default function (props, context, proxy) {
125
121
 
126
122
  watch(
127
123
  () => props.rdata,
128
- () => initData(),
124
+ () => {
125
+ let keyValue = $vUtils.get(props.rdata, props.rkey)
126
+ let keyFormula = $vUtils.get(props.rprops, 'formula')
127
+ if (keyValue && $vUtils.isEqual(keyValue, renderValue.value) && !keyFormula) return
128
+ initData()
129
+ },
129
130
  { deep: true, immediate: true }
130
131
  )
131
132
  watch(
132
133
  () => props.rprops,
133
- () => initData()
134
+ () => {
135
+ initData()
136
+ }
134
137
  )
135
138
 
136
139
  return {