jobsys-explore 4.2.3 → 4.2.5

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,5 @@
1
+ ---
2
+ "jobsys-explore": patch
3
+ ---
4
+
5
+ select
@@ -0,0 +1,5 @@
1
+ ---
2
+ "jobsys-explore": patch
3
+ ---
4
+
5
+ rate default null
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # jobsys-explore
2
2
 
3
+ ## 4.2.5
4
+
5
+ ### Patch Changes
6
+
7
+ - select
8
+ - d
9
+ - useFormFormat
10
+ - rate default null
11
+ - use Dayjs
12
+
13
+ ## 4.2.4
14
+
15
+ ### Patch Changes
16
+
17
+ - d
18
+ - useFormFormat
19
+ - rate default null
20
+ - use Dayjs
21
+
3
22
  ## 4.2.3
4
23
 
5
24
  ### Patch Changes
@@ -284,6 +284,13 @@ export default defineComponent({
284
284
  let form = cloneDeep(state.submitForm)
285
285
 
286
286
  formItems.value
287
+ .map((item) => {
288
+ if (item.match) {
289
+ // match 的属性需要在这里处理
290
+ return { ...item, ...item.match(form) }
291
+ }
292
+ return item
293
+ })
287
294
  .filter((item) => item.beforeSubmit && isFunction(item.beforeSubmit))
288
295
  .forEach((item) => {
289
296
  form[item.key] = item.beforeSubmit({
@@ -13,7 +13,7 @@ export default defineComponent({
13
13
  props: {
14
14
  ...defaultFieldProps,
15
15
 
16
- modelValue: { type: [Number, String], default: 1 },
16
+ modelValue: { type: [Number, String], default: null },
17
17
  },
18
18
  emits: ["update:modelValue"],
19
19
  setup(props, { emit, slots }) {
@@ -26,6 +26,7 @@ export default defineComponent({
26
26
  )
27
27
 
28
28
  const options = ref([])
29
+
29
30
  useOptionTrait(options, props)
30
31
 
31
32
  const onChange = (value) => {
@@ -13,7 +13,7 @@ export default defineComponent({
13
13
  props: {
14
14
  ...defaultFieldProps,
15
15
 
16
- modelValue: { type: Number, default: 2 },
16
+ modelValue: { type: Number, default: null },
17
17
  },
18
18
  emits: ["update:modelValue"],
19
19
  setup(props, { emit, slots }) {
@@ -1,9 +1,9 @@
1
1
  import { computed, defineComponent, ref, watch } from "vue"
2
2
  import PickerWrapper, { pickerSlots } from "./PickerWrapper.jsx"
3
- import { Button, Picker } from "vant"
3
+ import { Button, Picker, Search } from "vant"
4
4
  import { defaultFieldProps, defaultOptionsProps } from "../utils"
5
5
  import { useFetch } from "../../hooks"
6
- import { find, isArray, isFunction, isString } from "lodash-es"
6
+ import { cloneDeep, find, isArray, isFunction, isString } from "lodash-es"
7
7
 
8
8
  /**
9
9
  * ExSelect 下拉选择
@@ -31,13 +31,31 @@ export default defineComponent({
31
31
  * 是否把选项的值返回到modelValue
32
32
  */
33
33
  textInValue: { type: Boolean, default: false },
34
+
35
+ /**
36
+ * 是否可以搜索
37
+ */
38
+ filtable: { type: Boolean, default: false },
39
+
40
+ /**
41
+ * 搜索链接
42
+ */
43
+ filterUrl: { type: String, default: "" },
44
+
45
+ /**
46
+ * 自定义渲染选项
47
+ */
48
+ optionRender: { type: Function, default: null },
34
49
  },
35
50
  emits: ["update:modelValue", "change"],
36
51
  setup(props, { emit, slots, expose }) {
37
52
  const componentValue = ref([])
38
53
  const options = ref([])
54
+ const recordOptions = ref([]) // 缓存 options
39
55
  let columns = 1 //根据子项的数组数来确定 Picker 的列数,默认为1列
40
56
  const pickerRef = ref()
57
+ const keyword = ref("")
58
+ const fetcher = ref({ loading: false })
41
59
 
42
60
  const setModelValue = () => {
43
61
  let value = isArray(props.modelValue) ? props.modelValue : [props.modelValue]
@@ -54,7 +72,7 @@ export default defineComponent({
54
72
  )
55
73
 
56
74
  const displayText = computed(() => {
57
- if (props.modelValue.length === 0) {
75
+ if (!props.modelValue || (isArray(props.modelValue) && !props.modelValue.length)) {
58
76
  return ""
59
77
  }
60
78
  let modelValue = isArray(props.modelValue) ? props.modelValue : [props.modelValue]
@@ -101,6 +119,9 @@ export default defineComponent({
101
119
 
102
120
  return isString(option) ? { value: option, label: option, text: option } : { text: option.label, ...option }
103
121
  })
122
+
123
+ recordOptions.value = cloneDeep(options)
124
+
104
125
  return options
105
126
  }
106
127
 
@@ -111,12 +132,24 @@ export default defineComponent({
111
132
  () => prepareOptions(props.options).then((opts) => (options.value = opts)),
112
133
  )
113
134
 
135
+ const filterOnlineDataByKeyword = async () => {
136
+ let res = await useFetch(fetcher).get(props.filterUrl, { params: { keyword: keyword.value } })
137
+ if (props.afterFetched) {
138
+ res = props.afterFetched(res)
139
+ }
140
+ options.value = res
141
+ }
142
+
143
+ const filterLocalDataByKeyword = () => {
144
+ options.value = recordOptions.value.filter((item) => item.text.includes(keyword.value))
145
+ }
146
+
114
147
  // @hack
115
148
  // 由于在 Picker 清除 model value 后再次打开 Picker 在不重新选择新选项的情况下无法选中之前的选项
116
149
  // 所以这里手动重新赋一次值给 model value
117
150
  const onOpenWrapper = () => {
118
151
  if (columns === 1 && !componentValue.value?.[0]) {
119
- componentValue.value = [options.value[0].value]
152
+ componentValue.value = [options.value[0]?.value]
120
153
  }
121
154
  }
122
155
 
@@ -128,6 +161,30 @@ export default defineComponent({
128
161
  pickerRef.value.close()
129
162
  }
130
163
 
164
+ const onSearch = () => {
165
+ if (keyword.value) {
166
+ if (props.filterUrl) {
167
+ filterOnlineDataByKeyword()
168
+ } else {
169
+ filterLocalDataByKeyword()
170
+ }
171
+ } else {
172
+ if (props.filterUrl) {
173
+ filterOnlineDataByKeyword()
174
+ } else {
175
+ filterLocalDataByKeyword()
176
+ }
177
+ }
178
+ }
179
+
180
+ const onSearchClear = () => {
181
+ if (props.filterUrl) {
182
+ filterOnlineDataByKeyword()
183
+ } else {
184
+ filterLocalDataByKeyword()
185
+ }
186
+ }
187
+
131
188
  const onClear = () => {
132
189
  const value = columns === 1 ? null : []
133
190
  emit("change", value)
@@ -137,6 +194,28 @@ export default defineComponent({
137
194
 
138
195
  expose({ displayText })
139
196
 
197
+ /********** render **********/
198
+
199
+ const pickerSlotElem = () => {
200
+ const elem = {}
201
+ if (props.filtable) {
202
+ elem["columns-top"] = () => (
203
+ <Search
204
+ shape={"round"}
205
+ placeholder={"搜索"}
206
+ v-model={keyword.value}
207
+ onSearch={onSearch}
208
+ onClear={onSearchClear}
209
+ style={{ width: "100%" }}
210
+ ></Search>
211
+ )
212
+ }
213
+ if (props.optionRender) {
214
+ elem["option"] = (option, index) => props.optionRender(option, index)
215
+ }
216
+ return elem
217
+ }
218
+
140
219
  return () => (
141
220
  <PickerWrapper ref={pickerRef} closeable={false} onOpen={onOpenWrapper} disabled={props.readonly || props.disabled}>
142
221
  {{
@@ -146,9 +225,12 @@ export default defineComponent({
146
225
  v-model={componentValue.value}
147
226
  columns={options.value}
148
227
  onConfirm={onConfirm}
228
+ loading={fetcher.value.loading}
149
229
  onCancel={() => pickerRef.value.close()}
150
230
  {...props.defaultProps}
151
- />,
231
+ >
232
+ {pickerSlotElem()}
233
+ </Picker>,
152
234
  props.clearable ? (
153
235
  <div class={"ex-field-popup__clear-btn"}>
154
236
  <Button block type={"primary"} plain={true} round={true} onClick={onClear}>
@@ -25,7 +25,7 @@ const initItemDefaultValue = (item, existingData, submitForm, provider) => {
25
25
  }
26
26
 
27
27
  if (item.type === "number" || item.type === "rate") {
28
- value = value ? Number(value) : 0
28
+ value = value ? Number(value) : null
29
29
  } else if (item.type === "slider") {
30
30
  value = item.defaultProps && item.defaultProps.range ? value || [0, 100] : value ? Number(value) : 0
31
31
  } else if (item.type === "switch") {
@@ -1,9 +1,9 @@
1
- import { defineComponent, nextTick, reactive, ref, watch } from "vue"
1
+ import { isArray, isFunction } from "lodash-es"
2
2
  import { Button, Icon, Popup, Search } from "vant"
3
- import { find, isArray, isFunction } from "lodash-es"
3
+ import { computed, defineComponent, nextTick, reactive, ref, watch } from "vue"
4
+ import ExGrid from "../grid/ExGrid.jsx"
4
5
  import { createExpand, createField, createQuick } from "./components"
5
6
  import "./index.less"
6
- import ExGrid from "../grid/ExGrid.jsx"
7
7
 
8
8
  /**
9
9
  * ExSearch 搜索组件
@@ -83,9 +83,6 @@ export default defineComponent({
83
83
 
84
84
  const state = reactive({
85
85
  queryForm: {}, // 搜索表单
86
- quickColumns: [], //快速检索项
87
- fieldColumns: [], //表单搜索项
88
-
89
86
  showFilterPopup: false,
90
87
  })
91
88
 
@@ -108,26 +105,20 @@ export default defineComponent({
108
105
  return value
109
106
  }
110
107
 
108
+ //快速检索项
109
+ const quickColumns = computed(() => {
110
+ return props.columns.filter((item) => item.quick)
111
+ })
112
+
113
+ //表单搜索项
114
+ const fieldColumns = computed(() => {
115
+ return props.columns.filter((item) => !item.quick)
116
+ })
117
+
111
118
  const initQueryForm = () => {
112
119
  const form = {}
113
120
  props.columns.forEach((item) => {
114
- const value = searchItemDefaultValue(item)
115
-
116
- if (item.quick && !find(state.quickColumns, { key: item.key })) {
117
- state.quickColumns.push(item)
118
- } else {
119
- if (item.expandable) {
120
- if (!item.options) {
121
- console.error(`expandable 为 true 时,必须提供 options 属性`)
122
- return
123
- }
124
- }
125
-
126
- if (!find(state.fieldColumns, { key: item.key })) {
127
- state.fieldColumns.push(item)
128
- }
129
- }
130
- form[item.key] = value
121
+ form[item.key] = searchItemDefaultValue(item)
131
122
  })
132
123
  state.queryForm = form
133
124
  }
@@ -176,16 +167,16 @@ export default defineComponent({
176
167
  }
177
168
 
178
169
  const onClearFields = () => {
179
- state.fieldColumns.forEach((item) => {
170
+ fieldColumns.value.forEach((item) => {
180
171
  state.queryForm[item.key] = searchItemDefaultValue(item)
181
172
  })
182
173
  }
183
174
 
184
175
  const reset = () => {
185
- state.fieldColumns.forEach((item) => {
176
+ fieldColumns.value.forEach((item) => {
186
177
  state.queryForm[item.key] = searchItemDefaultValue(item)
187
178
  })
188
- state.quickColumns.forEach((item) => {
179
+ quickColumns.value.forEach((item) => {
189
180
  state.queryForm[item.key] = searchItemDefaultValue(item)
190
181
  })
191
182
  componentValue.value = ""
@@ -196,7 +187,7 @@ export default defineComponent({
196
187
  /******************* render *********************/
197
188
 
198
189
  const quickElems = () => {
199
- return state.quickColumns.map((item) => createQuick(item, state.queryForm, onSearch))
190
+ return quickColumns.value.map((item) => createQuick(item, state.queryForm, onSearch))
200
191
  }
201
192
 
202
193
  const popupHeaderElem = () => (
@@ -214,7 +205,7 @@ export default defineComponent({
214
205
 
215
206
  const fieldElems = () => (
216
207
  <div class={"ex-search-popup__content"}>
217
- {state.fieldColumns.map((item) => (item.expandable ? createExpand(item, state.queryForm) : createField(item, state.queryForm)))}
208
+ {fieldColumns.value.map((item) => (item.expandable ? createExpand(item, state.queryForm) : createField(item, state.queryForm)))}
218
209
  </div>
219
210
  )
220
211
 
@@ -236,13 +227,13 @@ export default defineComponent({
236
227
  )
237
228
 
238
229
  const quickBarElem = () => {
239
- if (!state.quickColumns.length && !state.fieldColumns?.length) {
230
+ if (!quickColumns.value?.length && !fieldColumns.value?.length) {
240
231
  return null
241
232
  }
242
233
  return (
243
234
  <div class={"ex-search__quick-bar"}>
244
235
  <div class={"ex-search__quick-container"}>{quickElems()}</div>
245
- {state.fieldColumns?.length ? (
236
+ {fieldColumns.value?.length ? (
246
237
  <div class={"ex-search__filter"} onClick={onOpenFilter}>
247
238
  筛选<Icon name={"filter-o"}></Icon>
248
239
  </div>