feat: add mine page and secondary pages

This commit is contained in:
czz
2026-05-08 11:22:59 +08:00
parent bc66b0ff0a
commit 6ff9070eca
32 changed files with 1163 additions and 1 deletions

View File

@@ -1,5 +1,17 @@
export default defineAppConfig({
pages: ["pages/index/index", "pages/message/index"],
pages: [
"pages/index/index",
"pages/message/index",
"pages/mine/index",
"pages/profile/index",
"pages/settings/index",
"pages/support/index",
"pages/devices/index",
"pages/repair/index",
"pages/feedback/index",
"pages/videos/index",
"pages/follow-us/index"
],
window: {
navigationBarTitleText: "新手小程序",
navigationBarBackgroundColor: "#1AAD19",

View File

@@ -0,0 +1,128 @@
.secondary-page {
position: relative;
min-height: 100vh;
padding: 32rpx 24rpx 48rpx;
box-sizing: border-box;
background: linear-gradient(180deg, #1e2432 0%, #171d29 100%);
overflow: hidden;
}
.secondary-page__halo {
position: absolute;
border-radius: 50%;
pointer-events: none;
}
.secondary-page__halo--large {
top: -80rpx;
right: -44rpx;
width: 320rpx;
height: 320rpx;
background:
radial-gradient(circle, rgba(54, 228, 170, 0.08) 0 24%, transparent 25% 44%, rgba(109, 121, 154, 0.16) 45% 62%, transparent 63%),
radial-gradient(circle at center, rgba(255, 255, 255, 0.06), transparent 72%);
}
.secondary-page__halo--small {
top: 180rpx;
right: 90rpx;
width: 160rpx;
height: 120rpx;
background: radial-gradient(circle at center, rgba(255, 255, 255, 0.05), transparent 68%);
}
.secondary-page__hero {
position: relative;
z-index: 1;
margin-bottom: 28rpx;
padding: 32rpx 30rpx;
border-radius: 28rpx;
background: rgba(39, 46, 64, 0.95);
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.03);
}
.secondary-page__eyebrow {
display: block;
margin-bottom: 12rpx;
color: #40deb4;
font-size: 22rpx;
letter-spacing: 4rpx;
}
.secondary-page__title {
display: block;
color: #f6f8fb;
font-size: 42rpx;
font-weight: 600;
}
.secondary-page__description {
display: block;
margin-top: 14rpx;
color: #9aa5bb;
font-size: 24rpx;
line-height: 1.7;
}
.secondary-page__content {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
gap: 20rpx;
}
.secondary-page__card {
padding: 28rpx;
border-radius: 24rpx;
background: rgba(39, 46, 64, 0.94);
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.03);
}
.secondary-page__card-title {
display: block;
margin-bottom: 20rpx;
color: #eef3fb;
font-size: 28rpx;
font-weight: 600;
}
.secondary-page__list {
display: flex;
flex-direction: column;
gap: 2rpx;
}
.secondary-page__list-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1rpx solid rgba(255, 255, 255, 0.06);
}
.secondary-page__list-item:last-child {
padding-bottom: 0;
border-bottom: 0;
}
.secondary-page__list-label {
color: #edf1f7;
font-size: 26rpx;
}
.secondary-page__list-value {
color: #7c879d;
font-size: 22rpx;
}
.secondary-page__footer-tip {
position: relative;
z-index: 1;
display: block;
margin-top: 22rpx;
color: #7d88a1;
font-size: 22rpx;
line-height: 1.7;
text-align: center;
}

View File

@@ -0,0 +1,56 @@
import { Text, View } from "@tarojs/components";
import "./index.scss";
export type SecondaryPageItem = {
label: string;
value?: string;
};
export type SecondaryPageSection = {
title: string;
items: SecondaryPageItem[];
};
type SecondaryPageProps = {
eyebrow: string;
title: string;
description: string;
sections: SecondaryPageSection[];
footerTip?: string;
};
export default function SecondaryPage(props: SecondaryPageProps) {
const { eyebrow, title, description, sections, footerTip } = props;
return (
<View className="secondary-page">
<View className="secondary-page__halo secondary-page__halo--large" />
<View className="secondary-page__halo secondary-page__halo--small" />
<View className="secondary-page__hero">
<Text className="secondary-page__eyebrow">{eyebrow}</Text>
<Text className="secondary-page__title">{title}</Text>
<Text className="secondary-page__description">{description}</Text>
</View>
<View className="secondary-page__content">
{sections.map((section) => (
<View className="secondary-page__card" key={section.title}>
<Text className="secondary-page__card-title">{section.title}</Text>
<View className="secondary-page__list">
{section.items.map((item) => (
<View className="secondary-page__list-item" key={`${section.title}-${item.label}`}>
<Text className="secondary-page__list-label">{item.label}</Text>
<Text className="secondary-page__list-value">{item.value || "待接入"}</Text>
</View>
))}
</View>
</View>
))}
</View>
{footerTip ? <Text className="secondary-page__footer-tip">{footerTip}</Text> : null}
</View>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "我的设备"
});

View File

@@ -0,0 +1,3 @@
.devices-page {
display: block;
}

View File

@@ -0,0 +1,29 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "设备概览",
items: [
{ label: "已绑定设备", value: "0 台" },
{ label: "设备共享管理", value: "待接入" },
{ label: "添加设备", value: "可复用首页绑定能力" }
]
},
{
title: "当前状态",
items: [{ label: "设备列表", value: "暂无已绑定设备" }]
}
];
export default function DevicesPage() {
return (
<SecondaryPage
eyebrow="DEVICES"
title="我的设备"
description="这里先保留设备管理骨架,后续可以接真实设备列表、设备状态和共享管理。"
sections={sections}
footerTip="如果后面要对接设备绑定,可以优先复用首页已经实现的扫码和蓝牙入口。"
/>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "问题反馈"
});

