jobsys-explore 4.2.4 → 4.2.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,5 @@
1
+ ---
2
+ "jobsys-explore": patch
3
+ ---
4
+
5
+ select
@@ -0,0 +1,5 @@
1
+ ---
2
+ "jobsys-explore": patch
3
+ ---
4
+
5
+ select
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # jobsys-explore
2
2
 
3
+ ## 4.2.6
4
+
5
+ ### Patch Changes
6
+
7
+ - select
8
+ - d
9
+ - useFormFormat
10
+ - rate default null
11
+ - use Dayjs
12
+ - select
13
+
14
+ ## 4.2.5
15
+
16
+ ### Patch Changes
17
+
18
+ - select
19
+ - d
20
+ - useFormFormat
21
+ - rate default null
22
+ - use Dayjs
23
+
3
24
  ## 4.2.4
4
25
 
5
26
  ### Patch Changes
@@ -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) {
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,22 +119,39 @@ 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
 
107
- prepareOptions(props.options).then((opts) => (options.value = opts))
128
+ prepareOptions(props.options).then((opts) => {
129
+ options.value = opts
130
+ })
108
131
 
109
132
  watch(
110
133
  () => props.options,
111
134
  () => prepareOptions(props.options).then((opts) => (options.value = opts)),
112
135
  )
113
136
 
137
+ const filterOnlineDataByKeyword = async () => {
138
+ let res = await useFetch(fetcher.value).get(props.filterUrl, { params: { keyword: keyword.value } })
139
+ if (props.afterFetched) {
140
+ res = props.afterFetched(res)
141
+ }
142
+ prepareOptions(res).then((opts) => (options.value = opts))
143
+ }
144
+
145
+ const filterLocalDataByKeyword = () => {
146
+ options.value = recordOptions.value.filter((item) => item.text.includes(keyword.value))
147
+ }
148
+
114
149
  // @hack
115
150
  // 由于在 Picker 清除 model value 后再次打开 Picker 在不重新选择新选项的情况下无法选中之前的选项
116
151
  // 所以这里手动重新赋一次值给 model value
117
152
  const onOpenWrapper = () => {
118
153
  if (columns === 1 && !componentValue.value?.[0]) {
119
- componentValue.value = [options.value[0].value]
154
+ componentValue.value = [options.value[0]?.value]
120
155
  }
121
156
  }
122
157
 
@@ -128,6 +163,30 @@ export default defineComponent({
128
163
  pickerRef.value.close()
129
164
  }
130
165
 
166
+ const onSearch = () => {
167
+ if (keyword.value) {
168
+ if (props.filterUrl) {
169
+ filterOnlineDataByKeyword()
170
+ } else {
171
+ filterLocalDataByKeyword()
172
+ }
173
+ } else {
174
+ if (props.filterUrl) {
175
+ filterOnlineDataByKeyword()
176
+ } else {
177
+ filterLocalDataByKeyword()
178
+ }
179
+ }
180
+ }
181
+
182
+ const onSearchClear = () => {
183
+ if (props.filterUrl) {
184
+ filterOnlineDataByKeyword()
185
+ } else {
186
+ filterLocalDataByKeyword()
187
+ }
188
+ }
189
+
131
190
  const onClear = () => {
132
191
  const value = columns === 1 ? null : []
133
192
  emit("change", value)
@@ -137,6 +196,28 @@ export default defineComponent({
137
196
 
138
197
  expose({ displayText })
139
198
 
199
+ /********** render **********/
200
+
201
+ const pickerSlotElem = () => {
202
+ const elem = {}
203
+ if (props.filtable) {
204
+ elem["columns-top"] = () => (
205
+ <Search
206
+ shape={"round"}
207
+ placeholder={"搜索"}
208
+ v-model={keyword.value}
209
+ onSearch={onSearch}
210
+ onClear={onSearchClear}
211
+ style={{ width: "100%" }}
212
+ ></Search>
213
+ )
214
+ }
215
+ if (props.optionRender) {
216
+ elem["option"] = (option, index) => props.optionRender(option, index)
217
+ }
218
+ return elem
219
+ }
220
+
140
221
  return () => (
141
222
  <PickerWrapper ref={pickerRef} closeable={false} onOpen={onOpenWrapper} disabled={props.readonly || props.disabled}>
142
223
  {{
@@ -146,9 +227,12 @@ export default defineComponent({
146
227
  v-model={componentValue.value}
147
228
  columns={options.value}
148
229
  onConfirm={onConfirm}
230
+ loading={fetcher.value.loading}
149
231
  onCancel={() => pickerRef.value.close()}
150
232
  {...props.defaultProps}
151
- />,
233
+ >
234
+ {pickerSlotElem()}
235
+ </Picker>,
152
236
  props.clearable ? (
153
237
  <div class={"ex-field-popup__clear-btn"}>
154
238
  <Button block type={"primary"} plain={true} round={true} onClick={onClear}>
@@ -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>