@coze-arch/cli 0.0.1-alpha.bd5b49 → 0.0.1-alpha.c199b3

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.
Files changed (155) hide show
  1. package/README.md +1 -0
  2. package/lib/__templates__/expo/README.md +16 -13
  3. package/lib/__templates__/expo/_npmrc +1 -0
  4. package/lib/__templates__/expo/client/app/+not-found.tsx +19 -4
  5. package/lib/__templates__/expo/client/app/_layout.tsx +17 -16
  6. package/lib/__templates__/expo/client/components/Screen.tsx +2 -2
  7. package/lib/__templates__/expo/client/constants/theme.ts +177 -0
  8. package/lib/__templates__/expo/client/eslint.config.mjs +7 -0
  9. package/lib/__templates__/expo/client/hooks/useColorScheme.tsx +48 -0
  10. package/lib/__templates__/expo/client/hooks/useTheme.ts +33 -0
  11. package/lib/__templates__/expo/client/metro.config.js +4 -8
  12. package/lib/__templates__/expo/client/package.json +1 -3
  13. package/lib/__templates__/expo/client/screens/demo/index.tsx +13 -7
  14. package/lib/__templates__/expo/client/screens/demo/styles.ts +28 -0
  15. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +10 -10
  16. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/index.js +9 -0
  17. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/rule.js +112 -0
  18. package/lib/__templates__/expo/eslint-plugins/forbid-emoji/tech.md +94 -0
  19. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/index.js +9 -0
  20. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/rule.js +120 -0
  21. package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/tech.md +58 -0
  22. package/lib/__templates__/native-static/.coze +11 -0
  23. package/lib/__templates__/native-static/index.html +33 -0
  24. package/lib/__templates__/native-static/styles/main.css +136 -0
  25. package/lib/__templates__/native-static/template.config.js +22 -0
  26. package/lib/__templates__/nextjs/AGENTS.md +54 -0
  27. package/lib/__templates__/nextjs/README.md +5 -0
  28. package/lib/__templates__/nextjs/eslint.config.mjs +5 -0
  29. package/lib/__templates__/nextjs/next.config.ts +1 -2
  30. package/lib/__templates__/nextjs/package.json +2 -5
  31. package/lib/__templates__/nextjs/pnpm-lock.yaml +1028 -5
  32. package/lib/__templates__/nextjs/scripts/build.sh +4 -1
  33. package/lib/__templates__/nextjs/scripts/dev.sh +8 -2
  34. package/lib/__templates__/nextjs/scripts/start.sh +7 -1
  35. package/lib/__templates__/nextjs/src/app/layout.tsx +1 -1
  36. package/lib/__templates__/nextjs/src/app/page.tsx +1 -2
  37. package/lib/__templates__/nextjs/src/server.ts +35 -0
  38. package/lib/__templates__/nextjs/tsconfig.json +1 -1
  39. package/lib/__templates__/nuxt-vue/.coze +12 -0
  40. package/lib/__templates__/nuxt-vue/AGENTS.md +42 -0
  41. package/lib/__templates__/nuxt-vue/README.md +73 -0
  42. package/lib/__templates__/nuxt-vue/_gitignore +24 -0
  43. package/lib/__templates__/nuxt-vue/_npmrc +23 -0
  44. package/lib/__templates__/nuxt-vue/app/app.vue +6 -0
  45. package/lib/__templates__/nuxt-vue/app/pages/index.vue +23 -0
  46. package/lib/__templates__/nuxt-vue/assets/css/main.css +24 -0
  47. package/lib/__templates__/nuxt-vue/nuxt.config.ts +116 -0
  48. package/lib/__templates__/nuxt-vue/package.json +35 -0
  49. package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +8759 -0
  50. package/lib/__templates__/nuxt-vue/postcss.config.mjs +8 -0
  51. package/lib/__templates__/nuxt-vue/public/favicon.ico +0 -0
  52. package/lib/__templates__/nuxt-vue/public/robots.txt +2 -0
  53. package/lib/__templates__/nuxt-vue/scripts/build.sh +14 -0
  54. package/lib/__templates__/nuxt-vue/scripts/dev.sh +39 -0
  55. package/lib/__templates__/nuxt-vue/scripts/prepare.sh +14 -0
  56. package/lib/__templates__/nuxt-vue/scripts/start.sh +21 -0
  57. package/lib/__templates__/nuxt-vue/server/api/hello.ts +10 -0
  58. package/lib/__templates__/nuxt-vue/server/middleware/logger.ts +10 -0
  59. package/lib/__templates__/nuxt-vue/server/routes/health.ts +10 -0
  60. package/lib/__templates__/nuxt-vue/tailwind.config.js +13 -0
  61. package/lib/__templates__/nuxt-vue/template.config.js +87 -0
  62. package/lib/__templates__/nuxt-vue/tsconfig.json +18 -0
  63. package/lib/__templates__/taro/.cozeproj/scripts/dev_run.sh +107 -36
  64. package/lib/__templates__/taro/.cozeproj/scripts/pack.sh +24 -1
  65. package/lib/__templates__/taro/README.md +61 -45
  66. package/lib/__templates__/taro/config/index.ts +106 -41
  67. package/lib/__templates__/taro/config/prod.ts +4 -5
  68. package/lib/__templates__/taro/eslint.config.mjs +82 -4
  69. package/lib/__templates__/taro/package.json +22 -7
  70. package/lib/__templates__/taro/patches/@tarojs__plugin-mini-ci@4.1.9.patch +30 -0
  71. package/lib/__templates__/taro/pnpm-lock.yaml +924 -220
  72. package/lib/__templates__/taro/server/package.json +0 -1
  73. package/lib/__templates__/taro/src/app.css +140 -36
  74. package/lib/__templates__/taro/src/app.tsx +9 -0
  75. package/lib/__templates__/taro/src/components/ui/accordion.tsx +159 -0
  76. package/lib/__templates__/taro/src/components/ui/alert-dialog.tsx +260 -0
  77. package/lib/__templates__/taro/src/components/ui/alert.tsx +60 -0
  78. package/lib/__templates__/taro/src/components/ui/aspect-ratio.tsx +36 -0
  79. package/lib/__templates__/taro/src/components/ui/avatar.tsx +84 -0
  80. package/lib/__templates__/taro/src/components/ui/badge.tsx +37 -0
  81. package/lib/__templates__/taro/src/components/ui/breadcrumb.tsx +117 -0
  82. package/lib/__templates__/taro/src/components/ui/button-group.tsx +83 -0
  83. package/lib/__templates__/taro/src/components/ui/button.tsx +67 -0
  84. package/lib/__templates__/taro/src/components/ui/calendar.tsx +394 -0
  85. package/lib/__templates__/taro/src/components/ui/card.tsx +108 -0
  86. package/lib/__templates__/taro/src/components/ui/carousel.tsx +228 -0
  87. package/lib/__templates__/taro/src/components/ui/checkbox.tsx +58 -0
  88. package/lib/__templates__/taro/src/components/ui/code-block.tsx +169 -0
  89. package/lib/__templates__/taro/src/components/ui/collapsible.tsx +71 -0
  90. package/lib/__templates__/taro/src/components/ui/command.tsx +385 -0
  91. package/lib/__templates__/taro/src/components/ui/context-menu.tsx +614 -0
  92. package/lib/__templates__/taro/src/components/ui/dialog.tsx +256 -0
  93. package/lib/__templates__/taro/src/components/ui/drawer.tsx +192 -0
  94. package/lib/__templates__/taro/src/components/ui/dropdown-menu.tsx +561 -0
  95. package/lib/__templates__/taro/src/components/ui/field.tsx +228 -0
  96. package/lib/__templates__/taro/src/components/ui/hover-card.tsx +282 -0
  97. package/lib/__templates__/taro/src/components/ui/input-group.tsx +197 -0
  98. package/lib/__templates__/taro/src/components/ui/input-otp.tsx +136 -0
  99. package/lib/__templates__/taro/src/components/ui/input.tsx +56 -0
  100. package/lib/__templates__/taro/src/components/ui/label.tsx +24 -0
  101. package/lib/__templates__/taro/src/components/ui/menubar.tsx +595 -0
  102. package/lib/__templates__/taro/src/components/ui/navigation-menu.tsx +264 -0
  103. package/lib/__templates__/taro/src/components/ui/pagination.tsx +118 -0
  104. package/lib/__templates__/taro/src/components/ui/popover.tsx +291 -0
  105. package/lib/__templates__/taro/src/components/ui/portal.tsx +19 -0
  106. package/lib/__templates__/taro/src/components/ui/progress.tsx +28 -0
  107. package/lib/__templates__/taro/src/components/ui/radio-group.tsx +64 -0
  108. package/lib/__templates__/taro/src/components/ui/resizable.tsx +346 -0
  109. package/lib/__templates__/taro/src/components/ui/scroll-area.tsx +34 -0
  110. package/lib/__templates__/taro/src/components/ui/select.tsx +438 -0
  111. package/lib/__templates__/taro/src/components/ui/separator.tsx +30 -0
  112. package/lib/__templates__/taro/src/components/ui/sheet.tsx +262 -0
  113. package/lib/__templates__/taro/src/components/ui/skeleton.tsx +17 -0
  114. package/lib/__templates__/taro/src/components/ui/slider.tsx +203 -0
  115. package/lib/__templates__/taro/src/components/ui/sonner.tsx +1 -0
  116. package/lib/__templates__/taro/src/components/ui/switch.tsx +55 -0
  117. package/lib/__templates__/taro/src/components/ui/table.tsx +142 -0
  118. package/lib/__templates__/taro/src/components/ui/tabs.tsx +114 -0
  119. package/lib/__templates__/taro/src/components/ui/textarea.tsx +54 -0
  120. package/lib/__templates__/taro/src/components/ui/toast.tsx +517 -0
  121. package/lib/__templates__/taro/src/components/ui/toggle-group.tsx +120 -0
  122. package/lib/__templates__/taro/src/components/ui/toggle.tsx +77 -0
  123. package/lib/__templates__/taro/src/components/ui/tooltip.tsx +455 -0
  124. package/lib/__templates__/taro/src/lib/hooks/use-keyboard-offset.ts +37 -0
  125. package/lib/__templates__/taro/src/lib/measure.ts +115 -0
  126. package/lib/__templates__/taro/src/lib/platform.ts +12 -0
  127. package/lib/__templates__/taro/src/lib/utils.ts +6 -0
  128. package/lib/__templates__/taro/src/presets/dev-debug.ts +23 -0
  129. package/lib/__templates__/taro/src/presets/h5-container.tsx +15 -0
  130. package/lib/__templates__/taro/src/presets/h5-navbar.tsx +238 -0
  131. package/lib/__templates__/taro/src/presets/h5-styles.ts +220 -0
  132. package/lib/__templates__/taro/src/presets/index.tsx +18 -0
  133. package/lib/__templates__/templates.json +43 -0
  134. package/lib/__templates__/vite/AGENTS.md +41 -0
  135. package/lib/__templates__/vite/README.md +190 -11
  136. package/lib/__templates__/vite/_gitignore +1 -0
  137. package/lib/__templates__/vite/eslint.config.mjs +6 -1
  138. package/lib/__templates__/vite/package.json +10 -3
  139. package/lib/__templates__/vite/pnpm-lock.yaml +755 -15
  140. package/lib/__templates__/vite/scripts/build.sh +4 -1
  141. package/lib/__templates__/vite/scripts/dev.sh +9 -2
  142. package/lib/__templates__/vite/scripts/start.sh +9 -3
  143. package/lib/__templates__/vite/server/routes/index.ts +31 -0
  144. package/lib/__templates__/vite/server/server.ts +65 -0
  145. package/lib/__templates__/vite/server/vite.ts +67 -0
  146. package/lib/__templates__/vite/tsconfig.json +4 -3
  147. package/lib/__templates__/vite/vite.config.ts +5 -0
  148. package/lib/cli.js +3037 -535
  149. package/package.json +10 -3
  150. package/lib/__templates__/expo/client/global.css +0 -78
  151. package/lib/__templates__/expo/client/styles.css +0 -263
  152. package/lib/__templates__/expo/client/uniwind-types.d.ts +0 -10
  153. package/lib/__templates__/taro/src/app.ts +0 -14
  154. package/lib/__templates__/taro/src/utils/h5-styles.ts +0 -33
  155. package/lib/__templates__/taro/src/utils/wx-debug.ts +0 -23
