@coze-arch/cli 0.0.1-alpha.b6f2c1 → 0.0.1-alpha.bd5b49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__templates__/expo/.cozeproj/scripts/dev_run.sh +30 -21
- package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +2 -2
- package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +2 -2
- package/lib/__templates__/expo/.cozeproj/scripts/server_dev_run.sh +21 -2
- package/lib/__templates__/expo/README.md +15 -37
- package/lib/__templates__/expo/client/app/+not-found.tsx +15 -0
- package/lib/__templates__/expo/client/app/_layout.tsx +14 -12
- package/lib/__templates__/expo/client/app.config.ts +2 -2
- package/lib/__templates__/expo/client/components/Screen.tsx +1 -17
- package/lib/__templates__/expo/client/components/ThemedView.tsx +1 -2
- package/lib/__templates__/expo/client/declarations.d.ts +5 -0
- package/lib/__templates__/expo/client/eslint.config.mjs +33 -10
- package/lib/__templates__/expo/client/global.css +78 -0
- package/lib/__templates__/expo/client/hooks/useSafeRouter.ts +152 -0
- package/lib/__templates__/expo/client/metro.config.js +8 -1
- package/lib/__templates__/expo/client/package.json +37 -33
- package/lib/__templates__/expo/client/screens/demo/index.tsx +6 -12
- package/lib/__templates__/expo/client/scripts/install-missing-deps.js +1 -0
- package/lib/__templates__/expo/client/styles.css +263 -0
- package/lib/__templates__/expo/client/uniwind-types.d.ts +10 -0
- package/lib/__templates__/expo/client/utils/index.ts +22 -0
- package/lib/__templates__/expo/eslint-plugins/fontawesome6/index.js +9 -0
- package/lib/__templates__/expo/eslint-plugins/fontawesome6/names.js +1889 -0
- package/lib/__templates__/expo/eslint-plugins/fontawesome6/rule.js +174 -0
- package/lib/__templates__/expo/eslint-plugins/fontawesome6/v5-only-names.js +388 -0
- package/lib/__templates__/expo/eslint-plugins/react-native/index.js +9 -0
- package/lib/__templates__/expo/eslint-plugins/react-native/rule.js +64 -0
- package/lib/__templates__/expo/eslint-plugins/reanimated/index.js +9 -0
- package/lib/__templates__/expo/eslint-plugins/reanimated/rule.js +88 -0
- package/lib/__templates__/expo/package.json +3 -0
- package/lib/__templates__/expo/patches/expo@54.0.33.patch +45 -0
- package/lib/__templates__/expo/pnpm-lock.yaml +1318 -2636
- package/lib/__templates__/expo/server/build.js +21 -0
- package/lib/__templates__/expo/server/package.json +9 -7
- package/lib/__templates__/expo/server/src/index.ts +3 -1
- package/lib/__templates__/expo/server/tsconfig.json +2 -2
- package/lib/__templates__/expo/template.config.js +56 -0
- package/lib/__templates__/nextjs/.babelrc +15 -0
- package/lib/__templates__/nextjs/next.config.ts +2 -2
- package/lib/__templates__/nextjs/package.json +11 -1
- package/lib/__templates__/nextjs/pnpm-lock.yaml +2701 -1813
- package/lib/__templates__/nextjs/src/app/layout.tsx +5 -3
- package/lib/__templates__/nextjs/src/app/page.tsx +17 -59
- package/lib/__templates__/nextjs/template.config.js +47 -12
- package/lib/__templates__/taro/.coze +14 -0
- package/lib/__templates__/taro/.cozeproj/scripts/deploy_build.sh +19 -0
- package/lib/__templates__/taro/.cozeproj/scripts/deploy_run.sh +14 -0
- package/lib/__templates__/taro/.cozeproj/scripts/dev_build.sh +2 -0
- package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +80 -0
- package/lib/__templates__/taro/.cozeproj/scripts/init_env.sh +5 -0
- package/lib/__templates__/taro/.cozeproj/scripts/pack.sh +1 -0
- package/lib/__templates__/taro/README.md +747 -0
- package/lib/__templates__/taro/_gitignore +40 -0
- package/lib/__templates__/taro/_npmrc +18 -0
- package/lib/__templates__/taro/babel.config.js +12 -0
- package/lib/__templates__/taro/config/dev.ts +9 -0
- package/lib/__templates__/taro/config/index.ts +173 -0
- package/lib/__templates__/taro/config/prod.ts +35 -0
- package/lib/__templates__/taro/eslint.config.mjs +57 -0
- package/lib/__templates__/taro/key/private.appid.key +0 -0
- package/lib/__templates__/taro/package.json +97 -0
- package/lib/__templates__/taro/pnpm-lock.yaml +22708 -0
- package/lib/__templates__/taro/pnpm-workspace.yaml +2 -0
- package/lib/__templates__/taro/project.config.json +15 -0
- package/lib/__templates__/taro/server/nest-cli.json +10 -0
- package/lib/__templates__/taro/server/package.json +41 -0
- package/lib/__templates__/taro/server/src/app.controller.ts +23 -0
- package/lib/__templates__/taro/server/src/app.module.ts +10 -0
- package/lib/__templates__/taro/server/src/app.service.ts +8 -0
- package/lib/__templates__/taro/server/src/interceptors/http-status.interceptor.ts +23 -0
- package/lib/__templates__/taro/server/src/main.ts +49 -0
- package/lib/__templates__/taro/server/tsconfig.json +24 -0
- package/lib/__templates__/taro/src/app.config.ts +11 -0
- package/lib/__templates__/taro/src/app.css +52 -0
- package/lib/__templates__/taro/src/app.ts +14 -0
- package/lib/__templates__/taro/src/index.html +39 -0
- package/lib/__templates__/taro/src/network.ts +39 -0
- package/lib/__templates__/taro/src/pages/index/index.config.ts +3 -0
- package/lib/__templates__/taro/src/pages/index/index.css +1 -0
- package/lib/__templates__/taro/src/pages/index/index.tsx +33 -0
- package/lib/__templates__/taro/src/utils/h5-styles.ts +33 -0
- package/lib/__templates__/taro/src/utils/wx-debug.ts +23 -0
- package/lib/__templates__/taro/stylelint.config.mjs +4 -0
- package/lib/__templates__/taro/template.config.js +68 -0
- package/lib/__templates__/taro/tsconfig.json +29 -0
- package/lib/__templates__/taro/types/global.d.ts +32 -0
- package/lib/__templates__/templates.json +32 -0
- package/lib/__templates__/vite/package.json +10 -1
- package/lib/__templates__/vite/pnpm-lock.yaml +350 -2341
- package/lib/__templates__/vite/src/main.ts +17 -48
- package/lib/__templates__/vite/template.config.js +47 -10
- package/lib/cli.js +830 -129
- package/package.json +1 -1
- package/lib/__templates__/expo/client/app/demo.tsx +0 -1
- package/lib/__templates__/expo/client/constants/theme.ts +0 -854
- package/lib/__templates__/expo/client/hooks/useColorScheme.ts +0 -34
- package/lib/__templates__/expo/client/hooks/useTheme.ts +0 -13
- package/lib/__templates__/expo/client/screens/demo/styles.ts +0 -28
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
1
|
+
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
2
2
|
PREVIEW_DIR="${COZE_PREVIEW_DIR:-/source/preview}"
|
|
3
3
|
LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
|
|
4
|
-
|
|
4
|
+
LOG_CLIENT_FILE="$LOG_DIR/client.log"
|
|
5
5
|
mkdir -p "$LOG_DIR"
|
|
6
6
|
|
|
7
7
|
# ==================== 配置项 ====================
|
|
@@ -15,13 +15,14 @@ EXPO_PORT="5000"
|
|
|
15
15
|
WEB_URL="${COZE_PROJECT_DOMAIN_DEFAULT:-http://127.0.0.1:${SERVER_PORT}}"
|
|
16
16
|
ASSUME_YES="1"
|
|
17
17
|
EXPO_PUBLIC_BACKEND_BASE_URL="${EXPO_PUBLIC_BACKEND_BASE_URL:-$WEB_URL}"
|
|
18
|
-
|
|
18
|
+
EXPO_PUBLIC_COZE_PROJECT_ID="${COZE_PROJECT_ID:-}"
|
|
19
19
|
|
|
20
20
|
EXPO_PACKAGER_PROXY_URL="${EXPO_PUBLIC_BACKEND_BASE_URL}"
|
|
21
|
-
export EXPO_PUBLIC_BACKEND_BASE_URL EXPO_PACKAGER_PROXY_URL
|
|
21
|
+
export EXPO_PUBLIC_BACKEND_BASE_URL EXPO_PACKAGER_PROXY_URL EXPO_PUBLIC_COZE_PROJECT_ID
|
|
22
22
|
# 运行时变量(为避免 set -u 的未绑定错误,预置为空)
|
|
23
23
|
SERVER_PID=""
|
|
24
24
|
EXPO_PID=""
|
|
25
|
+
|
|
25
26
|
# ==================== 工具函数 ====================
|
|
26
27
|
check_command() {
|
|
27
28
|
if ! command -v "$1" &> /dev/null; then
|
|
@@ -88,14 +89,17 @@ ensure_port() {
|
|
|
88
89
|
pipe_to_log() {
|
|
89
90
|
local source="${1:-CLIENT}"
|
|
90
91
|
local raw_log="${2:-}"
|
|
91
|
-
local line timestamp
|
|
92
|
+
local line clean_line timestamp
|
|
92
93
|
while IFS= read -r line || [ -n "$line" ]; do
|
|
94
|
+
clean_line=$(printf '%s' "$line" | sed 's/\x1b\[[0-9;]*[mA-Za-z]//g')
|
|
95
|
+
if echo "$clean_line" | grep -qE '(^(Web|iOS|Android) node_modules/.*expo-router.*entry\.js.*%|^(Web|iOS|Android) Bundled [0-9]+ms node_modules/.*expo-router.*entry\.js|Logs will appear in the browser)'; then
|
|
96
|
+
continue
|
|
97
|
+
fi
|
|
93
98
|
if [ -n "$raw_log" ]; then
|
|
94
|
-
|
|
99
|
+
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
100
|
+
echo "[$timestamp] $clean_line" >> "$raw_log"
|
|
95
101
|
fi
|
|
96
|
-
|
|
97
|
-
msg="${line}"
|
|
98
|
-
echo "$msg"
|
|
102
|
+
printf '[%s] %s\n' "$source" "$clean_line"
|
|
99
103
|
done
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -111,14 +115,14 @@ wait_port_connectable() {
|
|
|
111
115
|
start_expo() {
|
|
112
116
|
local offline="${1:-0}"
|
|
113
117
|
|
|
114
|
-
pushd
|
|
118
|
+
pushd "$ROOT_DIR/client"
|
|
115
119
|
|
|
116
120
|
if [ "$offline" = "1" ]; then
|
|
117
|
-
( EXPO_OFFLINE=1
|
|
118
|
-
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "
|
|
121
|
+
( EXPO_OFFLINE=1 EXPO_NO_DEPENDENCY_VALIDATION=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" EXPO_PUBLIC_COZE_PROJECT_ID="$EXPO_PUBLIC_COZE_PROJECT_ID" \
|
|
122
|
+
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$LOG_CLIENT_FILE" ) &
|
|
119
123
|
else
|
|
120
|
-
(
|
|
121
|
-
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "
|
|
124
|
+
( EXPO_NO_DEPENDENCY_VALIDATION=1 EXPO_PUBLIC_BACKEND_BASE_URL="$EXPO_PUBLIC_BACKEND_BASE_URL" EXPO_PACKAGER_PROXY_URL="$EXPO_PACKAGER_PROXY_URL" EXPO_PUBLIC_COZE_PROJECT_ID="$EXPO_PUBLIC_COZE_PROJECT_ID" \
|
|
125
|
+
nohup npx expo start --clear --port "$EXPO_PORT" 2>&1 | pipe_to_log "CLIENT" "$LOG_CLIENT_FILE" ) &
|
|
122
126
|
fi
|
|
123
127
|
EXPO_PID=$!
|
|
124
128
|
disown $EXPO_PID 2>/dev/null || true
|
|
@@ -129,9 +133,9 @@ start_expo() {
|
|
|
129
133
|
detect_expo_fetch_failed() {
|
|
130
134
|
local timeout="${1:-8}"
|
|
131
135
|
local waited=0
|
|
132
|
-
local log_file="
|
|
136
|
+
local log_file="$LOG_CLIENT_FILE"
|
|
133
137
|
while [ "$waited" -lt "$timeout" ]; do
|
|
134
|
-
if [ -f "$log_file" ] &&
|
|
138
|
+
if [ -f "$log_file" ] && tail -n 100 "$log_file" 2>/dev/null | grep -q "TypeError: fetch failed"; then
|
|
135
139
|
return 0
|
|
136
140
|
fi
|
|
137
141
|
sleep 1
|
|
@@ -150,6 +154,12 @@ if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
|
|
|
150
154
|
python "$PREVIEW_DIR/pre_install.py" || echo "pre_install.py 执行失败"
|
|
151
155
|
fi
|
|
152
156
|
|
|
157
|
+
echo "检查根目录 post_install.py"
|
|
158
|
+
if [ -f "$PREVIEW_DIR/post_install.py" ]; then
|
|
159
|
+
echo "执行:python $PREVIEW_DIR/post_install.py"
|
|
160
|
+
python "$PREVIEW_DIR/post_install.py" || echo "post_install.py 执行失败"
|
|
161
|
+
fi
|
|
162
|
+
|
|
153
163
|
echo "==================== 开始启动 ===================="
|
|
154
164
|
echo "开始执行服务启动脚本(start_dev.sh)..."
|
|
155
165
|
echo "正在检查依赖命令和目录是否存在..."
|
|
@@ -159,15 +169,13 @@ check_command "pnpm"
|
|
|
159
169
|
check_command "lsof"
|
|
160
170
|
check_command "bash"
|
|
161
171
|
|
|
162
|
-
echo "准备日志目录:logs"
|
|
163
|
-
mkdir -p logs
|
|
164
172
|
# 端口占用预检查与处理
|
|
165
173
|
ensure_port SERVER_PORT "$SERVER_PORT"
|
|
166
174
|
ensure_port EXPO_PORT "$EXPO_PORT"
|
|
167
175
|
|
|
168
176
|
echo "==================== 启动 server 服务 ===================="
|
|
169
|
-
echo "正在执行:
|
|
170
|
-
(
|
|
177
|
+
echo "正在执行:pnpm run dev (server)"
|
|
178
|
+
( pushd "$ROOT_DIR/server" > /dev/null && SERVER_PORT="$SERVER_PORT" nohup pnpm run dev; popd > /dev/null ) &
|
|
171
179
|
SERVER_PID=$!
|
|
172
180
|
disown $SERVER_PID 2>/dev/null || true
|
|
173
181
|
if [ -z "${SERVER_PID}" ]; then
|
|
@@ -181,13 +189,14 @@ start_expo 0
|
|
|
181
189
|
if detect_expo_fetch_failed 8; then
|
|
182
190
|
echo "Expo 启动检测到网络错误:TypeError: fetch failed,启用离线模式重试"
|
|
183
191
|
if [ -n "${EXPO_PID}" ]; then kill -9 "$EXPO_PID" 2>/dev/null || true; fi
|
|
184
|
-
: > logs/client.log
|
|
192
|
+
: > "$ROOT_DIR/logs/client.log"
|
|
185
193
|
start_expo 1
|
|
186
194
|
fi
|
|
187
195
|
# 输出以下环境变量,确保 Expo 项目能正确连接到 Server 服务
|
|
188
196
|
echo "Expo 环境变量配置:"
|
|
189
197
|
echo "EXPO_PUBLIC_BACKEND_BASE_URL=${EXPO_PUBLIC_BACKEND_BASE_URL}"
|
|
190
198
|
echo "EXPO_PACKAGER_PROXY_URL=${EXPO_PACKAGER_PROXY_URL}"
|
|
199
|
+
echo "EXPO_PUBLIC_COZE_PROJECT_ID=${EXPO_PUBLIC_COZE_PROJECT_ID}"
|
|
191
200
|
if [ -z "${EXPO_PID}" ]; then
|
|
192
201
|
echo "无法获取 Expo 后台进程 PID"
|
|
193
202
|
fi
|
|
@@ -40,8 +40,8 @@ fi
|
|
|
40
40
|
info "==================== 依赖安装完成!====================\n"
|
|
41
41
|
|
|
42
42
|
info "==================== dist打包 ===================="
|
|
43
|
-
info "开始执行:
|
|
44
|
-
(
|
|
43
|
+
info "开始执行:pnpm run build (server)"
|
|
44
|
+
(pushd "$ROOT_DIR/server" > /dev/null && pnpm run build; popd > /dev/null) || error "dist打包失败"
|
|
45
45
|
info "==================== dist打包完成!====================\n"
|
|
46
46
|
|
|
47
47
|
info "下一步:执行 ./prod_run.sh 启动服务"
|
|
@@ -29,6 +29,6 @@ check_command() {
|
|
|
29
29
|
check_command "pnpm"
|
|
30
30
|
check_command "npm"
|
|
31
31
|
|
|
32
|
-
info "开始执行:
|
|
33
|
-
(
|
|
32
|
+
info "开始执行:pnpm run start (server)"
|
|
33
|
+
(pushd "$ROOT_DIR/server" > /dev/null && PORT="$PORT" pnpm run start; popd > /dev/null) || error "服务启动失败"
|
|
34
34
|
info "服务启动完成!\n"
|
|
@@ -2,7 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
4
4
|
SERVER_DIR="$ROOT_DIR/server"
|
|
5
|
-
|
|
5
|
+
LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
|
|
6
|
+
LOG_SERVER_FILE="$LOG_DIR/server.log"
|
|
7
|
+
SERVER_PORT="${SERVER_PORT:-9091}"
|
|
8
|
+
|
|
9
|
+
mkdir -p "$LOG_DIR"
|
|
10
|
+
|
|
11
|
+
pipe_to_log() {
|
|
12
|
+
local source="${1:-SERVER}"
|
|
13
|
+
local raw_log="${2:-}"
|
|
14
|
+
local line clean_line timestamp
|
|
15
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
16
|
+
clean_line=$(printf '%s' "$line" | sed 's/\x1b\[[0-9;]*[mA-Za-z]//g')
|
|
17
|
+
if [ -n "$raw_log" ]; then
|
|
18
|
+
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
19
|
+
echo "[$timestamp] $clean_line" >> "$raw_log"
|
|
20
|
+
fi
|
|
21
|
+
printf '[%s] %s\n' "$source" "$clean_line"
|
|
22
|
+
done
|
|
23
|
+
}
|
|
6
24
|
|
|
7
25
|
kill_old_server() {
|
|
8
26
|
if command -v lsof &> /dev/null; then
|
|
@@ -19,9 +37,10 @@ kill_old_server() {
|
|
|
19
37
|
echo "==================== Server Dev Run ===================="
|
|
20
38
|
echo "Server 目录:$SERVER_DIR"
|
|
21
39
|
echo "Server 端口:$SERVER_PORT"
|
|
40
|
+
echo "日志文件:$LOG_SERVER_FILE"
|
|
22
41
|
|
|
23
42
|
kill_old_server
|
|
24
43
|
|
|
25
44
|
echo "启动 server 服务..."
|
|
26
45
|
cd "$SERVER_DIR"
|
|
27
|
-
NODE_ENV=development PORT="$SERVER_PORT" npx tsx ./src/index.ts
|
|
46
|
+
NODE_ENV=development PORT="$SERVER_PORT" npx tsx watch ./src/index.ts 2>&1 | pipe_to_log "SERVER" "$LOG_SERVER_FILE"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Expo App + Express.js
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 目录结构规范
|
|
4
4
|
|
|
5
5
|
当前仓库是一个 monorepo(基于 pnpm 的 workspace)
|
|
6
6
|
|
|
@@ -15,23 +15,31 @@
|
|
|
15
15
|
| └── package.json # 服务端 package.json
|
|
16
16
|
├── client/ # React Native 前端代码
|
|
17
17
|
│ ├── app/ # Expo Router 路由目录(仅路由配置)
|
|
18
|
-
│ │ ├── _layout.tsx #
|
|
19
|
-
│ │
|
|
20
|
-
│ │ └── index.tsx # re-export home.tsx
|
|
18
|
+
│ │ ├── _layout.tsx # 根布局文件(必需,务必阅读)
|
|
19
|
+
│ │ └── index.tsx # 首页
|
|
21
20
|
│ ├── screens/ # 页面实现目录(与 app/ 路由对应)
|
|
22
|
-
│ │ └──
|
|
23
|
-
│ │
|
|
24
|
-
│ │ └── styles.ts # 页面样式
|
|
21
|
+
│ │ └── demo/
|
|
22
|
+
│ │ └── index.tsx # demo 示例页面(默认首页,不需要可以删除,记得同时更新路由文件)
|
|
25
23
|
│ ├── components/ # 可复用组件
|
|
26
24
|
│ │ └── Screen.tsx # 页面容器组件(必用)
|
|
27
25
|
│ ├── hooks/ # 自定义 Hooks
|
|
28
26
|
│ ├── contexts/ # React Context 代码
|
|
27
|
+
│ ├── utils/ # 工具函数
|
|
29
28
|
│ ├── assets/ # 静态资源
|
|
30
29
|
| └── package.json # Expo 应用 package.json
|
|
31
30
|
├── package.json
|
|
32
31
|
├── .cozeproj # 预置脚手架脚本(禁止修改)
|
|
33
32
|
└── .coze # 配置文件(禁止修改)
|
|
34
33
|
|
|
34
|
+
## 技术选型(严格遵循)
|
|
35
|
+
|
|
36
|
+
- 前端:Expo + React Native + TailwindCSS
|
|
37
|
+
- 后端:Express.js
|
|
38
|
+
|
|
39
|
+
本项目通过 uniwind 实现了 react-native 对 TailwindCSS v4 的支持,在编写样式时应使用 TailwindCSS 写法
|
|
40
|
+
|
|
41
|
+
在开始开发前,先查看 client/global.css 了解必要的信息
|
|
42
|
+
|
|
35
43
|
## 安装依赖
|
|
36
44
|
|
|
37
45
|
### 命令
|
|
@@ -40,15 +48,6 @@
|
|
|
40
48
|
pnpm i
|
|
41
49
|
```
|
|
42
50
|
|
|
43
|
-
### 新增依赖约束
|
|
44
|
-
|
|
45
|
-
如果需要新增依赖,需在 client 和 server 各自的目录添加(原因:隔离前后端的依赖),禁止在根目录直接安装依赖
|
|
46
|
-
|
|
47
|
-
### 新增依赖标准流程
|
|
48
|
-
|
|
49
|
-
- 编辑 `client/package.json` 或 `server/package.json`
|
|
50
|
-
- 在根目录执行 `pnpm i`
|
|
51
|
-
|
|
52
51
|
## Expo 开发规范
|
|
53
52
|
|
|
54
53
|
### 路径别名
|
|
@@ -63,27 +62,6 @@ import { Screen } from '@/components/Screen';
|
|
|
63
62
|
import { Screen } from '../../../components/Screen';
|
|
64
63
|
```
|
|
65
64
|
|
|
66
|
-
## Server 开发规范
|
|
67
|
-
|
|
68
|
-
服务端是一个 Node.js 项目,基于 ESM 规范开发,在引用相对路径时,需要加上明确的后缀名
|
|
69
|
-
|
|
70
|
-
错误的做法
|
|
71
|
-
|
|
72
|
-
```ts
|
|
73
|
-
import file from './file'
|
|
74
|
-
import folder from './folder'
|
|
75
|
-
import isoWeek from 'dayjs/plugin/isoWeek'
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
正确的做法
|
|
79
|
-
|
|
80
|
-
```ts
|
|
81
|
-
import file from './file.ts'
|
|
82
|
-
import folder from './folder/index.ts'
|
|
83
|
-
// 如果是来自 npm 包某个具体路径的引用,如果实际路径为 .js,则使用 .js 后缀
|
|
84
|
-
import isoWeek from 'dayjs/plugin/isoWeek.js'
|
|
85
|
-
```
|
|
86
|
-
|
|
87
65
|
## 本地开发
|
|
88
66
|
|
|
89
67
|
运行 coze dev 可以同时启动前端和后端服务,如果端口已占用,该命令会先杀掉占用端口的进程再启动,也可以用来重启前端和后端服务
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { View, Text } from 'react-native';
|
|
2
|
+
import { Link } from 'expo-router';
|
|
3
|
+
|
|
4
|
+
export default function NotFoundScreen() {
|
|
5
|
+
return (
|
|
6
|
+
<View className="flex-1 justify-center items-center bg-background">
|
|
7
|
+
<Text className="text-foreground">
|
|
8
|
+
页面不存在
|
|
9
|
+
</Text>
|
|
10
|
+
<Link href="/" className="text-accent mt-6">
|
|
11
|
+
返回首页
|
|
12
|
+
</Link>
|
|
13
|
+
</View>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -6,6 +6,8 @@ import { LogBox } from 'react-native';
|
|
|
6
6
|
import Toast from 'react-native-toast-message';
|
|
7
7
|
import { AuthProvider } from "@/contexts/AuthContext";
|
|
8
8
|
|
|
9
|
+
import '../global.css';
|
|
10
|
+
|
|
9
11
|
LogBox.ignoreLogs([
|
|
10
12
|
"TurboModuleRegistry.getEnforcing(...): 'RNMapsAirModule' could not be found",
|
|
11
13
|
// 添加其它想暂时忽略的错误或警告信息
|
|
@@ -15,18 +17,18 @@ export default function RootLayout() {
|
|
|
15
17
|
return (
|
|
16
18
|
<AuthProvider>
|
|
17
19
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
<StatusBar style="dark"></StatusBar>
|
|
21
|
+
<Stack screenOptions={{
|
|
22
|
+
// 设置所有页面的切换动画为从右侧滑入,适用于iOS 和 Android
|
|
23
|
+
animation: 'slide_from_right',
|
|
24
|
+
gestureEnabled: true,
|
|
25
|
+
gestureDirection: 'horizontal',
|
|
26
|
+
// 隐藏自带的头部
|
|
27
|
+
headerShown: false
|
|
28
|
+
}}>
|
|
29
|
+
<Stack.Screen name="index" options={{ title: "" }} />
|
|
30
|
+
</Stack>
|
|
31
|
+
<Toast />
|
|
30
32
|
</GestureHandlerRootView>
|
|
31
33
|
</AuthProvider>
|
|
32
34
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExpoConfig, ConfigContext } from 'expo/config';
|
|
2
2
|
|
|
3
|
-
const appName = process.env.EXPO_PUBLIC_COZE_PROJECT_NAME || '应用';
|
|
4
|
-
const projectId = process.env.EXPO_PUBLIC_COZE_PROJECT_ID;
|
|
3
|
+
const appName = process.env.COZE_PROJECT_NAME || process.env.EXPO_PUBLIC_COZE_PROJECT_NAME || '应用';
|
|
4
|
+
const projectId = process.env.COZE_PROJECT_ID || process.env.EXPO_PUBLIC_COZE_PROJECT_ID;
|
|
5
5
|
const slugAppName = projectId ? `app${projectId}` : 'myapp';
|
|
6
6
|
|
|
7
7
|
export default ({ config }: ConfigContext): ExpoConfig => {
|
|
@@ -197,26 +197,10 @@ export const Screen = ({
|
|
|
197
197
|
// 强制禁用 iOS 自动调整内容区域,完全由手动 padding 控制,消除系统自动计算带来的多余空白
|
|
198
198
|
const contentInsetBehaviorIOS = 'never';
|
|
199
199
|
|
|
200
|
-
// 1. 外层容器样式
|
|
201
|
-
// 负责:背景色、Top/Left/Right 安全区、以及非滚动模式下的 Bottom 安全区
|
|
202
|
-
const childArray = React.Children.toArray(children);
|
|
203
|
-
let firstChild: React.ReactElement<any, any> | null = null;
|
|
204
|
-
for (let i = 0; i < childArray.length; i++) {
|
|
205
|
-
const el = childArray[i];
|
|
206
|
-
if (React.isValidElement(el)) { firstChild = el as React.ReactElement<any, any>; break; }
|
|
207
|
-
}
|
|
208
|
-
const firstChildHasInlinePaddingTop = (() => {
|
|
209
|
-
if (!firstChild) return false;
|
|
210
|
-
const st: any = (firstChild as any).props?.style;
|
|
211
|
-
const arr = Array.isArray(st) ? st : st ? [st] : [];
|
|
212
|
-
return arr.some((s) => s && typeof s === 'object' && typeof (s as any).paddingTop === 'number' && (s as any).paddingTop > 10);
|
|
213
|
-
})();
|
|
214
|
-
const applyTopInset = hasTop && !firstChildHasInlinePaddingTop;
|
|
215
|
-
|
|
216
200
|
const wrapperStyle: ViewStyle = {
|
|
217
201
|
flex: 1,
|
|
218
202
|
backgroundColor,
|
|
219
|
-
paddingTop:
|
|
203
|
+
paddingTop: hasTop ? insets.top : 0,
|
|
220
204
|
paddingLeft: hasLeft ? insets.left : 0,
|
|
221
205
|
paddingRight: hasRight ? insets.right : 0,
|
|
222
206
|
// 当页面不使用外层 ScrollView 时(子树本身可滚动),由外层 View 负责底部安全区
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { View, ViewProps, ViewStyle } from 'react-native';
|
|
3
3
|
import { useTheme } from '@/hooks/useTheme';
|
|
4
4
|
|
|
5
|
-
type BackgroundLevel = 'root' | 'default' | '
|
|
5
|
+
type BackgroundLevel = 'root' | 'default' | 'tertiary';
|
|
6
6
|
|
|
7
7
|
interface ThemedViewProps extends ViewProps {
|
|
8
8
|
level?: BackgroundLevel;
|
|
@@ -12,7 +12,6 @@ interface ThemedViewProps extends ViewProps {
|
|
|
12
12
|
const backgroundMap: Record<BackgroundLevel, string> = {
|
|
13
13
|
root: 'backgroundRoot',
|
|
14
14
|
default: 'backgroundDefault',
|
|
15
|
-
secondary: 'backgroundSecondary',
|
|
16
15
|
tertiary: 'backgroundTertiary',
|
|
17
16
|
};
|
|
18
17
|
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import js from
|
|
2
|
-
import globals from
|
|
3
|
-
import tseslint from
|
|
4
|
-
import pluginReact from
|
|
5
|
-
import reactHooks from
|
|
6
|
-
import regexp from
|
|
7
|
-
import pluginImport from
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import globals from 'globals';
|
|
3
|
+
import tseslint from 'typescript-eslint';
|
|
4
|
+
import pluginReact from 'eslint-plugin-react';
|
|
5
|
+
import reactHooks from 'eslint-plugin-react-hooks';
|
|
6
|
+
import regexp from 'eslint-plugin-regexp';
|
|
7
|
+
import pluginImport from 'eslint-plugin-import';
|
|
8
|
+
import fontawesome6 from '../eslint-plugins/fontawesome6/index.js';
|
|
9
|
+
import reanimated from '../eslint-plugins/reanimated/index.js';
|
|
10
|
+
import reactnative from '../eslint-plugins/react-native/index.js';
|
|
8
11
|
|
|
9
12
|
export default [
|
|
10
13
|
{
|
|
@@ -15,19 +18,21 @@ export default [
|
|
|
15
18
|
'src/api/**', // 排除 src 下的自动生成 API
|
|
16
19
|
'.expo/**', // 排除 Expo 自动生成的文件
|
|
17
20
|
'tailwind.config.js', // 排除 Tailwind 配置文件
|
|
21
|
+
'**/*.d.ts',
|
|
22
|
+
'eslint.config.*',
|
|
18
23
|
],
|
|
19
24
|
},
|
|
20
25
|
regexp.configs["flat/recommended"],
|
|
21
26
|
js.configs.recommended,
|
|
22
27
|
...tseslint.configs.recommended,
|
|
23
|
-
|
|
28
|
+
|
|
24
29
|
// React 的推荐配置
|
|
25
30
|
pluginReact.configs.flat.recommended,
|
|
26
31
|
pluginReact.configs.flat['jsx-runtime'],
|
|
27
32
|
reactHooks.configs.flat.recommended,
|
|
28
33
|
{
|
|
29
34
|
files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
|
|
30
|
-
|
|
35
|
+
|
|
31
36
|
// 语言选项:设置全局变量
|
|
32
37
|
languageOptions: {
|
|
33
38
|
globals: {
|
|
@@ -52,6 +57,9 @@ export default [
|
|
|
52
57
|
|
|
53
58
|
plugins: {
|
|
54
59
|
import: pluginImport,
|
|
60
|
+
fontawesome6,
|
|
61
|
+
reanimated,
|
|
62
|
+
reactnative,
|
|
55
63
|
},
|
|
56
64
|
rules: {
|
|
57
65
|
// 关闭代码风格规则
|
|
@@ -70,6 +78,21 @@ export default [
|
|
|
70
78
|
'no-prototype-builtins': 'off',
|
|
71
79
|
'react/react-in-jsx-scope': 'off',
|
|
72
80
|
'react/jsx-uses-react': 'off',
|
|
81
|
+
'fontawesome6/valid-name': 'error',
|
|
82
|
+
'reanimated/ban-mix-use': 'error',
|
|
83
|
+
// 禁止使用 via.placeholder.com 服务
|
|
84
|
+
'no-restricted-syntax': [
|
|
85
|
+
'error',
|
|
86
|
+
{
|
|
87
|
+
'selector': 'Literal[value=/via\\.placeholder\\.com/]',
|
|
88
|
+
'message': 'via.placeholder.com 服务不可用,禁止在代码中使用',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
'selector': 'TemplateLiteral > TemplateElement[value.raw=/via\\.placeholder\\.com/]',
|
|
92
|
+
'message': 'via.placeholder.com 服务不可用,禁止在代码中使用',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
'reactnative/wrap-horizontal-scrollview-inside-view': ['error'],
|
|
73
96
|
},
|
|
74
97
|
},
|
|
75
98
|
|
|
@@ -91,7 +114,7 @@ export default [
|
|
|
91
114
|
// 在 .js 文件中关闭 TS 规则
|
|
92
115
|
'@typescript-eslint/no-require-imports': 'off',
|
|
93
116
|
// 在 Node.js 文件中允许 require
|
|
94
|
-
'@typescript-eslint/no-var-requires': 'off',
|
|
117
|
+
'@typescript-eslint/no-var-requires': 'off',
|
|
95
118
|
'no-undef': 'off',
|
|
96
119
|
},
|
|
97
120
|
},
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
@import 'uniwind';
|
|
3
|
+
|
|
4
|
+
@import './styles';
|
|
5
|
+
|
|
6
|
+
:root,
|
|
7
|
+
.light,
|
|
8
|
+
.default,
|
|
9
|
+
[data-theme="light"],
|
|
10
|
+
[data-theme="default"] {
|
|
11
|
+
/* Theme Colors (Light Mode) */
|
|
12
|
+
--accent: oklch(55.00% 0.2500 254.00);
|
|
13
|
+
--accent-foreground: oklch(99.11% 0 0);
|
|
14
|
+
--background: oklch(97.02% 0.0040 254.00);
|
|
15
|
+
--border: oklch(90.00% 0.0040 254.00);
|
|
16
|
+
--danger: oklch(65.32% 0.2347 25.76);
|
|
17
|
+
--danger-foreground: oklch(99.11% 0 0);
|
|
18
|
+
--default: oklch(94.00% 0.0040 254.00);
|
|
19
|
+
--default-foreground: oklch(21.03% 0.0059 254.00);
|
|
20
|
+
--field-background: oklch(100.00% 0.0020 254.00);
|
|
21
|
+
--field-foreground: oklch(21.03% 0.0059 254.00);
|
|
22
|
+
--field-placeholder: oklch(55.17% 0.0081 254.00);
|
|
23
|
+
--focus: oklch(55.00% 0.2500 254.00);
|
|
24
|
+
--foreground: oklch(21.03% 0.0059 254.00);
|
|
25
|
+
--muted: oklch(55.17% 0.0081 254.00);
|
|
26
|
+
--overlay: oklch(100.00% 0.0012 254.00);
|
|
27
|
+
--overlay-foreground: oklch(21.03% 0.0059 254.00);
|
|
28
|
+
--scrollbar: oklch(87.10% 0.0040 254.00);
|
|
29
|
+
--segment: oklch(100.00% 0.0040 254.00);
|
|
30
|
+
--segment-foreground: oklch(21.03% 0.0059 254.00);
|
|
31
|
+
--separator: oklch(92.00% 0.0040 254.00);
|
|
32
|
+
--success: oklch(73.29% 0.1951 150.83);
|
|
33
|
+
--success-foreground: oklch(21.03% 0.0059 150.83);
|
|
34
|
+
--surface: oklch(100.00% 0.0020 254.00);
|
|
35
|
+
--surface-foreground: oklch(21.03% 0.0059 254.00);
|
|
36
|
+
--warning: oklch(78.19% 0.1598 72.35);
|
|
37
|
+
--warning-foreground: oklch(21.03% 0.0059 72.35);
|
|
38
|
+
|
|
39
|
+
/* Border Radius */
|
|
40
|
+
--radius: 0.75rem;
|
|
41
|
+
--field-radius: 0.5rem;
|
|
42
|
+
|
|
43
|
+
/* Font Family */
|
|
44
|
+
/* Make sure to load Google Sans font in your app */
|
|
45
|
+
--font-sans: var(--font-google-sans);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.dark,
|
|
49
|
+
[data-theme="dark"] {
|
|
50
|
+
color-scheme: dark;
|
|
51
|
+
/* Theme Colors (Dark Mode) */
|
|
52
|
+
--accent: oklch(55.00% 0.2500 254.00);
|
|
53
|
+
--accent-foreground: oklch(99.11% 0 0);
|
|
54
|
+
--background: oklch(12.00% 0.0040 254.00);
|
|
55
|
+
--border: oklch(28.00% 0.0040 254.00);
|
|
56
|
+
--danger: oklch(59.40% 0.1983 24.65);
|
|
57
|
+
--danger-foreground: oklch(99.11% 0 0);
|
|
58
|
+
--default: oklch(27.40% 0.0040 254.00);
|
|
59
|
+
--default-foreground: oklch(99.11% 0 0);
|
|
60
|
+
--field-background: oklch(21.03% 0.0081 254.00);
|
|
61
|
+
--field-foreground: oklch(99.11% 0.0000 0.00);
|
|
62
|
+
--field-placeholder: oklch(70.50% 0.0081 254.00);
|
|
63
|
+
--focus: oklch(55.00% 0.2500 254.00);
|
|
64
|
+
--foreground: oklch(99.11% 0.0000 0.00);
|
|
65
|
+
--muted: oklch(70.50% 0.0081 254.00);
|
|
66
|
+
--overlay: oklch(21.03% 0.0081 254.00);
|
|
67
|
+
--overlay-foreground: oklch(99.11% 0.0000 0.00);
|
|
68
|
+
--scrollbar: oklch(70.50% 0.0040 254.00);
|
|
69
|
+
--segment: oklch(39.64% 0.0040 254.00);
|
|
70
|
+
--segment-foreground: oklch(99.11% 0.0000 0.00);
|
|
71
|
+
--separator: oklch(25.00% 0.0040 254.00);
|
|
72
|
+
--success: oklch(73.29% 0.1951 150.83);
|
|
73
|
+
--success-foreground: oklch(21.03% 0.0059 150.83);
|
|
74
|
+
--surface: oklch(21.03% 0.0081 254.00);
|
|
75
|
+
--surface-foreground: oklch(99.11% 0.0000 0.00);
|
|
76
|
+
--warning: oklch(82.03% 0.1399 76.36);
|
|
77
|
+
--warning-foreground: oklch(21.03% 0.0059 76.36);
|
|
78
|
+
}
|