@coze-arch/cli 0.0.1-alpha.a37c60 → 0.0.1-alpha.a8e799
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 +10 -6
- package/lib/__templates__/expo/.cozeproj/scripts/prod_build.sh +2 -2
- package/lib/__templates__/expo/.cozeproj/scripts/prod_run.sh +3 -4
- package/lib/__templates__/expo/README.md +58 -8
- package/lib/__templates__/expo/_gitignore +1 -1
- package/lib/__templates__/expo/_npmrc +2 -4
- package/lib/__templates__/expo/client/app/_layout.tsx +1 -1
- package/lib/__templates__/expo/client/app/index.ts +1 -0
- package/lib/__templates__/expo/client/app.config.ts +71 -0
- package/lib/__templates__/expo/client/package.json +92 -0
- package/lib/__templates__/expo/client/screens/home/index.tsx +0 -1
- package/lib/__templates__/expo/client/tsconfig.json +24 -0
- package/lib/__templates__/expo/package.json +7 -106
- package/lib/__templates__/expo/pnpm-lock.yaml +111 -2130
- package/lib/__templates__/expo/pnpm-workspace.yaml +3 -0
- package/lib/__templates__/expo/server/package.json +17 -0
- package/lib/__templates__/expo/tsconfig.json +1 -24
- package/lib/__templates__/nextjs/next.config.ts +0 -1
- package/lib/__templates__/templates.json +0 -27
- package/lib/cli.js +31 -144
- package/package.json +3 -5
- package/lib/__templates__/expo/app.json +0 -63
- package/lib/__templates__/expo/babel.config.js +0 -19
- package/lib/__templates__/expo/client/app/(tabs)/_layout.tsx +0 -43
- package/lib/__templates__/expo/client/app/(tabs)/home.tsx +0 -1
- package/lib/__templates__/expo/client/app/(tabs)/index.tsx +0 -7
- package/lib/__templates__/expo/client/app/+not-found.tsx +0 -79
- package/lib/__templates__/expo/client/index.js +0 -12
- /package/lib/__templates__/expo/{eslint-formatter-simple.mjs → client/eslint-formatter-simple.mjs} +0 -0
- /package/lib/__templates__/expo/{eslint.config.mjs → client/eslint.config.mjs} +0 -0
- /package/lib/__templates__/expo/{metro.config.js → client/metro.config.js} +0 -0
- /package/lib/__templates__/expo/{src → server/src}/index.ts +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "server",
|
|
3
|
+
"private": true,
|
|
4
|
+
"scripts": {
|
|
5
|
+
"preinstall": "npx only-allow pnpm",
|
|
6
|
+
"dev": "NODE_ENV=development tsx ./src/index.ts",
|
|
7
|
+
"build": "pnpm exec esbuild src/index.ts --platform=node --packages=external --bundle --format=esm --outdir=dist",
|
|
8
|
+
"start": "NODE_ENV=production PORT=${PORT:-5000} node dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"express": "^4.22.1"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"@types/express": "^5.0.6",
|
|
15
|
+
"tsx": "^4.21.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,24 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "expo/tsconfig.base",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"skipLibCheck": true,
|
|
5
|
-
"jsx": "react-jsx",
|
|
6
|
-
"baseUrl": ".",
|
|
7
|
-
"strict": true,
|
|
8
|
-
"noEmit": true,
|
|
9
|
-
"paths": {
|
|
10
|
-
"@/*": ["./client/*"]
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"include": ["**/*.ts", "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts"],
|
|
14
|
-
"exclude": [
|
|
15
|
-
"node_modules",
|
|
16
|
-
"**/*.spec.ts",
|
|
17
|
-
"**/*.test.ts",
|
|
18
|
-
"**/*.spec.tsx",
|
|
19
|
-
"**/*.test.tsx",
|
|
20
|
-
"dist",
|
|
21
|
-
"build",
|
|
22
|
-
"client/.expo"
|
|
23
|
-
]
|
|
24
|
-
}
|
|
1
|
+
{}
|
|
@@ -39,33 +39,6 @@
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
|
-
{
|
|
43
|
-
"name": "test-only",
|
|
44
|
-
"description": "test-only template",
|
|
45
|
-
"location": "./test-only",
|
|
46
|
-
"paramsSchema": {
|
|
47
|
-
"appName": {
|
|
48
|
-
"type": "string",
|
|
49
|
-
"description": "Application name (lowercase, alphanumeric and hyphens only)",
|
|
50
|
-
"pattern": "^[a-z0-9-]+$"
|
|
51
|
-
},
|
|
52
|
-
"port": {
|
|
53
|
-
"type": "number",
|
|
54
|
-
"description": "Development server port",
|
|
55
|
-
"default": 5000,
|
|
56
|
-
"minimum": 1024,
|
|
57
|
-
"maximum": 65535
|
|
58
|
-
},
|
|
59
|
-
"includeTests": {
|
|
60
|
-
"type": "boolean",
|
|
61
|
-
"description": "Include test files"
|
|
62
|
-
},
|
|
63
|
-
"addCopyright": {
|
|
64
|
-
"type": "boolean",
|
|
65
|
-
"description": "Add copyright header to source files"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
42
|
{
|
|
70
43
|
"name": "vite",
|
|
71
44
|
"description": "vite template",
|
package/lib/cli.js
CHANGED
|
@@ -1248,139 +1248,17 @@ const convertDotfileName = (filePath) => {
|
|
|
1248
1248
|
};
|
|
1249
1249
|
|
|
1250
1250
|
/**
|
|
1251
|
-
*
|
|
1251
|
+
* 复制并处理模板文件到目标目录
|
|
1252
1252
|
*
|
|
1253
|
-
* @param
|
|
1254
|
-
* @param
|
|
1253
|
+
* @param templatePath - 模板目录路径
|
|
1254
|
+
* @param outputPath - 输出目录路径
|
|
1255
1255
|
* @param context - 模板上下文
|
|
1256
|
-
* @returns 处理后的文件信息,或 null 表示跳过该文件
|
|
1257
1256
|
*/
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
|
|
1257
|
+
const processTemplateFiles = async (
|
|
1258
|
+
templatePath,
|
|
1259
|
+
outputPath,
|
|
1261
1260
|
context,
|
|
1262
1261
|
) => {
|
|
1263
|
-
if (!templateConfig.onFileRender) {
|
|
1264
|
-
return fileInfo;
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
const result = await templateConfig.onFileRender(
|
|
1268
|
-
fileInfo,
|
|
1269
|
-
context,
|
|
1270
|
-
);
|
|
1271
|
-
|
|
1272
|
-
// false: 跳过文件
|
|
1273
|
-
if (result === false) {
|
|
1274
|
-
return null;
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
// undefined/void: 使用默认内容
|
|
1278
|
-
if (result === undefined || result === null) {
|
|
1279
|
-
return fileInfo;
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
// string: 作为 content,其他不变
|
|
1283
|
-
if (typeof result === 'string') {
|
|
1284
|
-
return {
|
|
1285
|
-
...fileInfo,
|
|
1286
|
-
content: result,
|
|
1287
|
-
};
|
|
1288
|
-
}
|
|
1289
|
-
|
|
1290
|
-
// FileRenderInfo: 使用新对象的信息
|
|
1291
|
-
return result;
|
|
1292
|
-
};
|
|
1293
|
-
|
|
1294
|
-
/**
|
|
1295
|
-
* 处理单个文件
|
|
1296
|
-
*/
|
|
1297
|
-
const processSingleFile = async (options
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
) => {
|
|
1304
|
-
const { file, templatePath, outputPath, context, templateConfig } = options;
|
|
1305
|
-
|
|
1306
|
-
const srcPath = path.join(templatePath, file);
|
|
1307
|
-
const destFile = convertDotfileName(file);
|
|
1308
|
-
|
|
1309
|
-
logger.verbose(
|
|
1310
|
-
` - Processing: ${file}${destFile !== file ? ` -> ${destFile}` : ''}`,
|
|
1311
|
-
);
|
|
1312
|
-
|
|
1313
|
-
// 判断是否为二进制文件
|
|
1314
|
-
const isBinary = !shouldRenderFile(srcPath);
|
|
1315
|
-
let content;
|
|
1316
|
-
let wasRendered = false;
|
|
1317
|
-
|
|
1318
|
-
if (isBinary) {
|
|
1319
|
-
// 二进制文件,读取为 buffer 然后转为 base64
|
|
1320
|
-
const buffer = await fs$1.readFile(srcPath);
|
|
1321
|
-
content = buffer.toString('base64');
|
|
1322
|
-
} else {
|
|
1323
|
-
// 文本文件,渲染后的内容
|
|
1324
|
-
content = await renderTemplate(srcPath, context);
|
|
1325
|
-
wasRendered = true;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
// 构造文件信息对象
|
|
1329
|
-
const fileInfo = {
|
|
1330
|
-
path: file,
|
|
1331
|
-
destPath: destFile,
|
|
1332
|
-
content,
|
|
1333
|
-
isBinary,
|
|
1334
|
-
wasRendered,
|
|
1335
|
-
};
|
|
1336
|
-
|
|
1337
|
-
// 执行文件渲染钩子
|
|
1338
|
-
const processedFileInfo = await executeFileRenderHook(
|
|
1339
|
-
templateConfig,
|
|
1340
|
-
fileInfo,
|
|
1341
|
-
context,
|
|
1342
|
-
);
|
|
1343
|
-
|
|
1344
|
-
// 如果返回 null,跳过该文件
|
|
1345
|
-
if (processedFileInfo === null) {
|
|
1346
|
-
logger.verbose(' ⊘ Skipped by onFileRender hook');
|
|
1347
|
-
return;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
// 使用处理后的目标路径
|
|
1351
|
-
const finalDestPath = path.join(outputPath, processedFileInfo.destPath);
|
|
1352
|
-
|
|
1353
|
-
// 确保目标目录存在
|
|
1354
|
-
await ensureDir(path.dirname(finalDestPath));
|
|
1355
|
-
|
|
1356
|
-
// 写入文件
|
|
1357
|
-
if (processedFileInfo.isBinary) {
|
|
1358
|
-
// 二进制文件:如果内容没变,直接复制;否则从 base64 解码写入
|
|
1359
|
-
if (processedFileInfo.content === content) {
|
|
1360
|
-
await fs$1.copyFile(srcPath, finalDestPath);
|
|
1361
|
-
logger.verbose(' ✓ Copied (binary)');
|
|
1362
|
-
} else {
|
|
1363
|
-
const buffer = Buffer.from(processedFileInfo.content, 'base64');
|
|
1364
|
-
await fs$1.writeFile(finalDestPath, buffer);
|
|
1365
|
-
logger.verbose(' ✓ Written (binary, modified by hook)');
|
|
1366
|
-
}
|
|
1367
|
-
} else {
|
|
1368
|
-
// 文本文件
|
|
1369
|
-
await fs$1.writeFile(finalDestPath, processedFileInfo.content, 'utf-8');
|
|
1370
|
-
logger.verbose(' ✓ Rendered and written');
|
|
1371
|
-
}
|
|
1372
|
-
};
|
|
1373
|
-
|
|
1374
|
-
/**
|
|
1375
|
-
* 复制并处理模板文件到目标目录
|
|
1376
|
-
*/
|
|
1377
|
-
const processTemplateFiles = async (options
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
) => {
|
|
1383
|
-
const { templatePath, outputPath, context, templateConfig } = options;
|
|
1384
1262
|
logger.verbose('Processing template files:');
|
|
1385
1263
|
logger.verbose(` - Template path: ${templatePath}`);
|
|
1386
1264
|
logger.verbose(` - Output path: ${outputPath}`);
|
|
@@ -1411,15 +1289,29 @@ const processTemplateFiles = async (options
|
|
|
1411
1289
|
}
|
|
1412
1290
|
|
|
1413
1291
|
await Promise.all(
|
|
1414
|
-
files.map(file =>
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1292
|
+
files.map(async file => {
|
|
1293
|
+
const srcPath = path.join(templatePath, file);
|
|
1294
|
+
const destFile = convertDotfileName(file);
|
|
1295
|
+
const destPath = path.join(outputPath, destFile);
|
|
1296
|
+
|
|
1297
|
+
logger.verbose(
|
|
1298
|
+
` - Processing: ${file}${destFile !== file ? ` -> ${destFile}` : ''}`,
|
|
1299
|
+
);
|
|
1300
|
+
|
|
1301
|
+
// 确保目标目录存在
|
|
1302
|
+
await ensureDir(path.dirname(destPath));
|
|
1303
|
+
|
|
1304
|
+
if (shouldRenderFile(srcPath)) {
|
|
1305
|
+
// 渲染文本文件
|
|
1306
|
+
const rendered = await renderTemplate(srcPath, context);
|
|
1307
|
+
await fs$1.writeFile(destPath, rendered, 'utf-8');
|
|
1308
|
+
logger.verbose(' ✓ Rendered and written');
|
|
1309
|
+
} else {
|
|
1310
|
+
// 直接复制二进制文件
|
|
1311
|
+
await fs$1.copyFile(srcPath, destPath);
|
|
1312
|
+
logger.verbose(' ✓ Copied');
|
|
1313
|
+
}
|
|
1314
|
+
}),
|
|
1423
1315
|
);
|
|
1424
1316
|
|
|
1425
1317
|
logger.verbose('✓ All files processed successfully');
|
|
@@ -1606,12 +1498,7 @@ const execute = async (
|
|
|
1606
1498
|
const absoluteOutputPath = await prepareOutputDirectory(outputPath);
|
|
1607
1499
|
|
|
1608
1500
|
// 6. 处理模板文件
|
|
1609
|
-
await processTemplateFiles(
|
|
1610
|
-
templatePath,
|
|
1611
|
-
outputPath: absoluteOutputPath,
|
|
1612
|
-
context,
|
|
1613
|
-
templateConfig,
|
|
1614
|
-
});
|
|
1501
|
+
await processTemplateFiles(templatePath, absoluteOutputPath, context);
|
|
1615
1502
|
|
|
1616
1503
|
// 7. 执行 onAfterRender 钩子
|
|
1617
1504
|
await executeAfterRenderHook(templateConfig, context, absoluteOutputPath);
|
|
@@ -1854,7 +1741,7 @@ const registerCommand = program => {
|
|
|
1854
1741
|
});
|
|
1855
1742
|
};
|
|
1856
1743
|
|
|
1857
|
-
var version = "0.0.1-alpha.
|
|
1744
|
+
var version = "0.0.1-alpha.a8e799";
|
|
1858
1745
|
var packageJson = {
|
|
1859
1746
|
version: version};
|
|
1860
1747
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coze-arch/cli",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.a8e799",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "coze coding devtools cli",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,13 +25,14 @@
|
|
|
25
25
|
"test": "vitest --run --passWithNoTests",
|
|
26
26
|
"test:all": "bash scripts/test-coverage.sh",
|
|
27
27
|
"test:cov": "vitest --run --passWithNoTests --coverage",
|
|
28
|
-
"test:e2e": "
|
|
28
|
+
"test:e2e": "bash scripts/e2e.sh",
|
|
29
29
|
"test:perf": "vitest bench --run --config vitest.perf.config.ts",
|
|
30
30
|
"test:perf:compare": "bash scripts/compare-perf.sh",
|
|
31
31
|
"test:perf:save": "bash scripts/run-perf-with-output.sh"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@iarna/toml": "^2.2.5",
|
|
35
|
+
"@inquirer/prompts": "^3.2.0",
|
|
35
36
|
"ajv": "^8.17.1",
|
|
36
37
|
"ajv-formats": "^3.0.1",
|
|
37
38
|
"change-case": "^5.4.4",
|
|
@@ -49,17 +50,14 @@
|
|
|
49
50
|
"@coze-arch/ts-config": "workspace:*",
|
|
50
51
|
"@coze-arch/vitest-config": "workspace:*",
|
|
51
52
|
"@coze-coding/lambda": "workspace:*",
|
|
52
|
-
"@inquirer/prompts": "^3.2.0",
|
|
53
53
|
"@types/ejs": "^3.1.5",
|
|
54
54
|
"@types/iarna__toml": "^2.0.5",
|
|
55
55
|
"@types/js-yaml": "^4.0.9",
|
|
56
|
-
"@types/minimatch": "^5.1.2",
|
|
57
56
|
"@types/minimist": "^1.2.5",
|
|
58
57
|
"@types/node": "^24",
|
|
59
58
|
"@types/shelljs": "^0.10.0",
|
|
60
59
|
"@vitest/coverage-v8": "~4.0.16",
|
|
61
60
|
"json-schema-to-typescript": "^15.0.3",
|
|
62
|
-
"minimatch": "^10.0.1",
|
|
63
61
|
"rollup": "^4.41.1",
|
|
64
62
|
"sucrase": "^3.35.0",
|
|
65
63
|
"tsx": "^4.20.6",
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"expo": {
|
|
3
|
-
"name": "${app_name}",
|
|
4
|
-
"slug": "${slug}",
|
|
5
|
-
"version": "1.0.0",
|
|
6
|
-
"orientation": "portrait",
|
|
7
|
-
"icon": "./client/assets/images/icon.png",
|
|
8
|
-
"scheme": "myapp",
|
|
9
|
-
"userInterfaceStyle": "automatic",
|
|
10
|
-
"newArchEnabled": true,
|
|
11
|
-
"ios": {
|
|
12
|
-
"supportsTablet": true
|
|
13
|
-
},
|
|
14
|
-
"android": {
|
|
15
|
-
"adaptiveIcon": {
|
|
16
|
-
"foregroundImage": "./client/assets/images/adaptive-icon.png",
|
|
17
|
-
"backgroundColor": "#ffffff"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"web": {
|
|
21
|
-
"bundler": "metro",
|
|
22
|
-
"output": "single",
|
|
23
|
-
"favicon": "./client/assets/images/favicon.png"
|
|
24
|
-
},
|
|
25
|
-
"plugins": [
|
|
26
|
-
"expo-router",
|
|
27
|
-
[
|
|
28
|
-
"expo-splash-screen",
|
|
29
|
-
{
|
|
30
|
-
"image": "./client/assets/images/splash-icon.png",
|
|
31
|
-
"imageWidth": 200,
|
|
32
|
-
"resizeMode": "contain",
|
|
33
|
-
"backgroundColor": "#ffffff"
|
|
34
|
-
}
|
|
35
|
-
],
|
|
36
|
-
[
|
|
37
|
-
"expo-image-picker",
|
|
38
|
-
{
|
|
39
|
-
"photosPermission": "允许${app_name}访问您的相册,以便您上传或保存图片。",
|
|
40
|
-
"cameraPermission": "允许${app_name}使用您的相机,以便您直接拍摄照片上传。",
|
|
41
|
-
"microphonePermission": "允许${app_name}访问您的麦克风,以便您拍摄带有声音的视频。"
|
|
42
|
-
}
|
|
43
|
-
],
|
|
44
|
-
[
|
|
45
|
-
"expo-location",
|
|
46
|
-
{
|
|
47
|
-
"locationWhenInUsePermission": "${app_name}需要访问您的位置以提供周边服务及导航功能。"
|
|
48
|
-
}
|
|
49
|
-
],
|
|
50
|
-
[
|
|
51
|
-
"expo-camera",
|
|
52
|
-
{
|
|
53
|
-
"cameraPermission": "${app_name}需要访问相机以拍摄照片和视频。",
|
|
54
|
-
"microphonePermission": "${app_name}需要访问麦克风以录制视频声音。",
|
|
55
|
-
"recordAudioAndroid": true
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
],
|
|
59
|
-
"experiments": {
|
|
60
|
-
"typedRoutes": true
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
module.exports = function (api) {
|
|
2
|
-
api.cache(true);
|
|
3
|
-
return {
|
|
4
|
-
presets: ["babel-preset-expo"],
|
|
5
|
-
plugins: [
|
|
6
|
-
[
|
|
7
|
-
"module-resolver",
|
|
8
|
-
{
|
|
9
|
-
root: ["./"],
|
|
10
|
-
alias: {
|
|
11
|
-
"@": "./client",
|
|
12
|
-
},
|
|
13
|
-
extensions: [".ios.js", ".android.js", ".js", ".ts", ".tsx", ".json"],
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
"react-native-reanimated/plugin",
|
|
17
|
-
],
|
|
18
|
-
};
|
|
19
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { Tabs } from 'expo-router';
|
|
2
|
-
import { FontAwesome6 } from '@expo/vector-icons';
|
|
3
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
|
-
import { useTheme } from '@/hooks/useTheme';
|
|
5
|
-
|
|
6
|
-
export default function TabLayout() {
|
|
7
|
-
const insets = useSafeAreaInsets();
|
|
8
|
-
const { theme } = useTheme();
|
|
9
|
-
const tabBarHeight = 56 + Math.max(insets.bottom, 8);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Tabs
|
|
13
|
-
backBehavior='history'
|
|
14
|
-
screenOptions={{
|
|
15
|
-
headerShown: false,
|
|
16
|
-
tabBarActiveTintColor: theme.tabIconSelected,
|
|
17
|
-
tabBarInactiveTintColor: theme.tabIconDefault,
|
|
18
|
-
tabBarStyle: {
|
|
19
|
-
backgroundColor: theme.backgroundRoot,
|
|
20
|
-
borderTopColor: theme.backgroundSecondary,
|
|
21
|
-
borderTopWidth: 1,
|
|
22
|
-
height: tabBarHeight,
|
|
23
|
-
paddingBottom: Math.max(insets.bottom, 8),
|
|
24
|
-
paddingTop: 6,
|
|
25
|
-
},
|
|
26
|
-
}}
|
|
27
|
-
>
|
|
28
|
-
<Tabs.Screen
|
|
29
|
-
name='index'
|
|
30
|
-
options={{ href: null }}
|
|
31
|
-
/>
|
|
32
|
-
<Tabs.Screen
|
|
33
|
-
name='home'
|
|
34
|
-
options={{
|
|
35
|
-
title: '首页',
|
|
36
|
-
tabBarIcon: ({ color }) => (
|
|
37
|
-
<FontAwesome6 name='house' size={20} color={color} />
|
|
38
|
-
),
|
|
39
|
-
}}
|
|
40
|
-
/>
|
|
41
|
-
</Tabs>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from "@/screens/home";
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { useRouter } from 'expo-router';
|
|
2
|
-
import { StyleSheet, View, Text, Pressable, Platform } from 'react-native';
|
|
3
|
-
|
|
4
|
-
export default function NotFoundScreen() {
|
|
5
|
-
const router = useRouter();
|
|
6
|
-
|
|
7
|
-
const goBack = () => {
|
|
8
|
-
if (router.canGoBack()) {
|
|
9
|
-
router.back();
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<View style={styles.container}>
|
|
15
|
-
<Text style={styles.heading}>404</Text>
|
|
16
|
-
<Text style={styles.textStyle}>页面未找到</Text>
|
|
17
|
-
<Text style={styles.subTextStyle}>
|
|
18
|
-
抱歉!您访问的页面不存在,当前页面功能待完善。
|
|
19
|
-
</Text>
|
|
20
|
-
<Pressable onPress={goBack} style={styles.button}>
|
|
21
|
-
<Text style={styles.buttonText}>返回上一页</Text>
|
|
22
|
-
</Pressable>
|
|
23
|
-
</View>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const styles = StyleSheet.create({
|
|
28
|
-
container: {
|
|
29
|
-
flex: 1,
|
|
30
|
-
alignItems: 'center',
|
|
31
|
-
justifyContent: 'center',
|
|
32
|
-
backgroundColor: '#f3f5ff',
|
|
33
|
-
padding: 16,
|
|
34
|
-
},
|
|
35
|
-
heading: {
|
|
36
|
-
fontSize: 120,
|
|
37
|
-
fontWeight: '900',
|
|
38
|
-
color: '#4a5568',
|
|
39
|
-
textShadowColor: 'rgba(0, 0, 0, 0.05)',
|
|
40
|
-
textShadowOffset: { width: 0, height: 4 },
|
|
41
|
-
textShadowRadius: 8,
|
|
42
|
-
},
|
|
43
|
-
textStyle: {
|
|
44
|
-
fontSize: 24,
|
|
45
|
-
fontWeight: '500',
|
|
46
|
-
marginTop: -16,
|
|
47
|
-
marginBottom: 16,
|
|
48
|
-
color: '#4a5568',
|
|
49
|
-
},
|
|
50
|
-
subTextStyle: {
|
|
51
|
-
fontSize: 16,
|
|
52
|
-
color: '#718096',
|
|
53
|
-
marginBottom: 32,
|
|
54
|
-
maxWidth: 400,
|
|
55
|
-
textAlign: 'center',
|
|
56
|
-
},
|
|
57
|
-
button: {
|
|
58
|
-
paddingVertical: 12,
|
|
59
|
-
paddingHorizontal: 24,
|
|
60
|
-
backgroundColor: '#6366f1',
|
|
61
|
-
borderRadius: 9999,
|
|
62
|
-
...Platform.select({
|
|
63
|
-
ios: {
|
|
64
|
-
shadowColor: 'rgba(0, 0, 0, 0.1)',
|
|
65
|
-
shadowOffset: { width: 0, height: 10 },
|
|
66
|
-
shadowOpacity: 1,
|
|
67
|
-
shadowRadius: 15,
|
|
68
|
-
},
|
|
69
|
-
android: {
|
|
70
|
-
elevation: 5,
|
|
71
|
-
},
|
|
72
|
-
}),
|
|
73
|
-
},
|
|
74
|
-
buttonText: {
|
|
75
|
-
fontSize: 16,
|
|
76
|
-
fontWeight: '600',
|
|
77
|
-
color: '#ffffff',
|
|
78
|
-
},
|
|
79
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import '@expo/metro-runtime';
|
|
2
|
-
import { registerRootComponent } from 'expo';
|
|
3
|
-
import { ExpoRoot } from 'expo-router';
|
|
4
|
-
|
|
5
|
-
// 显式定义 App 组件
|
|
6
|
-
export function App() {
|
|
7
|
-
// eslint-disable-next-line no-undef
|
|
8
|
-
const ctx = require.context('./app');
|
|
9
|
-
return <ExpoRoot context={ctx} />;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
registerRootComponent(App);
|
/package/lib/__templates__/expo/{eslint-formatter-simple.mjs → client/eslint-formatter-simple.mjs}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|