小程序初始提交

This commit is contained in:
jdc
2025-11-13 10:36:23 +08:00
parent f26b4f9a2f
commit 5db3b180eb
447 changed files with 83351 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-avatar src="https://unix.cool-js.com/images/demo/avatar.jpg"></cl-avatar>
</demo-item>
<demo-item :label="t('无图片')">
<cl-avatar></cl-avatar>
</demo-item>
<demo-item :label="t('圆角')">
<cl-avatar
rounded
src="https://unix.cool-js.com/images/demo/avatar.jpg"
></cl-avatar>
</demo-item>
<demo-item :label="t('自定义大小')">
<cl-avatar
:size="120"
src="https://unix.cool-js.com/images/demo/avatar.jpg"
></cl-avatar>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
</script>

View File

@@ -0,0 +1,59 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-banner :list="list"></cl-banner>
</demo-item>
<demo-item :label="t('禁用手势')">
<cl-banner :list="list" :disable-touch="true"></cl-banner>
</demo-item>
<demo-item :label="t('自定义样式')">
<cl-banner
:list="list"
:pt="{
className: 'mx-[-12rpx] !rounded-none',
item: {
className: parseClass(['scale-y-80 !px-[12rpx]'])
},
itemActive: {
className: parseClass(['!scale-y-100'])
},
image: {
className: '!rounded-none'
}
}"
:previous-margin="40"
:next-margin="40"
></cl-banner>
</demo-item>
<demo-item :label="t('自定义样式2')">
<cl-banner
:list="list"
:pt="{
className: 'mx-[-12rpx]',
item: {
className: parseClass(['px-[12rpx]'])
}
}"
:next-margin="40"
></cl-banner>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
import { ref } from "vue";
import { parseClass } from "@/cool";
const list = ref<string[]>([
"https://unix.cool-js.com/images/demo/bg1.png",
"https://unix.cool-js.com/images/demo/bg2.png",
"https://unix.cool-js.com/images/demo/bg3.png"
]);
</script>

View File

@@ -0,0 +1,217 @@
<template>
<cl-page>
<view class="p-3">
<demo-item>
<cl-text color="info">
{{ t("长按项即可拖动排序") }}
</cl-text>
</demo-item>
<demo-item :label="t('单列排序')">
<cl-draggable v-model="list">
<template #item="{ item, index }">
<view
class="flex flex-row items-center p-3 bg-surface-100 rounded-lg mb-2 dark:!bg-surface-700"
:class="{
'opacity-50': item['disabled']
}"
>
<cl-text>{{ (item as UTSJSONObject).label }}</cl-text>
</view>
</template>
</cl-draggable>
</demo-item>
<demo-item :label="t('不需要长按')">
<cl-draggable v-model="list5" :long-press="false">
<template #item="{ item }">
<view
class="flex flex-row items-center p-3 bg-surface-100 rounded-lg mb-2 dark:!bg-surface-700"
>
<cl-text>{{ (item as UTSJSONObject).label }}</cl-text>
</view>
</template>
</cl-draggable>
</demo-item>
<demo-item :label="t('结合列表使用')">
<cl-list border>
<cl-draggable v-model="list2">
<template #item="{ item, index, dragging, dragIndex }">
<cl-list-item
icon="chat-thread-line"
:label="(item as UTSJSONObject).label"
arrow
:pt="{
inner: {
className: parseClass([
[
dragging && dragIndex == index,
isDark ? '!bg-surface-700' : '!bg-surface-100'
]
])
}
}"
></cl-list-item>
</template>
</cl-draggable>
</cl-list>
</demo-item>
<demo-item :label="t('多列排序')">
<cl-draggable v-model="list3" :columns="4">
<template #item="{ item, index }">
<view
class="flex flex-row items-center justify-center p-3 bg-surface-100 rounded-lg m-1 dark:!bg-surface-700"
:class="{
'opacity-50': item['disabled']
}"
>
<cl-text>{{ (item as UTSJSONObject).label }}</cl-text>
</view>
</template>
</cl-draggable>
</demo-item>
<demo-item :label="t('结合图片使用')">
<cl-draggable v-model="list4" :columns="4">
<template #item="{ item, index }">
<view class="p-[2px]">
<cl-image
:src="(item as UTSJSONObject).url"
mode="widthFix"
:pt="{
className: '!w-full'
}"
preview
></cl-image>
</view>
</template>
</cl-draggable>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
import { ref } from "vue";
import { isDark, parseClass } from "@/cool";
// list李白《将进酒》
const list = ref<UTSJSONObject[]>([
{
label: "君不见黄河之水天上来"
},
{
label: "奔流到海不复回",
disabled: true
},
{
label: "君不见高堂明镜悲白发"
},
{
label: "朝如青丝暮成雪"
},
{
label: "人生得意须尽欢"
}
]);
// list5杜甫《春望》
const list5 = ref<UTSJSONObject[]>([
{
label: "国破山河在"
},
{
label: "城春草木深"
},
{
label: "感时花溅泪"
}
]);
// list2王之涣《登鹳雀楼》
const list2 = ref<UTSJSONObject[]>([
{
label: "白日依山尽"
},
{
label: "黄河入海流"
},
{
label: "欲穷千里目"
},
{
label: "更上一层楼"
},
{
label: "一览众山小"
}
]);
const list3 = ref<UTSJSONObject[]>([
{
label: "项目1"
},
{
label: "项目2"
},
{
label: "项目3"
},
{
label: "项目4"
},
{
label: "项目5"
},
{
label: "项目6"
},
{
label: "项目7"
},
{
label: "项目8",
disabled: true
},
{
label: "项目9"
},
{
label: "项目10"
},
{
label: "项目11"
},
{
label: "项目12"
}
]);
const list4 = ref<UTSJSONObject[]>([
{
url: "https://unix.cool-js.com/images/demo/1.jpg"
},
{
url: "https://unix.cool-js.com/images/demo/2.jpg"
},
{
url: "https://unix.cool-js.com/images/demo/3.jpg"
},
{
url: "https://unix.cool-js.com/images/demo/4.jpg"
},
{
url: "https://unix.cool-js.com/images/demo/5.jpg"
},
{
url: "https://unix.cool-js.com/images/demo/6.jpg"
},
{
url: "https://unix.cool-js.com/images/demo/7.jpg"
}
]);
</script>

