
【报Bug】我之前发布的文章,为啥下面的评论,你们官方都删除了
【报Bug】我之前发布的文章,为啥下面的评论,你们官方都删除了???
【报Bug】我之前发布的文章,为啥下面的评论,你们官方都删除了???

cli项目使用vscode开发的一些自动化配置及问题
package.json 中 scripts 如下
"scripts": {
"dev:h5": "uni",
"build:h5": "uni build",
"dev:mp-weixin": "concurrently 'uni -p mp-weixin' 'node adt.js'",
"build:mp-weixin": "uni build -p mp-weixin && node adt.js",
"dev:app": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app' 'node adt.js'",
"build:app": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app && node adt.js",
"dev:app-android": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app-android' 'node adt.js'",
"build:app-android": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app-android && node adt.js",
"dev:app-ios": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app-ios' 'node adt.js'",
"build:app-ios": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app-ios && node adt.js",
"dev:app-harmony": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app-harmony' 'node adt.js'",
"build:app-harmony": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app-harmony && node adt.js"
}
1、concurrently 为npm命令多线程执行库 可以全局安装或项目下安装
开发模式下 uni编译命令不会结束, 直接使用 && 串行执行,造成后续 node命令 不能执行 ; 如果使用& 并行执行 开发模式 下后续没法监控变化 ;使用这个库可以解决问题
2、UNI_OUTPUT_DIR 为改变编译输出目录 一定要写到 uni命令之前 ,否则无效
adt.js 脚本 放到根目录 代码如下
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const npmEvent = process.env.npm_lifecycle_event;
let cli;
if (process.platform === 'win32') {//Windows
if (npmEvent.includes('mp-weixin')) {
cli = 'C:\\Program Files (x86)\\Tencent\\微信web开发者工具\\cli.exe';
} else {
cli = 'C:\\Program Files\\DCloud\\HBuilderX\\cli.exe';
}
} else if (process.platform === 'darwin') {//MacOS
if (npmEvent.includes('mp-weixin')) {
cli = '/Applications/wechatwebdevtools.app/Contents/MacOS/cli';
} else {
cli = '/Applications/HBuilderX.app/Contents/MacOS/cli';
}
}
let project;
let cls;
const envEvent = npmEvent.split(':')[0];
if (npmEvent.includes('mp-weixin')) {//微信小程序
project = path.resolve(__dirname, `dist/${envEvent}/mp-weixin`);
cls = `${cli} open --project ${project}`;
} else {//APP
project = path.resolve(__dirname, `dist/${envEvent}/${process.env.npm_package_name}-app-${envEvent}`);
cls = `${cli} open && ${cli} project open --path ${project}`;
}
if (fs.existsSync(project)) {
execSync(cls);
} else {
let startTime = Date.now();
const checkProject = () => {
if (fs.existsSync(project)) {
execSync(cls);
} else {
const elapsedTime = Date.now() - startTime;
if (elapsedTime < 300 * 1000) {
setTimeout(checkProject, 1000);
} else {
console.error('编译失败,请检查代码后重新执行。');
}
}
};
checkProject();
}
windows下 工具路径可能不对 (安装目录 找到 cli 路径 替换即可 )
问题:上面的是 cls 的命令代码 在 vscode 直接执行 是没问题的 ,但是 如果 使用 HBuilderX 打开的这个项目 就没法执行 cls 的命令代码(注 如果 使用cli命令启动的 HBuilderX 好像没问题)
package.json 中 scripts 如下
"scripts": {
"dev:h5": "uni",
"build:h5": "uni build",
"dev:mp-weixin": "concurrently 'uni -p mp-weixin' 'node adt.js'",
"build:mp-weixin": "uni build -p mp-weixin && node adt.js",
"dev:app": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app' 'node adt.js'",
"build:app": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app && node adt.js",
"dev:app-android": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app-android' 'node adt.js'",
"build:app-android": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app-android && node adt.js",
"dev:app-ios": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app-ios' 'node adt.js'",
"build:app-ios": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app-ios && node adt.js",
"dev:app-harmony": "concurrently 'UNI_OUTPUT_DIR=dist/dev/${npm_package_name}-app-dev uni -p app-harmony' 'node adt.js'",
"build:app-harmony": "UNI_OUTPUT_DIR=dist/build/${npm_package_name}-app-build uni build -p app-harmony && node adt.js"
}
1、concurrently 为npm命令多线程执行库 可以全局安装或项目下安装
开发模式下 uni编译命令不会结束, 直接使用 && 串行执行,造成后续 node命令 不能执行 ; 如果使用& 并行执行 开发模式 下后续没法监控变化 ;使用这个库可以解决问题
2、UNI_OUTPUT_DIR 为改变编译输出目录 一定要写到 uni命令之前 ,否则无效
adt.js 脚本 放到根目录 代码如下
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const npmEvent = process.env.npm_lifecycle_event;
let cli;
if (process.platform === 'win32') {//Windows
if (npmEvent.includes('mp-weixin')) {
cli = 'C:\\Program Files (x86)\\Tencent\\微信web开发者工具\\cli.exe';
} else {
cli = 'C:\\Program Files\\DCloud\\HBuilderX\\cli.exe';
}
} else if (process.platform === 'darwin') {//MacOS
if (npmEvent.includes('mp-weixin')) {
cli = '/Applications/wechatwebdevtools.app/Contents/MacOS/cli';
} else {
cli = '/Applications/HBuilderX.app/Contents/MacOS/cli';
}
}
let project;
let cls;
const envEvent = npmEvent.split(':')[0];
if (npmEvent.includes('mp-weixin')) {//微信小程序
project = path.resolve(__dirname, `dist/${envEvent}/mp-weixin`);
cls = `${cli} open --project ${project}`;
} else {//APP
project = path.resolve(__dirname, `dist/${envEvent}/${process.env.npm_package_name}-app-${envEvent}`);
cls = `${cli} open && ${cli} project open --path ${project}`;
}
if (fs.existsSync(project)) {
execSync(cls);
} else {
let startTime = Date.now();
const checkProject = () => {
if (fs.existsSync(project)) {
execSync(cls);
} else {
const elapsedTime = Date.now() - startTime;
if (elapsedTime < 300 * 1000) {
setTimeout(checkProject, 1000);
} else {
console.error('编译失败,请检查代码后重新执行。');
}
}
};
checkProject();
}
windows下 工具路径可能不对 (安装目录 找到 cli 路径 替换即可 )
问题:上面的是 cls 的命令代码 在 vscode 直接执行 是没问题的 ,但是 如果 使用 HBuilderX 打开的这个项目 就没法执行 cls 的命令代码(注 如果 使用cli命令启动的 HBuilderX 好像没问题)
收起阅读 »
uniApp获取通话记录
uniApp获取通话记录
首先讲一个大坑
要拿到通过记录真机调试时候必须前给足权限,必须打包成自定义基座再测试!!!!!!一定要先打包!!!!
必要权限
首先勾取manifest.json里APP模块里通讯录权限
添加以下权限
<uses-feature android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
为了怕遗漏我把我所有的权限都放出来提供参考
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-feature android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
然后打包制作自定义基座
获取通话记录代码
我也是从其他地方粘的
getCalllog(){
var CallLog = plus.android.importClass('android.provider.CallLog');
var Activity = plus.android.runtimeMainActivity();
var ContentResolver = plus.android.importClass('android.content.ContentResolver');
var resolver = Activity.getContentResolver();
plus.android.importClass(resolver);
var String = plus.android.importClass("java.lang.String");
var cs = resolver.query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
var talist = [];
uni.showLoading({
title: "匹配通话记录中.."
});
var count = 0; // 记录多少条 用于处理循环跳出
while (plus.android.invoke(cs, "moveToNext")) {
count++;
talist.push({
xm: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.CACHED_NAME)),
telphone: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.NUMBER)),
duration: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.DURATION)),
date: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.DATE)),
type: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.TYPE))
});
if(count > 50){
break;
}
}
uni.hideLoading();
console.info("talist",talist);
},
uniApp获取通话记录
首先讲一个大坑
要拿到通过记录真机调试时候必须前给足权限,必须打包成自定义基座再测试!!!!!!一定要先打包!!!!
必要权限
首先勾取manifest.json里APP模块里通讯录权限
添加以下权限
<uses-feature android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
为了怕遗漏我把我所有的权限都放出来提供参考
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-feature android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
然后打包制作自定义基座
获取通话记录代码
我也是从其他地方粘的
getCalllog(){
var CallLog = plus.android.importClass('android.provider.CallLog');
var Activity = plus.android.runtimeMainActivity();
var ContentResolver = plus.android.importClass('android.content.ContentResolver');
var resolver = Activity.getContentResolver();
plus.android.importClass(resolver);
var String = plus.android.importClass("java.lang.String");
var cs = resolver.query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DEFAULT_SORT_ORDER);
var talist = [];
uni.showLoading({
title: "匹配通话记录中.."
});
var count = 0; // 记录多少条 用于处理循环跳出
while (plus.android.invoke(cs, "moveToNext")) {
count++;
talist.push({
xm: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.CACHED_NAME)),
telphone: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.NUMBER)),
duration: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.DURATION)),
date: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.DATE)),
type: plus.android.invoke(cs, "getString", plus.android.invoke(cs, "getColumnIndex", CallLog.Calls.TYPE))
});
if(count > 50){
break;
}
}
uni.hideLoading();
console.info("talist",talist);
},
收起阅读 »

