
[项目外包]外包一个UNIAPP项目
需开发一个安卓APP项目,TV端,APP需打包为启动器,能自动热更,能自动下载APP并安装等一些功能,有兴趣的联系我啦~~
需开发一个安卓APP项目,TV端,APP需打包为启动器,能自动热更,能自动下载APP并安装等一些功能,有兴趣的联系我啦~~

通过包名获取软件的基本信息
代码:
// 通过包名获取应用基本信息 形参:包名 返回信息{code: true/fals, information: {"appName":"NP管理器","packageName":"player.normal.np","versionName":"3.0.54","versionCode":20221004}}
function getAppInformation(package_name, information) {
function isEmptyObject(obj) {
return Object.keys(obj).length === 0;
}
plus.android.importClass('java.util.ArrayList');
plus.android.importClass('android.content.pm.PackageInfo');
plus.android.importClass('android.content.pm.PackageManager');
var ApplicationInfo = plus.android.importClass('android.content.pm.ApplicationInfo');
var MainActivity = plus.android.runtimeMainActivity();
var PackageManager = MainActivity.getPackageManager();
var pinfo = plus.android.invoke(PackageManager, 'getInstalledPackages', 0)
if (pinfo != null) {
var apkdist = {}
for (var i = 0; i < pinfo.size(); i++) {
//PackageInfo{4b45699f9d com.tencent.mobileqq}
var pkginfo = pinfo.get(i);
var issysapk = ((pkginfo.plusGetAttribute("applicationInfo").plusGetAttribute("flags") & ApplicationInfo.FLAG_SYSTEM) != 0) ? true : false
if (issysapk == false && pkginfo.plusGetAttribute("packageName") === package_name) {
apkdist.appName = pkginfo.plusGetAttribute("applicationInfo").loadLabel(PackageManager).toString();
apkdist.packageName = pkginfo.plusGetAttribute("packageName");
apkdist.versionName = pkginfo.plusGetAttribute("versionName");
apkdist.versionCode = pkginfo.plusGetAttribute("versionCode");
}
}
if (typeof information === 'function' && isEmptyObject(apkdist) === false) {
information(null, {code: true, information: apkdist})
}else {
if (typeof information === 'function') {
information(null, {code: false, information: {}})
}
}
}
}
使用方法:
getAppInformation('你要获取的应用包名', function(err, data) {
console.log(JSON.stringify(data))
})
代码:
// 通过包名获取应用基本信息 形参:包名 返回信息{code: true/fals, information: {"appName":"NP管理器","packageName":"player.normal.np","versionName":"3.0.54","versionCode":20221004}}
function getAppInformation(package_name, information) {
function isEmptyObject(obj) {
return Object.keys(obj).length === 0;
}
plus.android.importClass('java.util.ArrayList');
plus.android.importClass('android.content.pm.PackageInfo');
plus.android.importClass('android.content.pm.PackageManager');
var ApplicationInfo = plus.android.importClass('android.content.pm.ApplicationInfo');
var MainActivity = plus.android.runtimeMainActivity();
var PackageManager = MainActivity.getPackageManager();
var pinfo = plus.android.invoke(PackageManager, 'getInstalledPackages', 0)
if (pinfo != null) {
var apkdist = {}
for (var i = 0; i < pinfo.size(); i++) {
//PackageInfo{4b45699f9d com.tencent.mobileqq}
var pkginfo = pinfo.get(i);
var issysapk = ((pkginfo.plusGetAttribute("applicationInfo").plusGetAttribute("flags") & ApplicationInfo.FLAG_SYSTEM) != 0) ? true : false
if (issysapk == false && pkginfo.plusGetAttribute("packageName") === package_name) {
apkdist.appName = pkginfo.plusGetAttribute("applicationInfo").loadLabel(PackageManager).toString();
apkdist.packageName = pkginfo.plusGetAttribute("packageName");
apkdist.versionName = pkginfo.plusGetAttribute("versionName");
apkdist.versionCode = pkginfo.plusGetAttribute("versionCode");
}
}
if (typeof information === 'function' && isEmptyObject(apkdist) === false) {
information(null, {code: true, information: apkdist})
}else {
if (typeof information === 'function') {
information(null, {code: false, information: {}})
}
}
}
}
使用方法:
getAppInformation('你要获取的应用包名', function(err, data) {
console.log(JSON.stringify(data))
})
收起阅读 »

