更新语言及描述

This commit is contained in:
icssoa
2025-08-06 18:14:11 +08:00
parent da573d0d35
commit fd8ff27fb0
16 changed files with 149 additions and 70 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,18 +2,15 @@
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-select-date v-model="form.date1" type="year"></cl-select-date>
<cl-select-date v-model="form.date1" type="date"></cl-select-date>
</demo-item>
<demo-item :label="t('精确到秒')">
<cl-select-date v-model="form.date2" type="second"></cl-select-date>
</demo-item>
<demo-item :label="t('固定开始、结束时间')">
<demo-item :label="t('固定开始、结束日期')">
<cl-select-date
v-model="form.date3"
start="2025-06-01 10:00:00"
end="2026-06-01 10:00:00"
start="2025-06-01"
end="2026-06-01"
type="date"
></cl-select-date>
</demo-item>

View File

@@ -22,6 +22,7 @@
v-model="form.time3"
:disabled="isDisabled"
:label-format="labelFormat"
:type="type"
></cl-select-time>
<cl-list
@@ -30,6 +31,18 @@
className: 'mt-3'
}"
>
<cl-list-item :label="t('时')">
<cl-switch v-model="isHour"></cl-switch>
</cl-list-item>
<cl-list-item :label="t('时:分')">
<cl-switch v-model="isMinute"></cl-switch>
</cl-list-item>
<cl-list-item :label="t('时:分:秒')">
<cl-switch v-model="isSecond"></cl-switch>
</cl-list-item>
<cl-list-item :label="t('标签格式化')">
<cl-switch v-model="isFormat"></cl-switch>
</cl-list-item>
@@ -65,14 +78,9 @@ const form = reactive<Form>({
const isDisabled = ref(false);
const isFormat = ref(false);
const labelFormat = computed(() => {
if (isFormat.value) {
return "{H}时{m}分{s}秒";
} else {
return "{H}:{m}:{s}";
}
});
const isHour = ref(false);
const isMinute = ref(false);
const isSecond = ref(true);
const selectRef2 = ref<ClSelectTimeComponentPublicInstance | null>(null);
@@ -83,4 +91,33 @@ function openSelect2() {
});
});
}
const type = computed(() => {
if (isHour.value) {
return "hour";
}
if (isMinute.value) {
return "minute";
}
return "second";
});
const labelFormat = computed(() => {
if (isFormat.value) {
switch (type.value) {
case "hour":
return "{H}时";
case "minute":
return "{H}时{m}分";
case "second":
return "{H}时{m}分{s}秒";
default:
return null;
}
} else {
return null;
}
});
</script>

View File

@@ -1,16 +1,21 @@
import type { ClFormItemPassThrough } from "./props";
import type { ClFormRule } from "../cl-form/props";
import type { ClFormLabelPosition, PassThroughProps } from "../../types";
export type ClFormItemPassThrough = {
className?: string;
inner?: PassThroughProps;
label?: PassThroughProps;
content?: PassThroughProps;
error?: PassThroughProps;
};
export type ClFormItemProps = {
className?: string;
pt?: ClFormItemPassThrough;
label?: string;
prop?: string;
labelPosition?: ClFormLabelPosition;
labelWidth?: string | any;
showAsterisk?: boolean | any;
showMessage?: boolean | any;
required?: boolean;
labelPosition?: "left" | "top" | "right";
labelWidth?: string;
rules?: ClFormRule | ClFormRule[];
showRequiredAsterisk?: boolean;
error?: string;
disabled?: boolean;
};

View File

@@ -1,12 +1,17 @@
import type { ClFormData, ClFormRule, ClFormValidateResult, ClFormPassThrough } from "./props";
import type { ClFormLabelPosition, ClFormRule, ClFormValidateError } from "../../types";
export type ClFormPassThrough = {
className?: string;
};
export type ClFormProps = {
className?: string;
pt?: ClFormPassThrough;
modelValue?: ClFormData;
rules?: Record<string, ClFormRule | ClFormRule[]>;
labelPosition?: "left" | "top" | "right";
modelValue?: any;
rules?: Map<string, ClFormRule[]>;
labelPosition?: ClFormLabelPosition;
labelWidth?: string;
showRequiredAsterisk?: boolean;
showAsterisk?: boolean;
showMessage?: boolean;
disabled?: boolean;
};

View File

