feat: update project structure and add new pages
- Changed the clone URL in README to point to the new webpack-taro-template. - Added 'mine' page to app configuration. - Enhanced index page styles and structure. - Created BottomNav component for navigation. - Added configuration and styles for the new 'mine' page. - Introduced navItems configuration for navigation. - Added AGENTS.md for project overview and development guidelines.
This commit is contained in:
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": ["taro/react"],
|
|
||||||
"rules": {
|
|
||||||
"react/jsx-uses-react": "off",
|
|
||||||
"react/react-in-jsx-scope": "off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ node_modules/
|
|||||||
.swc
|
.swc
|
||||||
*.local
|
*.local
|
||||||
.env*
|
.env*
|
||||||
|
taro-docs
|
||||||
121
AGENTS.md
Normal file
121
AGENTS.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
这是一个基于 **Taro 框架的多端小程序开发模板**项目。它提供了一个统一的开发框架,用于构建跨平台小程序,可以编译到微信、小红书、支付宝、百度、字节跳动、H5、React Native、QQ、京东等多个平台。
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- **框架**: Taro 4.1.11 (基于 React)
|
||||||
|
- **语言**: TypeScript 5.9.3
|
||||||
|
- **UI 框架**: React 18.3.1
|
||||||
|
- **构建工具**: Webpack 5.105.4
|
||||||
|
- **包管理器**: pnpm
|
||||||
|
|
||||||
|
## 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
taro-template/
|
||||||
|
├── src/ # 源代码目录
|
||||||
|
│ ├── app.ts # 应用入口组件
|
||||||
|
│ ├── app.config.ts # 应用全局配置
|
||||||
|
│ ├── app.css # 全局样式
|
||||||
|
│ ├── index.html # HTML 模板(用于 H5)
|
||||||
|
│ ├── components/ # 公共组件
|
||||||
|
│ │ └── BottomNav/ # 底部导航组件
|
||||||
|
│ ├── pages/ # 页面组件
|
||||||
|
│ │ ├── index/ # 首页
|
||||||
|
│ │ │ ├── index.tsx # 首页组件
|
||||||
|
│ │ │ ├── index.config.ts
|
||||||
|
│ │ │ └── index.css
|
||||||
|
│ │ ├── mine/ # 我的页面
|
||||||
|
│ │ │ ├── index.tsx
|
||||||
|
│ │ │ ├── index.config.ts
|
||||||
|
│ │ │ └── index.css
|
||||||
|
│ │ └── xhs/ # 小红书平台特定工具
|
||||||
|
│ │ └── utils/
|
||||||
|
│ │ └── is-xhs.ts
|
||||||
|
├── config/ # 构建配置
|
||||||
|
├── types/ # TypeScript 类型定义
|
||||||
|
├── project.xhs.json # 小红书 IDE 配置
|
||||||
|
├── project.config.json # 微信 IDE 配置
|
||||||
|
├── project.tt.json # 字节跳动 IDE 配置
|
||||||
|
├── tsconfig.json # TypeScript 配置
|
||||||
|
├── babel.config.js # Babel 配置
|
||||||
|
├── kevisual.json # Kevisual 平台配置
|
||||||
|
└── package.json # 项目依赖
|
||||||
|
```
|
||||||
|
|
||||||
|
## 开发指南
|
||||||
|
|
||||||
|
### 创建新页面
|
||||||
|
|
||||||
|
使用 Taro CLI 创建新页面:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run new -- [pageName]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 添加平台特定代码
|
||||||
|
|
||||||
|
使用 `Taro.getEnv()` 检测当前平台:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import Taro from "@tarojs/taro";
|
||||||
|
|
||||||
|
const env = Taro.getEnv();
|
||||||
|
if (env === Taro.ENV_TYPE.WEAPP) {
|
||||||
|
// 微信小程序特定代码
|
||||||
|
} else if (env === "xhs") {
|
||||||
|
// 小红书特定代码
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
或使用提供的工具函数:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { isXHS } from './pages/xhs/utils/is-xhs';
|
||||||
|
|
||||||
|
if (isXHS()) {
|
||||||
|
// 小红书特定代码
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 样式
|
||||||
|
|
||||||
|
项目使用标准 CSS,页面样式与组件放在一起:
|
||||||
|
|
||||||
|
- 全局样式: `src/app.css`
|
||||||
|
- 页面样式: `src/pages/{page}/{page}.css`
|
||||||
|
|
||||||
|
### 环境变量
|
||||||
|
|
||||||
|
- `.env.development` - 开发环境
|
||||||
|
- `.env.test` - 测试环境
|
||||||
|
- `.env.production` - 生产环境
|
||||||
|
|
||||||
|
## 配置文件说明
|
||||||
|
|
||||||
|
### app.config.ts
|
||||||
|
|
||||||
|
全局应用配置,包括页面注册、导航栏等。
|
||||||
|
|
||||||
|
### app.ts
|
||||||
|
|
||||||
|
应用入口组件,包含 `useLaunch` 生命周期钩子,用于应用初始化。在微信环境下会自动调用 `Taro.login`。
|
||||||
|
|
||||||
|
### project.xhs.json
|
||||||
|
|
||||||
|
小红书 IDE 特定配置(appid、编译设置等)。
|
||||||
|
|
||||||
|
### tsconfig.json
|
||||||
|
|
||||||
|
TypeScript 编译器选项,包括路径别名配置(`@/*` → `./src/*`)。
|
||||||
|
|
||||||
|
## AI 代理注意事项
|
||||||
|
|
||||||
|
1. 修改平台特定代码时,使用环境检测确保跨平台兼容性
|
||||||
|
2. 避免使用浏览器专用 API,应使用 Taro 提供的统一 API
|
||||||
|
3. 遵循现有的代码风格和目录结构
|
||||||
|
4. 添加新依赖时,确保与所有目标平台兼容
|
||||||
|
5. 项目使用 pnpm 作为包管理器
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"ignore": [
|
"ignore": [
|
||||||
".swc"
|
".swc"
|
||||||
],
|
],
|
||||||
"registry": "https://kevisual.cn/root/resources/ai/1.0.0/kevisual/mini/taro-template",
|
"registry": "https://kevisual.cn/root/resources/ai/1.0.0/kevisual/mini/webpack-taro-template",
|
||||||
"clone": {
|
"clone": {
|
||||||
".": {
|
".": {
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
"dev:rn": "npm run build:rn -- --watch",
|
"dev:rn": "npm run build:rn -- --watch",
|
||||||
"dev:qq": "npm run build:qq -- --watch",
|
"dev:qq": "npm run build:qq -- --watch",
|
||||||
"dev:jd": "npm run build:jd -- --watch",
|
"dev:jd": "npm run build:jd -- --watch",
|
||||||
"dev:harmony-hybrid": "npm run build:harmony-hybrid -- --watch"
|
"dev:harmony-hybrid": "npm run build:harmony-hybrid -- --watch",
|
||||||
|
"docs": "git clone --depth 1 git@github.com:NervJS/taro-docs.git taro-docs"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"defaults and fully supports es6-module",
|
"defaults and fully supports es6-module",
|
||||||
@@ -39,6 +40,8 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.28.6",
|
"@babel/runtime": "^7.28.6",
|
||||||
|
"@nutui/icons-react-taro": "3.0.2-cpp.3.beta.5",
|
||||||
|
"@nutui/nutui-react-taro": "^2.7.15",
|
||||||
"@tarojs/components": "4.1.11",
|
"@tarojs/components": "4.1.11",
|
||||||
"@tarojs/helper": "4.1.11",
|
"@tarojs/helper": "4.1.11",
|
||||||
"@tarojs/plugin-framework-react": "4.1.11",
|
"@tarojs/plugin-framework-react": "4.1.11",
|
||||||
@@ -71,8 +74,6 @@
|
|||||||
"@types/react": "^18.3.23",
|
"@types/react": "^18.3.23",
|
||||||
"@types/webpack-env": "^1.18.8",
|
"@types/webpack-env": "^1.18.8",
|
||||||
"babel-preset-taro": "4.1.11",
|
"babel-preset-taro": "4.1.11",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
|
||||||
"postcss": "^8.5.8",
|
"postcss": "^8.5.8",
|
||||||
"react-refresh": "^0.18.0",
|
"react-refresh": "^0.18.0",
|
||||||
"tsconfig-paths-webpack-plugin": "^4.2.0",
|
"tsconfig-paths-webpack-plugin": "^4.2.0",
|
||||||
|
|||||||
1203
pnpm-lock.yaml
generated
1203
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,5 +3,5 @@
|
|||||||
## clone
|
## clone
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ev sync clone -i https://kevisual.cn/root/resources/ai/1.0.0/kevisual/mini/taro-template/kevisual.json
|
ev sync clone -i https://kevisual.cn/root/resources/ai/1.0.0/kevisual/mini/webpack-taro-template/kevisual.json
|
||||||
```
|
```
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export default defineAppConfig({
|
export default defineAppConfig({
|
||||||
pages: [
|
pages: [
|
||||||
'pages/index/index'
|
'pages/index/index',
|
||||||
|
'pages/mine/index'
|
||||||
],
|
],
|
||||||
window: {
|
window: {
|
||||||
backgroundTextStyle: 'light',
|
backgroundTextStyle: 'light',
|
||||||
|
|||||||
37
src/components/BottomNav/index.css
Normal file
37
src/components/BottomNav/index.css
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
.bottom-nav {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 100px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-top: 1px solid #e8e8e8;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
z-index: 999;
|
||||||
|
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-nav-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.bottom-nav-label {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #9e9e9e;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-nav-item.active .bottom-nav-label {
|
||||||
|
color: #1976d2;
|
||||||
|
}
|
||||||
42
src/components/BottomNav/index.tsx
Normal file
42
src/components/BottomNav/index.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { View, Text } from "@tarojs/components";
|
||||||
|
import Taro from "@tarojs/taro";
|
||||||
|
import type { NavItem, NavKey } from "../../config";
|
||||||
|
import "./index.css";
|
||||||
|
|
||||||
|
const ACTIVE_COLOR = "#1976d2";
|
||||||
|
const DEFAULT_COLOR = "#9e9e9e";
|
||||||
|
const ICON_SIZE = 24;
|
||||||
|
|
||||||
|
interface BottomNavProps {
|
||||||
|
active: NavKey;
|
||||||
|
navItems: NavItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BottomNav({ active, navItems }: BottomNavProps) {
|
||||||
|
const handleNavigate = (item: NavItem) => {
|
||||||
|
if (item.key === active) return;
|
||||||
|
Taro.redirectTo({ url: item.path });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className="bottom-nav">
|
||||||
|
{navItems.map((item) => {
|
||||||
|
const isActive = active === item.key;
|
||||||
|
const IconComp = item.icon;
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
key={item.key}
|
||||||
|
className={`bottom-nav-item${isActive ? " active" : ""}`}
|
||||||
|
onClick={() => handleNavigate(item)}
|
||||||
|
>
|
||||||
|
<IconComp
|
||||||
|
size={ICON_SIZE}
|
||||||
|
color={isActive ? ACTIVE_COLOR : DEFAULT_COLOR}
|
||||||
|
/>
|
||||||
|
<Text className="bottom-nav-label">{item.label}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
26
src/config.tsx
Normal file
26
src/config.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Home, User } from "@nutui/icons-react-taro";
|
||||||
|
import type { ComponentType } from "react";
|
||||||
|
|
||||||
|
export type NavKey = string;
|
||||||
|
|
||||||
|
export interface NavItem {
|
||||||
|
key: NavKey;
|
||||||
|
label: string;
|
||||||
|
path: string;
|
||||||
|
icon: ComponentType<{ size?: string | number; color?: string }>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const navItems: NavItem[] = [
|
||||||
|
{
|
||||||
|
key: "index",
|
||||||
|
label: "主页",
|
||||||
|
path: "/pages/index/index",
|
||||||
|
icon: Home,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "mine",
|
||||||
|
label: "我的",
|
||||||
|
path: "/pages/mine/index",
|
||||||
|
icon: User,
|
||||||
|
},
|
||||||
|
];
|
||||||
@@ -5,3 +5,23 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.index {
|
||||||
|
height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding-top: 80px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { View, Text, Button } from "@tarojs/components";
|
import { View, Text, Button } from "@tarojs/components";
|
||||||
import { useLoad } from "@tarojs/taro";
|
import { useLoad } from "@tarojs/taro";
|
||||||
|
import BottomNav from "../../components/BottomNav";
|
||||||
|
import { navItems } from "../../config";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
@@ -9,6 +11,7 @@ export default function Index() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View className="index">
|
<View className="index">
|
||||||
|
<View className="index-content">
|
||||||
<Text>Hello world!</Text>
|
<Text>Hello world!</Text>
|
||||||
<Button
|
<Button
|
||||||
openType="getUserInfo"
|
openType="getUserInfo"
|
||||||
@@ -19,5 +22,7 @@ export default function Index() {
|
|||||||
User Info
|
User Info
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
<BottomNav active="index" navItems={navItems} />
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
3
src/pages/mine/index.config.ts
Normal file
3
src/pages/mine/index.config.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export default definePageConfig({
|
||||||
|
navigationBarTitleText: "我的",
|
||||||
|
});
|
||||||
31
src/pages/mine/index.css
Normal file
31
src/pages/mine/index.css
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
.mine-page {
|
||||||
|
height: 100vh;
|
||||||
|
background: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 80px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-avatar {
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
border-radius: 60px;
|
||||||
|
background: #1976d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-name {
|
||||||
|
font-size: 32px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
16
src/pages/mine/index.tsx
Normal file
16
src/pages/mine/index.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { View, Text } from "@tarojs/components";
|
||||||
|
import BottomNav from "../../components/BottomNav";
|
||||||
|
import { navItems } from "../../config";
|
||||||
|
import "./index.css";
|
||||||
|
|
||||||
|
export default function Mine() {
|
||||||
|
return (
|
||||||
|
<View className="mine-page">
|
||||||
|
<View className="mine-content">
|
||||||
|
<View className="mine-avatar" />
|
||||||
|
<Text className="mine-name">用户昵称</Text>
|
||||||
|
</View>
|
||||||
|
<BottomNav active="mine" navItems={navItems} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user