mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 17:18:40 +08:00
refactor: ♻️ 重构Picker和Cell
This commit is contained in:
parent
fb7580df7e
commit
24243ca55c
@ -1,3 +1,13 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-11-14 21:27:00
|
||||
* @LastEditTime: 2024-11-14 22:17:54
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: /wot-design-uni/src/hooks/useColPickerData.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import type { ColPickerOption } from '@/uni_modules/wot-design-uni/components/wd-col-picker/types'
|
||||
import { useCascaderAreaData } from '@vant/area-data'
|
||||
|
||||
export type CascaderOption = {
|
||||
@ -15,7 +25,7 @@ export function useColPickerData() {
|
||||
const colPickerData: CascaderOption[] = useCascaderAreaData()
|
||||
|
||||
// 根据code查找子节点,不传code则返回所有节点
|
||||
function findChildrenByCode(data: CascaderOption[], code?: string): CascaderOption[] | null {
|
||||
function findChildrenByCode(data: CascaderOption[], code?: string | number): CascaderOption[] | null {
|
||||
if (!code) {
|
||||
return data
|
||||
}
|
||||
@ -33,5 +43,25 @@ export function useColPickerData() {
|
||||
return null
|
||||
}
|
||||
|
||||
return { colPickerData, findChildrenByCode }
|
||||
function findNodeByCodeList(codeList: string[]): ColPickerOption[] {
|
||||
const result: ColPickerOption[] = []
|
||||
let data = colPickerData
|
||||
|
||||
for (const code of codeList) {
|
||||
const item = data.find((item) => item.value === code)
|
||||
if (item) {
|
||||
result.push({
|
||||
text: item.text,
|
||||
value: item.value
|
||||
})
|
||||
data = item.children || []
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
return { colPickerData, findChildrenByCode, findNodeByCodeList }
|
||||
}
|
||||
|
||||
@ -2,14 +2,14 @@
|
||||
<page-wraper>
|
||||
<wd-toast />
|
||||
<demo-block title="基本用法" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="标题文字" value="内容" />
|
||||
<wd-cell title="标题文字" label="描述信息" value="内容" />
|
||||
</wd-cell-group>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="图标" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="标题文字" value="内容" icon="setting" />
|
||||
<wd-cell title="标题文字" value="内容">
|
||||
<template #icon>
|
||||
@ -20,14 +20,14 @@
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="分组标题" transparent>
|
||||
<wd-cell-group title="交易管理" value="内容">
|
||||
<wd-cell-group border title="交易管理" value="内容">
|
||||
<wd-cell title="标题文字" value="内容" />
|
||||
<wd-cell title="标题文字" label="描述信息" value="内容"></wd-cell>
|
||||
</wd-cell-group>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="大尺寸" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell size="large" title="标题文字" value="内容" />
|
||||
<wd-cell title="标题文字" value="内容" size="large" icon="setting" is-link />
|
||||
<wd-cell size="large" title="标题文字" label="描述信息" value="内容" />
|
||||
@ -43,20 +43,20 @@
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="点击事件" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="标题文字" value="内容" clickable @click="showToast" />
|
||||
</wd-cell-group>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="页面跳转" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="帮助与反馈" is-link to="/pages/index/Index" />
|
||||
<wd-cell title="设置" value="内容" is-link to="/pages/button/Index" replace></wd-cell>
|
||||
</wd-cell-group>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="垂直居中" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="标题文字" value="内容" center />
|
||||
<wd-cell title="标题文字" label="描述信息" value="内容" center />
|
||||
</wd-cell-group>
|
||||
@ -74,13 +74,13 @@
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="设置宽度" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="标题文字" label="这里是文字描述这里是文字描述这里是文字描述" title-width="200px" value="内容" />
|
||||
</wd-cell-group>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="自定义slot" transparent>
|
||||
<wd-cell-group>
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="标题文字" center>
|
||||
<wd-button custom-class="custom-value" size="small" plain>按钮</wd-button>
|
||||
</wd-cell>
|
||||
|
||||
@ -1,83 +1,143 @@
|
||||
<template>
|
||||
<page-wraper>
|
||||
<wd-toast />
|
||||
<wd-col-picker
|
||||
v-model:visible="visible.visible1"
|
||||
v-model="value1"
|
||||
:columns="areaData1"
|
||||
:column-change="columnChange1"
|
||||
@confirm="(result) => handleConfirm({ ...result, index: 1 })"
|
||||
/>
|
||||
|
||||
<wd-col-picker
|
||||
v-model:visible="visible.visible2"
|
||||
v-model="value2"
|
||||
:columns="areaData2"
|
||||
:column-change="columnChange"
|
||||
@confirm="(result) => handleConfirm({ ...result, index: 2 })"
|
||||
auto-complete
|
||||
/>
|
||||
<wd-col-picker
|
||||
v-model:visible="visible.visible3"
|
||||
v-model="value4"
|
||||
:columns="areaData4"
|
||||
:column-change="columnChange1"
|
||||
@confirm="(result) => handleConfirm({ ...result, index: 3 })"
|
||||
/>
|
||||
|
||||
<wd-col-picker
|
||||
v-model:visible="visible.visible4"
|
||||
v-model="value4"
|
||||
:columns="areaData5"
|
||||
:column-change="columnChange1"
|
||||
@confirm="(result) => handleConfirm({ ...result, index: 4 })"
|
||||
/>
|
||||
|
||||
<wd-col-picker
|
||||
v-model="value7"
|
||||
v-model:visible="visible.visible5"
|
||||
title="选择地址"
|
||||
:columns="areaData1"
|
||||
:column-change="columnChange1"
|
||||
@confirm="(result) => handleConfirm({ ...result, index: 5 })"
|
||||
/>
|
||||
|
||||
<wd-col-picker
|
||||
v-model:visible="visible.visible6"
|
||||
v-model="value8"
|
||||
:columns="areaData1"
|
||||
:column-change="columnChange1"
|
||||
:before-confirm="beforeConfirm"
|
||||
@confirm="(result) => handleConfirm({ ...result, index: 6 })"
|
||||
/>
|
||||
|
||||
<wd-col-picker
|
||||
label="选择地址"
|
||||
v-model="value11"
|
||||
v-model:visible="visible.visible7"
|
||||
:columns="areaData1"
|
||||
@confirm="(result) => handleConfirm({ ...result, index: 7 })"
|
||||
:column-change="columnChange2"
|
||||
/>
|
||||
|
||||
<view style="margin: 20px 0">
|
||||
<wd-cell-group border>
|
||||
<wd-col-picker label="选择地址" v-model="value1" :columns="areaData1" :column-change="columnChange1" @confirm="handleValue" />
|
||||
<wd-col-picker label="初始选项" v-model="value2" :columns="areaData2" :column-change="columnChange" auto-complete />
|
||||
<wd-col-picker label="禁用" disabled v-model="value3" :columns="areaData3" :column-change="columnChange1" />
|
||||
<wd-col-picker label="只读" readonly v-model="value3" :columns="areaData3" :column-change="columnChange1" />
|
||||
<wd-col-picker label="禁用选项" v-model="value4" :columns="areaData4" :column-change="columnChange1" />
|
||||
<wd-col-picker label="选项提示信息" v-model="value5" :columns="areaData5" :column-change="columnChange1" />
|
||||
<wd-col-picker label="展示格式化" v-model="value6" :columns="areaData3" :column-change="columnChange1" :display-format="displayFormat" />
|
||||
<wd-col-picker label="标题" v-model="value7" title="选择地址" :columns="areaData1" :column-change="columnChange1" />
|
||||
<wd-col-picker label="before-confirm" v-model="value8" :columns="areaData1" :column-change="columnChange1" :before-confirm="beforeConfirm" />
|
||||
<wd-col-picker label="错误" error v-model="value9" :columns="areaData1" :column-change="columnChange1" />
|
||||
<wd-col-picker label="必填" required v-model="value10" :columns="areaData1" :column-change="columnChange1" />
|
||||
<wd-cell title="选择地址" :value="cellValue.value1" is-link @click="visible.visible1 = true"></wd-cell>
|
||||
<wd-cell title="初始选项" :value="cellValue.value2" is-link @click="visible.visible2 = true"></wd-cell>
|
||||
<wd-cell title="禁用选项" :value="cellValue.value3" is-link @click="visible.visible3 = true"></wd-cell>
|
||||
<wd-cell title="选项提示信息" :value="cellValue.value4" is-link @click="visible.visible4 = true"></wd-cell>
|
||||
<wd-cell title="自定义标题" :value="cellValue.value5" is-link @click="visible.visible5 = true"></wd-cell>
|
||||
<wd-cell title="before-confirm" :value="cellValue.value6" is-link @click="visible.visible6 = true"></wd-cell>
|
||||
<wd-cell title="加载动画" :value="cellValue.value7" is-link @click="visible.visible7 = true"></wd-cell>
|
||||
</wd-cell-group>
|
||||
</view>
|
||||
<demo-block title="一般column-change是个异步获取数据的操作,触发column-change组件会有默认loading,数据响应后关闭loading" transparent>
|
||||
<wd-col-picker label="选择地址" v-model="value11" :columns="areaData1" :column-change="columnChange2" />
|
||||
</demo-block>
|
||||
<demo-block title="label不传" transparent>
|
||||
<wd-col-picker v-model="value12" :columns="areaData1" :column-change="columnChange1" />
|
||||
</demo-block>
|
||||
<demo-block title="大小" transparent>
|
||||
<wd-col-picker label="选择地址" v-model="value13" size="large" :columns="areaData1" :column-change="columnChange1" />
|
||||
</demo-block>
|
||||
<demo-block title="值靠右展示" transparent>
|
||||
<wd-col-picker label="选择地址" align-right v-model="value14" :columns="areaData1" :column-change="columnChange1" />
|
||||
</demo-block>
|
||||
<demo-block title="自定义选择器" transparent>
|
||||
<view style="margin-left: 15px">
|
||||
<view style="margin-bottom: 10px">当前选中项: {{ displayValue }}</view>
|
||||
<wd-col-picker
|
||||
v-model="value15"
|
||||
use-default-slot
|
||||
:columns="areaData1"
|
||||
:column-change="columnChange1"
|
||||
style="display: inline-block"
|
||||
@confirm="handleConfirm"
|
||||
>
|
||||
<wd-button>选择地址</wd-button>
|
||||
</wd-col-picker>
|
||||
</view>
|
||||
</demo-block>
|
||||
<wd-toast />
|
||||
</page-wraper>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { useToast } from '@/uni_modules/wot-design-uni'
|
||||
import type { ColPickerColumnChange } from '@/uni_modules/wot-design-uni/components/wd-col-picker/types'
|
||||
import type { ColPickerColumnChange, ColPickerOption } from '@/uni_modules/wot-design-uni/components/wd-col-picker/types'
|
||||
import { useColPickerData } from '@/hooks/useColPickerData'
|
||||
|
||||
const { colPickerData, findChildrenByCode } = useColPickerData()
|
||||
const { colPickerData, findChildrenByCode, findNodeByCodeList } = useColPickerData()
|
||||
const toast = useToast()
|
||||
|
||||
onMounted(async () => {
|
||||
toast.loading('数据加载中')
|
||||
await sleep()
|
||||
toast.close()
|
||||
value2.value = ['150000', '150100', '150121']
|
||||
const result = findNodeByCodeList(value2.value)
|
||||
cellValue.value2 = result.map((item) => item.text).join('/')
|
||||
})
|
||||
|
||||
const value1 = ref<any[]>([])
|
||||
const visible = reactive({
|
||||
visible1: false,
|
||||
visible2: false,
|
||||
visible3: false,
|
||||
visible4: false,
|
||||
visible5: false,
|
||||
visible6: false,
|
||||
visible7: false,
|
||||
visible8: false,
|
||||
visible9: false,
|
||||
visible10: false,
|
||||
visible11: false,
|
||||
visible12: false,
|
||||
visible13: false,
|
||||
visible14: false,
|
||||
visible15: false
|
||||
})
|
||||
|
||||
const cellValue = reactive<{ [key: PropertyKey]: any }>({
|
||||
value1: '',
|
||||
value2: '',
|
||||
value3: '',
|
||||
value4: '',
|
||||
value5: '',
|
||||
value6: '',
|
||||
value7: '',
|
||||
value8: '',
|
||||
value9: '',
|
||||
value10: '',
|
||||
value11: ''
|
||||
})
|
||||
|
||||
const value1 = ref<string[]>([])
|
||||
const value2 = ref<string[]>([])
|
||||
const value3 = ref<any[]>(['130000', '130200', '130204'])
|
||||
const value4 = ref<any[]>([])
|
||||
const value5 = ref<any[]>([])
|
||||
const value6 = ref<any[]>(['130000', '130200', '130204'])
|
||||
const value7 = ref<any[]>([])
|
||||
const value8 = ref<any[]>([])
|
||||
const value9 = ref<any[]>([])
|
||||
const value10 = ref<any[]>([])
|
||||
const value11 = ref<any[]>([])
|
||||
const value12 = ref<any[]>([])
|
||||
const value13 = ref<any[]>([])
|
||||
const value14 = ref<any[]>([])
|
||||
const value15 = ref<any[]>([])
|
||||
const value3 = ref<string[]>(['130000', '130200', '130204'])
|
||||
const value4 = ref<string[]>([])
|
||||
const value5 = ref<string[]>([])
|
||||
const value6 = ref<string[]>(['130000', '130200', '130204'])
|
||||
const value7 = ref<string[]>([])
|
||||
const value8 = ref<string[]>([])
|
||||
const value9 = ref<string[]>([])
|
||||
const value10 = ref<string[]>([])
|
||||
const value11 = ref<string[]>([])
|
||||
const value12 = ref<string[]>([])
|
||||
const value13 = ref<string[]>([])
|
||||
const value14 = ref<string[]>([])
|
||||
const value15 = ref<string[]>([])
|
||||
const displayValue = ref<string>('')
|
||||
const areaData1 = ref<any[]>([
|
||||
const areaData1 = ref<ColPickerOption[][]>([
|
||||
colPickerData.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
@ -86,8 +146,8 @@ const areaData1 = ref<any[]>([
|
||||
})
|
||||
])
|
||||
|
||||
const areaData2 = ref<any[]>([])
|
||||
const areaData3 = ref<any[]>([
|
||||
const areaData2 = ref<ColPickerOption[][]>([])
|
||||
const areaData3 = ref<ColPickerOption[][]>([
|
||||
colPickerData.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
@ -107,7 +167,7 @@ const areaData3 = ref<any[]>([
|
||||
}
|
||||
})
|
||||
])
|
||||
const areaData4 = ref<any[]>([
|
||||
const areaData4 = ref<ColPickerOption[][]>([
|
||||
colPickerData.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
@ -143,7 +203,7 @@ const columnChange1: ColPickerColumnChange = ({ selectedItem, resolve, finish })
|
||||
}
|
||||
}
|
||||
|
||||
const columnChange: ColPickerColumnChange = async ({ selectedItem, resolve, finish }) => {
|
||||
const columnChange: ColPickerColumnChange = async ({ selectedItem, index, resolve, finish }) => {
|
||||
await sleep(0.3)
|
||||
const areaData = findChildrenByCode(colPickerData, selectedItem.value)
|
||||
if (areaData && areaData.length) {
|
||||
@ -182,10 +242,10 @@ const columnChange2: ColPickerColumnChange = ({ selectedItem, resolve, finish })
|
||||
}
|
||||
}, 300)
|
||||
}
|
||||
const displayFormat = (selectedItems: Record<string, any>[]) => {
|
||||
const displayFormat = (selectedItems: ColPickerOption[]) => {
|
||||
return selectedItems[selectedItems.length - 2].label + '-' + selectedItems[selectedItems.length - 1].label
|
||||
}
|
||||
const beforeConfirm = (value: (string | number)[], selectedItems: Record<string, any>[], resolve: (isPass: boolean) => void) => {
|
||||
const beforeConfirm = (value: (string | number)[], selectedItems: ColPickerOption[], resolve: (isPass: boolean) => void) => {
|
||||
if (parseInt(String(value[2])) > 120000) {
|
||||
toast.error('该地区库存不足')
|
||||
resolve(false)
|
||||
@ -202,15 +262,12 @@ function sleep(second: number = 1) {
|
||||
})
|
||||
}
|
||||
|
||||
function handleConfirm({ selectedItems }: any) {
|
||||
displayValue.value = selectedItems
|
||||
.map((item: any) => {
|
||||
function handleConfirm({ selectedItems, index }: { selectedItems: ColPickerOption[]; index: number }) {
|
||||
cellValue[`value${index}`] = selectedItems
|
||||
.map((item) => {
|
||||
return item.label
|
||||
})
|
||||
.join('')
|
||||
}
|
||||
function handleValue({ value }: any) {
|
||||
console.log(value)
|
||||
.join('/')
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
<demo-block title="进度条状态">
|
||||
<wd-progress :percentage="100" hide-text status="success" />
|
||||
<wd-progress :percentage="80" hide-text status="danger" />
|
||||
<wd-progress :percentage="90" hide-text status="warning" />
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="修改颜色">
|
||||
@ -24,9 +25,10 @@
|
||||
</page-wraper>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import type { ProgressColor } from '@/uni_modules/wot-design-uni/components/wd-progress/types'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const colorObject = ref<any>([
|
||||
const colorObject = ref<ProgressColor[]>([
|
||||
{
|
||||
color: 'yellow',
|
||||
percentage: 30
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
* 辅助函数
|
||||
*/
|
||||
@import 'config';
|
||||
$default-theme: #4d80f0 !default; // 正常色
|
||||
|
||||
/* 转换成字符串 */
|
||||
@function selectorToString($selector) {
|
||||
@ -37,53 +36,3 @@ $default-theme: #4d80f0 !default; // 正常色
|
||||
@return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 主题色切换
|
||||
* @params $theme-color 主题色
|
||||
* @params $type 变暗’dark‘ 变亮 'light'
|
||||
* @params $mix-color 自己设置的混色
|
||||
*/
|
||||
@function themeColor($theme-color, $type: "", $mix-color: "") {
|
||||
@if $default-theme !=#4d80f0 {
|
||||
@if $type=="dark" {
|
||||
@return darken($theme-color, 10%);
|
||||
}
|
||||
|
||||
@else if $type=="light" {
|
||||
@return lighten($theme-color, 10%);
|
||||
}
|
||||
|
||||
@else {
|
||||
@return $theme-color;
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
@return $mix-color;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 颜色结果切换, 如果开启线性渐变色 使用渐变色,如果没有开启,那么使用主题色
|
||||
* @params $open-linear 是否开启线性渐变色
|
||||
* @params $deg 渐变色角度
|
||||
* @params $theme-color 当前配色
|
||||
* @params [Array] $set 主题色明暗设置,与 $color-list 数量对应
|
||||
* @params [Array] $color-list 渐变色顺序, $color-list 和 $per-list 数量相同
|
||||
* @params [Array] $per-list 渐变色比例
|
||||
*/
|
||||
@function resultColor($deg, $theme-color, $set, $color-list, $per-list) {
|
||||
// 开启渐变
|
||||
|
||||
$len: length($color-list);
|
||||
$arg: $deg;
|
||||
|
||||
@for $i from 1 through $len {
|
||||
$arg: $arg + ","+ themeColor($theme-color, nth($set, $i), nth($color-list, $i)) + " "+ nth($per-list, $i);
|
||||
}
|
||||
|
||||
@return linear-gradient(unquote($arg));
|
||||
|
||||
}
|
||||
@ -5,9 +5,9 @@
|
||||
*/
|
||||
/*----------------------------------------- Theme color. start ----------------------------------------*/
|
||||
/* 主题颜色 */
|
||||
$-color-theme: var(--wot-color-theme, $default-theme) !default; // 主题色
|
||||
$-color-white: var(--wot-color-white, rgb(255, 255, 255)) !default; // 用于mix的白色
|
||||
$-color-black: var(--wot-color-black, rgb(0, 0, 0)) !default; // 用于mix的黑色
|
||||
$-color-theme: var(--wot-color-theme, #4d80f0) !default; // 主题色
|
||||
$-color-white: var(--wot-color-white, #ffffff) !default; // 白色
|
||||
$-color-black: var(--wot-color-black, #000000) !default; // 黑色
|
||||
|
||||
/* 辅助色 */
|
||||
$-color-success: var(--wot-color-success, #34d19d) !default; // 成功色
|
||||
@ -170,19 +170,17 @@ $-button-error-bg-color: var(--wot-button-error-bg-color, $-color-danger) !defau
|
||||
$-button-text-hover-opacity: var(--wot-button-text-hover-opacity, 0.7) !default; // 文字button激活时透明度
|
||||
|
||||
/* cell */
|
||||
$-cell-padding: var(--wot-cell-padding, $-size-side-padding) !default; // cell 左右padding距离
|
||||
$-cell-line-height: var(--wot-cell-line-height, 24px) !default; // 行高
|
||||
$-cell-vertical-padding: var(--wot-cell-vertical-padding, $-size-side-padding) !default; // cell 左右padding距离
|
||||
$-cell-horizontal-padding: var(--wot-cell-horizontal-padding, 10px) !default; // cell 上下padding
|
||||
$-cell-horizontal-padding-large: var(--wot-cell-horizontal-padding-large, 12px) !default; // large类型cell上下padding
|
||||
$-cell-horizontal-padding-with-label: var(--wot-cell-wrapper-padding-with-label, 16px) !default; // cell 上下padding(有label情况下)
|
||||
|
||||
$-cell-line-height: var(--wot-cell-line-height, 24px) !default; // 行高
|
||||
$-cell-group-title-fs: var(--wot-cell-group-title-fs, $-fs-title) !default; // 组标题字号
|
||||
$-cell-group-padding: var(--wot-cell-group-padding, 13px $-cell-padding) !default; // 组padding
|
||||
$-cell-group-padding: var(--wot-cell-group-padding, 13px $-cell-vertical-padding) !default; // 组padding
|
||||
$-cell-group-title-color: var(--wot-cell-group-title-color, rgba(0, 0, 0, 0.85)) !default; // 组标题文字颜色
|
||||
$-cell-group-value-fs: var(--wot-cell-group-value-fs, $-fs-content) !default; // 组值字号
|
||||
$-cell-group-value-color: var(--wot-cell-group-value-color, $-color-content) !default; // 组值文字颜色
|
||||
|
||||
$-cell-wrapper-padding: var(--wot-cell-wrapper-padding, 10px) !default; // cell 容器padding
|
||||
$-cell-wrapper-padding-large: var(--wot-cell-wrapper-padding-large, 12px) !default; // large类型cell容器padding
|
||||
|
||||
$-cell-wrapper-padding-with-label: var(--wot-cell-wrapper-padding-with-label, 16px) !default; // cell 容器上下padding(有label情况下)
|
||||
$-cell-icon-right: var(--wot-cell-icon-right, 4px) !default; // 图标距离右边缘
|
||||
$-cell-icon-size: var(--wot-cell-icon-size, 16px) !default; // 图标大小
|
||||
$-cell-title-fs: var(--wot-cell-title-fs, 14px) !default; // 标题字号
|
||||
@ -457,10 +455,7 @@ $-col-picker-selected-color: var(--wot-col-picker-selected-color, rgba(0, 0, 0,
|
||||
$-col-picker-selected-fw: var(--wot-col-picker-selected-fw, 700) !default; // 弹框顶部值高亮字重
|
||||
$-col-picker-line-width: var(--wot-col-picker-line-width, 16px) !default; // 弹框顶部值高亮线条宽度
|
||||
$-col-picker-line-height: var(--wot-col-picker-line-height, 3px) !default; // 弹框顶部值高亮线条高度
|
||||
$-col-picker-line-color: var(
|
||||
--wot-col-picker-line-color,
|
||||
linear-gradient(315deg, rgba(81, 124, 240, 1), rgba(118, 158, 245, 1))
|
||||
) !default; // 弹框顶部值高亮线条颜色
|
||||
$-col-picker-line-color: var(--wot-col-picker-line-color,linear-gradient(315deg, rgba(81, 124, 240, 1), rgba(118, 158, 245, 1))) !default; // 弹框顶部值高亮线条颜色
|
||||
$-col-picker-line-box-shadow: var(--wot-col-picker-line-box-shadow, 0px 1px 2px 0px rgba(1, 87, 255, 0.2)) !default; // 弹框顶部值高亮线条阴影
|
||||
$-col-picker-list-height: var(--wot-col-picker-list-height, 53vh) !default; // 弹框列表高度
|
||||
$-col-picker-list-padding-bottom: var(--wot-col-picker-list-padding-bottom, 30px) !default; // 弹框列表底部间距
|
||||
@ -486,15 +481,9 @@ $-progress-padding: var(--wot-progress-padding, 9px 0 8px) !default; // 进度
|
||||
$-progress-bg: var(--wot-progress-bg, rgba(229, 229, 229, 1)) !default; // 进度条底色
|
||||
$-progress-danger-color: var(--wot-progress-danger-color, $-color-danger) !default; // 进度条danger颜色
|
||||
$-progress-success-color: var(--wot-progress-success-color, $-color-success) !default; // 进度条success进度条颜色
|
||||
$-progress-color: var(--wot-progress-color, resultColor(315deg, $-color-theme, 'dark' 'light', #517cf0 #769ef5, 0% 100%)) !default; // 进度条渐变色
|
||||
$-progress-linear-success-color: var(
|
||||
--wot-progress-linear-success-color,
|
||||
resultColor(315deg, $-color-theme, 'dark' 'light', #20b080 #2bd69d, 0% 100%)
|
||||
) !default; // success进度条渐变色
|
||||
$-progress-linear-danger-color: var(
|
||||
--wot-progress-linear-danger-color,
|
||||
resultColor(315deg, $-color-theme, 'dark' 'light', #e04350 #ff5964, 0% 100%)
|
||||
) !default; // danger进度条渐变色
|
||||
$-progress-warning-color: var(--wot-progress-warning-color, $-color-warning) !default; // 进度条warning进度条颜色
|
||||
|
||||
$-progress-color: var(--wot-progress-color, $-color-success) !default; // 进度条颜色
|
||||
$-progress-height: var(--wot-progress-height, 3px) !default; // 进度条高度
|
||||
$-progress-label-color: var(--wot-progress-label-color, #333) !default; // 文字颜色
|
||||
$-progress-label-fs: var(--wot-progress-label-fs, 14px) !default; // 文字字号
|
||||
@ -552,14 +541,11 @@ $-search-light-bg: var(--wot-search-light-bg, $-color-bg) !default; // light 类
|
||||
/* slider */
|
||||
$-slider-fs: var(--wot-slider-fs, $-fs-content) !default; // 字体大小
|
||||
$-slider-handle-radius: var(--wot-slider-handle-radius, 12px) !default; // 滑块半径
|
||||
$-slider-handle-bg: var(--wot-slider-handle-bg, resultColor(139deg, $-color-theme, 'dark' 'light', #ffffff #f7f7f7, 0% 100%)) !default; // 滑块背景
|
||||
$-slider-handle-bg: var(--wot-slider-handle-bg, $-color-white) !default; // 滑块背景
|
||||
$-slider-axie-height: var(--wot-slider-axie-height, 3px) !default; // 滑轴高度
|
||||
$-slider-color: var(--wot-slider-color, #333) !default; // 字体颜色
|
||||
$-slider-axie-bg: var(--wot-slider-axie-bg, #e5e5e5) !default; // 滑轴的默认背景色
|
||||
$-slider-line-color: var(
|
||||
--wot-slider-line-color,
|
||||
resultColor(315deg, $-color-theme, 'dark' 'light', #517cf0 #769ef5, 0% 100%)
|
||||
) !default; // 进度条颜色
|
||||
$-slider-line-color: var(--wot-slider-line-color, $-color-theme) !default; // 进度条颜色
|
||||
$-slider-disabled-color: var(--wot-slider-disabled-color, rgba(0, 0, 0, 0.25)) !default; // 禁用状态下字体颜色
|
||||
|
||||
/* sort-button */
|
||||
@ -628,7 +614,7 @@ $-tag-primary-color: var(--wot-tag-primary-color, $-color-theme) !default; //
|
||||
$-tag-danger-color: var(--wot-tag-danger-color, $-color-danger) !default; // danger 颜色
|
||||
$-tag-warning-color: var(--wot-tag-warning-color, $-color-warning) !default; // warning 颜色
|
||||
$-tag-success-color: var(--wot-tag-success-color, $-color-success) !default; // success 颜色
|
||||
$-tag-info-bg: var(--wot-tag-info-bg, resultColor(49deg, $-color-black, 'dark' 'light', #808080 #999999, 0% 100%)) !default; // info 背景颜色
|
||||
$-tag-info-bg: var(--wot-tag-info-bg, linear-gradient(49deg, #808080 0%, #999999 100%)) !default; // info 背景颜色
|
||||
$-tag-primary-bg: var(--wot-tag-primary-bg, $-color-theme) !default; // 主背景颜色
|
||||
$-tag-danger-bg: var(--wot-tag-danger-bg, $-color-danger) !default; // danger 背景颜色
|
||||
$-tag-warning-bg: var(--wot-tag-warning-bg, $-color-warning) !default; // warning 背景颜色
|
||||
@ -763,7 +749,7 @@ $-circle-text-color: var(--wot-circle-text-color, $-color-content) !default; //
|
||||
/* swiper */
|
||||
$-swiper-radius: var(--wot-swiper-radius, 8px);
|
||||
$-swiper-item-padding: var(--wot-swiper-item-padding, 0);
|
||||
$-swiper-item-text-color: var(--wot-swiper-item-text-color, #ffffff);
|
||||
$-swiper-item-text-color: var(--wot-swiper-item-text-color, $-color-white);
|
||||
$-swiper-item-text-fs: var(--wot-swiper-item-text-fs, $-fs-title);
|
||||
|
||||
|
||||
@ -787,7 +773,7 @@ $-swiper-nav-btn-size: var(--wot-swiper-nav-btn-size, 48rpx) !default;
|
||||
$-segmented-padding: var(--wot-segmented-padding, 4px) !default; // 分段器padding
|
||||
$-segmented-item-bg-color: var(--wot-segmented-item-bg-color, #eeeeee) !default;
|
||||
$-segmented-item-color: var(--wot-segmented-item-color, rgba(0, 0, 0, 0.85)) !default; // 标题文字颜色
|
||||
$-segmented-item-acitve-bg: var(--wot-segmented-item-acitve-bg, #ffffff) !default; // 标题文字颜色
|
||||
$-segmented-item-acitve-bg: var(--wot-segmented-item-acitve-bg, $-color-white) !default; // 标题文字颜色
|
||||
$-segmented-item-disabled-color: var(--wot-segmented-item-disabled-color, rgba(0, 0, 0, 0.25)) !default; // 标题文字禁用颜色
|
||||
|
||||
/* tabbar */
|
||||
@ -827,7 +813,7 @@ $-navbar-capsule-icon-size: var(--wot-navbar-capsule-icon-size, 20px) !default;
|
||||
|
||||
/* table */
|
||||
$-table-color: var(--wot-table-color, $-font-gray-1) !default; // 表格字体颜色
|
||||
$-table-bg: var(--wot-table-bg, #ffffff) !default; // 表格背景颜色
|
||||
$-table-bg: var(--wot-table-bg, $-color-white) !default; // 表格背景颜色
|
||||
$-table-stripe-bg: var(--wot-table-stripe-bg, #f3f3f3) !default; // 表格背景颜色
|
||||
$-table-border-color: var(--wot-table-border-color, #ececec) !default; // 表格边框颜色
|
||||
$-table-font-size: var(--wot-table-font-size, 13px) !default; // 表格字体大小
|
||||
|
||||
@ -115,7 +115,13 @@ export const actionSheetProps = {
|
||||
* @default true
|
||||
* @type {boolean}
|
||||
*/
|
||||
safeAreaInsetBottom: makeBooleanProp(true)
|
||||
safeAreaInsetBottom: makeBooleanProp(true),
|
||||
/**
|
||||
* 是否当关闭时将弹出层隐藏(display: none)
|
||||
* 类型:boolean
|
||||
* 默认值:true
|
||||
*/
|
||||
hideWhenClose: makeBooleanProp(true)
|
||||
}
|
||||
|
||||
export type ActionSheetProps = ExtractPropTypes<typeof actionSheetProps>
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
:close-on-click-modal="closeOnClickModal"
|
||||
:safe-area-inset-bottom="safeAreaInsetBottom"
|
||||
:lazy-render="lazyRender"
|
||||
:hideWhenClose="hideWhenClose"
|
||||
@enter="handleOpen"
|
||||
@close="close"
|
||||
@after-enter="handleOpened"
|
||||
@ -127,9 +128,6 @@ function select(rowIndex: number, type: 'action' | 'panels', colIndex?: number)
|
||||
}
|
||||
function handleClickModal() {
|
||||
emit('click-modal')
|
||||
// if (props.closeOnClickModal) {
|
||||
// close()
|
||||
// }
|
||||
}
|
||||
function handleCancel() {
|
||||
emit('cancel')
|
||||
|
||||
@ -3,34 +3,15 @@
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(calendar) {
|
||||
@include e(cell) {
|
||||
background-color: $-dark-background2;
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(value) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(title) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
:deep(.wd-calendar__arrow),
|
||||
:deep(.wd-calendar__close) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
|
||||
@include when(border) {
|
||||
.wd-calendar__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding, $-dark-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
@include e(range-label-item) {
|
||||
color: $-dark-color;
|
||||
@ -47,123 +28,6 @@
|
||||
}
|
||||
|
||||
@include b(calendar) {
|
||||
@include when(border) {
|
||||
.wd-calendar__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding);
|
||||
}
|
||||
}
|
||||
|
||||
@include e(cell) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: $-cell-wrapper-padding $-cell-padding;
|
||||
align-items: flex-start;
|
||||
background-color: $-color-white;
|
||||
text-decoration: none;
|
||||
color: $-cell-title-color;
|
||||
font-size: $-cell-title-fs;
|
||||
overflow: hidden;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
|
||||
@include e(cell) {
|
||||
@include when(disabled) {
|
||||
.wd-calendar__value {
|
||||
color: $-input-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include when(align-right) {
|
||||
.wd-calendar__value {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
@include when(error) {
|
||||
.wd-calendar__value {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
|
||||
:deep(.wd-calendar__arrow) {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include when(large) {
|
||||
font-size: $-cell-title-fs-large;
|
||||
|
||||
:deep(.wd-calendar__arrow) {
|
||||
font-size: $-cell-icon-size-large;
|
||||
}
|
||||
}
|
||||
|
||||
@include when(center) {
|
||||
align-items: center;
|
||||
|
||||
:deep(.wd-calendar__arrow) {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include e(error-message){
|
||||
color: $-form-item-error-message-color;
|
||||
font-size: $-form-item-error-message-font-size;
|
||||
line-height: $-form-item-error-message-line-height;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
position: relative;
|
||||
width: $-input-cell-label-width;
|
||||
margin-right: $-cell-padding;
|
||||
color: $-cell-title-color;
|
||||
box-sizing: border-box;
|
||||
|
||||
@include when(required) {
|
||||
padding-left: 12px;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
content: '*';
|
||||
font-size: $-cell-required-size;
|
||||
line-height: 1.1;
|
||||
color: $-cell-required-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include e(value-wraper) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@include e(value) {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
color: $-cell-value-color;
|
||||
|
||||
@include when(ellipsis) {
|
||||
@include lineEllipsis;
|
||||
}
|
||||
|
||||
@include m(placeholder) {
|
||||
color: $-input-placeholder-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(body) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@include edeep(arrow) {
|
||||
display: block;
|
||||
font-size: $-cell-icon-size;
|
||||
color: $-cell-arrow-color;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
|
||||
@include e(header) {
|
||||
position: relative;
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-03-15 20:40:34
|
||||
* @LastEditTime: 2024-06-09 14:38:57
|
||||
* @LastEditTime: 2024-11-13 13:18:15
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-calendar/types.ts
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-calendar\types.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import type { PropType } from 'vue'
|
||||
import { baseProps, makeArrayProp, makeBooleanProp, makeNumberProp, makeRequiredProp, makeStringProp } from '../common/props'
|
||||
import type { CalendarFormatter, CalendarTimeFilter, CalendarType } from '../wd-calendar-view/types'
|
||||
import type { FormItemRule } from '../wd-form/types'
|
||||
|
||||
export const calendarProps = {
|
||||
...baseProps,
|
||||
@ -64,58 +63,10 @@ export const calendarProps = {
|
||||
* type 为 'datetime' 或 'datetimerange' 时有效,是否不展示秒修改
|
||||
*/
|
||||
hideSecond: makeBooleanProp(false),
|
||||
/**
|
||||
* 选择器左侧文案
|
||||
*/
|
||||
label: String,
|
||||
/**
|
||||
* 设置左侧标题宽度
|
||||
*/
|
||||
labelWidth: String,
|
||||
/**
|
||||
* 使用 label 插槽时设置该选项
|
||||
*/
|
||||
useLabelSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 使用默认插槽时设置该选项
|
||||
*/
|
||||
useDefaultSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
disabled: makeBooleanProp(false),
|
||||
/**
|
||||
* 只读
|
||||
*/
|
||||
readonly: makeBooleanProp(false),
|
||||
/**
|
||||
* 选择器占位符
|
||||
*/
|
||||
placeholder: String,
|
||||
/**
|
||||
* 弹出层标题
|
||||
*/
|
||||
title: String,
|
||||
/**
|
||||
* 选择器的值靠右展示
|
||||
*/
|
||||
alignRight: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否为错误状态,错误状态时右侧内容为红色
|
||||
*/
|
||||
error: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
required: makeBooleanProp(false),
|
||||
/**
|
||||
* 设置选择器大小,可选值:large
|
||||
*/
|
||||
size: String,
|
||||
/**
|
||||
* 是否垂直居中
|
||||
*/
|
||||
center: makeBooleanProp(false),
|
||||
/**
|
||||
* 点击遮罩是否关闭
|
||||
*/
|
||||
@ -132,18 +83,10 @@ export const calendarProps = {
|
||||
* 确定按钮文字
|
||||
*/
|
||||
confirmText: String,
|
||||
/**
|
||||
* 自定义展示文案的格式化函数,返回一个字符串
|
||||
*/
|
||||
displayFormat: Function as PropType<CalendarDisplayFormat>,
|
||||
/**
|
||||
* 自定义范围选择类型的面板内部回显,返回一个字符串
|
||||
*/
|
||||
innerDisplayFormat: Function as PropType<CalendarInnerDisplayFormat>,
|
||||
/**
|
||||
* 是否超出隐藏
|
||||
*/
|
||||
ellipsis: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否显示类型切换功能
|
||||
*/
|
||||
@ -164,23 +107,6 @@ export const calendarProps = {
|
||||
* 确定前校验函数,接收 { value, resolve } 参数,通过 resolve 继续执行,resolve 接收 1 个 boolean 参数
|
||||
*/
|
||||
beforeConfirm: Function as PropType<CalendarBeforeConfirm>,
|
||||
/**
|
||||
* 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
|
||||
*/
|
||||
prop: String,
|
||||
/**
|
||||
* 表单验证规则,结合wd-form组件使用
|
||||
*/
|
||||
rules: makeArrayProp<FormItemRule>(),
|
||||
customViewClass: makeStringProp(''),
|
||||
/**
|
||||
* label 外部自定义样式
|
||||
*/
|
||||
customLabelClass: makeStringProp(''),
|
||||
/**
|
||||
* value 外部自定义样式
|
||||
*/
|
||||
customValueClass: makeStringProp(''),
|
||||
/**
|
||||
* 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。
|
||||
*/
|
||||
|
||||
@ -1,34 +1,5 @@
|
||||
<template>
|
||||
<view :class="`wd-calendar ${cell.border.value ? 'is-border' : ''} ${customClass}`">
|
||||
<view class="wd-calendar__field" @click="open">
|
||||
<slot v-if="useDefaultSlot"></slot>
|
||||
<view
|
||||
v-else
|
||||
:class="`wd-calendar__cell ${disabled ? 'is-disabled' : ''} ${readonly ? 'is-readonly' : ''} ${alignRight ? 'is-align-right' : ''} ${
|
||||
error ? 'is-error' : ''
|
||||
} ${size ? 'is-' + size : ''} ${center ? 'is-center' : ''}`"
|
||||
>
|
||||
<view
|
||||
v-if="label || useLabelSlot"
|
||||
:class="`wd-calendar__label ${isRequired ? 'is-required' : ''} ${customLabelClass}`"
|
||||
:style="labelWidth ? 'min-width:' + labelWidth + ';max-width:' + labelWidth + ';' : ''"
|
||||
>
|
||||
<block v-if="label">{{ label }}</block>
|
||||
<slot v-else name="label"></slot>
|
||||
</view>
|
||||
<view class="wd-calendar__body">
|
||||
<view class="wd-calendar__value-wraper">
|
||||
<view
|
||||
:class="`wd-calendar__value ${ellipsis ? 'is-ellipsis' : ''} ${customValueClass} ${showValue ? '' : 'wd-calendar__value--placeholder'}`"
|
||||
>
|
||||
{{ showValue || placeholder || translate('placeholder') }}
|
||||
</view>
|
||||
<wd-icon v-if="!disabled && !readonly" custom-class="wd-calendar__arrow" name="arrow-right" />
|
||||
</view>
|
||||
<view v-if="errorMessage" class="wd-calendar__error-message">{{ errorMessage }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="`wd-calendar ${customClass}`">
|
||||
<wd-action-sheet
|
||||
v-model="pickerShow"
|
||||
:duration="250"
|
||||
@ -124,57 +95,11 @@ import { ref, computed, watch } from 'vue'
|
||||
import { dayjs } from '../common/dayjs'
|
||||
import { deepClone, isArray, isEqual, padZero, requestAnimationFrame } from '../common/util'
|
||||
import { getWeekNumber, isRange } from '../wd-calendar-view/utils'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { calendarProps, type CalendarExpose } from './types'
|
||||
import type { CalendarType } from '../wd-calendar-view/types'
|
||||
const { translate } = useTranslate('calendar')
|
||||
|
||||
const defaultDisplayFormat = (value: number | number[], type: CalendarType): string => {
|
||||
switch (type) {
|
||||
case 'date':
|
||||
return dayjs(value as number).format('YYYY-MM-DD')
|
||||
case 'dates':
|
||||
return (value as number[])
|
||||
.map((item) => {
|
||||
return dayjs(item).format('YYYY-MM-DD')
|
||||
})
|
||||
.join(', ')
|
||||
case 'daterange':
|
||||
return `${(value as number[])[0] ? dayjs((value as number[])[0]).format('YYYY-MM-DD') : translate('startTime')} ${translate('to')} ${
|
||||
(value as number[])[1] ? dayjs((value as number[])[1]).format('YYYY-MM-DD') : translate('endTime')
|
||||
}`
|
||||
case 'datetime':
|
||||
return dayjs(value as number).format('YYYY-MM-DD HH:mm:ss')
|
||||
case 'datetimerange':
|
||||
return `${(value as number[])[0] ? dayjs((value as number[])[0]).format(translate('timeFormat')) : translate('startTime')} ${translate(
|
||||
'to'
|
||||
)}\n${(value as number[])[1] ? dayjs((value as number[])[1]).format(translate('timeFormat')) : translate('endTime')}`
|
||||
case 'week': {
|
||||
const year = new Date(value as number).getFullYear()
|
||||
const week = getWeekNumber(value as number)
|
||||
return translate('weekFormat', year, padZero(week))
|
||||
}
|
||||
case 'weekrange': {
|
||||
const year1 = new Date((value as number[])[0]).getFullYear()
|
||||
const week1 = getWeekNumber((value as number[])[0])
|
||||
const year2 = new Date((value as number[])[1]).getFullYear()
|
||||
const week2 = getWeekNumber((value as number[])[1])
|
||||
return `${(value as number[])[0] ? translate('weekFormat', year1, padZero(week1)) : translate('startWeek')} - ${
|
||||
(value as number[])[1] ? translate('weekFormat', year2, padZero(week2)) : translate('endWeek')
|
||||
}`
|
||||
}
|
||||
case 'month':
|
||||
return dayjs(value as number).format('YYYY / MM')
|
||||
case 'monthrange':
|
||||
return `${(value as number[])[0] ? dayjs((value as number[])[0]).format('YYYY / MM') : translate('startMonth')} ${translate('to')} ${
|
||||
(value as number[])[1] ? dayjs((value as number[])[1]).format('YYYY / MM') : translate('endMonth')
|
||||
}`
|
||||
}
|
||||
}
|
||||
|
||||
const formatRange = (value: number, rangeType: 'start' | 'end', type: CalendarType) => {
|
||||
switch (type) {
|
||||
case 'daterange':
|
||||
@ -217,7 +142,6 @@ const lastTab = ref<number>(0)
|
||||
const currentType = ref<CalendarType>('date')
|
||||
const lastCurrentType = ref<CalendarType>()
|
||||
const inited = ref<boolean>(false)
|
||||
const cell = useCell()
|
||||
const calendarView = ref()
|
||||
const calendarTabs = ref()
|
||||
|
||||
@ -228,14 +152,6 @@ const rangeLabel = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
const showValue = computed(() => {
|
||||
if ((!isArray(props.modelValue) && props.modelValue) || (isArray(props.modelValue) && props.modelValue.length)) {
|
||||
return (props.displayFormat || defaultDisplayFormat)(props.modelValue, lastCurrentType.value || currentType.value)
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val, oldVal) => {
|
||||
@ -250,7 +166,7 @@ watch(
|
||||
|
||||
watch(
|
||||
() => props.type,
|
||||
(newValue, oldValue) => {
|
||||
(newValue) => {
|
||||
if (props.showTypeSwitch) {
|
||||
const tabs = ['date', 'week', 'month']
|
||||
const rangeTabs = ['daterange', 'weekrange', 'monthrange']
|
||||
@ -278,31 +194,6 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const { parent: form } = useParent(FORM_KEY)
|
||||
|
||||
// 表单校验错误信息
|
||||
const errorMessage = computed(() => {
|
||||
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
|
||||
return form.errorMessages[props.prop]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
// 是否展示必填
|
||||
const isRequired = computed(() => {
|
||||
let formRequired = false
|
||||
if (form && form.props.rules) {
|
||||
const rules = form.props.rules
|
||||
for (const key in rules) {
|
||||
if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
|
||||
formRequired = rules[key].some((rule: FormItemRule) => rule.required)
|
||||
}
|
||||
}
|
||||
}
|
||||
return props.required || props.rules.some((rule) => rule.required) || formRequired
|
||||
})
|
||||
|
||||
const range = computed(() => {
|
||||
return (type: CalendarType) => {
|
||||
return isRange(type)
|
||||
@ -314,10 +205,6 @@ function scrollIntoView() {
|
||||
}
|
||||
// 对外暴露方法
|
||||
function open() {
|
||||
const { disabled, readonly } = props
|
||||
|
||||
if (disabled || readonly) return
|
||||
|
||||
inited.value = true
|
||||
pickerShow.value = true
|
||||
lastCalendarValue.value = deepClone(calendarValue.value)
|
||||
|
||||
@ -19,9 +19,7 @@
|
||||
}
|
||||
|
||||
@include when(border) {
|
||||
.wd-cell__wrapper {
|
||||
@include halfPixelBorder('top', 0, $-dark-border-color);
|
||||
}
|
||||
@include halfPixelBorder('top', 0, $-dark-border-color);
|
||||
}
|
||||
|
||||
:deep(.wd-cell__arrow-right) {
|
||||
@ -32,45 +30,37 @@
|
||||
|
||||
@include b(cell) {
|
||||
position: relative;
|
||||
padding-left: $-cell-padding;
|
||||
background-color: $-color-white;
|
||||
padding: $-cell-horizontal-padding $-cell-vertical-padding;
|
||||
text-decoration: none;
|
||||
color: $-cell-title-color;
|
||||
line-height: $-cell-line-height;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
display: flex;
|
||||
|
||||
|
||||
@include when(border) {
|
||||
.wd-cell__wrapper {
|
||||
@include halfPixelBorder('top');
|
||||
@include halfPixelBorder('top');
|
||||
}
|
||||
|
||||
@include when(vertical) {
|
||||
display: block;
|
||||
|
||||
.wd-cell__right {
|
||||
margin-top: $-cell-vertical-top;
|
||||
}
|
||||
|
||||
.wd-cell__value {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.wd-cell__left {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(wrapper) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: $-cell-wrapper-padding $-cell-padding $-cell-wrapper-padding 0;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
@include when(vertical) {
|
||||
display: block;
|
||||
|
||||
.wd-cell__right {
|
||||
margin-top: $-cell-vertical-top;
|
||||
}
|
||||
|
||||
.wd-cell__value {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.wd-cell__left {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include when(label) {
|
||||
padding: $-cell-wrapper-padding-with-label $-cell-padding $-cell-wrapper-padding-with-label 0;
|
||||
}
|
||||
@include when(label) {
|
||||
padding: $-cell-horizontal-padding-with-label $-cell-vertical-padding;
|
||||
}
|
||||
|
||||
@include e(left) {
|
||||
@ -80,7 +70,6 @@
|
||||
text-align: left;
|
||||
font-size: $-cell-title-fs;
|
||||
box-sizing: border-box;
|
||||
margin-right: $-cell-padding;
|
||||
|
||||
@include when(required) {
|
||||
padding-left: 12px;
|
||||
@ -123,7 +112,7 @@
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
|
||||
@include e(body){
|
||||
@include e(body) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@ -146,7 +135,7 @@
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
|
||||
@include e(error-message){
|
||||
@include e(error-message) {
|
||||
color: $-form-item-error-message-color;
|
||||
font-size: $-form-item-error-message-font-size;
|
||||
line-height: $-form-item-error-message-line-height;
|
||||
@ -163,14 +152,13 @@
|
||||
}
|
||||
|
||||
@include when(large) {
|
||||
padding-top: $-cell-horizontal-padding-large;
|
||||
padding-bottom: $-cell-horizontal-padding-large;
|
||||
|
||||
.wd-cell__title {
|
||||
font-size: $-cell-title-fs-large;
|
||||
}
|
||||
|
||||
.wd-cell__wrapper {
|
||||
padding-top: $-cell-wrapper-padding-large;
|
||||
padding-bottom: $-cell-wrapper-padding-large;
|
||||
}
|
||||
|
||||
.wd-cell__label {
|
||||
font-size: $-cell-label-fs-large;
|
||||
@ -182,8 +170,6 @@
|
||||
}
|
||||
|
||||
@include when(center) {
|
||||
.wd-cell__wrapper {
|
||||
align-items: center;
|
||||
}
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
@ -1,47 +1,45 @@
|
||||
<template>
|
||||
<view
|
||||
:class="['wd-cell', isBorder ? 'is-border' : '', size ? 'is-' + size : '', center ? 'is-center' : '', customClass]"
|
||||
:class="['wd-cell', isBorder ? 'is-border' : '', size ? 'is-' + size : '', center ? 'is-center' : '', vertical ? 'is-vertical' : '', customClass]"
|
||||
:style="customStyle"
|
||||
:hover-class="isLink || clickable ? 'is-hover' : 'none'"
|
||||
:hover-stay-time="70"
|
||||
@click="onClick"
|
||||
@click="handleClick"
|
||||
>
|
||||
<view :class="['wd-cell__wrapper', vertical ? 'is-vertical' : '']">
|
||||
<view
|
||||
:class="['wd-cell__left', isRequired ? 'is-required' : '']"
|
||||
:style="titleWidth ? 'min-width:' + titleWidth + ';max-width:' + titleWidth + ';' : ''"
|
||||
>
|
||||
<!--左侧icon部位-->
|
||||
<wd-icon v-if="icon" :name="icon" :custom-class="`wd-cell__icon ${customIconClass}`"></wd-icon>
|
||||
<slot v-else name="icon" />
|
||||
<view
|
||||
:class="['wd-cell__left', isRequired ? 'is-required' : '']"
|
||||
:style="titleWidth ? 'min-width:' + titleWidth + ';max-width:' + titleWidth + ';' : ''"
|
||||
>
|
||||
<!--左侧icon部位-->
|
||||
<wd-icon v-if="icon" :name="icon" :custom-class="`wd-cell__icon ${customIconClass}`"></wd-icon>
|
||||
<slot v-else name="icon" />
|
||||
|
||||
<view class="wd-cell__title">
|
||||
<!--title BEGIN-->
|
||||
<view v-if="title" :class="customTitleClass">{{ title }}</view>
|
||||
<slot v-else name="title"></slot>
|
||||
<!--title END-->
|
||||
<view class="wd-cell__title">
|
||||
<!--title BEGIN-->
|
||||
<view v-if="title" :class="customTitleClass">{{ title }}</view>
|
||||
<slot v-else name="title"></slot>
|
||||
<!--title END-->
|
||||
|
||||
<!--label BEGIN-->
|
||||
<view v-if="label" :class="`wd-cell__label ${customLabelClass}`">{{ label }}</view>
|
||||
<slot v-else name="label" />
|
||||
<!--label END-->
|
||||
</view>
|
||||
<!--label BEGIN-->
|
||||
<view v-if="label" :class="`wd-cell__label ${customLabelClass}`">{{ label }}</view>
|
||||
<slot v-else name="label" />
|
||||
<!--label END-->
|
||||
</view>
|
||||
<!--right content BEGIN-->
|
||||
<view class="wd-cell__right">
|
||||
<view class="wd-cell__body">
|
||||
<!--文案内容-->
|
||||
<view :class="`wd-cell__value ${customValueClass}`">
|
||||
<slot>{{ value }}</slot>
|
||||
</view>
|
||||
<!--箭头-->
|
||||
<wd-icon v-if="isLink" custom-class="wd-cell__arrow-right" name="arrow-right" />
|
||||
<slot v-else name="right-icon" />
|
||||
</view>
|
||||
<view v-if="errorMessage" class="wd-cell__error-message">{{ errorMessage }}</view>
|
||||
</view>
|
||||
<!--right content END-->
|
||||
</view>
|
||||
<!--right content BEGIN-->
|
||||
<view class="wd-cell__right">
|
||||
<view class="wd-cell__body">
|
||||
<!--文案内容-->
|
||||
<view :class="`wd-cell__value ${customValueClass}`">
|
||||
<slot>{{ value }}</slot>
|
||||
</view>
|
||||
<!--箭头-->
|
||||
<wd-icon v-if="isLink" custom-class="wd-cell__arrow-right" name="arrow-right" />
|
||||
<slot v-else name="right-icon" />
|
||||
</view>
|
||||
<view v-if="errorMessage" class="wd-cell__error-message">{{ errorMessage }}</view>
|
||||
</view>
|
||||
<!--right content END-->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -98,10 +96,7 @@ const isRequired = computed(() => {
|
||||
return props.required || props.rules.some((rule) => rule.required) || formRequired
|
||||
})
|
||||
|
||||
/**
|
||||
* @description 点击cell的handle
|
||||
*/
|
||||
function onClick() {
|
||||
function handleClick() {
|
||||
const url = props.to
|
||||
|
||||
if (props.clickable || props.isLink) {
|
||||
|
||||
@ -3,30 +3,7 @@
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(col-picker) {
|
||||
|
||||
@include when(border) {
|
||||
.wd-col-picker__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding, $-dark-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(cell) {
|
||||
background-color: $-dark-background2;
|
||||
color: $-dark-color;
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-col-picker__value {
|
||||
color: $-dark-color3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include e(list-item) {
|
||||
|
||||
@include when(disabled) {
|
||||
color: $-dark-color3;
|
||||
}
|
||||
@ -36,18 +13,6 @@
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
|
||||
@include e(value) {
|
||||
color: $-dark-color;
|
||||
|
||||
@include m(placeholder) {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.wd-col-picker__arrow) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(list) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
@ -59,140 +24,11 @@
|
||||
}
|
||||
|
||||
@include b(col-picker) {
|
||||
@include when(border) {
|
||||
.wd-col-picker__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding);
|
||||
}
|
||||
}
|
||||
@include e(cell) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: $-cell-wrapper-padding $-cell-padding;
|
||||
align-items: flex-start;
|
||||
background-color: $-color-white;
|
||||
text-decoration: none;
|
||||
color: $-cell-title-color;
|
||||
font-size: $-cell-title-fs;
|
||||
overflow: hidden;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
@include e(cell) {
|
||||
@include when(disabled) {
|
||||
.wd-col-picker__value {
|
||||
color: $-input-disabled-color;
|
||||
}
|
||||
}
|
||||
@include when(align-right) {
|
||||
.wd-col-picker__value {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@include when(error) {
|
||||
.wd-col-picker__value {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
:deep(.wd-col-picker__arrow) {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
}
|
||||
@include when(large) {
|
||||
font-size: $-cell-title-fs-large;
|
||||
|
||||
:deep(.wd-col-picker__arrow) {
|
||||
font-size: $-cell-icon-size-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include e(error-message){
|
||||
color: $-form-item-error-message-color;
|
||||
font-size: $-form-item-error-message-font-size;
|
||||
line-height: $-form-item-error-message-line-height;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@include e(label) {
|
||||
position: relative;
|
||||
width: $-input-cell-label-width;
|
||||
margin-right: $-cell-padding;
|
||||
color: $-cell-title-color;
|
||||
box-sizing: border-box;
|
||||
|
||||
@include when(required) {
|
||||
padding-left: 12px;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
content: '*';
|
||||
font-size: $-cell-required-size;
|
||||
line-height: 1.1;
|
||||
color: $-cell-required-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include e(value-wraper) {
|
||||
display: flex;
|
||||
}
|
||||
@include e(value) {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
color: $-cell-value-color;
|
||||
|
||||
@include when(ellipsis) {
|
||||
@include lineEllipsis;
|
||||
}
|
||||
@include m(placeholder) {
|
||||
color: $-input-placeholder-color;
|
||||
}
|
||||
}
|
||||
@include e(body) {
|
||||
flex: 1;
|
||||
}
|
||||
@include edeep(arrow) {
|
||||
display: block;
|
||||
font-size: $-cell-icon-size;
|
||||
color: $-cell-arrow-color;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
@include e(selected) {
|
||||
height: $-col-picker-selected-height;
|
||||
font-size: $-col-picker-selected-fs;
|
||||
color: $-col-picker-selected-color;
|
||||
overflow: hidden;
|
||||
}
|
||||
@include e(selected-container){
|
||||
position: relative;
|
||||
display: flex;
|
||||
user-select: none;
|
||||
}
|
||||
@include e(selected-item) {
|
||||
flex: 0 0 auto;
|
||||
height: $-col-picker-selected-height;
|
||||
line-height: $-col-picker-selected-height;
|
||||
padding: $-col-picker-selected-padding;
|
||||
|
||||
@include when(selected) {
|
||||
font-weight: $-col-picker-selected-fw;
|
||||
}
|
||||
}
|
||||
@include e(selected-line) {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
width: $-col-picker-line-width;
|
||||
left: 0;
|
||||
height: $-col-picker-line-height;
|
||||
background: $-col-picker-line-color;
|
||||
z-index: 1;
|
||||
border-radius: calc($-col-picker-line-height / 2);
|
||||
box-shadow: $-col-picker-line-box-shadow;
|
||||
}
|
||||
@include e(list-container){
|
||||
position: relative;
|
||||
}
|
||||
@include e(list) {
|
||||
height: $-col-picker-list-height;
|
||||
padding-bottom: $-col-picker-list-padding-bottom;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
color: $-col-picker-list-color;
|
||||
|
||||
@ -1,6 +1,13 @@
|
||||
import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue'
|
||||
import { baseProps, makeArrayProp, makeBooleanProp, makeNumberProp, makeRequiredProp, makeStringProp, numericProp } from '../common/props'
|
||||
import type { FormItemRule } from '../wd-form/types'
|
||||
|
||||
export type ColPickerOption = {
|
||||
label?: string
|
||||
value?: string | number
|
||||
tip?: string
|
||||
disabled?: boolean
|
||||
[key: PropertyKey]: any
|
||||
}
|
||||
|
||||
export const colPickerProps = {
|
||||
...baseProps,
|
||||
@ -8,38 +15,14 @@ export const colPickerProps = {
|
||||
* 选中项
|
||||
*/
|
||||
modelValue: makeRequiredProp(Array as PropType<Array<string | number>>),
|
||||
/**
|
||||
* 是否显示
|
||||
*/
|
||||
visible: makeBooleanProp(false),
|
||||
/**
|
||||
* 选择器数据,二维数组
|
||||
*/
|
||||
columns: makeArrayProp<Record<string, any>[]>(),
|
||||
/**
|
||||
* 选择器左侧文案
|
||||
*/
|
||||
label: String,
|
||||
/**
|
||||
* 设置左侧标题宽度
|
||||
*/
|
||||
labelWidth: makeStringProp('33%'),
|
||||
/**
|
||||
* 使用 label 插槽时设置该选项
|
||||
*/
|
||||
useLabelSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 使用默认插槽时设置该选项
|
||||
*/
|
||||
useDefaultSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
disabled: makeBooleanProp(false),
|
||||
/**
|
||||
* 只读
|
||||
*/
|
||||
readonly: makeBooleanProp(false),
|
||||
/**
|
||||
* 选择器占位符
|
||||
*/
|
||||
placeholder: String,
|
||||
columns: makeArrayProp<ColPickerOption[]>(),
|
||||
/**
|
||||
* 弹出层标题
|
||||
*/
|
||||
@ -48,30 +31,10 @@ export const colPickerProps = {
|
||||
* 接收当前列的选中项 item、当前列下标、当前列选中项下标下一列数据处理函数 resolve、结束选择 finish
|
||||
*/
|
||||
columnChange: Function as PropType<ColPickerColumnChange>,
|
||||
/**
|
||||
* 自定义展示文案的格式化函数,返回一个字符串
|
||||
*/
|
||||
displayFormat: Function as PropType<ColPickerDisplayFormat>,
|
||||
/**
|
||||
* 确定前校验函数,接收 (value, resolve) 参数,通过 resolve 继续执行 picker,resolve 接收 1 个 boolean 参数
|
||||
*/
|
||||
beforeConfirm: Function as PropType<ColPickerBeforeConfirm>,
|
||||
/**
|
||||
* 选择器的值靠右展示
|
||||
*/
|
||||
alignRight: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否为错误状态,错误状态时右侧内容为红色
|
||||
*/
|
||||
error: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
required: makeBooleanProp(false),
|
||||
/**
|
||||
* 设置选择器大小,可选值:large
|
||||
*/
|
||||
size: String,
|
||||
/**
|
||||
* 选项对象中,value 对应的 key
|
||||
*/
|
||||
@ -104,18 +67,6 @@ export const colPickerProps = {
|
||||
* 弹出面板是否设置底部安全距离(iphone X 类型的机型)
|
||||
*/
|
||||
safeAreaInsetBottom: makeBooleanProp(true),
|
||||
/**
|
||||
* 是否超出隐藏
|
||||
*/
|
||||
ellipsis: makeBooleanProp(false),
|
||||
/**
|
||||
* 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
|
||||
*/
|
||||
prop: String,
|
||||
/**
|
||||
* 表单验证规则,结合wd-form组件使用
|
||||
*/
|
||||
rules: makeArrayProp<FormItemRule>(),
|
||||
/**
|
||||
* 底部条宽度,单位像素
|
||||
*/
|
||||
@ -123,30 +74,21 @@ export const colPickerProps = {
|
||||
/**
|
||||
* 底部条高度,单位像素
|
||||
*/
|
||||
lineHeight: numericProp,
|
||||
/**
|
||||
* label 外部自定义样式
|
||||
*/
|
||||
customViewClass: makeStringProp(''),
|
||||
/**
|
||||
* value 外部自定义样式
|
||||
*/
|
||||
customLabelClass: makeStringProp(''),
|
||||
customValueClass: makeStringProp('')
|
||||
lineHeight: numericProp
|
||||
}
|
||||
|
||||
export type ColPickerProps = ExtractPropTypes<typeof colPickerProps>
|
||||
|
||||
export type ColPickerColumnChangeOption = {
|
||||
selectedItem: Record<string, any>
|
||||
selectedItem: ColPickerOption
|
||||
index: number
|
||||
rowIndex: number
|
||||
resolve: (nextColumn: Record<string, any>[]) => void
|
||||
resolve: (nextColumn: ColPickerOption[]) => void
|
||||
finish: (isOk?: boolean) => void
|
||||
}
|
||||
export type ColPickerColumnChange = (option: ColPickerColumnChangeOption) => void
|
||||
export type ColPickerDisplayFormat = (selectedItems: Record<string, any>[]) => string
|
||||
export type ColPickerBeforeConfirm = (value: (string | number)[], selectedItems: Record<string, any>[], resolve: (isPass: boolean) => void) => void
|
||||
export type ColPickerDisplayFormat = (selectedItems: ColPickerOption[]) => string
|
||||
export type ColPickerBeforeConfirm = (value: (string | number)[], selectedItems: ColPickerOption[], resolve: (isPass: boolean) => void) => void
|
||||
|
||||
export type ColPickerExpose = {
|
||||
// 关闭picker弹框
|
||||
|
||||
@ -1,86 +1,42 @@
|
||||
<template>
|
||||
<view :class="`wd-col-picker ${cell.border.value ? 'is-border' : ''} ${customClass}`" :style="customStyle">
|
||||
<view class="wd-col-picker__field" @click="showPicker">
|
||||
<slot v-if="useDefaultSlot"></slot>
|
||||
<view
|
||||
v-else
|
||||
:class="`wd-col-picker__cell ${disabled && 'is-disabled'} ${readonly && 'is-readonly'} ${alignRight && 'is-align-right'} ${
|
||||
error && 'is-error'
|
||||
} ${size && 'is-' + size}`"
|
||||
>
|
||||
<view
|
||||
v-if="label || useLabelSlot"
|
||||
:class="`wd-col-picker__label ${isRequired && 'is-required'} ${customLabelClass}`"
|
||||
:style="labelWidth ? 'min-width:' + labelWidth + ';max-width:' + labelWidth + ';' : ''"
|
||||
>
|
||||
<block v-if="label">{{ label }}</block>
|
||||
<slot v-else name="label"></slot>
|
||||
</view>
|
||||
<view class="wd-col-picker__body">
|
||||
<view class="wd-col-picker__value-wraper">
|
||||
<view
|
||||
:class="`wd-col-picker__value ${ellipsis && 'is-ellipsis'} ${customValueClass} ${showValue ? '' : 'wd-col-picker__value--placeholder'}`"
|
||||
>
|
||||
{{ showValue || placeholder || translate('placeholder') }}
|
||||
</view>
|
||||
<wd-icon v-if="!disabled && !readonly" custom-class="wd-col-picker__arrow" name="arrow-right" />
|
||||
</view>
|
||||
<view v-if="errorMessage" class="wd-col-picker__error-message">{{ errorMessage }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="`wd-col-picker ${customClass}`" :style="customStyle">
|
||||
<wd-action-sheet
|
||||
v-model="pickerShow"
|
||||
:duration="250"
|
||||
:title="title || translate('title')"
|
||||
:close-on-click-modal="closeOnClickModal"
|
||||
:hideWhenClose="false"
|
||||
:z-index="zIndex"
|
||||
:safe-area-inset-bottom="safeAreaInsetBottom"
|
||||
@open="handlePickerOpend"
|
||||
@opened="handlePickerOpened"
|
||||
@close="handlePickerClose"
|
||||
@closed="handlePickerClosed"
|
||||
>
|
||||
<view class="wd-col-picker__selected">
|
||||
<scroll-view :scroll-x="true" scroll-with-animation :scroll-left="scrollLeft">
|
||||
<view class="wd-col-picker__selected-container">
|
||||
<view
|
||||
v-for="(_, colIndex) in selectList"
|
||||
:key="colIndex"
|
||||
:class="`wd-col-picker__selected-item ${colIndex === currentCol && 'is-selected'}`"
|
||||
@click="handleColClick(colIndex)"
|
||||
>
|
||||
{{ selectShowList[colIndex] || translate('select') }}
|
||||
<wd-tabs ref="tabs" v-model="currentCol" :animated="animated" slidable="always">
|
||||
<wd-tab v-for="(col, colIndex) in innerColumns" :key="colIndex" :title="`${currentColumn[colIndex] || translate('select')}`" :name="colIndex">
|
||||
<view class="wd-col-picker__list-container">
|
||||
<view class="wd-col-picker__list">
|
||||
<view
|
||||
v-for="(item, index) in col"
|
||||
:key="index"
|
||||
:class="`wd-col-picker__list-item ${innerValue[colIndex] && item[valueKey] === innerValue[colIndex] && 'is-selected'} ${
|
||||
item.disabled && 'is-disabled'
|
||||
}`"
|
||||
@click="chooseItem(colIndex, index)"
|
||||
>
|
||||
<view>
|
||||
<view class="wd-col-picker__list-item-label">{{ item[labelKey] }}</view>
|
||||
<view v-if="item[tipKey]" class="wd-col-picker__list-item-tip">{{ item[tipKey] }}</view>
|
||||
</view>
|
||||
<wd-icon custom-class="wd-col-picker__checked" name="check"></wd-icon>
|
||||
</view>
|
||||
<view v-if="loading" class="wd-col-picker__loading">
|
||||
<wd-loading :color="loadingColor" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="wd-col-picker__selected-line" :style="state.lineStyle"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="wd-col-picker__list-container">
|
||||
<view
|
||||
v-for="(col, colIndex) in selectList"
|
||||
:key="colIndex"
|
||||
class="wd-col-picker__list"
|
||||
:style="colIndex === currentCol ? 'display: block;' : 'display: none;'"
|
||||
>
|
||||
<view
|
||||
v-for="(item, index) in col"
|
||||
:key="index"
|
||||
:class="`wd-col-picker__list-item ${pickerColSelected[colIndex] && item[valueKey] === pickerColSelected[colIndex] && 'is-selected'} ${
|
||||
item.disabled && 'is-disabled'
|
||||
}`"
|
||||
@click="chooseItem(colIndex, index)"
|
||||
>
|
||||
<view>
|
||||
<view class="wd-col-picker__list-item-label">{{ item[labelKey] }}</view>
|
||||
<view v-if="item[tipKey]" class="wd-col-picker__list-item-tip">{{ item[tipKey] }}</view>
|
||||
</view>
|
||||
<wd-icon custom-class="wd-col-picker__checked" name="check"></wd-icon>
|
||||
</view>
|
||||
<view v-if="loading" class="wd-col-picker__loading">
|
||||
<wd-loading :color="loadingColor" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</wd-tab>
|
||||
</wd-tabs>
|
||||
</wd-action-sheet>
|
||||
</view>
|
||||
</template>
|
||||
@ -99,78 +55,41 @@ export default {
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import wdLoading from '../wd-loading/wd-loading.vue'
|
||||
import wdActionSheet from '../wd-action-sheet/wd-action-sheet.vue'
|
||||
import { computed, getCurrentInstance, onMounted, ref, watch, type CSSProperties, reactive, nextTick } from 'vue'
|
||||
import { addUnit, debounce, getRect, isArray, isBoolean, isDef, isFunction, objToStyle } from '../common/util'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { ref, watch, nextTick } from 'vue'
|
||||
import { deepClone, isArray, isBoolean, isDef, isEqual } from '../common/util'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { colPickerProps, type ColPickerExpose } from './types'
|
||||
import { colPickerProps, type ColPickerExpose, type ColPickerOption } from './types'
|
||||
import type { TabsInstance } from '../wd-tabs/types'
|
||||
|
||||
const { translate } = useTranslate('col-picker')
|
||||
|
||||
const $container = '.wd-col-picker__selected-container'
|
||||
const $item = '.wd-col-picker__selected-item'
|
||||
const tabs = ref<TabsInstance>()
|
||||
|
||||
const props = defineProps(colPickerProps)
|
||||
const emit = defineEmits(['close', 'update:modelValue', 'confirm'])
|
||||
const emit = defineEmits(['close', 'update:modelValue', 'update:visible', 'confirm'])
|
||||
const innerValue = ref(props.modelValue) // 当前选择值
|
||||
const innerColumns = ref<ColPickerOption[][]>(props.columns) // 全部列数据
|
||||
const currentColumn = ref<ColPickerOption[]>([]) // 当前展示列数据
|
||||
const animated = ref<boolean>(false) // 是否开启切换动画 弹窗打开后开启
|
||||
|
||||
const pickerShow = ref<boolean>(false)
|
||||
const currentCol = ref<number>(0)
|
||||
const selectList = ref<Record<string, any>[][]>([])
|
||||
const pickerColSelected = ref<(string | number)[]>([])
|
||||
const selectShowList = ref<Record<string, any>[]>([])
|
||||
const loading = ref<boolean>(false)
|
||||
const isChange = ref<boolean>(false)
|
||||
const lastSelectList = ref<Record<string, any>[][]>([])
|
||||
const lastSelectList = ref<ColPickerOption[][]>([])
|
||||
const lastPickerColSelected = ref<(string | number)[]>([])
|
||||
const scrollLeft = ref<number>(0)
|
||||
const inited = ref<boolean>(false)
|
||||
const isCompleting = ref<boolean>(false)
|
||||
|
||||
const state = reactive({
|
||||
lineStyle: 'display:none;' // 激活项边框线样式
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const cell = useCell()
|
||||
|
||||
const updateLineAndScroll = debounce(function (animation = true) {
|
||||
setLineStyle(animation)
|
||||
lineScrollIntoView()
|
||||
}, 50)
|
||||
|
||||
const showValue = computed(() => {
|
||||
const selectedItems = (props.modelValue || []).map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, selectList.value)
|
||||
})
|
||||
|
||||
if (props.displayFormat) {
|
||||
return props.displayFormat(selectedItems)
|
||||
} else {
|
||||
return selectedItems
|
||||
.map((item) => {
|
||||
return item[props.labelKey]
|
||||
})
|
||||
.join('')
|
||||
}
|
||||
})
|
||||
watch(() => props.modelValue, updateInnerValue)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => props.visible,
|
||||
(newValue) => {
|
||||
if (newValue === pickerColSelected.value) return
|
||||
pickerColSelected.value = newValue
|
||||
newValue.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, selectList.value)[props.labelKey]
|
||||
})
|
||||
handleAutoComplete()
|
||||
if (newValue) {
|
||||
open()
|
||||
} else {
|
||||
close()
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
{ deep: true, immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
@ -181,138 +100,76 @@ watch(
|
||||
return
|
||||
}
|
||||
if (newValue.length === 0 && !oldValue) return
|
||||
|
||||
const newSelectedList = newValue.slice(0)
|
||||
|
||||
selectList.value = newSelectedList
|
||||
|
||||
selectShowList.value = pickerColSelected.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, newSelectedList)[props.labelKey]
|
||||
innerColumns.value = deepClone(newValue)
|
||||
currentColumn.value = innerValue.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, innerColumns.value)[props.labelKey]
|
||||
})
|
||||
lastSelectList.value = newSelectedList
|
||||
|
||||
if (newSelectedList.length > 0) {
|
||||
currentCol.value = newSelectedList.length - 1
|
||||
}
|
||||
lastSelectList.value = deepClone(innerColumns.value)
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.columnChange,
|
||||
(fn) => {
|
||||
if (fn && !isFunction(fn)) {
|
||||
console.error('The type of columnChange must be Function')
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.displayFormat,
|
||||
(fn) => {
|
||||
if (fn && !isFunction(fn)) {
|
||||
console.error('The type of displayFormat must be Function')
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.beforeConfirm,
|
||||
(fn) => {
|
||||
if (fn && !isFunction(fn)) {
|
||||
console.error('The type of beforeConfirm must be Function')
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
const { parent: form } = useParent(FORM_KEY)
|
||||
|
||||
// 表单校验错误信息
|
||||
const errorMessage = computed(() => {
|
||||
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
|
||||
return form.errorMessages[props.prop]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
// 是否展示必填
|
||||
const isRequired = computed(() => {
|
||||
let formRequired = false
|
||||
if (form && form.props.rules) {
|
||||
const rules = form.props.rules
|
||||
for (const key in rules) {
|
||||
if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
|
||||
formRequired = rules[key].some((rule: FormItemRule) => rule.required)
|
||||
}
|
||||
}
|
||||
}
|
||||
return props.required || props.rules.some((rule) => rule.required) || formRequired
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
inited.value = true
|
||||
})
|
||||
|
||||
// 打开弹框
|
||||
function open() {
|
||||
showPicker()
|
||||
updateInnerValue()
|
||||
pickerShow.value = true
|
||||
lastPickerColSelected.value = deepClone(innerValue.value)
|
||||
lastSelectList.value = deepClone(innerColumns.value)
|
||||
}
|
||||
// 关闭弹框
|
||||
function close() {
|
||||
handlePickerClose()
|
||||
}
|
||||
function handlePickerOpend() {
|
||||
updateLineAndScroll(false)
|
||||
}
|
||||
|
||||
function handlePickerClose() {
|
||||
pickerShow.value = false
|
||||
emit('close')
|
||||
}
|
||||
|
||||
function handlePickerClosed() {
|
||||
if (isChange.value) {
|
||||
setTimeout(() => {
|
||||
selectList.value = lastSelectList.value.slice(0)
|
||||
pickerColSelected.value = lastPickerColSelected.value.slice(0)
|
||||
selectShowList.value = lastPickerColSelected.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, lastSelectList.value)[props.labelKey]
|
||||
})
|
||||
currentCol.value = lastSelectList.value.length - 1
|
||||
isChange.value = false
|
||||
}, 250)
|
||||
function updateInnerValue() {
|
||||
if (isEqual(props.modelValue, innerValue.value)) return
|
||||
innerValue.value = props.modelValue
|
||||
handleAutoComplete()
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹出框打开后
|
||||
*/
|
||||
function handlePickerOpened() {
|
||||
if (isDef(tabs.value)) {
|
||||
tabs.value?.updateLineStyle(false)
|
||||
animated.value = true
|
||||
}
|
||||
}
|
||||
|
||||
function showPicker() {
|
||||
const { disabled, readonly } = props
|
||||
|
||||
if (disabled || readonly) return
|
||||
pickerShow.value = true
|
||||
lastPickerColSelected.value = pickerColSelected.value.slice(0)
|
||||
lastSelectList.value = selectList.value.slice(0)
|
||||
/**
|
||||
* 弹出框关闭时
|
||||
*/
|
||||
function handlePickerClose() {
|
||||
emit('update:visible', false)
|
||||
emit('close')
|
||||
}
|
||||
|
||||
function getSelectedItem(value: string | number, colIndex: number, selectList: Record<string, any>[][]) {
|
||||
/**
|
||||
* 弹出框关闭后
|
||||
*/
|
||||
function handlePickerClosed() {
|
||||
animated.value = false
|
||||
setTimeout(() => {
|
||||
innerColumns.value = lastSelectList.value.slice(0)
|
||||
innerValue.value = lastPickerColSelected.value.slice(0)
|
||||
currentColumn.value = lastPickerColSelected.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, lastSelectList.value)[props.labelKey]
|
||||
})
|
||||
currentCol.value = lastSelectList.value.length - 1
|
||||
if (isDef(tabs.value)) {
|
||||
tabs.value.updateLineStyle(false)
|
||||
}
|
||||
}, 250)
|
||||
}
|
||||
|
||||
function getSelectedItem(value: string | number, colIndex: number, innerColumns: ColPickerOption[][]) {
|
||||
const { valueKey, labelKey } = props
|
||||
if (selectList[colIndex]) {
|
||||
const selecteds = selectList[colIndex].filter((item) => {
|
||||
if (innerColumns[colIndex]) {
|
||||
const selecteds = innerColumns[colIndex].filter((item) => {
|
||||
return item[valueKey] === value
|
||||
})
|
||||
|
||||
@ -328,26 +185,20 @@ function getSelectedItem(value: string | number, colIndex: number, selectList: R
|
||||
}
|
||||
|
||||
function chooseItem(colIndex: number, index: number) {
|
||||
const item = selectList.value[colIndex][index]
|
||||
const item = innerColumns.value[colIndex][index]
|
||||
if (item.disabled) return
|
||||
|
||||
const newPickerColSelected = pickerColSelected.value.slice(0, colIndex)
|
||||
const newPickerColSelected = innerValue.value.slice(0, colIndex)
|
||||
newPickerColSelected.push(item[props.valueKey])
|
||||
isChange.value = true
|
||||
pickerColSelected.value = newPickerColSelected
|
||||
selectList.value = selectList.value.slice(0, colIndex + 1)
|
||||
selectShowList.value = newPickerColSelected.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, selectList.value)[props.labelKey]
|
||||
innerValue.value = newPickerColSelected
|
||||
innerColumns.value = innerColumns.value.slice(0, colIndex + 1)
|
||||
currentColumn.value = newPickerColSelected.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, innerColumns.value)[props.labelKey]
|
||||
})
|
||||
|
||||
if (selectShowList.value[colIndex] && colIndex === currentCol.value) {
|
||||
updateLineAndScroll(true)
|
||||
}
|
||||
|
||||
handleColChange(colIndex, item, index)
|
||||
}
|
||||
|
||||
function handleColChange(colIndex: number, item: Record<string, any>, index: number, callback?: () => void) {
|
||||
function handleColChange(colIndex: number, item: ColPickerOption, index: number, callback?: () => void) {
|
||||
loading.value = true
|
||||
const { columnChange, beforeConfirm } = props
|
||||
columnChange &&
|
||||
@ -355,24 +206,20 @@ function handleColChange(colIndex: number, item: Record<string, any>, index: num
|
||||
selectedItem: item,
|
||||
index: colIndex,
|
||||
rowIndex: index,
|
||||
resolve: (nextColumn: Record<string, any>[]) => {
|
||||
resolve: (nextColumn: ColPickerOption[]) => {
|
||||
if (!isArray(nextColumn)) {
|
||||
console.error('[wot design] error(wd-col-picker): the data of each column of wd-col-picker should be an array')
|
||||
return
|
||||
}
|
||||
|
||||
const newSelectList = selectList.value.slice(0)
|
||||
newSelectList[colIndex + 1] = nextColumn
|
||||
|
||||
selectList.value = newSelectList
|
||||
innerColumns.value[colIndex + 1] = nextColumn
|
||||
loading.value = false
|
||||
currentCol.value = colIndex + 1
|
||||
|
||||
updateLineAndScroll(true)
|
||||
nextTick(() => {
|
||||
currentCol.value = colIndex + 1
|
||||
})
|
||||
if (typeof callback === 'function') {
|
||||
isCompleting.value = false
|
||||
selectShowList.value = pickerColSelected.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, selectList.value)[props.labelKey]
|
||||
currentColumn.value = innerValue.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, innerColumns.value)[props.labelKey]
|
||||
})
|
||||
callback()
|
||||
}
|
||||
@ -391,9 +238,9 @@ function handleColChange(colIndex: number, item: Record<string, any>, index: num
|
||||
|
||||
if (beforeConfirm) {
|
||||
beforeConfirm(
|
||||
pickerColSelected.value,
|
||||
pickerColSelected.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, selectList.value)
|
||||
innerValue.value,
|
||||
innerValue.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, innerColumns.value)
|
||||
}),
|
||||
(isPass: boolean) => {
|
||||
if (isPass) {
|
||||
@ -410,68 +257,18 @@ function handleColChange(colIndex: number, item: Record<string, any>, index: num
|
||||
})
|
||||
}
|
||||
function onConfirm() {
|
||||
isChange.value = false
|
||||
loading.value = false
|
||||
pickerShow.value = false
|
||||
|
||||
emit('update:modelValue', pickerColSelected.value)
|
||||
lastPickerColSelected.value = deepClone(innerValue.value)
|
||||
lastSelectList.value = deepClone(innerColumns.value)
|
||||
emit('update:modelValue', innerValue.value)
|
||||
emit('confirm', {
|
||||
value: pickerColSelected.value,
|
||||
selectedItems: pickerColSelected.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, selectList.value)
|
||||
value: innerValue.value,
|
||||
selectedItems: innerValue.value.map((item, colIndex) => {
|
||||
return getSelectedItem(item, colIndex, innerColumns.value)
|
||||
})
|
||||
})
|
||||
}
|
||||
function handleColClick(index: number) {
|
||||
isChange.value = true
|
||||
currentCol.value = index
|
||||
updateLineAndScroll(true)
|
||||
}
|
||||
/**
|
||||
* @description 更新navBar underline的偏移量
|
||||
* @param {Boolean} animation 是否伴随动画
|
||||
*/
|
||||
function setLineStyle(animation: boolean = true) {
|
||||
if (!inited.value) return
|
||||
const { lineWidth, lineHeight } = props
|
||||
getRect($item, true, proxy)
|
||||
.then((rects) => {
|
||||
const lineStyle: CSSProperties = {}
|
||||
if (isDef(lineWidth)) {
|
||||
lineStyle.width = addUnit(lineWidth)
|
||||
}
|
||||
if (isDef(lineHeight)) {
|
||||
lineStyle.height = addUnit(lineHeight)
|
||||
lineStyle.borderRadius = `calc(${addUnit(lineHeight)} / 2)`
|
||||
}
|
||||
const rect = rects[currentCol.value]
|
||||
let left = rects.slice(0, currentCol.value).reduce((prev, curr) => prev + Number(curr.width), 0) + Number(rect.width) / 2
|
||||
lineStyle.transform = `translateX(${left}px) translateX(-50%)`
|
||||
|
||||
if (animation) {
|
||||
lineStyle.transition = 'width 300ms ease, transform 300ms ease'
|
||||
}
|
||||
|
||||
state.lineStyle = objToStyle(lineStyle)
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
/**
|
||||
* @description scroll-view滑动到active的tab_nav
|
||||
*/
|
||||
function lineScrollIntoView() {
|
||||
if (!inited.value) return
|
||||
Promise.all([getRect($item, true, proxy), getRect($container, false, proxy)])
|
||||
.then(([navItemsRects, navRect]) => {
|
||||
if (!isArray(navItemsRects) || navItemsRects.length === 0) return
|
||||
// 选中元素
|
||||
const selectItem = navItemsRects[currentCol.value]
|
||||
// 选中元素之前的节点的宽度总和
|
||||
const offsetLeft = navItemsRects.slice(0, currentCol.value).reduce((prev, curr) => prev + Number(curr.width), 0)
|
||||
// scroll-view滑动到selectItem的偏移量
|
||||
scrollLeft.value = offsetLeft - ((navRect as any).width - Number(selectItem.width)) / 2
|
||||
})
|
||||
.catch(() => {})
|
||||
emit('update:visible', false)
|
||||
}
|
||||
|
||||
// 递归列数据补齐
|
||||
@ -480,7 +277,7 @@ function diffColumns(colIndex: number) {
|
||||
const item = colIndex === -1 ? {} : { [props.valueKey]: props.modelValue[colIndex] }
|
||||
handleColChange(colIndex, item, -1, () => {
|
||||
// 如果 columns 长度还小于 value 长度,colIndex + 1,继续递归补齐
|
||||
if (selectList.value.length < props.modelValue.length) {
|
||||
if (innerColumns.value.length < props.modelValue.length) {
|
||||
diffColumns(colIndex + 1)
|
||||
}
|
||||
})
|
||||
@ -488,11 +285,11 @@ function diffColumns(colIndex: number) {
|
||||
function handleAutoComplete() {
|
||||
if (props.autoComplete) {
|
||||
// 如果 columns 数组长度为空,或者长度小于 value 的长度,自动触发 columnChange 来补齐数据
|
||||
if (selectList.value.length < props.modelValue.length || selectList.value.length === 0) {
|
||||
if (innerColumns.value.length < props.modelValue.length || innerColumns.value.length === 0) {
|
||||
// isCompleting 是否在自动补全,锁操作
|
||||
if (!isCompleting.value) {
|
||||
// 如果 columns 长度为空,则传入的 colIndex 为 -1
|
||||
const colIndex = selectList.value.length === 0 ? -1 : selectList.value.length - 1
|
||||
const colIndex = innerColumns.value.length === 0 ? -1 : innerColumns.value.length - 1
|
||||
diffColumns(colIndex)
|
||||
}
|
||||
isCompleting.value = true
|
||||
|
||||
@ -3,37 +3,10 @@
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(picker) {
|
||||
@include e(cell) {
|
||||
background-color: $-dark-background2;
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(title) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
@include e(value) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(placeholder) {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
|
||||
|
||||
@include when(border) {
|
||||
.wd-picker__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding, $-dark-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.wd-picker__arrow){
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(action) {
|
||||
@include m(cancel) {
|
||||
color: $-dark-color;
|
||||
@ -61,118 +34,6 @@
|
||||
padding-bottom: var(--window-bottom);
|
||||
}
|
||||
|
||||
@include when(border) {
|
||||
.wd-picker__cell {
|
||||
@include halfPixelBorder("top", $-cell-padding);
|
||||
}
|
||||
}
|
||||
@include when(large) {
|
||||
.wd-picker__cell {
|
||||
font-size: $-cell-title-fs-large;
|
||||
}
|
||||
:deep(.wd-picker__arrow) {
|
||||
font-size: $-cell-icon-size-large;
|
||||
}
|
||||
}
|
||||
@include when(error) {
|
||||
.wd-picker__value,
|
||||
.wd-picker__placeholder {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
|
||||
:deep(.wd-picker__arrow){
|
||||
color: $-input-error-color;
|
||||
}
|
||||
}
|
||||
@include when(align-right) {
|
||||
.wd-picker__value {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@include e(cell) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: $-cell-wrapper-padding $-cell-padding;
|
||||
align-items: flex-start;
|
||||
background-color: $-color-white;
|
||||
text-decoration: none;
|
||||
color: $-cell-title-color;
|
||||
font-size: $-cell-title-fs;
|
||||
overflow: hidden;
|
||||
line-height: $-cell-line-height;
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-picker__value {
|
||||
color: $-input-disabled-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-picker__value {
|
||||
color: $-picker-column-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(error-message){
|
||||
color: $-form-item-error-message-color;
|
||||
font-size: $-form-item-error-message-font-size;
|
||||
line-height: $-form-item-error-message-line-height;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
position: relative;
|
||||
width: $-input-cell-label-width;
|
||||
margin-right: $-cell-padding;
|
||||
color: $-cell-title-color;
|
||||
box-sizing: border-box;
|
||||
|
||||
@include when(required) {
|
||||
padding-left: 12px;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
content: "*";
|
||||
font-size: $-cell-required-size;
|
||||
line-height: 1.1;
|
||||
color: $-cell-required-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include e(value-wraper) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@include e(value) {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
color: $-cell-value-color;
|
||||
|
||||
@include when(ellipsis) {
|
||||
@include lineEllipsis;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(body) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@include e(placeholder) {
|
||||
color: $-input-placeholder-color;
|
||||
}
|
||||
|
||||
@include edeep(arrow) {
|
||||
display: block;
|
||||
font-size: $-cell-icon-size;
|
||||
color: $-cell-arrow-color;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
|
||||
@include e(toolbar) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
@ -1,26 +1,9 @@
|
||||
import type { ComponentPublicInstance, ExtractPropTypes, PropType } from 'vue'
|
||||
import { baseProps, makeArrayProp, makeBooleanProp, makeNumberProp, makeRequiredProp, makeStringProp } from '../common/props'
|
||||
import { baseProps, makeBooleanProp, makeNumberProp, makeRequiredProp, makeStringProp } from '../common/props'
|
||||
import type { DateTimeType, DatetimePickerViewFilter, DatetimePickerViewFormatter } from '../wd-datetime-picker-view/types'
|
||||
import type { FormItemRule } from '../wd-form/types'
|
||||
|
||||
export const datetimePickerProps = {
|
||||
...baseProps,
|
||||
/**
|
||||
* 选择器左侧文案,label可以不传
|
||||
*/
|
||||
label: String,
|
||||
/**
|
||||
* 选择器占位符
|
||||
*/
|
||||
placeholder: String,
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
disabled: makeBooleanProp(false),
|
||||
/**
|
||||
* 只读
|
||||
*/
|
||||
readonly: makeBooleanProp(false),
|
||||
/**
|
||||
* 加载中
|
||||
*/
|
||||
@ -41,34 +24,6 @@ export const datetimePickerProps = {
|
||||
* 确认按钮文案
|
||||
*/
|
||||
confirmButtonText: String,
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
required: makeBooleanProp(false),
|
||||
/**
|
||||
* 设置选择器大小,可选值:large
|
||||
*/
|
||||
size: String,
|
||||
/**
|
||||
* 设置左侧标题宽度
|
||||
*/
|
||||
labelWidth: makeStringProp('33%'),
|
||||
/**
|
||||
* 使用默认插槽
|
||||
*/
|
||||
useDefaultSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* label 使用插槽
|
||||
*/
|
||||
useLabelSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否为错误状态,错误状态时右侧内容为红色
|
||||
*/
|
||||
error: makeBooleanProp(false),
|
||||
/**
|
||||
* 选择器的值靠右展示
|
||||
*/
|
||||
alignRight: makeBooleanProp(false),
|
||||
/**
|
||||
* 点击遮罩是否关闭
|
||||
*/
|
||||
@ -77,10 +32,6 @@ export const datetimePickerProps = {
|
||||
* 弹出面板是否设置底部安全距离(iphone X 类型的机型)
|
||||
*/
|
||||
safeAreaInsetBottom: makeBooleanProp(true),
|
||||
/**
|
||||
* 是否超出隐藏
|
||||
*/
|
||||
ellipsis: makeBooleanProp(false),
|
||||
/**
|
||||
* picker内部滚筒高
|
||||
*/
|
||||
@ -147,30 +98,10 @@ export const datetimePickerProps = {
|
||||
* 弹窗层级
|
||||
*/
|
||||
zIndex: makeNumberProp(15),
|
||||
/**
|
||||
* 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
|
||||
*/
|
||||
prop: String,
|
||||
/**
|
||||
* 表单验证规则,结合wd-form组件使用
|
||||
*/
|
||||
rules: makeArrayProp<FormItemRule>(),
|
||||
/**
|
||||
* picker cell 外部自定义样式
|
||||
*/
|
||||
customCellClass: makeStringProp(''),
|
||||
/**
|
||||
* pickerView 外部自定义样式
|
||||
*/
|
||||
customViewClass: makeStringProp(''),
|
||||
/**
|
||||
* label 外部自定义样式
|
||||
*/
|
||||
customLabelClass: makeStringProp(''),
|
||||
/**
|
||||
* value 外部自定义样式
|
||||
*/
|
||||
customValueClass: makeStringProp(''),
|
||||
/**
|
||||
* 是否在手指松开时立即触发picker-view的 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。
|
||||
*/
|
||||
|
||||
@ -1,49 +1,5 @@
|
||||
<template>
|
||||
<view
|
||||
:class="`wd-picker ${disabled ? 'is-disabled' : ''} ${size ? 'is-' + size : ''} ${cell.border.value ? 'is-border' : ''} ${
|
||||
alignRight ? 'is-align-right' : ''
|
||||
} ${error ? 'is-error' : ''} ${customClass}`"
|
||||
:style="customStyle"
|
||||
>
|
||||
<!--文案-->
|
||||
<view class="wd-picker__field" @click="showPopup">
|
||||
<slot v-if="useDefaultSlot"></slot>
|
||||
<view v-else :class="['wd-picker__cell', customCellClass]">
|
||||
<view
|
||||
v-if="label || useLabelSlot"
|
||||
:class="`wd-picker__label ${customLabelClass} ${isRequired ? 'is-required' : ''}`"
|
||||
:style="labelWidth ? 'min-width:' + labelWidth + ';max-width:' + labelWidth + ';' : ''"
|
||||
>
|
||||
<block v-if="label">{{ label }}</block>
|
||||
<slot v-else name="label"></slot>
|
||||
</view>
|
||||
<view class="wd-picker__body">
|
||||
<view class="wd-picker__value-wraper">
|
||||
<view :class="`wd-picker__value ${customValueClass}`">
|
||||
<template v-if="region">
|
||||
<view v-if="isArray(showValue)">
|
||||
<text :class="showValue[0] ? '' : 'wd-picker__placeholder'">
|
||||
{{ showValue[0] ? showValue[0] : placeholder || translate('placeholder') }}
|
||||
</text>
|
||||
{{ translate('to') }}
|
||||
<text :class="showValue[1] ? '' : 'wd-picker__placeholder'">
|
||||
{{ showValue[1] ? showValue[1] : placeholder || translate('placeholder') }}
|
||||
</text>
|
||||
</view>
|
||||
<view v-else class="wd-picker__placeholder">
|
||||
{{ placeholder || translate('placeholder') }}
|
||||
</view>
|
||||
</template>
|
||||
<view v-else :class="showValue ? '' : 'wd-picker__placeholder'">
|
||||
{{ showValue ? showValue : placeholder || translate('placeholder') }}
|
||||
</view>
|
||||
</view>
|
||||
<wd-icon v-if="!disabled && !readonly" custom-class="wd-picker__arrow" name="arrow-right" />
|
||||
</view>
|
||||
<view v-if="errorMessage" class="wd-picker__error-message">{{ errorMessage }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="`wd-picker ${customClass}`" :style="customStyle">
|
||||
<!--弹出层,picker-view 在隐藏时修改值,会触发多次change事件,从而导致所有列选中第一项,因此picker在关闭时不隐藏 -->
|
||||
<wd-popup
|
||||
v-model="popupShow"
|
||||
@ -154,17 +110,14 @@ export default {
|
||||
<script lang="ts" setup>
|
||||
import wdPopup from '../wd-popup/wd-popup.vue'
|
||||
import wdDatetimePickerView from '../wd-datetime-picker-view/wd-datetime-picker-view.vue'
|
||||
import { computed, getCurrentInstance, nextTick, onBeforeMount, onMounted, ref, watch } from 'vue'
|
||||
import { getCurrentInstance, nextTick, onBeforeMount, onMounted, ref, watch } from 'vue'
|
||||
import { deepClone, isArray, isDef, isEqual, isFunction, padZero } from '../common/util'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import {
|
||||
getPickerValue,
|
||||
type DatetimePickerViewInstance,
|
||||
type DatetimePickerViewColumnFormatter,
|
||||
type DatetimePickerViewColumnType
|
||||
} from '../wd-datetime-picker-view/types'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { datetimePickerProps, type DatetimePickerExpose } from './types'
|
||||
import { dayjs } from '../common/dayjs'
|
||||
@ -177,7 +130,6 @@ const { translate } = useTranslate('datetime-picker')
|
||||
const datetimePickerView = ref<DatetimePickerViewInstance>()
|
||||
const datetimePickerView1 = ref<DatetimePickerViewInstance>()
|
||||
|
||||
const showValue = ref<string | Date | Array<string | Date>>('')
|
||||
const popupShow = ref<boolean>(false)
|
||||
const showStart = ref<boolean>(true)
|
||||
const region = ref<boolean>(false)
|
||||
@ -191,8 +143,6 @@ const hasConfirmed = ref<boolean>(false) // 判断用户是否点击了确认按
|
||||
const isLoading = ref<boolean>(false) // 加载
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
const cell = useCell()
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val, oldVal) => {
|
||||
@ -293,31 +243,6 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const { parent: form } = useParent(FORM_KEY)
|
||||
|
||||
// 表单校验错误信息
|
||||
const errorMessage = computed(() => {
|
||||
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
|
||||
return form.errorMessages[props.prop]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
// 是否展示必填
|
||||
const isRequired = computed(() => {
|
||||
let formRequired = false
|
||||
if (form && form.props.rules) {
|
||||
const rules = form.props.rules
|
||||
for (const key in rules) {
|
||||
if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
|
||||
formRequired = rules[key].some((rule: FormItemRule) => rule.required)
|
||||
}
|
||||
}
|
||||
}
|
||||
return props.required || props.rules.some((rule) => rule.required) || formRequired
|
||||
})
|
||||
|
||||
/**
|
||||
* @description 自定义列项筛选规则,对每列单项进行禁用校验,最终返回传入PickerView的columns数组
|
||||
* @param {Component} picker datetimePickerView对象
|
||||
@ -419,8 +344,6 @@ function close() {
|
||||
* @description 展示popup,小程序有个bug,在picker-view弹出时设置value,会触发change事件,而且会将picker-view的value多次触发change重置为第一项
|
||||
*/
|
||||
function showPopup() {
|
||||
if (props.disabled || props.readonly) return
|
||||
|
||||
emit('open')
|
||||
if (region.value) {
|
||||
popupShow.value = true
|
||||
@ -536,7 +459,7 @@ function onPickEnd() {
|
||||
}
|
||||
|
||||
function handleConfirm() {
|
||||
if (props.loading || isLoading.value || props.disabled) {
|
||||
if (props.loading || isLoading.value) {
|
||||
popupShow.value = false
|
||||
return
|
||||
}
|
||||
@ -585,19 +508,7 @@ function setShowValue(tab: boolean = false, isConfirm: boolean = false, beforeMo
|
||||
? (endInnerValue.value && getSelects('after')) || []
|
||||
: (datetimePickerView1.value && datetimePickerView1.value.getSelects && datetimePickerView1.value.getSelects()) || []
|
||||
|
||||
showValue.value = tab
|
||||
? showValue.value
|
||||
: [
|
||||
(props.modelValue as (string | number)[])[0] || isConfirm ? defaultDisplayFormat(items as Record<string, any>[]) : '',
|
||||
(props.modelValue as (string | number)[])[1] || isConfirm ? defaultDisplayFormat(endItems as Record<string, any>[]) : ''
|
||||
]
|
||||
showTabLabel.value = [defaultDisplayFormat(items as Record<string, any>[], true), defaultDisplayFormat(endItems as Record<string, any>[], true)]
|
||||
} else {
|
||||
const items = beforeMount
|
||||
? (innerValue.value && getSelects('before')) || []
|
||||
: (datetimePickerView.value && datetimePickerView.value.getSelects && datetimePickerView.value.getSelects()) || []
|
||||
|
||||
showValue.value = deepClone(props.modelValue || isConfirm ? defaultDisplayFormat(items as Record<string, any>[]) : '')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
<!--
|
||||
* @Author: weisheng
|
||||
* @Date: 2023-12-14 11:21:58
|
||||
* @LastEditTime: 2024-03-15 21:29:33
|
||||
* @Date: 2024-10-25 10:34:37
|
||||
* @LastEditTime: 2024-11-13 18:33:38
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-form-item/wd-form-item.vue
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-form-item\wd-form-item.vue
|
||||
* 记得注释
|
||||
-->
|
||||
<template>
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
display: flex;
|
||||
width: $-input-cell-label-width;
|
||||
color: $-cell-title-color;
|
||||
margin-right: $-cell-padding;
|
||||
margin-right: $-cell-vertical-padding;
|
||||
box-sizing: border-box;
|
||||
font-size: $-input-fs;
|
||||
flex-shrink: 0;
|
||||
|
||||
@ -4,55 +4,11 @@
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(picker) {
|
||||
@include when(border) {
|
||||
.wd-picker__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding, $-dark-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
@include e(title) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
@include e(value) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(placeholder) {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
|
||||
:deep(.wd-picker__arrow),
|
||||
:deep(.wd-picker__clear) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include e(cell) {
|
||||
background-color: $-dark-background2;
|
||||
color: $-dark-color;
|
||||
@include when(disabled) {
|
||||
.wd-picker__value {
|
||||
color: $-dark-color3;
|
||||
}
|
||||
.wd-picker__placeholder {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-picker__value {
|
||||
color: $-dark-color3;
|
||||
}
|
||||
|
||||
.wd-picker__placeholder {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(action) {
|
||||
@include m(cancel) {
|
||||
color: $-dark-color;
|
||||
@ -70,119 +26,6 @@
|
||||
border-radius: 16px 16px 0px 0px;
|
||||
}
|
||||
|
||||
@include when(border) {
|
||||
.wd-picker__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding);
|
||||
}
|
||||
}
|
||||
@include when(large) {
|
||||
.wd-picker__cell {
|
||||
font-size: $-cell-title-fs-large;
|
||||
}
|
||||
:deep(.wd-picker__arrow),
|
||||
:deep(.wd-picker__clear) {
|
||||
font-size: $-cell-icon-size-large;
|
||||
}
|
||||
}
|
||||
@include when(error) {
|
||||
.wd-picker__value,
|
||||
:deep(.wd-picker__arrow) {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
}
|
||||
@include when(align-right) {
|
||||
.wd-picker__value {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@include e(cell) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: $-cell-wrapper-padding $-cell-padding;
|
||||
align-items: flex-start;
|
||||
background-color: $-color-white;
|
||||
text-decoration: none;
|
||||
color: $-cell-title-color;
|
||||
font-size: $-cell-title-fs;
|
||||
overflow: hidden;
|
||||
line-height: $-cell-line-height;
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-picker__value {
|
||||
color: $-input-disabled-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-picker__value {
|
||||
color: $-picker-column-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(error-message){
|
||||
color: $-form-item-error-message-color;
|
||||
font-size: $-form-item-error-message-font-size;
|
||||
line-height: $-form-item-error-message-line-height;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
position: relative;
|
||||
width: $-input-cell-label-width;
|
||||
margin-right: $-cell-padding;
|
||||
color: $-cell-title-color;
|
||||
box-sizing: border-box;
|
||||
|
||||
@include when(required) {
|
||||
padding-left: 12px;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
content: '*';
|
||||
font-size: $-cell-required-size;
|
||||
line-height: 1.1;
|
||||
color: $-cell-required-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include e(value-wraper) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@include e(value) {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
color: $-cell-value-color;
|
||||
|
||||
@include when(ellipsis) {
|
||||
@include lineEllipsis;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(body) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@include e(placeholder) {
|
||||
color: $-input-placeholder-color;
|
||||
}
|
||||
|
||||
@include edeep(arrow,clear) {
|
||||
display: block;
|
||||
font-size: $-cell-icon-size;
|
||||
color: $-cell-arrow-color;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
|
||||
@include edeep(clear){
|
||||
color: $-cell-clear-color;
|
||||
}
|
||||
|
||||
@include e(wraper) {
|
||||
padding-bottom: var(--window-bottom);
|
||||
}
|
||||
|
||||
@ -5,34 +5,10 @@ import type { FormItemRule } from '../wd-form/types'
|
||||
|
||||
export const pickerProps = {
|
||||
...baseProps,
|
||||
/**
|
||||
* label 外部自定义样式
|
||||
*/
|
||||
customLabelClass: makeStringProp(''),
|
||||
/**
|
||||
* value 外部自定义样式
|
||||
*/
|
||||
customValueClass: makeStringProp(''),
|
||||
/**
|
||||
* pickerView 外部自定义样式
|
||||
*/
|
||||
customViewClass: makeStringProp(''),
|
||||
/**
|
||||
* 选择器左侧文案
|
||||
*/
|
||||
label: String,
|
||||
/**
|
||||
* 选择器占位符
|
||||
*/
|
||||
placeholder: String,
|
||||
/**
|
||||
* 是否禁用
|
||||
*/
|
||||
disabled: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否只读
|
||||
*/
|
||||
readonly: makeBooleanProp(false),
|
||||
/**
|
||||
* 加载中
|
||||
*/
|
||||
@ -54,34 +30,6 @@ export const pickerProps = {
|
||||
* 确认按钮文案
|
||||
*/
|
||||
confirmButtonText: String,
|
||||
/**
|
||||
* 是否必填
|
||||
*/
|
||||
required: makeBooleanProp(false),
|
||||
/**
|
||||
* 尺寸
|
||||
*/
|
||||
size: String,
|
||||
/**
|
||||
* 标签宽度
|
||||
*/
|
||||
labelWidth: String,
|
||||
/**
|
||||
* 使用默认插槽
|
||||
*/
|
||||
useDefaultSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 使用标签插槽
|
||||
*/
|
||||
useLabelSlot: makeBooleanProp(false),
|
||||
/**
|
||||
* 错误状态
|
||||
*/
|
||||
error: makeBooleanProp(false),
|
||||
/**
|
||||
* 右对齐
|
||||
*/
|
||||
alignRight: makeBooleanProp(false),
|
||||
/**
|
||||
* 确定前校验函数,接收 (value, resolve, picker) 参数,通过 resolve 继续执行 picker,resolve 接收1个boolean参数
|
||||
*/
|
||||
@ -94,10 +42,6 @@ export const pickerProps = {
|
||||
* 底部安全区域内
|
||||
*/
|
||||
safeAreaInsetBottom: makeBooleanProp(true),
|
||||
/**
|
||||
* 文本溢出显示省略号
|
||||
*/
|
||||
ellipsis: makeBooleanProp(false),
|
||||
/**
|
||||
* 选项总高度
|
||||
*/
|
||||
@ -136,22 +80,10 @@ export const pickerProps = {
|
||||
* 自定义层级
|
||||
*/
|
||||
zIndex: makeNumberProp(15),
|
||||
/**
|
||||
* 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
|
||||
*/
|
||||
prop: String,
|
||||
/**
|
||||
* 表单验证规则,结合wd-form组件使用
|
||||
*/
|
||||
rules: makeArrayProp<FormItemRule>(),
|
||||
/**
|
||||
* 是否在手指松开时立即触发 change 事件。若不开启则会在滚动动画结束后触发 change 事件,1.2.25版本起提供,仅微信小程序和支付宝小程序支持。
|
||||
*/
|
||||
immediateChange: makeBooleanProp(false),
|
||||
/**
|
||||
* 显示清空按钮
|
||||
*/
|
||||
clearable: makeBooleanProp(false)
|
||||
immediateChange: makeBooleanProp(false)
|
||||
}
|
||||
|
||||
export type PickerProps = ExtractPropTypes<typeof pickerProps>
|
||||
|
||||
@ -1,35 +1,5 @@
|
||||
<template>
|
||||
<view
|
||||
:class="`wd-picker ${disabled ? 'is-disabled' : ''} ${size ? 'is-' + size : ''} ${cell.border.value ? 'is-border' : ''} ${
|
||||
alignRight ? 'is-align-right' : ''
|
||||
} ${error ? 'is-error' : ''} ${customClass}`"
|
||||
:style="customStyle"
|
||||
>
|
||||
<view class="wd-picker__field" @click="showPopup">
|
||||
<slot v-if="useDefaultSlot"></slot>
|
||||
<view v-else class="wd-picker__cell">
|
||||
<view
|
||||
v-if="label || useLabelSlot"
|
||||
:class="`wd-picker__label ${customLabelClass} ${isRequired ? 'is-required' : ''}`"
|
||||
:style="labelWidth ? 'min-width:' + labelWidth + ';max-width:' + labelWidth + ';' : ''"
|
||||
>
|
||||
<template v-if="label">{{ label }}</template>
|
||||
<slot v-else name="label"></slot>
|
||||
</view>
|
||||
<view class="wd-picker__body">
|
||||
<view class="wd-picker__value-wraper">
|
||||
<view :class="`wd-picker__value ${ellipsis && 'is-ellipsis'} ${customValueClass} ${showValue ? '' : 'wd-picker__placeholder'}`">
|
||||
{{ showValue ? showValue : placeholder || translate('placeholder') }}
|
||||
</view>
|
||||
<wd-icon v-if="showArrow" custom-class="wd-picker__arrow" name="arrow-right" />
|
||||
<view v-else-if="showClear" @click.stop="handleClear">
|
||||
<wd-icon custom-class="wd-picker__clear" name="error-fill" />
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="errorMessage" class="wd-picker__error-message">{{ errorMessage }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="`wd-picker ${customClass}`" :style="customStyle">
|
||||
<wd-popup
|
||||
v-model="popupShow"
|
||||
position="bottom"
|
||||
@ -83,15 +53,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import wdPopup from '../wd-popup/wd-popup.vue'
|
||||
import wdPickerView from '../wd-picker-view/wd-picker-view.vue'
|
||||
import { getCurrentInstance, onBeforeMount, ref, watch, computed, onMounted, nextTick } from 'vue'
|
||||
import { deepClone, defaultDisplayFormat, getType, isArray, isDef, isFunction } from '../common/util'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { deepClone, getType, isArray, isDef, isFunction } from '../common/util'
|
||||
import { type ColumnItem, formatArray, type PickerViewInstance } from '../wd-picker-view/types'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { pickerProps, type PickerExpose } from './types'
|
||||
const { translate } = useTranslate('picker')
|
||||
@ -100,14 +66,12 @@ const props = defineProps(pickerProps)
|
||||
const emit = defineEmits(['confirm', 'open', 'cancel', 'clear', 'update:modelValue'])
|
||||
|
||||
const pickerViewWd = ref<PickerViewInstance | null>(null)
|
||||
const cell = useCell()
|
||||
|
||||
const innerLoading = ref<boolean>(false) // 内部控制是否loading
|
||||
|
||||
// 弹出层是否显示
|
||||
const popupShow = ref<boolean>(false)
|
||||
// 选定后展示的选中项
|
||||
const showValue = ref<string>('')
|
||||
const pickerValue = ref<string | number | boolean | string[] | number[] | boolean[]>('')
|
||||
const displayColumns = ref<Array<string | number | ColumnItem | Array<string | number | ColumnItem>>>([]) // 传入 pickerView 的columns
|
||||
const resetColumns = ref<Array<string | number | ColumnItem | Array<string | number | ColumnItem>>>([]) // 保存之前的 columns,当取消时,将数据源回滚,避免多级联动数据源不正确的情况
|
||||
@ -174,31 +138,6 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const { parent: form } = useParent(FORM_KEY)
|
||||
|
||||
// 表单校验错误信息
|
||||
const errorMessage = computed(() => {
|
||||
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
|
||||
return form.errorMessages[props.prop]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
// 是否展示必填
|
||||
const isRequired = computed(() => {
|
||||
let formRequired = false
|
||||
if (form && form.props.rules) {
|
||||
const rules = form.props.rules
|
||||
for (const key in rules) {
|
||||
if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
|
||||
formRequired = rules[key].some((rule: FormItemRule) => rule.required)
|
||||
}
|
||||
}
|
||||
}
|
||||
return props.required || props.rules.some((rule) => rule.required) || formRequired
|
||||
})
|
||||
|
||||
const { proxy } = getCurrentInstance() as any
|
||||
|
||||
onMounted(() => {
|
||||
@ -219,13 +158,13 @@ function handleShowValueUpdate(value: string | number | Array<string | number>)
|
||||
if ((isArray(value) && value.length > 0) || (isDef(value) && !isArray(value) && value !== '')) {
|
||||
if (pickerViewWd.value) {
|
||||
nextTick(() => {
|
||||
setShowValue(pickerViewWd.value!.getSelects())
|
||||
// setShowValue(pickerViewWd.value!.getSelects())
|
||||
})
|
||||
} else {
|
||||
setShowValue(getSelects(value)!)
|
||||
// setShowValue(getSelects(value)!)
|
||||
}
|
||||
} else {
|
||||
showValue.value = ''
|
||||
// showValue.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,8 +223,6 @@ function close() {
|
||||
* 展示popup
|
||||
*/
|
||||
function showPopup() {
|
||||
if (props.disabled || props.readonly) return
|
||||
|
||||
emit('open')
|
||||
popupShow.value = true
|
||||
pickerValue.value = props.modelValue
|
||||
@ -329,7 +266,7 @@ function onConfirm() {
|
||||
}
|
||||
}
|
||||
function handleConfirm() {
|
||||
if (isLoading.value || props.disabled) {
|
||||
if (isLoading.value) {
|
||||
popupShow.value = false
|
||||
return
|
||||
}
|
||||
@ -342,7 +279,7 @@ function handleConfirm() {
|
||||
resetColumns.value = deepClone(columns)
|
||||
emit('update:modelValue', values)
|
||||
|
||||
setShowValue(selects)
|
||||
// setShowValue(selects)
|
||||
emit('confirm', {
|
||||
value: values,
|
||||
selectedItems: selects
|
||||
@ -355,18 +292,9 @@ function handleConfirm() {
|
||||
function pickerViewChange({ value }: any) {
|
||||
pickerValue.value = value
|
||||
}
|
||||
/**
|
||||
* 设置展示值
|
||||
* @param items
|
||||
*/
|
||||
function setShowValue(items: ColumnItem | ColumnItem[]) {
|
||||
// 避免值为空时调用自定义展示函数
|
||||
if ((isArray(items) && !items.length) || !items) return
|
||||
|
||||
const { valueKey, labelKey } = props
|
||||
showValue.value = (props.displayFormat || defaultDisplayFormat)(items, { valueKey, labelKey })
|
||||
}
|
||||
function noop() {}
|
||||
|
||||
function onPickStart() {
|
||||
isPicking.value = true
|
||||
}
|
||||
@ -387,22 +315,6 @@ function setLoading(loading: boolean) {
|
||||
innerLoading.value = loading
|
||||
}
|
||||
|
||||
// 是否展示清除按钮
|
||||
const showClear = computed(() => {
|
||||
return props.clearable && !props.disabled && !props.readonly && showValue.value.length
|
||||
})
|
||||
|
||||
function handleClear() {
|
||||
const clearValue = isArray(pickerValue.value) ? [] : ''
|
||||
emit('update:modelValue', clearValue)
|
||||
emit('clear')
|
||||
}
|
||||
|
||||
// 是否展示箭头
|
||||
const showArrow = computed(() => {
|
||||
return !props.disabled && !props.readonly && !showClear.value
|
||||
})
|
||||
|
||||
defineExpose<PickerExpose>({
|
||||
close,
|
||||
open,
|
||||
|
||||
@ -37,10 +37,13 @@
|
||||
font-size: $-progress-icon-fs;
|
||||
|
||||
@include when(danger) {
|
||||
background: $-progress-linear-danger-color;
|
||||
background: $-progress-danger-color;
|
||||
}
|
||||
@include when(success) {
|
||||
background: $-progress-linear-success-color;
|
||||
background: $-progress-success-color;
|
||||
}
|
||||
@include when(warning) {
|
||||
background: $-progress-warning-color;
|
||||
}
|
||||
}
|
||||
@include edeep(label) {
|
||||
@ -58,5 +61,8 @@
|
||||
@include when(success) {
|
||||
color: $-progress-success-color;
|
||||
}
|
||||
@include when(warning) {
|
||||
color: $-progress-warning-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,16 +1,21 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-03-15 20:40:34
|
||||
* @LastEditTime: 2024-03-18 15:32:11
|
||||
* @LastEditTime: 2024-11-13 21:52:52
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-progress\types.ts
|
||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-progress/types.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import type { PropType } from 'vue'
|
||||
import { baseProps, makeBooleanProp, makeNumberProp } from '../common/props'
|
||||
|
||||
export type ProgressStatus = 'success' | 'danger' // 状态类型
|
||||
export type ProgressStatus = 'success' | 'danger' | 'warning' // 状态类型
|
||||
|
||||
export type ProgressColor = {
|
||||
color: string // 颜色
|
||||
percentage: number // 百分比
|
||||
}
|
||||
|
||||
export const progressProps = {
|
||||
...baseProps,
|
||||
@ -26,8 +31,8 @@ export const progressProps = {
|
||||
* 进度条颜色
|
||||
*/
|
||||
color: {
|
||||
type: [String, Array, Object] as PropType<string | string[] | Record<string, any>[]>,
|
||||
default: 'linear-gradient(315deg, rgba(81,124,240,1) 0%,rgba(118,158,245,1) 100%)'
|
||||
type: [String, Array, Object] as PropType<string | string[] | ProgressColor[]>,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 进度增加1%所需毫秒数
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<wd-icon
|
||||
v-else-if="status"
|
||||
:custom-class="`wd-progress__label wd-progress__icon ${progressClass}`"
|
||||
:name="status == 'danger' ? 'close-outline' : 'check-outline'"
|
||||
:name="statusIcon"
|
||||
:color="typeof color === 'string' ? color : ''"
|
||||
></wd-icon>
|
||||
</view>
|
||||
@ -28,9 +28,9 @@ export default {
|
||||
|
||||
<script lang="ts" setup>
|
||||
import wdIcon from '../wd-icon/wd-icon.vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { checkNumRange, isArray, objToStyle } from '../common/util'
|
||||
import { progressProps } from './types'
|
||||
import { computed, ref, watch, type CSSProperties } from 'vue'
|
||||
import { checkNumRange, isArray, isObj, objToStyle } from '../common/util'
|
||||
import { progressProps, type ProgressColor } from './types'
|
||||
|
||||
const props = defineProps(progressProps)
|
||||
// 进度条展示的颜色
|
||||
@ -44,14 +44,34 @@ const progressClass = ref<string>('')
|
||||
let timer: NodeJS.Timeout | null = null // 定时器
|
||||
|
||||
const rootStyle = computed(() => {
|
||||
const style: Record<string, string | number> = {
|
||||
background: showColor.value,
|
||||
const style: CSSProperties = {
|
||||
width: showPercent.value + '%',
|
||||
'transition-duration': changeCount.value * props.duration * 0.001 + 's'
|
||||
}
|
||||
if (showColor.value) {
|
||||
style.background = showColor.value
|
||||
}
|
||||
return objToStyle(style)
|
||||
})
|
||||
|
||||
const statusIcon = computed(() => {
|
||||
let icon: string = ''
|
||||
switch (props.status) {
|
||||
case 'danger':
|
||||
icon = 'close-outline'
|
||||
break
|
||||
case 'success':
|
||||
icon = 'check-outline'
|
||||
break
|
||||
case 'warning':
|
||||
icon = 'warn-bold'
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
return icon
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.percentage,
|
||||
(newValue) => {
|
||||
@ -129,22 +149,15 @@ function update(targetPercent: number, color: string) {
|
||||
* @description 控制进度条的进度和每段的颜色
|
||||
*/
|
||||
function controlProgress() {
|
||||
const {
|
||||
// 目标百分比
|
||||
percentage,
|
||||
// 传入的color数组
|
||||
color
|
||||
} = props
|
||||
// 锁
|
||||
const { percentage, color } = props
|
||||
if (showPercent.value === percentage || !percentage) return
|
||||
/**
|
||||
* 数组边界安全判断
|
||||
*/
|
||||
let colorArray: string[] | Record<string, any>[] = (isArray(color) ? color : [color]) as string[] | Record<string, any>[]
|
||||
let colorArray: string[] | ProgressColor[] = (isArray(color) ? color : [color]) as string[] | ProgressColor[]
|
||||
if (colorArray.length === 0) throw Error('The colorArray is empty')
|
||||
const isStrArray = (colorArray as any).every((item: any) => typeof item === 'string')
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
const isObjArray = (colorArray as any).every((color: any) => color.hasOwnProperty('color') && color.hasOwnProperty('percentage'))
|
||||
const isStrArray = colorArray.every((item) => typeof item === 'string')
|
||||
const isObjArray = colorArray.every((color) => isObj(color))
|
||||
if (!isStrArray && !isObjArray) {
|
||||
throw Error('Color must be String or Object with color and percentage')
|
||||
}
|
||||
|
||||
@ -3,144 +3,11 @@
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(select-picker) {
|
||||
@include when(border) {
|
||||
.wd-select-picker__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding, $-dark-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
@include e(cell) {
|
||||
background-color: $-dark-background2;
|
||||
color: $-dark-color;
|
||||
@include when(disabled) {
|
||||
.wd-select-picker__value {
|
||||
color: $-dark-color3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include e(label) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
@include e(value) {
|
||||
color: $-dark-color;
|
||||
@include m(placeholder) {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.wd-select-picker__arrow),
|
||||
:deep(.wd-select-picker__close),
|
||||
:deep(.wd-select-picker__clear) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@include b(select-picker) {
|
||||
@include when(border) {
|
||||
.wd-select-picker__cell {
|
||||
@include halfPixelBorder('top', $-cell-padding);
|
||||
}
|
||||
}
|
||||
@include e(cell) {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: $-cell-wrapper-padding $-cell-padding;
|
||||
align-items: flex-start;
|
||||
background-color: $-color-white;
|
||||
text-decoration: none;
|
||||
color: $-cell-title-color;
|
||||
font-size: $-cell-title-fs;
|
||||
overflow: hidden;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
@include e(cell) {
|
||||
@include when(disabled) {
|
||||
.wd-select-picker__value {
|
||||
color: $-input-disabled-color;
|
||||
}
|
||||
}
|
||||
@include when(align-right) {
|
||||
.wd-select-picker__value {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
@include when(error) {
|
||||
.wd-select-picker__value {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
:deep(.wd-select-picker__arrow) {
|
||||
color: $-input-error-color;
|
||||
}
|
||||
}
|
||||
@include when(large) {
|
||||
font-size: $-cell-title-fs-large;
|
||||
|
||||
:deep(.wd-select-picker__arrow),
|
||||
:deep(.wd-select-picker__clear) {
|
||||
font-size: $-cell-icon-size-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include e(error-message){
|
||||
color: $-form-item-error-message-color;
|
||||
font-size: $-form-item-error-message-font-size;
|
||||
line-height: $-form-item-error-message-line-height;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@include e(label) {
|
||||
position: relative;
|
||||
width: $-input-cell-label-width;
|
||||
color: $-cell-title-color;
|
||||
margin-right: $-cell-padding;
|
||||
box-sizing: border-box;
|
||||
|
||||
@include when(required) {
|
||||
padding-left: 12px;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 2px;
|
||||
content: '*';
|
||||
font-size: $-cell-required-size;
|
||||
line-height: 1.1;
|
||||
color: $-cell-required-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include e(value-wraper) {
|
||||
display: flex;
|
||||
}
|
||||
@include e(value) {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
color: $-cell-value-color;
|
||||
|
||||
@include when(ellipsis) {
|
||||
@include lineEllipsis;
|
||||
}
|
||||
@include m(placeholder) {
|
||||
color: $-input-placeholder-color;
|
||||
}
|
||||
}
|
||||
@include e(body) {
|
||||
flex: 1;
|
||||
}
|
||||
@include edeep(arrow, clear) {
|
||||
display: block;
|
||||
font-size: $-cell-icon-size;
|
||||
color: $-cell-arrow-color;
|
||||
line-height: $-cell-line-height;
|
||||
}
|
||||
|
||||
@include edeep(clear) {
|
||||
color: $-cell-clear-color;
|
||||
}
|
||||
|
||||
@include e(loading) {
|
||||
position: absolute;
|
||||
|
||||
@ -1,40 +1,5 @@
|
||||
<template>
|
||||
<view :class="`wd-select-picker ${cell.border.value ? 'is-border' : ''} ${customClass}`" :style="customStyle">
|
||||
<view class="wd-select-picker__field" @click="open">
|
||||
<slot v-if="useDefaultSlot"></slot>
|
||||
<view
|
||||
v-else
|
||||
:class="`wd-select-picker__cell ${disabled && 'is-disabled'} ${readonly && 'is-readonly'} ${alignRight && 'is-align-right'} ${
|
||||
error && 'is-error'
|
||||
} ${size && 'is-' + size}`"
|
||||
>
|
||||
<view
|
||||
v-if="label || useLabelSlot"
|
||||
:class="`wd-select-picker__label ${isRequired && 'is-required'} ${customLabelClass}`"
|
||||
:style="labelWidth ? 'min-width:' + labelWidth + ';max-width:' + labelWidth + ';' : ''"
|
||||
>
|
||||
<block v-if="label">{{ label }}</block>
|
||||
<slot v-else name="label"></slot>
|
||||
</view>
|
||||
<view class="wd-select-picker__body">
|
||||
<view class="wd-select-picker__value-wraper">
|
||||
<view
|
||||
:class="`wd-select-picker__value ${ellipsis && 'is-ellipsis'} ${customValueClass} ${
|
||||
showValue ? '' : 'wd-select-picker__value--placeholder'
|
||||
}`"
|
||||
>
|
||||
{{ showValue || placeholder || translate('placeholder') }}
|
||||
</view>
|
||||
<wd-icon v-if="showArrow" custom-class="wd-select-picker__arrow" name="arrow-right" />
|
||||
<view v-else-if="showClear" @click.stop="handleClear">
|
||||
<wd-icon custom-class="wd-select-picker__clear" name="error-fill" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="errorMessage" class="wd-select-picker__error-message">{{ errorMessage }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="`wd-select-picker ${customClass}`" :style="customStyle">
|
||||
<wd-action-sheet
|
||||
v-model="pickerShow"
|
||||
:duration="250"
|
||||
@ -127,10 +92,7 @@ import wdButton from '../wd-button/wd-button.vue'
|
||||
import wdLoading from '../wd-loading/wd-loading.vue'
|
||||
|
||||
import { getCurrentInstance, onBeforeMount, ref, watch, nextTick, computed } from 'vue'
|
||||
import { useCell } from '../composables/useCell'
|
||||
import { getRect, isArray, isDef, isFunction, requestAnimationFrame } from '../common/util'
|
||||
import { useParent } from '../composables/useParent'
|
||||
import { FORM_KEY, type FormItemRule } from '../wd-form/types'
|
||||
import { useTranslate } from '../composables/useTranslate'
|
||||
import { selectPickerProps, type SelectPickerExpose } from './types'
|
||||
|
||||
@ -146,34 +108,6 @@ const lastSelectList = ref<Array<number | boolean | string> | number | boolean |
|
||||
const filterVal = ref<string>('')
|
||||
const filterColumns = ref<Array<Record<string, any>>>([])
|
||||
const scrollTop = ref<number>(0) // 滚动位置
|
||||
const cell = useCell()
|
||||
|
||||
const showValue = computed(() => {
|
||||
const value = valueFormat(props.modelValue)
|
||||
let showValueTemp: string = ''
|
||||
|
||||
if (props.displayFormat) {
|
||||
showValueTemp = props.displayFormat(value, props.columns)
|
||||
} else {
|
||||
const { type, labelKey } = props
|
||||
if (type === 'checkbox') {
|
||||
const selectedItems = (isArray(value) ? value : []).map((item) => {
|
||||
return getSelectedItem(item)
|
||||
})
|
||||
showValueTemp = selectedItems
|
||||
.map((item) => {
|
||||
return item[labelKey]
|
||||
})
|
||||
.join(', ')
|
||||
} else if (type === 'radio') {
|
||||
const selectedItem = getSelectedItem(value as string | number | boolean)
|
||||
showValueTemp = selectedItem[labelKey]
|
||||
} else {
|
||||
showValueTemp = value as string
|
||||
}
|
||||
}
|
||||
return showValueTemp
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
@ -229,31 +163,6 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const { parent: form } = useParent(FORM_KEY)
|
||||
|
||||
// 表单校验错误信息
|
||||
const errorMessage = computed(() => {
|
||||
if (form && props.prop && form.errorMessages && form.errorMessages[props.prop]) {
|
||||
return form.errorMessages[props.prop]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
// 是否展示必填
|
||||
const isRequired = computed(() => {
|
||||
let formRequired = false
|
||||
if (form && form.props.rules) {
|
||||
const rules = form.props.rules
|
||||
for (const key in rules) {
|
||||
if (Object.prototype.hasOwnProperty.call(rules, key) && key === props.prop && Array.isArray(rules[key])) {
|
||||
formRequired = rules[key].some((rule: FormItemRule) => rule.required)
|
||||
}
|
||||
}
|
||||
}
|
||||
return props.required || props.rules.some((rule) => rule.required) || formRequired
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
selectList.value = valueFormat(props.modelValue)
|
||||
filterColumns.value = props.columns
|
||||
@ -429,21 +338,6 @@ const showConfirm = computed(() => {
|
||||
return (props.type === 'radio' && props.showConfirm) || props.type === 'checkbox'
|
||||
})
|
||||
|
||||
// 是否展示清除按钮
|
||||
const showClear = computed(() => {
|
||||
return props.clearable && !props.disabled && !props.readonly && showValue.value.length
|
||||
})
|
||||
|
||||
function handleClear() {
|
||||
emit('update:modelValue', props.type === 'checkbox' ? [] : '')
|
||||
emit('clear')
|
||||
}
|
||||
|
||||
// 是否展示箭头
|
||||
const showArrow = computed(() => {
|
||||
return !props.disabled && !props.readonly && !showClear.value
|
||||
})
|
||||
|
||||
defineExpose<SelectPickerExpose>({
|
||||
close,
|
||||
open
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
display: flex;
|
||||
width: $-input-cell-label-width;
|
||||
color: $-cell-title-color;
|
||||
margin-right: $-cell-padding;
|
||||
margin-right: $-cell-vertical-padding;
|
||||
box-sizing: border-box;
|
||||
font-size: $-textarea-fs;
|
||||
flex-shrink: 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user