package/README.md CHANGED
@@ -14,6 +14,7 @@ Coze Coding 的项目模板引擎,提供基于前端技术栈的项目初始
14
14
 
15
15
  ```bash
16
16
  rush update
17
+
17
18
  ```
18
19
 
19
20
  ## 使用
@@ -1,6 +1,6 @@
1
1
  # Expo App + Express.js
2
2
 
3
- ## 目录结构规范
3
+ ## 目录结构规范(严格遵循)
4
4
 
5
5
  当前仓库是一个 monorepo(基于 pnpm 的 workspace)
6
6
 
@@ -16,14 +16,17 @@
16
16
  ├── client/ # React Native 前端代码
17
17
  │ ├── app/ # Expo Router 路由目录(仅路由配置)
18
18
  │ │ ├── _layout.tsx # 根布局文件(必需,务必阅读)
19
- │ │ └── index.tsx # 首页
19
+ │ │ ├── home.tsx # 首页
20
+ │ │ └── index.tsx # re-export home.tsx
20
21
  │ ├── screens/ # 页面实现目录(与 app/ 路由对应)
21
- │ │ └── demo/
22
- │ │ └── index.tsx # demo 示例页面(默认首页,不需要可以删除,记得同时更新路由文件)
22
+ │ │ └── demo/ # demo 示例页面
23
+ │ │ ├── index.tsx # 页面组件实现
24
+ │ │ └── styles.ts # 页面样式
23
25
  │ ├── components/ # 可复用组件