View File

@@ -0,0 +1,3 @@
.feedback-page {
display: block;
}

View File

@@ -0,0 +1,28 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "反馈入口",
items: [
{ label: "提交问题" },
{ label: "提交建议" },
{ label: "上传截图", value: "待接入上传能力" }
]
},
{
title: "记录查询",
items: [{ label: "反馈记录", value: "后续展示处理进度" }]
}
];
export default function FeedbackPage() {
return (
<SecondaryPage
eyebrow="FEEDBACK"
title="问题反馈"
description="这里先保留问题和建议入口,后续补充表单校验、截图上传和反馈历史即可继续扩展。"
sections={sections}
/>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "关注我们"
});

View File

@@ -0,0 +1,3 @@
.follow-us-page {
display: block;
}

View File

@@ -0,0 +1,25 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "官方入口",
items: [
{ label: "官方公众号", value: "待补充二维码" },
{ label: "官方网站", value: "待补充地址" },
{ label: "联系方式", value: "待补充电话或邮箱" },
{ label: "社区入口", value: "待补充链接" }
]
}
];
export default function FollowUsPage() {
return (
<SecondaryPage
eyebrow="FOLLOW"
title="关注我们"
description="这里先预留官方触点,后续可以继续接公众号二维码、官网跳转和社区活动入口。"
sections={sections}
/>
);
}

View File

@@ -28,6 +28,7 @@ const navItems: TabbarItem[] = [
{ key: "message", label: "消息", active: false, badge: true },
{ key: "mine", label: "我的", active: false }
];
const mockBluetoothDevices: DeviceCandidate[] = [
{ id: "mock-thermo-01", name: "体征监测设备 A1", source: "mock" },
{ id: "mock-thermo-02", name: "体征监测设备 B2", source: "mock" }
@@ -124,6 +125,11 @@ export default function Index() {
return;
}
if (item.key === "mine") {
Taro.navigateTo({ url: "/pages/mine/index" });
return;
}
showToast(`${item.label}功能待接入`);
};

