@coze-arch/cli 0.0.1-alpha.db1c06 → 0.0.1-alpha.dcc485
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/README.md +1 -0
- package/lib/__templates__/expo/_npmrc +1 -0
- package/lib/__templates__/expo/client/components/Screen.tsx +2 -2
- package/lib/__templates__/expo/client/eslint.config.mjs +7 -0
- package/lib/__templates__/expo/client/scripts/install-missing-deps.js +10 -10
- package/lib/__templates__/expo/eslint-plugins/forbid-emoji/index.js +9 -0
- package/lib/__templates__/expo/eslint-plugins/forbid-emoji/rule.js +112 -0
- package/lib/__templates__/expo/eslint-plugins/forbid-emoji/tech.md +94 -0
- package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/index.js +9 -0
- package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/rule.js +120 -0
- package/lib/__templates__/expo/eslint-plugins/restrict-linear-gradient/tech.md +58 -0
- package/lib/__templates__/nextjs/AGENTS.md +54 -0
- package/lib/__templates__/nextjs/README.md +5 -0
- package/lib/__templates__/nextjs/eslint.config.mjs +5 -0
- package/lib/__templates__/nextjs/next.config.ts +1 -2
- package/lib/__templates__/nextjs/package.json +2 -5
- package/lib/__templates__/nextjs/pnpm-lock.yaml +1028 -5
- package/lib/__templates__/nextjs/scripts/build.sh +4 -1
- package/lib/__templates__/nextjs/scripts/dev.sh +8 -2
- package/lib/__templates__/nextjs/scripts/start.sh +7 -1
- package/lib/__templates__/nextjs/src/app/layout.tsx +1 -1
- package/lib/__templates__/nextjs/src/app/page.tsx +1 -2
- package/lib/__templates__/nextjs/src/server.ts +35 -0
- package/lib/__templates__/nextjs/tsconfig.json +1 -1
- package/lib/__templates__/nuxt-vue/.coze +12 -0
- package/lib/__templates__/nuxt-vue/AGENTS.md +42 -0
- package/lib/__templates__/nuxt-vue/README.md +73 -0
- package/lib/__templates__/nuxt-vue/_gitignore +24 -0
- package/lib/__templates__/nuxt-vue/_npmrc +23 -0
- package/lib/__templates__/nuxt-vue/app/app.vue +6 -0
- package/lib/__templates__/nuxt-vue/app/pages/index.vue +23 -0
- package/lib/__templates__/nuxt-vue/assets/css/main.css +24 -0
- package/lib/__templates__/nuxt-vue/nuxt.config.ts +116 -0
- package/lib/__templates__/nuxt-vue/package.json +35 -0
- package/lib/__templates__/nuxt-vue/pnpm-lock.yaml +8759 -0
- package/lib/__templates__/nuxt-vue/postcss.config.mjs +8 -0
- package/lib/__templates__/nuxt-vue/public/favicon.ico +0 -0
- package/lib/__templates__/nuxt-vue/public/robots.txt +2 -0
- package/lib/__templates__/nuxt-vue/scripts/build.sh +14 -0
- package/lib/__templates__/nuxt-vue/scripts/dev.sh +39 -0
- package/lib/__templates__/nuxt-vue/scripts/prepare.sh +14 -0
- package/lib/__templates__/nuxt-vue/scripts/start.sh +21 -0
- package/lib/__templates__/nuxt-vue/server/api/hello.ts +10 -0
- package/lib/__templates__/nuxt-vue/server/middleware/logger.ts +10 -0
- package/lib/__templates__/nuxt-vue/server/routes/health.ts +10 -0
- package/lib/__templates__/nuxt-vue/tailwind.config.js +13 -0
- package/lib/__templates__/nuxt-vue/template.config.js +87 -0
- package/lib/__templates__/nuxt-vue/tsconfig.json +18 -0
- package/lib/__templates__/taro/README.md +57 -45
- package/lib/__templates__/taro/config/index.ts +106 -41
- package/lib/__templates__/taro/config/prod.ts +4 -5
- package/lib/__templates__/taro/eslint.config.mjs +62 -6
- package/lib/__templates__/taro/package.json +19 -4
- package/lib/__templates__/taro/patches/@tarojs__plugin-mini-ci@4.1.9.patch +30 -0
- package/lib/__templates__/taro/pnpm-lock.yaml +912 -206
- package/lib/__templates__/taro/src/app.css +140 -36
- package/lib/__templates__/taro/src/components/ui/accordion.tsx +159 -0
- package/lib/__templates__/taro/src/components/ui/alert-dialog.tsx +260 -0
- package/lib/__templates__/taro/src/components/ui/alert.tsx +60 -0
- package/lib/__templates__/taro/src/components/ui/aspect-ratio.tsx +36 -0
- package/lib/__templates__/taro/src/components/ui/avatar.tsx +84 -0
- package/lib/__templates__/taro/src/components/ui/badge.tsx +37 -0
- package/lib/__templates__/taro/src/components/ui/breadcrumb.tsx +117 -0
- package/lib/__templates__/taro/src/components/ui/button-group.tsx +83 -0
- package/lib/__templates__/taro/src/components/ui/button.tsx +67 -0
- package/lib/__templates__/taro/src/components/ui/calendar.tsx +394 -0
- package/lib/__templates__/taro/src/components/ui/card.tsx +108 -0
- package/lib/__templates__/taro/src/components/ui/carousel.tsx +228 -0
- package/lib/__templates__/taro/src/components/ui/checkbox.tsx +58 -0
- package/lib/__templates__/taro/src/components/ui/code-block.tsx +169 -0
- package/lib/__templates__/taro/src/components/ui/collapsible.tsx +71 -0
- package/lib/__templates__/taro/src/components/ui/command.tsx +385 -0
- package/lib/__templates__/taro/src/components/ui/context-menu.tsx +614 -0
- package/lib/__templates__/taro/src/components/ui/dialog.tsx +256 -0
- package/lib/__templates__/taro/src/components/ui/drawer.tsx +192 -0
- package/lib/__templates__/taro/src/components/ui/dropdown-menu.tsx +561 -0
- package/lib/__templates__/taro/src/components/ui/field.tsx +228 -0
- package/lib/__templates__/taro/src/components/ui/hover-card.tsx +282 -0
- package/lib/__templates__/taro/src/components/ui/input-group.tsx +197 -0
- package/lib/__templates__/taro/src/components/ui/input-otp.tsx +136 -0
- package/lib/__templates__/taro/src/components/ui/input.tsx +56 -0
- package/lib/__templates__/taro/src/components/ui/label.tsx +24 -0
- package/lib/__templates__/taro/src/components/ui/menubar.tsx +595 -0
- package/lib/__templates__/taro/src/components/ui/navigation-menu.tsx +264 -0
- package/lib/__templates__/taro/src/components/ui/pagination.tsx +118 -0
- package/lib/__templates__/taro/src/components/ui/popover.tsx +291 -0
- package/lib/__templates__/taro/src/components/ui/portal.tsx +19 -0
- package/lib/__templates__/taro/src/components/ui/progress.tsx +28 -0
- package/lib/__templates__/taro/src/components/ui/radio-group.tsx +64 -0
- package/lib/__templates__/taro/src/components/ui/resizable.tsx +346 -0
- package/lib/__templates__/taro/src/components/ui/scroll-area.tsx +34 -0
- package/lib/__templates__/taro/src/components/ui/select.tsx +438 -0
- package/lib/__templates__/taro/src/components/ui/separator.tsx +30 -0
- package/lib/__templates__/taro/src/components/ui/sheet.tsx +262 -0
- package/lib/__templates__/taro/src/components/ui/skeleton.tsx +17 -0
- package/lib/__templates__/taro/src/components/ui/slider.tsx +203 -0
- package/lib/__templates__/taro/src/components/ui/sonner.tsx +1 -0
- package/lib/__templates__/taro/src/components/ui/switch.tsx +55 -0
- package/lib/__templates__/taro/src/components/ui/table.tsx +142 -0
- package/lib/__templates__/taro/src/components/ui/tabs.tsx +114 -0
- package/lib/__templates__/taro/src/components/ui/textarea.tsx +54 -0
- package/lib/__templates__/taro/src/components/ui/toast.tsx +517 -0
- package/lib/__templates__/taro/src/components/ui/toggle-group.tsx +120 -0
- package/lib/__templates__/taro/src/components/ui/toggle.tsx +77 -0
- package/lib/__templates__/taro/src/components/ui/tooltip.tsx +455 -0
- package/lib/__templates__/taro/src/lib/hooks/use-keyboard-offset.ts +37 -0
- package/lib/__templates__/taro/src/lib/measure.ts +115 -0
- package/lib/__templates__/taro/src/lib/platform.ts +12 -0
- package/lib/__templates__/taro/src/lib/utils.ts +6 -0
- package/lib/__templates__/taro/src/presets/dev-debug.ts +23 -0
- package/lib/__templates__/taro/src/presets/h5-container.tsx +15 -0
- package/lib/__templates__/taro/src/presets/h5-navbar.tsx +97 -30
- package/lib/__templates__/taro/src/presets/h5-styles.ts +192 -5
- package/lib/__templates__/taro/src/presets/index.tsx +4 -4
- package/lib/__templates__/templates.json +32 -0
- package/lib/__templates__/vite/AGENTS.md +41 -0
- package/lib/__templates__/vite/README.md +190 -11
- package/lib/__templates__/vite/_gitignore +1 -0
- package/lib/__templates__/vite/eslint.config.mjs +6 -1
- package/lib/__templates__/vite/package.json +10 -3
- package/lib/__templates__/vite/pnpm-lock.yaml +755 -15
- package/lib/__templates__/vite/scripts/build.sh +4 -1
- package/lib/__templates__/vite/scripts/dev.sh +9 -2
- package/lib/__templates__/vite/scripts/start.sh +9 -3
- package/lib/__templates__/vite/server/routes/index.ts +31 -0
- package/lib/__templates__/vite/server/server.ts +65 -0
- package/lib/__templates__/vite/server/vite.ts +67 -0
- package/lib/__templates__/vite/tsconfig.json +4 -3
- package/lib/__templates__/vite/vite.config.ts +4 -0
- package/lib/cli.js +99 -92
- package/package.json +6 -3
- package/lib/__templates__/taro/src/presets/wx-debug.ts +0 -23
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import Taro from '@tarojs/taro'
|
|
2
|
+
import { canUseDOM, isH5 } from './platform'
|
|
3
|
+
|
|
4
|
+
export type Rect = { left: number; top: number; width: number; height: number }
|
|
5
|
+
|
|
6
|
+
const toNumber = (v: unknown) => {
|
|
7
|
+
if (typeof v === 'number') return v
|
|
8
|
+
if (typeof v === 'string') {
|
|
9
|
+
const n = parseFloat(v)
|
|
10
|
+
return Number.isFinite(n) ? n : 0
|
|
11
|
+
}
|
|
12
|
+
return 0
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const normalizeRect = (r: any): Rect | null => {
|
|
16
|
+
if (!r) return null
|
|
17
|
+
return {
|
|
18
|
+
left: toNumber(r.left),
|
|
19
|
+
top: toNumber(r.top),
|
|
20
|
+
width: toNumber(r.width),
|
|
21
|
+
height: toNumber(r.height),
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getViewport = () => {
|
|
26
|
+
if (isH5() && canUseDOM()) {
|
|
27
|
+
return { width: window.innerWidth, height: window.innerHeight }
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const info = Taro.getSystemInfoSync()
|
|
31
|
+
return {
|
|
32
|
+
width: toNumber(info.windowWidth),
|
|
33
|
+
height: toNumber(info.windowHeight),
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
return { width: 375, height: 667 }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const getRectH5 = (id: string): Rect | null => {
|
|
41
|
+
if (!isH5() || !canUseDOM()) return null
|
|
42
|
+
const el = document.getElementById(id)
|
|
43
|
+
if (!el) return null
|
|
44
|
+
const r = el.getBoundingClientRect()
|
|
45
|
+
return normalizeRect(r)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const getRectById = (id: string): Promise<Rect | null> => {
|
|
49
|
+
const h5Rect = getRectH5(id)
|
|
50
|
+
if (h5Rect) return Promise.resolve(h5Rect)
|
|
51
|
+
return new Promise(resolve => {
|
|
52
|
+
const query = Taro.createSelectorQuery()
|
|
53
|
+
query
|
|
54
|
+
.select(`#${id}`)
|
|
55
|
+
.boundingClientRect(res => {
|
|
56
|
+
const rect = Array.isArray(res) ? res[0] : res
|
|
57
|
+
resolve(normalizeRect(rect))
|
|
58
|
+
})
|
|
59
|
+
.exec()
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const computePosition = (params: {
|
|
64
|
+
triggerRect: Rect
|
|
65
|
+
contentRect: Rect
|
|
66
|
+
align: 'start' | 'center' | 'end'
|
|
67
|
+
side: 'top' | 'bottom' | 'left' | 'right'
|
|
68
|
+
sideOffset: number
|
|
69
|
+
}) => {
|
|
70
|
+
const { triggerRect, contentRect, align, side, sideOffset } = params
|
|
71
|
+
const { width: vw, height: vh } = getViewport()
|
|
72
|
+
const margin = 8
|
|
73
|
+
|
|
74
|
+
const crossStart =
|
|
75
|
+
side === 'left' || side === 'right' ? triggerRect.top : triggerRect.left
|
|
76
|
+
const crossSize =
|
|
77
|
+
side === 'left' || side === 'right'
|
|
78
|
+
? triggerRect.height
|
|
79
|
+
: triggerRect.width
|
|
80
|
+
const contentCrossSize =
|
|
81
|
+
side === 'left' || side === 'right'
|
|
82
|
+
? contentRect.height
|
|
83
|
+
: contentRect.width
|
|
84
|
+
|
|
85
|
+
const cross = (() => {
|
|
86
|
+
if (align === 'start') return crossStart
|
|
87
|
+
if (align === 'end') return crossStart + crossSize - contentCrossSize
|
|
88
|
+
return crossStart + crossSize / 2 - contentCrossSize / 2
|
|
89
|
+
})()
|
|
90
|
+
|
|
91
|
+
let left = 0
|
|
92
|
+
let top = 0
|
|
93
|
+
|
|
94
|
+
if (side === 'bottom' || side === 'top') {
|
|
95
|
+
left = cross
|
|
96
|
+
top =
|
|
97
|
+
side === 'bottom'
|
|
98
|
+
? triggerRect.top + triggerRect.height + sideOffset
|
|
99
|
+
: triggerRect.top - contentRect.height - sideOffset
|
|
100
|
+
} else {
|
|
101
|
+
top = cross
|
|
102
|
+
left =
|
|
103
|
+
side === 'right'
|
|
104
|
+
? triggerRect.left + triggerRect.width + sideOffset
|
|
105
|
+
: triggerRect.left - contentRect.width - sideOffset
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const maxLeft = Math.max(margin, vw - contentRect.width - margin)
|
|
109
|
+
const maxTop = Math.max(margin, vh - contentRect.height - margin)
|
|
110
|
+
|
|
111
|
+
left = Math.min(Math.max(left, margin), maxLeft)
|
|
112
|
+
top = Math.min(Math.max(top, margin), maxTop)
|
|
113
|
+
|
|
114
|
+
return { left, top }
|
|
115
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Taro from "@tarojs/taro"
|
|
2
|
+
|
|
3
|
+
export const canUseDOM = () => typeof window !== "undefined" && typeof document !== "undefined"
|
|
4
|
+
|
|
5
|
+
export const isH5 = () => {
|
|
6
|
+
try {
|
|
7
|
+
return Taro.getEnv() === Taro.ENV_TYPE.WEB
|
|
8
|
+
} catch {
|
|
9
|
+
return canUseDOM()
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import Taro from '@tarojs/taro';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 小程序调试工具
|
|
5
|
+
* 在开发版/体验版自动开启调试模式
|
|
6
|
+
* 支持微信小程序和抖音小程序
|
|
7
|
+
*/
|
|
8
|
+
export function devDebug() {
|
|
9
|
+
const env = Taro.getEnv();
|
|
10
|
+
if (env === Taro.ENV_TYPE.WEAPP || env === Taro.ENV_TYPE.TT) {
|
|
11
|
+
try {
|
|
12
|
+
const accountInfo = Taro.getAccountInfoSync();
|
|
13
|
+
const envVersion = accountInfo.miniProgram.envVersion;
|
|
14
|
+
console.log('[Debug] envVersion:', envVersion);
|
|
15
|
+
|
|
16
|
+
if (envVersion !== 'release') {
|
|
17
|
+
Taro.setEnableDebug({ enableDebug: true });
|
|
18
|
+
}
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error('[Debug] 开启调试模式失败:', error);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { H5NavBar } from './h5-navbar';
|
|
3
|
+
|
|
4
|
+
export const H5Container = ({ children }: PropsWithChildren) => {
|
|
5
|
+
if (TARO_ENV !== 'h5') {
|
|
6
|
+
return <>{children}</>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<>
|
|
11
|
+
<H5NavBar />
|
|
12
|
+
{children}
|
|
13
|
+
</>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { View, Text } from '@tarojs/components';
|
|
2
2
|
import Taro, { useDidShow, usePageScroll } from '@tarojs/taro';
|
|
3
|
-
import { useState, useEffect,
|
|
3
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
4
4
|
import { ChevronLeft, House } from 'lucide-react-taro';
|
|
5
5
|
|
|
6
6
|
interface NavConfig {
|
|
@@ -37,6 +37,11 @@ const DEFAULT_NAV_STATE: NavState = {
|
|
|
37
37
|
leftIcon: LeftIcon.None,
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
const getGlobalWindowConfig = (): Partial<NavConfig> => {
|
|
41
|
+
const app = Taro.getApp();
|
|
42
|
+
return app?.config?.window || {};
|
|
43
|
+
};
|
|
44
|
+
|
|
40
45
|
const getTabBarPages = (): Set<string> => {
|
|
41
46
|
const tabBar = Taro.getApp()?.config?.tabBar;
|
|
42
47
|
return new Set(
|
|
@@ -44,16 +49,26 @@ const getTabBarPages = (): Set<string> => {
|
|
|
44
49
|
);
|
|
45
50
|
};
|
|
46
51
|
|
|
52
|
+
const getHomePage = (): string => {
|
|
53
|
+
const app = Taro.getApp();
|
|
54
|
+
return app?.config?.pages?.[0] || 'pages/index/index';
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const cleanPath = (path: string): string => path.replace(/^\//, '');
|
|
58
|
+
|
|
47
59
|
const computeLeftIcon = (
|
|
48
60
|
route: string,
|
|
49
61
|
tabBarPages: Set<string>,
|
|
50
62
|
historyLength: number,
|
|
63
|
+
homePage: string,
|
|
51
64
|
): LeftIcon => {
|
|
52
65
|
if (!route) return LeftIcon.None;
|
|
53
66
|
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const
|
|
67
|
+
const cleanRoute = cleanPath(route);
|
|
68
|
+
const cleanHomePage = cleanPath(homePage);
|
|
69
|
+
const isHomePage = cleanRoute === cleanHomePage;
|
|
70
|
+
const isTabBarPage =
|
|
71
|
+
tabBarPages.has(cleanRoute) || tabBarPages.has(`/${cleanRoute}`);
|
|
57
72
|
const hasHistory = historyLength > 1;
|
|
58
73
|
|
|
59
74
|
if (isTabBarPage || isHomePage) return LeftIcon.None;
|
|
@@ -61,29 +76,60 @@ const computeLeftIcon = (
|
|
|
61
76
|
return LeftIcon.Home;
|
|
62
77
|
};
|
|
63
78
|
|
|
64
|
-
export const H5NavBar = (
|
|
79
|
+
export const H5NavBar = () => {
|
|
65
80
|
const [navState, setNavState] = useState<NavState>(DEFAULT_NAV_STATE);
|
|
66
81
|
const [scrollOpacity, setScrollOpacity] = useState(0);
|
|
67
82
|
|
|
68
83
|
const updateNavState = useCallback(() => {
|
|
69
84
|
const pages = Taro.getCurrentPages();
|
|
85
|
+
if (pages.length === 0) {
|
|
86
|
+
setNavState(prev => ({ ...prev, visible: false }));
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
70
90
|
const currentPage = pages[pages.length - 1];
|
|
71
91
|
const route = currentPage?.route || '';
|
|
72
|
-
|
|
92
|
+
if (!route) return;
|
|
93
|
+
|
|
94
|
+
const pageConfig: NavConfig = (currentPage as any)?.config || {};
|
|
95
|
+
const globalConfig = getGlobalWindowConfig();
|
|
73
96
|
const tabBarPages = getTabBarPages();
|
|
97
|
+
const homePage = getHomePage();
|
|
98
|
+
|
|
99
|
+
const cleanRoute = cleanPath(route);
|
|
100
|
+
const cleanHomePage = cleanPath(homePage);
|
|
101
|
+
|
|
102
|
+
const isHomePage = cleanRoute === cleanHomePage;
|
|
103
|
+
const isTabBarPage =
|
|
104
|
+
tabBarPages.has(cleanRoute) || tabBarPages.has(`/${cleanRoute}`);
|
|
74
105
|
|
|
75
|
-
const
|
|
106
|
+
const shouldHideNav =
|
|
107
|
+
tabBarPages.size <= 1 &&
|
|
108
|
+
pages.length <= 1 &&
|
|
109
|
+
(isHomePage || isTabBarPage);
|
|
76
110
|
|
|
77
111
|
setNavState({
|
|
78
|
-
visible: !
|
|
79
|
-
title:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
112
|
+
visible: !shouldHideNav,
|
|
113
|
+
title:
|
|
114
|
+
document.title ||
|
|
115
|
+
pageConfig.navigationBarTitleText ||
|
|
116
|
+
globalConfig.navigationBarTitleText ||
|
|
117
|
+
'',
|
|
118
|
+
bgColor:
|
|
119
|
+
pageConfig.navigationBarBackgroundColor ||
|
|
120
|
+
globalConfig.navigationBarBackgroundColor ||
|
|
121
|
+
'#ffffff',
|
|
122
|
+
textStyle:
|
|
123
|
+
pageConfig.navigationBarTextStyle ||
|
|
124
|
+
globalConfig.navigationBarTextStyle ||
|
|
125
|
+
'black',
|
|
126
|
+
navStyle:
|
|
127
|
+
pageConfig.navigationStyle || globalConfig.navigationStyle || 'default',
|
|
128
|
+
transparent:
|
|
129
|
+
pageConfig.transparentTitle || globalConfig.transparentTitle || 'none',
|
|
130
|
+
leftIcon: shouldHideNav
|
|
85
131
|
? LeftIcon.None
|
|
86
|
-
: computeLeftIcon(
|
|
132
|
+
: computeLeftIcon(cleanRoute, tabBarPages, pages.length, cleanHomePage),
|
|
87
133
|
});
|
|
88
134
|
}, []);
|
|
89
135
|
|
|
@@ -100,23 +146,42 @@ export const H5NavBar = ({ children }: PropsWithChildren) => {
|
|
|
100
146
|
useEffect(() => {
|
|
101
147
|
if (TARO_ENV !== 'h5') return;
|
|
102
148
|
|
|
103
|
-
|
|
104
|
-
const observer = new MutationObserver(() =>
|
|
105
|
-
|
|
149
|
+
let timer: NodeJS.Timeout | null = null;
|
|
150
|
+
const observer = new MutationObserver(() => {
|
|
151
|
+
if (timer) clearTimeout(timer);
|
|
152
|
+
timer = setTimeout(() => {
|
|
153
|
+
updateNavState();
|
|
154
|
+
}, 50);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
observer.observe(document.head, {
|
|
106
158
|
subtree: true,
|
|
107
159
|
childList: true,
|
|
108
160
|
characterData: true,
|
|
109
161
|
});
|
|
110
162
|
|
|
111
|
-
|
|
163
|
+
updateNavState();
|
|
164
|
+
|
|
165
|
+
return () => {
|
|
166
|
+
observer.disconnect();
|
|
167
|
+
if (timer) clearTimeout(timer);
|
|
168
|
+
};
|
|
112
169
|
}, [updateNavState]);
|
|
113
170
|
|
|
114
|
-
|
|
115
|
-
TARO_ENV
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
171
|
+
const shouldRender =
|
|
172
|
+
TARO_ENV === 'h5' && navState.visible && navState.navStyle !== 'custom';
|
|
173
|
+
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
if (TARO_ENV !== 'h5') return;
|
|
176
|
+
if (shouldRender) {
|
|
177
|
+
document.body.classList.add('h5-navbar-visible');
|
|
178
|
+
} else {
|
|
179
|
+
document.body.classList.remove('h5-navbar-visible');
|
|
180
|
+
}
|
|
181
|
+
}, [shouldRender]);
|
|
182
|
+
|
|
183
|
+
if (!shouldRender) {
|
|
184
|
+
return <></>;
|
|
120
185
|
}
|
|
121
186
|
|
|
122
187
|
const iconColor = navState.textStyle === 'white' ? '#fff' : '#333';
|
|
@@ -134,12 +199,15 @@ export const H5NavBar = ({ children }: PropsWithChildren) => {
|
|
|
134
199
|
};
|
|
135
200
|
|
|
136
201
|
const handleBack = () => Taro.navigateBack();
|
|
137
|
-
const handleGoHome = () =>
|
|
202
|
+
const handleGoHome = () => {
|
|
203
|
+
const homePage = getHomePage();
|
|
204
|
+
Taro.reLaunch({ url: `/${homePage}` });
|
|
205
|
+
};
|
|
138
206
|
|
|
139
207
|
return (
|
|
140
|
-
|
|
208
|
+
<>
|
|
141
209
|
<View
|
|
142
|
-
className=
|
|
210
|
+
className="fixed top-0 left-0 right-0 h-11 flex items-center justify-center z-1000"
|
|
143
211
|
style={getBgStyle()}
|
|
144
212
|
>
|
|
145
213
|
{navState.leftIcon === LeftIcon.Back && (
|
|
@@ -165,7 +233,6 @@ export const H5NavBar = ({ children }: PropsWithChildren) => {
|
|
|
165
233
|
</Text>
|
|
166
234
|
</View>
|
|
167
235
|
<View className="h-11 shrink-0" />
|
|
168
|
-
|
|
169
|
-
</View>
|
|
236
|
+
</>
|
|
170
237
|
);
|
|
171
238
|
};
|
|
@@ -2,11 +2,8 @@
|
|
|
2
2
|
* H5 端特殊样式注入
|
|
3
3
|
* 如无必要,请勿修改本文件
|
|
4
4
|
*/
|
|
5
|
-
export function injectH5Styles() {
|
|
6
|
-
if (TARO_ENV !== 'h5') return;
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
style.innerHTML = `
|
|
6
|
+
const H5_BASE_STYLES = `
|
|
10
7
|
/* H5 端隐藏 TabBar 空图标(只隐藏没有 src 的图标) */
|
|
11
8
|
.weui-tabbar__icon:not([src]),
|
|
12
9
|
.weui-tabbar__icon[src=''] {
|
|
@@ -28,6 +25,196 @@ vite-error-overlay::part(window) {
|
|
|
28
25
|
max-width: 90vw;
|
|
29
26
|
padding: 10px;
|
|
30
27
|
}
|
|
31
|
-
|
|
28
|
+
|
|
29
|
+
.taro_page {
|
|
30
|
+
overflow: auto;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
::-webkit-scrollbar {
|
|
34
|
+
width: 4px;
|
|
35
|
+
height: 4px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
::-webkit-scrollbar-track {
|
|
39
|
+
background: transparent;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
::-webkit-scrollbar-thumb {
|
|
43
|
+
background: rgba(0, 0, 0, 0.2);
|
|
44
|
+
border-radius: 2px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
::-webkit-scrollbar-thumb:hover {
|
|
48
|
+
background: rgba(0, 0, 0, 0.3);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* H5 导航栏页面自动添加顶部间距 */
|
|
52
|
+
body.h5-navbar-visible .taro_page {
|
|
53
|
+
padding-top: 44px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
body.h5-navbar-visible .toaster[data-position^="top"] {
|
|
57
|
+
top: 44px !important;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Sheet 组件在 H5 导航栏下的位置修正 */
|
|
61
|
+
body.h5-navbar-visible .sheet-content:not([data-side="bottom"]) {
|
|
62
|
+
top: 44px !important;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
* H5 端 rem 适配:与小程序 rpx 缩放一致
|
|
67
|
+
* 375px 屏幕:1rem = 16px,小程序 32rpx = 16px
|
|
68
|
+
*/
|
|
69
|
+
html {
|
|
70
|
+
font-size: 4vw !important;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* H5 端组件默认样式修复 */
|
|
74
|
+
taro-view-core {
|
|
75
|
+
display: block;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
taro-text-core {
|
|
79
|
+
display: inline;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
taro-input-core {
|
|
83
|
+
display: block;
|
|
84
|
+
width: 100%;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
taro-input-core input {
|
|
88
|
+
width: 100%;
|
|
89
|
+
background: transparent;
|
|
90
|
+
border: none;
|
|
91
|
+
outline: none;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
taro-input-core.taro-otp-hidden-input input {
|
|
95
|
+
color: transparent;
|
|
96
|
+
caret-color: transparent;
|
|
97
|
+
-webkit-text-fill-color: transparent;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* 全局按钮样式重置 */
|
|
101
|
+
taro-button-core,
|
|
102
|
+
button {
|
|
103
|
+
margin: 0 !important;
|
|
104
|
+
padding: 0 !important;
|
|
105
|
+
line-height: inherit;
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: center;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
taro-button-core::after,
|
|
112
|
+
button::after {
|
|
113
|
+
border: none;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
taro-textarea-core > textarea,
|
|
117
|
+
.taro-textarea,
|
|
118
|
+
textarea.taro-textarea {
|
|
119
|
+
resize: none !important;
|
|
120
|
+
}
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const PC_WIDESCREEN_STYLES = `
|
|
124
|
+
/* PC 宽屏适配 - 基础布局 */
|
|
125
|
+
@media (min-width: 769px) {
|
|
126
|
+
html {
|
|
127
|
+
font-size: 15px !important;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
body {
|
|
131
|
+
background-color: #f3f4f6 !important;
|
|
132
|
+
display: flex !important;
|
|
133
|
+
justify-content: center !important;
|
|
134
|
+
align-items: center !important;
|
|
135
|
+
min-height: 100vh !important;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
|
|
140
|
+
const PC_WIDESCREEN_PHONE_FRAME = `
|
|
141
|
+
/* PC 宽屏适配 - 手机框样式(有 TabBar 页面) */
|
|
142
|
+
@media (min-width: 769px) {
|
|
143
|
+
.taro-tabbar__container {
|
|
144
|
+
width: 375px !important;
|
|
145
|
+
max-width: 375px !important;
|
|
146
|
+
height: calc(100vh - 40px) !important;
|
|
147
|
+
max-height: 900px !important;
|
|
148
|
+
background-color: #fff !important;
|
|
149
|
+
transform: translateX(0) !important;
|
|
150
|
+
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1) !important;
|
|
151
|
+
border-radius: 20px !important;
|
|
152
|
+
overflow: hidden !important;
|
|
153
|
+
position: relative !important;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.taro-tabbar__panel {
|
|
157
|
+
height: 100% !important;
|
|
158
|
+
overflow: auto !important;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* PC 宽屏适配 - Toast 定位到手机框范围内 */
|
|
163
|
+
@media (min-width: 769px) {
|
|
164
|
+
body .toaster {
|
|
165
|
+
left: 50% !important;
|
|
166
|
+
right: auto !important;
|
|
167
|
+
width: 375px !important;
|
|
168
|
+
max-width: 375px !important;
|
|
169
|
+
transform: translateX(-50%) !important;
|
|
170
|
+
box-sizing: border-box !important;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* PC 宽屏适配 - 手机框样式(无 TabBar 页面,通过 JS 添加 no-tabbar 类) */
|
|
175
|
+
@media (min-width: 769px) {
|
|
176
|
+
body.no-tabbar #app {
|
|
177
|
+
width: 375px !important;
|
|
178
|
+
max-width: 375px !important;
|
|
179
|
+
height: calc(100vh - 40px) !important;
|
|
180
|
+
max-height: 900px !important;
|
|
181
|
+
background-color: #fff !important;
|
|
182
|
+
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1) !important;
|
|
183
|
+
border-radius: 20px !important;
|
|
184
|
+
overflow: hidden !important;
|
|
185
|
+
position: relative !important;
|
|
186
|
+
transform: translateX(0) !important;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
body.no-tabbar #app .taro_router {
|
|
190
|
+
height: 100% !important;
|
|
191
|
+
overflow: auto !important;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
`;
|
|
195
|
+
|
|
196
|
+
function injectStyles() {
|
|
197
|
+
const style = document.createElement('style');
|
|
198
|
+
style.innerHTML =
|
|
199
|
+
H5_BASE_STYLES + PC_WIDESCREEN_STYLES + PC_WIDESCREEN_PHONE_FRAME;
|
|
32
200
|
document.head.appendChild(style);
|
|
33
201
|
}
|
|
202
|
+
|
|
203
|
+
function setupTabbarDetection() {
|
|
204
|
+
const checkTabbar = () => {
|
|
205
|
+
const hasTabbar = !!document.querySelector('.taro-tabbar__container');
|
|
206
|
+
document.body.classList.toggle('no-tabbar', !hasTabbar);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
checkTabbar();
|
|
210
|
+
|
|
211
|
+
const observer = new MutationObserver(checkTabbar);
|
|
212
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export function injectH5Styles() {
|
|
216
|
+
if (TARO_ENV !== 'h5') return;
|
|
217
|
+
|
|
218
|
+
injectStyles();
|
|
219
|
+
setupTabbarDetection();
|
|
220
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { useLaunch } from '@tarojs/taro';
|
|
2
2
|
import { PropsWithChildren } from 'react';
|
|
3
|
-
import { H5NavBar } from './h5-navbar';
|
|
4
3
|
import { injectH5Styles } from './h5-styles';
|
|
5
|
-
import {
|
|
4
|
+
import { devDebug } from './dev-debug';
|
|
5
|
+
import { H5Container } from './h5-container';
|
|
6
6
|
|
|
7
7
|
export const Preset = ({ children }: PropsWithChildren) => {
|
|
8
8
|
useLaunch(() => {
|
|
9
|
-
|
|
9
|
+
devDebug();
|
|
10
10
|
injectH5Styles();
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
if (TARO_ENV === 'h5') {
|
|
14
|
-
return <
|
|
14
|
+
return <H5Container>{children}</H5Container>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
return <>{children}</>;
|
|
@@ -62,6 +62,38 @@
|
|
|
62
62
|
"additionalProperties": false
|
|
63
63
|
}
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
"name": "nuxt-vue",
|
|
67
|
+
"description": "Nuxt.js(服务端 + Vue):`coze init ${COZE_WORKSPACE_PATH} --template nuxt-vue`\n- 适用:全栈应用、需要服务端接口能力的 Vue 项目\n- 特点:\n - **服务端能力**:内置服务端 API 路由,可直接创建后端接口\n - **Vue 3**:基于最新的 Vue 3 Composition API\n - **Vite**:使用 Vite 作为构建工具,开发体验极佳\n - **TypeScript**:完整的 TypeScript 支持\n - **文件路由**:基于文件系统的自动路由\n - **项目理解加速**:可依赖项目下 `package.json` 和 `nuxt.config.ts` 理解项目配置",
|
|
68
|
+
"location": "./nuxt-vue",
|
|
69
|
+
"paramsSchema": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"appName": {
|
|
73
|
+
"type": "string",
|
|
74
|
+
"minLength": 1,
|
|
75
|
+
"pattern": "^[a-z0-9-]+$",
|
|
76
|
+
"description": "Application name (lowercase, alphanumeric and hyphens only)"
|
|
77
|
+
},
|
|
78
|
+
"port": {
|
|
79
|
+
"type": "number",
|
|
80
|
+
"default": 5000,
|
|
81
|
+
"minimum": 1024,
|
|
82
|
+
"maximum": 65535,
|
|
83
|
+
"description": "Development server port (for Nuxt dev server)"
|
|
84
|
+
},
|
|
85
|
+
"hmrPort": {
|
|
86
|
+
"type": "number",
|
|
87
|
+
"default": 6000,
|
|
88
|
+
"minimum": 1024,
|
|
89
|
+
"maximum": 65535,
|
|
90
|
+
"description": "Hot Module Replacement (HMR) port"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"required": [],
|
|
94
|
+
"additionalProperties": false
|
|
95
|
+
}
|
|
96
|
+
},
|
|
65
97
|
{
|
|
66
98
|
"name": "taro",
|
|
67
99
|
"description": "Taro(小程序 + H5):`coze init ${COZE_WORKSPACE_PATH} --template taro`\n- 适用:微信小程序、H5 跨端应用\n- 前后端分离架构:Taro 4 + NestJS\n- 支持微信小程序和 H5 双端构建\n- 使用 TailwindCSS + weapp-tailwindcss 实现跨端样式",
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 项目上下文
|
|
2
|
+
|
|
3
|
+
## 技术栈
|
|
4
|
+
|
|
5
|
+
- **核心**: Vite 7, TypeScript, Express
|
|
6
|
+
- **UI**: Tailwind CSS
|
|
7
|
+
|
|
8
|
+
## 目录结构
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
├── scripts/ # 构建与启动脚本
|
|
12
|
+
│ ├── build.sh # 构建脚本
|
|
13
|
+
│ ├── dev.sh # 开发环境启动脚本
|
|
14
|
+
│ ├── prepare.sh # 预处理脚本
|
|
15
|
+
│ └── start.sh # 生产环境启动脚本
|
|
16
|
+
├── server/ # 服务端逻辑
|
|
17
|
+
│ ├── routes/ # API 路由
|
|
18
|
+
│ ├── server.ts # Express 服务入口
|
|
19
|
+
│ └── vite.ts # Vite 中间件集成
|
|
20
|
+
├── src/ # 前端源码
|
|
21
|
+
│ ├── index.css # 全局样式
|
|
22
|
+
│ ├── index.ts # 客户端入口
|
|
23
|
+
│ └── main.ts # 主逻辑
|
|
24
|
+
├── index.html # 入口 HTML
|
|
25
|
+
├── package.json # 项目依赖管理
|
|
26
|
+
├── tsconfig.json # TypeScript 配置
|
|
27
|
+
└── vite.config.ts # Vite 配置
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 包管理规范
|
|
31
|
+
|
|
32
|
+
**仅允许使用 pnpm** 作为包管理器,**严禁使用 npm 或 yarn**。
|
|
33
|
+
**常用命令**:
|
|
34
|
+
- 安装依赖:`pnpm add <package>`
|
|
35
|
+
- 安装开发依赖:`pnpm add -D <package>`
|
|
36
|
+
- 安装所有依赖:`pnpm install`
|
|
37
|
+
- 移除依赖:`pnpm remove <package>`
|
|
38
|
+
|
|
39
|
+
## 开发规范
|
|
40
|
+
|
|
41
|
+
- 使用 Tailwind CSS 进行样式开发
|