|
@@ -1,31 +1,38 @@
|
|
|
<template>
|
|
|
<view class="labelColor itemBox" style="height: 45px;">
|
|
|
- <view class="item" v-for="(item, index) in filterList" :key="item[props.idValue]">
|
|
|
- <!-- v-slot:default="{ data, error }" -->
|
|
|
- <uni-data-picker
|
|
|
- ref="pickerRef"
|
|
|
- v-model="item.value"
|
|
|
- v-slot:default="{ error }"
|
|
|
- :localdata="item.array"
|
|
|
- :popup-title="'请选择' + item[labelValue]"
|
|
|
- :map="item.map || { text: 'label', value: 'value' }"
|
|
|
- @change="e => handleClick(e, item)"
|
|
|
+ <view class="item" v-for="(item) in filterList" :key="item[props.idValue]">
|
|
|
+ <m-filter
|
|
|
+ class="itemFilter"
|
|
|
+ :items="item.array"
|
|
|
+ :label="item.label"
|
|
|
+ :multiple="item.multiple"
|
|
|
+ :item-label="item.itemLabel"
|
|
|
+ :item-value="item.itemValue"
|
|
|
+ @change="($event, $name) => handleClick($event, $name, item)"
|
|
|
>
|
|
|
- <view v-if="error" class="error">
|
|
|
- <text>{{error}}</text>
|
|
|
- </view>
|
|
|
- <view v-else class="d-flex">
|
|
|
- <view
|
|
|
- class="selectText font-weight-bold"
|
|
|
- :style="`color: ${item.value? '#008978' : ''}`"
|
|
|
- >
|
|
|
- {{ item[labelValue] }}
|
|
|
- <!-- {{ item.text || item[labelValue] }} -->
|
|
|
+ <view
|
|
|
+ :class="(item.multiple && item.value?.length) || (!item.multiple && item.value) ? 'active' : ''"
|
|
|
+ class="name"
|
|
|
+ >
|
|
|
+ <view class="over">
|
|
|
+ {{ item.name ?? item.label }}
|
|
|
</view>
|
|
|
- <uni-icons v-if="!item.value" type="icon-arrow-sortdown-smal" custom-prefix="iconfont" color="#999"/>
|
|
|
+ <template v-if="item.multiple && item.value?.length > 1">
|
|
|
+ <uni-icons
|
|
|
+ class="point"
|
|
|
+ type="smallcircle-filled"
|
|
|
+ color=""
|
|
|
+ size="6"
|
|
|
+ />
|
|
|
+ {{item.value.length}}
|
|
|
+ </template>
|
|
|
+ <uni-icons
|
|
|
+ type="down"
|
|
|
+ color=""
|
|
|
+ size="12"
|
|
|
+ />
|
|
|
</view>
|
|
|
- </uni-data-picker>
|
|
|
- <uni-icons v-if="item.value" class="marginT2" type="closeempty" size="16" color="#999" @click="handleClear(item, index)"></uni-icons>
|
|
|
+ </m-filter>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
@@ -33,43 +40,60 @@
|
|
|
<script setup>
|
|
|
import { ref, watch } from 'vue'
|
|
|
import { getDict } from '@/hooks/useDictionaries'
|
|
|
+import MFilter from './mFilter.vue'
|
|
|
|
|
|
const emit = defineEmits(['change'])
|
|
|
const props = defineProps({
|
|
|
list: { type: Array, default: () => [] },
|
|
|
idValue: { type: String, default: 'id' },
|
|
|
labelValue: { type: String, default: 'label' },
|
|
|
- selectIdValue: { type: String, default: 'id' },
|
|
|
- selectLabelValue: { type: String, default: 'label' },
|
|
|
- useApiData: { type: Boolean, default: true },
|
|
|
+ // selectIdValue: { type: String, default: 'id' },
|
|
|
+ // selectLabelValue: { type: String, default: 'label' },
|
|
|
+ // useApiData: { type: Boolean, default: true },
|
|
|
lazy: { type: Boolean, default: false },
|
|
|
})
|
|
|
|
|
|
-const pickerRef = ref()
|
|
|
-const handleClick = (e, item) => {
|
|
|
- const obj = e.detail.value?.length ? e.detail.value[e.detail.value.length-1] : {}
|
|
|
- const obj0 = e.detail.value?.length ? e.detail.value[0] : {}
|
|
|
- //
|
|
|
- let val = obj.value
|
|
|
- item.value = obj.value
|
|
|
- item.text = obj.text || ''
|
|
|
- if (typeof val === 'string' && val.includes('unlimited') && obj0) {
|
|
|
- val = Number.isInteger(obj0.id) ? Number(val.split('unlimited')[0]) : val.split('unlimited')[0]
|
|
|
+const popup = ref()
|
|
|
+
|
|
|
+const handleOpen = (index) => {
|
|
|
+ popup.value[index].open('bottom')
|
|
|
+}
|
|
|
+const handleChangeItem = (i, item) => {
|
|
|
+ if (i === item.active) {
|
|
|
+ return
|
|
|
}
|
|
|
- emit('change', item.key, val)
|
|
|
+ item.active = i
|
|
|
}
|
|
|
|
|
|
-const handleClear = (item, index) => {
|
|
|
- item.value = null
|
|
|
- item.text = null
|
|
|
- // pickerRef.value[index]?.clear()
|
|
|
- emit('change', item.key, item.value)
|
|
|
+
|
|
|
+const handleClick = (e, name, item) => {
|
|
|
+ item.value = e
|
|
|
+ item.name = name ?? item.label
|
|
|
+ // const obj = e.detail.value?.length ? e.detail.value[e.detail.value.length-1] : {}
|
|
|
+ // const obj0 = e.detail.value?.length ? e.detail.value[0] : {}
|
|
|
+ // //
|
|
|
+ // let val = obj.value
|
|
|
+ // item.value = obj.value
|
|
|
+ // item.text = obj.text || ''
|
|
|
+ // if (typeof val === 'string' && val.includes('unlimited') && obj0) {
|
|
|
+ // val = Number.isInteger(obj0.id) ? Number(val.split('unlimited')[0]) : val.split('unlimited')[0]
|
|
|
+ // }
|
|
|
+ emit('change', item.key, e)
|
|
|
}
|
|
|
|
|
|
+// const handleClear = (item, index) => {
|
|
|
+// item.value = e.multiple ? [] : null
|
|
|
+// item.text = null
|
|
|
+// emit('change', item.key, item.value)
|
|
|
+// }
|
|
|
+
|
|
|
// 获取字典数据
|
|
|
const getData = (e) => {
|
|
|
getDict(e.dictType, e.map ? {} : null, e.map ? e.dictType : 'dict').then(({ data }) => {
|
|
|
e.array = data.data
|
|
|
+ e.itemLabel = e.map?.text
|
|
|
+ e.itemValue = e.map?.value
|
|
|
+ e.value = []
|
|
|
})
|
|
|
}
|
|
|
|
|
@@ -83,9 +107,15 @@ const setItemSelectData = () => {
|
|
|
const filterList = ref([])
|
|
|
watch(() => props.list,
|
|
|
(newVal) => {
|
|
|
- filterList.value = newVal ? [...newVal] : []
|
|
|
- filterList.value.forEach(e => e.value = null)
|
|
|
- if (filterList.value.length && !props.lazy) setItemSelectData()
|
|
|
+ if (!newVal) {
|
|
|
+ filterList.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+ filterList.value = newVal
|
|
|
+
|
|
|
+ if (!props.lazy) {
|
|
|
+ setItemSelectData()
|
|
|
+ }
|
|
|
},
|
|
|
{ immediate: true }
|
|
|
)
|
|
@@ -94,14 +124,35 @@ watch(() => props.list,
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.labelColor { color: #5c5c5c; }
|
|
|
-.marginT2 { margin-top: 2px; }
|
|
|
.itemBox {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
.item {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ flex: 1;
|
|
|
+ width: 0;
|
|
|
font-size: 14px;
|
|
|
+ .itemFilter {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ .name {
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ .over {
|
|
|
+ overflow: hidden;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ .point {
|
|
|
+ margin: 0 5px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|