View File

@@ -0,0 +1,4 @@
export default definePageConfig({
navigationStyle: "custom",
navigationBarTitleText: "我的"
});

429
src/pages/mine/index.scss Normal file
View File

@@ -0,0 +1,429 @@
.mine-page {
position: relative;
min-height: 100vh;
padding: calc(var(--top-safe-height, 0px) + 34rpx) 24rpx 170rpx;
box-sizing: border-box;
background: linear-gradient(180deg, #1f2534 0%, #171d29 100%);
overflow: hidden;
}
.mine-page__halo {
position: absolute;
border-radius: 50%;
pointer-events: none;
}
.mine-page__halo--large {
top: -110rpx;
right: -34rpx;
width: 360rpx;
height: 360rpx;
background:
radial-gradient(circle, rgba(54, 228, 170, 0.06) 0 24%, transparent 25% 42%, rgba(110, 121, 151, 0.14) 43% 62%, transparent 63%),
radial-gradient(circle at center, rgba(255, 255, 255, 0.05), transparent 72%);
}
.mine-page__halo--small {
top: 90rpx;
right: 88rpx;
width: 150rpx;
height: 110rpx;
background: radial-gradient(circle at center, rgba(255, 255, 255, 0.04), transparent 70%);
}
.mine-page__header-card {
position: relative;
z-index: 1;
display: flex;
justify-content: space-between;
padding: 34rpx 28rpx 30rpx;
margin-bottom: 22rpx;
border-radius: 0 0 28rpx 28rpx;
background: rgba(39, 46, 64, 0.96);
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.03);
}
.mine-page__header-main {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
}
.mine-page__avatar {
display: flex;
align-items: center;
justify-content: center;
width: 104rpx;
height: 104rpx;
margin-right: 24rpx;
border-radius: 50%;
background: linear-gradient(180deg, rgba(170, 177, 192, 0.55) 0%, rgba(131, 141, 159, 0.75) 100%);
}
.mine-page__avatar-placeholder {
position: relative;
width: 56rpx;
height: 56rpx;
}
.mine-page__avatar-head,
.mine-page__avatar-body {
position: absolute;
left: 50%;
background: rgba(238, 240, 244, 0.72);
transform: translateX(-50%);
}
.mine-page__avatar-head {
top: 0;
width: 24rpx;
height: 24rpx;
border-radius: 50%;
}
.mine-page__avatar-body {
bottom: 0;
width: 48rpx;
height: 26rpx;
border-radius: 26rpx 26rpx 20rpx 20rpx;
}
.mine-page__identity {
display: flex;
flex: 1;
flex-direction: column;
min-width: 0;
}
.mine-page__name {
color: #f4f7fb;
font-size: 34rpx;
font-weight: 600;
}
.mine-page__phone {
margin-top: 10rpx;
color: #c2cad9;
font-size: 24rpx;
}
.mine-page__vip-row {
display: flex;
align-items: center;
margin-top: 12rpx;
gap: 10rpx;
}
.mine-page__vip-badge {
color: #f4a55c;
font-size: 22rpx;
font-style: italic;
}
.mine-page__vip-text,
.mine-page__vip-count {
color: #11d1ba;
font-size: 20rpx;
}
.mine-page__header-actions {
display: flex;
flex-direction: column;
align-items: flex-end;
padding-left: 18rpx;
padding-right: calc(var(--menu-safe-width, 0px) + 6rpx);
}
.mine-page__icon-actions {
display: flex;
align-items: center;
gap: 16rpx;
}
.mine-page__circle-action {
position: relative;
width: 34rpx;
height: 34rpx;
opacity: 0.9;
}
.mine-page__circle-action::before,
.mine-page__circle-action::after {
position: absolute;
content: "";
}
.mine-page__circle-action--support::before {
inset: 7rpx 4rpx 10rpx;
border: 2rpx solid rgba(255, 255, 255, 0.84);
border-bottom: 0;
border-radius: 20rpx 20rpx 0 0;
}
.mine-page__circle-action--support::after {
left: 12rpx;
right: 12rpx;
bottom: 6rpx;
height: 10rpx;
border-left: 2rpx solid rgba(255, 255, 255, 0.84);
border-right: 2rpx solid rgba(255, 255, 255, 0.84);
border-radius: 0 0 10rpx 10rpx;
}
.mine-page__circle-action--settings::before {
inset: 8rpx;
border: 2rpx solid rgba(255, 255, 255, 0.84);
border-radius: 50%;
}
.mine-page__circle-action--settings::after {
inset: 3rpx;
border: 2rpx dashed rgba(255, 255, 255, 0.56);
border-radius: 50%;
}
.mine-page__profile-link {
margin-top: 56rpx;
color: #1ac9c0;
font-size: 24rpx;
}
.mine-page__menu-card {
position: relative;
z-index: 1;
border-radius: 24rpx;
background: rgba(39, 46, 64, 0.96);
box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.03);
overflow: hidden;
}
.mine-page__menu-item {
display: flex;
align-items: center;
min-height: 96rpx;
padding: 0 24rpx;
border-top: 1rpx solid rgba(255, 255, 255, 0.05);
}
.mine-page__menu-item--first {
border-top: 0;
}
.mine-page__menu-icon {
position: relative;
width: 28rpx;
height: 28rpx;
margin-right: 18rpx;
}
.mine-page__menu-icon::before,
.mine-page__menu-icon::after {
position: absolute;
content: "";
border-color: #19d3be;
}
.mine-page__menu-icon--device::before {
inset: 4rpx;
border: 2rpx solid #19d3be;
border-radius: 6rpx;
}
.mine-page__menu-icon--device::after {
left: 6rpx;
right: 6rpx;
top: 12rpx;
height: 2rpx;
background: #19d3be;
}
.mine-page__menu-icon--repair::before {
left: 4rpx;
top: 12rpx;
width: 20rpx;
height: 2rpx;
background: #19d3be;
transform: rotate(45deg);
}
.mine-page__menu-icon--repair::after {
left: 10rpx;
top: 6rpx;
width: 10rpx;
height: 14rpx;
border: 2rpx solid #19d3be;
border-left: 0;
border-bottom: 0;
transform: rotate(45deg);
}
.mine-page__menu-icon--feedback::before {
inset: 4rpx;
border: 2rpx solid #19d3be;
border-radius: 50%;
}
.mine-page__menu-icon--feedback::after {
left: 12rpx;
top: 8rpx;
width: 2rpx;
height: 12rpx;
background: #19d3be;
box-shadow: 0 10rpx 0 #19d3be;
}
.mine-page__menu-icon--video::before {
inset: 5rpx 3rpx;
border: 2rpx solid #19d3be;
border-radius: 6rpx;
}
.mine-page__menu-icon--video::after {
top: 9rpx;
right: 7rpx;
width: 0;
height: 0;
border-top: 5rpx solid transparent;
border-bottom: 5rpx solid transparent;
border-left: 8rpx solid #19d3be;
}
.mine-page__menu-icon--follow::before {
left: 4rpx;
top: 8rpx;
width: 10rpx;
height: 16rpx;
border: 2rpx solid #19d3be;
border-right: 0;
border-radius: 12rpx 0 0 12rpx;
}
.mine-page__menu-icon--follow::after {
right: 4rpx;
top: 8rpx;
width: 10rpx;
height: 16rpx;
border: 2rpx solid #19d3be;
border-left: 0;
border-radius: 0 12rpx 12rpx 0;
}
.mine-page__menu-icon--version::before {
inset: 4rpx;
border: 2rpx solid #19d3be;
border-radius: 50%;
}
.mine-page__menu-icon--version::after {
left: 12rpx;
top: 8rpx;
width: 2rpx;
height: 8rpx;
background: #19d3be;
box-shadow: 0 12rpx 0 #19d3be;
}
.mine-page__menu-label {
flex: 1;
color: #edf2f7;
font-size: 30rpx;
}
.mine-page__menu-trailing {
display: flex;
align-items: center;
gap: 12rpx;
}
.mine-page__menu-value {
color: #707b92;
font-size: 24rpx;
}
.mine-page__menu-arrow {
color: #7d869d;
font-size: 26rpx;
}
.mine-page__tabbar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 5;
display: flex;
justify-content: space-around;
padding: 16rpx 24rpx calc(20rpx + env(safe-area-inset-bottom));
background: rgba(30, 35, 48, 0.98);
box-shadow: 0 -8rpx 24rpx rgba(4, 8, 20, 0.34);
}
.mine-page__tabbar-item {
display: flex;
flex-direction: column;
align-items: center;
min-width: 88rpx;
}
.mine-page__tabbar-icon {
position: relative;
width: 34rpx;
height: 34rpx;
margin-bottom: 8rpx;
border-radius: 10rpx;
border: 2rpx solid #8f97a9;
opacity: 0.86;
}
.mine-page__tabbar-icon::before,
.mine-page__tabbar-icon::after {
position: absolute;
content: "";
}
.mine-page__tabbar-icon::before {
left: 8rpx;
right: 8rpx;
top: 10rpx;
height: 2rpx;
background: #8f97a9;
}
.mine-page__tabbar-icon::after {
left: 8rpx;
right: 8rpx;
bottom: 10rpx;
height: 2rpx;
background: #8f97a9;
}
.mine-page__tabbar-icon--active {
border-color: #36e4aa;
background: rgba(54, 228, 170, 0.12);
}
.mine-page__tabbar-icon--active::before,
.mine-page__tabbar-icon--active::after {
background: #36e4aa;
}
.mine-page__tabbar-badge {
position: absolute;
top: -4rpx;
right: -4rpx;
width: 10rpx;
height: 10rpx;
border-radius: 50%;
background: #ff4d4f;
box-shadow: 0 0 0 4rpx rgba(30, 35, 48, 0.98);
}
.mine-page__tabbar-label {
color: #b0b6c4;
font-size: 20rpx;
}
.mine-page__tabbar-label--active {
color: #36e4aa;
}