UniDevTools - UniApp调试工具推荐
<b>在线文档 - 完整版使用教程:<br>
https://dev.api0.cn
不知道大家是否和我一样已经受够了使用Uniapp开发APP时需要插USB线连着HbuilderX才能看到console打印,各项指标数据全是黑盒,开发APP时无法选择调试节点等各类头疼问题。Uniapp官方一直没有一个标准的调试工具,为什么不能像Chrome调试工具一样调试App呢?为此我们开发了一个插件,把这些痛点问题依次解决!
UniDevTools是一个UniApp工具库,包含console打印日志、request请求记录、storage缓存管理、vuex状态管理、框架报错记录、文件管理等多功能调试工具合集:
Tools
常用工具(重启、请求构建、跳转指定页面、注入VConsole、Eruda)、自定义工具页Error
全局报错拦截:vue模板报错、uniapp框架报错Console
打印日志记录Network
request请求记录、重发请求JsRunner
执行js代码、支持App和H5端Storage
缓存管理,支持localStorage、cookie、sessionStoragePages
路由页面管理、日活时间记录Vuex
状态管理,支持Vuex
、Pinia
、globalData
Logs
框架运行日志、框架api调用日志、自定义上报的日志记录Info
当前设备参数、App启动参数、运行时信息、权限列表UniBus
uni框架事件总线调用记录FileSys
本地文件管理系统Setting
DevTools工具设置、清空全部缓存、导出全部日志
兼容框架: | Vue2+js+vuex | Vue3+ts+vuex(pinia) |
---|---|---|
√ | √ |
兼容平台: | H5 | APP | 微信小程序 | APP-NVUE | 其他小程序 | UniAppX |
---|---|---|---|---|---|---|
√ | √ | √ | √(大部分功能支持) | 未测试 | × (待办中) |
<b>本工具支持在<span style="color: red;">生产环境</span>中使用</b><br>
<span style="font-size: 13px;">生产环境使用时建议隐藏调试浮窗,可设置通过特定方法进入调试页</span>
下载运行本示例项目使用说明:
注意该项目使用Cli模式搭建,请勿导入HBuilderX中运行<br>
开始前请先准备好环境:node18
+pnpm
- 克隆项目到本地:
git clone https://github.com/1615958039/UniDevTools.git
- 进入项目
cd ./UniDevTools
- 安装依赖
pnpm i
- 启动预览H5
pnpm run dev:h5
说明:示例基于UniApp+Vue3+ts+Vite,UI框架为TM-UI3.1
把调试工具引入自己项目:
- 下载最新源码包
v3.4.5
GitHub: releases <br>
Gitee: releases <br>
备用:v3.4.5_r.zip - 引入项目(请移步至在线文档):https://dev.api0.cn/guide/install
示例项目
《斗图助手APP》表情包制作工具<br>
该项目基于Uniapp+Vue2,已集成DevTools工具<br>
打开APP后在搜索页输入__devtools__
即可打开调试弹窗查看请求和日志数据
<div class="qrCodeList" style="display: flex;flex-direction: row; align-items: center;gap: 30px;flex-wrap: wrap;">
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/iosAppStore.png" style="width: 160px;height: 160px;">
<div class="codeTitle">苹果AppStore</div>
</div>
<br><br><br>
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/androidYYB.png" style="width: 160px;height: 160px;">
<div class="codeTitle">安卓应用宝</div>
</div>
<br><br><br>
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/wxmp.jpg" style="width: 160px;height: 160px;">
<div class="codeTitle">微信小程序</div>
</div>
<br><br><br>
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/web.png" style="width: 160px;height: 160px;">
<div class="codeTitle">H5</div>
</div>
</div>
<b>在线文档 - 完整版使用教程:<br>
https://dev.api0.cn
不知道大家是否和我一样已经受够了使用Uniapp开发APP时需要插USB线连着HbuilderX才能看到console打印,各项指标数据全是黑盒,开发APP时无法选择调试节点等各类头疼问题。Uniapp官方一直没有一个标准的调试工具,为什么不能像Chrome调试工具一样调试App呢?为此我们开发了一个插件,把这些痛点问题依次解决!
UniDevTools是一个UniApp工具库,包含console打印日志、request请求记录、storage缓存管理、vuex状态管理、框架报错记录、文件管理等多功能调试工具合集:
Tools
常用工具(重启、请求构建、跳转指定页面、注入VConsole、Eruda)、自定义工具页Error
全局报错拦截:vue模板报错、uniapp框架报错Console
打印日志记录Network
request请求记录、重发请求JsRunner
执行js代码、支持App和H5端Storage
缓存管理,支持localStorage、cookie、sessionStoragePages
路由页面管理、日活时间记录Vuex
状态管理,支持Vuex
、Pinia
、globalData
Logs
框架运行日志、框架api调用日志、自定义上报的日志记录Info
当前设备参数、App启动参数、运行时信息、权限列表UniBus
uni框架事件总线调用记录FileSys
本地文件管理系统Setting
DevTools工具设置、清空全部缓存、导出全部日志
兼容框架: | Vue2+js+vuex | Vue3+ts+vuex(pinia) |
---|---|---|
√ | √ |
兼容平台: | H5 | APP | 微信小程序 | APP-NVUE | 其他小程序 | UniAppX |
---|---|---|---|---|---|---|
√ | √ | √ | √(大部分功能支持) | 未测试 | × (待办中) |
<b>本工具支持在<span style="color: red;">生产环境</span>中使用</b><br>
<span style="font-size: 13px;">生产环境使用时建议隐藏调试浮窗,可设置通过特定方法进入调试页</span>
下载运行本示例项目使用说明:
注意该项目使用Cli模式搭建,请勿导入HBuilderX中运行<br>
开始前请先准备好环境:node18
+pnpm
- 克隆项目到本地:
git clone https://github.com/1615958039/UniDevTools.git
- 进入项目
cd ./UniDevTools
- 安装依赖
pnpm i
- 启动预览H5
pnpm run dev:h5
说明:示例基于UniApp+Vue3+ts+Vite,UI框架为TM-UI3.1
把调试工具引入自己项目:
- 下载最新源码包
v3.4.5
GitHub: releases <br>
Gitee: releases <br>
备用:v3.4.5_r.zip - 引入项目(请移步至在线文档):https://dev.api0.cn/guide/install
示例项目
《斗图助手APP》表情包制作工具<br>
该项目基于Uniapp+Vue2,已集成DevTools工具<br>
打开APP后在搜索页输入__devtools__
即可打开调试弹窗查看请求和日志数据
<div class="qrCodeList" style="display: flex;flex-direction: row; align-items: center;gap: 30px;flex-wrap: wrap;">
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/iosAppStore.png" style="width: 160px;height: 160px;">
<div class="codeTitle">苹果AppStore</div>
</div>
<br><br><br>
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/androidYYB.png" style="width: 160px;height: 160px;">
<div class="codeTitle">安卓应用宝</div>
</div>
<br><br><br>
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/wxmp.jpg" style="width: 160px;height: 160px;">
<div class="codeTitle">微信小程序</div>
</div>
<br><br><br>
<div class="codeItem">
<img src="https://dev.api0.cn/qrCode/web.png" style="width: 160px;height: 160px;">
<div class="codeTitle">H5</div>
</div>
</div>