24
26
  │ │ └── Screen.tsx # 页面容器组件(必用)
25
27
  │ ├── hooks/ # 自定义 Hooks
26
28
  │ ├── contexts/ # React Context 代码
29
+ │ ├── constants/ # 常量定义(如主题配置)
27
30
  │ ├── utils/ # 工具函数
28
31
  │ ├── assets/ # 静态资源
29
32
  | └── package.json # Expo 应用 package.json
@@ -31,15 +34,6 @@
31
34
  ├── .cozeproj # 预置脚手架脚本(禁止修改)
32
35
  └── .coze # 配置文件(禁止修改)
33
36
 
34
- ## 技术选型(严格遵循)
35
-
36
- - 前端:Expo + React Native + TailwindCSS
37
- - 后端:Express.js
38
-
39
- 本项目通过 uniwind 实现了 react-native 对 TailwindCSS v4 的支持,在编写样式时应使用 TailwindCSS 写法
40
-
41
- 在开始开发前,先查看 client/global.css 了解必要的信息
42
-
43
37
  ## 安装依赖
44
38
 
45
39
  ### 命令
@@ -48,6 +42,15 @@
48
42
  pnpm i
49
43
  ```
50
44
 
45
+ ### 新增依赖约束
46
+
47
+ 如果需要新增依赖,需在 client 和 server 各自的目录添加(原因:隔离前后端的依赖),禁止在根目录直接安装依赖
48
+
49
+ ### 新增依赖标准流程
50
+
51
+ - 编辑 `client/package.json` 或 `server/package.json`
52
+ - 在根目录执行 `pnpm i`
53
+
51
54
  ## Expo 开发规范
52
55
 
53
56
  ### 路径别名
@@ -1,3 +1,4 @@
1
+ loglevel=error
1
2
  registry=https://registry.npmmirror.com
2
3
 
3
4
  strictStorePkgContentCheck=false
@@ -1,15 +1,30 @@
1
- import { View, Text } from 'react-native';
1
+ import { View, Text, StyleSheet } from 'react-native';
2
2
  import { Link } from 'expo-router';
3
+ import { useTheme } from '@/hooks/useTheme';
4
+ import { Spacing } from '@/constants/theme';
3
5
 
4
6
  export default function NotFoundScreen() {
7
+ const { theme } = useTheme();
8
+
5
9
  return (
6
- <View className="flex-1 justify-center items-center bg-background">
7
- <Text className="text-foreground">
10
+ <View style={[styles.container, { backgroundColor: theme.backgroundRoot }]}>
11
+ <Text>
8
12
  页面不存在
9
13
  </Text>
10
- <Link href="/" className="text-accent mt-6">
14
+ <Link href="/" style={[styles.gohome]}>
11
15
  返回首页
12
16
  </Link>
13
17
  </View>
14
18
  );
15
19
  }
20
+
21
+ const styles = StyleSheet.create({
22
+ container: {
23
+ flex: 1,
24
+ justifyContent: 'center',
25
+ alignItems: 'center',
26
+ },
27
+ gohome: {
28
+ marginTop: Spacing['2xl'],
29
+ },
30
+ });
@@ -5,8 +5,7 @@ import { StatusBar } from 'expo-status-bar';
5
5
  import { LogBox } from 'react-native';
6
6
  import Toast from 'react-native-toast-message';
7
7
  import { AuthProvider } from "@/contexts/AuthContext";
8
-
9
- import '../global.css';
8
+ import { ColorSchemeProvider } from '@/hooks/useColorScheme';
10
9
 
11
10
  LogBox.ignoreLogs([
12
11
  "TurboModuleRegistry.getEnforcing(...): 'RNMapsAirModule' could not be found",
@@ -16,20 +15,22 @@ LogBox.ignoreLogs([
16
15
  export default function RootLayout() {
17
16
  return (
18
17
  <AuthProvider>
19
- <GestureHandlerRootView style={{ flex: 1 }}>
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 />
32
- </GestureHandlerRootView>
18
+ <ColorSchemeProvider>
19
+ <GestureHandlerRootView style={{ flex: 1 }}>
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 />
32
+ </GestureHandlerRootView>
33
+ </ColorSchemeProvider>
33
34
  </AuthProvider>
34
35
  );
35
36
  }
@@ -32,7 +32,7 @@ import {
32
32
  *
33
33
  * ## 2. 沉浸式 Header (推荐)
34
34
  * - 场景:Header 背景色/图片需要延伸到状态栏 (如首页、个人中心)。
35
- * - 用法:`<Screen safeAreaEdges={['left', 'right', 'bottom']}>` (去掉 'top')
35
+ * - 用法:`<Screen safeAreaEdges={['left', 'right', 'bottom']}>` (去掉 'top')
36
36
  * - 配合:页面内部 Header 组件必须手动添加 paddingTop:
37
37
  * ```tsx
