diff --git a/cool/utils/parse.ts b/cool/utils/parse.ts index f3c4dec..6b28af3 100644 --- a/cool/utils/parse.ts +++ b/cool/utils/parse.ts @@ -119,23 +119,6 @@ export function parseToObject(data: T): UTSJSONObject { // #endif } -/** - * 将数值或字符串转换为rpx单位的字符串 - * @param val 要转换的值,可以是数字或字符串 - * @returns 转换后的rpx单位字符串 - * @example - * parseRpx(10) // 返回 '10rpx' - * parseRpx('10rpx') // 返回 '10rpx' - * parseRpx('10px') // 返回 '10px' - */ -export const parseRpx = (val: number | string): string => { - if (typeof val == "number") { - return val + "rpx"; - } - - return val; -}; - /** * 将rpx单位转换为px单位 * @param rpx 要转换的rpx值 @@ -167,16 +150,95 @@ export const px2rpx = (px: number): number => { }; /** - * 解析px单位,支持rpx单位转换 - * @param val 要解析的值,可以是数字或字符串 - * @returns 解析后的px单位 + * 将数值或字符串转换为rpx单位的字符串 + * @param val 要转换的值,可以是数字或字符串 + * @returns 转换后的rpx单位字符串 + * @example + * parseRpx(10) // 返回 '10rpx' + * parseRpx('10rpx') // 返回 '10rpx' + * parseRpx('10px') // 返回 '10px' */ -export const getPx = (val: string) => { - const num = parseInt(val); +export const parseRpx = (val: number | string): string => { + if (typeof val == "number") { + return val + "rpx"; + } - if (val.includes("rpx")) { + return val; +}; + +/** + * 示例: 获取数值部分 + * @example + * getNum("10rpx") // 返回 10 + * getNum("10px") // 返回 10 + * getNum("10") // 返回 10 + * getNum("-5.5px") // 返回 -5.5 + * @param val - 输入值,例如 "10rpx"、"10px"、"10" + * @returns number - 返回提取的数值 + */ +export const getNum = (val: string): number => { + // 使用正则提取数字部分,支持小数和负数 + const match = val.match(/-?\d+(\.\d+)?/); + return match != null ? parseFloat(match[0] ?? "0") : 0; +}; + +/** + * 示例: 获取单位 + * @example + * getUnit("10rpx") // 返回 "rpx" + * getUnit("10px") // 返回 "px" + * @param val - 输入值,例如 "10rpx"、"10px" + * @returns string - 返回单位字符串,如 "rpx" 或 "px" + */ +export const getUnit = (val: string): string => { + const num = getNum(val); + return val.replace(`${num}`, ""); +}; + +/** + * 示例: 转换为 rpx 值 + * @example + * getRpx("10rpx") // 返回 10 + * getRpx("10px") // 返回 px2rpx(10) + * getRpx(10) // 返回 10 + * @param val - 输入值,可以是 "10rpx"、"10px" 或数字 10 + * @returns number - 返回对应的 rpx 数值 + */ +export const getRpx = (val: number | string): number => { + if (typeof val == "number") { + return val; + } + + const num = getNum(val); + const unit = getUnit(val); + + if (unit == "px") { + return px2rpx(num); + } + + return num; +}; + +/** + * 示例: 转换为 px 值 + * @example + * getPx("10rpx") // 返回 rpx2px(10) + * getPx("10px") // 返回 10 + * getPx(10) // 返回 rpx2px(10) + * @param val - 输入值,可以是 "10rpx"、"10px" 或数字 10 + * @returns number - 返回对应的 px 数值 + */ +export const getPx = (val: string | number) => { + if (typeof val == "number") { + return rpx2px(val); + } + + const num = getNum(val); + const unit = getUnit(val); + + if (unit == "rpx") { return rpx2px(num); } - return Math.floor(num); + return num; }; diff --git a/package.json b/package.json index e5fa98b..38e9e76 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cool-unix", - "version": "8.0.23", + "version": "8.0.24", "license": "MIT", "scripts": { "build-ui": "node ./uni_modules/cool-ui/scripts/generate-types.js", diff --git a/pages.json b/pages.json index d4e7f1b..171856c 100644 --- a/pages.json +++ b/pages.json @@ -292,6 +292,12 @@ "navigationBarTitleText": "Banner 轮播图" } }, + { + "path": "data/marquee", + "style": { + "navigationBarTitleText": "Marquee 跑马灯" + } + }, { "path": "data/pagination", "style": { diff --git a/pages/demo/data/marquee.uvue b/pages/demo/data/marquee.uvue new file mode 100644 index 0000000..14f645f --- /dev/null +++ b/pages/demo/data/marquee.uvue @@ -0,0 +1,70 @@ + + + diff --git a/pages/index/home.uvue b/pages/index/home.uvue index 68c5e43..3d923f7 100644 --- a/pages/index/home.uvue +++ b/pages/index/home.uvue @@ -301,6 +301,11 @@ const data = computed(() => { icon: "carousel-view", path: "/pages/demo/data/banner" }, + { + label: t("跑马灯"), + icon: "film-line", + path: "/pages/demo/data/marquee" + }, { label: t("分页"), icon: "page-separator", diff --git a/uni_modules/cool-ui/components/cl-marquee/cl-marquee.uvue b/uni_modules/cool-ui/components/cl-marquee/cl-marquee.uvue new file mode 100644 index 0000000..4058bae --- /dev/null +++ b/uni_modules/cool-ui/components/cl-marquee/cl-marquee.uvue @@ -0,0 +1,283 @@ + + + + + diff --git a/uni_modules/cool-ui/components/cl-marquee/props.ts b/uni_modules/cool-ui/components/cl-marquee/props.ts new file mode 100644 index 0000000..cd90859 --- /dev/null +++ b/uni_modules/cool-ui/components/cl-marquee/props.ts @@ -0,0 +1,19 @@ +import type { PassThroughProps } from "../../types"; + +export type ClMarqueePassThrough = { + className?: string; + list?: PassThroughProps; + item?: PassThroughProps; + image?: PassThroughProps; +}; + +export type ClMarqueeProps = { + className?: string; + pt?: ClMarqueePassThrough; + list?: string[]; + direction?: "horizontal" | "vertical"; + duration?: number; + itemHeight?: any; + itemWidth?: any; + gap?: any; +}; diff --git a/uni_modules/cool-ui/index.d.ts b/uni_modules/cool-ui/index.d.ts index 09424b0..9024049 100644 --- a/uni_modules/cool-ui/index.d.ts +++ b/uni_modules/cool-ui/index.d.ts @@ -38,6 +38,7 @@ import type { ClListItemProps, ClListItemPassThrough } from "./components/cl-lis import type { ClListViewProps, ClListViewPassThrough } from "./components/cl-list-view/props"; import type { ClLoadingProps, ClLoadingPassThrough } from "./components/cl-loading/props"; import type { ClLoadmoreProps, ClLoadmorePassThrough } from "./components/cl-loadmore/props"; +import type { ClMarqueeProps, ClMarqueePassThrough } from "./components/cl-marquee/props"; import type { ClNoticebarProps, ClNoticebarPassThrough } from "./components/cl-noticebar/props"; import type { ClPageProps } from "./components/cl-page/props"; import type { ClPageThemeProps } from "./components/cl-page-theme/props"; @@ -116,6 +117,7 @@ declare module "vue" { "cl-list-view": (typeof import('./components/cl-list-view/cl-list-view.uvue')['default']) & import('vue').DefineComponent; "cl-loading": (typeof import('./components/cl-loading/cl-loading.uvue')['default']) & import('vue').DefineComponent; "cl-loadmore": (typeof import('./components/cl-loadmore/cl-loadmore.uvue')['default']) & import('vue').DefineComponent; + "cl-marquee": (typeof import('./components/cl-marquee/cl-marquee.uvue')['default']) & import('vue').DefineComponent; "cl-noticebar": (typeof import('./components/cl-noticebar/cl-noticebar.uvue')['default']) & import('vue').DefineComponent; "cl-page": (typeof import('./components/cl-page/cl-page.uvue')['default']) & import('vue').DefineComponent; "cl-page-theme": (typeof import('./components/cl-page-theme/cl-page-theme.uvue')['default']) & import('vue').DefineComponent; diff --git a/uni_modules/cool-ui/types/component.d.ts b/uni_modules/cool-ui/types/component.d.ts index a8dc933..9275259 100644 --- a/uni_modules/cool-ui/types/component.d.ts +++ b/uni_modules/cool-ui/types/component.d.ts @@ -230,3 +230,11 @@ declare type ClCalendarComponentPublicInstance = { open(cb: ((value: string | string[]) => void) | null = null): void; close(): void; }; + +declare type ClMarqueeComponentPublicInstance = { + play(): void; + pause(): void; + start(): void; + stop(): void; + reset(): void; +}; diff --git a/uni_modules/cool-ui/types/index.ts b/uni_modules/cool-ui/types/index.ts index 92d624f..3734a97 100644 --- a/uni_modules/cool-ui/types/index.ts +++ b/uni_modules/cool-ui/types/index.ts @@ -210,3 +210,30 @@ export type ClCalendarDateConfig = { disabled?: boolean; color?: string; }; + +export type ClMarqueeDirection = "horizontal" | "vertical"; + +export type ClMarqueeItem = { + url: string; + originalIndex: number; +}; + +export type ClMarqueePassThrough = { + className?: string; + container?: PassThroughProps; + item?: PassThroughProps; + image?: PassThroughProps; +}; + +export type ClMarqueeProps = { + className?: string; + pt?: ClMarqueePassThrough; + list?: string[]; + direction?: ClMarqueeDirection; + speed?: number; + pause?: boolean; + pauseOnHover?: boolean; + itemHeight?: number; + itemWidth?: number; + gap?: number; +};