离线打包 Vue2 项目,无法使用uni.createRequestPermissionListener()
- 升级到4.23后调用uni.createRequestPermissionListener() 提示[JS Framework] 当前运行的基座不包含原生插件[UTS-Proxy],请在manifest中配置该插件,重新制作包括该原生插件的自定义运行基座
- 引入utsplugin-release.aar后,提示打包时未添加uni-createRequestPermissionListener
- 引入uni-createRequestPermissionListener-release.aar后,仍然提示打包时未添加uni-createRequestPermissionListener
- 升级到4.23后调用uni.createRequestPermissionListener() 提示[JS Framework] 当前运行的基座不包含原生插件[UTS-Proxy],请在manifest中配置该插件,重新制作包括该原生插件的自定义运行基座
- 引入utsplugin-release.aar后,提示打包时未添加uni-createRequestPermissionListener
- 引入uni-createRequestPermissionListener-release.aar后,仍然提示打包时未添加uni-createRequestPermissionListener

uniapp微信小程序实现跨包加载js与异步组件,支持vue2和vue3,从此和主包超限说拜拜。
前言
最近在接到一个二开项目,发现一个普通的小项目居然主包超过了1.5MB,并且甲方还在持续加码功能,一看就是一个屎山项目。为了更好的进行开发,我打算重新规划一下整个小程序,并且进行分包,而当我打算在清理一堆屎的时候我才发现,这堆屎有毒!原项目经过多个作者反复拉屎,完美的实现了主包拉屎,分包也拉屎的操作,导致整体已经很难优化了,因此我就想到是否可以使用异步组件和跨包加载js,从而剥离一部分的文件出来,实现主包体积优化。
上姿势点
在这里,我们需要先引入来自微信小程序官方的文档:分包异步化
微信小程序在2.11.2之后就已经支持分包异步化了,因此引入了俩个特性,支持 跨分包自定义组件引用 与 跨分包 JS 代码引用,应用这俩个特性我们可以去优化主包体积。
1. 跨分包自定义组件引用
跨分包自定义组件引用,需要搭配占位组件的配置才可以实现,根据微信小程序官方文档描述如下。