@@ -37,15 +37,14 @@
v-for="(item, index) in column"
:key="index"
>
<text
class="cl-picker-view__item-text"
:class="[
{
'is-active': index == value[columnIndex],
'is-dark': isDark
}
]"
>{{ item.label }}</text
<cl-text
:pt="{
className: parseClass([
[isDark, '!text-surface-500'],
[isDark && index == value[columnIndex], '!text-white']
])
}"
>{{ item.value }}</cl-text
>
</view>
</picker-view-column>
@@ -55,7 +54,7 @@
</template>
<script setup lang="ts">
import { forInObject, isDark, rpx2px } from "@/cool";
import { forInObject, isDark, parseClass, rpx2px } from "@/cool";
import type { ClSelectOption } from "../../types";
import { parseRpx } from "@/cool";
import { computed } from "vue";
@@ -197,18 +196,6 @@ function onChange(e: UniPickerViewChangeEvent) {
&__item {
@apply flex flex-row items-center justify-center;
&-text {
@apply text-md text-center text-surface-700;
&.is-dark {
@apply text-surface-500;
&.is-active {
@apply text-white;
}
}
}
}
.uni-picker-view-indicator {

View File

@@ -251,7 +251,7 @@ const props = defineProps({
// 范围分隔符
rangeSeparator: {
type: String,
default: () => t("")
default: () => t("")
},
// 是否显示快捷选项
showShortcuts: {
@@ -404,7 +404,9 @@ const list = computed(() => {
// 判断是否为闰年
const isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
// 根据月份和是否闰年获取当月天数
const days = [31, isLeapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1];
const days = [31, isLeapYear ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][
month > 0 ? month - 1 : 0
];
// 计算年份范围确保至少有60年可选
const yearRange = Math.max(60, endYear - startYear + 1);
// 遍历生成年月日时分秒的选项
@@ -562,10 +564,19 @@ function getText() {
// 选择器值改变事件更新value
async function onChange(arr: number[]) {
const data = [] as number[];
for (let i = 0; i < arr.length; i++) {
value.value[i] = list.value[i][arr[i]].value as number;
const item = list.value[i][arr[i]];
if (item != null) {
data[i] = item.value as number;
}
}
// 更新value
value.value = data;
// 设置范围值
if (props.rangeable) {
values.value[rangeIndex.value] = dayUts(toDate()).format(valueFormat.value);
@@ -582,6 +593,8 @@ async function onChange(arr: number[]) {
// 设置value
function setValue(val: string) {
text.value = "";
// 如果值为空,使用当前时间
if (isNull(val) || isEmpty(val)) {
value.value = dayUts().toArray();

View File

@@ -93,6 +93,11 @@ const props = defineProps({
type: Array as PropType<string[]>,
default: () => [t("小时"), t("分钟"), t("秒数")]
},
// 类型,控制选择的粒度
type: {
type: String as PropType<"hour" | "minute" | "second">,
default: "second"
},
// 选择器标题
title: {
type: String,
@@ -135,8 +140,8 @@ const props = defineProps({
},
// 时间标签格式化
labelFormat: {
type: String as PropType<string>,
default: "{H}:{m}:{s}"
type: String as PropType<string | null>,
default: null
}
});
@@ -155,6 +160,23 @@ type PassThrough = {
// 解析透传样式配置
const pt = computed(() => parsePt<PassThrough>(props.pt));
// 标签格式化
const labelFormat = computed(() => {
if (props.labelFormat != null) {
return props.labelFormat;
}
if (props.type == "hour") {
return "{H}";
}
if (props.type == "minute") {
return "{H}:{m}";
}
return "{H}:{m}:{s}";
});
// 当前选中的值
const value = ref<string[]>([]);
@@ -162,7 +184,7 @@ const value = ref<string[]>([]);
const indexes = ref<number[]>([]);
// 时间选择器列表
const columns = computed(() => {
const list = computed(() => {
const arr = [[], [], []] as ClSelectOption[][];
for (let i = 0; i < 60; i++) {
@@ -184,6 +206,16 @@ const columns = computed(() => {
return arr;
});
// 列数,决定显示多少列(时、分、秒)
const columnNum = computed(() => {
return ["hour", "minute", "second"].findIndex((e) => e == props.type) + 1;
});
// 列数据,取出需要显示的列
const columns = computed(() => {
return list.value.slice(0, columnNum.value);
});
// 显示文本
const text = computed(() => {
// 获取当前v-model绑定的时间字符串
@@ -198,7 +230,7 @@ const text = computed(() => {
const [h, m, s] = val.split(":");
// 按照labelFormat格式化显示文本
return props.labelFormat.replace("{H}", h).replace("{m}", m).replace("{s}", s);
return labelFormat.value.replace("{H}", h).replace("{m}", m).replace("{s}", s);
});
// 选择器值改变事件
@@ -218,7 +250,7 @@ function onChange(a: number[]) {
// 更新组件内部维护的索引数组
indexes.value = b;
// 根据最新的索引数组,更新选中的值数组
value.value = b.map((e, i) => columns.value[i][e].value as string);
value.value = b.map((e, i) => list.value[i][e].value as string);
}
// 选择器显示状态
@@ -293,10 +325,10 @@ watch(
_indexes.push(0);
// 添加默认值
_value.push(columns.value[i][0].value as string);
_value.push(list.value[i][0].value as string);
} else {
// 查找当前值对应的索引
let index = columns.value[i].findIndex((e) => e.value == _value[i]);
let index = list.value[i].findIndex((e) => e.value == _value[i]);
// 索引无效时重置为0
if (index < 0) {

View File

@@ -12,6 +12,7 @@ export type ClSelectTimeProps = {
pt?: ClSelectTimePassThrough;
modelValue?: string;
headers?: string[];
type?: "hour" | "minute" | "second";
title?: string;
placeholder?: string;
showTrigger?: boolean;
@@ -20,5 +21,5 @@ export type ClSelectTimeProps = {
showConfirm?: boolean;
cancelText?: string;
showCancel?: boolean;
labelFormat?: string;
labelFormat?: string | any;
};

View File

@@ -20,4 +20,5 @@ export type ClTextProps = {
selectable?: boolean;
space?: "ensp" | "emsp" | "nbsp";
decode?: boolean;
preWrap?: boolean;
};

View File

@@ -109,7 +109,7 @@ const props = defineProps({
// 占位符
placeholder: {
type: String,
default: t("请输入")
default: () => t("请输入")
},
// 占位符样式类
placeholderClass: {

View File

@@ -22,4 +22,5 @@ export type ClUploadProps = {
multiple?: boolean;
limit?: number;
disabled?: boolean;
test?: boolean;
};

View File

@@ -6,6 +6,6 @@ type Config = {
export const config: Config = {
zIndex: 600,
startDate: "1950-01-01 00:00:00",
startDate: "2000-01-01 00:00:00",
endDate: "2050-12-31 23:59:59"
};

View File

@@ -1,4 +1,4 @@
import type { ClActionSheetItem, ClActionSheetOptions, PassThroughProps, Type, ClButtonType, Size, ClListViewItem, ClInputType, ClListItem, Justify, ClConfirmAction, ClConfirmOptions, ClToastOptions, ClSelectOption, ClPopupDirection, ClQrcodeMode, ClSelectDateShortcut, ClTabsItem, ClTextType, ClUploadItem } from "./types";
import type { ClActionSheetItem, ClActionSheetOptions, PassThroughProps, Type, ClButtonType, Size, ClListViewItem, ClFormLabelPosition, ClFormRule, ClFormValidateError, ClInputType, ClListItem, Justify, ClConfirmAction, ClConfirmOptions, ClToastOptions, ClSelectOption, ClPopupDirection, ClQrcodeMode, ClSelectDateShortcut, ClTabsItem, ClTextType, ClUploadItem } from "./types";
import { type UiInstance } from "./hooks";
import { type QrcodeOptions } from "./draw";
@@ -16,8 +16,8 @@ import type { ClCropperProps, ClCropperPassThrough } from "./components/cl-cropp
import type { ClDraggableProps, ClDraggablePassThrough } from "./components/cl-draggable/props";
import type { ClFloatViewProps } from "./components/cl-float-view/props";
import type { ClFooterProps, ClFooterPassThrough } from "./components/cl-footer/props";
import type { ClFormProps } from "./components/cl-form/props";
import type { ClFormItemProps } from "./components/cl-form-item/props";
import type { ClFormProps, ClFormPassThrough } from "./components/cl-form/props";
import type { ClFormItemProps, ClFormItemPassThrough } from "./components/cl-form-item/props";
import type { ClIconProps, ClIconPassThrough } from "./components/cl-icon/props";
import type { ClImageProps, ClImagePassThrough } from "./components/cl-image/props";
import type { ClIndexBarProps, ClIndexBarPassThrough } from "./components/cl-index-bar/props";