180
src/pages/mine/index.tsx Normal file
View File

@@ -0,0 +1,180 @@
import { Text, View } from "@tarojs/components";
import Taro from "@tarojs/taro";
import type { CSSProperties } from "react";
import { useEffect, useState } from "react";
import "./index.scss";
type UserProfile = {
userName: string;
phone: string;
vip: boolean;
avatar: string;
deviceCount: number;
};
type FeatureItem = {
key: string;
label: string;
value?: string;
icon: string;
url?: string;
};
const userProfile: UserProfile = {
userName: "张天爱",
phone: "135****2598",
vip: true,
avatar: "",
deviceCount: 0
};
const featureItems: FeatureItem[] = [
{ key: "devices", label: "我的设备", value: "已绑定 0 台", icon: "device", url: "/pages/devices/index" },
{ key: "repair", label: "设备报修", icon: "repair", url: "/pages/repair/index" },
{ key: "feedback", label: "问题反馈", icon: "feedback", url: "/pages/feedback/index" },
{ key: "videos", label: "教学视频", icon: "video", url: "/pages/videos/index" },
{ key: "follow-us", label: "关注我们", icon: "follow", url: "/pages/follow-us/index" },
{ key: "version", label: "当前版本", value: "V1.0.2504.12", icon: "version" }
];
const tabItems = [
{ key: "home", label: "首页" },
{ key: "report", label: "报告" },
{ key: "assistant", label: "小e" },
{ key: "message", label: "消息", badge: true },
{ key: "mine", label: "我的", active: true }
];
export default function MinePage() {
const [topSafeHeight, setTopSafeHeight] = useState(0);
const [menuSafeWidth, setMenuSafeWidth] = useState(0);
useEffect(() => {
const windowInfo = typeof Taro.getWindowInfo === "function" ? Taro.getWindowInfo() : Taro.getSystemInfoSync();
const menuButtonRect =
typeof Taro.getMenuButtonBoundingClientRect === "function" ? Taro.getMenuButtonBoundingClientRect() : null;
const safeTop = menuButtonRect?.bottom || windowInfo.statusBarHeight || 0;
const safeRight = menuButtonRect ? windowInfo.windowWidth - menuButtonRect.left : 0;
setTopSafeHeight(safeTop);
setMenuSafeWidth(safeRight);
}, []);
const showToast = (title: string) => {
Taro.showToast({
title,
icon: "none"
});
};
const openPage = (url: string) => {
Taro.navigateTo({ url });
};
const handleFeatureClick = (item: FeatureItem) => {
if (item.url) {
openPage(item.url);
return;
}
showToast("当前已是最新版本");
};
const handleTabClick = (key: string, label: string) => {
if (key === "mine") {
return;
}
if (key === "home") {
const pages = Taro.getCurrentPages();
if (pages.length > 1) {
Taro.navigateBack();
} else {
Taro.redirectTo({ url: "/pages/index/index" });
}
return;
}
showToast(`${label}功能待接入`);
};
const pageStyle = {
"--top-safe-height": `${topSafeHeight}px`,
"--menu-safe-width": `${menuSafeWidth}px`
} as CSSProperties;
return (
<View className="mine-page" style={pageStyle}>
<View className="mine-page__halo mine-page__halo--large" />
<View className="mine-page__halo mine-page__halo--small" />
<View className="mine-page__header-card">
<View className="mine-page__header-main">
<View className="mine-page__avatar">
{userProfile.avatar ? (
<View className="mine-page__avatar-image" />
) : (
<View className="mine-page__avatar-placeholder">
<View className="mine-page__avatar-head" />
<View className="mine-page__avatar-body" />
</View>
)}
</View>
<View className="mine-page__identity">
<Text className="mine-page__name">{userProfile.userName}</Text>
<Text className="mine-page__phone">: {userProfile.phone}</Text>
<View className="mine-page__vip-row">
<Text className="mine-page__vip-badge">VIP</Text>
<Text className="mine-page__vip-text">{userProfile.vip ? "已开通VIP会员" : "暂未开通VIP会员"}</Text>
<Text className="mine-page__vip-count">0</Text>
</View>
</View>
</View>
<View className="mine-page__header-actions">
<View className="mine-page__icon-actions">
<View className="mine-page__circle-action mine-page__circle-action--support" onClick={() => openPage("/pages/support/index")} />
<View className="mine-page__circle-action mine-page__circle-action--settings" onClick={() => openPage("/pages/settings/index")} />
</View>
<Text className="mine-page__profile-link" onClick={() => openPage("/pages/profile/index")}>
</Text>
</View>
</View>
<View className="mine-page__menu-card">
{featureItems.map((item, index) => (
<View
className={`mine-page__menu-item ${index === 0 ? "mine-page__menu-item--first" : ""}`}
key={item.key}
onClick={() => handleFeatureClick(item)}
>
<View className={`mine-page__menu-icon mine-page__menu-icon--${item.icon}`} />
<Text className="mine-page__menu-label">{item.label}</Text>
<View className="mine-page__menu-trailing">
{item.value ? <Text className="mine-page__menu-value">{item.value}</Text> : null}
<Text className="mine-page__menu-arrow">&gt;</Text>
</View>
</View>
))}
</View>
<View className="mine-page__tabbar">
{tabItems.map((item) => (
<View className="mine-page__tabbar-item" key={item.key} onClick={() => handleTabClick(item.key, item.label)}>
<View className={`mine-page__tabbar-icon ${item.active ? "mine-page__tabbar-icon--active" : ""}`}>
{item.badge ? <View className="mine-page__tabbar-badge" /> : null}
</View>
<Text className={`mine-page__tabbar-label ${item.active ? "mine-page__tabbar-label--active" : ""}`}>{item.label}</Text>
</View>
))}
</View>
</View>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "个人信息"
});

View File

@@ -0,0 +1,3 @@
.profile-page {
display: block;
}

View File

@@ -0,0 +1,26 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "资料编辑",
items: [
{ label: "头像", value: "支持后续替换" },
{ label: "昵称", value: "张天爱" },
{ label: "手机号", value: "135****2598" },
{ label: "修改密码", value: "待接入" }
]
}
];
export default function ProfilePage() {
return (
<SecondaryPage
eyebrow="PROFILE"
title="个人信息"
description="这里先保留资料编辑骨架,后续接入真实账号体系时可以直接补上头像上传、昵称编辑和密码修改。"
sections={sections}
footerTip="当前页面以结构预留为主,暂不提交真实修改。"
/>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "设备报修"
});

View File

@@ -0,0 +1,3 @@
.repair-page {
display: block;
}

View File

@@ -0,0 +1,28 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "报修申请",
items: [
{ label: "提交报修申请" },
{ label: "上传故障图片", value: "待接入上传能力" },
{ label: "填写设备问题", value: "待接入表单" }
]
},
{
title: "售后进度",
items: [{ label: "维修进度查询", value: "后续接接口" }]
}
];
export default function RepairPage() {
return (
<SecondaryPage
eyebrow="REPAIR"
title="设备报修"
description="这个页面先把报修流程的主要节点放齐,后面接图片上传和工单接口时改动会比较小。"
sections={sections}
/>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "设置"
});

View File

@@ -0,0 +1,3 @@
.settings-page {
display: block;
}

View File

@@ -0,0 +1,31 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "通用设置",
items: [
{ label: "通知设置" },
{ label: "权限管理" },
{ label: "清理缓存" }
]
},
{
title: "账号相关",
items: [
{ label: "关于我们" },
{ label: "退出登录", value: "待二次确认" }
]
}
];
export default function SettingsPage() {
return (
<SecondaryPage
eyebrow="SETTINGS"
title="设置"
description="这里先把常见设置入口排好,后续如果接入通知、缓存和权限管理,就可以在这个页面继续细化。"
sections={sections}
/>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "帮助与客服"
});

View File

@@ -0,0 +1,3 @@
.support-page {
display: block;
}

View File

@@ -0,0 +1,24 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "客服入口",
items: [
{ label: "在线客服", value: "工作日 9:00 - 18:00" },
{ label: "联系售后", value: "支持提交工单" },
{ label: "帮助中心", value: "常见问题待补充" }
]
}
];
export default function SupportPage() {
return (
<SecondaryPage
eyebrow="SUPPORT"
title="帮助与客服"
description="耳机按钮先统一收口到这个页面,方便后面继续接客服系统、售后单据和帮助中心文章。"
sections={sections}
/>
);
}

View File

@@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: "教学视频"
});

View File

@@ -0,0 +1,3 @@
.videos-page {
display: block;
}

View File

@@ -0,0 +1,24 @@
import SecondaryPage, { type SecondaryPageSection } from "../../components/secondary-page";
import "./index.scss";
const sections: SecondaryPageSection[] = [
{
title: "视频分类",
items: [
{ label: "设备使用教程", value: "3 个占位视频" },
{ label: "安装教程", value: "2 个占位视频" },
{ label: "健康指导视频", value: "持续补充" }
]
}
];
export default function VideosPage() {
return (
<SecondaryPage
eyebrow="VIDEOS"
title="教学视频"
description="当前先用列表骨架占位,后续接视频封面、时长和播放页后就可以扩展成真正的视频中心。"
sections={sections}
/>
);
}