u
This commit is contained in:
1 parent
92fbbf7c6d
commit
b03e2c1e69
149 files changed
+925
-14628
No files matched your search
@@ -0,0 +1,55 @@
|
||||
<script setup lang="ts">
|
||||
import PickerSelect from '../picker-select/index.vue'
|
||||
|
||||
const props = defineProps({
|
||||
label: { type: String, default: '' },
|
||||
value: { type: null as unknown as PropType<any>, default: undefined },
|
||||
labelField: { type: String, required: true },
|
||||
valueField: { type: String, required: true },
|
||||
viewname: { type: String, required: true },
|
||||
field1: { type: String, required: true },
|
||||
field2: { type: String, required: true },
|
||||
placeholder: { type: String, default: '请选择' },
|
||||
})
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'update:label', val: string): void
|
||||
(e: 'update:value', val: any): void
|
||||
}>()
|
||||
|
||||
const _visible = ref(false)
|
||||
const _label = ref(props.label)
|
||||
|
||||
// 同步 props.label
|
||||
watch(() => props.label, (val) => {
|
||||
_label.value = val
|
||||
})
|
||||
|
||||
// 选中时只处理 label
|
||||
function handleSelectChange(selectValue: any) {
|
||||
if (!selectValue)
|
||||
return
|
||||
_label.value = selectValue[props.labelField]
|
||||
emits('update:label', _label.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<sar-popout-input
|
||||
v-model="_label"
|
||||
:placeholder="props.placeholder"
|
||||
@click="_visible = true"
|
||||
>
|
||||
<PickerSelect
|
||||
v-model:visible="_visible"
|
||||
:value="props.value"
|
||||
:viewname="props.viewname"
|
||||
:field1="props.field1"
|
||||
:field2="props.field2"
|
||||
:label-field="props.labelField"
|
||||
:value-field="props.valueField"
|
||||
@update:value="emits('update:value', $event)"
|
||||
@change="handleSelectChange"
|
||||
/>
|
||||
</sar-popout-input>
|
||||
</template>
|
||||
@@ -0,0 +1,385 @@
|
||||
<script setup lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import { useIndeterminate } from 'sard-uniapp'
|
||||
import { computed, ref } from 'vue'
|
||||
import { getAutocompleteDataApi, getAutocompleteDataExApi } from '@/request/api'
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<'radio' | 'multiple'>,
|
||||
default: 'radio',
|
||||
},
|
||||
value: {
|
||||
type: null as unknown as PropType<any | any[]>,
|
||||
default: undefined,
|
||||
},
|
||||
labelField: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
valueField: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
viewname: {
|
||||
type: String,
|
||||
},
|
||||
searchcondition: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
userid: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
field1: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
field2: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
searchType: {
|
||||
type: String as PropType<'default' | 'ex' | 'single'>,
|
||||
default: 'default',
|
||||
required: false,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:visible', 'update:value', 'change'])
|
||||
|
||||
const _visible = ref(props.visible)
|
||||
|
||||
watch(() => props.visible, val => _visible.value = val)
|
||||
|
||||
const loading = ref(true)
|
||||
|
||||
const searchValue = ref('')
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
})
|
||||
|
||||
const isPrevDisabled = computed(() => pagination.value.current <= 1)
|
||||
const isNextDisabled = computed(() =>
|
||||
pagination.value.current >= Math.ceil(pagination.value.total / pagination.value.pageSize),
|
||||
)
|
||||
|
||||
// 内部 value,双向绑定 props.value
|
||||
const _value = computed({
|
||||
get: () => {
|
||||
if (props.type === 'multiple') {
|
||||
return Array.isArray(props.value) ? props.value : []
|
||||
}
|
||||
return props.value ?? null
|
||||
},
|
||||
set: (val) => {
|
||||
emit('update:value', val)
|
||||
},
|
||||
})
|
||||
|
||||
const options = ref<any[]>([])
|
||||
|
||||
const { allChecked, isIndeterminate, onAllChange } = useIndeterminate(
|
||||
_value,
|
||||
options,
|
||||
)
|
||||
|
||||
function select(option, toggle) {
|
||||
if (!option.disabled) {
|
||||
toggle(option.value)
|
||||
if (props.type === 'radio') {
|
||||
_visible.value = false
|
||||
|
||||
const selectedOption = options.value.find(
|
||||
o => o.value === option.value,
|
||||
)
|
||||
|
||||
_visible.value = false
|
||||
emit('update:visible', false)
|
||||
emit('change', selectedOption)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 显示数量
|
||||
const count = computed(() => {
|
||||
if (props.type === 'multiple') {
|
||||
return `${(_value.value).length || 0} / ${options.value.length}`
|
||||
}
|
||||
else {
|
||||
return _value.value != null ? `1 / ${options.value.length}` : `0 / ${options.value.length}`
|
||||
}
|
||||
})
|
||||
|
||||
function handleAfterEnter() {
|
||||
getData()
|
||||
}
|
||||
|
||||
function handlePagationChange(page: number) {
|
||||
pagination.value.current = page
|
||||
|
||||
getData()
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
pagination.value.current = 1
|
||||
pagination.value.total = 0
|
||||
pagination.value.pageSize = 10
|
||||
|
||||
getData()
|
||||
}
|
||||
|
||||
function getData() {
|
||||
if (props.searchType === 'ex') {
|
||||
getAutocompleteDataEx()
|
||||
}
|
||||
else if (props.searchType === 'single') {
|
||||
getAutocompleteDataSingle()
|
||||
}
|
||||
else {
|
||||
getAutocompleteData()
|
||||
}
|
||||
}
|
||||
|
||||
function getAutocompleteData() {
|
||||
loading.value = true
|
||||
|
||||
getAutocompleteDataApi({
|
||||
q: searchValue.value,
|
||||
page: pagination.value.current,
|
||||
limit: pagination.value.pageSize,
|
||||
viewname: props.viewname,
|
||||
field1: props.field1,
|
||||
field2: props.field2,
|
||||
}).then((res) => {
|
||||
pagination.value.total = res.data.total
|
||||
|
||||
options.value = res.data.rows.map(item => ({
|
||||
label: item[props.labelField] ?? '',
|
||||
value: item[props.valueField] ?? undefined,
|
||||
disabled: !!item.disabled,
|
||||
...item,
|
||||
}))
|
||||
|
||||
console.log(res.data.rows)
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function getAutocompleteDataEx() {
|
||||
loading.value = true
|
||||
|
||||
getAutocompleteDataExApi({
|
||||
q: searchValue.value,
|
||||
page: pagination.value.current,
|
||||
limit: pagination.value.pageSize,
|
||||
viewname: props.viewname,
|
||||
field1: props.field1,
|
||||
field2: props.field2,
|
||||
userid: props.userid,
|
||||
searchcondition: props.searchcondition,
|
||||
}).then((res) => {
|
||||
pagination.value.total = res.data.total
|
||||
|
||||
options.value = res.data.rows.map(item => ({
|
||||
label: item[props.labelField] ?? '',
|
||||
value: item[props.valueField] ?? undefined,
|
||||
disabled: !!item.disabled,
|
||||
...item,
|
||||
}))
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function getAutocompleteDataSingle() {
|
||||
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
_visible.value = false
|
||||
emit('update:visible', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<sar-popout
|
||||
:visible="_visible"
|
||||
:show-footer="false"
|
||||
title="请选择"
|
||||
@enter="handleAfterEnter"
|
||||
@close="handleCancel"
|
||||
>
|
||||
<template v-if="props.type === 'multiple'" #title-prepend>
|
||||
<view class="sar-checkbox-popout__check-all">
|
||||
<sar-checkbox
|
||||
v-model:checked="allChecked"
|
||||
:indeterminate="isIndeterminate"
|
||||
@change="onAllChange"
|
||||
>
|
||||
{{ count }}
|
||||
</sar-checkbox>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template #visible="{ already }">
|
||||
<view v-if="already">
|
||||
<sar-list-item>
|
||||
<sar-input
|
||||
v-model="searchValue"
|
||||
placeholder="请输入搜索的值"
|
||||
clearable
|
||||
@confirm="handleSearch"
|
||||
>
|
||||
<template #prepend>
|
||||
<sar-icon family="sari" name="search" />
|
||||
</template>
|
||||
</sar-input>
|
||||
</sar-list-item>
|
||||
|
||||
<view class="sar-checkbox-popout__container">
|
||||
<scroll-view
|
||||
class="sar-checkbox-popout__scroll_searchable sar-checkbox-popout__scroll"
|
||||
scroll-y
|
||||
trap-scroll
|
||||
:upper-threshold="0"
|
||||
:lower-threshold="0"
|
||||
:throttle="false"
|
||||
>
|
||||
<sar-empty
|
||||
v-if="options.length === 0"
|
||||
:root-style="{ height: '100%' }"
|
||||
/>
|
||||
|
||||
<sar-checkbox-group
|
||||
v-else-if="props.type === 'multiple'"
|
||||
v-model="_value"
|
||||
:validate-event="false"
|
||||
>
|
||||
<template #custom="{ toggle }">
|
||||
<sar-list inlaid>
|
||||
<sar-list-item
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:title="option.label"
|
||||
@click="select(option, toggle)"
|
||||
>
|
||||
<template #icon>
|
||||
<sar-checkbox
|
||||
readonly
|
||||
:value="option.value"
|
||||
:validate-event="false"
|
||||
/>
|
||||
</template>
|
||||
</sar-list-item>
|
||||
</sar-list>
|
||||
</template>
|
||||
</sar-checkbox-group>
|
||||
|
||||
<sar-radio-group
|
||||
v-else
|
||||
v-model="_value"
|
||||
:validate-event="false"
|
||||
>
|
||||
<template #custom="{ toggle }">
|
||||
<sar-list inlaid>
|
||||
<sar-list-item
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
:title="option.label"
|
||||
:hover="!option.disabled"
|
||||
@click="select(option, toggle)"
|
||||
>
|
||||
<template #icon>
|
||||
<sar-radio
|
||||
:key="option.value"
|
||||
readonly
|
||||
:disabled="option.disabled"
|
||||
:value="option.value"
|
||||
/>
|
||||
</template>
|
||||
</sar-list-item>
|
||||
</sar-list>
|
||||
</template>
|
||||
</sar-radio-group>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view class="sar-popout__footer">
|
||||
<sar-pagination
|
||||
:current="pagination.current"
|
||||
:total="pagination.total"
|
||||
:page-size="pagination.pageSize"
|
||||
type="simple"
|
||||
root-class="picker-select__pagination-root"
|
||||
@change="handlePagationChange"
|
||||
>
|
||||
<template #prev>
|
||||
<sar-button type="default" :disabled="isPrevDisabled" size="mini" :loading="loading">
|
||||
上一页
|
||||
</sar-button>
|
||||
</template>
|
||||
<template #next>
|
||||
<sar-button type="default" :disabled="isNextDisabled" size="mini" :loading="loading">
|
||||
下一页
|
||||
</sar-button>
|
||||
</template>
|
||||
</sar-pagination>
|
||||
|
||||
<sar-button
|
||||
v-if="props.type === 'multiple'"
|
||||
:root-style="{ width: '100%' }"
|
||||
>
|
||||
确认
|
||||
</sar-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</sar-popout>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.sar-checkbox-popout__check-all {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
left: 32rpx;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
color: var(--sar-tertiary-color);
|
||||
font-size: var(--sar-text-sm);
|
||||
}
|
||||
|
||||
.sar-checkbox-popout__container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sar-checkbox-popout__scroll_searchable {
|
||||
height: var(--sar-checkbox-popout-max-height);
|
||||
}
|
||||
|
||||
.sar-checkbox-popout__scroll {
|
||||
max-height: var(--sar-checkbox-popout-max-height);
|
||||
}
|
||||
|
||||
.sar-popout__footer {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
align-items: center;
|
||||
padding: var(--sar-popout-footer-gap-y) var(--sar-popout-footer-gap-x);
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user