38
38
  * const insets = useSafeAreaInsets();
@@ -41,7 +41,7 @@ import {
41
41
  *
42
42
  * ## 3. 底部有 TabBar 或 悬浮按钮
43
43
  * - 场景:页面底部有固定导航栏,或者需要精细控制底部留白。
44
- * - 用法:`<Screen safeAreaEdges={['top', 'left', 'right']}>` (去掉 'bottom')
44
+ * - 用法:`<Screen safeAreaEdges={['top', 'left', 'right']}>` (去掉 'bottom')
45
45
  * - 配合:
46
46
  * - 若是滚动页:`<ScrollView contentContainerStyle={{ paddingBottom: insets.bottom + 80 }}>`
47
47
  * - 若是固定页:`<View style={{ paddingBottom: insets.bottom + 60 }}>`
@@ -0,0 +1,177 @@
1
+ export const Colors = {
2
+ light: {
3
+ textPrimary: "#1C1917",
4
+ textSecondary: "#78716c",
5
+ textMuted: "#9CA3AF",
6
+ primary: "#4F46E5", // Indigo-600 - 品牌主色,代表科技与智能
7
+ accent: "#8B5CF6", // Violet-500 - 辅助色,代表创造力
8
+ success: "#10B981", // Emerald-500
9
+ error: "#EF4444",
10
+ backgroundRoot: "#FAFAFA",
11
+ backgroundDefault: "#FFFFFF",
12
+ backgroundTertiary: "#F9FAFB", // 更浅的背景色,用于去线留白
13
+ buttonPrimaryText: "#FFFFFF",
14
+ tabIconSelected: "#4F46E5",
15
+ border: "#E5E7EB",
16
+ borderLight: "#F3F4F6",
17
+ },
18
+ dark: {
19
+ textPrimary: "#FAFAF9",
20
+ textSecondary: "#A8A29E",
21
+ textMuted: "#6F767E",
22
+ primary: "#818CF8", // Indigo-400 - 暗色模式品牌主色
23
+ accent: "#A78BFA", // Violet-400
24
+ success: "#34D399",
25
+ error: "#F87171",
26
+ backgroundRoot: "#09090B", // 更深的背景色
27
+ backgroundDefault: "#1C1C1E",
28
+ backgroundTertiary: "#1F1F22", // 暗色模式去线留白背景
29
+ buttonPrimaryText: "#09090B",
30
+ tabIconSelected: "#818CF8",
31
+ border: "#3F3F46",
32
+ borderLight: "#27272A",
33
+ },
34
+ };
35
+
36
+ export const Spacing = {
37
+ xs: 4,
38
+ sm: 8,
39
+ md: 12,
40
+ lg: 16,
41
+ xl: 20,
42
+ "2xl": 24,
43
+ "3xl": 32,
44
+ "4xl": 40,
45
+ "5xl": 48,
46
+ "6xl": 64,
47
+ };
48
+
49
+ export const BorderRadius = {
50
+ xs: 4,
51
+ sm: 8,
52
+ md: 12,
53
+ lg: 16,
54
+ xl: 20,
55
+ "2xl": 24,
56
+ "3xl": 28,
57
+ "4xl": 32,
58
+ full: 9999,
59
+ };
60
+
61
+ export const Typography = {
62
+ display: {
63
+ fontSize: 112,
64
+ lineHeight: 112,
65
+ fontWeight: "200" as const,
66
+ letterSpacing: -4,
67
+ },
68
+ displayLarge: {
69
+ fontSize: 112,
70
+ lineHeight: 112,
71
+ fontWeight: "200" as const,
72
+ letterSpacing: -2,
73
+ },
74
+ displayMedium: {
75
+ fontSize: 48,
76
+ lineHeight: 56,
77
+ fontWeight: "200" as const,
78
+ },
79
+ h1: {
80
+ fontSize: 32,
81
+ lineHeight: 40,
82
+ fontWeight: "700" as const,
83
+ },
84
+ h2: {
85
+ fontSize: 28,
86
+ lineHeight: 36,
87
+ fontWeight: "700" as const,
88
+ },
89
+ h3: {
90
+ fontSize: 24,
91
+ lineHeight: 32,
92
+ fontWeight: "300" as const,
93
+ },
94
+ h4: {
95
+ fontSize: 20,
96
+ lineHeight: 28,
97
+ fontWeight: "600" as const,
98
+ },
99
+ title: {
100
+ fontSize: 18,
101
+ lineHeight: 24,
102
+ fontWeight: "700" as const,
103
+ },
104
+ body: {
105
+ fontSize: 16,
106
+ lineHeight: 24,
107
+ fontWeight: "400" as const,
108
+ },
109
+ bodyMedium: {
110
+ fontSize: 16,
111
+ lineHeight: 24,
112
+ fontWeight: "500" as const,
113
+ },
114
+ small: {
115
+ fontSize: 14,
116
+ lineHeight: 20,
117
+ fontWeight: "400" as const,
118
+ },
119
+ smallMedium: {
120
+ fontSize: 14,
121
+ lineHeight: 20,
122
+ fontWeight: "500" as const,
123
+ },
124
+ caption: {
125
+ fontSize: 12,
126
+ lineHeight: 16,
127
+ fontWeight: "400" as const,
128
+ },
129
+ captionMedium: {
130
+ fontSize: 12,
131
+ lineHeight: 16,
132
+ fontWeight: "500" as const,
133
+ },
134
+ label: {
135
+ fontSize: 14,
136
+ lineHeight: 20,
137
+ fontWeight: "500" as const,
138
+ letterSpacing: 2,
139
+ textTransform: "uppercase" as const,
140
+ },
141
+ labelSmall: {
142
+ fontSize: 12,
143
+ lineHeight: 16,
144
+ fontWeight: "500" as const,
145
+ letterSpacing: 1,
146
+ textTransform: "uppercase" as const,
147
+ },
148
+ labelTitle: {
149
+ fontSize: 14,
150
+ lineHeight: 20,
151
+ fontWeight: "700" as const,
152
+ letterSpacing: 2,
153
+ textTransform: "uppercase" as const,
154
+ },
155
+ link: {
156
+ fontSize: 16,
157
+ lineHeight: 24,
158
+ fontWeight: "400" as const,
159
+ },
160
+ stat: {
161
+ fontSize: 30,
162
+ lineHeight: 36,
163
+ fontWeight: "300" as const,
164
+ },
165
+ tiny: {
166
+ fontSize: 10,
167
+ lineHeight: 14,
168
+ fontWeight: "400" as const,
169
+ },
170
+ navLabel: {
171
+ fontSize: 10,
172
+ lineHeight: 14,
173
+ fontWeight: "500" as const,
174
+ },
175
+ };
176
+
177
+ export type Theme = typeof Colors.light;
@@ -8,6 +8,8 @@ import pluginImport from 'eslint-plugin-import';
8
8
  import fontawesome6 from '../eslint-plugins/fontawesome6/index.js';
9
9
  import reanimated from '../eslint-plugins/reanimated/index.js';
10
10
  import reactnative from '../eslint-plugins/react-native/index.js';
11
+ import forbidEmoji from '../eslint-plugins/forbid-emoji/index.js';
12
+ import restrictLinearGradient from '../eslint-plugins/restrict-linear-gradient/index.js';
11
13
 
12
14
  export default [
13
15
  {
@@ -20,6 +22,7 @@ export default [
20
22
  'tailwind.config.js', // 排除 Tailwind 配置文件
21
23
  '**/*.d.ts',
22
24
  'eslint.config.*',
25
+ 'metro.config.*',
23
26
  ],
24
27
  },
25
28
  regexp.configs["flat/recommended"],
@@ -60,6 +63,8 @@ export default [
60
63
  fontawesome6,
61
64
  reanimated,
62
65
  reactnative,
66
+ forbidEmoji,
67
+ restrictLinearGradient,
63
68
  },
64
69
  rules: {
65
70
  // 关闭代码风格规则
@@ -80,6 +85,8 @@ export default [
80
85
  'react/jsx-uses-react': 'off',
81
86
  'fontawesome6/valid-name': 'error',
82
87
  'reanimated/ban-mix-use': 'error',
88
+ 'forbidEmoji/no-emoji': 'error',
89
+ 'restrictLinearGradient/no-linear-gradient-backgroundcolor': 'error',
83
90
  // 禁止使用 via.placeholder.com 服务
84
91
  'no-restricted-syntax': [
85
92
  'error',
@@ -0,0 +1,48 @@
1
+ import { createContext, Dispatch, ReactNode, SetStateAction, useContext, useEffect, useState } from 'react';
2
+ import { ColorSchemeName, useColorScheme as useReactNativeColorScheme, Platform } from 'react-native';
3
+
4
+ const ColorSchemeContext = createContext<'light' | 'dark' | null | undefined>(null);
5
+
6
+ const ColorSchemeProvider = function ({ children }: { children?: ReactNode }) {
7
+ const systemColorScheme = useReactNativeColorScheme();
8
+ const [colorScheme, setColorScheme] = useState(systemColorScheme);
9
+
10
+ useEffect(() => {
11
+ setColorScheme(systemColorScheme);
12
+ }, [systemColorScheme]);
13
+
14
+ useEffect(() => {
15
+ function handleMessage(e: MessageEvent<{ event: string; colorScheme: ColorSchemeName; } | undefined>) {
16
+ if (e.data?.event === 'coze.workbench.colorScheme') {
17
+ const cs = e.data.colorScheme;
18
+ if (typeof cs === 'string' && typeof setColorScheme === 'function') {
19
+ setColorScheme(cs);
20
+ }
21
+ }
22
+ }
23
+
24
+ if (Platform.OS === 'web') {
25
+ window.addEventListener('message', handleMessage, false);
26
+ }
27
+
28
+ return () => {
29
+ if (Platform.OS === 'web') {
30
+ window.removeEventListener('message', handleMessage, false);
31
+ }
32
+ }
33
+ }, [setColorScheme]);
34
+
35
+ return <ColorSchemeContext.Provider value={colorScheme}>
36
+ {children}
37
+ </ColorSchemeContext.Provider>
38
+ };
39
+
40
+ function useColorScheme() {
41
+ const colorScheme = useContext(ColorSchemeContext);
42
+ return colorScheme;
43
+ }
44
+
45
+ export {
46
+ ColorSchemeProvider,
47
+ useColorScheme,
48
+ }
@@ -0,0 +1,33 @@
1
+ import { Colors } from '@/constants/theme';
2
+ import { useColorScheme } from '@/hooks/useColorScheme';
3
+
4
+ enum COLOR_SCHEME_CHOICE {
5
+ FOLLOW_SYSTEM = 'follow-system', // 跟随系统自动变化
6
+ DARK = 'dark', // 固定为 dark 主题,不随系统变化
7
+ LIGHT = 'light', // 固定为 light 主题,不随系统变化
8
+ };
9
+
10
+ const userPreferColorScheme: COLOR_SCHEME_CHOICE = COLOR_SCHEME_CHOICE.FOLLOW_SYSTEM;
11
+
12
+ function getTheme(colorScheme?: 'dark' | 'light' | null) {
13
+ const isDark = colorScheme === 'dark';
14
+ const theme = Colors[colorScheme ?? 'light'];
15
+
16
+ return {
17
+ theme,
18
+ isDark,
19
+ };
20
+ }
21
+
22
+ function useTheme() {
23
+ const systemColorScheme = useColorScheme()
24
+ const colorScheme = userPreferColorScheme === COLOR_SCHEME_CHOICE.FOLLOW_SYSTEM ?
25
+ systemColorScheme :
26
+ userPreferColorScheme;
27
+
28
+ return getTheme(colorScheme);
29
+ }
30
+
31
+ export {
32
+ useTheme,
33
+ }
@@ -1,7 +1,6 @@
1
1
  const { getDefaultConfig } = require('expo/metro-config');
2
2
  const { createProxyMiddleware } = require('http-proxy-middleware');
3
3
  const connect = require('connect');
4
- const { withUniwindConfig } = require('uniwind/metro');
5
4
 
6
5
  const config = getDefaultConfig(__dirname);
7
6
 
@@ -27,6 +26,9 @@ config.resolver.blockList = [
27
26
  // 4. 通用规则
28
27
  /.*\/__tests__\/.*/, // 排除所有测试目录
29
28
  /.*\.git\/.*/, // 排除 Git 目录
29
+
30
+ // 5. pnpm 临时目录(避免 ENOENT 错误)
31
+ /.*node_modules\/\.pnpm\/.*_tmp_\d+.*/,
30
32
  ];
31
33
 
32
34
  const BACKEND_TARGET = 'http://localhost:9091';
@@ -119,10 +121,4 @@ config.server = {
119
121
  },
120
122
  };
121
123
 
122
- module.exports = withUniwindConfig(config, {
123
- // relative path to your global.css file (from previous step)
124
- cssEntryFile: './global.css',
125
- // (optional) path where we gonna auto-generate typings
126
- // defaults to project's root
127
- dtsFile: './uniwind-types.d.ts'
128
- });
124
+ module.exports = config;
@@ -90,8 +90,6 @@
90
90
  "react-test-renderer": "19.1.0",
91
91
  "tsx": "^4.21.0",
92
92
  "typescript": "^5.8.3",
93
- "typescript-eslint": "^8.32.1",
94
- "tailwindcss": "^4.1.18",
95
- "uniwind": "^1.2.7"
93
+ "typescript-eslint": "^8.32.1"
96
94
  }
97
95
  }
@@ -1,18 +1,24 @@
1
1
  import { View, Text } from 'react-native';
2
2
  import { Image } from 'expo-image';
3
3
 
4
+ import { useTheme } from '@/hooks/useTheme';
4
5
  import { Screen } from '@/components/Screen';
6
+ import { styles } from './styles';
5
7
 
6
8
  export default function DemoPage() {
9
+ const { theme, isDark } = useTheme();
10
+
7
11
  return (
8
- <Screen backgroundColor="var(--background)" statusBarStyle="auto">
9
- <View className="absolute top-0 left-0 w-full h-full flex flex-col items-center justify-center">
12
+ <Screen backgroundColor={theme.backgroundRoot} statusBarStyle={isDark ? 'light' : 'dark'}>
13
+ <View
14
+ style={styles.container}
15
+ >
10
16
  <Image
11
- className="w-[130px] h-[109px]"
12
- source="https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/coze-coding/expo/coze-loading.gif"
13
- />
14
- <Text className="text-base font-bold text-foreground">APP 开发中</Text>
15
- <Text className="text-sm mt-2 text-muted">即将为您呈现应用界面</Text>
17
+ style={styles.logo}
18
+ source="https://lf-coze-web-cdn.coze.cn/obj/eden-cn/lm-lgvj/ljhwZthlaukjlkulzlp/coze-coding/icon/coze-coding.gif"
19
+ ></Image>
20
+ <Text style={{...styles.title, color: theme.textPrimary}}>应用开发中</Text>
21
+ <Text style={{...styles.description, color: theme.textSecondary}}>请稍候,界面即将呈现</Text>
16
22
  </View>
17
23
  </Screen>
18
24
  );
@@ -0,0 +1,28 @@
1
+ import { Spacing } from '@/constants/theme';
2
+ import { StyleSheet } from 'react-native';
3
+
4
+ export const styles = StyleSheet.create({
5
+ container: {
6
+ position: 'absolute',
7
+ top: 0,
8
+ left: 0,
9
+ width: '100%',
10
+ height: '100%',
11
+ display: 'flex',
12
+ flexDirection: 'column',
13
+ alignItems: 'center',
14
+ justifyContent: 'center',
15
+ },
16
+ logo: {
17
+ width: 130,
18
+ height: 109,
19
+ },
20
+ title: {
21
+ fontSize: 16,
22
+ fontWeight: 'bold',
23
+ },
24
+ description: {
25
+ fontSize: 14,
26
+ marginTop: Spacing.sm,
27
+ },
28
+ });
@@ -9,7 +9,7 @@ const { execSync } = require('child_process');
9
9
  const fs = require('fs');
10
10
  const path = require('path');
11
11
 
12
- console.log('🔍 检测缺失的依赖...\n');
12
+ console.log('检测缺失的依赖...\n');
13
13
 
14
14
  try {
15
15
  // 运行 depcheck 并获取 JSON 输出
@@ -61,11 +61,11 @@ try {
61
61
  });
62
62
 
63
63
  if (missingPackages.length === 0) {
64
- console.log('✅ 没有发现缺失的依赖!');
64
+ console.log('没有发现缺失的依赖');
65
65
  process.exit(0);
66
66
  }
67
67
 
68
- console.log('📦 发现以下缺失的依赖:');
68
+ console.log('发现以下缺失的依赖:');
69
69
  missingPackages.forEach((pkg, index) => {
70
70
  const files = missing[pkg];
71
71
  console.log(` ${index + 1}. ${pkg}`);
@@ -74,7 +74,7 @@ try {
74
74
  );
75
75
  });
76
76
 
77
- console.log('\n🚀 开始安装...\n');
77
+ console.log('\n开始安装...\n');
78
78
 
79
79
  // 使用 expo install 安装所有缺失的包
80
80
  const packagesToInstall = missingPackages.join(' ');
@@ -84,22 +84,22 @@ try {
84
84
  stdio: 'inherit',
85
85
  });
86
86
 
87
- console.log('\n✅ 所有缺失的依赖已安装完成!');
87
+ console.log('\n所有缺失的依赖已安装完成');
88
88
  } catch (installError) {
89
- console.log('\n⚠️ expo install 失败,尝试使用 npm install...\n');
89
+ console.log('\nexpo install 失败,尝试使用 npm install...\n');
90
90
 
91
91
  execSync(`npm install ${packagesToInstall}`, {
92
92
  stdio: 'inherit',
93
93
  });
94
94
 
95
- console.log('\n所有缺失的依赖已通过 npm 安装完成!');
95
+ console.log('\n所有缺失的依赖已通过 npm 安装完成');
96
96
  }
97
97
  } catch (error) {
98
98
  if (error.message.includes('depcheck')) {
99
- console.error('depcheck 未安装或运行失败');
100
- console.log('💡 尝试运行: npm install -g depcheck');
99
+ console.error('depcheck 未安装或运行失败');
100
+ console.log('尝试运行: npm install -g depcheck');
101
101
  } else {
102
- console.error('发生错误:', error.message);
102
+ console.error('发生错误:', error.message);
103
103
  }
104
104
  process.exit(1);
105
105
  }
@@ -0,0 +1,9 @@
1
+ const noEmoji = require('./rule')
2
+
3
+ const plugin = {
4
+ rules: {
5
+ 'no-emoji': noEmoji,
6
+ },
7
+ }
8
+
9
+ module.exports = plugin