View File

@@ -0,0 +1,467 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-filter-bar>
<!-- 下拉框 -->
<cl-filter-item
label="综合排序"
type="select"
:value="1"
:options="coreOptions"
:pt="{
className: 'w-[220rpx] !flex-none'
}"
@change="onOptionsChange"
></cl-filter-item>
<!-- 排序 -->
<cl-filter-item
label="销量"
type="sort"
value="desc"
@change="onSortChange"
></cl-filter-item>
<!-- 开关 -->
<cl-filter-item
label="国补"
type="switch"
:value="false"
@change="onSwitchChange"
></cl-filter-item>
<!-- 自定义 -->
<view
class="flex flex-row items-center justify-center flex-1"
@tap="openFilter"
>
<cl-text>筛选</cl-text>
<cl-icon name="filter-line"></cl-icon>
</view>
</cl-filter-bar>
</demo-item>
<demo-item>
<cl-text pre-wrap :pt="{ className: 'text-sm p-2' }">{{
JSON.stringify(filterForm, null, 4)
}}</cl-text>
</demo-item>
<demo-item>
<cl-text pre-wrap :pt="{ className: 'text-sm p-2' }">{{
JSON.stringify(searchForm, null, 4)
}}</cl-text>
</demo-item>
</view>
<!-- 自定义筛选 -->
<cl-popup
v-model="filterVisible"
:title="t('筛选')"
direction="right"
size="80%"
:show-header="false"
>
<view class="flex flex-col h-full">
<scroll-view class="flex-1">
<cl-form :pt="{ className: 'p-3' }">
<cl-form-item label="服务/折扣">
<cl-row :gutter="20">
<cl-col :span="8" v-for="(item, index) in disOptions" :key="index">
<cl-checkbox
v-model="searchForm.dis"
:label="item.label"
:value="item.value"
:show-icon="false"
:pt="{
className: parseClass([
'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
[isDark, 'bg-surface-800', 'bg-surface-100'],
[
searchForm.dis.includes(item.value),
`${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
]
]),
label: {
className: 'text-sm'
}
}"
></cl-checkbox>
</cl-col>
</cl-row>
</cl-form-item>
<cl-form-item label="价格区间">
<view class="flex flex-row items-center">
<cl-input
v-model="searchForm.minPrice"
type="digit"
placeholder="最低价"
:pt="{
className: 'flex-1',
inner: {
className: 'text-center'
}
}"
></cl-input>
<cl-text
:pt="{
className: 'px-2'
}"
>~</cl-text
>
<cl-input
v-model="searchForm.maxPrice"
type="digit"
placeholder="最高价"
:pt="{
className: 'flex-1',
inner: {
className: 'text-center'
}
}"
></cl-input>
</view>
</cl-form-item>
<cl-form-item label="品牌">
<cl-row :gutter="20">
<cl-col
:span="8"
v-for="(item, index) in brandOptions"
:key="index"
>
<cl-checkbox
v-model="searchForm.brand"
:label="item.label"
:value="item.value"
:show-icon="false"
:pt="{
className: parseClass([
'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
[isDark, 'bg-surface-800', 'bg-surface-100'],
[
searchForm.brand.includes(item.value),
`${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
]
]),
label: {
className: 'text-sm'
}
}"
></cl-checkbox>
</cl-col>
</cl-row>
</cl-form-item>
<cl-form-item label="内存">
<cl-row :gutter="20">
<cl-col
:span="8"
v-for="(item, index) in memoryOptions"
:key="index"
>
<cl-radio
v-model="searchForm.memory"
:label="item.label"
:value="item.value"
:show-icon="false"
:pt="{
className: parseClass([
'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
[isDark, 'bg-surface-800', 'bg-surface-100'],
[
searchForm.memory == item.value,
`${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
]
]),
label: {
className: 'text-sm'
}
}"
></cl-radio>
</cl-col>
</cl-row>
</cl-form-item>
<cl-form-item label="颜色">
<cl-row :gutter="20">
<cl-col
:span="8"
v-for="(item, index) in colorOptions"
:key="index"
>
<cl-radio
v-model="searchForm.color"
:label="item.label"
:value="item.value"
:show-icon="false"
:pt="{
className: parseClass([
'mb-3 p-2 rounded-lg justify-center border border-solid border-transparent',
[isDark, 'bg-surface-800', 'bg-surface-100'],
[
searchForm.color == item.value,
`${isDark ? '!bg-surface-700' : '!bg-white'} !border-primary-500`
]
]),
label: {
className: 'text-sm'
}
}"
></cl-radio>
</cl-col>
</cl-row>
</cl-form-item>
</cl-form>
</scroll-view>
<view class="flex flex-row p-3">
<cl-button
type="info"
text
border
:pt="{
className: 'flex-1'
}"
@tap="closeFilter"
>{{ t("取消") }}</cl-button
>
<cl-button
:pt="{
className: 'flex-1'
}"
@tap="submit"
>{{ t("确定") }}</cl-button
>
</view>
<cl-safe-area type="bottom"></cl-safe-area>
</view>
</cl-popup>
</cl-page>
</template>
<script lang="ts" setup>
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
import { reactive, ref } from "vue";
import { useUi, type ClSelectOption } from "@/uni_modules/cool-ui";
import { isDark, parseClass } from "@/cool";
const ui = useUi();
const filterVisible = ref(false);
function openFilter() {
filterVisible.value = true;
}
function closeFilter() {
filterVisible.value = false;
}
function submit() {
closeFilter();
ui.showLoading();
setTimeout(() => {
ui.hideLoading();
}, 1000);
}
const coreOptions = ref<ClSelectOption[]>([
{
label: "综合排序",
value: 1
},
{
label: "价格从高到底",
value: 2
},
{
label: "价格从低到高",
value: 3
}
]);
type Option = {
label: string;
value: string;
};
const disOptions = ref<Option[]>([
{
label: "百亿补贴",
value: "billion_subsidy"
},
{
label: "以旧换新",
value: "trade_in"
},
{
label: "分期免息",
value: "installment"
},
{
label: "包邮",
value: "free_shipping"
},
{
label: "促销",
value: "promotion"
},
{
label: "价保",
value: "price_protection"
},
{
label: "仅看有货",
value: "in_stock"
},
{
label: "货到付款",
value: "cod"
}
]);
const brandOptions = ref<Option[]>([
{
label: "华为",
value: "huawei"
},
{
label: "苹果",
value: "apple"
},
{
label: "小米",
value: "xiaomi"
},
{
label: "三星",
value: "samsung"
},
{
label: "OPPO",
value: "oppo"
},
{
label: "vivo",
value: "vivo"
},
{
label: "荣耀",
value: "honor"
}
]);
const colorOptions = ref<Option[]>([
{
label: "红色",
value: "red"
},
{
label: "蓝色",
value: "blue"
},
{
label: "黑色",
value: "black"
},
{
label: "白色",
value: "white"
},
{
label: "金色",
value: "gold"
},
{
label: "银色",
value: "silver"
},
{
label: "绿色",
value: "green"
},
{
label: "紫色",
value: "purple"
},
{
label: "灰色",
value: "gray"
},
{
label: "粉色",
value: "pink"
}
]);
const memoryOptions = ref<Option[]>([
{
label: "128GB",
value: "128"
},
{
label: "256GB",
value: "256"
},
{
label: "512GB",
value: "512"
},
{
label: "1TB",
value: "1024"
}
]);
type SearchForm = {
dis: string[];
minPrice: string;
maxPrice: string;
brand: string[];
memory: string;
color: string;
};
const searchForm = ref<SearchForm>({
dis: [],
minPrice: "50",
maxPrice: "300",
brand: [],
memory: "",
color: ""
});
type FilterForm = {
core: number;
sort: string;
switch: boolean;
};
const filterForm = reactive<FilterForm>({
core: 0,
sort: "none",
switch: false
});
function onOptionsChange(val: number) {
console.log(val);
filterForm.core = val;
}
function onSortChange(val: string) {
console.log(val);
filterForm.sort = val;
}
function onSwitchChange(val: boolean) {
console.log(val);
filterForm.switch = val;
}
</script>

View File

@@ -0,0 +1,118 @@
<template>
<cl-page>
<cl-list-view
ref="listViewRef"
:data="listView"
:virtual="false"
:pt="{
refresher: {
className: 'pt-3'
}
}"
:refresher-enabled="true"
@pull="onPull"
@bottom="loadMore"
>
<template #item="{ value }">
<goods-item :value="value"></goods-item>
</template>
<template #bottom>
<view class="py-3">
<cl-loadmore
v-if="list.length > 0"
:loading="loading"
safe-area-bottom
></cl-loadmore>
</view>
</template>
</cl-list-view>
</cl-page>
</template>
<script lang="ts" setup>
import { useUi } from "@/uni_modules/cool-ui";
import { ref } from "vue";
import { usePager } from "@/cool";
import GoodsItem from "../components/goods-item.uvue";
import { t } from "@/locale";
const ui = useUi();
const listViewRef = ref<ClListViewComponentPublicInstance | null>(null);
let id = 0;
const { refresh, list, listView, loading, loadMore } = usePager((params, { render }) => {
// 模拟请求
setTimeout(() => {
render({
list: [
{
id: id++,
title: "春日樱花盛开时节,粉色花瓣如诗如画般飘洒",
image: "https://unix.cool-js.com/images/demo/1.jpg"
},
{
id: id++,
title: "夕阳西下的海滩边,金色阳光温柔地洒在波光粼粼的海面上,构成令人心旷神怡的日落美景",
image: "https://unix.cool-js.com/images/demo/2.jpg"
},
{
id: id++,
title: "寒冬腊月时分,洁白雪花纷纷扬扬地覆盖着整个世界,感受冬日的宁静与美好",
image: "https://unix.cool-js.com/images/demo/3.jpg"
},
{
id: id++,
title: "都市夜景霓虹闪烁,五彩斑斓光芒照亮城市营造梦幻般景象",
image: "https://unix.cool-js.com/images/demo/5.jpg"
},
{
id: id++,
title: "云雾缭绕的山间风光如诗如画让人心旷神怡,微风轻抚树梢带来阵阵清香,鸟儿在林间自由歌唱",
image: "https://unix.cool-js.com/images/demo/6.jpg"
},
{
id: id++,
title: "古老建筑与现代摩天大楼交相辉映,传统与现代完美融合创造独特城市景观",
image: "https://unix.cool-js.com/images/demo/7.jpg"
},
{
id: id++,
title: "广袤田野绿意盎然风光无限,金黄麦浪在微风中轻柔摇曳,农家炊烟袅袅升起",
image: "https://unix.cool-js.com/images/demo/8.jpg"
},
{
id: id++,
title: "璀璨星空下银河横跨天际,繁星闪烁神秘光芒营造浪漫夜空美景",
image: "https://unix.cool-js.com/images/demo/9.jpg"
},
{
id: id++,
title: "雄伟瀑布从高耸悬崖飞流直下激起千层浪花,彩虹在水雾中若隐若现如梦如幻",
image: "https://unix.cool-js.com/images/demo/10.jpg"
}
],
pagination: {
page: params["page"],
size: params["size"],
total: 100
}
});
ui.hideLoading();
}, 1000);
});
async function onPull() {
await refresh({ page: 1 });
listViewRef.value!.stopRefresh();
}
onReady(() => {
ui.showLoading(t("加载中"));
// 默认请求
refresh({});
});
</script>

View File

@@ -0,0 +1,68 @@
<template>
<cl-page>
<view class="page">
<view class="p-3 pb-0">
<demo-item>
<cl-text
>采用虚拟列表技术实现高性能渲染,支持海量数据无限滚动,当前演示数据规模:{{
data.length
}}条</cl-text
>
</demo-item>
</view>
<view class="list">
<cl-list-view
:data="data"
:pt="{
indexBar: {
className: '!fixed'
},
itemHover: {
className: 'bg-gray-200'
}
}"
>
</cl-list-view>
</view>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { request } from "@/cool";
import DemoItem from "../components/item.uvue";
import { useListView, useUi, type ClListViewItem } from "@/uni_modules/cool-ui";
import { ref } from "vue";
const ui = useUi();
const data = ref<ClListViewItem[]>([]);
onReady(() => {
ui.showLoading();
request({
url: "https://unix.cool-js.com/data/pca_flat.json"
})
.then((res) => {
data.value = useListView(res as UTSJSONObject[]);
})
.catch((err) => {
console.error(err);
})
.finally(() => {
ui.hideLoading();
});
});
</script>
<style lang="scss" scoped>
.page {
height: 100%;
.list {
flex: 1;
}
}
</style>

View File

@@ -0,0 +1,120 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-list-item :label="t('用户名')">
<cl-text>神仙都没用</cl-text>
</cl-list-item>
</demo-item>
<demo-item :label="t('内容靠左')">
<cl-list-item
:label="t('QQ')"
justify="start"
:pt="{
label: {
className: '!w-10'
}
}"
>
<cl-text>615206459</cl-text>
</cl-list-item>
</demo-item>
<demo-item :label="t('带箭头')">
<cl-list-item label="年龄" arrow>
<cl-text>18</cl-text>
</cl-list-item>
</demo-item>
<demo-item :label="t('带图标')">
<cl-list-item :label="t('余额')" icon="wallet-line">
<cl-text>10,9000</cl-text>
</cl-list-item>
</demo-item>
<demo-item :label="t('带图片')">
<cl-list-item
arrow
:pt="{
image: {
width: 48,
height: 48
}
}"
:label="t('神仙都没用')"
image="https://unix.cool-js.com/images/demo/avatar.jpg"
>
</cl-list-item>
</demo-item>
<demo-item :label="t('折叠')">
<cl-list-item :label="t('点击展开')" collapse arrow>
<template #collapse>
<view class="bg-surface-100 dark:bg-surface-700 p-3 rounded-xl">
<cl-text
>云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。</cl-text
>
</view>
</template>
</cl-list-item>
</demo-item>
<demo-item :label="t('可滑动')">
<cl-list-item :label="t('左滑编辑')" swipeable>
<template #swipe-right>
<view
class="bg-green-500 w-20 h-full flex flex-row items-center justify-center"
>
<text class="text-white text-md">{{ t("编辑") }}</text>
</view>
</template>
</cl-list-item>
<cl-list-item ref="listItemRef" :label="t('右滑删除')" swipeable>
<template #swipe-left>
<view
class="bg-red-500 w-20 h-full flex flex-row items-center justify-center"
@tap="onDelete"
>
<text class="text-white text-md">{{ t("删除") }}</text>
</view>
</template>
</cl-list-item>
</demo-item>
<demo-item :label="t('禁用')">
<cl-list-item :label="t('账号')" disabled>
<cl-text>1234567890</cl-text>
</cl-list-item>
</demo-item>
<demo-item :label="t('列表')">
<cl-list border>
<cl-list-item :label="t('我的订单')" hoverable> </cl-list-item>
<cl-list-item :label="t('我的收藏')" hoverable> </cl-list-item>
<cl-list-item :label="t('我的钱包')" hoverable> </cl-list-item>
</cl-list>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
import { useUi } from "@/uni_modules/cool-ui";
import { ref } from "vue";
const ui = useUi();
const listItemRef = ref<ClListItemComponentPublicInstance | null>(null);
function onDelete() {
ui.showToast({
message: "删除成功"
});
listItemRef.value!.resetSwipe();
}
</script>

View File

@@ -0,0 +1,70 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('横向滚动')">
<cl-marquee
:list="list"
direction="horizontal"
:item-height="200"
:item-width="360"
:pt="{
className: 'h-[200rpx] rounded-xl'
}"
></cl-marquee>
</demo-item>
<demo-item :label="t('纵向滚动')">
<cl-marquee
ref="marqueeRef"
:list="list"
direction="vertical"
:item-height="260"
:duration="isSpeed ? 2000 : 5000"
:pt="{
className: 'h-[500rpx] rounded-xl'
}"
></cl-marquee>
<cl-list
border
:pt="{
className: 'mt-5'
}"
>
<cl-list-item :label="t('快一点')">
<cl-switch v-model="isSpeed"></cl-switch>
</cl-list-item>
<cl-list-item :label="t('暂停')">
<cl-switch v-model="isPause" @change="onPauseChange"></cl-switch>
</cl-list-item>
</cl-list>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import DemoItem from "../components/item.uvue";
import { t } from "@/locale";
import { ref } from "vue";
const marqueeRef = ref<ClMarqueeComponentPublicInstance | null>(null);
const list = ref<string[]>([
"https://unix.cool-js.com/images/demo/bg1.png",
"https://unix.cool-js.com/images/demo/bg2.png",
"https://unix.cool-js.com/images/demo/bg3.png"
]);
const isSpeed = ref(false);
const isPause = ref(false);
function onPauseChange(value: boolean) {
if (value) {
marqueeRef.value!.pause();
} else {
marqueeRef.value!.play();
}
}
</script>

View File

@@ -0,0 +1,70 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-pagination v-model="page1" :total="24"> </cl-pagination>
</demo-item>
<demo-item :label="t('多页数')">
<cl-pagination v-model="page2" :total="500"> </cl-pagination>
</demo-item>
<demo-item :label="t('自定义样式')">
<cl-pagination
v-model="page3"
:total="100"
:pt="{
item: {
className: '!rounded-none !mx-[2rpx]'
}
}"
>
</cl-pagination>
</demo-item>
<demo-item :label="t('自定义文本')">
<cl-pagination
v-model="page4"
:total="24"
:pt="{
prev: {
className: '!w-auto px-3'
},
next: {
className: '!w-auto px-3'
}
}"
>
<template #prev>
<cl-text
:pt="{
className: 'text-sm'
}"
>{{ t("上一页") }}</cl-text
>
</template>
<template #next>
<cl-text
:pt="{
className: 'text-sm'
}"
>{{ t("下一页") }}</cl-text
>
</template>
</cl-pagination>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
const page1 = ref(1);
const page2 = ref(13);
const page3 = ref(1);
const page4 = ref(1);
</script>

View File

@@ -0,0 +1,110 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-read-more>
<cl-text>
云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
一枝红艳露凝香,云雨巫山枉断肠。借问汉宫谁得似?可怜飞燕倚新妆。
名花倾国两相欢,常得君王带笑看。解释春风无限恨,沉香亭北倚阑干。
</cl-text>
</cl-read-more>
</demo-item>
<demo-item :label="t('禁用切换按钮')">
<cl-read-more
v-model="visible"
:disabled="disabled"
:expand-text="disabled ? '付费解锁' : '展开'"
:expand-icon="disabled ? 'lock-line' : 'arrow-down-s-line'"
@toggle="toggle"
>
<cl-text>
云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
一枝红艳露凝香,云雨巫山枉断肠。借问汉宫谁得似?可怜飞燕倚新妆。
名花倾国两相欢,常得君王带笑看。解释春风无限恨,沉香亭北倚阑干。
</cl-text>
</cl-read-more>
</demo-item>
<demo-item :label="t('动态内容')">
<cl-read-more :content="content" :show-toggle="content != ''" ref="readMoreRef">
<view
class="flex flex-row items-center justify-center h-14"
v-if="content == ''"
>
<cl-loading :size="32"></cl-loading>
</view>
</cl-read-more>
</demo-item>
<demo-item :label="t('自定义高度')">
<cl-read-more :height="300">
<cl-text>
云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。
一枝红艳露凝香,云雨巫山枉断肠。借问汉宫谁得似?可怜飞燕倚新妆。
</cl-text>
<cl-image
:height="300"
width="100%"
:pt="{
className: 'my-3'
}"
src="https://unix.cool-js.com/images/demo/bg1.png"
></cl-image>
<cl-text>
名花倾国两相欢,常得君王带笑看。解释春风无限恨,沉香亭北倚阑干。
</cl-text>
</cl-read-more>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
import { ref } from "vue";
import { useUi } from "@/uni_modules/cool-ui";
const ui = useUi();
const visible = ref(false);
const disabled = ref(true);
const readMoreRef = ref<ClReadMoreComponentPublicInstance | null>(null);
const content = ref("");
function getContent() {
setTimeout(() => {
content.value =
"云想衣裳花想容,春风拂槛露华浓。若非群玉山头见,会向瑶台月下逢。一枝红艳露凝香,云雨巫山枉断肠。借问汉宫谁得似?可怜飞燕倚新妆。名花倾国两相欢,常得君王带笑看。解释春风无限恨,沉香亭北倚阑干。";
// 使用 slot 插入内容时,如果内容发生变化,需要重新获取高度
// readMoreRef.value!.getContentHeight();
}, 500);
}
function toggle(isExpanded: boolean) {
ui.showConfirm({
title: "提示",
message: "需支付100元才能解锁全部内容是否继续",
callback(action) {
if (action == "confirm") {
ui.showToast({
message: "支付成功"
});
disabled.value = false;
visible.value = true;
}
}
});
}
onReady(() => {
getContent();
});
</script>

View File

@@ -0,0 +1,71 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('基础用法')">
<cl-timeline>
<cl-timeline-item
icon="account-box-line"
:title="t('开通账号')"
date="2025-01-01"
:content="t('赠送500元')"
>
</cl-timeline-item>
<cl-timeline-item
icon="id-card-line"
:title="t('完成实名认证')"
date="2025-01-02"
:content="t('通过身份证认证')"
>
</cl-timeline-item>
<cl-timeline-item
icon="bank-card-line"
:title="t('绑定银行卡')"
date="2025-01-03"
:content="t('绑定招商银行储蓄卡')"
>
</cl-timeline-item>
<cl-timeline-item
icon="money-cny-box-line"
:title="t('首次充值')"
date="2025-01-04"
:content="t('充值1000元')"
>
</cl-timeline-item>
<cl-timeline-item
icon="checkbox-line"
:title="t('完成首笔交易')"
date="2025-01-05"
:hide-line="true"
>
<view class="flex flex-row mb-3 mt-1">
<cl-image
src="https://unix.cool-js.com/images/demo/bg1.png"
></cl-image>
<view class="flex-1 px-3">
<cl-text>{{ t("优选灵活配置混合A") }}</cl-text>
<cl-text class="mr-5 mt-1 text-sm">{{ t("1000元起") }}</cl-text>
<view class="flex flex-row mt-2 items-center">
<cl-button size="small" type="light">{{
t("立即购买")
}}</cl-button>
</view>
</view>
</view>
</cl-timeline-item>
</cl-timeline>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { t } from "@/locale";
import DemoItem from "../components/item.uvue";
</script>

View File

@@ -0,0 +1,391 @@
<template>
<cl-page>
<view class="p-3">
<demo-item :label="t('树形结构')">
<cl-tree
v-model="checkedKeys"
ref="treeRef"
:list="list"
:icon="isCustomIcon ? 'add-circle-line' : 'arrow-right-s-fill'"
:expand-icon="isCustomIcon ? 'indeterminate-circle-line' : 'arrow-down-s-fill'"
:checkable="true"
:multiple="true"
:check-strictly="checkStrictly"
></cl-tree>
<cl-list border :pt="{ className: 'mt-5' }">
<cl-list-item :label="t('父子关联')">
<cl-switch v-model="checkStrictly"></cl-switch>
</cl-list-item>
<cl-list-item :label="t('换个图标')">
<cl-switch v-model="isCustomIcon"></cl-switch>
</cl-list-item>
</cl-list>
</demo-item>
<demo-item :label="t('选中值')">
<cl-text>{{ checkedKeys.join("、") }}</cl-text>
</demo-item>
<demo-item :label="t('选中操作')">
<view class="mb-2">
<cl-button @tap="setChecked">{{ t("选中部分节点") }}</cl-button>
</view>
<view class="mb-2">
<cl-button @tap="getChecked">{{ t("获取选中节点") }}</cl-button>
</view>
<view class="mb-2">
<cl-button @tap="getHalfChecked">{{ t("获取半选节点") }}</cl-button>
<cl-text
v-if="halfCheckedKeys.length > 0"
:pt="{
className: 'text-sm p-2'
}"
>{{ halfCheckedKeys.join("、") }}</cl-text
>
</view>
<view class="mb-2">
<cl-button @tap="clearChecked">{{ t("清空选中") }}</cl-button>
</view>
</demo-item>
<demo-item :label="t('展开操作')">
<view class="mb-2">
<cl-button @tap="expand">{{ t("展开部分节点") }}</cl-button>
</view>
<view class="mb-2">
<cl-button @tap="getExpanded">{{ t("获取展开节点") }}</cl-button>
<cl-text
v-if="expandedKeys.length > 0"
:pt="{
className: 'text-sm p-2'
}"
>{{ expandedKeys.join("、") }}</cl-text
>
</view>
<view class="mb-2">
<cl-button @tap="expandAll">{{ t("展开所有") }}</cl-button>
</view>
<view class="mb-2">
<cl-button @tap="collapseAll">{{ t("收起所有") }}</cl-button>
</view>
</demo-item>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import DemoItem from "../components/item.uvue";
import { t } from "@/locale";
import { ref } from "vue";
import { useTree, useUi, type ClTreeItem } from "@/uni_modules/cool-ui";
const ui = useUi();
const list = ref<ClTreeItem[]>([]);
function refresh() {
ui.showLoading();
setTimeout(() => {
list.value = useTree([
{
id: "1",
label: "华为",
children: [
{
id: "1-1",
label: "手机",
children: [
{
id: "1-1-1",
label: "Mate系列",
children: [
{
id: "1-1-1-1",
label: "Mate 50"
},
{
id: "1-1-1-2",
disabled: true,
label: "Mate 40"
},
{
id: "1-1-1-3",
label: "Mate 30"
}
]
},
{
id: "1-1-2",
label: "P系列",
children: [
{
id: "1-1-2-1",
disabled: true,
label: "P60"
},
{
id: "1-1-2-2",
label: "P50"
},
{
id: "1-1-2-3",
label: "P40"
}
]
}
]
},
{
id: "1-2",
label: "笔记本",
children: [
{
id: "1-2-1",
label: "MateBook X",
children: [
{
id: "1-2-1-1",
label: "MateBook X Pro"
},
{
id: "1-2-1-2",
label: "MateBook X 2022"
}
]
},
{
id: "1-2-2",
label: "MateBook D",
children: [
{
id: "1-2-2-1",
label: "MateBook D 14"
},
{
id: "1-2-2-2",
label: "MateBook D 15"
}
]
},
{
id: "1-2-3",
label: "MateBook 13"
}
]
}
]
},
{
id: "2",
label: "小米",
isExpand: true,
children: [
{
id: "2-1",
label: "手机",
children: [
{
id: "2-1-1",
label: "小米数字系列"
},
{
id: "2-1-2",
label: "Redmi系列"
}
]
},
{
id: "2-2",
label: "家电",
children: [
{
id: "2-2-1",
label: "电视"
},
{
id: "2-2-2",
label: "空调"
}
]
}
]
},
{
id: "3",
label: "苹果",
children: [
{
id: "3-1",
label: "手机",
children: [
{
id: "3-1-1",
label: "iPhone 14"
},
{
id: "3-1-2",
label: "iPhone 13"
}
]
},
{
id: "3-2",
label: "平板",
children: [
{
id: "3-2-1",
label: "iPad Pro"
},
{
id: "3-2-2",
label: "iPad Air"
}
]
}
]
},
{
id: "4",
label: "OPPO",
children: [
{
id: "4-1",
label: "手机",
children: [
{
id: "4-1-1",
label: "Find系列"
},
{
id: "4-1-2",
label: "Reno系列"
}
]
},
{
id: "4-2",
label: "配件",
children: [
{
id: "4-2-1",
label: "耳机"
},
{
id: "4-2-2",
label: "手环"
}
]
}
]
},
{
id: "5",
label: "vivo",
children: [
{
id: "5-1",
label: "手机",
children: [
{
id: "5-1-1",
label: "X系列"
},
{
id: "5-1-2",
label: "S系列"
}
]
},
{
id: "5-2",
label: "智能设备",
children: [
{
id: "5-2-1",
label: "手表"
},
{
id: "5-2-2",
label: "耳机"
}
]
}
]
}
]);
ui.hideLoading();
}, 500);
}
// 是否严格的遵循父子不互相关联
const checkStrictly = ref(false);
// 是否自定义图标
const isCustomIcon = ref(false);
// 树形组件引用
const treeRef = ref<ClTreeComponentPublicInstance | null>(null);
// 选中节点的keys
const checkedKeys = ref<(string | number)[]>(["1-1-1-1", "2-1-1", "2-1-2"]);
const checkedKeys2 = ref<string | null>("1-1-1");
// 半选节点的keys
const halfCheckedKeys = ref<(string | number)[]>([]);
// 展开节点的keys
const expandedKeys = ref<(string | number)[]>([]);
// 演示方法
function setChecked() {
treeRef.value!.setCheckedKeys(["1-1", "2"]);
}
function getChecked() {
checkedKeys.value = treeRef.value!.getCheckedKeys();
}
function clearChecked() {
treeRef.value!.clearChecked();
checkedKeys.value = [];
halfCheckedKeys.value = [];
}
function getHalfChecked() {
halfCheckedKeys.value = treeRef.value!.getHalfCheckedKeys();
}
function expand() {
treeRef.value!.setExpandedKeys(["4", "5"]);
}
function getExpanded() {
expandedKeys.value = treeRef.value!.getExpandedKeys();
}
function expandAll() {
treeRef.value!.expandAll();
expandedKeys.value = treeRef.value!.getExpandedKeys();
}
function collapseAll() {
treeRef.value!.collapseAll();
expandedKeys.value = [];
}
onReady(() => {
refresh();
});
</script>

View File

@@ -0,0 +1,138 @@
<template>
<cl-page back-top>
<view class="py-2">
<cl-waterfall ref="waterfallRef" :column="2" :gutter="16">
<template #item="{ item, index }">
<view class="bg-white mb-3 rounded-xl dark:!bg-gray-800 relative">
<image
:src="item['image']"
mode="widthFix"
class="w-full rounded-xl"
></image>
<template v-if="item['isAd']">
<cl-tag :pt="{ className: 'absolute left-1 top-1 scale-75' }"
>广告</cl-tag
>
<cl-icon
color="white"
name="close-line"
:pt="{ className: 'absolute right-2 top-2' }"
@tap="del(item['id'] as number)"
></cl-icon>
</template>
<view class="p-3" v-else>
<cl-text>{{ item["title"] }}</cl-text>
<cl-row class="mt-2" :pt="{ className: 'justify-end items-center' }">
<cl-icon name="heart-line"></cl-icon>
<cl-text :pt="{ className: 'text-sm ml-1' }">{{
item["likeCount"]
}}</cl-text>
</cl-row>
</view>
</view>
</template>
</cl-waterfall>
<cl-loadmore :loading="true" safe-area-bottom></cl-loadmore>
</view>
</cl-page>
</template>
<script lang="ts" setup>
import { random } from "@/cool";
import { onMounted, ref } from "vue";
const waterfallRef = ref<ClWaterfallComponentPublicInstance | null>(null);
const loading = ref(false);
let id = 0;
function refresh() {
const items = [
{
id: id++,
likeCount: random(100, 1000),
title: "春日樱花盛开时节,粉色花瓣如诗如画般飘洒",
image: "https://unix.cool-js.com/images/demo/1.jpg"
},
{
id: id++,
likeCount: random(100, 1000),
title: "夕阳西下的海滩边,金色阳光温柔地洒在波光粼粼的海面上,构成令人心旷神怡的日落美景",
image: "https://unix.cool-js.com/images/demo/2.jpg"
},
{
id: id++,
likeCount: random(100, 1000),
title: "寒冬腊月时分,洁白雪花纷纷扬扬地覆盖着整个世界,感受冬日的宁静与美好",
image: "https://unix.cool-js.com/images/demo/3.jpg"
},
{
id: id++,
image: "https://unix.cool-js.com/images/demo/4.jpg",
isAd: true
},
{
id: id++,
likeCount: random(100, 1000),
title: "都市夜景霓虹闪烁,五彩斑斓光芒照亮城市营造梦幻般景象",
image: "https://unix.cool-js.com/images/demo/5.jpg"
},
{
id: id++,
likeCount: random(100, 1000),
title: "云雾缭绕的山间风光如诗如画让人心旷神怡,微风轻抚树梢带来阵阵清香,鸟儿在林间自由歌唱",
image: "https://unix.cool-js.com/images/demo/6.jpg"
},
{
id: id++,
likeCount: random(100, 1000),
title: "古老建筑与现代摩天大楼交相辉映,传统与现代完美融合创造独特城市景观",
image: "https://unix.cool-js.com/images/demo/7.jpg"
},
{
id: id++,
likeCount: random(100, 1000),
title: "广袤田野绿意盎然风光无限,金黄麦浪在微风中轻柔摇曳,农家炊烟袅袅升起",
image: "https://unix.cool-js.com/images/demo/8.jpg"
},
{
id: id++,
likeCount: random(100, 1000),
title: "璀璨星空下银河横跨天际,繁星闪烁神秘光芒营造浪漫夜空美景",
image: "https://unix.cool-js.com/images/demo/9.jpg"
},
{
id: id++,
likeCount: random(100, 1000),
title: "雄伟瀑布从高耸悬崖飞流直下激起千层浪花,彩虹在水雾中若隐若现如梦如幻",
image: "https://unix.cool-js.com/images/demo/10.jpg"
}
];
waterfallRef.value!.append(items);
}
function del(id: number) {
waterfallRef.value!.remove(id);
}
onReachBottom(() => {
if (loading.value) return;
loading.value = true;
setTimeout(() => {
refresh();
loading.value = false;
}, 1000);
});
onMounted(() => {
refresh();
});
</script>