el-plus-crud 0.0.97 → 0.0.99

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.
@@ -6,7 +6,14 @@
6
6
  <el-row :gutter="10" v-for="(formList, index) in attrMapToTableList" :key="index" :style="{ marginRight: isTable ? '20px' : 0 }">
7
7
  <el-col v-for="(formItem, y) in formList" :key="index + '-' + y + '-' + formItem.field" :xs="24" :sm="24" :md="formItem.colspan && formItem.colspan >= column ? 24 : column >= 2 ? 12 : 24" :lg="formItem.colspan && formItem.colspan >= column ? 24 : Math.floor((24 / column) * (formItem.colspan || 1))" :xl="formItem.colspan && formItem.colspan >= column ? 24 : Math.floor((24 / column) * (formItem.colspan || 1))">
8
8
  <div v-if="formItem._vif" class="el-plus-form-column-panel" :style="{ 'justify-content': isTable ? 'flex-end' : 'flex-start' }">
9
- <el-form-item style="min-height: 40px; display: flex" :label="showLabel && formItem.showLabel !== false ? formItem._label : null" :label-width="formItem.labelWidth || labelWidth || (isDialog ? '100px' : '120px')" :prop="formItem.field" :style="{ width: formItem._attrs?.width || formItem.width || (isTable ? '150px' : '100%') }">
9
+ <el-form-item style="min-height: 40px; display: flex" :prop="formItem.field" :style="{ width: formItem._attrs?.width || formItem.width || (isTable ? '150px' : '100%') }">
10
+ <template #label>
11
+ <div v-if="showLabel && formItem.showLabel !== false" class="crud-form-label" :style="{ width: formItem.labelWidth || computedFormAttrs._labelWidth || (isDialog ? '100px' : '120px') }">
12
+ <span :class="{ required: formItem.required }">
13
+ {{ formItem._label }}
14
+ </span>
15
+ </div>
16
+ </template>
10
17
  <component style="min-width: 80px; width: 100%; flex: 1" :is="formItem._type" :formData="props.modelValue" :disabled="formItem._disabled ?? disabled ?? false" v-bind="formItem._attrs" :desc="formItem" :ref="setComponentRef" :field="formItem.field" v-model="props.modelValue[formItem.field || '']" :isTable="isTable" @validateThis="() => handelValidateThis(formItem.field || '')"></component>
11
18
  <div class="el-plus-form-tip" v-if="formItem._tip" v-html="formItem._tip" />
12
19
  </el-form-item>
@@ -38,7 +45,7 @@ export default {
38
45
  }
39
46
  </script>
40
47
  <script lang="ts" setup>
41
- import { ref, computed, useAttrs, nextTick, onMounted, watch, inject } from 'vue'
48
+ import { ref, computed, useAttrs, nextTick, onMounted, watch, inject, Ref } from 'vue'
42
49
  import { castArray, isMobile, time, cloneDeep, throttle, isPromiseLike } from './util'
43
50
  import * as validates from './util/validate'
44
51
  import { typeList } from './components/index'