而在uniapp中,对应的我们需要在pages.json中进行如下配置
配置之后,我们就可以在页面中正常使用了,对应的slots、props、events的传递在分包加载进来之后便可以正常响应。
但是这一切看似美好,实际上还是存在部分问题的,主要如下
- (1) 在分包未加载完成之前,该组件为占位组件,如果是view,text等基础组件,则slots的内容会直接显示出来,影响用户体验
- (2) 该方案只支持直接在页面使用分包组件,页面内的子组件引入均无效
- (3) 该方案在遇到分包比较大的时候容易造成过长的加载时间等待
虽然存在着部分问题,但是我们依然可以将部分业务组件分离到分包中,然后使用跨包组件,从而减少主包的体积,在我这个项目中我对接的腾讯云IM就是通过这种形式,将消息列表对接到tabbar中,否则按照以往的经验这一部分肯定占据主包大量的空间。
2. 跨分包js调用
跨分包js调用,需要到require,而对于uniapp而言,直接使用require会导致报错,无法通过编译。因此我开发了一个插件,可以简单直接的实现调用分包js。
对应的插件地址:zion-uniapp-mp-load-package
对应的github demo地址: zionLZH/zion-uniapp-mp-load-package
-
1.首先我们需要先安装依赖
npm install zion-uniapp-mp-load-package -D 或 yarn add zion-uniapp-mp-load-package -D
-
2.修改配置文件,因为vue2和vue3的配置文件不一样因此需要分别处理
这是vue2的,新增/修改vue.config.js
const { zionUniMpLoadPackagePlugin } = require('zionUniMpLoadPackagePlugin/webpack')
module.exports = {
configureWebpack: {
plugins: [
new zionUniMpLoadPackagePlugin()
],
optimization: {
moduleIds: 'named',
}
},
}
这是vue3的,新增/修改vite.config.js
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import { zionUniMpLoadPackagePlugin } from './script/zionUniMpLoadPackagePlugin/vite'
export default defineConfig({
plugins: [
uni(),
zionUniMpLoadPackagePlugin()
],
});
- 3.直接调用跨包js
// 这里的packageA对应的就是分包目录
loadMpPackage("packageA", () => {
// ...
console.log('加载成功')
// 这里就可以直接引入分包中对应位置的js,调用其方法
console.log(loadMpPackageModule('/packageA/sdk/index.js'))
console.log(loadMpPackageModule('/packageA/sdk/index.js').a())
}, ({mod, errMsg}) => {
// ...
console.log('加载出错', mod, errMsg)
})
在使用我的插件之后,基本上很多第三方的js,或者比较占体积的js可以直接转移到一个独立的分包中,从而极大的减少主包的占用,我通过这个方式把高德,省市区,im,音视频等插件都进行了转移,终于把主包减少到了1M左右。
对了,如果有大佬不吝啬的话,也可以帮我点个star哦:https://github.com/zionLZH/zion-uniapp-mp-load-package
2024年7月26日:已经确定有的bug,仅存在vue2版本,引入插件之后导致主包体积反而增大,这仅在vue2/webpack版本存在,原因是因为webpack打包模块的时候moduleId被插件接管之后计算出来的moduleId有问题(因为分包里面需要进行重定向,导致分包的Id有问题,目前暂时没有一个完美的结局方案)。建议开发者自行根据项目实际跑起来的情况确定是否采用本方案(可以先引入插件,空跑一下看看前后主包体积),感谢评论区大佬提出与配合调试。
前言
最近在接到一个二开项目,发现一个普通的小项目居然主包超过了1.5MB,并且甲方还在持续加码功能,一看就是一个屎山项目。为了更好的进行开发,我打算重新规划一下整个小程序,并且进行分包,而当我打算在清理一堆屎的时候我才发现,这堆屎有毒!原项目经过多个作者反复拉屎,完美的实现了主包拉屎,分包也拉屎的操作,导致整体已经很难优化了,因此我就想到是否可以使用异步组件和跨包加载js,从而剥离一部分的文件出来,实现主包体积优化。
上姿势点
在这里,我们需要先引入来自微信小程序官方的文档:分包异步化
微信小程序在2.11.2之后就已经支持分包异步化了,因此引入了俩个特性,支持 跨分包自定义组件引用 与 跨分包 JS 代码引用,应用这俩个特性我们可以去优化主包体积。
1. 跨分包自定义组件引用
跨分包自定义组件引用,需要搭配占位组件的配置才可以实现,根据微信小程序官方文档描述如下。
而在uniapp中,对应的我们需要在pages.json中进行如下配置
配置之后,我们就可以在页面中正常使用了,对应的slots、props、events的传递在分包加载进来之后便可以正常响应。
但是这一切看似美好,实际上还是存在部分问题的,主要如下
- (1) 在分包未加载完成之前,该组件为占位组件,如果是view,text等基础组件,则slots的内容会直接显示出来,影响用户体验
- (2) 该方案只支持直接在页面使用分包组件,页面内的子组件引入均无效
- (3) 该方案在遇到分包比较大的时候容易造成过长的加载时间等待
虽然存在着部分问题,但是我们依然可以将部分业务组件分离到分包中,然后使用跨包组件,从而减少主包的体积,在我这个项目中我对接的腾讯云IM就是通过这种形式,将消息列表对接到tabbar中,否则按照以往的经验这一部分肯定占据主包大量的空间。
2. 跨分包js调用
跨分包js调用,需要到require,而对于uniapp而言,直接使用require会导致报错,无法通过编译。因此我开发了一个插件,可以简单直接的实现调用分包js。
对应的插件地址:zion-uniapp-mp-load-package
对应的github demo地址: zionLZH/zion-uniapp-mp-load-package
-
1.首先我们需要先安装依赖
npm install zion-uniapp-mp-load-package -D 或 yarn add zion-uniapp-mp-load-package -D
-
2.修改配置文件,因为vue2和vue3的配置文件不一样因此需要分别处理
这是vue2的,新增/修改vue.config.js
const { zionUniMpLoadPackagePlugin } = require('zionUniMpLoadPackagePlugin/webpack')
module.exports = {
configureWebpack: {
plugins: [
new zionUniMpLoadPackagePlugin()
],
optimization: {
moduleIds: 'named',
}
},
}
这是vue3的,新增/修改vite.config.js
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
import { zionUniMpLoadPackagePlugin } from './script/zionUniMpLoadPackagePlugin/vite'
export default defineConfig({
plugins: [
uni(),
zionUniMpLoadPackagePlugin()
],
});
- 3.直接调用跨包js
// 这里的packageA对应的就是分包目录
loadMpPackage("packageA", () => {
// ...
console.log('加载成功')
// 这里就可以直接引入分包中对应位置的js,调用其方法
console.log(loadMpPackageModule('/packageA/sdk/index.js'))
console.log(loadMpPackageModule('/packageA/sdk/index.js').a())
}, ({mod, errMsg}) => {
// ...
console.log('加载出错', mod, errMsg)
})
在使用我的插件之后,基本上很多第三方的js,或者比较占体积的js可以直接转移到一个独立的分包中,从而极大的减少主包的占用,我通过这个方式把高德,省市区,im,音视频等插件都进行了转移,终于把主包减少到了1M左右。
对了,如果有大佬不吝啬的话,也可以帮我点个star哦:https://github.com/zionLZH/zion-uniapp-mp-load-package
2024年7月26日:已经确定有的bug,仅存在vue2版本,引入插件之后导致主包体积反而增大,这仅在vue2/webpack版本存在,原因是因为webpack打包模块的时候moduleId被插件接管之后计算出来的moduleId有问题(因为分包里面需要进行重定向,导致分包的Id有问题,目前暂时没有一个完美的结局方案)。建议开发者自行根据项目实际跑起来的情况确定是否采用本方案(可以先引入插件,空跑一下看看前后主包体积),感谢评论区大佬提出与配合调试。
收起阅读 »
【解决】使用yz-qr生成二维码,canvas有时候会空白问题
// 在weapp-qrcode.js里
// 注释下面这个代码
// _oContext.draw()
// 添加下面这些代码
setTimeout(() => {
_oContext.draw(true, (canvasResult) => {
console.log('二维码绘画成功', canvasResult);
this.success && this.success();
});
})
// 在yz-qr.vue文件下添加success成功回调
new qrCode('canvas', {
text: "123456",
width: 100,
height: 100,
......
success: () => {
// 二维码绘画成功回调
uni.canvasToTempFilePath({
canvasId: this.canvasId,
success: (res) => {
this.canvasQrPath = res.tempFilePath
this.$emit('update:qrPath', this.canvasQrPath)
console.log('canvas转成图片成功:', res.tempFilePath);
},
fail: (err) => {
console.log('canvas转成图片失败:', err)
}
}, this)
}
})
↓↓↓ 各位大佬点点赞
// 在weapp-qrcode.js里
// 注释下面这个代码
// _oContext.draw()
// 添加下面这些代码
setTimeout(() => {
_oContext.draw(true, (canvasResult) => {
console.log('二维码绘画成功', canvasResult);
this.success && this.success();
});
})
// 在yz-qr.vue文件下添加success成功回调
new qrCode('canvas', {
text: "123456",
width: 100,
height: 100,
......
success: () => {
// 二维码绘画成功回调
uni.canvasToTempFilePath({
canvasId: this.canvasId,
success: (res) => {
this.canvasQrPath = res.tempFilePath
this.$emit('update:qrPath', this.canvasQrPath)
console.log('canvas转成图片成功:', res.tempFilePath);
},
fail: (err) => {
console.log('canvas转成图片失败:', err)
}
}, this)
}
})
↓↓↓ 各位大佬点点赞
收起阅读 »
vue3+electron31+vite5客户端聊天应用
基于最新跨平台技术原创研发vue3+electron31.x+vite5+pinia2+element-plus仿微信电脑版聊天室Exe程序。整个聊天程序界面清爽简约,支持展示/收缩侧边栏、electron新开多窗口、换肤等功能。
electron31+vite5+vue3+elementPlus仿微信客户端聊天exe程序ElectronViteChat
vue3-electron-wechat使用vite5.x构建工具搭建项目模板,采用vue3 setup语法开发,融合electron跨平台技术。
实现技术
- 编码工具:Vscode
- 技术框架:electron31+vite5+vue3.4.29+vue-router4.4.0
- 跨端框架:electron^31.1.0
- 组件库:element-plus^2.7.6 (饿了么vue3组件库)
- 状态管理:pinia^2.1.7
- 存储服务:pinia-plugin-persistedstate^3.2.1
- electron打包工具:electron-builder^24.13.3
- electron整合vite插件:vite-plugin-electron^0.28.7
前段时间有分享一篇vue3+vite5网页版聊天室,感兴趣的可以去看看。
https://ask.dcloud.net.cn/article/41153
项目结构
vite-electronChat聊天已经同步到我的最新原创作品集,有需要的可以去看看。
https://gf.bilibili.com/item/detail/1106312011
入口配置main.js
import { createApp } from 'vue'
import './style.scss'
import App from './App.vue'
// 引入组件库
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 引入路由/状态管理
import Router from './router'
import Pinia from './pinia'
import { launchApp } from '@/windows/actions'
launchApp().then(config => {
if(config) {
console.log('窗口参数:', config)
console.log('窗口id:', config?.id)
// 全局存储窗口配置
window.config = config
}
// 创建app应用实例
createApp(App)
.use(ElementPlus)
.use(Router)
.use(Pinia)
.mount('#app')
})
electron主进程
/**
* 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()
})
项目布局模板
<template>
<template v-if="!route?.meta?.isNewWin">
<div
class="vu__container flexbox flex-alignc flex-justifyc"
:style="{'--themeSkin': appstate.config.skin}"
>
<div class="vu__layout flexbox flex-col">
<div class="vu__layout-body flex1 flexbox" @contextmenu.prevent>
<!-- 菜单栏 -->
<slot v-if="!route?.meta?.hideMenuBar" name="menubar">
<MenuBar />
</slot>
<!-- 侧边栏 -->
<div v-if="route?.meta?.showSideBar" class="vu__layout-sidebar flexbox">
<aside class="vu__layout-sidebar__body flexbox flex-col">
<slot name="sidebar">
<SideBar />
</slot>
</aside>
</div>
<!-- 主内容区 -->
<div class="vu__layout-main flex1 flexbox flex-col">
<ToolBar v-if="!route?.meta?.hideToolBar" />
<router-view v-slot="{ Component, route }">
<keep-alive>
<component :is="Component" :key="route.path" />
</keep-alive>
</router-view>
</div>
</div>
</div>
</div>
</template>
<template v-else>
<WinLayout />
</template>
</template>
electron多窗口|新开窗口
/**
* 创建新窗口
* @param {object} args 窗口配置参数 {url: '/chat', width: 850, height: 600, ...}
*/
export function winCreate(args) {
window.electron.send('win-create', args)
}
// 登录窗口
export function loginWindow() {
winCreate({
url: '/login',
title: '登录',
width: 320,
height: 380,
isMajor: true,
resizable: false,
maximizable: false,
alwaysOnTop: true
})
}
// 关于窗口
export function aboutWindow() {
winCreate({
url: '/win/about',
title: '关于',
width: 375,
height: 300,
minWidth: 375,
minHeight: 300,
maximizable: false,
alwaysOnTop: true,
})
}
// 设置窗口
export function settingWindow() {
winCreate({
url: '/win/setting',
title: '设置',
width: 550,
height: 470,
resizable: false,
maximizable: false,
})
}
新建窗口支持如下参数配置:
// 自定义窗口参数
const windowOptions = {
// 窗口唯一标识id
id: null,
// 窗口标题
title: 'Electron-ViteChat',
// 窗口路由地址
url: '',
// 窗口数据传参
data: null,
// 是否是主窗口(为true则会关闭所有窗口并创建一个新窗口)
isMajor: false,
// 是否支持多开窗口(为true则支持创建多个窗口)
isMultiple: false,
// 窗口是否最大化
maximize: false,
}
// 系统窗口参数(与electron的new BrowserWindow()参数一致)
const windowBaseOptions = {
// 窗口图标
icon: join(__root, 'resources/shortcut.ico'),
// 是否自动隐藏菜单栏(按下Alt键显示)
autoHideMenuBar: true,
// 窗口标题栏样式
titleBarStyle: 'hidden',
// 窗口背景色
backgroundColor: '#fff',
// 宽度
width: 840,
// 高度
height: 610,
// 最小宽度
minWidth: '',
// 最小高度
minHeight: '',
// 窗口x坐标
x: '',
// 窗口y坐标
y: '',
// 是否可缩放
resizable: true,
// 是否可最小化
minimizable: true,
// 是否可最大化
maximizable: true,
// 是否可关闭
closable: true,
// 父窗口
parent: null,
// 是否模态窗口
modal: false,
// 窗口是否置顶
alwaysOnTop: false,
// 是否显示窗口边框(要创建无边框窗口,将frame参数设置为false)
frame: false,
// 是否透明窗口(仅frame: false有效)
transparent: false,
// 创建时是否显示窗口
show: false,
}
electron-builder打包配置
{
"productName": "Electron-ViteChat",
"appId": "com.andy.electron-vite-wechat",
"copyright": "Copyright © 2024-present Andy Q:282310962",
"compression": "maximum",
"asar": true,
"directories": {
"output": "release/${version}"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"perMachine": true,
"deleteAppDataOnUninstall": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "ElectronViteChat"
},
"win": {
"icon": "./resources/shortcut.ico",
"artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}",
"target": [
{
"target": "nsis",
"arch": ["ia32"]
}
]
},
"mac": {
"icon": "./resources/shortcut.icns",
"artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}"
},
"linux": {
"icon": "./resources",
"artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}"
}
}
综上就是vue3+vite5+electron31实战开发仿微信客户端聊天的一些知识分享,希望对大家有些帮助~
作者:xiaoyan2017
链接: https://segmentfault.com/a/1190000045042968
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
基于最新跨平台技术原创研发vue3+electron31.x+vite5+pinia2+element-plus仿微信电脑版聊天室Exe程序。整个聊天程序界面清爽简约,支持展示/收缩侧边栏、electron新开多窗口、换肤等功能。
electron31+vite5+vue3+elementPlus仿微信客户端聊天exe程序ElectronViteChat
vue3-electron-wechat使用vite5.x构建工具搭建项目模板,采用vue3 setup语法开发,融合electron跨平台技术。
实现技术
- 编码工具:Vscode
- 技术框架:electron31+vite5+vue3.4.29+vue-router4.4.0
- 跨端框架:electron^31.1.0
- 组件库:element-plus^2.7.6 (饿了么vue3组件库)
- 状态管理:pinia^2.1.7
- 存储服务:pinia-plugin-persistedstate^3.2.1
- electron打包工具:electron-builder^24.13.3
- electron整合vite插件:vite-plugin-electron^0.28.7
前段时间有分享一篇vue3+vite5网页版聊天室,感兴趣的可以去看看。
https://ask.dcloud.net.cn/article/41153
项目结构
vite-electronChat聊天已经同步到我的最新原创作品集,有需要的可以去看看。
https://gf.bilibili.com/item/detail/1106312011
入口配置main.js
import { createApp } from 'vue'
import './style.scss'
import App from './App.vue'
// 引入组件库
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 引入路由/状态管理
import Router from './router'
import Pinia from './pinia'
import { launchApp } from '@/windows/actions'
launchApp().then(config => {
if(config) {
console.log('窗口参数:', config)
console.log('窗口id:', config?.id)
// 全局存储窗口配置
window.config = config
}
// 创建app应用实例
createApp(App)
.use(ElementPlus)
.use(Router)
.use(Pinia)
.mount('#app')
})
electron主进程
/**
* 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()
})
项目布局模板
<template>
<template v-if="!route?.meta?.isNewWin">
<div
class="vu__container flexbox flex-alignc flex-justifyc"
:style="{'--themeSkin': appstate.config.skin}"
>
<div class="vu__layout flexbox flex-col">
<div class="vu__layout-body flex1 flexbox" @contextmenu.prevent>
<!-- 菜单栏 -->
<slot v-if="!route?.meta?.hideMenuBar" name="menubar">
<MenuBar />
</slot>
<!-- 侧边栏 -->
<div v-if="route?.meta?.showSideBar" class="vu__layout-sidebar flexbox">
<aside class="vu__layout-sidebar__body flexbox flex-col">
<slot name="sidebar">
<SideBar />
</slot>
</aside>
</div>
<!-- 主内容区 -->
<div class="vu__layout-main flex1 flexbox flex-col">
<ToolBar v-if="!route?.meta?.hideToolBar" />
<router-view v-slot="{ Component, route }">
<keep-alive>
<component :is="Component" :key="route.path" />
</keep-alive>
</router-view>
</div>
</div>
</div>
</div>
</template>
<template v-else>
<WinLayout />
</template>
</template>
electron多窗口|新开窗口
/**
* 创建新窗口
* @param {object} args 窗口配置参数 {url: '/chat', width: 850, height: 600, ...}
*/
export function winCreate(args) {
window.electron.send('win-create', args)
}
// 登录窗口
export function loginWindow() {
winCreate({
url: '/login',
title: '登录',
width: 320,
height: 380,
isMajor: true,
resizable: false,
maximizable: false,
alwaysOnTop: true
})
}
// 关于窗口
export function aboutWindow() {
winCreate({
url: '/win/about',
title: '关于',
width: 375,
height: 300,
minWidth: 375,
minHeight: 300,
maximizable: false,
alwaysOnTop: true,
})
}
// 设置窗口
export function settingWindow() {
winCreate({
url: '/win/setting',
title: '设置',
width: 550,
height: 470,
resizable: false,
maximizable: false,
})
}
新建窗口支持如下参数配置:
// 自定义窗口参数
const windowOptions = {
// 窗口唯一标识id
id: null,
// 窗口标题
title: 'Electron-ViteChat',
// 窗口路由地址
url: '',
// 窗口数据传参
data: null,
// 是否是主窗口(为true则会关闭所有窗口并创建一个新窗口)
isMajor: false,
// 是否支持多开窗口(为true则支持创建多个窗口)
isMultiple: false,
// 窗口是否最大化
maximize: false,
}
// 系统窗口参数(与electron的new BrowserWindow()参数一致)
const windowBaseOptions = {
// 窗口图标
icon: join(__root, 'resources/shortcut.ico'),
// 是否自动隐藏菜单栏(按下Alt键显示)
autoHideMenuBar: true,
// 窗口标题栏样式
titleBarStyle: 'hidden',
// 窗口背景色
backgroundColor: '#fff',
// 宽度
width: 840,
// 高度
height: 610,
// 最小宽度
minWidth: '',
// 最小高度
minHeight: '',
// 窗口x坐标
x: '',
// 窗口y坐标
y: '',
// 是否可缩放
resizable: true,
// 是否可最小化
minimizable: true,
// 是否可最大化
maximizable: true,
// 是否可关闭
closable: true,
// 父窗口
parent: null,
// 是否模态窗口
modal: false,
// 窗口是否置顶
alwaysOnTop: false,
// 是否显示窗口边框(要创建无边框窗口,将frame参数设置为false)
frame: false,
// 是否透明窗口(仅frame: false有效)
transparent: false,
// 创建时是否显示窗口
show: false,
}
electron-builder打包配置
{
"productName": "Electron-ViteChat",
"appId": "com.andy.electron-vite-wechat",
"copyright": "Copyright © 2024-present Andy Q:282310962",
"compression": "maximum",
"asar": true,
"directories": {
"output": "release/${version}"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"perMachine": true,
"deleteAppDataOnUninstall": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "ElectronViteChat"
},
"win": {
"icon": "./resources/shortcut.ico",
"artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}",
"target": [
{
"target": "nsis",
"arch": ["ia32"]
}
]
},
"mac": {
"icon": "./resources/shortcut.icns",
"artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}"
},
"linux": {
"icon": "./resources",
"artifactName": "${productName}-v${version}-${platform}-${arch}-setup.${ext}"
}
}
综上就是vue3+vite5+electron31实战开发仿微信客户端聊天的一些知识分享,希望对大家有些帮助~
作者:xiaoyan2017
链接: https://segmentfault.com/a/1190000045042968
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

