| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- <template>
- <view class="nana-form-picker">
- <slot v-if="loaded && (columns.length === 0 || (columns.length === 1 && columns[0].length === 0))" name="empty">
- <Empty description="暂无可选数据" :innerStyle="{ position: 'absolute', width: '100%' }" />
- </slot>
- <picker-view
- v-else-if="loaded"
- :value="pickerSelectIndex"
- class="picker-view"
- :style="{
- width: themeContext.resolveThemeSize(pickerWidth),
- height: themeContext.resolveThemeSize(pickerHeight),
- }"
- immediate-change
- @change="bindChange"
- >
- <picker-view-column v-for="(column,c) in columns" :key="c">
- <view class="item" v-for="(item,k) in column" :key="k">{{item.text}}</view>
- </picker-view-column>
- </picker-view>
- </view>
- </template>
- <script setup lang="ts">
- import { nextTick, onMounted, ref, watch } from 'vue';
- import { useTheme } from '../theme/ThemeDefine';
- import Empty from '../feedback/Empty.vue';
- const themeContext = useTheme();
- export interface PickerItem {
- text: string;
- value: string|number;
- }
- export interface PickerProps {
- /**
- * 选择器列
- */
- columns: PickerItem[][];
- /**
- * 选中Value
- */
- value: (number|string)[],
- /**
- * picker高度
- * @default 300
- */
- pickerHeight?: string|number,
- /**
- * picker宽度
- * @default 750
- */
- pickerWidth?: string|number,
- /**
- * 是否在columns只有一列情况下value返回一个值
- * @default false
- */
- singleValue?: boolean,
- }
- const emit = defineEmits([ 'update:value', 'selectTextChange' ]);
- const props = withDefaults(defineProps<PickerProps>(), {
- pickerHeight: 300,
- pickerWidth: 750,
- });
- const loaded = ref(false);
- const pickerSelectIndex = ref<number[]>([]);
- function bindChange(e: any) {
- const val = e.detail.value as number[];
- for (let i = 0; i < props.columns.length; i++)
- if (val[i] === undefined)
- val[i] = 0;
- const value = val.map((p, i) => {
- const cols = props.columns[i];
- if (!cols || cols.length === 0)
- return null;
- return cols[p].value ?? cols[0].value ?? null;
- });
- pickerSelectIndex.value = val;
- if (props.singleValue && props.columns.length === 1)
- emit('update:value', value[0]);
- else
- emit('update:value', value);
- emit('selectTextChange', val.map((p, i) => {
- const cols = props.columns[i];
- if (!cols || cols.length === 0)
- return null;
- return cols[p].text ?? cols[0].text ?? null;
- }).join(' '));
- }
- function loadValues() {
- const value = typeof props.value === 'number' || typeof props.value === 'string' ? [props.value] : props.value ?? [];
- value.forEach((v,i) => {
- const index = props.columns[i]?.findIndex((item) => item.value === v);
- pickerSelectIndex.value[i] = index < 0 ? 0 : index;
- });
- emit('selectTextChange', pickerSelectIndex.value.map((p, i) => {
- const cols = props.columns[i];
- if (!cols || cols.length === 0)
- return null;
- return cols[p]?.text ?? cols[0]?.text ?? null;
- }).join(' '), true);
- }
- watch(() => props.value, (v) => {
- loadValues();
- })
- onMounted(() => {
- nextTick(() => {
- loadValues();
- loaded.value = true;
- })
- })
- const themeStyles = themeContext.useThemeStyles({
- });
- defineOptions({
- options: {
- styleIsolation: "shared",
- virtualHost: true,
- }
- })
- </script>
- <style lang="scss">
- .nana-form-picker {
- position: relative;
- display: flex;
- flex-direction: row;
- align-items: center;
- .picker-view {
- .item {
- text-align: center;
- }
- }
- }
- </style>
|