feat: Init
This commit is contained in:
commit
8cc0770753
1
.env
Normal file
1
.env
Normal file
@ -0,0 +1 @@
|
|||||||
|
CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL=https://alicdn.taoya.art/test/gradle-7.1.1-all.zip
|
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Generated by package manager
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Generated by Cordova
|
||||||
|
/plugins/
|
||||||
|
/platforms/
|
||||||
|
dist/
|
||||||
|
logs/
|
1
.java-version
Normal file
1
.java-version
Normal file
@ -0,0 +1 @@
|
|||||||
|
zulu64-17.0.9
|
73
.vscode/settings.json
vendored
Normal file
73
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||||
|
// Enable the flat config support
|
||||||
|
"eslint.experimental.useFlatConfig": true,
|
||||||
|
// Disable the default formatter
|
||||||
|
"prettier.enable": false,
|
||||||
|
"editor.formatOnSave": false,
|
||||||
|
"eslint.alwaysShowStatus": true,
|
||||||
|
// Auto fix
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": "explicit",
|
||||||
|
"source.organizeImports": "never"
|
||||||
|
},
|
||||||
|
// Silent the stylistic rules in you IDE, but still auto fix them
|
||||||
|
"eslint.rules.customizations": [
|
||||||
|
{
|
||||||
|
"rule": "@stylistic/*",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*-indent",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*-spacing",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*-spaces",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*-order",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*-dangle",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*-newline",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*quotes",
|
||||||
|
"severity": "off"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rule": "*semi",
|
||||||
|
"severity": "off"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// The following is optional.
|
||||||
|
// It's better to put under project setting `.vscode/settings.json`
|
||||||
|
// to avoid conflicts with working with different eslint configs
|
||||||
|
// that does not support all formats.
|
||||||
|
"eslint.validate": [
|
||||||
|
"javascript",
|
||||||
|
"javascriptreact",
|
||||||
|
"typescript",
|
||||||
|
"typescriptreact",
|
||||||
|
"vue",
|
||||||
|
"html",
|
||||||
|
"markdown",
|
||||||
|
"json",
|
||||||
|
"jsonc",
|
||||||
|
"yaml"
|
||||||
|
],
|
||||||
|
"i18n-ally.localesPaths": [
|
||||||
|
"layers/site/components/site/login/locale"
|
||||||
|
],
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib"
|
||||||
|
}
|
8
config.json
Normal file
8
config.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"homeUrl": "https://www.baidu.com",
|
||||||
|
"appId": "asd",
|
||||||
|
"appName": "asd",
|
||||||
|
"appVersion": "1.0.0",
|
||||||
|
"packType": "debug",
|
||||||
|
"pushEmail": "asd@qq.com"
|
||||||
|
}
|
28
config.xml
Normal file
28
config.xml
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<widget xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" id="com.example.tao" version="1.0.0">
|
||||||
|
<name>APP</name>
|
||||||
|
<description>app</description>
|
||||||
|
<author email="dev@cordova.apache.org" href="https://cordova.apache.org"></author>
|
||||||
|
<content src="http://test.taoya.art/" />
|
||||||
|
<allow-intent href="http://*/*"/>
|
||||||
|
<allow-intent href="https://*/*"/>
|
||||||
|
<allow-intent href="tel:*"/>
|
||||||
|
<allow-intent href="sms:*"/>
|
||||||
|
<allow-intent href="mailto:*"/>
|
||||||
|
<allow-intent href="geo:*"/>
|
||||||
|
<allow-intent href="market:*"/>
|
||||||
|
|
||||||
|
<platform name="android">
|
||||||
|
<preference name="Fullscreen" value="true"/>
|
||||||
|
<icon src="logo.png"></icon>
|
||||||
|
</platform>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 设置Java和Gradle版本 -->
|
||||||
|
<preference name="android-minSdkVersion" value="24" />
|
||||||
|
<preference name="android-targetSdkVersion" value="34" />
|
||||||
|
<preference name="android-compileSdkVersion" value="34" />
|
||||||
|
<preference name="GradleVersion" value="7.6.3" />
|
||||||
|
<preference name="AndroidGradlePluginVersion" value="7.2.0" />
|
||||||
|
<preference name="JavaVersion" value="17" />
|
||||||
|
</widget>
|
35
eslint.config.js
Normal file
35
eslint.config.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import antfu from '@antfu/eslint-config'
|
||||||
|
|
||||||
|
export default antfu({
|
||||||
|
typescript: true,
|
||||||
|
stylistic: {
|
||||||
|
semi: false,
|
||||||
|
singleQuote: true,
|
||||||
|
indent: 2,
|
||||||
|
jsx: true,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'vue/custom-event-name-casing': [2, 'kebab-case'], // 对自定义事件名称强制使用特定大小写
|
||||||
|
'style/max-statements-per-line': 'off',
|
||||||
|
// 允许单行if不换行
|
||||||
|
'antfu/if-newline': 'off',
|
||||||
|
// 仅单行if允许不使用大括号
|
||||||
|
'curly': ['error', 'multi-line'],
|
||||||
|
'no-console': 'off',
|
||||||
|
'node/prefer-global/process': 'off',
|
||||||
|
'ts/ban-types': 'off',
|
||||||
|
'ts/method-signature-style': 'off',
|
||||||
|
'unused-imports/no-unused-vars': 'off',
|
||||||
|
'array-callback-return': 'off',
|
||||||
|
'ts/ban-ts-comment': 'off',
|
||||||
|
'@typescript-eslint/interface-name-prefix': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'ts/consistent-type-imports': 'off',
|
||||||
|
'ts/no-require-imports': 'off',
|
||||||
|
'ts/no-var-requires': 'off',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
9612
package-lock.json
generated
Normal file
9612
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
45
package.json
Normal file
45
package.json
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"name": "io.cordova.hellocordova",
|
||||||
|
"displayName": "cordova",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"ad": "cordova platform rm android && cordova platform add android && cordova build android",
|
||||||
|
"clean": "rm -rf node_modules && rm -rf plugins && rm -rf platforms",
|
||||||
|
"initial": "tsx src/init.ts",
|
||||||
|
"build": "cordova build android",
|
||||||
|
"dev": "node scripts/dev.js",
|
||||||
|
"logo": "tsx scripts/logo.ts",
|
||||||
|
"allInOne": "npm run clean && npm i && npm run ad"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "taolin taolin@taoya.art",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@clack/prompts": "^0.8.2",
|
||||||
|
"@types/node": "^22.10.2",
|
||||||
|
"axios": "^1.7.9",
|
||||||
|
"chalk": "^5.3.0",
|
||||||
|
"consola": "^3.2.3",
|
||||||
|
"cordova": "^12.0.0",
|
||||||
|
"cordova-android": "^13.0.0",
|
||||||
|
"es6-promise-plugin": "^4.2.2",
|
||||||
|
"eslint": "^9.17.0",
|
||||||
|
"picocolors": "^1.1.1",
|
||||||
|
"tsx": "^4.19.2",
|
||||||
|
"typeorm": "^0.3.20",
|
||||||
|
"zod": "^3.24.1"
|
||||||
|
},
|
||||||
|
"cordova": {
|
||||||
|
"platforms": [
|
||||||
|
"browser",
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"plugins": {}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^12.1.0"
|
||||||
|
}
|
||||||
|
}
|
0
res/icon/android/.gitkeep
Normal file
0
res/icon/android/.gitkeep
Normal file
140
scripts/cmd.ts
Normal file
140
scripts/cmd.ts
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import { z } from 'zod';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
import { intro, outro, text, select, isCancel, cancel, group } from '@clack/prompts';
|
||||||
|
import { bgRed } from 'picocolors';
|
||||||
|
|
||||||
|
const ConfigSchema = z.object({
|
||||||
|
homeUrl: z.string().url({
|
||||||
|
message: "URL格式不正确"
|
||||||
|
}),
|
||||||
|
appId: z.string().min(1, {
|
||||||
|
message: "应用ID不能为空"
|
||||||
|
}).regex(/^[a-zA-Z0-9._-]+$/, {
|
||||||
|
message: "应用ID只能包含字母、数字、点、下划线和横线"
|
||||||
|
}),
|
||||||
|
appName: z.string().min(1, {
|
||||||
|
message: "应用名称不能为空"
|
||||||
|
}),
|
||||||
|
appVersion: z.string().regex(/^\d+\.\d+\.\d+$/, {
|
||||||
|
message: "版本号格式必须为 x.x.x"
|
||||||
|
}),
|
||||||
|
packType: z.enum(['release', 'debug'], {
|
||||||
|
errorMap: () => ({ message: "打包类型必须是 release 或 debug" })
|
||||||
|
}),
|
||||||
|
pushEmail: z.string().email({
|
||||||
|
message: "邮箱格式不正确"
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
type Config = z.infer<typeof ConfigSchema>;
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
intro('欢迎使用Cali配置工具');
|
||||||
|
|
||||||
|
const config = await group(
|
||||||
|
{
|
||||||
|
homeUrl: () => text({
|
||||||
|
message: '请输入主页URL',
|
||||||
|
validate(value) {
|
||||||
|
try {
|
||||||
|
new URL(value);
|
||||||
|
} catch {
|
||||||
|
return '请输入正确的网址';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
appId: () => text({
|
||||||
|
message: '请输入应用ID',
|
||||||
|
validate(value) {
|
||||||
|
if (!value.length) return '应用ID不能为空';
|
||||||
|
if (!/^[a-zA-Z0-9._-]+$/.test(value)) {
|
||||||
|
return '应用ID只能包含字母、数字、点、下划线和横线';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
appName: () => text({
|
||||||
|
message: '请输入应用名称',
|
||||||
|
validate(value) {
|
||||||
|
if (!value.length) return '应用名称不能为空';
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
appVersion: () => text({
|
||||||
|
message: '请输入应用版本号',
|
||||||
|
validate(value) {
|
||||||
|
if (!/^\d+\.\d+\.\d+$/.test(value)) {
|
||||||
|
return '请输入正确的版本号,例如: 1.0.0';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
packType: () => select({
|
||||||
|
message: '请选择打包类型',
|
||||||
|
options: [
|
||||||
|
{ value: 'release', label: 'release' },
|
||||||
|
{ value: 'debug', label: 'debug' },
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
|
||||||
|
pushEmail: () => text({
|
||||||
|
message: '请输入推送邮箱',
|
||||||
|
validate(value) {
|
||||||
|
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
|
||||||
|
return '请输入正确的邮箱地址';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onCancel: () => {
|
||||||
|
cancel('操作已取消');
|
||||||
|
process.exit(0);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 检查是否有任何输入被取消
|
||||||
|
for (const [key, value] of Object.entries(config)) {
|
||||||
|
if (isCancel(value)) {
|
||||||
|
cancel('操作已取消');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 使用zod验证配置
|
||||||
|
const result = ConfigSchema.safeParse(config);
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
cancel('配置验证失败');
|
||||||
|
result.error.errors.forEach(error => {
|
||||||
|
console.error(bgRed(` ${error.path.join('.')}: ${error.message} `));
|
||||||
|
});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(process.cwd(), 'config.json'),
|
||||||
|
JSON.stringify(result.data, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
outro('配置文件保存成功!');
|
||||||
|
} catch (error) {
|
||||||
|
cancel('保存配置文件时出错');
|
||||||
|
if (error instanceof Error) {
|
||||||
|
console.error(bgRed(` ${error.message} `));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(error => {
|
||||||
|
cancel('发生意外错误');
|
||||||
|
if (error instanceof Error) {
|
||||||
|
console.error(bgRed(` ${error.message} `));
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
});
|
86
scripts/dev.ts
Normal file
86
scripts/dev.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
* @author Taoya
|
||||||
|
* @date 2022/5/23
|
||||||
|
* @Description: 构建开发环境包
|
||||||
|
*/
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import { resolve } from 'path';
|
||||||
|
import { exec, ChildProcess } from 'child_process';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import logger from 'consola'
|
||||||
|
|
||||||
|
interface BuildResult {
|
||||||
|
success: boolean;
|
||||||
|
message: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildAndroid(): Promise<BuildResult> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const buildProcess = exec('npx cordova run android', (error, stdout, stderr) => {
|
||||||
|
if (error) {
|
||||||
|
resolve({
|
||||||
|
success: false,
|
||||||
|
message: error.message
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stdout.includes('BUILD SUCCESSFUL')) {
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
message: 'BUILD SUCCESSFUL'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve({
|
||||||
|
success: false,
|
||||||
|
message: stderr || '构建失败'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 输出构建日志
|
||||||
|
buildProcess.stdout?.on('data', (data: string) => {
|
||||||
|
console.log(chalk.green(data));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const packageName: string = 'dev.apk';
|
||||||
|
const distPath: string = './dist';
|
||||||
|
const outputPath: string = './platforms/android/app/build/outputs/apk/debug/app-debug.apk';
|
||||||
|
|
||||||
|
// 检查dist目录是否存在,不存在则创建
|
||||||
|
if (!fs.existsSync(distPath)) {
|
||||||
|
fs.mkdirSync(distPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建android应用
|
||||||
|
const buildResult = await buildAndroid();
|
||||||
|
|
||||||
|
if (buildResult.success) {
|
||||||
|
logger.log('info', '构建成功');
|
||||||
|
|
||||||
|
// 如果目标文件已存在则删除
|
||||||
|
if (fs.existsSync(`${distPath}/${packageName}`)) {
|
||||||
|
fs.unlinkSync(`${distPath}/${packageName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动构建产物
|
||||||
|
fs.renameSync(outputPath, `${distPath}/${packageName}`);
|
||||||
|
} else {
|
||||||
|
logger.log('error', `构建失败: ${buildResult.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.log('error', `执行失败: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行主函数
|
||||||
|
main().catch(error => {
|
||||||
|
logger.log('error', `意外错误: ${error instanceof Error ? error.message : '未知错误'}`);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
146
scripts/logo.ts
Normal file
146
scripts/logo.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
import { resolve } from 'path';
|
||||||
|
import { execSync } from 'child_process';
|
||||||
|
import * as path from 'path';
|
||||||
|
import consola from 'consola';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { URL } from 'url';
|
||||||
|
|
||||||
|
// 错误信息常量
|
||||||
|
const ErrorMessages = {
|
||||||
|
NO_SOURCE: '请提供源文件路径或URL',
|
||||||
|
INVALID_FILE_TYPE: '无效的文件类型,仅支持 PNG、JPG、JPEG 和 GIF',
|
||||||
|
FILE_NOT_EXIST: '源文件不存在',
|
||||||
|
DOWNLOAD_FAILED: '文件下载失败:',
|
||||||
|
COPY_FAILED: '文件复制失败:',
|
||||||
|
UNEXPECTED_ERROR: '发生意外错误:',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从URL下载文件到指定目录
|
||||||
|
* @param url 文件的URL地址
|
||||||
|
* @param destination 目标保存路径
|
||||||
|
*/
|
||||||
|
async function downloadFile(url: string, destination: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
const response = await axios({
|
||||||
|
url,
|
||||||
|
method: 'GET',
|
||||||
|
responseType: 'stream'
|
||||||
|
});
|
||||||
|
|
||||||
|
const writer = fs.createWriteStream(destination);
|
||||||
|
|
||||||
|
response.data.pipe(writer);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
writer.on('finish', resolve);
|
||||||
|
writer.on('error', reject);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`${ErrorMessages.DOWNLOAD_FAILED} ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制文件到指定目录
|
||||||
|
* @param source 源文件路径
|
||||||
|
* @param destination 目标路径
|
||||||
|
*/
|
||||||
|
function copy(source: string, destination: string): void {
|
||||||
|
try {
|
||||||
|
execSync(`cp ${source} ${destination}`);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`${ErrorMessages.COPY_FAILED} ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证字符串是否为有效URL
|
||||||
|
* @param string 待验证的字符串
|
||||||
|
* @returns boolean 是否为有效URL
|
||||||
|
*/
|
||||||
|
function isValidUrl(string: string): boolean {
|
||||||
|
try {
|
||||||
|
new URL(string);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证文件是否为支持的图片类型
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @returns boolean 是否为支持的图片类型
|
||||||
|
*/
|
||||||
|
function isValidImageFile(filePath: string): boolean {
|
||||||
|
const validExtensions = ['.png', '.jpg', '.jpeg', '.gif'];
|
||||||
|
const ext = path.extname(filePath).toLowerCase();
|
||||||
|
return validExtensions.includes(ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主函数 - 处理Logo替换逻辑
|
||||||
|
*/
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
try {
|
||||||
|
// 获取命令行参数中的源文件路径
|
||||||
|
const sourcePath = process.argv[2];
|
||||||
|
|
||||||
|
if (!sourcePath) {
|
||||||
|
throw new Error(ErrorMessages.NO_SOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseDir: string = resolve('./');
|
||||||
|
const destinationPath = './res/icon/android/logo.png';
|
||||||
|
|
||||||
|
// 打印初始信息
|
||||||
|
consola.info('开始替换Logo');
|
||||||
|
consola.info('当前目录: ' + baseDir);
|
||||||
|
consola.info('源文件: ' + sourcePath);
|
||||||
|
|
||||||
|
// 验证文件类型
|
||||||
|
if (!isValidImageFile(sourcePath)) {
|
||||||
|
throw new Error(ErrorMessages.INVALID_FILE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据源文件类型处理(URL或本地文件)
|
||||||
|
if (isValidUrl(sourcePath)) {
|
||||||
|
consola.info('正在从URL下载文件...');
|
||||||
|
const tempFile = path.join(baseDir, 'temp-logo' + path.extname(sourcePath));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 下载并替换文件
|
||||||
|
await downloadFile(sourcePath, tempFile);
|
||||||
|
copy(tempFile, destinationPath);
|
||||||
|
consola.success('Logo替换成功');
|
||||||
|
} finally {
|
||||||
|
// 清理临时文件
|
||||||
|
if (fs.existsSync(tempFile)) {
|
||||||
|
fs.unlinkSync(tempFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 处理本地文件
|
||||||
|
const localPath = path.resolve(sourcePath);
|
||||||
|
if (!fs.existsSync(localPath)) {
|
||||||
|
throw new Error(ErrorMessages.FILE_NOT_EXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制文件
|
||||||
|
copy(localPath, destinationPath);
|
||||||
|
consola.success('Logo替换成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
consola.error('Logo替换失败:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行主函数
|
||||||
|
main().catch(error => {
|
||||||
|
consola.error(ErrorMessages.UNEXPECTED_ERROR, error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
175
www/index.html
Normal file
175
www/index.html
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="initial-scale=1, width=device-width, viewport-fit=cover"
|
||||||
|
/>
|
||||||
|
<title>Hello World</title>
|
||||||
|
<script src="cordova.js"></script>
|
||||||
|
<!-- 导入样式 -->
|
||||||
|
<link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
|
||||||
|
<!-- 导入 Vue 3 -->
|
||||||
|
<script src="//unpkg.com/vue@next"></script>
|
||||||
|
<!-- 导入组件库 -->
|
||||||
|
<script src="//unpkg.com/element-plus"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<h1>Cordova plugins</h1>
|
||||||
|
<el-button @click="getDeviceInfo">获取设备信息</el-button>
|
||||||
|
<el-button @click="openUrl">打开百度</el-button>
|
||||||
|
<el-button @click="deviceVibration">设备震动</el-button>
|
||||||
|
<el-button @click="scanCode">扫码</el-button>
|
||||||
|
<el-button @click="takPhoto">拍照</el-button>
|
||||||
|
<el-button @click="docPrint">文件打印</el-button>
|
||||||
|
<el-button @click="versionCheck">版本升级</el-button>
|
||||||
|
<el-button @click="installAPK" type="danger">安装apk</el-button>
|
||||||
|
<el-button @click="customPlugin">自定义插件</el-button>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var vConsole = new window.VConsole();
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
const app = Vue.createApp({
|
||||||
|
mounted() {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.addEventListener("batterystatus", this.onBatteryStatus, false);
|
||||||
|
}, 600);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
customPlugin() {
|
||||||
|
console.log(cordovaTest);
|
||||||
|
cordovaTest.coolMethod(
|
||||||
|
"param",
|
||||||
|
(res) => {
|
||||||
|
console.log(res);
|
||||||
|
this.$message.success(res);
|
||||||
|
},
|
||||||
|
(e) => {
|
||||||
|
this.$message.error(e);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
installAPK() {
|
||||||
|
let url = "http://3000.taoya.art/app.apk";
|
||||||
|
var filename = url.split("/").pop();
|
||||||
|
var targetPath = cordova.file.externalRootDirectory + filename;
|
||||||
|
console.log(cordova.file.externalRootDirectory);
|
||||||
|
//1. 下载
|
||||||
|
let _this = this;
|
||||||
|
_this.progress = 0;
|
||||||
|
_this.fileTransfer = new FileTransfer();
|
||||||
|
_this.fileTransfer.onprogress = function (e) {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const progress = e.loaded / e.total;
|
||||||
|
_this.progress = (progress * 100).toFixed(2);
|
||||||
|
console.log(progress);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log("download file");
|
||||||
|
_this.fileTransfer.download(
|
||||||
|
encodeURI(url), //服务器地址
|
||||||
|
targetPath, //本地存储地址
|
||||||
|
function (entry) {
|
||||||
|
//下载完成回调
|
||||||
|
let url = entry.toURL();
|
||||||
|
console.log(url);
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
console.log(error);
|
||||||
|
_this.$message.error(error);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
trustHosts: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
|
||||||
|
//2. 安装
|
||||||
|
cordova.plugins.fileOpener2.open(
|
||||||
|
"",
|
||||||
|
"application/vnd.android.package-archive",
|
||||||
|
{
|
||||||
|
error: function (e) {
|
||||||
|
console.log("open fail");
|
||||||
|
},
|
||||||
|
success: function () {
|
||||||
|
console.log("open successfully");
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
async versionCheck() {
|
||||||
|
let versionCode =
|
||||||
|
await window.cordova.getAppVersion.getVersionNumber();
|
||||||
|
this.$message.success(`当前版本: ${versionCode}`);
|
||||||
|
},
|
||||||
|
docPrint() {
|
||||||
|
// use
|
||||||
|
// cordova.plugins.printer.print();
|
||||||
|
cordova.plugins.printer.print("<b>Hello Cordova!</b>");
|
||||||
|
},
|
||||||
|
takPhoto() {
|
||||||
|
let that = this;
|
||||||
|
window.navigator.camera.getPicture(
|
||||||
|
(imageURI) => {
|
||||||
|
console.log(imageURI);
|
||||||
|
that.$message.success(`文件路径: ${imageURI}`);
|
||||||
|
},
|
||||||
|
(message) => {
|
||||||
|
this.$message.warning("取消拍照");
|
||||||
|
},
|
||||||
|
{
|
||||||
|
quality: 50,
|
||||||
|
destinationType: Camera.DestinationType.FILE_URI,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
scanCode() {
|
||||||
|
cordova.plugins.barcodeScanner.scan(
|
||||||
|
function (result) {
|
||||||
|
console.log("扫码结果", result);
|
||||||
|
try {
|
||||||
|
if (result.text) {
|
||||||
|
alert(result.text);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
that.$message.error("扫描失败");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onBatteryStatus(status) {
|
||||||
|
this.$message.warning(
|
||||||
|
"电池电量: " + status.level + " 是否充电中: " + status.isPlugged
|
||||||
|
);
|
||||||
|
},
|
||||||
|
deviceVibration() {
|
||||||
|
navigator.vibrate(600);
|
||||||
|
// var pattern = [1000, 1000, 1000, 1000];
|
||||||
|
// navigator.vibrate(pattern);
|
||||||
|
},
|
||||||
|
openUrl() {
|
||||||
|
var ref = cordova.InAppBrowser.open(
|
||||||
|
"https://www.baidu.com",
|
||||||
|
"_blank",
|
||||||
|
"location=yes"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
getDeviceInfo() {
|
||||||
|
this.$message.success("请打开控制台查看");
|
||||||
|
console.log(window.device);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
app.use(ElementPlus);
|
||||||
|
app.mount("#app");
|
||||||
|
</script>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user