【公告】DCloud发票系统升级

Windows在符号链接的文件夹下创建项目导致运行报错,关键字:keepAliveInclude,Unknown custom element,'id' of undefined
创建项目为官方提供的Demo
可能出现的bug如下
Web运行:
index.js:1127 Uncaught
ReferenceError: uni is not defined
Property or method "keepAliveInclude" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
Unknown custom element: <App> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
微信小程序运行:
ERROR TypeError: Cannot read property 'id' of undefined
如遇到上述错误提示信息,请检查项目路径是否包含符号链接文件夹,如果有该情况或类似情况,可将项目移动至无符号链接的文件夹中,可正常运行
创建项目为官方提供的Demo
可能出现的bug如下
Web运行:
index.js:1127 Uncaught
ReferenceError: uni is not defined
Property or method "keepAliveInclude" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
Unknown custom element: <App> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
微信小程序运行:
ERROR TypeError: Cannot read property 'id' of undefined
如遇到上述错误提示信息,请检查项目路径是否包含符号链接文件夹,如果有该情况或类似情况,可将项目移动至无符号链接的文件夹中,可正常运行
收起阅读 »
HBuilder X 编辑器体验极差的一个地方
作为新手,刚用这个 IDE,经常找不到打开项目的入口。后来我找到原因了:如果我不小心收起了侧边栏,下次打开 HBuilder 后,界面如下:
然后,我会尝试重新打开项目,但编辑器会提示
让人百思不得其解(如果此时自动显示侧边框也可以啊)。
最后我在【视图--显示项目管理器等左侧视图】菜单下,找到了恢复侧边框的办法。
好家伙,原来项目是已打开的,只是我不知道还原侧边栏导致。HBuilder X 界面的设计非常不人性化,它那个侧边栏的指示「箭头」默认会自动隐藏,只有你把鼠标移到相应位置,再点击一个,才会显示出来。
熟练之后,我把快捷键记下来了,下次按 cmd+b 就能直接开关侧边栏了,好像体验也没什么问题? 但对于新手,还是要摸索一下的,给人不是很顺手的感觉。
还有很多小点,总感觉这个编辑器是个半成品。
吐槽完了,仅代表个人体验~
作为新手,刚用这个 IDE,经常找不到打开项目的入口。后来我找到原因了:如果我不小心收起了侧边栏,下次打开 HBuilder 后,界面如下:
然后,我会尝试重新打开项目,但编辑器会提示
让人百思不得其解(如果此时自动显示侧边框也可以啊)。
最后我在【视图--显示项目管理器等左侧视图】菜单下,找到了恢复侧边框的办法。
好家伙,原来项目是已打开的,只是我不知道还原侧边栏导致。HBuilder X 界面的设计非常不人性化,它那个侧边栏的指示「箭头」默认会自动隐藏,只有你把鼠标移到相应位置,再点击一个,才会显示出来。
熟练之后,我把快捷键记下来了,下次按 cmd+b 就能直接开关侧边栏了,好像体验也没什么问题? 但对于新手,还是要摸索一下的,给人不是很顺手的感觉。
还有很多小点,总感觉这个编辑器是个半成品。
吐槽完了,仅代表个人体验~
收起阅读 »
UID短信无法登录问题,短信验证无法登录问题。
相信很多朋友在建立项目是碰见了这个问题:使用uid短信登陆,一切都弄好了,但是一运行就出现;
未找到scene=login-by-sms,的短信模版templateId。\n已启动测试模式,直接使用:123456作为短信验证码即可。\n如果是正式项目,请在路径:/common/uni-config-center/uni-id/config.json中service->sms中配置密钥等信息,
最后我试了很多遍,发现问题在这里;
官方在指引文件中给的方法是在UID的设置文件config中,选择填写
"service": {
"sms": {
"name": "模板名称",
"codeExpiresIn": 180,
"scene": {
"bind-mobile-by-sms": {
"templateId": "模板ID",
"codeExpiresIn": 240
}
}
}
}
但其实scene是场景的意思,也就是说,SMS应用场景有可能不止一个,而其中的bind-mobile-by-sms意思是指通过短信绑定手机号,并不是我们要的短信登陆,所以才导致我们填写完了相关信息却在登陆环节一直没有识别,导致出现未找到登陆对应的场景。以下借用其他朋友的编码解决该问题。
"service": {
"sms": {
"name": 模板名称",
"codeExpiresIn": 180,
"scene": {
"login-by-sms": {
"templateId": "模板id",
"codeExpiresIn": 240
},
"bind-mobile-by-sms": {
"templateId": "模板id",
"codeExpiresIn": 240
},
"reset-pwd-by-sms": {
"templateId": "模板id",
"codeExpiresIn": 240
}
}
},
"univerify": {
"appid": ""
}
}
}
这样我们就在一个短信模板下加了三个场景,分别是登陆,绑定,重置密码。如果需要使用不同ID的短息模板的话,去自己服务器相关页面设置就好。
亲测有效。
相信很多朋友在建立项目是碰见了这个问题:使用uid短信登陆,一切都弄好了,但是一运行就出现;
未找到scene=login-by-sms,的短信模版templateId。\n已启动测试模式,直接使用:123456作为短信验证码即可。\n如果是正式项目,请在路径:/common/uni-config-center/uni-id/config.json中service->sms中配置密钥等信息,
最后我试了很多遍,发现问题在这里;
官方在指引文件中给的方法是在UID的设置文件config中,选择填写
"service": {
"sms": {
"name": "模板名称",
"codeExpiresIn": 180,
"scene": {
"bind-mobile-by-sms": {
"templateId": "模板ID",
"codeExpiresIn": 240
}
}
}
}
但其实scene是场景的意思,也就是说,SMS应用场景有可能不止一个,而其中的bind-mobile-by-sms意思是指通过短信绑定手机号,并不是我们要的短信登陆,所以才导致我们填写完了相关信息却在登陆环节一直没有识别,导致出现未找到登陆对应的场景。以下借用其他朋友的编码解决该问题。
"service": {
"sms": {
"name": 模板名称",
"codeExpiresIn": 180,
"scene": {
"login-by-sms": {
"templateId": "模板id",
"codeExpiresIn": 240
},
"bind-mobile-by-sms": {
"templateId": "模板id",
"codeExpiresIn": 240
},
"reset-pwd-by-sms": {
"templateId": "模板id",
"codeExpiresIn": 240
}
}
},
"univerify": {
"appid": ""
}
}
}
这样我们就在一个短信模板下加了三个场景,分别是登陆,绑定,重置密码。如果需要使用不同ID的短息模板的话,去自己服务器相关页面设置就好。
亲测有效。

ios应用的测试方法-testflight
ios的应用开发好后,让开发人员测试有两种方法:
1、上传到app stoe,然后测试人员的手机安装testflight,通过testflight去测试
2、创建ad hoc格式的证书和证书profile文件(描述文件),然后将测试者的手机的udid添加到profile文件,通过这种证书打包的应用打好ipa包后,可以不上架,可以上传到香蕉云编或蒲公英等内测平台生成安装二维码,扫码安装。
这里我们重点讲述第一种,通过testflight的方法
1、首选,在app store创建好app,创建app的时候,选择的套装ID(bundle ID)要跟我们在uniapp里打包的appId(包名)一致, 如下图,假如已经创建好app就可以跳过这个步骤:
2、创建好app后,可以看看有一个testflight的目录
这里的testflight需要mac的xcode等上传工具上传上来,假如没有mac电脑,可以使用香蕉云编来上传:
https://www.yunedit.com/ipasend
3、然后就是需要邀请用户进来测试,进入用户和访问模块,点蓝色加号添加测试人员的appleid进来:
4、然后测试人员在测试手机安装testflight软件,使用testflight安装刚上传的构建版本,就可以测试了。
5、在testflight的测试员界面,也可以清楚的看到谁安装了
ios的应用开发好后,让开发人员测试有两种方法:
1、上传到app stoe,然后测试人员的手机安装testflight,通过testflight去测试
2、创建ad hoc格式的证书和证书profile文件(描述文件),然后将测试者的手机的udid添加到profile文件,通过这种证书打包的应用打好ipa包后,可以不上架,可以上传到香蕉云编或蒲公英等内测平台生成安装二维码,扫码安装。
这里我们重点讲述第一种,通过testflight的方法
1、首选,在app store创建好app,创建app的时候,选择的套装ID(bundle ID)要跟我们在uniapp里打包的appId(包名)一致, 如下图,假如已经创建好app就可以跳过这个步骤:
2、创建好app后,可以看看有一个testflight的目录
这里的testflight需要mac的xcode等上传工具上传上来,假如没有mac电脑,可以使用香蕉云编来上传:
https://www.yunedit.com/ipasend
3、然后就是需要邀请用户进来测试,进入用户和访问模块,点蓝色加号添加测试人员的appleid进来:
4、然后测试人员在测试手机安装testflight软件,使用testflight安装刚上传的构建版本,就可以测试了。
5、在testflight的测试员界面,也可以清楚的看到谁安装了
收起阅读 »