Commit f5182a1c authored by wuhao's avatar wuhao 🎯

root

parents
File added
node_modules
/.env.local
/.umirc.local.ts
/config/config.local.ts
/src/.umi
/src/.umi-production
/src/.umi-test
dist
.swc
.history
\ No newline at end of file
This diff is collapsed.
# EE框架 v3
[![star](https://gitee.com/dromara/electron-egg/badge/star.svg?theme=gvp)](https://gitee.com/dromara/electron-egg/stargazers)
<div align=center>
<h3>🎉🎉🎉 框架下载量突破10万+ 🎉🎉🎉</h3>
</div>
<br>
<div align=center>
<img src="https://wallace5303.gitee.io/ee/images/electron-egg/logo.png" width="150" height="150" />
</div>
<div align=center>
<h3><strong>一个入门简单、跨平台、企业级桌面软件开发框架</strong></h3>
</div>
<br>
## 🌏 [English](https://www.yuque.com/u34495/ee-doc) | [中文](https://www.kaka996.com/)
## 📋 介绍
- 🍩 **为什么使用?** 桌面软件(办公方向、 个人工具),仍然是未来十几年PC端需求之一,提高工作效率
- 🍉 **简单:** 只需懂 JavaScript
- 🍑 **愿景:** 所有开发者都能学会桌面软件研发
- 🍰 **gitee:** https://gitee.com/dromara/electron-egg **3400+**
- 🍨 **github:** https://github.com/dromara/electron-egg **900+**
- 🏆 码云最有价值开源项目
![](https://wallace5303.gitee.io/ee/images/electron-egg/ee-zs.png)
## 📚 文档
- [教程文档](https://www.kaka996.com/)
## 📦 特性
1. 🍄 跨平台:一套代码,可以打包成windows版、Mac版、Linux版、国产UOS、Deepin、麒麟等
2. 🌹 架构:单业务进程/模块化/多任务(进程,线程,渲染进程),让开发大型项目变的简单。
3. 🌱 简单高效:只需学习 js 语言
4. 🌴 前端独立:理论上支持任何前端技术,如:vue、react、html等等
5. 🍁 工程化:可以用前端、服务端的开发思维,来编写桌面软件
6. 🌷 高性能:事件驱动、非阻塞式IO
7. 🌰 功能丰富:配置、通信、插件、数据库、升级、打包、工具... 应有尽有
8. 💐 安全:支持字节码加密、压缩混淆加密
9. 🌻 功能demo:桌面软件常见功能,框架集成或提供demo
## ✈️ 使用场景
### 1. 🚀 常规桌面软件
- 🚖 windows平台
![](https://wallace5303.gitee.io/ee/images/electron-egg/home.png)
- 🚍 macOS平台
![](https://wallace5303.gitee.io/ee/images/electron-egg/mac-socket.png)
- 🚔 linux平台 - 国产UOS、Deepin
![](https://wallace5303.gitee.io/ee/images/electron-egg/uos-home.png)
- 🚔 linux平台 - ubuntu
![](https://wallace5303.gitee.io/ee/images/electron-egg/ubuntu-db.png)
### 🚐 2. vue、react、angular、web 转换成桌面软件
- 🚙 vue-ant-design(本地)
![](https://wallace5303.gitee.io/ee/images/electron-egg/vue-antd.png)
- 🚙 禅道项目管理(web项目地址)
![](https://wallace5303.gitee.io/ee/images/electron-egg/ee-project-7.png)
### 🚂 3. 游戏(h5相关技术开发)
- 🚊 忍者100层
![](https://wallace5303.gitee.io/ee/images/electron-egg/ee_game_1.png)
## 📒 开始使用
- ✒️ [安装文档](https://www.kaka996.com/pages/e64ff6/)
## 🐶 项目案例
- 🐟 EE框架已经应用于医疗、学校、政务、股票交易、ERP、娱乐、视频、企业等领域客户端
- 🐸 英雄联盟助手
![](https://wallace5303.gitee.io/ee/images/electron-egg/serendipity/lol-zhanji.png)
- [更多项目](https://www.kaka996.com/pages/eadf46/)
## 💬 交流
1. [讨论](https://www.kaka996.com/pages/c2720e/)
## 📌 关于pr
请前往[GitHub项目](https://github.com/dromara/electron-egg)提pr(避免代码同步后,pr被覆盖掉),感谢!
地址:https://github.com/dromara/electron-egg
## 📔 框架核心包 ee-core
ee-core:[https://github.com/wallace5303/ee-core](https://github.com/wallace5303/ee-core)
## 📚 Dromara 成员项目
<p align="center">
<a href="https://gitee.com/dromara/TLog" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/tlog2.png" title="一个轻量级的分布式日志标记追踪神器,10分钟即可接入,自动对日志打标签完成微服务的链路追踪" width="15%">
</a>
<a href="https://gitee.com/dromara/liteFlow" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/liteflow.png" title="轻量,快速,稳定,可编排的组件式流程引擎" width="15%">
</a>
<a href="https://hutool.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/hutool.jpg" title="小而全的Java工具类库,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。" width="15%">
</a>
<a href="https://sa-token.dev33.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/sa-token.png" title="一个轻量级 java 权限认证框架,让鉴权变得简单、优雅!" width="15%">
</a>
<a href="https://gitee.com/dromara/hmily" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/hmily.png" title="高性能一站式分布式事务解决方案。" width="15%">
</a>
<a href="https://gitee.com/dromara/Raincat" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/raincat.png" title="强一致性分布式事务解决方案。" width="15%">
</a>
</p>
<p align="center">
<a href="https://gitee.com/dromara/myth" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/myth.png" title="可靠消息分布式事务解决方案。" width="15%">
</a>
<a href="https://cubic.jiagoujishu.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/cubic.png" title="一站式问题定位平台,以agent的方式无侵入接入应用,完整集成arthas功能模块,致力于应用级监控,帮助开发人员快速定位问题" width="15%">
</a>
<a href="https://maxkey.top/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/maxkey.png" title="业界领先的身份管理和认证产品" width="15%">
</a>
<a href="http://forest.dtflyx.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/forest-logo.png" title="Forest能够帮助您使用更简单的方式编写Java的HTTP客户端" width="15%">
</a>
<a href="https://jpom.io/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/jpom.png" title="一款简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件" width="15%">
</a>
<a href="https://su.usthe.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/sureness.png" title="面向 REST API 的高性能认证鉴权框架" width="15%">
</a>
</p>
<p align="center">
<a href="https://easy-es.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/easy-es2.png" title="傻瓜级ElasticSearch搜索引擎ORM框架" width="15%">
</a>
<a href="https://gitee.com/dromara/northstar" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/northstar_logo.png" title="Northstar盈富量化交易平台" width="15%">
</a>
<a href="https://hertzbeat.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/hertzbeat_brand.jpg" title="易用友好的云监控系统" width="15%">
</a>
<a href="https://plugins.sheng90.wang/fast-request/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/fast-request.gif" title="Idea 版 Postman,为简化调试API而生" width="15%">
</a>
<a href="https://www.jeesuite.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/mendmix.png" title="开源分布式云原生架构一站式解决方案" width="15%">
</a>
<a href="https://gitee.com/dromara/koalas-rpc" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/koalas-rpc2.png" title="企业生产级百亿日PV高可用可拓展的RPC框架。" width="15%">
</a>
</p>
<p align="center">
<a href="https://async.sizegang.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/gobrs-async.png" title="配置极简功能强大的异步任务动态编排框架" width="15%">
</a>
<a href="https://dynamictp.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/dynamic-tp.png" title="基于配置中心的轻量级动态可监控线程池" width="15%">
</a>
<a href="https://www.x-easypdf.cn" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/x-easypdf.png" title="一个用搭积木的方式构建pdf的框架(基于pdfbox)" width="15%">
</a>
<a href="http://dromara.gitee.io/image-combiner" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/image-combiner.png" title="一个专门用于图片合成的工具,没有很复杂的功能,简单实用,却不失强大" width="15%">
</a>
<a href="https://www.herodotus.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/dante-cloud2.png" title="Dante-Cloud 是一款企业级微服务架构和服务能力开发平台。" width="15%">
</a>
<a href="https://dromara.org/zh/projects/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/dromara.png" title="让每一位开源爱好者,体会到开源的快乐。" width="15%">
</a>
</p>
\ No newline at end of file
# EE框架 v3
[![star](https://gitee.com/dromara/electron-egg/badge/star.svg?theme=gvp)](https://gitee.com/dromara/electron-egg/stargazers)
<div align=center>
<h3>🎉🎉🎉 框架下载量突破10万+ 🎉🎉🎉</h3>
</div>
<br>
<div align=center>
<img src="https://wallace5303.gitee.io/ee/images/electron-egg/logo.png" width="150" height="150" />
</div>
<div align=center>
<h3><strong>一个入门简单、跨平台、企业级桌面软件开发框架</strong></h3>
</div>
<br>
## 🌏 [English](https://www.yuque.com/u34495/ee-doc) | [中文](https://www.kaka996.com/)
## 📋 介绍
- 🍩 **为什么使用?** 桌面软件(办公方向、 个人工具),仍然是未来十几年PC端需求之一,提高工作效率
- 🍉 **简单:** 只需懂 JavaScript
- 🍑 **愿景:** 所有开发者都能学会桌面软件研发
- 🍰 **gitee:** https://gitee.com/dromara/electron-egg **3400+**
- 🍨 **github:** https://github.com/dromara/electron-egg **900+**
- 🏆 码云最有价值开源项目
![](https://wallace5303.gitee.io/ee/images/electron-egg/ee-zs.png)
## 📚 文档
- [教程文档](https://www.kaka996.com/)
## 📦 特性
1. 🍄 跨平台:一套代码,可以打包成windows版、Mac版、Linux版、国产UOS、Deepin、麒麟等
2. 🌹 架构:单业务进程/模块化/多任务(进程,线程,渲染进程),让开发大型项目变的简单。
3. 🌱 简单高效:只需学习 js 语言
4. 🌴 前端独立:理论上支持任何前端技术,如:vue、react、html等等
5. 🍁 工程化:可以用前端、服务端的开发思维,来编写桌面软件
6. 🌷 高性能:事件驱动、非阻塞式IO
7. 🌰 功能丰富:配置、通信、插件、数据库、升级、打包、工具... 应有尽有
8. 💐 安全:支持字节码加密、压缩混淆加密
9. 🌻 功能demo:桌面软件常见功能,框架集成或提供demo
## ✈️ 使用场景
### 1. 🚀 常规桌面软件
- 🚖 windows平台
![](https://wallace5303.gitee.io/ee/images/electron-egg/home.png)
- 🚍 macOS平台
![](https://wallace5303.gitee.io/ee/images/electron-egg/mac-socket.png)
- 🚔 linux平台 - 国产UOS、Deepin
![](https://wallace5303.gitee.io/ee/images/electron-egg/uos-home.png)
- 🚔 linux平台 - ubuntu
![](https://wallace5303.gitee.io/ee/images/electron-egg/ubuntu-db.png)
### 🚐 2. vue、react、angular、web 转换成桌面软件
- 🚙 vue-ant-design(本地)
![](https://wallace5303.gitee.io/ee/images/electron-egg/vue-antd.png)
- 🚙 禅道项目管理(web项目地址)
![](https://wallace5303.gitee.io/ee/images/electron-egg/ee-project-7.png)
### 🚂 3. 游戏(h5相关技术开发)
- 🚊 忍者100层
![](https://wallace5303.gitee.io/ee/images/electron-egg/ee_game_1.png)
## 📒 开始使用
- ✒️ [安装文档](https://www.kaka996.com/pages/e64ff6/)
## 🐶 项目案例
- 🐟 EE框架已经应用于医疗、学校、政务、股票交易、ERP、娱乐、视频、企业等领域客户端
- 🐸 英雄联盟助手
![](https://wallace5303.gitee.io/ee/images/electron-egg/serendipity/lol-zhanji.png)
- [更多项目](https://www.kaka996.com/pages/eadf46/)
## 💬 交流
1. [讨论](https://www.kaka996.com/pages/c2720e/)
## 📌 关于pr
请前往[GitHub项目](https://github.com/dromara/electron-egg)提pr(避免代码同步后,pr被覆盖掉),感谢!
地址:https://github.com/dromara/electron-egg
## 📔 框架核心包 ee-core
ee-core:[https://github.com/wallace5303/ee-core](https://github.com/wallace5303/ee-core)
## 📚 Dromara 成员项目
<p align="center">
<a href="https://gitee.com/dromara/TLog" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/tlog2.png" title="一个轻量级的分布式日志标记追踪神器,10分钟即可接入,自动对日志打标签完成微服务的链路追踪" width="15%">
</a>
<a href="https://gitee.com/dromara/liteFlow" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/liteflow.png" title="轻量,快速,稳定,可编排的组件式流程引擎" width="15%">
</a>
<a href="https://hutool.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/hutool.jpg" title="小而全的Java工具类库,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。" width="15%">
</a>
<a href="https://sa-token.dev33.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/sa-token.png" title="一个轻量级 java 权限认证框架,让鉴权变得简单、优雅!" width="15%">
</a>
<a href="https://gitee.com/dromara/hmily" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/hmily.png" title="高性能一站式分布式事务解决方案。" width="15%">
</a>
<a href="https://gitee.com/dromara/Raincat" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/raincat.png" title="强一致性分布式事务解决方案。" width="15%">
</a>
</p>
<p align="center">
<a href="https://gitee.com/dromara/myth" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/myth.png" title="可靠消息分布式事务解决方案。" width="15%">
</a>
<a href="https://cubic.jiagoujishu.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/cubic.png" title="一站式问题定位平台,以agent的方式无侵入接入应用,完整集成arthas功能模块,致力于应用级监控,帮助开发人员快速定位问题" width="15%">
</a>
<a href="https://maxkey.top/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/maxkey.png" title="业界领先的身份管理和认证产品" width="15%">
</a>
<a href="http://forest.dtflyx.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/forest-logo.png" title="Forest能够帮助您使用更简单的方式编写Java的HTTP客户端" width="15%">
</a>
<a href="https://jpom.io/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/jpom.png" title="一款简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件" width="15%">
</a>
<a href="https://su.usthe.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/sureness.png" title="面向 REST API 的高性能认证鉴权框架" width="15%">
</a>
</p>
<p align="center">
<a href="https://easy-es.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/easy-es2.png" title="傻瓜级ElasticSearch搜索引擎ORM框架" width="15%">
</a>
<a href="https://gitee.com/dromara/northstar" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/northstar_logo.png" title="Northstar盈富量化交易平台" width="15%">
</a>
<a href="https://hertzbeat.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/hertzbeat_brand.jpg" title="易用友好的云监控系统" width="15%">
</a>
<a href="https://plugins.sheng90.wang/fast-request/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/fast-request.gif" title="Idea 版 Postman,为简化调试API而生" width="15%">
</a>
<a href="https://www.jeesuite.com/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/mendmix.png" title="开源分布式云原生架构一站式解决方案" width="15%">
</a>
<a href="https://gitee.com/dromara/koalas-rpc" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/koalas-rpc2.png" title="企业生产级百亿日PV高可用可拓展的RPC框架。" width="15%">
</a>
</p>
<p align="center">
<a href="https://async.sizegang.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/gobrs-async.png" title="配置极简功能强大的异步任务动态编排框架" width="15%">
</a>
<a href="https://dynamictp.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/dynamic-tp.png" title="基于配置中心的轻量级动态可监控线程池" width="15%">
</a>
<a href="https://www.x-easypdf.cn" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/x-easypdf.png" title="一个用搭积木的方式构建pdf的框架(基于pdfbox)" width="15%">
</a>
<a href="http://dromara.gitee.io/image-combiner" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/image-combiner.png" title="一个专门用于图片合成的工具,没有很复杂的功能,简单实用,却不失强大" width="15%">
</a>
<a href="https://www.herodotus.cn/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/dante-cloud2.png" title="Dante-Cloud 是一款企业级微服务架构和服务能力开发平台。" width="15%">
</a>
<a href="https://dromara.org/zh/projects/" target="_blank">
<img src="https://oss.dev33.cn/sa-token/link/dromara.png" title="让每一位开源爱好者,体会到开源的快乐。" width="15%">
</a>
</p>
\ No newline at end of file
chrome应用商店ctx文件,解压后,放置在此目录中,打包时会将资源加入安装包内。
\ No newline at end of file
建议第三方软件放置在此目录中,打包时会将资源加入安装包内。
\ No newline at end of file
{
"cache": {
"config": {
"env": "local",
"name": "ee",
"baseDir": "/Users/wuhao/Desktop/demos/standaloneframe/electron",
"HOME": "/Users/wuhao/Desktop/demos/standaloneframe",
"rundir": "/Users/wuhao/Desktop/demos/standaloneframe/electron/run",
"dump": {
"ignore": {}
},
"homeDir": "/Users/wuhao/Desktop/demos/standaloneframe",
"root": "/Users/wuhao/Desktop/demos/standaloneframe",
"appUserDataDir": "/Users/wuhao/Library/Application Support/ee",
"userHome": "/Users/wuhao",
"appVersion": "3.4.0",
"isPackaged": false,
"execDir": "/Users/wuhao/Desktop/demos/standaloneframe",
"logger": {
"type": "application",
"dir": "/Users/wuhao/Desktop/demos/standaloneframe/logs",
"encoding": "utf8",
"env": "local",
"level": "INFO",
"consoleLevel": "INFO",
"disableConsoleAfterReady": false,
"outputJSON": false,
"buffer": true,
"appLogName": "ee.log",
"coreLogName": "ee-core.log",
"agentLogName": "ee-agent.log",
"errorLogName": "ee-error.log",
"coreLogger": {},
"allowDebugAtProd": false,
"enablePerformanceTimer": false,
"rotator": "day"
},
"customLogger": {},
"httpclient": {
"enableDNSCache": false,
"dnsCacheLookupInterval": 10000,
"dnsCacheMaxLength": 1000,
"request": {
"timeout": 5000
},
"httpAgent": {
"keepAlive": true,
"freeSocketTimeout": 4000,
"maxSockets": 9007199254740991,
"maxFreeSockets": 256
},
"httpsAgent": {
"keepAlive": true,
"freeSocketTimeout": 4000,
"maxSockets": 9007199254740991,
"maxFreeSockets": 256
}
},
"developmentMode": {
"default": "vue",
"mode": {
"vue": {
"protocol": "http://",
"hostname": "localhost",
"port": 8080
},
"react": {
"protocol": "http://",
"hostname": "localhost",
"port": 3000
},
"html": {
"protocol": "http://",
"hostname": "localhost",
"indexPage": "index.html"
}
}
},
"socketServer": {
"enable": false,
"port": 7070,
"path": "/socket.io/",
"connectTimeout": 45000,
"pingTimeout": 30000,
"pingInterval": 25000,
"maxHttpBufferSize": 100000000,
"transports": [
"polling",
"websocket"
],
"cors": {
"origin": true
}
},
"httpServer": {
"enable": false,
"https": {
"enable": false,
"key": "/public/ssl/localhost+1.key",
"cert": "/public/ssl/localhost+1.pem"
},
"protocol": "http://",
"host": "localhost",
"port": 7071,
"cors": {
"origin": "*"
},
"body": {
"multipart": true,
"formidable": {
"keepExtensions": true
}
},
"filterRequest": {
"uris": [
"favicon.ico"
],
"returnData": ""
}
},
"mainServer": {
"protocol": "http://",
"indexPath": "/public/dist/index.html",
"host": "localhost",
"port": 7072,
"options": {},
"ssl": {
"key": "",
"cert": ""
}
},
"openAppMenu": "dev-show",
"hardGpu": {
"enable": false
},
"storage": {
"dir": "/Users/wuhao/Desktop/demos/standaloneframe/data"
},
"loadingPage": false,
"addons": {
"window": {
"enable": true
},
"tray": {
"enable": true,
"title": "EE程序",
"icon": "/public/images/tray_logo.png"
},
"security": {
"enable": true
},
"awaken": {
"enable": true,
"protocol": "ee",
"args": []
},
"autoUpdater": {
"enable": true,
"windows": false,
"macOS": false,
"linux": false,
"options": {
"provider": "generic",
"url": "http://kodo.qiniu.com/"
},
"force": false
},
"javaServer": {
"enable": false,
"port": 18080,
"jreVersion": "jre1.8.0_201",
"opt": "-server -Xms512M -Xmx512M -Xss512k -Dspring.profiles.active=prod -Dserver.port=${port} -Dlogging.file.path=\"${path}\" ",
"name": "java-app.jar"
}
},
"exception": {
"mainExit": false,
"childExit": true,
"rendererExit": true
},
"openDevTools": false,
"windowsOption": {
"title": "EE框架",
"width": 980,
"height": 650,
"minWidth": 800,
"minHeight": 650,
"webPreferences": {
"contextIsolation": false,
"nodeIntegration": true
},
"frame": true,
"show": false,
"icon": "/Users/wuhao/Desktop/demos/standaloneframe/public/images/logo-32.png"
},
"remoteUrl": {
"enable": false,
"url": "http://electron-egg.kaka996.com/"
},
"testConfig": {
"login": "http://local.com/api/login"
},
"coreMiddlewares": [],
"coreMiddleware": [],
"appMiddlewares": [],
"appMiddleware": []
}
}
}
\ No newline at end of file
const { app: electronApp } = require('electron');
const { autoUpdater } = require("electron-updater");
const is = require('ee-core/utils/is');
const Log = require('ee-core/log');
const Conf = require('ee-core/config');
const CoreWindow = require('ee-core/electron/window');
/**
* 自动升级插件
* @class
*/
class AutoUpdaterAddon {
constructor() {
}
/**
* 创建
*/
create () {
Log.info('[addon:autoUpdater] load');
const cfg = Conf.getValue('addons.autoUpdater');
if ((is.windows() && cfg.windows)
|| (is.macOS() && cfg.macOS)
|| (is.linux() && cfg.linux))
{
// continue
} else {
return
}
// 是否检查更新
if (cfg.force) {
this.checkUpdate();
}
const status = {
error: -1,
available: 1,
noAvailable: 2,
downloading: 3,
downloaded: 4,
}
const version = electronApp.getVersion();
Log.info('[addon:autoUpdater] current version: ', version);
// 设置下载服务器地址
let server = cfg.options.url;
let lastChar = server.substring(server.length - 1);
server = lastChar === '/' ? server : server + "/";
//Log.info('[addon:autoUpdater] server: ', server);
cfg.options.url = server;
// 是否后台自动下载
autoUpdater.autoDownload = cfg.force ? true : false;
try {
autoUpdater.setFeedURL(cfg.options);
} catch (error) {
Log.error('[addon:autoUpdater] setFeedURL error : ', error);
}
autoUpdater.on('checking-for-update', () => {
//sendStatusToWindow('正在检查更新...');
})
autoUpdater.on('update-available', (info) => {
info.status = status.available;
info.desc = '有可用更新';
this.sendStatusToWindow(info);
})
autoUpdater.on('update-not-available', (info) => {
info.status = status.noAvailable;
info.desc = '没有可用更新';
this.sendStatusToWindow(info);
})
autoUpdater.on('error', (err) => {
let info = {
status: status.error,
desc: err
}
this.sendStatusToWindow(info);
})
autoUpdater.on('download-progress', (progressObj) => {
let percentNumber = parseInt(progressObj.percent);
let totalSize = this.bytesChange(progressObj.total);
let transferredSize = this.bytesChange(progressObj.transferred);
let text = '已下载 ' + percentNumber + '%';
text = text + ' (' + transferredSize + "/" + totalSize + ')';
let info = {
status: status.downloading,
desc: text,
percentNumber: percentNumber,
totalSize: totalSize,
transferredSize: transferredSize
}
Log.info('[addon:autoUpdater] progress: ', text);
this.sendStatusToWindow(info);
})
autoUpdater.on('update-downloaded', (info) => {
info.status = status.downloaded;
info.desc = '下载完成';
this.sendStatusToWindow(info);
// quit and update
// app.appQuit();
autoUpdater.quitAndInstall();
});
}
/**
* 检查更新
*/
checkUpdate () {
autoUpdater.checkForUpdates();
}
/**
* 下载更新
*/
download () {
autoUpdater.downloadUpdate();
}
/**
* 向前端发消息
*/
sendStatusToWindow(content = {}) {
const textJson = JSON.stringify(content);
const channel = 'app.updater';
const win = CoreWindow.getMainWindow();
win.webContents.send(channel, textJson);
}
/**
* 单位转换
*/
bytesChange (limit) {
let size = "";
if(limit < 0.1 * 1024){
size = limit.toFixed(2) + "B";
}else if(limit < 0.1 * 1024 * 1024){
size = (limit/1024).toFixed(2) + "KB";
}else if(limit < 0.1 * 1024 * 1024 * 1024){
size = (limit/(1024 * 1024)).toFixed(2) + "MB";
}else{
size = (limit/(1024 * 1024 * 1024)).toFixed(2) + "GB";
}
let sizeStr = size + "";
let index = sizeStr.indexOf(".");
let dou = sizeStr.substring(index + 1 , index + 3);
if(dou == "00"){
return sizeStr.substring(0, index) + sizeStr.substring(index + 3, index + 5);
}
return size;
}
}
AutoUpdaterAddon.toString = () => '[class AutoUpdaterAddon]';
module.exports = AutoUpdaterAddon;
\ No newline at end of file
const { app: electronApp } = require('electron');
const Log = require('ee-core/log');
const Conf = require('ee-core/config');
/**
* 唤醒插件
* @class
*/
class AwakenAddon {
constructor() {
this.protocol = '';
}
/**
* 创建
*/
create () {
Log.info('[addon:awaken] load');
const cfg = Conf.getValue('addons.awaken');
this.protocol = cfg.protocol;
electronApp.setAsDefaultProtocolClient(this.protocol);
this.handleArgv(process.argv);
electronApp.on('second-instance', (event, argv) => {
if (process.platform === 'win32') {
this.handleArgv(argv)
}
})
// 仅用于macOS
electronApp.on('open-url', (event, urlStr) => {
this.handleUrl(urlStr)
})
}
/**
* 参数处理
*/
handleArgv(argv) {
const offset = electronApp.isPackaged ? 1 : 2;
const url = argv.find((arg, i) => i >= offset && arg.startsWith(this.protocol));
this.handleUrl(url)
}
/**
* url解析
*/
handleUrl(awakeUrlStr) {
if (!awakeUrlStr || awakeUrlStr.length === 0) {
return
}
const {hostname, pathname, search} = new URL(awakeUrlStr);
let awakeUrlInfo = {
urlStr: awakeUrlStr,
urlHost: hostname,
urlPath: pathname,
urlParams: search && search.slice(1)
}
Log.info('[addon:awaken] awakeUrlInfo:', awakeUrlInfo);
}
}
AwakenAddon.toString = () => '[class AwakenAddon]';
module.exports = AwakenAddon;
\ No newline at end of file
const { app, session } = require('electron');
const _ = require('lodash');
const fs = require('fs');
const path = require('path');
const Log = require('ee-core/log');
/**
* 扩展插件 (electron自身对该功能并不完全支持,官方也不建议使用)
* @class
*/
class ChromeExtensionAddon {
constructor() {
}
/**
* 创建
*/
async create () {
Log.info('[addon:chromeExtension] load');
const extensionIds = this.getAllIds();
for (let i = 0; i < extensionIds.length; i++) {
await this.load(extensionIds[i]);
}
}
/**
* 获取扩展id列表(crx解压后的目录名,即是该扩展的id)
*/
getAllIds () {
const extendsionDir = this.getDirectory();
const ids = this.getDirs(extendsionDir);
return ids;
}
/**
* 扩展所在目录
*/
getDirectory () {
let extensionDirPath = '';
let variablePath = 'build'; // 打包前路径
if (app.isPackaged) {
variablePath = '..'; // 打包后路径
}
extensionDirPath = path.join(app.getAppPath(), variablePath, "extraResources", "chromeExtension");
return extensionDirPath;
}
/**
* 加载扩展
*/
async load (extensionId = '') {
if (_.isEmpty(extensionId)) {
return false
}
try {
const extensionPath = path.join(this.getDirectory(), extensionId);
Log.info('[addon:chromeExtension] extensionPath:', extensionPath);
await session.defaultSession.loadExtension(extensionPath, { allowFileAccess: true });
} catch (e) {
Log.info('[addon:chromeExtension] load extension error extensionId:%s, errorInfo:%s', extensionId, e.toString());
return false
}
return true
}
/**
* 获取目录下所有文件夹
*/
getDirs(dir) {
if (!dir) {
return [];
}
const components = [];
const files = fs.readdirSync(dir);
files.forEach(function(item, index) {
const stat = fs.lstatSync(dir + '/' + item);
if (stat.isDirectory() === true) {
components.push(item);
}
});
return components;
};
}
ChromeExtensionAddon.toString = () => '[class ChromeExtensionAddon]';
module.exports = ChromeExtensionAddon;
\ No newline at end of file
const server = require("./server");
const { app: electronApp } = require('electron');
const Log = require('ee-core/log');
const Conf = require('ee-core/config');
const GetPort = require('ee-core/utils/get-port');
/**
* java server插件
* @class
*/
class JavaServerAddon {
constructor() {
this.cfg;
this.javaServer;
}
/**
* 创建java服务
*
* @function
* @since 1.0.0
*/
async createServer () {
this.cfg = Conf.getValue('addons.javaServer');
await this.createJavaPorts();
this.javaServer = new server();
await this.javaServer.create(this.cfg);
// kill
electronApp.on("before-quit", async () => {
Log.info("[addon:javaServer] before-quit: kill-----------");
await this.javaServer.kill();
});
return;
}
/**
* todo 检查服务是否启动
*
* @function
* @since 1.0.0
*/
async check () {
}
/**
* 创建服务端口
*
* @function
* @since 1.0.0
*/
async createJavaPorts() {
if (!this.cfg.enable) {
return;
}
const javaPort = await GetPort({ port: this.cfg.port });
process.env.EE_JAVA_PORT = javaPort;
this.cfg.port = javaPort;
// 更新config配置
Conf.setValue('addons.javaServer', this.cfg);
}
/**
* 杀掉进程
*
* @function
* @since 1.0.0
*/
async kill() {
if (!this.cfg.enable) {
return;
}
await this.javaServer.kill();
}
}
JavaServerAddon.toString = () => '[class JavaServerAddon]';
module.exports = JavaServerAddon;
\ No newline at end of file
var ChildProcess = require("child_process");
var IS_WIN = process.platform === "win32";
var TableParser = require("table-parser");
/**
* End of line.
* Basically, the EOL should be:
* - windows: \r\n
* - *nix: \n
* But i'm trying to get every possibilities covered.
*/
var EOL = /(\r\n)|(\n\r)|\n|\r/;
var SystemEOL = require("os").EOL;
/**
* Execute child process
* @type {Function}
* @param {String[]} args
* @param {String} where
* @param {Function} callback
* @param {Object=null} callback.err
* @param {Object[]} callback.stdout
*/
var Exec = function (args, where) {
var spawnSync = ChildProcess.spawnSync;
var execSync = ChildProcess.execSync;
// on windows, if use ChildProcess.exec(`wmic process get`), the stdout will gives you nothing
// that's why I use `cmd` instead
if (IS_WIN) {
const cmd = `wmic process where ${where} get ProcessId,ParentProcessId,CommandLine \n`;
const result = execSync(cmd);
if (!result) {
throw new Error(result);
}
var stdout = result.toString();
var beginRow;
stdout = stdout.split(EOL);
// Find the line index for the titles
stdout.forEach(function (out, index) {
if (
out &&
typeof beginRow == "undefined" &&
out.indexOf("CommandLine") === 0
) {
beginRow = index;
}
});
// get rid of the start (copyright) and the end (current pwd)
stdout.splice(stdout.length - 1, 1);
stdout.splice(0, beginRow);
return stdout.join(SystemEOL) || false;
} else {
if (typeof args === "string") {
args = args.split(/\s+/);
}
const result = spawnSync("ps", args);
if (result.stderr && !!result.stderr.toString()) {
throw new Error(result.stderr);
} else {
return result.stdout.toString();
}
}
};
/**
* Query Process: Focus on pid & cmd
* @param query
* @param {String|String[]} query.pid
* @param {String} query.command RegExp String
* @param {String} query.arguments RegExp String
* @param {String|array} query.psargs
* @param {String|array} query.where where 条件
* @param {Function} callback
* @param {Object=null} callback.err
* @param {Object[]} callback.processList
* @return {Object}
*/
exports.lookup = function (query) {
/**
* add 'lx' as default ps arguments, since the default ps output in linux like "ubuntu", wont include command arguments
*/
var exeArgs = query.psargs || ["lx"];
var where = query.where || 'name="javaw.exe"';
var filter = {};
var idList;
// Lookup by PID
if (query.pid) {
if (Array.isArray(query.pid)) {
idList = query.pid;
} else {
idList = [query.pid];
}
// Cast all PIDs as Strings
idList = idList.map(function (v) {
return String(v);
});
}
if (query.command) {
filter["command"] = new RegExp(query.command, "i");
}
if (query.arguments) {
filter["arguments"] = new RegExp(query.arguments, "i");
}
if (query.ppid) {
filter["ppid"] = new RegExp(query.ppid);
}
const result = Exec(exeArgs, where);
var processList = parseGrid(result);
var resultList = [];
processList.forEach(function (p) {
var flt;
var type;
var result = true;
if (idList && idList.indexOf(String(p.pid)) < 0) {
return;
}
for (type in filter) {
flt = filter[type];
result = flt.test(p[type]) ? result : false;
}
if (result) {
resultList.push(p);
}
});
return resultList;
};
/**
* Kill process
* @param pid
* @param {Object|String} signal
* @param {String} signal.signal
* @param {number} signal.timeout
* @param next
*/
exports.kill = function (pid, signal, next) {
//opts are optional
if (arguments.length == 2 && typeof signal == "function") {
next = signal;
signal = undefined;
}
var checkTimeoutSeconds = (signal && signal.timeout) || 30;
if (typeof signal === "object") {
signal = signal.signal;
}
try {
process.kill(pid, signal);
} catch (e) {
return next && next(e);
}
var checkConfident = 0;
var checkTimeoutTimer = null;
var checkIsTimeout = false;
function checkKilled(finishCallback) {
exports.lookup({ pid: pid }, function (err, list) {
if (checkIsTimeout) return;
if (err) {
clearTimeout(checkTimeoutTimer);
finishCallback && finishCallback(err);
} else if (list.length > 0) {
checkConfident = checkConfident - 1 || 0;
checkKilled(finishCallback);
} else {
checkConfident++;
if (checkConfident === 5) {
clearTimeout(checkTimeoutTimer);
finishCallback && finishCallback();
} else {
checkKilled(finishCallback);
}
}
});
}
next && checkKilled(next);
checkTimeoutTimer =
next &&
setTimeout(function () {
checkIsTimeout = true;
next(new Error("Kill process timeout"));
}, checkTimeoutSeconds * 1000);
};
/**
* Parse the stdout into readable object.
* @param {String} output
*/
function parseGrid(output) {
if (!output) {
return [];
}
return formatOutput(TableParser.parse(output));
}
/**
* format the structure, extract pid, command, arguments, ppid
* @param data
* @return {Array}
*/
function formatOutput(data) {
var formatedData = [];
data.forEach(function (d) {
var pid =
(d.PID && d.PID[0]) || (d.ProcessId && d.ProcessId[0]) || undefined;
var cmd = d.CMD || d.CommandLine || d.COMMAND || undefined;
var ppid =
(d.PPID && d.PPID[0]) ||
(d.ParentProcessId && d.ParentProcessId[0]) ||
undefined;
if (pid && cmd) {
var command = cmd[0];
var args = "";
if (cmd.length > 1) {
args = cmd.slice(1);
}
formatedData.push({
pid: pid,
command: command,
arguments: args,
ppid: ppid,
});
}
});
return formatedData;
}
const _ = require("lodash");
const assert = require("assert");
const fs = require("fs");
const path = require("path");
const { exec, execSync } = require("child_process");
const ps = require("./ps");
const Log = require('ee-core/log');
const is = require('ee-core/utils/is');
const UtilsPs = require('ee-core/ps');
/**
* java server
*/
class JavaServer {
constructor () {
this.options;
}
/**
* 创建服务
*/
async create (cfg) {
this.options = cfg;
if (this.options.enable == false) {
return;
}
let port = process.env.EE_JAVA_PORT ? parseInt(process.env.EE_JAVA_PORT) : parseInt(this.options.port);
assert(typeof port === "number", "java port required, and must be a number");
try {
const jarName = this.options.name;
let softwarePath = path.join(UtilsPs.getExtraResourcesDir(), jarName);
let javaOptStr = this.options.opt;
let jrePath = path.join(UtilsPs.getExtraResourcesDir(), this.options.jreVersion);
let cmdStr = '';
Log.info("[addon:javaServer] jar file path:", softwarePath);
if (!fs.existsSync(softwarePath)) throw new Error('java program does not exist');
// 替换opt参数
javaOptStr = _.replace(javaOptStr, "${port}", port);
javaOptStr = _.replace(javaOptStr, "${path}", UtilsPs.getLogDir());
if (is.windows()) {
jrePath = path.join(jrePath, "bin", "javaw.exe");
cmdStr = `start ${jrePath} -jar ${javaOptStr} ${softwarePath}`;
} else if (is.macOS()) {
// 如果提示:不受信任,请执行: sudo spctl --master-disable
jrePath = path.join(jrePath, "Contents", "Home", "bin", "java");
//cmdStr = `nohup ${jrePath} -jar ${javaOptStr} ${softwarePath} >/dev/null 2>&1 &`;
cmdStr = `${jrePath} -jar ${javaOptStr} ${softwarePath}`;
} else {
// todo linux
}
Log.info("[addon:javaServer] cmdStr:", cmdStr);
exec(cmdStr);
} catch (err) {
Log.error('[addon:javaServer] throw error:', err);
}
}
/**
* 关闭服务
*/
async kill () {
const jarName = this.options.name;
if (is.windows()) {
const resultList = ps.lookup({
command: "java",
where: 'caption="javaw.exe"',
arguments: jarName,
});
//Log.info("[addon:javaServer] resultList:", resultList);
resultList.forEach((item) => {
ps.kill(item.pid, "SIGKILL", (err) => {
if (err) {
throw new Error(err);
}
Log.info("[addon:javaServer] java程序退出 pid: ", item.pid);
});
});
// const cmd = `for /f "tokens=1-5" %i in ('netstat -ano ^| findstr ":${port}"') do taskkill /F /T /PID %m`;
// const a = await execSync(cmd, {encoding: 'utf-8'});
// Log.info("[javaServer] kill:", a);
} else if (is.macOS()) {
const cmd = `ps -ef | grep java | grep ${jarName} | grep -v grep | awk '{print $2}' | xargs kill -9`;
const result = await execSync(cmd);
Log.info("[addon:javaServer] kill:", result != null ? result.toString(): '');
} else {
// todo linux
}
}
}
module.exports = JavaServer;
\ No newline at end of file
const Log = require('ee-core/log');
const EE = require('ee-core/ee');
/**
* 安全插件
* @class
*/
class SecurityAddon {
constructor() {
}
/**
* 创建
*/
create () {
Log.info('[addon:security] load');
const { CoreApp } = EE;
const runWithDebug = process.argv.find(function(e){
let isHasDebug = e.includes("--inspect") || e.includes("--inspect-brk") || e.includes("--remote-debugging-port");
return isHasDebug;
})
// 不允许远程调试
if (runWithDebug) {
Log.error('[error] Remote debugging is not allowed, runWithDebug:', runWithDebug);
CoreApp.appQuit();
}
}
}
SecurityAddon.toString = () => '[class SecurityAddon]';
module.exports = SecurityAddon;
\ No newline at end of file
const { Tray, Menu, shell } = require('electron');
const path = require('path');
const Ps = require('ee-core/ps');
const Log = require('ee-core/log');
const Electron = require('ee-core/electron');
const CoreWindow = require('ee-core/electron/window');
const Conf = require('ee-core/config');
const EE = require('ee-core/ee');
/**
* 托盘插件
* @class
*/
class TrayAddon {
constructor() {
this.tray = null;
}
/**
* 创建托盘
*/
create () {
// 开发环境,代码热更新开启时,会导致托盘中有残影
if (Ps.isDev() && Ps.isHotReload()) return;
Log.info('[addon:tray] load');
const { CoreApp } = EE;
const cfg = Conf.getValue('addons.tray');
const mainWindow = CoreWindow.getMainWindow();
// 托盘图标
let iconPath = path.join(Ps.getHomeDir(), cfg.icon);
// 托盘菜单功能列表
let trayMenuTemplate = [
{
label: '显示',
click: function () {
mainWindow.show();
}
},
{
label: '退出',
click: function () {
CoreApp.appQuit();
}
}
]
// 点击关闭,最小化到托盘
mainWindow.on('close', (event) => {
if (Electron.extra.closeWindow == true) {
return;
}
mainWindow.hide();
event.preventDefault();
});
// 实例化托盘
this.tray = new Tray(iconPath);
this.tray.setToolTip(cfg.title);
const contextMenu = Menu.buildFromTemplate(trayMenuTemplate);
this.tray.setContextMenu(contextMenu);
// 使用默认浏览器打开链接
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: 'deny' }
})
}
}
TrayAddon.toString = () => '[class TrayAddon]';
module.exports = TrayAddon;
\ No newline at end of file
{
"productName": "ee",
"appId": "com.electron.ee",
"copyright": "© 2023 哆啦好梦 Technology Co., Ltd.",
"directories": {
"output": "out"
},
"asar": true,
"files": [
"**/*",
"!frontend/",
"!run/",
"!logs/",
"!data/"
],
"extraResources": {
"from": "build/extraResources/",
"to": "extraResources"
},
"nsis": {
"oneClick": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true,
"installerIcon": "build/icons/icon.ico",
"uninstallerIcon": "build/icons/icon.ico",
"installerHeaderIcon": "build/icons/icon.ico",
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "EE框架"
},
"mac": {
"icon": "build/icons/icon.icns",
"artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
"darkModeSupport": true,
"hardenedRuntime": false
},
"win": {
"icon": "build/icons/icon.ico",
"artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
"target": [
{
"target": "nsis"
}
]
},
"linux": {
"icon": "build/icons/icon.icns",
"artifactName": "${productName}-${os}-${version}-${arch}.${ext}",
"target": [
"deb"
],
"category": "Utility"
}
}
\ No newline at end of file
'use strict';
const path = require('path');
/**
* 默认配置
*/
module.exports = (appInfo) => {
const config = {};
/**
* 应用模式配置
*/
config.developmentMode = {
default: 'vue',
mode: {
vue: {
hostname: 'localhost',
port: 8080
},
react: {
hostname: 'localhost',
port: 3000
},
html: {
hostname: 'localhost',
indexPage: 'index.html'
},
}
};
/**
* 开发者工具
*/
config.openDevTools = false;
/**
* 应用程序顶部菜单
*/
config.openAppMenu = 'dev-show';
/**
* 主窗口
*/
config.windowsOption = {
title: 'EE框架',
width: 980,
height: 650,
minWidth: 800,
minHeight: 650,
webPreferences: {
//webSecurity: false, // 跨域问题 -> 打开注释
contextIsolation: false, // false -> 可在渲染进程中使用electron的api,true->需要bridge.js(contextBridge)
nodeIntegration: true,
//preload: path.join(appInfo.baseDir, 'preload', 'bridge.js'),
},
frame: true,
show: false,
icon: path.join(appInfo.home, 'public', 'images', 'logo-32.png'),
};
/**
* ee框架日志
*/
config.logger = {
encoding: 'utf8',
level: 'INFO',
outputJSON: false,
buffer: true,
enablePerformanceTimer: false,
rotator: 'day',
appLogName: 'ee.log',
coreLogName: 'ee-core.log',
errorLogName: 'ee-error.log'
}
/**
* 远程模式-web地址
*/
config.remoteUrl = {
enable: false,
url: 'http://electron-egg.kaka996.com/'
};
/**
* 内置socket服务
*/
config.socketServer = {
enable: false,
port: 7070,
path: "/socket.io/",
connectTimeout: 45000,
pingTimeout: 30000,
pingInterval: 25000,
maxHttpBufferSize: 1e8,
transports: ["polling", "websocket"],
cors: {
origin: true,
}
};
/**
* 内置http服务
*/
config.httpServer = {
enable: false,
https: {
enable: false,
key: '/public/ssl/localhost+1.key',
cert: '/public/ssl/localhost+1.pem'
},
port: 7071,
cors: {
origin: "*"
},
body: {
multipart: true,
formidable: {
keepExtensions: true
}
},
filterRequest: {
uris: [
'favicon.ico'
],
returnData: ''
}
};
/**
* 主进程
*/
config.mainServer = {
protocol: 'http://',
indexPath: '/public/dist/index.html',
host: 'localhost',
port: 7072,
};
/**
* 硬件加速
*/
config.hardGpu = {
enable: false
};
/**
* 异常捕获
*/
config.exception = {
mainExit: false,
childExit: true,
rendererExit: true,
};
/**
* 插件功能
*/
config.addons = {
window: {
enable: true,
},
tray: {
enable: true,
title: 'EE程序',
icon: '/public/images/tray_logo.png'
},
security: {
enable: true,
},
awaken: {
enable: true,
protocol: 'ee',
args: []
},
autoUpdater: {
enable: true,
windows: false,
macOS: false,
linux: false,
options: {
provider: 'generic',
url: 'http://kodo.qiniu.com/'
},
force: false,
},
javaServer: {
enable: false,
port: 18080,
jreVersion: 'jre1.8.0_201',
opt: '-server -Xms512M -Xmx512M -Xss512k -Dspring.profiles.active=prod -Dserver.port=${port} -Dlogging.file.path="${path}" ',
name: 'java-app.jar'
}
};
return {
...config
};
}
'use strict';
/*
* test
*/
exports.testConfig = {
login: 'http://local.com/api/login',
};
'use strict';
/*
* test
*/
exports.testConfig = {
login: 'http://prod.com/api/login',
};
/**
* 加密配置
* @param type - confusion | bytecode | strict
*/
module.exports = {
type: 'confusion',
files: [
'electron/**/*.(js|json)',
'!electron/config/encrypt.js',
'!electron/config/nodemon.json',
'!electron/config/builder.json',
],
fileExt: ['.js'],
confusionOptions: {
compact: true,
stringArray: true,
stringArrayEncoding: ['none'],
deadCodeInjection: false,
}
};
\ No newline at end of file
{
"watch": [
"electron/",
"main.js"
],
"ignore": [],
"ext": "js,json",
"verbose": true,
"exec": "electron . --env=local --hot-reload=1",
"restartable": "hr",
"colours": true,
"events": {}
}
\ No newline at end of file
'use strict';
const { Controller } = require('ee-core');
const Log = require('ee-core/log');
const Services = require('ee-core/services');
/**
* example
* @class
*/
class ExampleController extends Controller {
constructor(ctx) {
super(ctx);
}
/**
* 所有方法接收两个参数
* @param args 前端传的参数
* @param event - ipc通信时才有值。详情见:控制器文档
*/
/**
* test
*/
async test () {
const result = await Services.get('example').test('electron');
Log.info('service result:', result);
return 'hello electron-egg';
}
}
ExampleController.toString = () => '[class ExampleController]';
module.exports = ExampleController;
\ No newline at end of file
const { Application } = require('ee-core');
class Index extends Application {
constructor() {
super();
// this === eeApp;
}
/**
* core app have been loaded
*/
async ready () {
// do some things
}
/**
* electron app ready
*/
async electronAppReady () {
// do some things
}
/**
* main window have been loaded
*/
async windowReady () {
// do some things
// 延迟加载,无白屏
const winOpt = this.config.windowsOption;
if (winOpt.show == false) {
const win = this.electron.mainWindow;
win.once('ready-to-show', () => {
win.show();
})
}
}
/**
* before app close
*/
async beforeClose () {
// do some things
}
}
Index.toString = () => '[class Index]';
module.exports = Index;
\ No newline at end of file
const Log = require('ee-core/log');
exports.welcome = function () {
Log.info('[child-process] [jobs/example/hello] welcome ! ');
}
\ No newline at end of file
const Job = require('ee-core/jobs/baseJobClass');
const Loader = require('ee-core/loader');
const Log = require('ee-core/log');
const Ps = require('ee-core/ps');
const { childMessage } = require('ee-core/message');
const Hello = Loader.requireJobsModule('./example/hello');
/**
* example - TimerJob
* @class
*/
class TimerJob extends Job {
constructor(params) {
super();
this.params = params;
}
/**
* handle()方法是必要的,且会被自动调用
*/
async handle () {
Log.info("[child-process] TimerJob params: ", this.params);
// 计时器任务
let eventName = 'job-timer-progress';
let number = 0;
let jobId = this.params.jobId;
let timer = setInterval(function() {
Hello.welcome();
childMessage.send(eventName, {jobId, number});
number++;
}, 1000);
// 用 setTimeout 模拟任务运行时长
setTimeout(() => {
// 关闭定时器
clearInterval(timer);
// 任务结束,重置前端显示
childMessage.send(eventName, {jobId, number:0, pid:0});
// 如果是childJob任务,必须调用 Ps.exit() 方法,让进程退出,否则会常驻内存
// 如果是childPoolJob任务,常驻内存,等待下一个业务
if (Ps.isChildJob()) {
Ps.exit();
}
}, 10 * 1000)
}
}
TimerJob.toString = () => '[class TimerJob]';
module.exports = TimerJob;
/*
* 如果启用了上下文隔离,渲染进程无法使用electron的api,
* 可通过contextBridge 导出api给渲染进程使用
*/
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electron', {
ipcRenderer: ipcRenderer,
})
\ No newline at end of file
/*************************************************
** preload为预加载模块,该文件将会在程序启动时加载 **
*************************************************/
const Addon = require('ee-core/addon');
/**
* 预加载模块入口
*/
module.exports = async () => {
// 示例功能模块,可选择性使用和修改
Addon.get('tray').create();
Addon.get('security').create();
Addon.get('awaken').create();
Addon.get('autoUpdater').create();
}
\ No newline at end of file
'use strict';
const { Service } = require('ee-core');
/**
* 示例服务(service层为单例)
* @class
*/
class ExampleService extends Service {
constructor(ctx) {
super(ctx);
}
/**
* test
*/
async test(args) {
let obj = {
status:'ok',
params: args
}
return obj;
}
}
ExampleService.toString = () => '[class ExampleService]';
module.exports = ExampleService;
\ No newline at end of file
import { defineConfig } from "umi";
import env from "./env";
import routes from './routes';
const { REACT_APP_ENV = "dev",NODE_ENV } = process.env;
export default defineConfig({
npmClient: "yarn",
plugins: [
"@umijs/plugins/dist/antd",
"@umijs/plugins/dist/locale",
"@umijs/plugins/dist/layout",
"@umijs/plugins/dist/initial-state",
"@umijs/plugins/dist/model",
"@umijs/plugins/dist/access",
],
antd: {
},
model: {},
initialState: {},
define: env[REACT_APP_ENV],
routes,
hash: true,
history: {
type: 'hash',
},
manifest: {
basePath: '/',
},
publicPath:NODE_ENV!=="development"?"./":"/"
});
export default {
dev:{
"REACT_APP_URL":"http://118.89.86.27:7001" //"http://118.89.86.27:7001"
},
test:{
"REACT_APP_URL":"http://localhost:7001"
},
prod:{
"REACT_APP_URL":"http://118.89.86.27:7001"
}
}
export default [
{
path: "/user",
routes: [
{
path: "/user",
redirect: "/user/login",
},
{
name: "登录",
path: "/user/login",
component: "./user/login",
},
],
},
{
path: '/',
name: '欢迎使用',
component:"@/layouts/layout",
routes: [
{
path: '/',
redirect: '/port',
},
{
name: '报单',
path: '/port',
component: './port',
},
{
name: '退货单',
path: '/report',
component: './report',
},
{
name: '个人中心',
path: '/mycenter',
component: './mycenter',
},
],
},
];
{
"private": true,
"author": "wuhao930406 <1148547900@qq.com>",
"scripts": {
"dev": "umi dev",
"build": "cross-env REACT_APP_ENV=prod umi build",
"postinstall": "umi setup",
"setup": "umi setup",
"start": "npm run dev"
},
"dependencies": {
"@ant-design/icons": "^5.1.4",
"@ant-design/pro-components": "^2.5.2",
"ahooks": "^3.7.7",
"antd": "^5.5.2",
"antd-img-crop": "^4.12.2",
"dayjs": "^1.11.7",
"react-resizable": "^3.0.5",
"react-reveal": "^1.2.2",
"umi": "^4.0.69",
"umi-request": "^1.4.0"
},
"devDependencies": {
"@types/react": "^18.0.33",
"@types/react-dom": "^18.0.11",
"@umijs/plugins": "^4.0.69",
"cross-env": "^7.0.3",
"typescript": "^5.0.3"
}
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Outlet, useOutletContext } from 'umi';
export default function EmptyRoute() {
const context = useOutletContext();
return <Outlet context={context} />;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import type { IRuntimeConfig as Plugin0 } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-antd/runtimeConfig.d'
import type { IRuntimeConfig as Plugin1 } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-initialState/runtimeConfig.d'
interface IDefaultRuntimeConfig {
onRouteChange?: (props: { routes: any, clientRoutes: any, location: any, action: any, isFirst: boolean }) => void;
patchRoutes?: (props: { routes: any }) => void;
patchClientRoutes?: (props: { routes: any }) => void;
render?: (oldRender: () => void) => void;
rootContainer?: (lastRootContainer: JSX.Element, args?: any) => void;
[key: string]: any;
}
export type RuntimeConfig = IDefaultRuntimeConfig & Plugin0 & Plugin1
export function defineApp(config: RuntimeConfig): RuntimeConfig {
return config;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { HelmetProvider } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/@umijs/renderer-react';
import { context } from './helmetContext';
export const innerProvider = (container) => {
return React.createElement(HelmetProvider, { context }, container);
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export const context = {};
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { createHashHistory, createMemoryHistory, createBrowserHistory } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/@umijs/renderer-react';
import type { UmiHistory } from './historyIntelli';
let history: UmiHistory;
let basename: string = '/';
export function createHistory(opts: any) {
let h;
if (opts.type === 'hash') {
h = createHashHistory();
} else if (opts.type === 'memory') {
h = createMemoryHistory(opts);
} else {
h = createBrowserHistory();
}
if (opts.basename) {
basename = opts.basename;
}
history = {
...h,
push(to, state) {
h.push(patchTo(to, h), state);
},
replace(to, state) {
h.replace(patchTo(to, h), state);
},
get location() {
return h.location;
},
get action() {
return h.action;
}
}
return h;
}
// Patch `to` to support basename
// Refs:
// https://github.com/remix-run/history/blob/3e9dab4/packages/history/index.ts#L484
// https://github.com/remix-run/history/blob/dev/docs/api-reference.md#to
function patchTo(to: any, h: History) {
if (typeof to === 'string') {
return `${stripLastSlash(basename)}${to}`;
} else if (typeof to === 'object') {
const currentPathname = h.location.pathname;
return {
...to,
pathname: to.pathname? `${stripLastSlash(basename)}${to.pathname}` : currentPathname,
};
} else {
throw new Error(`Unexpected to: ${to}`);
}
}
function stripLastSlash(path) {
return path.slice(-1) === '/' ? path.slice(0, -1) : path;
}
export { history };
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { getRoutes } from './route'
import type { History } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/@umijs/renderer-react'
type Routes = Awaited<ReturnType<typeof getRoutes>>['routes']
type AllRoute = Routes[keyof Routes]
type IsRoot<T extends any> = 'parentId' extends keyof T ? false : true
// show `/` in not `layout / wrapper` only
type GetAllRouteWithoutLayout<Item extends AllRoute> = Item extends any
? 'isWrapper' extends keyof Item
? never
: 'isLayout' extends keyof Item
? never
: Item
: never
type AllRouteWithoutLayout = GetAllRouteWithoutLayout<AllRoute>
type IndexRoutePathname = '/' extends AllRouteWithoutLayout['path']
? '/'
: never
type GetChildrens<T extends any> = T extends any
? IsRoot<T> extends true
? never
: T
: never
type Childrens = GetChildrens<AllRoute>
type Root = Exclude<AllRoute, Childrens>
type AllIds = AllRoute['id']
type GetChildrensByParentId<
Id extends AllIds,
Item = AllRoute
> = Item extends any
? 'parentId' extends keyof Item
? Item['parentId'] extends Id
? Item
: never
: never
: never
type RouteObject<
Id extends AllIds,
Item = GetChildrensByParentId<Id>
> = IsNever<Item> extends true
? ''
: Item extends AllRoute
? {
[Key in Item['path'] as TrimSlash<Key>]: UnionMerge<
RouteObject<Item['id']>
>
}
: never
type GetRootRouteObject<Item extends Root> = Item extends Root
? {
[K in Item['path'] as TrimSlash<K>]: UnionMerge<RouteObject<Item['id']>>
}
: never
type MergedResult = UnionMerge<GetRootRouteObject<Root>>
// --- patch history types ---
type HistoryTo = Parameters<History['push']>['0']
type HistoryPath = Exclude<HistoryTo, string>
type UmiPathname = Path<MergedResult> | (string & {})
interface UmiPath extends HistoryPath {
pathname: UmiPathname
}
type UmiTo = UmiPathname | UmiPath
type UmiPush = (to: UmiTo, state?: any) => void
type UmiReplace = (to: UmiTo, state?: any) => void
export interface UmiHistory extends History {
push: UmiPush
replace: UmiReplace
}
// --- type utils ---
type TrimLeftSlash<T extends string> = T extends `/${infer R}`
? TrimLeftSlash<R>
: T
type TrimRightSlash<T extends string> = T extends `${infer R}/`
? TrimRightSlash<R>
: T
type TrimSlash<T extends string> = TrimLeftSlash<TrimRightSlash<T>>
type IsNever<T> = [T] extends [never] ? true : false
type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends <G>() => G extends B
? 1
: 2
? true
: false
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never
type UnionMerge<U> = UnionToIntersection<U> extends infer O
? { [K in keyof O]: O[K] }
: never
type ExcludeEmptyKey<T> = IsEqual<T, ''> extends true ? never : T
type PathConcat<
TKey extends string,
TValue,
N = TrimSlash<TKey>
> = TValue extends string
? ExcludeEmptyKey<N>
:
| ExcludeEmptyKey<N>
| `${N & string}${IsNever<ExcludeEmptyKey<N>> extends true
? ''
: '/'}${UnionPath<TValue>}`
type UnionPath<T> = {
[K in keyof T]-?: PathConcat<K & string, T[K]>
}[keyof T]
type MakeSureLeftSlash<T> = T extends any
? `/${TrimRightSlash<T & string>}`
: never
// exclude `/*`, because it always at the top of the IDE tip list
type Path<T, K = UnionPath<T>> = Exclude<MakeSureLeftSlash<K>, '/*'> | IndexRoutePathname
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import * as Plugin_0 from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/app.jsx';
import * as Plugin_1 from '@@/core/helmet.ts';
import * as Plugin_2 from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-initialState/runtime.tsx';
import * as Plugin_3 from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-model/runtime.tsx';
import { PluginManager } from 'umi';
function __defaultExport (obj) {
if (obj.default) {
return typeof obj.default === 'function' ? obj.default() : obj.default
}
return obj;
}
export function getPlugins() {
return [
{
apply: __defaultExport(Plugin_0),
path: process.env.NODE_ENV === 'production' ? void 0 : '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/app.jsx',
},
{
apply: Plugin_1,
path: process.env.NODE_ENV === 'production' ? void 0 : '@@/core/helmet.ts',
},
{
apply: Plugin_2,
path: process.env.NODE_ENV === 'production' ? void 0 : '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-initialState/runtime.tsx',
},
{
apply: Plugin_3,
path: process.env.NODE_ENV === 'production' ? void 0 : '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-model/runtime.tsx',
},
];
}
export function getValidKeys() {
return ['patchRoutes','patchClientRoutes','modifyContextOpts','modifyClientRenderOpts','rootContainer','innerProvider','i18nProvider','accessProvider','dataflowProvider','outerProvider','render','onRouteChange','antd','getInitialState',];
}
let pluginManager = null;
export function createPluginManager() {
pluginManager = PluginManager.create({
plugins: getPlugins(),
validKeys: getValidKeys(),
});
return pluginManager;
}
export function getPluginManager() {
return pluginManager;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { IConfigFromPluginsJoi } from "./pluginConfigJoi.d";
interface IConfigTypes {
codeSplitting: {
jsStrategy: "bigVendors" | "depPerChunk" | "granularChunks";
jsStrategyOptions?: ({
} | undefined);
cssStrategy?: ("mergeAll" | undefined);
cssStrategyOptions?: ({
} | undefined);
};
title: string;
styles: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
scripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
routes: Array<{
component?: (string | undefined);
layout?: (false | undefined);
path?: (string | undefined);
redirect?: (string | undefined);
routes?: IConfigTypes['routes'];
wrappers?: (Array<string> | undefined);
} | { [x: string]: any }>;
reactRouter5Compat: boolean | {
};
presets: Array<string>;
plugins: Array<string>;
npmClient: "pnpm" | "tnpm" | "cnpm" | "yarn" | "npm";
mountElementId: string;
metas: Array<{
charset?: (string | undefined);
content?: (string | undefined);
"http-equiv"?: (string | undefined);
name?: (string | undefined);
} | { [x: string]: any }>;
links: Array<{
crossorigin?: (string | undefined);
href?: (string | undefined);
hreflang?: (string | undefined);
media?: (string | undefined);
referrerpolicy?: (string | undefined);
rel?: (string | undefined);
sizes?: (any | undefined);
title?: (any | undefined);
type?: (any | undefined);
} | { [x: string]: any }>;
historyWithQuery: {
};
history: {
type: "browser" | "hash" | "memory";
};
headScripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
esbuildMinifyIIFE: boolean;
conventionRoutes: {
base?: (string | undefined);
exclude?: (Array<any> | undefined);
};
conventionLayout: boolean;
base: string;
analyze: {
};
writeToDisk: boolean;
theme: { [x: string]: any };
targets: { [x: string]: any };
svgr: { [x: string]: any };
svgo: { [x: string]: any } | boolean;
styleLoader: { [x: string]: any };
srcTranspilerOptions: {
esbuild?: ({ [x: string]: any } | undefined);
swc?: ({ [x: string]: any } | undefined);
};
srcTranspiler: "babel" | "esbuild" | "swc" | "none";
sassLoader: { [x: string]: any };
runtimePublicPath: {
};
purgeCSS: { [x: string]: any };
publicPath: string;
proxy: { [x: string]: any } | Array<any>;
postcssLoader: { [x: string]: any };
outputPath: string;
normalCSSLoaderModules: { [x: string]: any };
mfsu: {
cacheDirectory?: (string | undefined);
chainWebpack?: (((...args: any[]) => unknown) | undefined);
esbuild?: (boolean | undefined);
exclude?: (Array<string | any> | undefined);
include?: (Array<string> | undefined);
mfName?: (string | undefined);
remoteAliases?: (Array<string> | undefined);
remoteName?: (string | undefined);
runtimePublicPath?: (boolean | undefined);
shared?: ({ [x: string]: any } | undefined);
strategy?: ("eager" | "normal" | undefined);
} | boolean;
mdx: {
loader?: (string | undefined);
loaderOptions?: ({ [x: string]: any } | undefined);
};
manifest: {
basePath?: (string | undefined);
fileName?: (string | undefined);
};
lessLoader: { [x: string]: any };
jsMinifierOptions: { [x: string]: any };
jsMinifier: "esbuild" | "swc" | "terser" | "uglifyJs" | "none";
inlineLimit: number;
ignoreMomentLocale: boolean;
https: {
cert?: (string | undefined);
hosts?: (Array<string> | undefined);
http2?: (boolean | undefined);
key?: (string | undefined);
};
hash: boolean;
forkTSChecker: { [x: string]: any };
fastRefresh: boolean;
extraPostCSSPlugins: Array<any>;
extraBabelPresets: Array<string | Array<any>>;
extraBabelPlugins: Array<string | Array<any>>;
extraBabelIncludes: Array<string | any>;
externals: { [x: string]: any } | string | ((...args: any[]) => unknown);
esm: {
};
devtool: "cheap-source-map" | "cheap-module-source-map" | "eval" | "eval-source-map" | "eval-cheap-source-map" | "eval-cheap-module-source-map" | "eval-nosources-cheap-source-map" | "eval-nosources-cheap-module-source-map" | "eval-nosources-source-map" | "source-map" | "hidden-source-map" | "hidden-nosources-cheap-source-map" | "hidden-nosources-cheap-module-source-map" | "hidden-nosources-source-map" | "hidden-cheap-source-map" | "hidden-cheap-module-source-map" | "inline-source-map" | "inline-cheap-source-map" | "inline-cheap-module-source-map" | "inline-nosources-cheap-source-map" | "inline-nosources-cheap-module-source-map" | "inline-nosources-source-map" | "nosources-source-map" | "nosources-cheap-source-map" | "nosources-cheap-module-source-map" | boolean;
depTranspiler: "babel" | "esbuild" | "swc" | "none";
define: { [x: string]: any };
deadCode: {
context?: (string | undefined);
detectUnusedExport?: (boolean | undefined);
detectUnusedFiles?: (boolean | undefined);
exclude?: (Array<string> | undefined);
failOnHint?: (boolean | undefined);
patterns?: (Array<string> | undefined);
};
cssMinifierOptions: { [x: string]: any };
cssMinifier: "cssnano" | "esbuild" | "parcelCSS" | "none";
cssLoaderModules: { [x: string]: any };
cssLoader: { [x: string]: any };
copy: Array<{
from: string;
to: string;
} | string>;
checkDepCssModules?: boolean;
cacheDirectoryPath: string;
babelLoaderCustomize: string;
autoprefixer: { [x: string]: any };
autoCSSModules: boolean;
alias: { [x: string]: any };
crossorigin: boolean | {
includes?: (Array<any> | undefined);
};
esmi: {
cdnOrigin: string;
shimUrl?: (string | undefined);
};
exportStatic: {
extraRoutePaths?: (((...args: any[]) => unknown) | Array<string> | undefined);
};
favicons: Array<string>;
helmet: boolean;
icons: {
autoInstall?: ({
} | undefined);
defaultComponentConfig?: ({
} | undefined);
alias?: ({
} | undefined);
include?: (Array<string> | undefined);
};
mock: {
exclude?: (Array<string> | undefined);
include?: (Array<string> | undefined);
};
mpa: {
template?: (string | undefined);
layout?: (string | undefined);
getConfigFromEntryFile?: (boolean | undefined);
entry?: ({
} | undefined);
};
phantomDependency: {
exclude?: (Array<string> | undefined);
};
polyfill: {
imports?: (Array<string> | undefined);
};
routePrefetch: {
};
terminal: {
};
tmpFiles: boolean;
clientLoader: {
};
routeProps: {
};
ssr: {
serverBuildPath?: (string | undefined);
platform?: (string | undefined);
builder?: ("esbuild" | "webpack" | undefined);
};
lowImport: {
libs?: (Array<any> | undefined);
css?: (string | undefined);
};
vite: {
};
apiRoute: {
platform?: (string | undefined);
};
monorepoRedirect: boolean | {
srcDir?: (Array<string> | undefined);
exclude?: (Array<any> | undefined);
peerDeps?: (boolean | undefined);
};
test: {
};
clickToComponent: {
/** 默认情况下,点击将默认编辑器为vscode, 你可以设置编辑器 vscode 或者 vscode-insiders */
editor?: (string | undefined);
};
legacy: {
buildOnly?: (boolean | undefined);
nodeModulesTransform?: (boolean | undefined);
checkOutput?: (boolean | undefined);
};
/** 设置 babel class-properties 启用 loose
@doc https://umijs.org/docs/api/config#classpropertiesloose */
classPropertiesLoose: boolean | {
};
ui: {
};
hmrGuardian: boolean;
verifyCommit: {
scope?: (Array<string> | undefined);
allowEmoji?: (boolean | undefined);
};
run: {
globals?: (Array<string> | undefined);
};
antd: {
configProvider?: ({ [x: string]: any } | undefined);
dark?: (boolean | undefined);
compact?: (boolean | undefined);
import?: (boolean | undefined);
style?: ("less" | "css" | undefined);
theme?: ({ [x: string]: any } | undefined);
appConfig?: ({ [x: string]: any } | undefined);
momentPicker?: (boolean | undefined);
styleProvider?: ({ [x: string]: any } | undefined);
};
locale: {
default?: (string | undefined);
useLocalStorage?: (boolean | undefined);
baseNavigator?: (boolean | undefined);
title?: (boolean | undefined);
antd?: (boolean | undefined);
baseSeparator?: (string | undefined);
};
layout: { [x: string]: any };
initialState: {
loading?: (string | undefined);
};
model: {
extraModels?: (Array<string> | undefined);
};
access: { [x: string]: any };
};
type PrettifyWithCloseable<T> = {
[K in keyof T]: T[K] | false;
} & {};
export type IConfigFromPlugins = PrettifyWithCloseable<
IConfigFromPluginsJoi & Partial<IConfigTypes>
>;
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// Created by Umi Plugin
export interface IConfigFromPluginsJoi {
}
This diff is collapsed.
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
export async function getRoutes() {
const routes = {"1":{"path":"/user","parentId":"@@/global-layout","id":"1"},"2":{"path":"/user","redirect":"/user/login","parentId":"1","id":"2"},"3":{"name":"登录","path":"/user/login","parentId":"1","id":"3"},"4":{"path":"/","name":"欢迎使用","parentId":"@@/global-layout","id":"4"},"5":{"path":"/","redirect":"/port","parentId":"4","id":"5"},"6":{"name":"报单","path":"/port","parentId":"4","id":"6"},"7":{"name":"退货单","path":"/report","parentId":"4","id":"7"},"8":{"name":"个人中心","path":"/mycenter","parentId":"4","id":"8"},"@@/global-layout":{"id":"@@/global-layout","path":"/","isLayout":true}} as const;
return {
routes,
routeComponents: {
'1': React.lazy(() => import( './EmptyRoute')),
'2': React.lazy(() => import( './EmptyRoute')),
'3': React.lazy(() => import(/* webpackChunkName: "p__user__login" */'@/pages/user/login.jsx')),
'4': React.lazy(() => import(/* webpackChunkName: "layouts__layout" */'@/layouts/layout.jsx')),
'5': React.lazy(() => import( './EmptyRoute')),
'6': React.lazy(() => import(/* webpackChunkName: "p__port__index" */'@/pages/port/index.jsx')),
'7': React.lazy(() => import(/* webpackChunkName: "p__report__index" */'@/pages/report/index.jsx')),
'8': React.lazy(() => import(/* webpackChunkName: "p__mycenter__index" */'@/pages/mycenter/index.jsx')),
'@@/global-layout': React.lazy(() => import(/* webpackChunkName: "layouts__index" */'/Users/wuhao/Desktop/demos/electron-egg/frontend/src/layouts/index.jsx')),
},
};
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
let count = 0;
let groupLevel = 0;
function send(type: string, message?: string) {
if(process.env.NODE_ENV==='production'){
return;
}else{
const encodedMessage = message ? `&m=${encodeURI(message)}` : '';
fetch(`/__umi/api/terminal?type=${type}&t=${Date.now()}&c=${count++}&g=${groupLevel}${encodedMessage}`, { mode: 'no-cors' })
}
}
function prettyPrint(obj: any) {
return JSON.stringify(obj, null, 2);
}
function stringifyObjs(objs: any[]) {
const obj = objs.length > 1 ? objs.map(stringify).join(' ') : objs[0];
return typeof obj === 'object' ? `${prettyPrint(obj)}` : obj.toString();
}
function stringify(obj: any) {
return typeof obj === 'object' ? `${JSON.stringify(obj)}` : obj.toString();
}
const terminal = {
log(...objs: any[]) { send('log', stringifyObjs(objs)) },
info(...objs: any[]) { send('info', stringifyObjs(objs)) },
warn(...objs: any[]) { send('warn', stringifyObjs(objs)) },
error(...objs: any[]) { send('error', stringifyObjs(objs)) },
group() { groupLevel++ },
groupCollapsed() { groupLevel++ },
groupEnd() { groupLevel && --groupLevel },
clear() { send('clear') },
trace(...args: any[]) { console.trace(...args) },
profile(...args: any[]) { console.profile(...args) },
profileEnd(...args: any[]) { console.profileEnd(...args) },
};
export { terminal };
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export { defineApp } from './core/defineApp'
export type { RuntimeConfig } from './core/defineApp'
// @umijs/renderer-*
export { createBrowserHistory, createHashHistory, createMemoryHistory, Helmet, HelmetProvider, createSearchParams, generatePath, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, useAppData, useClientLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData, renderClient, __getRoot, Link, useRouteData, __useFetcher, withRouter } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/@umijs/renderer-react';
export type { History } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/@umijs/renderer-react'
// umi/client/client/plugin
export { ApplyPluginsType, PluginManager } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/umi/client/client/plugin.js';
export { history, createHistory } from './core/history';
export { terminal } from './core/terminal';
// plugins
export { Provider, useModel } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-model';
// plugins types.d.ts
export * from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-antd/types.d';
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import {
Modal,
message,
notification,
} from 'antd';
import { ApplyPluginsType } from 'umi';
import { getPluginManager } from '../core/plugin';
let cacheAntdConfig = null;
const getAntdConfig = () => {
if(!cacheAntdConfig){
cacheAntdConfig = getPluginManager().applyPlugins({
key: 'antd',
type: ApplyPluginsType.modify,
initialValue: {
},
});
}
return cacheAntdConfig;
}
export function rootContainer(rawContainer) {
const {
appConfig,
...finalConfigProvider
} = getAntdConfig();
let container = rawContainer;
return container;
}
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import type { RuntimeAntdConfig } from './types.d';
export type IRuntimeConfig = {
antd?: RuntimeAntdConfig
};
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};
type AntdConfig = Prettify<{}
>;
export type RuntimeAntdConfig = (memo: AntdConfig) => AntdConfig;
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { useState, useEffect, useCallback } from 'react';
import { getInitialState } from '@/app';
export type InitialStateType = Awaited<ReturnType<typeof getInitialState>> | undefined;
const initState = {
initialState: undefined as InitialStateType,
loading: true,
error: undefined,
};
export default () => {
const [state, setState] = useState(initState);
const refresh = useCallback(async () => {
setState((s) => ({ ...s, loading: true, error: undefined }));
try {
const ret = await getInitialState();
setState((s) => ({ ...s, initialState: ret, loading: false }));
} catch (e) {
setState((s) => ({ ...s, error: e, loading: false }));
}
}, []);
const setInitialState = useCallback(
async (
initialState: InitialStateType | ((initialState: InitialStateType) => InitialStateType),
) => {
setState((s) => {
if (typeof initialState === 'function') {
return { ...s, initialState: initialState(s.initialState), loading: false };
}
return { ...s, initialState, loading: false };
});
},
[],
);
useEffect(() => {
refresh();
}, []);
return {
...state,
refresh,
setInitialState,
};
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { useModel } from '@@/plugin-model';
function Loading() { return <div />; }
export default function InitialStateProvider(props: any) {
const appLoaded = React.useRef(false);
const { loading = false } = useModel("@@initialState") || {};
React.useEffect(() => {
if (!loading) {
appLoaded.current = true;
}
}, [loading]);
if (loading && !appLoaded.current) {
return <Loading />;
}
return props.children;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import Provider from './Provider';
export function dataflowProvider(container) {
return <Provider>{ container }</Provider>;
}
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export interface IRuntimeConfig {
getInitialState?: () => Promise<Record<string, any>>
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// @ts-ignore
import type { models as rawModels } from '@@/plugin-model/model';
import isEqual from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/fast-deep-equal/index.js';
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
type Models = typeof rawModels;
type GetNamespaces<M> = {
[K in keyof M]: M[K] extends { namespace: string }
? M[K]['namespace']
: never;
}[keyof M];
type Namespaces = GetNamespaces<Models>;
// @ts-ignore
const Context = React.createContext<{ dispatcher: Dispatcher }>(null);
class Dispatcher {
callbacks: Record<Namespaces, Set<Function>> = {};
data: Record<Namespaces, unknown> = {};
update = (namespace: Namespaces) => {
if (this.callbacks[namespace]) {
this.callbacks[namespace].forEach((cb) => {
try {
const data = this.data[namespace];
cb(data);
} catch (e) {
cb(undefined);
}
});
}
};
}
interface ExecutorProps {
hook: () => any;
onUpdate: (val: any) => void;
namespace: string;
}
function Executor(props: ExecutorProps) {
const { hook, onUpdate, namespace } = props;
const updateRef = useRef(onUpdate);
const initialLoad = useRef(false);
let data: any;
try {
data = hook();
} catch (e) {
console.error(
`plugin-model: Invoking '${namespace || 'unknown'}' model failed:`,
e,
);
}
// 首次执行时立刻返回初始值
useMemo(() => {
updateRef.current(data);
}, []);
// React 16.13 后 update 函数用 useEffect 包裹
useEffect(() => {
if (initialLoad.current) {
updateRef.current(data);
} else {
initialLoad.current = true;
}
});
return null;
}
const dispatcher = new Dispatcher();
export function Provider(props: {
models: Record<string, any>;
children: React.ReactNode;
}) {
return (
<Context.Provider value={{ dispatcher }}>
{Object.keys(props.models).map((namespace) => {
return (
<Executor
key={namespace}
hook={props.models[namespace]}
namespace={namespace}
onUpdate={(val) => {
dispatcher.data[namespace] = val;
dispatcher.update(namespace);
}}
/>
);
})}
{props.children}
</Context.Provider>
);
}
type GetModelByNamespace<M, N> = {
[K in keyof M]: M[K] extends { namespace: string; model: unknown }
? M[K]['namespace'] extends N
? M[K]['model'] extends (...args: any) => any
? ReturnType<M[K]['model']>
: never
: never
: never;
}[keyof M];
type Model<N> = GetModelByNamespace<Models, N>;
type Selector<N, S> = (model: Model<N>) => S;
type SelectedModel<N, T> = T extends (...args: any) => any
? ReturnType<NonNullable<T>>
: Model<N>;
export function useModel<N extends Namespaces>(namespace: N): Model<N>;
export function useModel<N extends Namespaces, S>(
namespace: N,
selector: Selector<N, S>,
): SelectedModel<N, typeof selector>;
export function useModel<N extends Namespaces, S>(
namespace: N,
selector?: Selector<N, S>,
): SelectedModel<N, typeof selector> {
const { dispatcher } = useContext<{ dispatcher: Dispatcher }>(Context);
const selectorRef = useRef(selector);
selectorRef.current = selector;
const [state, setState] = useState(() =>
selectorRef.current
? selectorRef.current(dispatcher.data[namespace])
: dispatcher.data[namespace],
);
const stateRef = useRef<any>(state);
stateRef.current = state;
const isMount = useRef(false);
useEffect(() => {
isMount.current = true;
return () => {
isMount.current = false;
};
}, []);
useEffect(() => {
const handler = (data: any) => {
if (!isMount.current) {
// 如果 handler 执行过程中,组件被卸载了,则强制更新全局 data
// TODO: 需要加个 example 测试
setTimeout(() => {
dispatcher.data[namespace] = data;
dispatcher.update(namespace);
});
} else {
const currentState = selectorRef.current
? selectorRef.current(data)
: data;
const previousState = stateRef.current;
if (!isEqual(currentState, previousState)) {
// 避免 currentState 拿到的数据是老的,从而导致 isEqual 比对逻辑有问题
stateRef.current = currentState;
setState(currentState);
}
}
};
dispatcher.callbacks[namespace] ||= new Set() as any; // rawModels 是 umi 动态生成的文件,导致前面 callback[namespace] 的类型无法推导出来,所以用 as any 来忽略掉
dispatcher.callbacks[namespace].add(handler);
dispatcher.update(namespace);
return () => {
dispatcher.callbacks[namespace].delete(handler);
};
}, [namespace]);
return state;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import model_1 from '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/.umi-production/plugin-initialState/@@initialState';
export const models = {
model_1: { namespace: '@@initialState', model: model_1 },
} as const
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Provider } from './';
import { models as rawModels } from './model';
function ProviderWrapper(props: any) {
const models = React.useMemo(() => {
return Object.keys(rawModels).reduce((memo, key) => {
memo[rawModels[key].namespace] = rawModels[key].model;
return memo;
}, {});
}, []);
return <Provider models={models} {...props}>{ props.children }</Provider>
}
export function dataflowProvider(container, opts) {
return <ProviderWrapper {...opts}>{ container }</ProviderWrapper>;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React, { useEffect, useState } from 'react';
import { ApplyPluginsType } from 'umi';
import { renderClient, RenderClientOpts } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/@umijs/renderer-react';
import { createHistory } from './core/history';
import { createPluginManager } from './core/plugin';
import { getRoutes } from './core/route';
import type { Location } from 'history';
import '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/global.less';
import 'antd/dist/reset.css';
const publicPath = '/';
const runtimePublicPath = false;
type TestBrowserProps = {
location?: Partial<Location>;
historyRef?: React.MutableRefObject<Location>;
};
export function TestBrowser(props: TestBrowserProps) {
const pluginManager = createPluginManager();
const [context, setContext] = useState<RenderClientOpts | undefined>(
undefined
);
useEffect(() => {
const genContext = async () => {
const { routes, routeComponents } = await getRoutes(pluginManager);
// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});
const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});
const basename = contextOpts.basename || '/';
const history = createHistory({
type: 'memory',
basename,
});
const context = {
routes,
routeComponents,
pluginManager,
rootElement: contextOpts.rootElement || document.getElementById('root'),
publicPath,
runtimePublicPath,
history,
basename,
components: true,
};
const modifiedContext = pluginManager.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: context,
});
return modifiedContext;
};
genContext().then((context) => {
setContext(context);
if (props.location) {
context?.history?.push(props.location);
}
if (props.historyRef) {
props.historyRef.current = context?.history;
}
});
}, []);
if (context === undefined) {
return <div id="loading" />;
}
const Children = renderClient(context);
return (
<React.Fragment>
<Children />
</React.Fragment>
);
}
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"moduleResolution": "bundler",
"importHelpers": true,
"noEmit": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"sourceMap": true,
"baseUrl": "../../",
"strict": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"paths": {
"@/*": [
"src/*"
],
"@@/*": [
"src/.umi/*"
],
"umi": [
"/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/umi"
],
"umi/typings": [
"src/.umi/typings"
]
}
},
"include": [
"../../.umirc.ts",
"../../**/*.d.ts",
"../../**/*.ts",
"../../**/*.tsx"
]
}
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
type CSSModuleClasses = { readonly [key: string]: string }
declare module '*.css' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.scss' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.sass' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.less' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.styl' {
const classes: CSSModuleClasses
export default classes
}
declare module '*.stylus' {
const classes: CSSModuleClasses
export default classes
}
// images
declare module '*.jpg' {
const src: string
export default src
}
declare module '*.jpeg' {
const src: string
export default src
}
declare module '*.png' {
const src: string
export default src
}
declare module '*.gif' {
const src: string
export default src
}
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<React.SVGProps<
SVGSVGElement
> & { title?: string }>;
const src: string
export default src
}
declare module '*.ico' {
const src: string
export default src
}
declare module '*.webp' {
const src: string
export default src
}
declare module '*.avif' {
const src: string
export default src
}
// media
declare module '*.mp4' {
const src: string
export default src
}
declare module '*.webm' {
const src: string
export default src
}
declare module '*.ogg' {
const src: string
export default src
}
declare module '*.mp3' {
const src: string
export default src
}
declare module '*.wav' {
const src: string
export default src
}
declare module '*.flac' {
const src: string
export default src
}
declare module '*.aac' {
const src: string
export default src
}
// fonts
declare module '*.woff' {
const src: string
export default src
}
declare module '*.woff2' {
const src: string
export default src
}
declare module '*.eot' {
const src: string
export default src
}
declare module '*.ttf' {
const src: string
export default src
}
declare module '*.otf' {
const src: string
export default src
}
// other
declare module '*.wasm' {
const initWasm: (options: WebAssembly.Imports) => Promise<WebAssembly.Exports>
export default initWasm
}
declare module '*.webmanifest' {
const src: string
export default src
}
declare module '*.pdf' {
const src: string
export default src
}
declare module '*.txt' {
const src: string
export default src
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import './core/polyfill';
import '/Users/wuhao/Desktop/demos/electron-egg/frontend/src/global.less';
import 'antd/dist/reset.css';
import { renderClient } from '/Users/wuhao/Desktop/demos/electron-egg/frontend/node_modules/@umijs/renderer-react';
import { getRoutes } from './core/route';
import { createPluginManager } from './core/plugin';
import { createHistory } from './core/history';
import { ApplyPluginsType } from 'umi';
const publicPath = "./";
const runtimePublicPath = false;
async function render() {
const pluginManager = createPluginManager();
const { routes, routeComponents } = await getRoutes(pluginManager);
// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});
const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});
const basename = contextOpts.basename || '/';
const historyType = contextOpts.historyType || 'hash';
const history = createHistory({
type: historyType,
basename,
...contextOpts.historyOpts,
});
return (pluginManager.applyPlugins({
key: 'render',
type: ApplyPluginsType.compose,
initialValue() {
const context = {
routes,
routeComponents,
pluginManager,
rootElement: contextOpts.rootElement || document.getElementById('root'),
publicPath,
runtimePublicPath,
history,
historyType,
basename,
callback: contextOpts.callback,
};
const modifiedContext = pluginManager.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: context,
});
return renderClient(modifiedContext);
},
}))();
}
render();
window.g_umi = {
version: '4.0.70',
};
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Outlet, useOutletContext } from 'umi';
export default function EmptyRoute() {
const context = useOutletContext();
return <Outlet context={context} />;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import type { IRuntimeConfig as Plugin0 } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-antd/runtimeConfig.d'
import type { IRuntimeConfig as Plugin1 } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-initialState/runtimeConfig.d'
interface IDefaultRuntimeConfig {
onRouteChange?: (props: { routes: any, clientRoutes: any, location: any, action: any, isFirst: boolean }) => void;
patchRoutes?: (props: { routes: any }) => void;
patchClientRoutes?: (props: { routes: any }) => void;
render?: (oldRender: () => void) => void;
rootContainer?: (lastRootContainer: JSX.Element, args?: any) => void;
[key: string]: any;
}
export type RuntimeConfig = IDefaultRuntimeConfig & Plugin0 & Plugin1
export function defineApp(config: RuntimeConfig): RuntimeConfig {
return config;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { HelmetProvider } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/node_modules/@umijs/renderer-react';
import { context } from './helmetContext';
export const innerProvider = (container) => {
return React.createElement(HelmetProvider, { context }, container);
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export const context = {};
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { createHashHistory, createMemoryHistory, createBrowserHistory } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/node_modules/@umijs/renderer-react';
import type { UmiHistory } from './historyIntelli';
let history: UmiHistory;
let basename: string = '/';
export function createHistory(opts: any) {
let h;
if (opts.type === 'hash') {
h = createHashHistory();
} else if (opts.type === 'memory') {
h = createMemoryHistory(opts);
} else {
h = createBrowserHistory();
}
if (opts.basename) {
basename = opts.basename;
}
history = {
...h,
push(to, state) {
h.push(patchTo(to, h), state);
},
replace(to, state) {
h.replace(patchTo(to, h), state);
},
get location() {
return h.location;
},
get action() {
return h.action;
}
}
return h;
}
// Patch `to` to support basename
// Refs:
// https://github.com/remix-run/history/blob/3e9dab4/packages/history/index.ts#L484
// https://github.com/remix-run/history/blob/dev/docs/api-reference.md#to
function patchTo(to: any, h: History) {
if (typeof to === 'string') {
return `${stripLastSlash(basename)}${to}`;
} else if (typeof to === 'object') {
const currentPathname = h.location.pathname;
return {
...to,
pathname: to.pathname? `${stripLastSlash(basename)}${to.pathname}` : currentPathname,
};
} else {
throw new Error(`Unexpected to: ${to}`);
}
}
function stripLastSlash(path) {
return path.slice(-1) === '/' ? path.slice(0, -1) : path;
}
export { history };
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { getRoutes } from './route'
import type { History } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/node_modules/@umijs/renderer-react'
type Routes = Awaited<ReturnType<typeof getRoutes>>['routes']
type AllRoute = Routes[keyof Routes]
type IsRoot<T extends any> = 'parentId' extends keyof T ? false : true
// show `/` in not `layout / wrapper` only
type GetAllRouteWithoutLayout<Item extends AllRoute> = Item extends any
? 'isWrapper' extends keyof Item
? never
: 'isLayout' extends keyof Item
? never
: Item
: never
type AllRouteWithoutLayout = GetAllRouteWithoutLayout<AllRoute>
type IndexRoutePathname = '/' extends AllRouteWithoutLayout['path']
? '/'
: never
type GetChildrens<T extends any> = T extends any
? IsRoot<T> extends true
? never
: T
: never
type Childrens = GetChildrens<AllRoute>
type Root = Exclude<AllRoute, Childrens>
type AllIds = AllRoute['id']
type GetChildrensByParentId<
Id extends AllIds,
Item = AllRoute
> = Item extends any
? 'parentId' extends keyof Item
? Item['parentId'] extends Id
? Item
: never
: never
: never
type RouteObject<
Id extends AllIds,
Item = GetChildrensByParentId<Id>
> = IsNever<Item> extends true
? ''
: Item extends AllRoute
? {
[Key in Item['path'] as TrimSlash<Key>]: UnionMerge<
RouteObject<Item['id']>
>
}
: never
type GetRootRouteObject<Item extends Root> = Item extends Root
? {
[K in Item['path'] as TrimSlash<K>]: UnionMerge<RouteObject<Item['id']>>
}
: never
type MergedResult = UnionMerge<GetRootRouteObject<Root>>
// --- patch history types ---
type HistoryTo = Parameters<History['push']>['0']
type HistoryPath = Exclude<HistoryTo, string>
type UmiPathname = Path<MergedResult> | (string & {})
interface UmiPath extends HistoryPath {
pathname: UmiPathname
}
type UmiTo = UmiPathname | UmiPath
type UmiPush = (to: UmiTo, state?: any) => void
type UmiReplace = (to: UmiTo, state?: any) => void
export interface UmiHistory extends History {
push: UmiPush
replace: UmiReplace
}
// --- type utils ---
type TrimLeftSlash<T extends string> = T extends `/${infer R}`
? TrimLeftSlash<R>
: T
type TrimRightSlash<T extends string> = T extends `${infer R}/`
? TrimRightSlash<R>
: T
type TrimSlash<T extends string> = TrimLeftSlash<TrimRightSlash<T>>
type IsNever<T> = [T] extends [never] ? true : false
type IsEqual<A, B> = (<G>() => G extends A ? 1 : 2) extends <G>() => G extends B
? 1
: 2
? true
: false
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
k: infer I
) => void
? I
: never
type UnionMerge<U> = UnionToIntersection<U> extends infer O
? { [K in keyof O]: O[K] }
: never
type ExcludeEmptyKey<T> = IsEqual<T, ''> extends true ? never : T
type PathConcat<
TKey extends string,
TValue,
N = TrimSlash<TKey>
> = TValue extends string
? ExcludeEmptyKey<N>
:
| ExcludeEmptyKey<N>
| `${N & string}${IsNever<ExcludeEmptyKey<N>> extends true
? ''
: '/'}${UnionPath<TValue>}`
type UnionPath<T> = {
[K in keyof T]-?: PathConcat<K & string, T[K]>
}[keyof T]
type MakeSureLeftSlash<T> = T extends any
? `/${TrimRightSlash<T & string>}`
: never
// exclude `/*`, because it always at the top of the IDE tip list
type Path<T, K = UnionPath<T>> = Exclude<MakeSureLeftSlash<K>, '/*'> | IndexRoutePathname
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import * as Plugin_0 from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/app.jsx';
import * as Plugin_1 from '@@/core/helmet.ts';
import * as Plugin_2 from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-initialState/runtime.tsx';
import * as Plugin_3 from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-model/runtime.tsx';
import { PluginManager } from 'umi';
function __defaultExport (obj) {
if (obj.default) {
return typeof obj.default === 'function' ? obj.default() : obj.default
}
return obj;
}
export function getPlugins() {
return [
{
apply: __defaultExport(Plugin_0),
path: process.env.NODE_ENV === 'production' ? void 0 : '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/app.jsx',
},
{
apply: Plugin_1,
path: process.env.NODE_ENV === 'production' ? void 0 : '@@/core/helmet.ts',
},
{
apply: Plugin_2,
path: process.env.NODE_ENV === 'production' ? void 0 : '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-initialState/runtime.tsx',
},
{
apply: Plugin_3,
path: process.env.NODE_ENV === 'production' ? void 0 : '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-model/runtime.tsx',
},
];
}
export function getValidKeys() {
return ['patchRoutes','patchClientRoutes','modifyContextOpts','modifyClientRenderOpts','rootContainer','innerProvider','i18nProvider','accessProvider','dataflowProvider','outerProvider','render','onRouteChange','antd','getInitialState',];
}
let pluginManager = null;
export function createPluginManager() {
pluginManager = PluginManager.create({
plugins: getPlugins(),
validKeys: getValidKeys(),
});
return pluginManager;
}
export function getPluginManager() {
return pluginManager;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { IConfigFromPluginsJoi } from "./pluginConfigJoi.d";
interface IConfigTypes {
codeSplitting: {
jsStrategy: "bigVendors" | "depPerChunk" | "granularChunks";
jsStrategyOptions?: ({
} | undefined);
cssStrategy?: ("mergeAll" | undefined);
cssStrategyOptions?: ({
} | undefined);
};
title: string;
styles: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
scripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
routes: Array<{
component?: (string | undefined);
layout?: (false | undefined);
path?: (string | undefined);
redirect?: (string | undefined);
routes?: IConfigTypes['routes'];
wrappers?: (Array<string> | undefined);
} | { [x: string]: any }>;
reactRouter5Compat: boolean | {
};
presets: Array<string>;
plugins: Array<string>;
npmClient: "pnpm" | "tnpm" | "cnpm" | "yarn" | "npm";
mountElementId: string;
metas: Array<{
charset?: (string | undefined);
content?: (string | undefined);
"http-equiv"?: (string | undefined);
name?: (string | undefined);
} | { [x: string]: any }>;
links: Array<{
crossorigin?: (string | undefined);
href?: (string | undefined);
hreflang?: (string | undefined);
media?: (string | undefined);
referrerpolicy?: (string | undefined);
rel?: (string | undefined);
sizes?: (any | undefined);
title?: (any | undefined);
type?: (any | undefined);
} | { [x: string]: any }>;
historyWithQuery: {
};
history: {
type: "browser" | "hash" | "memory";
};
headScripts: Array<string | {
src?: (string | undefined);
} | {
content?: (string | undefined);
} | { [x: string]: any }>;
esbuildMinifyIIFE: boolean;
conventionRoutes: {
base?: (string | undefined);
exclude?: (Array<any> | undefined);
};
conventionLayout: boolean;
base: string;
analyze: {
};
writeToDisk: boolean;
theme: { [x: string]: any };
targets: { [x: string]: any };
svgr: { [x: string]: any };
svgo: { [x: string]: any } | boolean;
styleLoader: { [x: string]: any };
srcTranspilerOptions: {
esbuild?: ({ [x: string]: any } | undefined);
swc?: ({ [x: string]: any } | undefined);
};
srcTranspiler: "babel" | "esbuild" | "swc" | "none";
sassLoader: { [x: string]: any };
runtimePublicPath: {
};
purgeCSS: { [x: string]: any };
publicPath: string;
proxy: { [x: string]: any } | Array<any>;
postcssLoader: { [x: string]: any };
outputPath: string;
normalCSSLoaderModules: { [x: string]: any };
mfsu: {
cacheDirectory?: (string | undefined);
chainWebpack?: (((...args: any[]) => unknown) | undefined);
esbuild?: (boolean | undefined);
exclude?: (Array<string | any> | undefined);
include?: (Array<string> | undefined);
mfName?: (string | undefined);
remoteAliases?: (Array<string> | undefined);
remoteName?: (string | undefined);
runtimePublicPath?: (boolean | undefined);
shared?: ({ [x: string]: any } | undefined);
strategy?: ("eager" | "normal" | undefined);
} | boolean;
mdx: {
loader?: (string | undefined);
loaderOptions?: ({ [x: string]: any } | undefined);
};
manifest: {
basePath?: (string | undefined);
fileName?: (string | undefined);
};
lessLoader: { [x: string]: any };
jsMinifierOptions: { [x: string]: any };
jsMinifier: "esbuild" | "swc" | "terser" | "uglifyJs" | "none";
inlineLimit: number;
ignoreMomentLocale: boolean;
https: {
cert?: (string | undefined);
hosts?: (Array<string> | undefined);
http2?: (boolean | undefined);
key?: (string | undefined);
};
hash: boolean;
forkTSChecker: { [x: string]: any };
fastRefresh: boolean;
extraPostCSSPlugins: Array<any>;
extraBabelPresets: Array<string | Array<any>>;
extraBabelPlugins: Array<string | Array<any>>;
extraBabelIncludes: Array<string | any>;
externals: { [x: string]: any } | string | ((...args: any[]) => unknown);
esm: {
};
devtool: "cheap-source-map" | "cheap-module-source-map" | "eval" | "eval-source-map" | "eval-cheap-source-map" | "eval-cheap-module-source-map" | "eval-nosources-cheap-source-map" | "eval-nosources-cheap-module-source-map" | "eval-nosources-source-map" | "source-map" | "hidden-source-map" | "hidden-nosources-cheap-source-map" | "hidden-nosources-cheap-module-source-map" | "hidden-nosources-source-map" | "hidden-cheap-source-map" | "hidden-cheap-module-source-map" | "inline-source-map" | "inline-cheap-source-map" | "inline-cheap-module-source-map" | "inline-nosources-cheap-source-map" | "inline-nosources-cheap-module-source-map" | "inline-nosources-source-map" | "nosources-source-map" | "nosources-cheap-source-map" | "nosources-cheap-module-source-map" | boolean;
depTranspiler: "babel" | "esbuild" | "swc" | "none";
define: { [x: string]: any };
deadCode: {
context?: (string | undefined);
detectUnusedExport?: (boolean | undefined);
detectUnusedFiles?: (boolean | undefined);
exclude?: (Array<string> | undefined);
failOnHint?: (boolean | undefined);
patterns?: (Array<string> | undefined);
};
cssMinifierOptions: { [x: string]: any };
cssMinifier: "cssnano" | "esbuild" | "parcelCSS" | "none";
cssLoaderModules: { [x: string]: any };
cssLoader: { [x: string]: any };
copy: Array<{
from: string;
to: string;
} | string>;
checkDepCssModules?: boolean;
cacheDirectoryPath: string;
babelLoaderCustomize: string;
autoprefixer: { [x: string]: any };
autoCSSModules: boolean;
alias: { [x: string]: any };
crossorigin: boolean | {
includes?: (Array<any> | undefined);
};
esmi: {
cdnOrigin: string;
shimUrl?: (string | undefined);
};
exportStatic: {
extraRoutePaths?: (((...args: any[]) => unknown) | Array<string> | undefined);
};
favicons: Array<string>;
helmet: boolean;
icons: {
autoInstall?: ({
} | undefined);
defaultComponentConfig?: ({
} | undefined);
alias?: ({
} | undefined);
include?: (Array<string> | undefined);
};
mock: {
exclude?: (Array<string> | undefined);
include?: (Array<string> | undefined);
};
mpa: {
template?: (string | undefined);
layout?: (string | undefined);
getConfigFromEntryFile?: (boolean | undefined);
entry?: ({
} | undefined);
};
phantomDependency: {
exclude?: (Array<string> | undefined);
};
polyfill: {
imports?: (Array<string> | undefined);
};
routePrefetch: {
};
terminal: {
};
tmpFiles: boolean;
clientLoader: {
};
routeProps: {
};
ssr: {
serverBuildPath?: (string | undefined);
platform?: (string | undefined);
builder?: ("esbuild" | "webpack" | undefined);
};
lowImport: {
libs?: (Array<any> | undefined);
css?: (string | undefined);
};
vite: {
};
apiRoute: {
platform?: (string | undefined);
};
monorepoRedirect: boolean | {
srcDir?: (Array<string> | undefined);
exclude?: (Array<any> | undefined);
peerDeps?: (boolean | undefined);
};
test: {
};
clickToComponent: {
/** 默认情况下,点击将默认编辑器为vscode, 你可以设置编辑器 vscode 或者 vscode-insiders */
editor?: (string | undefined);
};
legacy: {
buildOnly?: (boolean | undefined);
nodeModulesTransform?: (boolean | undefined);
checkOutput?: (boolean | undefined);
};
/** 设置 babel class-properties 启用 loose
@doc https://umijs.org/docs/api/config#classpropertiesloose */
classPropertiesLoose: boolean | {
};
ui: {
};
hmrGuardian: boolean;
verifyCommit: {
scope?: (Array<string> | undefined);
allowEmoji?: (boolean | undefined);
};
run: {
globals?: (Array<string> | undefined);
};
antd: {
configProvider?: ({ [x: string]: any } | undefined);
dark?: (boolean | undefined);
compact?: (boolean | undefined);
import?: (boolean | undefined);
style?: ("less" | "css" | undefined);
theme?: ({ [x: string]: any } | undefined);
appConfig?: ({ [x: string]: any } | undefined);
momentPicker?: (boolean | undefined);
styleProvider?: ({ [x: string]: any } | undefined);
};
locale: {
default?: (string | undefined);
useLocalStorage?: (boolean | undefined);
baseNavigator?: (boolean | undefined);
title?: (boolean | undefined);
antd?: (boolean | undefined);
baseSeparator?: (string | undefined);
};
layout: { [x: string]: any };
initialState: {
loading?: (string | undefined);
};
model: {
extraModels?: (Array<string> | undefined);
};
access: { [x: string]: any };
};
type PrettifyWithCloseable<T> = {
[K in keyof T]: T[K] | false;
} & {};
export type IConfigFromPlugins = PrettifyWithCloseable<
IConfigFromPluginsJoi & Partial<IConfigTypes>
>;
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// Created by Umi Plugin
export interface IConfigFromPluginsJoi {
}
This diff is collapsed.
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
export async function getRoutes() {
const routes = {"1":{"path":"/user","parentId":"@@/global-layout","id":"1"},"2":{"path":"/user","redirect":"/user/login","parentId":"1","id":"2"},"3":{"name":"登录","path":"/user/login","parentId":"1","id":"3"},"4":{"path":"/","name":"欢迎使用","parentId":"@@/global-layout","id":"4"},"5":{"path":"/","redirect":"/port","parentId":"4","id":"5"},"6":{"name":"报单","path":"/port","parentId":"4","id":"6"},"7":{"name":"退货单","path":"/report","parentId":"4","id":"7"},"8":{"name":"个人中心","path":"/mycenter","parentId":"4","id":"8"},"@@/global-layout":{"id":"@@/global-layout","path":"/","isLayout":true}} as const;
return {
routes,
routeComponents: {
'1': React.lazy(() => import( './EmptyRoute')),
'2': React.lazy(() => import( './EmptyRoute')),
'3': React.lazy(() => import(/* webpackChunkName: "p__user__login" */'@/pages/user/login.jsx')),
'4': React.lazy(() => import(/* webpackChunkName: "layouts__layout" */'@/layouts/layout.jsx')),
'5': React.lazy(() => import( './EmptyRoute')),
'6': React.lazy(() => import(/* webpackChunkName: "p__port__index" */'@/pages/port/index.jsx')),
'7': React.lazy(() => import(/* webpackChunkName: "p__report__index" */'@/pages/report/index.jsx')),
'8': React.lazy(() => import(/* webpackChunkName: "p__mycenter__index" */'@/pages/mycenter/index.jsx')),
'@@/global-layout': React.lazy(() => import(/* webpackChunkName: "layouts__index" */'/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/layouts/index.jsx')),
},
};
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
let count = 0;
let groupLevel = 0;
function send(type: string, message?: string) {
if(process.env.NODE_ENV==='production'){
return;
}else{
const encodedMessage = message ? `&m=${encodeURI(message)}` : '';
fetch(`/__umi/api/terminal?type=${type}&t=${Date.now()}&c=${count++}&g=${groupLevel}${encodedMessage}`, { mode: 'no-cors' })
}
}
function prettyPrint(obj: any) {
return JSON.stringify(obj, null, 2);
}
function stringifyObjs(objs: any[]) {
const obj = objs.length > 1 ? objs.map(stringify).join(' ') : objs[0];
return typeof obj === 'object' ? `${prettyPrint(obj)}` : obj.toString();
}
function stringify(obj: any) {
return typeof obj === 'object' ? `${JSON.stringify(obj)}` : obj.toString();
}
const terminal = {
log(...objs: any[]) { send('log', stringifyObjs(objs)) },
info(...objs: any[]) { send('info', stringifyObjs(objs)) },
warn(...objs: any[]) { send('warn', stringifyObjs(objs)) },
error(...objs: any[]) { send('error', stringifyObjs(objs)) },
group() { groupLevel++ },
groupCollapsed() { groupLevel++ },
groupEnd() { groupLevel && --groupLevel },
clear() { send('clear') },
trace(...args: any[]) { console.trace(...args) },
profile(...args: any[]) { console.profile(...args) },
profileEnd(...args: any[]) { console.profileEnd(...args) },
};
export { terminal };
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export { defineApp } from './core/defineApp'
export type { RuntimeConfig } from './core/defineApp'
// @umijs/renderer-*
export { createBrowserHistory, createHashHistory, createMemoryHistory, Helmet, HelmetProvider, createSearchParams, generatePath, matchPath, matchRoutes, Navigate, NavLink, Outlet, resolvePath, useLocation, useMatch, useNavigate, useOutlet, useOutletContext, useParams, useResolvedPath, useRoutes, useSearchParams, useAppData, useClientLoaderData, useRouteProps, useSelectedRoutes, useServerLoaderData, renderClient, __getRoot, Link, useRouteData, __useFetcher, withRouter } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/node_modules/@umijs/renderer-react';
export type { History } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/node_modules/@umijs/renderer-react'
// umi/client/client/plugin
export { ApplyPluginsType, PluginManager } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/node_modules/umi/client/client/plugin.js';
export { history, createHistory } from './core/history';
export { terminal } from './core/terminal';
export { TestBrowser } from './testBrowser';
// plugins
export { Provider, useModel } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-model';
// plugins types.d.ts
export * from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-antd/types.d';
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import {
Modal,
message,
notification,
} from 'antd';
import { ApplyPluginsType } from 'umi';
import { getPluginManager } from '../core/plugin';
let cacheAntdConfig = null;
const getAntdConfig = () => {
if(!cacheAntdConfig){
cacheAntdConfig = getPluginManager().applyPlugins({
key: 'antd',
type: ApplyPluginsType.modify,
initialValue: {
},
});
}
return cacheAntdConfig;
}
export function rootContainer(rawContainer) {
const {
appConfig,
...finalConfigProvider
} = getAntdConfig();
let container = rawContainer;
return container;
}
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import type { RuntimeAntdConfig } from './types.d';
export type IRuntimeConfig = {
antd?: RuntimeAntdConfig
};
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
type Prettify<T> = {
[K in keyof T]: T[K];
} & {};
type AntdConfig = Prettify<{}
>;
export type RuntimeAntdConfig = (memo: AntdConfig) => AntdConfig;
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { useState, useEffect, useCallback } from 'react';
import { getInitialState } from '@/app';
export type InitialStateType = Awaited<ReturnType<typeof getInitialState>> | undefined;
const initState = {
initialState: undefined as InitialStateType,
loading: true,
error: undefined,
};
export default () => {
const [state, setState] = useState(initState);
const refresh = useCallback(async () => {
setState((s) => ({ ...s, loading: true, error: undefined }));
try {
const ret = await getInitialState();
setState((s) => ({ ...s, initialState: ret, loading: false }));
} catch (e) {
setState((s) => ({ ...s, error: e, loading: false }));
}
}, []);
const setInitialState = useCallback(
async (
initialState: InitialStateType | ((initialState: InitialStateType) => InitialStateType),
) => {
setState((s) => {
if (typeof initialState === 'function') {
return { ...s, initialState: initialState(s.initialState), loading: false };
}
return { ...s, initialState, loading: false };
});
},
[],
);
useEffect(() => {
refresh();
}, []);
return {
...state,
refresh,
setInitialState,
};
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { useModel } from '@@/plugin-model';
function Loading() { return <div />; }
export default function InitialStateProvider(props: any) {
const appLoaded = React.useRef(false);
const { loading = false } = useModel("@@initialState") || {};
React.useEffect(() => {
if (!loading) {
appLoaded.current = true;
}
}, [loading]);
if (loading && !appLoaded.current) {
return <Loading />;
}
return props.children;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import Provider from './Provider';
export function dataflowProvider(container) {
return <Provider>{ container }</Provider>;
}
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
export interface IRuntimeConfig {
getInitialState?: () => Promise<Record<string, any>>
}
This diff is collapsed.
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import model_1 from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/.umi/plugin-initialState/@@initialState';
export const models = {
model_1: { namespace: '@@initialState', model: model_1 },
} as const
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Provider } from './';
import { models as rawModels } from './model';
function ProviderWrapper(props: any) {
const models = React.useMemo(() => {
return Object.keys(rawModels).reduce((memo, key) => {
memo[rawModels[key].namespace] = rawModels[key].model;
return memo;
}, {});
}, []);
return <Provider models={models} {...props}>{ props.children }</Provider>
}
export function dataflowProvider(container, opts) {
return <ProviderWrapper {...opts}>{ container }</ProviderWrapper>;
}
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React, { useEffect, useState } from 'react';
import { ApplyPluginsType } from 'umi';
import { renderClient, RenderClientOpts } from '/Users/wuhao/Desktop/demos/standaloneframe/frontend/node_modules/@umijs/renderer-react';
import { createHistory } from './core/history';
import { createPluginManager } from './core/plugin';
import { getRoutes } from './core/route';
import type { Location } from 'history';
import '/Users/wuhao/Desktop/demos/standaloneframe/frontend/src/global.less';
import 'antd/dist/reset.css';
const publicPath = '/';
const runtimePublicPath = false;
type TestBrowserProps = {
location?: Partial<Location>;
historyRef?: React.MutableRefObject<Location>;
};
export function TestBrowser(props: TestBrowserProps) {
const pluginManager = createPluginManager();
const [context, setContext] = useState<RenderClientOpts | undefined>(
undefined
);
useEffect(() => {
const genContext = async () => {
const { routes, routeComponents } = await getRoutes(pluginManager);
// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});
const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});
const basename = contextOpts.basename || '/';
const history = createHistory({
type: 'memory',
basename,
});
const context = {
routes,
routeComponents,
pluginManager,
rootElement: contextOpts.rootElement || document.getElementById('root'),
publicPath,
runtimePublicPath,
history,
basename,
components: true,
};
const modifiedContext = pluginManager.applyPlugins({
key: 'modifyClientRenderOpts',
type: ApplyPluginsType.modify,
initialValue: context,
});
return modifiedContext;
};
genContext().then((context) => {
setContext(context);
if (props.location) {
context?.history?.push(props.location);
}
if (props.historyRef) {
props.historyRef.current = context?.history;
}
});
}, []);
if (context === undefined) {
return <div id="loading" />;
}
const Children = renderClient(context);
return (
<React.Fragment>
<Children />
</React.Fragment>
);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment