From a212e9f4122eba3c5ff257304aa7d7a23ccca88e Mon Sep 17 00:00:00 2001 From: czz <862977248@qq.com> Date: Thu, 7 May 2026 15:12:29 +0800 Subject: [PATCH] feat: update home empty state design --- README.md | 33 ++- src/app.scss | 20 +- src/pages/index/index.config.ts | 1 + src/pages/index/index.scss | 348 ++++++++++++++++++++++++++++---- src/pages/index/index.tsx | 107 +++++++--- 5 files changed, 418 insertions(+), 91 deletions(-) diff --git a/README.md b/README.md index c37a4e5..f0617c8 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,12 @@ 这是一个适合零基础开发者的 `Taro + React + TypeScript` 微信小程序项目模板。你后续会用 React 组件方式开发页面,再编译成微信小程序代码进行预览和发布。 +当前首页已经改成了一版“无数据状态”业务样式,方便你直接在这个基础上继续接真实接口和页面跳转。 + ## 1. 目前已经包含什么 - `Taro + React + TypeScript` 项目骨架 -- 首页 React 示例页面 +- 首页无数据状态业务示例页面 - 小程序 `AppID` 配置 - `AGENTS.md` 协作规则文件 - 从开发到发布的中文说明 @@ -154,7 +156,24 @@ npm run dev:weapp - [src/pages/index/index.scss](C:/Users/a/Documents/New%20project%203/src/pages/index/index.scss) 首页样式 -## 12. 你接下来最常做的开发动作 +## 12. 当前首页做了什么 + +现在首页已经不是默认演示页,而是一个更接近正式项目的静态业务首页,包含: + +- 顶部登录入口 +- 已关联设备数量展示 +- 两个主操作按钮 +- 绑定前提示卡片 +- 底部导航视觉样式 + +这些内容当前是静态演示结构,点击后会先弹出提示,方便你后续继续接: + +- 登录页 +- 扫码添加设备 +- 设备列表 +- 商城、我的等页面 + +## 13. 你接下来最常做的开发动作 ### 改页面文案和逻辑 @@ -183,7 +202,7 @@ src 然后记得在 [src/app.config.ts](C:/Users/a/Documents/New%20project%203/src/app.config.ts) 里注册页面路径。 -## 13. 本地预览与真机调试 +## 14. 本地预览与真机调试 ### 本地预览 @@ -197,7 +216,7 @@ src 3. 使用管理员或绑定开发者微信扫码 4. 在手机里查看效果 -## 14. 上传、提交审核和发布 +## 15. 上传、提交审核和发布 当你开发完成后,一般流程如下: @@ -215,7 +234,7 @@ npm run build:weapp 7. 提交审核 8. 审核通过后,点击发布 -## 15. 常见问题 +## 16. 常见问题 ### 1. `npm install` 失败怎么办 @@ -252,7 +271,7 @@ npm run build:weapp - HTTPS - 后台服务正常可访问 -## 16. 建议你下一步怎么做 +## 17. 建议你下一步怎么做 如果你是零基础,推荐按这个顺序继续: @@ -263,7 +282,7 @@ npm run build:weapp 5. 再学页面跳转 6. 最后接接口和发布 -## 17. 后续我可以继续帮你做什么 +## 18. 后续我可以继续帮你做什么 接下来你可以继续让我直接帮你: diff --git a/src/app.scss b/src/app.scss index 713b29b..7d16128 100644 --- a/src/app.scss +++ b/src/app.scss @@ -1,21 +1,5 @@ page { - background: #f6f7fb; - color: #1f2937; + background: #1b2130; + color: #f5f7fb; font-size: 32rpx; } - -.page { - min-height: 100vh; - padding: 40rpx 32rpx 60rpx; - box-sizing: border-box; - background: - radial-gradient(circle at top right, rgba(26, 173, 25, 0.15), transparent 26%), - linear-gradient(180deg, #f7fbf5 0%, #f6f7fb 100%); -} - -.card { - background: rgba(255, 255, 255, 0.96); - border-radius: 28rpx; - padding: 36rpx 32rpx; - box-shadow: 0 18rpx 48rpx rgba(15, 23, 42, 0.08); -} diff --git a/src/pages/index/index.config.ts b/src/pages/index/index.config.ts index d3a481b..dd4d51f 100644 --- a/src/pages/index/index.config.ts +++ b/src/pages/index/index.config.ts @@ -1,3 +1,4 @@ export default definePageConfig({ + navigationStyle: "custom", navigationBarTitleText: "首页" }); diff --git a/src/pages/index/index.scss b/src/pages/index/index.scss index 805cc48..9e92554 100644 --- a/src/pages/index/index.scss +++ b/src/pages/index/index.scss @@ -1,48 +1,322 @@ -.title { - display: block; - font-size: 46rpx; - font-weight: 700; - line-height: 1.4; - margin-bottom: 16rpx; - color: #0f172a; +.home-page { + position: relative; + min-height: 100vh; + padding: 24rpx 24rpx 148rpx; + box-sizing: border-box; + background: #1b2130; + overflow: hidden; } -.subtitle { - display: block; - font-size: 28rpx; - line-height: 1.8; - color: #475569; +.hero-bg { + position: absolute; + top: -54rpx; + right: -36rpx; + width: 340rpx; + height: 340rpx; + border-radius: 50%; + background: + radial-gradient(circle, rgba(67, 78, 109, 0.18) 0 30%, transparent 31% 47%, rgba(67, 78, 109, 0.12) 48% 66%, transparent 67%), + radial-gradient(circle at center, rgba(87, 212, 184, 0.12), transparent 70%); } -.section { - margin-top: 28rpx; +.home-header { + position: relative; + z-index: 1; + display: flex; + align-items: center; + margin-bottom: 26rpx; } -.section-title { - display: block; - font-size: 32rpx; - font-weight: 600; - margin-bottom: 14rpx; - color: #111827; -} - -.list-item { - margin-bottom: 12rpx; - line-height: 1.8; - color: #334155; -} - -.primary-btn { - margin-top: 28rpx; +.login-pill { + min-width: 94rpx; + height: 48rpx; + padding: 0 24rpx; border-radius: 999rpx; - background: linear-gradient(135deg, #1aad19 0%, #138a15 100%); + background: linear-gradient(90deg, #34e5b4 0%, #18c9b7 100%); color: #ffffff; - border: none; + font-size: 22rpx; + line-height: 48rpx; + text-align: center; + box-shadow: 0 10rpx 24rpx rgba(32, 214, 181, 0.24); } -.tip { - display: block; - margin-top: 20rpx; - font-size: 24rpx; - color: #64748b; +.device-summary { + position: relative; + z-index: 1; + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 22rpx; + color: #ffffff; +} + +.device-summary__content { + display: flex; + align-items: baseline; + gap: 10rpx; +} + +.device-summary__title { + font-size: 26rpx; + font-weight: 600; + color: #eff4ff; +} + +.device-summary__count { + font-size: 26rpx; + font-weight: 700; + color: #ff9d57; +} + +.device-summary__arrow { + font-size: 28rpx; + color: #7f889f; +} + +.action-card { + position: relative; + z-index: 1; + padding: 38rpx 30rpx 34rpx; + border-radius: 24rpx; + background: rgba(43, 49, 67, 0.94); + box-shadow: inset 0 0 0 2rpx rgba(255, 255, 255, 0.02); +} + +.action-button { + display: flex; + align-items: center; + justify-content: center; + height: 74rpx; + border-radius: 999rpx; + background: linear-gradient(90deg, #39e7aa 0%, #1cc9c1 100%); + box-shadow: 0 14rpx 26rpx rgba(20, 184, 166, 0.18); +} + +.action-button + .action-button { + margin-top: 34rpx; +} + +.action-button__icon { + position: relative; + width: 34rpx; + height: 34rpx; + margin-right: 16rpx; +} + +.action-button__icon-core { + position: absolute; + inset: 0; + border: 2rpx solid rgba(255, 255, 255, 0.95); + border-radius: 8rpx; +} + +.action-button__icon--scan .action-button__icon-core::before, +.action-button__icon--scan .action-button__icon-core::after, +.action-button__icon--tag .action-button__icon-core::before, +.action-button__icon--tag .action-button__icon-core::after { + position: absolute; + content: ""; +} + +.action-button__icon--scan .action-button__icon-core::before { + left: 6rpx; + right: 6rpx; + top: 14rpx; + height: 2rpx; + background: #ffffff; +} + +.action-button__icon--scan .action-button__icon-core::after { + top: 6rpx; + bottom: 6rpx; + left: 14rpx; + width: 2rpx; + background: #ffffff; +} + +.action-button__icon--tag .action-button__icon-core { + transform: rotate(45deg) scale(0.8); + border-radius: 6rpx; +} + +.action-button__icon--tag .action-button__icon-core::before { + top: 9rpx; + left: 9rpx; + width: 8rpx; + height: 8rpx; + border-radius: 50%; + background: #ffffff; +} + +.action-button__icon--tag .action-button__icon-core::after { + right: -7rpx; + top: 14rpx; + width: 10rpx; + height: 2rpx; + background: #ffffff; +} + +.action-button__label { + color: #ffffff; + font-size: 28rpx; + font-weight: 600; + letter-spacing: 1rpx; +} + +.notice-card { + position: relative; + z-index: 1; + margin-top: 22rpx; + padding: 22rpx 24rpx 24rpx; + border-radius: 22rpx; + background: #fbefc7; + color: #977244; + box-shadow: 0 12rpx 24rpx rgba(6, 10, 22, 0.14); +} + +.notice-card__title-row { + display: flex; + align-items: center; + margin-bottom: 10rpx; +} + +.notice-card__speaker { + position: relative; + width: 20rpx; + height: 16rpx; + margin-right: 12rpx; + border-radius: 4rpx; + background: #ff9d57; +} + +.notice-card__speaker::before, +.notice-card__speaker::after { + position: absolute; + content: ""; +} + +.notice-card__speaker::before { + right: -8rpx; + top: 2rpx; + width: 0; + height: 0; + border-top: 6rpx solid transparent; + border-bottom: 6rpx solid transparent; + border-left: 8rpx solid #ff9d57; +} + +.notice-card__speaker::after { + right: -16rpx; + top: 2rpx; + width: 8rpx; + height: 8rpx; + border-top: 2rpx solid #ff9d57; + border-right: 2rpx solid #ff9d57; + border-radius: 0 8rpx 0 0; + transform: rotate(45deg); +} + +.notice-card__title { + font-size: 22rpx; + font-weight: 600; + color: #af7e42; +} + +.notice-list { + display: flex; + flex-direction: column; + gap: 6rpx; +} + +.notice-item { + font-size: 22rpx; + line-height: 1.7; + color: #9f7a4c; +} + +.tab-bar { + position: fixed; + left: 0; + right: 0; + bottom: 0; + z-index: 5; + display: flex; + align-items: flex-start; + justify-content: space-around; + padding: 16rpx 24rpx calc(20rpx + env(safe-area-inset-bottom)); + background: rgba(31, 36, 49, 0.98); + box-shadow: 0 -8rpx 24rpx rgba(4, 8, 20, 0.34); +} + +.tab-item { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + min-width: 88rpx; +} + +.tab-item__icon { + position: relative; + width: 34rpx; + height: 34rpx; + margin-bottom: 8rpx; + border-radius: 10rpx; + border: 2rpx solid #8f97a9; + opacity: 0.86; +} + +.tab-item__icon::before, +.tab-item__icon::after { + position: absolute; + content: ""; +} + +.tab-item__icon::before { + left: 8rpx; + right: 8rpx; + top: 10rpx; + height: 2rpx; + background: currentColor; + color: #8f97a9; +} + +.tab-item__icon::after { + left: 8rpx; + right: 8rpx; + bottom: 10rpx; + height: 2rpx; + background: currentColor; + color: #8f97a9; +} + +.tab-item__icon--active { + border-color: #36e4aa; + background: rgba(54, 228, 170, 0.12); +} + +.tab-item__icon--active::before, +.tab-item__icon--active::after { + color: #36e4aa; +} + +.tab-item__badge { + position: absolute; + top: -4rpx; + right: -4rpx; + width: 10rpx; + height: 10rpx; + border-radius: 50%; + background: #ff4d4f; + box-shadow: 0 0 0 4rpx rgba(31, 36, 49, 0.98); +} + +.tab-item__label { + font-size: 20rpx; + color: #b0b6c4; + line-height: 1.2; +} + +.tab-item__label--active { + color: #36e4aa; } diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx index e42714d..b7ebf73 100644 --- a/src/pages/index/index.tsx +++ b/src/pages/index/index.tsx @@ -1,48 +1,97 @@ -import { useState } from "react"; -import { Button, Text, View } from "@tarojs/components"; +import { Text, View } from "@tarojs/components"; import Taro from "@tarojs/taro"; import "./index.scss"; -const steps = [ - "先执行 npm install 安装依赖", - "再执行 npm run dev:weapp 启动编译", - "用微信开发者工具打开当前项目", - "继续在 React 页面里开发你的业务" +const quickActions = [ + { + key: "scan", + icon: "scan", + label: "扫一扫 添加如新设备", + toast: "后续可以在这里接入扫码添加设备" + }, + { + key: "tag", + icon: "service", + label: "暂无捐赠所得的设备", + toast: "后续可以在这里展示捐赠设备" + } +]; + +const notices = [ + "1. 传感器是否上电成功,控制盒三绿灯状态。", + "2. 对APP进行蓝牙和位置(定位服务)授权。", + "3. 若使用扫一扫功能,请对摄像头进行授权。" +]; + +const navItems = [ + { key: "home", label: "首页", active: true }, + { key: "report", label: "报告", active: false }, + { key: "service", label: "小e", active: false }, + { key: "mall", label: "商城", active: false, badge: true }, + { key: "mine", label: "我的", active: false } ]; export default function Index() { - const [clicked, setClicked] = useState(false); - - const handleStart = () => { - setClicked(true); + const handleClick = (title: string) => { Taro.showToast({ - title: "开始开发吧", - icon: "success" + title, + icon: "none" }); }; return ( - - - 欢迎开始你的第一个 React 小程序 - - 这是一个基于 Taro、React 和 TypeScript 的微信小程序模板,后续你写页面时会更接近前端 React 开发方式。 - + + - - 推荐步骤 - {steps.map((item, index) => ( - - {index + 1}. {item} + + handleClick("登录功能待接入")}> + 登录 + + + + handleClick("设备列表页待接入")}> + + 已关联体征监测设备 + 0 + + > + + + + {quickActions.map((item) => ( + handleClick(item.toast)}> + + - ))} + {item.label} + + ))} + + + + + + 尊敬的用户您好!绑定前请注意以下几点。 - + + {notices.map((item) => ( + + {item} + + ))} + + - {clicked ? 按钮事件已经触发,说明 React 页面逻辑正常运行。 : null} + + {navItems.map((item) => ( + handleClick(`${item.label}功能待接入`)}> + + {item.badge ? : null} + + {item.label} + + ))} );