@@ -185,7 +192,7 @@ const formLayout = computed(() => ({ display: 'flex', flexDirection: props.isTab
185
192
  const computedFormAttrs = computed(() => {
186
193
  return {
187
194
  ...props.formAttrs,
188
- labelWidth: props.labelWidth === 'auto' ? (props.isDialog ? '100px' : '120px') : parseInt(props.labelWidth + '') + 'px',
195
+ _labelWidth: props.labelWidth === 'auto' ? (props.isDialog ? '100px' : '120px') : parseInt(props.labelWidth + '') + 'px',
189
196
  // validateOnRuleChange: false,
190
197
  disabled: props.disabled || innerIsLoading.value,
191
198
  rules: computedRules,
@@ -205,7 +212,7 @@ const computedRules = computed(() => {
205
212
  if (props.formDesc) {
206
213
  Object.keys(props.formDesc).map((field: any) => {
207
214
  if (!tempRules[field]) tempRules[field] = []
208
- let required = false as boolean | ((data?: any) => boolean)
215
+ let required = false as boolean | ((data?: any) => boolean) | Ref<boolean>
209
216
  if (props.formDesc && props.formDesc[field]) {
210
217
  required = (props.formDesc && props.formDesc[field].required) || false
211
218
  }
@@ -223,6 +230,11 @@ const computedRules = computed(() => {
223
230
  tempRules[field].push(item)
224
231
  })
225
232
  }
233
+ // 这里判断一下rules中是否有required
234
+ if (tempRules[field].find((item: any) => item.required)) {
235
+ // 设置必填
236
+ props.formDesc[field].required = true
237
+ }
226
238
  } else if (required) {
227
239
  let rules = 'notAllBlank'
228
240
  switch (props.formDesc[field].type) {
@@ -820,10 +832,26 @@ defineExpose({ fid: props.fid, submit: handleSubmitForm, getData: getFormData, v
820
832
  .el-plus-form-column-panel {
821
833
  & > .el-form-item--default {
822
834
  margin-bottom: 18px !important;
835
+ // & > .el-form-item__label-wrap {
823
836
  & > .el-form-item__label {
824
837
  line-height: 40px;
825
838
  margin-bottom: 0;
839
+ width: auto !important;
840
+ &::before {
841
+ content: '' !important;
842
+ }
843
+ .crud-form-label {
844
+ text-align: right;
845
+ .required {
846
+ &::before {
847
+ content: '*';
848
+ color: var(--el-color-danger);
849
+ margin-right: 4px;
850
+ }
851
+ }
852
+ }
826
853
  }
854
+ // }
827
855
  }
828
856
  }
829
857
  }
@@ -1,10 +1,12 @@
1
1
  <template>
2
2
  <div class="ele-form-image">
3
3
  <template v-if="imagLIst && imagLIst.length > 0">
4
- <el-image v-for="(image, i) in imagLIst" :class="desc.class" :key="image" :preview-src-list="attrs.isShowPreview === false ? null : imagLIst" :initial-index="i" :src="format.imgUrl(image)" v-bind="attrs" :style="styles" v-on="onEvents" :fit="attrs.fit || 'cover'" />
4
+ <template v-for="(image, i) in imagLIst" :key="image + i">
5
+ <el-image :class="desc.class" :src="image" :preview-src-list="attrs.isShowPreview === false ? null : imagLIst" :initial-index="i" v-bind="attrs" :style="styles" v-on="onEvents" :fit="attrs.fit || 'cover'" />
6
+ </template>
5
7
  </template>
6
8
  <div v-else>
7
- <span class="no-img-tip">—</span>
9
+ <span class="no-img-tip">-</span>
8
10
  </div>
9
11
  </div>
10
12
  </template>
@@ -17,12 +19,9 @@ export default {
17
19
  }
18
20
  </script>
19
21
  <script lang="ts" setup>
20
- import { ref, computed, useAttrs, onBeforeMount, inject } from 'vue'
22
+ import { ref, computed, useAttrs, onBeforeMount } from 'vue'
21
23
  import { getAttrs, getEvents } from '../mixins'
22
24
 
23
- // 格式化
24
- const format = inject('format') as any
25
-
26
25
  const props = defineProps<{
27
26
  modelValue?: Array<any> | string | null
28
27
  field?: string
@@ -49,7 +48,7 @@ const imagLIst = computed(() => {
49
48
  return props.modelValue.map((item) => item.shareUrl || item.furl)
50
49
  }
51
50
  } else if (typeof props.modelValue === 'string') {
52
- return props.modelValue.split(',').map((url) => format.imgUrl(url))
51
+ return props.modelValue.split(',')
53
52
  } else {
54
53
  // console.log('unknown image Type.....')
55
54
  }
@@ -29,6 +29,7 @@ const props = defineProps<{
29
29
 
30
30
  const emits = defineEmits(['update:modelValue', 'validateThis'])
31
31
  const currentValue = ref(props.modelValue)
32
+
32
33
  emits('update:modelValue', currentValue)
33
34
  const attrs = ref({} as any)
34
35
  const isInit = ref(false)
@@ -70,7 +70,7 @@ watch(
70
70
  () => props.modelValue,
71
71
  async () => {
72
72
  if (!props.desc.format) {
73
- formatValue.value = props.modelValue === '' ? props.desc.default ?? '' : props.modelValue ?? props.desc.default ?? ''
73
+ formatValue.value = props.modelValue === '' ? props.desc.default ?? '-' : props.modelValue ?? props.desc.default ?? '-'
74
74
  } else {
75
75
  if (typeof props.desc.format === 'function') {
76
76
  // 如果有方法类型的判断,则需要启用动态监测
@@ -78,7 +78,7 @@ watch(
78
78
  } else if (typeof props.desc.format === 'string') {
79
79
  formatValue.value = format[props.desc.format] ? format[props.desc.format](props.modelValue, props.formData || {}, props.field) : '--'
80
80
  } else {
81
- formatValue.value = props.modelValue || ''
81
+ formatValue.value = props.modelValue || '-'
82
82
  }
83
83
  }
84
84
  },
@@ -62,7 +62,7 @@ watch(
62
62
  () => props.modelValue,
63
63
  async () => {
64
64
  if (!props.desc.format) {
65
- formatValue.value = props.modelValue === '' ? '' : props.modelValue ?? ''
65
+ formatValue.value = props.modelValue === '' ? '-' : props.modelValue ?? '-'
66
66
  } else {
67
67
  if (typeof props.desc.format === 'function') {
68
68
  // 如果有方法类型的判断,则需要启用动态监测
@@ -70,7 +70,7 @@ watch(
70
70
  } else if (typeof props.desc.format === 'string') {
71
71
  formatValue.value = (await format)[props.desc.format](props.modelValue, props.formData || {}, props.field)
72
72
  } else {
73
- formatValue.value = props.modelValue || ''
73
+ formatValue.value = props.modelValue || '-'
74
74
  }
75
75
  }
76
76
  },
@@ -80,7 +80,7 @@ watch(
80
80
  () => props.modelValue,
81
81
  async () => {
82
82
  if (!props.desc.format) {
83
- formatValue.value = props.modelValue === '' ? props.desc.default ?? '' : props.modelValue ?? props.desc.default ?? ''
83
+ formatValue.value = props.modelValue === '' ? props.desc.default ?? '-' : props.modelValue ?? props.desc.default ?? '-'
84
84
  } else {
85
85
  if (typeof props.desc.format === 'function') {
86
86
  // 如果有方法类型的判断,则需要启用动态监测
@@ -89,7 +89,7 @@ watch(
89
89
  } else if (typeof props.desc.format === 'string') {
90
90
  formatValue.value = format[props.desc.format] ? format[props.desc.format](props.modelValue, props.formData, props.field) : '--'
91
91
  } else {
92
- formatValue.value = props.modelValue || ''
92
+ formatValue.value = props.modelValue || '-'
93
93
  }
94
94
  }
95
95
  },
@@ -223,7 +223,11 @@ async function handelUploadSuccess(response: any, file: any) {
223
223
  file.raw.path = response.furl || file.path
224
224
  }
225
225
  file.raw.shareUrl = file.path
226
- file.url = getFileIcon(file.raw)
226
+ if (props.desc.upType !== 'file') {
227
+ file.url = getFileIcon(file.raw)
228
+ } else {
229
+ file.url = response.furl || file.path
230
+ }
227
231
  handelListChange(file, 1)
228
232
  }
229
233
 
@@ -232,18 +236,16 @@ async function handelUploadSuccess(response: any, file: any) {
232
236
  * @param file
233
237
  */
234
238
  function getFileIcon(file?: any): string {
235
- if (file && props.desc.upType !== 'file') {
236
- const fileUrl = file.shareUrl || file.furl || file.path || file.url
237
- const suffix = (file?.suffix || fileUrl.substring(fileUrl.lastIndexOf('.')) || '') as string
238
- if (suffix) {
239
- if (fileTypes.imageSuffixes.indexOf(suffix.toLocaleLowerCase()) >= 0) {
240
- return fileUrl
241
- }
242
- for (let i = 0; i < fileTypes.suffixTypes.length; i++) {
243
- for (let j = 0; j < fileTypes.suffixTypes[i].suffixes.length; j++) {
244
- if (fileTypes.suffixTypes[i].suffixes[j] === suffix) {
245
- return iconMap[fileTypes.suffixTypes[i].type]
246
- }
239
+ const fileUrl = file.shareUrl || file.furl || file.path || file.url
240
+ const suffix = (file?.suffix || fileUrl.substring(fileUrl.lastIndexOf('.')) || '') as string
241
+ if (suffix) {
242
+ if (fileTypes.imageSuffixes.indexOf(suffix.toLocaleLowerCase()) >= 0) {
243
+ return fileUrl
244
+ }
245
+ for (let i = 0; i < fileTypes.suffixTypes.length; i++) {
246
+ for (let j = 0; j < fileTypes.suffixTypes[i].suffixes.length; j++) {
247
+ if (fileTypes.suffixTypes[i].suffixes[j] === suffix) {
248
+ return iconMap[fileTypes.suffixTypes[i].type]
247
249
  }
248
250
  }
249
251
  }
@@ -270,7 +272,7 @@ function handelListChange(item: UploadUserFile, type: 0 | 1) {
270
272
  currentValue.value.push({
271
273
  name: item.name,
272
274
  furl: (item.raw as any)?.path || item.url,
273
- url: getFileIcon(item.raw),
275
+ url: props.desc.upType !== 'file' ? getFileIcon(item.raw) : item.url,
274
276
  fsize: item.size,
275
277
  uid: item.uid,
276
278
  mimeType: item.raw?.type,
@@ -361,9 +363,12 @@ watch(
361
363
  } else {
362
364
  currentValue.value =
363
365
  data?.map((item: IOssInfo) => {
364
- item.url = getFileIcon(item)
365
- item.furl = getFileIcon(item)
366
- item.suffix = item.suffix || item.url.substring(item.url.lastIndexOf('.'))
366
+ if (props.desc.upType !== 'file') {
367
+ item.url = getFileIcon(item)
368
+ item.furl = getFileIcon(item)
369
+ }
370
+ item.suffix = item.suffix || item.url?.substring(item.url.lastIndexOf('.'))
371
+ item.previewUrl = item.furl || item.url
367
372
  return item
368
373
  }) || []
369
374
  }
@@ -206,7 +206,7 @@ const listLoading = ref(false)
206
206
  const size = defaultConf.size || 'default'
207
207
 
208
208
  // 顶部查询条件数据缓存
209
- const topQueryData = ref({} as any)
209
+ // const topQueryData = ref({} as any)
210
210
 
211
211
  // 数据
212
212
  let toolFormData = reactive({} as any)
@@ -497,8 +497,8 @@ async function getListQueryData() {
497
497
  let queryMap = {
498
498
  // 封装查询条件
499
499
  // ...route.query,
500
- // ...tableHeaderRef.value.getData(),
501
- ...topQueryData.value,
500
+ // ...topQueryData.value,
501
+ ...tableHeaderRef.value.getData(),
502
502
  ...(typeof props.tableConfig.queryMap === 'function' ? await props.tableConfig.queryMap() : props.tableConfig.queryMap),
503
503
  t_: new Date().getTime()
504
504
  } as any
@@ -643,10 +643,6 @@ async function loadData(isInit: Boolean) {
643
643
  dataResult = dataPage[props.tableConfig?.fetchMap?.list || 'records'] || null
644
644
  }
645
645
  tableData.value = dataResult
646
- if (isInit) {
647
- // 调用父类init
648
- emits('inited', tableData)
649
- }
650
646
  // 如果是树形结构
651
647
  if (props.type === 'expand') {
652
648
  treeIndexList.splice(0, treeIndexList.length)
@@ -698,8 +694,12 @@ async function reload(isTab: boolean = false) {
698
694
  * 处理顶部条件表单筛选
699
695
  */
700
696
  async function handelTopQuery() {
701
- topQueryData.value = cloneDeep(tableHeaderRef.value.getData())
702
- emits('queryChange', await getListQueryData())
697
+ // topQueryData.value = cloneDeep(tableHeaderRef.value.getData())
698
+ let tempQueryData = await getListQueryData()
699
+ if (props.tableConfig?.toolbar?.formConfig?.beforeRequest) {
700
+ tempQueryData = props.tableConfig?.toolbar?.formConfig?.beforeRequest(JSON.parse(JSON.stringify(tempQueryData))) || tempQueryData
701
+ }
702
+ if (tempQueryData) emits('queryChange', tempQueryData)
703
703
  reload()
704
704
  }
705
705
 
@@ -741,7 +741,10 @@ if (props.isDIYMain) {
741
741
  }
742
742
 
743
743
  onMounted(() => {
744
- reload()
744
+ // toolbar.formConfig
745
+ if (!(Object.keys(props.tableConfig?.toolbar?.formConfig || {}).length || props.tableConfig?.tbName)) {
746
+ reload()
747
+ }
745
748
  })
746
749
 
747
750
  defineExpose({ reload, tableData, changeSelect, resetSelect, initCol })
@@ -3,7 +3,7 @@
3
3
  <template v-if="props.toolbar && Object.keys(props.toolbar || {}).length">
4
4
  <el-form :inline="true" class="el-plus-table-header-form" :style="{ justifyContent: !props.toolbar.formConfig && props.toolbar.btnRight ? 'flex-end' : 'space-between' }">
5
5
  <div v-if="props.toolbar.formConfig" class="el-plus-table-form-items">
6
- <ElPlusForm ref="elPlusFormRef" v-bind="formConfig" v-model="props.modelValue" labelWidth="1" :requestFn="handelQueryData" :showBtns="false" :isTable="true">
6
+ <ElPlusForm ref="elPlusFormRef" v-bind="formConfig" v-model="props.modelValue" :requestFn="handelQueryData" :showBtns="false" :isTable="true">
7
7
  <template #row>
8
8
  <div class="table-header-form-btns">
9
9
  <ElPlusFormBtn type="primary" icon="ele-Search" :loading="loading" :desc="{ label: '查询', on: { click: handelSearch }, size }" />
@@ -193,7 +193,7 @@ async function handelDownload({ callBack }: IBtnBack) {
193
193
  * 处理搜索
194
194
  */
195
195
  function handelSearch() {
196
- elPlusFormRef.value.submit()
196
+ elPlusFormRef.value?.submit()
197
197
  }
198
198
 
199
199
  /**
@@ -202,7 +202,7 @@ function handelSearch() {
202
202
  function handelReset() {
203
203
  elPlusFormRef.value.clear()
204
204
  nextTick(() => {
205
- elPlusFormRef.value.submit()
205
+ elPlusFormRef.value?.submit()
206
206
  })
207
207
  }
208
208
 
@@ -251,7 +251,13 @@ function initCol() {
251
251
  }
252
252
  }
253
253
 
254
- onMounted(() => {})
254
+ onMounted(() => {
255
+ nextTick(() => {
256
+ setTimeout(() => {
257
+ handelSearch()
258
+ }, 200)
259
+ })
260
+ })
255
261
 
256
262
  defineExpose({ getData: () => elPlusFormRef.value?.getData(), initCol })
257
263
  </script>
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "el-plus-crud",
3
- "version": "0.0.97",
3
+ "version": "0.0.99",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "el-plus-crud",
9
- "version": "0.0.97",
9
+ "version": "0.0.99",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@element-plus/icons-vue": "^2.1.0",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "el-plus-crud",
3
3
  "description": "采用Vue3 + TS,封装的element-plus数据驱动表单、列表组件",
4
4
  "author": "K.D.Jack",
5
- "version": "0.0.97",
5
+ "version": "0.0.99",
6
6
  "license": "MIT",
7
7
  "private": false,
8
8
  "main": "dist/el-plus-crud.mjs",
package/types/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Ref } from 'vue'
2
+
1
3
  // 基础类型
2
4
  export type IBaseObj = IBaseObj
3
5
 
@@ -79,14 +81,14 @@ export type IDescItem = {
79
81
  */
80
82
  export interface IFormDescItem extends IDescItem {
81
83
  field?: string
82
- disabled?: boolean | ((data?: any) => boolean)
84
+ disabled?: boolean | Ref<boolean> | ((data?: any) => boolean)
83
85
  showLabel?: boolean
84
86
  labelWidth?: string | number
85
87
  tip?: string | ((data?: any) => string)
86
88
  size?: string
87
89
  placeholder?: string
88
90
  attrs?: IBaseObj | ((data?: any) => IBaseObj)
89
- options?: Array<IFormDescItemOptionItem> | IFetch<Array<IFormDescItemOptionItem>> | string
91
+ options?: Ref<Array<IFormDescItemOptionItem>> | Array<IFormDescItemOptionItem> | (() => Array<IFormDescItemOptionItem>) | IFetch<Array<IFormDescItemOptionItem>> | string
90
92
  default?: string | boolean | number
91
93
  defaultItem?: { value: string | number; label: string; dataItem?: IBaseObj }
92
94
  rules?: string | Array<any>