添加模板页
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cool-unix",
|
"name": "cool-unix",
|
||||||
"version": "8.0.10",
|
"version": "8.0.11",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-ui": "node ./uni_modules/cool-ui/scripts/generate-types.js",
|
"build-ui": "node ./uni_modules/cool-ui/scripts/generate-types.js",
|
||||||
|
|||||||
33
pages.json
33
pages.json
@@ -11,6 +11,12 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/index/template",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "%模板%"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"subPackages": [
|
"subPackages": [
|
||||||
@@ -20,19 +26,19 @@
|
|||||||
{
|
{
|
||||||
"path": "index",
|
"path": "index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "%page.设置%"
|
"navigationBarTitleText": "%设置%"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "general",
|
"path": "general",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "%page.通用设置%"
|
"navigationBarTitleText": "%通用设置%"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "notice",
|
"path": "notice",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "%page.通知设置%"
|
"navigationBarTitleText": "%通知设置%"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -44,7 +50,7 @@
|
|||||||
{
|
{
|
||||||
"path": "cs",
|
"path": "cs",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "%page.联系客服%"
|
"navigationBarTitleText": "%联系客服%"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -55,7 +61,7 @@
|
|||||||
{
|
{
|
||||||
"path": "edit",
|
"path": "edit",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "%page.编辑资料%"
|
"navigationBarTitleText": "%编辑资料%"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -413,6 +419,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"root": "pages/template",
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"path": "shop/goods-category",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "%商品分类%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"globalStyle": {
|
"globalStyle": {
|
||||||
@@ -436,6 +453,12 @@
|
|||||||
"selectedIconPath": "/static/icon/tabbar/home2.png",
|
"selectedIconPath": "/static/icon/tabbar/home2.png",
|
||||||
"text": "%首页%"
|
"text": "%首页%"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pagePath": "pages/index/template",
|
||||||
|
"iconPath": "/static/icon/tabbar/template.png",
|
||||||
|
"selectedIconPath": "/static/icon/tabbar/template2.png",
|
||||||
|
"text": "%模板%"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pagePath": "pages/index/my",
|
"pagePath": "pages/index/my",
|
||||||
"iconPath": "/static/icon/tabbar/my.png",
|
"iconPath": "/static/icon/tabbar/my.png",
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
<view class="p-3">
|
<view class="p-3">
|
||||||
<view class="group" v-for="item in data" :key="item.label">
|
<view class="group" v-for="item in data" :key="item.label">
|
||||||
<cl-text :pt="{ className: '!text-sm !text-surface-400 mb-2 ml-1' }">{{
|
<cl-text :pt="{ className: '!text-sm !text-surface-400 mb-2 ml-2' }">{{
|
||||||
item.label
|
item.label
|
||||||
}}</cl-text>
|
}}</cl-text>
|
||||||
|
|
||||||
|
|||||||
111
pages/index/template.uvue
Normal file
111
pages/index/template.uvue
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<template>
|
||||||
|
<cl-page>
|
||||||
|
<view class="p-3">
|
||||||
|
<cl-list
|
||||||
|
v-for="(item, index) in list"
|
||||||
|
:key="index"
|
||||||
|
:title="item.label"
|
||||||
|
:pt="{
|
||||||
|
className: 'mb-5'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<cl-list-item
|
||||||
|
v-for="child in item.children"
|
||||||
|
:key="child.label"
|
||||||
|
:label="child.label"
|
||||||
|
:arrow="child.path != null"
|
||||||
|
:pt="{
|
||||||
|
label: {
|
||||||
|
className: '!w-auto'
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
@tap="toPath(child)"
|
||||||
|
>
|
||||||
|
</cl-list-item>
|
||||||
|
</cl-list>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 自定义底部导航栏 -->
|
||||||
|
<tabbar></tabbar>
|
||||||
|
</cl-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Tabbar from "@/components/tabbar.uvue";
|
||||||
|
import { router } from "@/cool";
|
||||||
|
import { t } from "@/locale";
|
||||||
|
import { useUi } from "@/uni_modules/cool-ui";
|
||||||
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
const ui = useUi();
|
||||||
|
|
||||||
|
type Item = {
|
||||||
|
label: string;
|
||||||
|
path?: string;
|
||||||
|
children?: Item[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const list = computed<Item[]>(() => [
|
||||||
|
{
|
||||||
|
label: t("商城"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: t("商品分类"),
|
||||||
|
path: "/pages/template/shop/goods-category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("商品详情")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("商品列表、筛选")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("购物车")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("订单列表、详情")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("聊天"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: t("对话列表、历史记录")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "AI",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: t("流式回复")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("语言合成")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("语音识别")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t("其他"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: t("文件管理")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
function toPath(item: Item) {
|
||||||
|
if (item.path == null) {
|
||||||
|
return ui.showToast({
|
||||||
|
message: t("该模板正在开发中")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
router.to(item.path!);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
335
pages/template/shop/goods-category.uvue
Normal file
335
pages/template/shop/goods-category.uvue
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
<template>
|
||||||
|
<cl-page>
|
||||||
|
<view class="flex flex-col h-full">
|
||||||
|
<view class="flex flex-row p-3">
|
||||||
|
<cl-input
|
||||||
|
:pt="{
|
||||||
|
className: parseClass(['flex-1 !border-2 !rounded-xl'])
|
||||||
|
}"
|
||||||
|
prefix-icon="search-line"
|
||||||
|
placeholder="iPhone 16 Pro Max"
|
||||||
|
></cl-input>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex flex-row flex-1">
|
||||||
|
<!-- 左侧分类列表 -->
|
||||||
|
<view class="h-full w-[200rpx] bg-white dark:bg-surface-800 mr-2 rounded-tr-xl">
|
||||||
|
<scroll-view direction="vertical" :show-scrollbar="false" class="h-full">
|
||||||
|
<view
|
||||||
|
class="h-[100rpx] p-2"
|
||||||
|
v-for="(item, index) in list"
|
||||||
|
:key="item.label"
|
||||||
|
@click="onCategoryChange(index)"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="flex flex-row items-center justify-center h-full rounded-lg"
|
||||||
|
:class="[
|
||||||
|
categoryActive == index
|
||||||
|
? isDark
|
||||||
|
? 'bg-primary-500'
|
||||||
|
: 'bg-primary-50'
|
||||||
|
: ''
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<cl-text
|
||||||
|
:pt="{
|
||||||
|
className: parseClass([
|
||||||
|
[
|
||||||
|
categoryActive == index,
|
||||||
|
isDark ? '!text-white' : '!text-primary-500',
|
||||||
|
isDark ? '!text-surface-300' : '!text-surface-500'
|
||||||
|
]
|
||||||
|
])
|
||||||
|
}"
|
||||||
|
>{{ item.label }}</cl-text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 右侧商品列表 -->
|
||||||
|
<view class="flex-1">
|
||||||
|
<scroll-view
|
||||||
|
direction="vertical"
|
||||||
|
:scroll-into-view="scrollIntoView"
|
||||||
|
:scroll-with-animation="!scrollLock"
|
||||||
|
class="h-full"
|
||||||
|
@scroll="onScroll"
|
||||||
|
>
|
||||||
|
<view class="pr-2">
|
||||||
|
<view
|
||||||
|
class="category-item flex rounded-xl bg-white dark:bg-surface-800 mb-2 pb-3"
|
||||||
|
v-for="(item, index) in list"
|
||||||
|
:key="item.label"
|
||||||
|
:id="`category-item-${index}`"
|
||||||
|
>
|
||||||
|
<cl-text
|
||||||
|
:pt="{
|
||||||
|
className: 'p-3'
|
||||||
|
}"
|
||||||
|
>{{ item.label }}</cl-text
|
||||||
|
>
|
||||||
|
|
||||||
|
<view class="px-1">
|
||||||
|
<cl-row :gutter="10">
|
||||||
|
<cl-col
|
||||||
|
v-for="goods in item.list"
|
||||||
|
:key="goods.name"
|
||||||
|
:span="8"
|
||||||
|
>
|
||||||
|
<view class="flex items-center flex-col justify-center">
|
||||||
|
<cl-image :src="goods.image"></cl-image>
|
||||||
|
<cl-text
|
||||||
|
:ellipsis="true"
|
||||||
|
:pt="{ className: '!text-xs text-center mt-2' }"
|
||||||
|
>{{ goods.name }}</cl-text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
</cl-col>
|
||||||
|
</cl-row>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</cl-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { isDark, parseClass } from "@/cool";
|
||||||
|
import { getCurrentInstance, ref } from "vue";
|
||||||
|
|
||||||
|
const { proxy } = getCurrentInstance()!;
|
||||||
|
|
||||||
|
// 商品类型
|
||||||
|
type Goods = {
|
||||||
|
name: string;
|
||||||
|
price: number;
|
||||||
|
image: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分类类型
|
||||||
|
type Category = {
|
||||||
|
label: string;
|
||||||
|
top?: number;
|
||||||
|
list: Goods[];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 商品分类示例数据
|
||||||
|
const list = ref<Category[]>([
|
||||||
|
{
|
||||||
|
label: "推荐",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "iPhone 15 Pro",
|
||||||
|
price: 8999,
|
||||||
|
image: "/static/goods/iphone15pro.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "华为 Mate 60 Pro",
|
||||||
|
price: 6999,
|
||||||
|
image: "/static/goods/mate60pro.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "小米 14 Ultra",
|
||||||
|
price: 5999,
|
||||||
|
image: "/static/goods/xiaomi14ultra.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Apple",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "iPhone 15 Pro",
|
||||||
|
price: 8999,
|
||||||
|
image: "/static/goods/iphone15pro.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iPhone 14",
|
||||||
|
price: 5999,
|
||||||
|
image: "/static/goods/iphone14.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "华为",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "华为 Mate 60 Pro",
|
||||||
|
price: 6999,
|
||||||
|
image: "/static/goods/mate60pro.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "华为 P60",
|
||||||
|
price: 4999,
|
||||||
|
image: "/static/goods/p60.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "小米",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "小米 14 Ultra",
|
||||||
|
price: 5999,
|
||||||
|
image: "/static/goods/xiaomi14ultra.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "小米 13",
|
||||||
|
price: 3999,
|
||||||
|
image: "/static/goods/xiaomi13.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "三星",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "三星 Galaxy S24",
|
||||||
|
price: 7999,
|
||||||
|
image: "/static/goods/galaxys24.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "三星 Galaxy Z Flip5",
|
||||||
|
price: 8999,
|
||||||
|
image: "/static/goods/galaxyzflip5.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "OPPO",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "OPPO Find X7",
|
||||||
|
price: 4999,
|
||||||
|
image: "/static/goods/findx7.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "VIVO",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "VIVO X100 Pro",
|
||||||
|
price: 5999,
|
||||||
|
image: "/static/goods/x100pro.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "荣耀",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "荣耀 Magic6",
|
||||||
|
price: 4599,
|
||||||
|
image: "/static/goods/magic6.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "一加",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "一加 12",
|
||||||
|
price: 4299,
|
||||||
|
image: "/static/goods/oneplus12.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "红米",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "红米 K70 Pro",
|
||||||
|
price: 3299,
|
||||||
|
image: "/static/goods/k70pro.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "魅族",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "魅族 21",
|
||||||
|
price: 3999,
|
||||||
|
image: "/static/goods/meizu21.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "坚果",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "坚果 R2",
|
||||||
|
price: 2999,
|
||||||
|
image: "/static/goods/nutR2.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "其他",
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
name: "诺基亚 X30",
|
||||||
|
price: 2599,
|
||||||
|
image: "/static/goods/nokiax30.png"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 滚动到指定分类
|
||||||
|
const scrollIntoView = ref("");
|
||||||
|
|
||||||
|
// 滚动锁定
|
||||||
|
const scrollLock = ref(false);
|
||||||
|
|
||||||
|
// 当前选中的分类
|
||||||
|
const categoryActive = ref(0);
|
||||||
|
|
||||||
|
// 分类切换
|
||||||
|
function onCategoryChange(index: number) {
|
||||||
|
categoryActive.value = index;
|
||||||
|
|
||||||
|
scrollIntoView.value = `category-item-${index}`;
|
||||||
|
scrollLock.value = true;
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
scrollLock.value = false;
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动时,更新当前选中的分类
|
||||||
|
function onScroll(e: UniScrollEvent) {
|
||||||
|
if (scrollLock.value) return;
|
||||||
|
|
||||||
|
const top = e.detail.scrollTop;
|
||||||
|
|
||||||
|
list.value.forEach((e, i) => {
|
||||||
|
if (top >= e.top!) {
|
||||||
|
categoryActive.value = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
function init() {
|
||||||
|
uni.createSelectorQuery()
|
||||||
|
.in(proxy!.$root)
|
||||||
|
.selectAll(".category-item")
|
||||||
|
.boundingClientRect((res) => {
|
||||||
|
(res as NodeInfo[]).forEach((e, i, arr) => {
|
||||||
|
list.value[i].top = (e.top ?? 0) - (arr[0].top ?? 0);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
onReady(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -3,6 +3,7 @@ import { router, useStore } from "@/cool";
|
|||||||
const ignoreToken = [
|
const ignoreToken = [
|
||||||
"/pages/index/home",
|
"/pages/index/home",
|
||||||
"/pages/index/my",
|
"/pages/index/my",
|
||||||
|
"/pages/index/template",
|
||||||
"/pages/user/login",
|
"/pages/user/login",
|
||||||
"/pages/user/doc"
|
"/pages/user/doc"
|
||||||
];
|
];
|
||||||
@@ -10,7 +11,11 @@ const ignoreToken = [
|
|||||||
router.beforeEach((to, next) => {
|
router.beforeEach((to, next) => {
|
||||||
const { user } = useStore();
|
const { user } = useStore();
|
||||||
|
|
||||||
if (ignoreToken.includes(to.path) || to.path.startsWith("/pages/demo")) {
|
if (
|
||||||
|
ignoreToken.includes(to.path) ||
|
||||||
|
to.path.startsWith("/pages/demo") ||
|
||||||
|
to.path.startsWith("/pages/template")
|
||||||
|
) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
if (!user.isNull()) {
|
if (!user.isNull()) {
|
||||||
|
|||||||
BIN
static/icon/tabbar/template.png
Normal file
BIN
static/icon/tabbar/template.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
static/icon/tabbar/template2.png
Normal file
BIN
static/icon/tabbar/template2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
Reference in New Issue
Block a user