记录一个支付宝小程序问题:切换组件出现生命周期不存在
最近写一个支付宝、微信、h5三端互通 的程序,用uniapp开发,
然后涉及到不同身份,不同的主页,所以原生的TabBar理所当然的GG,接着就自己定义了一个tabBar组件;然后发现了狗屎,,,小程序不支持component动态组件,,,就只能v-if切换组件的方式实现tabBar了;
接着,由于一开始使用的原生tabBar,所以页面是放在pages下面的,改成组件切换后,tabBar里切换的组件页面在支付宝小程序全部失去生命周期-.-||,绝了。
一开始以为是v-if的问题,后面排查完,改一个路径即可,换到components下
特此记录,狗屎小程序!!!
最近写一个支付宝、微信、h5三端互通 的程序,用uniapp开发,
然后涉及到不同身份,不同的主页,所以原生的TabBar理所当然的GG,接着就自己定义了一个tabBar组件;然后发现了狗屎,,,小程序不支持component动态组件,,,就只能v-if切换组件的方式实现tabBar了;
接着,由于一开始使用的原生tabBar,所以页面是放在pages下面的,改成组件切换后,tabBar里切换的组件页面在支付宝小程序全部失去生命周期-.-||,绝了。
一开始以为是v-if的问题,后面排查完,改一个路径即可,换到components下
特此记录,狗屎小程序!!!
收起阅读 »
【分享】分享一次AppStore成功上架经验
最近刚刚在AppStore成功上架了一款VPN类软件,App采用离线打包,期间也是经历一系列问题,现在整理出来分享给有需要的朋友。
Guideline 4.3(a) - Design - Spam
这个是比较常见的打回原因,大意就是app雷同,这个雷同分2方面,一是UI/功能与其他APP雷同,二是代码雷同,根据我们上架后的修改情况来看,我们遇到的第一次4.3,是因为代码雷同(因为自始至终我们都不曾修改UI及布局)。这里说一下我们的使用过的处理方式:
- 离线打包的项目名,必须修改,不要使用默认命名“HBuilder-Hello”,项目中所有涉及到HBuilder的关键字都搜索并修改
- HBuidler发布离线资源后,使用“javascript-obfuscator”等工具进行混淆,具体方式网上很多,这里不再赘述
- 在appstoreconnect上提审/回复审核消息时,提前备注,“app使用的是uniapp这类hybrid框架,底层框架代码可能部分雷同”,
- 尽可能详细的准备app资质类文件,由于我们是VPN这类敏感软件,本身上架就有诸多限制,所以相关证书不能少,有“代码版权”最佳
- 4.3这个打回,很奇葩的,我们居然遇到2次,首次提审遇到一次,上线成功后,进行过几次修改,发布新版,后面第5次更新版时,居然再次被4.3打回,这次重点强调第3点,态度良好的跟苹果审核员沟通,就再次过了。
Guideline 5.1.1 - Legal - Data Collection and Storage
这个比较简单,根据具体反馈内容显示,苹果的内购,必须有游客购买功能,很多人初次上架都会遇到,开发相应功能即可
Guideline 2.1 - Performance - App Completeness
这个也比较简单,app不可以有假死,用户无法操作的情况出现,属于业务范畴,比较容易修改,覆盖测试到位就行
Guideline 5.1.1(v) - Data Collection and Storage
神奇的再次遇到5.1.1,而且还是成功上架后,第4次更新提审时被打回,打回原因居然是app必须要有注销功能,无奈加上注销后,审核通过
总体心得:
- 与苹果审核人员沟通,态度要诚恳,各类资质提前备好,尽量让审核人员审核方便,提审功能尽量写清楚怎么操作,入口在哪里(审核员也是人,你让他舒服,他也让你舒服,能省不少麻烦)
- 离线打包资源如果混淆不够,可以尝试对app进行加固混淆:ipaguard。不过很遗憾,我们的app有vpn进程服务,加固后找不到进程入口,所以未使用。
- 很多人遇到的隐私类问题,我们这次完美规避。因为之前上架android各大商店,频繁被隐私类问题打回(动辄是XXsdk违规收集用户隐私),这次的推送、广告、一键登录、内购等等uni-sdk一概未用,仅使用uniapp的基础sdk包,使用uniapp做UI及上层业务逻辑,有需要的sdk,尽量使用原生开发,便于找问题,比如内购、一键登录,都是自己接的原生。
- 关于热更,uniapp本身是有热更功能的,我们在android上保留了热更功能,但是为了在苹果上少一些麻烦,所以关掉了热更。
- 总体来说,使用uniapp负责上层业务,做到了一套代码,android及ios双端复用(底层tun2sock加速分别采用java及swift原生开发),省去不少重复内容的开发时间。离线打包+部分原生开发,提供了很高的自由度,在审核时,省去许多麻烦。
- 本项目是外包性质,先上架的另一个android同类app,后上架ios,均使用uniapp,开发效率不错。
欢迎加Q交流:272669509
最近刚刚在AppStore成功上架了一款VPN类软件,App采用离线打包,期间也是经历一系列问题,现在整理出来分享给有需要的朋友。
Guideline 4.3(a) - Design - Spam
这个是比较常见的打回原因,大意就是app雷同,这个雷同分2方面,一是UI/功能与其他APP雷同,二是代码雷同,根据我们上架后的修改情况来看,我们遇到的第一次4.3,是因为代码雷同(因为自始至终我们都不曾修改UI及布局)。这里说一下我们的使用过的处理方式:
- 离线打包的项目名,必须修改,不要使用默认命名“HBuilder-Hello”,项目中所有涉及到HBuilder的关键字都搜索并修改
- HBuidler发布离线资源后,使用“javascript-obfuscator”等工具进行混淆,具体方式网上很多,这里不再赘述
- 在appstoreconnect上提审/回复审核消息时,提前备注,“app使用的是uniapp这类hybrid框架,底层框架代码可能部分雷同”,
- 尽可能详细的准备app资质类文件,由于我们是VPN这类敏感软件,本身上架就有诸多限制,所以相关证书不能少,有“代码版权”最佳
- 4.3这个打回,很奇葩的,我们居然遇到2次,首次提审遇到一次,上线成功后,进行过几次修改,发布新版,后面第5次更新版时,居然再次被4.3打回,这次重点强调第3点,态度良好的跟苹果审核员沟通,就再次过了。
Guideline 5.1.1 - Legal - Data Collection and Storage
这个比较简单,根据具体反馈内容显示,苹果的内购,必须有游客购买功能,很多人初次上架都会遇到,开发相应功能即可
Guideline 2.1 - Performance - App Completeness
这个也比较简单,app不可以有假死,用户无法操作的情况出现,属于业务范畴,比较容易修改,覆盖测试到位就行
Guideline 5.1.1(v) - Data Collection and Storage
神奇的再次遇到5.1.1,而且还是成功上架后,第4次更新提审时被打回,打回原因居然是app必须要有注销功能,无奈加上注销后,审核通过
总体心得:
- 与苹果审核人员沟通,态度要诚恳,各类资质提前备好,尽量让审核人员审核方便,提审功能尽量写清楚怎么操作,入口在哪里(审核员也是人,你让他舒服,他也让你舒服,能省不少麻烦)
- 离线打包资源如果混淆不够,可以尝试对app进行加固混淆:ipaguard。不过很遗憾,我们的app有vpn进程服务,加固后找不到进程入口,所以未使用。
- 很多人遇到的隐私类问题,我们这次完美规避。因为之前上架android各大商店,频繁被隐私类问题打回(动辄是XXsdk违规收集用户隐私),这次的推送、广告、一键登录、内购等等uni-sdk一概未用,仅使用uniapp的基础sdk包,使用uniapp做UI及上层业务逻辑,有需要的sdk,尽量使用原生开发,便于找问题,比如内购、一键登录,都是自己接的原生。
- 关于热更,uniapp本身是有热更功能的,我们在android上保留了热更功能,但是为了在苹果上少一些麻烦,所以关掉了热更。
- 总体来说,使用uniapp负责上层业务,做到了一套代码,android及ios双端复用(底层tun2sock加速分别采用java及swift原生开发),省去不少重复内容的开发时间。离线打包+部分原生开发,提供了很高的自由度,在审核时,省去许多麻烦。
- 本项目是外包性质,先上架的另一个android同类app,后上架ios,均使用uniapp,开发效率不错。
欢迎加Q交流:272669509
收起阅读 »
vue3+electron31+element-plus后台系统管理应用程序
整合vite5.x+electron31+pinia2+vue-i18n+echarts全新后台管理方案Vue3ElectronAdmin。提供了4种通用布局模板,支持中英文/繁体国际化解决方案、动态路由权限,实现了表格、表单、列表、图表、编辑器、错误处理等模块。
原创Electron31+Vue3+ElementPlus桌面端后台管理系统
技术栈
- 编辑器:vscode
- 框架技术:vite^5.3.4+vue^3.4.31+vue-router^4.4.0
- 跨端框架:electron^31.3.0
- 组件库:element-plus^2.7.8
- 状态管理:pinia^2.2.0
- 国际化方案:vue-i18n@9
- 图表组件:echarts^5.5.1
- markdown编辑器:md-editor-v3^4.18.0
- 模拟数据:mockjs^1.1.0
- 打包工具:electron-builder^24.13.3
- electron+vite桥接插件:vite-plugin-electron^0.28.7
功能性
1、最新前端技术栈Vite5.x、Vue3、Electron31、ElementPlus、Vue-I18n、Echarts
2、支持中英文/繁体国际化解决方案
3、支持动态权限路由、多页签缓存路由
4、封装多窗口管理器
5、内置4种通用布局模板、自由切换风格
6、整合通用的表格、表单、列表、图表、编辑器、错误处理等模块
7、高颜值UI界面、轻量级模块化、高定制性
项目结构
整个项目整合vite.js+electronjs
跨平台技术,采用vue3 setup
语法编码。
electronjs主线程配置
/**
* electron主线程配置
* @author andy
*/
import { app, BrowserWindow } from 'electron'
import { WindowManager } from '../src/windows/index.js'
// 忽略安全警告提示 Electron Security Warning (Insecure Content-Security-Policy)
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = true
const createWindow = () => {
let win = new WindowManager()
win.create({isMajor: true})
// 系统托盘管理
win.trayManager()
// 监听ipcMain事件
win.ipcManager()
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if(BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if(process.platform !== 'darwin') app.quit()
})
electron31-vue3-admin布局模板
/**
* 通用布局模板
* @author Andy
*/
<script setup>
import { appState } from '@/pinia/modules/app'
// 引入布局模板
import Classic from './template/classic/index.vue'
import Columns from './template/columns/index.vue'
import Vertical from './template/vertical/index.vue'
import Horizontal from './template/horizontal/index.vue'
const appstate = appState()
const LayoutMap = {
'classic': Classic,
'columns': Columns,
'vertical': Vertical,
'horizontal': Horizontal
}
</script>
<template>
<div class="vuadmin__container" :style="{'--themeSkin': appstate.config.skin}">
<component :is="LayoutMap[appstate.config.layout]" />
</div>
</template>
electron31-admin国际化配置
/**
* 国际化配置
* @author YXY
*/
import { createI18n } from 'vue-i18n'
import { appState } from '@/pinia/modules/app'
// 引入语言配置
import enUS from './en-US'
import zhCN from './zh-CN'
import zhTW from './zh-TW'
// 默认语言
export const langVal = 'zh-CN'
export default async (app) => {
const appstate = appState()
const lang = appstate.lang || langVal
appstate.setLang(lang)
const i18n = createI18n({
legacy: false,
locale: lang,
messages: {
'en': enUS,
'zh-CN': zhCN,
'zh-TW': zhTW
}
})
app.use(i18n)
}
vue3封装echarts图表hook
/**
* 动态图表Hook
*/
import { onMounted, onBeforeUnmount, ref } from 'vue'
import * as echarts from 'echarts'
import elementResizeDetectorMaker from 'element-resize-detector'
export function useEcharts(el, options) {
let chartEl
let chartRef = ref(null)
let erd = elementResizeDetectorMaker()
const resizeHandle = () => {
chartEl && chartEl.resize()
}
onMounted(() => {
if(el?.value) {
chartEl = echarts.init(el.value)
chartEl.setOption(options)
chartRef.value = chartEl
}
erd.listenTo(el.value, resizeHandle)
})
onBeforeUnmount(() => {
chartEl.dispose()
erd.removeListener(el.value, resizeHandle)
})
return chartRef
}
OK,以上就是Electron31+Vue3+ElementPlus跨平台实战开发后台管理系统的一些分享。整个项目涉及到的知识点还是蛮多的,限于篇幅就暂时分享到这里。希望对大家有所帮助哈~
作者:xiaoyan2017
链接: https://segmentfault.com/a/1190000045186093
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
整合vite5.x+electron31+pinia2+vue-i18n+echarts全新后台管理方案Vue3ElectronAdmin。提供了4种通用布局模板,支持中英文/繁体国际化解决方案、动态路由权限,实现了表格、表单、列表、图表、编辑器、错误处理等模块。
原创Electron31+Vue3+ElementPlus桌面端后台管理系统
技术栈
- 编辑器:vscode
- 框架技术:vite^5.3.4+vue^3.4.31+vue-router^4.4.0
- 跨端框架:electron^31.3.0
- 组件库:element-plus^2.7.8
- 状态管理:pinia^2.2.0
- 国际化方案:vue-i18n@9
- 图表组件:echarts^5.5.1
- markdown编辑器:md-editor-v3^4.18.0
- 模拟数据:mockjs^1.1.0
- 打包工具:electron-builder^24.13.3
- electron+vite桥接插件:vite-plugin-electron^0.28.7
功能性
1、最新前端技术栈Vite5.x、Vue3、Electron31、ElementPlus、Vue-I18n、Echarts
2、支持中英文/繁体国际化解决方案
3、支持动态权限路由、多页签缓存路由
4、封装多窗口管理器
5、内置4种通用布局模板、自由切换风格
6、整合通用的表格、表单、列表、图表、编辑器、错误处理等模块
7、高颜值UI界面、轻量级模块化、高定制性
项目结构
整个项目整合vite.js+electronjs
跨平台技术,采用vue3 setup
语法编码。
electronjs主线程配置
/**
* electron主线程配置
* @author andy
*/
import { app, BrowserWindow } from 'electron'
import { WindowManager } from '../src/windows/index.js'
// 忽略安全警告提示 Electron Security Warning (Insecure Content-Security-Policy)
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = true
const createWindow = () => {
let win = new WindowManager()
win.create({isMajor: true})
// 系统托盘管理
win.trayManager()
// 监听ipcMain事件
win.ipcManager()
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if(BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', () => {
if(process.platform !== 'darwin') app.quit()
})
electron31-vue3-admin布局模板
/**
* 通用布局模板
* @author Andy
*/
<script setup>
import { appState } from '@/pinia/modules/app'
// 引入布局模板
import Classic from './template/classic/index.vue'
import Columns from './template/columns/index.vue'
import Vertical from './template/vertical/index.vue'
import Horizontal from './template/horizontal/index.vue'
const appstate = appState()
const LayoutMap = {
'classic': Classic,
'columns': Columns,
'vertical': Vertical,
'horizontal': Horizontal
}
</script>
<template>
<div class="vuadmin__container" :style="{'--themeSkin': appstate.config.skin}">
<component :is="LayoutMap[appstate.config.layout]" />
</div>
</template>
electron31-admin国际化配置
/**
* 国际化配置
* @author YXY
*/
import { createI18n } from 'vue-i18n'
import { appState } from '@/pinia/modules/app'
// 引入语言配置
import enUS from './en-US'
import zhCN from './zh-CN'
import zhTW from './zh-TW'
// 默认语言
export const langVal = 'zh-CN'
export default async (app) => {
const appstate = appState()
const lang = appstate.lang || langVal
appstate.setLang(lang)
const i18n = createI18n({
legacy: false,
locale: lang,
messages: {
'en': enUS,
'zh-CN': zhCN,
'zh-TW': zhTW
}
})
app.use(i18n)
}
vue3封装echarts图表hook
/**
* 动态图表Hook
*/
import { onMounted, onBeforeUnmount, ref } from 'vue'
import * as echarts from 'echarts'
import elementResizeDetectorMaker from 'element-resize-detector'
export function useEcharts(el, options) {
let chartEl
let chartRef = ref(null)
let erd = elementResizeDetectorMaker()
const resizeHandle = () => {
chartEl && chartEl.resize()
}
onMounted(() => {
if(el?.value) {
chartEl = echarts.init(el.value)
chartEl.setOption(options)
chartRef.value = chartEl
}
erd.listenTo(el.value, resizeHandle)
})
onBeforeUnmount(() => {
chartEl.dispose()
erd.removeListener(el.value, resizeHandle)
})
return chartRef
}
OK,以上就是Electron31+Vue3+ElementPlus跨平台实战开发后台管理系统的一些分享。整个项目涉及到的知识点还是蛮多的,限于篇幅就暂时分享到这里。希望对大家有所帮助哈~
作者:xiaoyan2017
链接: https://segmentfault.com/a/1190000045186093
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。