refactor: ♻️ 重构Picker和Cell

This commit is contained in:
不如摸鱼去 2024-11-18 13:09:43 +08:00 committed by Moonofweisheng
parent fb7580df7e
commit 24243ca55c
30 changed files with 472 additions and 2036 deletions

View File

@ -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 }
}

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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));
}

View File

@ -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; // 表格字体大小

View File

@ -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>

View File

@ -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')

View File

@ -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;

View File

@ -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
*/

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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 pickerresolve 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弹框

View File

@ -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-viewselectItem
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

View File

@ -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;

View File

@ -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
*/

View File

@ -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>[]) : '')
}
}

View File

@ -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>

View File

@ -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;

View File

@ -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);
}

View File

@ -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 pickerresolve 1boolean参数
*/
@ -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>

View File

@ -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,

View File

@ -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;
}
}
}

View File

@ -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%

View File

@ -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')
}

View File

@ -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;

View File

@ -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

View File

@ -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;