mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-08-03 10:27:59 +08:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
ddf891e3bc | |||
7ae473d492 | |||
c20a6c369d | |||
57b71e1354 | |||
127f6e9f6c | |||
d1951dbcb5 | |||
5edcf63e24 | |||
b01b8b24ba | |||
d9c7085472 | |||
a01acddb9c | |||
e5208cd751 | |||
dc326c324c | |||
e0d15f8039 | |||
169ab08b88 | |||
3b8336105a | |||
7214a22ea5 | |||
3152a8d3e8 | |||
40e8eff5f3 | |||
47e67dd503 | |||
903ea1820a | |||
c08ea62064 | |||
4860299959 | |||
72f9d1a3ec | |||
98718a010c |
34
CHANGELOG.md
34
CHANGELOG.md
@ -2,33 +2,29 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
### [1.1.1](https://github.com/nsnail/NetAdmin/compare/v1.0.0...v1.1.1) (2024-04-29)
|
## [1.2.0](https://github.com/nsnail/NetAdmin/compare/v1.1.1...v1.2.0) (2024-06-06)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* ✨ 版本更新日志组件 ([#96](https://github.com/nsnail/NetAdmin/issues/96)) ([a37acc4](https://github.com/nsnail/NetAdmin/commit/a37acc4b55c91d57d51c7fa079da8700530412a5))
|
* ✨ 计划作业-上次执行耗时 ([#133](https://github.com/nsnail/NetAdmin/issues/133)) ([57b71e1](https://github.com/nsnail/NetAdmin/commit/57b71e1354ab8b0be995b5f563dd8c3fb7965d5f))
|
||||||
* ✨ 计划作业 ([#87](https://github.com/nsnail/NetAdmin/issues/87)) ([8293ec0](https://github.com/nsnail/NetAdmin/commit/8293ec0297875ebc9ad75cce9465bd587929c0bf))
|
* ✨ 框架代码同步 ([#129](https://github.com/nsnail/NetAdmin/issues/129)) ([b01b8b2](https://github.com/nsnail/NetAdmin/commit/b01b8b24ba574c08ba5605e103ff2ccf15e5830a))
|
||||||
* ✨ 计划作业执行记录 ([#89](https://github.com/nsnail/NetAdmin/issues/89)) ([6f89015](https://github.com/nsnail/NetAdmin/commit/6f890151989ad733e35653933b7597eec478cc3b))
|
* ✨ 框架代码同步 ([#130](https://github.com/nsnail/NetAdmin/issues/130)) ([5edcf63](https://github.com/nsnail/NetAdmin/commit/5edcf63e24f6b13f5515e01ee8cf120b1a814d40))
|
||||||
* ✨ 将数据库结构同步和种子数据初始化作为命令行开关 ([#78](https://github.com/nsnail/NetAdmin/issues/78)) ([05ed3d3](https://github.com/nsnail/NetAdmin/commit/05ed3d3746aa274a0f88f7afadfea12a3c8a80ff))
|
* ✨ 默认头像根据用户名绘制svg ([#132](https://github.com/nsnail/NetAdmin/issues/132)) ([127f6e9](https://github.com/nsnail/NetAdmin/commit/127f6e9f6c8c12974e5340e9697281250737bed3))
|
||||||
* ✨ 快捷启用/禁用用户 ([#91](https://github.com/nsnail/NetAdmin/issues/91)) ([6c2d167](https://github.com/nsnail/NetAdmin/commit/6c2d1676e45b9f1ecf3be3ae5a172db49b62a81d))
|
* ✨ 手动执行计划作业 ([#122](https://github.com/nsnail/NetAdmin/issues/122)) ([3b83361](https://github.com/nsnail/NetAdmin/commit/3b8336105a908ba6bc300bec6ac4f49747ea66e9))
|
||||||
* ✨ 前端表格高级筛选 ([#100](https://github.com/nsnail/NetAdmin/issues/100)) ([3847d6f](https://github.com/nsnail/NetAdmin/commit/3847d6fdbbd27efb53921bcc8374157f0da47155))
|
* ✨ 增强作业执行记录页面 ([#135](https://github.com/nsnail/NetAdmin/issues/135)) ([7ae473d](https://github.com/nsnail/NetAdmin/commit/7ae473d492b9ba60cbb1c355894917d14f5ffa8f))
|
||||||
* ✨ 日志管理独立出来、增加登录日志界面 ([#65](https://github.com/nsnail/NetAdmin/issues/65)) ([9134c4f](https://github.com/nsnail/NetAdmin/commit/9134c4fe01165a87ebc7e2cbd0a2abff3c9fb3ea))
|
* ✨ naColId组件 ([#118](https://github.com/nsnail/NetAdmin/issues/118)) ([47e67dd](https://github.com/nsnail/NetAdmin/commit/47e67dd503dd0ba6818e8b798e41c62420363f58))
|
||||||
* ✨ 首页仪表面板 ([#103](https://github.com/nsnail/NetAdmin/issues/103)) ([149e1af](https://github.com/nsnail/NetAdmin/commit/149e1afa533b142a3666a325ec84a091d53c1840))
|
* **frontend:** ✨ 手机端分页控件显示总条数 ([#124](https://github.com/nsnail/NetAdmin/issues/124)) ([e0d15f8](https://github.com/nsnail/NetAdmin/commit/e0d15f8039a74a9826a0395983960ab620308899))
|
||||||
* ✨ cron表达式选择器 ([#92](https://github.com/nsnail/NetAdmin/issues/92)) ([bde9fb1](https://github.com/nsnail/NetAdmin/commit/bde9fb1ea264bd0b786ac68d590691892d7ce067))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* 🐛 'Numbers' does not contain a definition for 'CACHE_SECS_DEFAULT' ([#102](https://github.com/nsnail/NetAdmin/issues/102)) ([8f69c29](https://github.com/nsnail/NetAdmin/commit/8f69c2907be282b1b39f4a179badb11502aa2403))
|
* 🐛 字段顺序 ([#131](https://github.com/nsnail/NetAdmin/issues/131)) ([d1951db](https://github.com/nsnail/NetAdmin/commit/d1951dbcb5fa50a7ff308f6b6d554da5f791bcf2))
|
||||||
* 🐛 低版本jetbrains.resharper.globaltools搞乱了代码 ([#97](https://github.com/nsnail/NetAdmin/issues/97)) ([c117ddf](https://github.com/nsnail/NetAdmin/commit/c117ddfe7a433215b3449cdd6b19318a1f3cbf37))
|
* 🐛 字段长度 ([#134](https://github.com/nsnail/NetAdmin/issues/134)) ([c20a6c3](https://github.com/nsnail/NetAdmin/commit/c20a6c369d7b6d6dcfd07b3f3eaeab0fa309e766))
|
||||||
* 🐛 前端样式问题 ([#84](https://github.com/nsnail/NetAdmin/issues/84)) ([6615df3](https://github.com/nsnail/NetAdmin/commit/6615df339934f6d19880c9822b44d5305c2f2a75))
|
* 🐛 take count ([c08ea62](https://github.com/nsnail/NetAdmin/commit/c08ea62064cc522d7cca9c90a5f15f23d833b6e3))
|
||||||
* 🐛 请求日志客户端IP显示不正确 ([#60](https://github.com/nsnail/NetAdmin/issues/60)) ([ec698ce](https://github.com/nsnail/NetAdmin/commit/ec698ce4db49861eaaeb8bf5080764939e6d7231))
|
* **backend:** 🐛 更新计划作业在sqlite数据库环境报错 ([#120](https://github.com/nsnail/NetAdmin/issues/120)) ([3152a8d](https://github.com/nsnail/NetAdmin/commit/3152a8d3e8054524470883c336fb6e93903a8426))
|
||||||
* 🐛 时区问题 ([#107](https://github.com/nsnail/NetAdmin/issues/107)) ([59c85ce](https://github.com/nsnail/NetAdmin/commit/59c85cef217c121b36d52993b6b5a774fe22df9e))
|
|
||||||
* 🐛 小问题 ([#76](https://github.com/nsnail/NetAdmin/issues/76)) ([52ddf27](https://github.com/nsnail/NetAdmin/commit/52ddf273c856d8f7e363ce23e5886b9eedf4604f))
|
### [1.1.1](https://github.com/nsnail/NetAdmin/compare/v1.1.0...v1.1.1) (2024-04-29)
|
||||||
* 🐛 在弹窗界面中引用的列表组件,点击重置搜索条件按钮时,会关闭弹窗的bug ([#95](https://github.com/nsnail/NetAdmin/issues/95)) ([8fee14c](https://github.com/nsnail/NetAdmin/commit/8fee14cd6ebd86456956fc59bbb61c545faa1fdd))
|
|
||||||
* 🐛 tinymce editor css 加载路径错误 ([#93](https://github.com/nsnail/NetAdmin/issues/93)) ([5fe7387](https://github.com/nsnail/NetAdmin/commit/5fe73878a2a53dc5e7e2dcbcbf22f91ffb4376dd))
|
|
||||||
* 🐛 tinymce editor css 加载路径错误 ([#94](https://github.com/nsnail/NetAdmin/issues/94)) ([802251e](https://github.com/nsnail/NetAdmin/commit/802251e42347bfe4fa0bcb4867b615d7c03abf19))
|
|
||||||
|
|
||||||
## [1.1.0](https://github.com/nsnail/NetAdmin/compare/v1.0.0...v1.1.0) (2024-04-29)
|
## [1.1.0](https://github.com/nsnail/NetAdmin/compare/v1.0.0...v1.1.0) (2024-04-29)
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/aspnet:9.0.0-preview.3 AS base
|
FROM mcr.microsoft.com/dotnet/aspnet:9.0.0-preview.4 AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
RUN apt update
|
RUN apt update
|
||||||
|
79
README.md
79
README.md
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
通用后台权限管理系统、快速开发框架(基于C#12/.NET9、Vue3/Vite、Element Plus等现代技术构建,具有十分整洁、优雅的编码规范)
|
通用后台权限管理系统、快速开发框架(基于C#12/.NET9、Vue3/Vite、Element Plus等现代技术构建,具有十分整洁、优雅的编码规范)
|
||||||
|
|
||||||
[](https://github.com/nsnail/NetAdmin/actions/workflows/ci.yml)
|
[](https://github.com/nsnail/NetAdmin/actions/workflows/nightly-build.yml)
|
||||||
[](https://github.com/nsnail/NetAdmin/blob/main/LICENSE)
|
[](https://github.com/nsnail/NetAdmin/blob/main/LICENSE)
|
||||||
[](https://github.com/nsnail/NetAdmin/blob/main/LICENSE)
|
[](https://github.com/nsnail/NetAdmin/blob/main/LICENSE)
|
||||||
[](https://github.com/nsnail/NetAdmin/blob/main/LICENSE)
|
[](https://github.com/nsnail/NetAdmin/blob/main/LICENSE)
|
||||||
@ -19,64 +19,47 @@ docker run -p 8080:8080 nsnail/netadmin
|
|||||||
|
|
||||||
## 构建步骤
|
## 构建步骤
|
||||||
|
|
||||||
- 后端
|
```shell
|
||||||
1. 检查dotnet-sdk版本>=9.0.0
|
# 1. 克隆代码仓库
|
||||||
``` shell
|
# 下载 git https://git-scm.com/downloads
|
||||||
dotnet --list-sdks
|
git clone https://github.com/nsnail/NetAdmin.git && cd ./NetAdmin
|
||||||
|
|
||||||
# 下载 dotnet https://dotnet.microsoft.com/zh-cn/download/dotnet
|
# 2. 检查dotnet-sdk版本>=9.0.0
|
||||||
```
|
# 下载 dotnet https://dotnet.microsoft.com/zh-cn/download/dotnet
|
||||||
2. 克隆代码仓库
|
dotnet --list-sdks
|
||||||
``` shell
|
|
||||||
git clone https://github.com/nsnail/NetAdmin.git
|
|
||||||
cd ./NetAdmin
|
|
||||||
|
|
||||||
# 下载 git https://git-scm.com/downloads
|
# 3. 确保本机redis处于运行状态
|
||||||
```
|
# 下载 redis for windows https://github.com/redis-windows/redis-windows/releases
|
||||||
3. 确保本机redis处于运行状态
|
# 下载 redis for linux/mac https://redis.io/download
|
||||||
``` shell
|
redis-cli
|
||||||
redis-cli
|
|
||||||
|
|
||||||
# 下载 redis for windows https://github.com/redis-windows/redis-windows/releases
|
# 4. 运行后端WebApi
|
||||||
# 下载 redis for linux/mac https://redis.io/download
|
# 浏览器打开 http://localhost:5010 ,将看到Swagger(Knife4jUI)界面
|
||||||
```
|
dotnet run --project ./src/backend/NetAdmin.AdmServer.Host/NetAdmin.AdmServer.Host.csproj --urls http://[::]:5010 -is
|
||||||
4. 运行后端WebApi
|
|
||||||
``` shell
|
|
||||||
dotnet run --project ./src/backend/NetAdmin.AdmServer.Host/NetAdmin.AdmServer.Host.csproj --urls http://[::]:5010 -is
|
|
||||||
```
|
|
||||||
5. 体验WebApi程序
|
|
||||||
- 浏览器打开 http://localhost:5010 ,将看到Swagger(Knife4jUI)界面
|
|
||||||
|
|
||||||
---
|
# 5. 检查nodejs版本>=20
|
||||||
|
# 下载 nodejs https://nodejs.org/en/download
|
||||||
|
node -v
|
||||||
|
|
||||||
- 前端
|
# 6. 安装npm依赖包
|
||||||
1. 检查nodejs版本>=20
|
cd ./src/frontend/admin && npm install
|
||||||
``` shell
|
|
||||||
node -v
|
|
||||||
|
|
||||||
# 下载 nodejs https://nodejs.org/en/download
|
# 7. 运行前端项目
|
||||||
```
|
# 浏览器打开 http://localhost:5020 ,将看到管理界面(默认用户名:root,密码:1234qwer)
|
||||||
2. 安装npm依赖包
|
npm run dev
|
||||||
``` shell
|
```
|
||||||
cd ./src/frontend/admin
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
3. 运行前端项目
|
|
||||||
``` shell
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
4. 体验前端程序
|
|
||||||
- 浏览器打开 http://localhost:5020 ,将看到管理界面(默认用户名:root,密码:1234qwer)
|
|
||||||
|
|
||||||
## 文件目录树
|
## 文件目录树
|
||||||
|
|
||||||
```
|
```
|
||||||
+---.template.config # dotnet 项目模板配置目录
|
+---.template.config # dotnet 项目模板配置目录
|
||||||
+---assets # 程序运行需要的资源文件目录
|
+---assets # 项目资源文件目录
|
||||||
+---dist # 程序编译与分发的二进制文件目录
|
+---build # 构建相关的工程文件目录
|
||||||
+---docs # 项目文档目录
|
+---dist # 编译生成的二进制文件目录
|
||||||
+---refs # 引用的第三方项目仓库目录
|
+---docs # 项目开发文档目录
|
||||||
+---src # 项目源文件目录
|
+---refs # 引用的第三方包的仓库目录
|
||||||
|
+---scripts # 各种工具脚本文件目录
|
||||||
|
+---src # 项目源码文件目录
|
||||||
```
|
```
|
||||||
|
|
||||||
## 后端项目架构
|
## 后端项目架构
|
||||||
|
@ -70,13 +70,13 @@
|
|||||||
等于
|
等于
|
||||||
等待发送
|
等待发送
|
||||||
系统模块
|
系统模块
|
||||||
绑定手机号
|
绑定手机号码
|
||||||
结果非预期
|
结果非预期
|
||||||
群众
|
群众
|
||||||
自定义
|
自定义
|
||||||
范围
|
范围
|
||||||
菜单
|
菜单
|
||||||
解绑手机号
|
解绑手机号码
|
||||||
警告
|
警告
|
||||||
调试
|
调试
|
||||||
跟踪
|
跟踪
|
||||||
|
@ -23,6 +23,7 @@ XML注释文件不存在
|
|||||||
学历不正确
|
学历不正确
|
||||||
密码不能为空
|
密码不能为空
|
||||||
已处理完毕
|
已处理完毕
|
||||||
|
并发冲突请稍后重试
|
||||||
开始事务
|
开始事务
|
||||||
性别不正确
|
性别不正确
|
||||||
手机号码不正确
|
手机号码不正确
|
||||||
@ -57,7 +58,7 @@ XML注释文件不存在
|
|||||||
父节点不存在
|
父节点不存在
|
||||||
用户不存在
|
用户不存在
|
||||||
用户名不能为空
|
用户名不能为空
|
||||||
用户名不能是手机号
|
用户名不能是手机号码
|
||||||
用户名或密码错误
|
用户名或密码错误
|
||||||
用户名长度4位以上
|
用户名长度4位以上
|
||||||
用户头像不能为空
|
用户头像不能为空
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
"Id": 373837717815301,
|
"Id": 373837717815301,
|
||||||
"Name": "home",
|
"Name": "home",
|
||||||
"Path": "/home",
|
"Path": "/home",
|
||||||
"Sort": 100,
|
"Sort": 999,
|
||||||
"Title": "主控面板",
|
"Title": "主控面板",
|
||||||
"Type": 1
|
"Type": 1
|
||||||
},
|
},
|
||||||
|
@ -14,5 +14,25 @@
|
|||||||
{
|
{
|
||||||
"ApiId": "api/sys/user",
|
"ApiId": "api/sys/user",
|
||||||
"RoleId": 371729946431493
|
"RoleId": 371729946431493
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ApiId": "api/sys/site.msg/unread.count",
|
||||||
|
"RoleId": 371729946431493,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ApiId": "api/sys/site.msg",
|
||||||
|
"RoleId": 371729946431493,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ApiId": "api/sys/site.msg/get.mine",
|
||||||
|
"RoleId": 371729946431493,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ApiId": "api/sys/site.msg/paged.query.mine",
|
||||||
|
"RoleId": 371729946431493,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ApiId": "api/sys/site.msg/set.site.msg.status",
|
||||||
|
"RoleId": 371729946431493,
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -15,15 +15,15 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.10.12-preview">
|
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.10.48">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Roslynator.Analyzers" Version="4.12.2">
|
<PackageReference Include="Roslynator.Analyzers" Version="4.12.4">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.24.0.89429">
|
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.26.0.92422">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"version": "1.1.1",
|
"version": "1.2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cz-git": "^1.9.1",
|
"cz-git": "^1.9.2",
|
||||||
"commitizen": "^4.3.0",
|
"commitizen": "^4.3.0",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.3.0",
|
||||||
"standard-version": "^9.5.0"
|
"standard-version": "^9.5.0"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"packageName": "Furion.Pure.NS",
|
"packageName": "Furion.Pure.NS",
|
||||||
"version": "4.9.2.31-ns3"
|
"version": "4.9.3-ns1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
<ProjectReference Include="../NetAdmin.AdmServer.Host/NetAdmin.AdmServer.Host.csproj"/>
|
<ProjectReference Include="../NetAdmin.AdmServer.Host/NetAdmin.AdmServer.Host.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0-release-24177-07"/>
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -0,0 +1,29 @@
|
|||||||
|
using NetAdmin.Application.Repositories;
|
||||||
|
using NetAdmin.Domain.DbMaps.Dependency;
|
||||||
|
using RedLockNet;
|
||||||
|
|
||||||
|
namespace NetAdmin.Application.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RedLocker Service Base
|
||||||
|
/// </summary>
|
||||||
|
public abstract class RedLockerService<T1, T2>(DefaultRepository<T1> rpo, RedLocker redLocker)
|
||||||
|
: RepositoryService<T1, T2>(rpo)
|
||||||
|
where T1 : EntityBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 获取锁
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="NetAdminGetLockerException">NetAdminGetLockerException</exception>
|
||||||
|
protected async Task<IRedLock> GetLockerAsync(string lockName)
|
||||||
|
{
|
||||||
|
// 加锁
|
||||||
|
var redLock = await redLocker.RedLockFactory.CreateLockAsync( //
|
||||||
|
lockName, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_EXPIRY)
|
||||||
|
, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_WAIT)
|
||||||
|
, TimeSpan.FromSeconds(Numbers.SECS_RED_LOCK_RETRY))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
return redLock.IsAcquired ? redLock : throw new NetAdminGetLockerException();
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
namespace NetAdmin.Domain.Attributes.DataValidation;
|
namespace NetAdmin.Domain.Attributes.DataValidation;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 手机号验证器
|
/// 手机号码验证器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter)]
|
||||||
public sealed class MobileAttribute : RegexAttribute
|
public sealed class MobileAttribute : RegexAttribute
|
||||||
|
@ -10,7 +10,7 @@ public sealed class PortAttribute : RangeAttribute
|
|||||||
/// Initializes a new instance of the <see cref="PortAttribute" /> class.
|
/// Initializes a new instance of the <see cref="PortAttribute" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PortAttribute() //
|
public PortAttribute() //
|
||||||
: base(1, 65535)
|
: base(1, ushort.MaxValue)
|
||||||
{
|
{
|
||||||
ErrorMessageResourceName = nameof(Ln.无效端口号);
|
ErrorMessageResourceName = nameof(Ln.无效端口号);
|
||||||
ErrorMessageResourceType = typeof(Ln);
|
ErrorMessageResourceType = typeof(Ln);
|
||||||
|
@ -27,8 +27,8 @@ public sealed class UserNameAttribute : RegexAttribute
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 不能是手机号
|
// 不能是手机号码
|
||||||
ErrorMessageResourceName = nameof(Ln.用户名不能是手机号);
|
ErrorMessageResourceName = nameof(Ln.用户名不能是手机号码);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -61,7 +61,11 @@ public record Sys_Dept : VersionEntity, IFieldEnabled, IFieldSummary, IFieldSort
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 部门描述
|
/// 部门描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Summary { get; init; }
|
public virtual string Summary { get; init; }
|
||||||
}
|
}
|
@ -37,6 +37,13 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string JobName { get; init; }
|
public virtual string JobName { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上次执行耗时
|
||||||
|
/// </summary>
|
||||||
|
[Column]
|
||||||
|
[JsonIgnore]
|
||||||
|
public virtual long? LastDuration { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 上次执行时间
|
/// 上次执行时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -68,21 +75,33 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求体
|
/// 请求体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string RequestBody { get; init; }
|
public virtual string RequestBody { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求头
|
/// 请求头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string RequestHeader { get; init; }
|
public virtual string RequestHeader { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求的网络地址
|
/// 请求的网络地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string RequestUrl { get; init; }
|
public virtual string RequestUrl { get; init; }
|
||||||
|
|
||||||
@ -94,7 +113,11 @@ public record Sys_Job : VersionEntity, IFieldEnabled, IFieldSummary
|
|||||||
public virtual JobStatues Status { get; init; }
|
public virtual JobStatues Status { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldSummary.Summary" />
|
/// <inheritdoc cref="IFieldSummary.Summary" />
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Summary { get; init; }
|
public virtual string Summary { get; init; }
|
||||||
|
|
||||||
|
@ -48,14 +48,22 @@ public record Sys_JobRecord : LiteImmutableEntity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求体
|
/// 请求体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string RequestBody { get; init; }
|
public virtual string RequestBody { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求头
|
/// 请求头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string RequestHeader { get; init; }
|
public virtual string RequestHeader { get; init; }
|
||||||
|
|
||||||
@ -69,14 +77,22 @@ public record Sys_JobRecord : LiteImmutableEntity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应体
|
/// 响应体
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string ResponseBody { get; init; }
|
public virtual string ResponseBody { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应头
|
/// 响应头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string ResponseHeader { get; init; }
|
public virtual string ResponseHeader { get; init; }
|
||||||
|
|
||||||
|
@ -35,14 +35,22 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建者来源地址
|
/// 创建者来源地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string CreatedReferer { get; init; }
|
public string CreatedReferer { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建者客户端用户代理
|
/// 创建者客户端用户代理
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(Position = -1, DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_1022)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string CreatedUserAgent { get; init; }
|
public virtual string CreatedUserAgent { get; init; }
|
||||||
|
|
||||||
@ -63,14 +71,22 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异常信息
|
/// 异常信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Exception { get; init; }
|
public virtual string Exception { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 附加数据
|
/// 附加数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string ExtraData { get; init; }
|
public virtual string ExtraData { get; init; }
|
||||||
|
|
||||||
@ -91,14 +107,22 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 来源地址
|
/// 来源地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string ReferUrl { get; init; }
|
public virtual string ReferUrl { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求内容
|
/// 请求内容
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string RequestBody { get; init; }
|
public virtual string RequestBody { get; init; }
|
||||||
|
|
||||||
@ -112,7 +136,11 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求头信息
|
/// 请求头信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string RequestHeaders { get; init; }
|
public virtual string RequestHeaders { get; init; }
|
||||||
|
|
||||||
@ -126,7 +154,11 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应内容
|
/// 响应内容
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string ResponseBody { get; init; }
|
public virtual string ResponseBody { get; init; }
|
||||||
|
|
||||||
@ -140,7 +172,11 @@ public record Sys_RequestLog : ImmutableEntity, IFieldCreatedClient
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 响应头
|
/// 响应头
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string ResponseHeaders { get; init; }
|
public virtual string ResponseHeaders { get; init; }
|
||||||
|
|
||||||
|
@ -85,7 +85,11 @@ public record Sys_Role : VersionEntity, IFieldSort, IFieldEnabled, IFieldSummary
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 备注
|
/// 备注
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Summary { get; init; }
|
public virtual string Summary { get; init; }
|
||||||
|
|
||||||
|
@ -14,7 +14,11 @@ public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息内容
|
/// 消息内容
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Content { get; init; }
|
public virtual string Content { get; init; }
|
||||||
|
|
||||||
@ -55,14 +59,22 @@ public record Sys_SiteMsg : VersionEntity, IRegister, IFieldSummary
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息摘要
|
/// 消息摘要
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Summary { get; init; }
|
public virtual string Summary { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 消息主题
|
/// 消息主题
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Title { get; init; }
|
public virtual string Title { get; init; }
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister
|
|||||||
public virtual bool Enabled { get; init; }
|
public virtual bool Enabled { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 手机号
|
/// 手机号码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
@ -85,7 +85,11 @@ public record Sys_User : VersionEntity, IFieldSummary, IFieldEnabled, IRegister
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 描述
|
/// 描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public virtual string Summary { get; init; }
|
public virtual string Summary { get; init; }
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ public record Sys_UserProfile : VersionEntity, IRegister
|
|||||||
public int? EmergencyContactArea { get; init; }
|
public int? EmergencyContactArea { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 紧急联系人手机号
|
/// 紧急联系人手机号码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_15)]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
@ -33,7 +33,11 @@ public record Sys_VerifyCode : VersionEntity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 发送报告
|
/// 发送报告
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
#if DBTYPE_SQLITE
|
||||||
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_255)]
|
||||||
|
#else
|
||||||
|
[Column(DbType = Chars.FLG_DB_FIELD_TYPE_VARCHAR_MAX)]
|
||||||
|
#endif
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string Report { get; init; }
|
public string Report { get; init; }
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ public sealed record QueryJobRsp : Sys_Job
|
|||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public override string JobName { get; init; }
|
public override string JobName { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Sys_Job.LastDuration" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
|
public override long? LastDuration { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Sys_Job.LastExecTime" />
|
/// <inheritdoc cref="Sys_Job.LastExecTime" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||||
public override DateTime? LastExecTime { get; init; }
|
public override DateTime? LastExecTime { get; init; }
|
||||||
|
@ -9,6 +9,10 @@ namespace NetAdmin.Domain.Dto.Sys.JobRecord;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record QueryJobRecordRsp : Sys_JobRecord
|
public sealed record QueryJobRecordRsp : Sys_JobRecord
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc cref="Sys_JobRecord.HttpStatusCode" />
|
||||||
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
|
public new HttpStatusCode HttpStatusCode => (HttpStatusCode)base.HttpStatusCode;
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
/// <inheritdoc cref="IFieldCreatedTime.CreatedTime" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public override DateTime CreatedTime { get; init; }
|
public override DateTime CreatedTime { get; init; }
|
||||||
@ -21,10 +25,6 @@ public sealed record QueryJobRecordRsp : Sys_JobRecord
|
|||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public override HttpMethods HttpMethod { get; init; }
|
public override HttpMethods HttpMethod { get; init; }
|
||||||
|
|
||||||
/// <inheritdoc cref="Sys_JobRecord.HttpStatusCode" />
|
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
|
||||||
public override int HttpStatusCode { get; init; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
/// <inheritdoc cref="IFieldPrimary{T}.Id" />
|
||||||
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
[JsonIgnore(Condition = JsonIgnoreCondition.Never)]
|
||||||
public override long Id { get; init; }
|
public override long Id { get; init; }
|
||||||
|
@ -4,7 +4,7 @@ using NetAdmin.Domain.DbMaps.Sys;
|
|||||||
namespace NetAdmin.Domain.Dto.Sys.User;
|
namespace NetAdmin.Domain.Dto.Sys.User;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:检查手机号是否可用
|
/// 请求:检查手机号码是否可用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record CheckMobileAvailableReq : Sys_User
|
public sealed record CheckMobileAvailableReq : Sys_User
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@ namespace NetAdmin.Domain.Dto.Sys.User;
|
|||||||
public sealed record LoginByPwdReq : DataAbstraction
|
public sealed record LoginByPwdReq : DataAbstraction
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户名、手机号、邮箱
|
/// 用户名、手机号码、邮箱
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.账号不能为空))]
|
[Required(ErrorMessageResourceType = typeof(Ln), ErrorMessageResourceName = nameof(Ln.账号不能为空))]
|
||||||
public string Account { get; init; }
|
public string Account { get; init; }
|
||||||
|
@ -21,7 +21,7 @@ public sealed record LoginRsp : DataAbstraction
|
|||||||
public void SetToRspHeader()
|
public void SetToRspHeader()
|
||||||
{
|
{
|
||||||
// 设置响应报文头
|
// 设置响应报文头
|
||||||
App.HttpContext.Response.Headers[Chars.FLG_HTTP_HEADER_VALUE_ACCESS_TOKEN] = AccessToken;
|
App.HttpContext.Response.Headers[Chars.FLG_HTTP_HEADER_KEY_ACCESS_TOKEN] = AccessToken;
|
||||||
App.HttpContext.Response.Headers[Chars.FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN] = RefreshToken;
|
App.HttpContext.Response.Headers[Chars.FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN] = RefreshToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@ using NetAdmin.Domain.Dto.Sys.VerifyCode;
|
|||||||
namespace NetAdmin.Domain.Dto.Sys.User;
|
namespace NetAdmin.Domain.Dto.Sys.User;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 请求:设置手机号
|
/// 请求:设置手机号码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record SetMobileReq : DataAbstraction
|
public sealed record SetMobileReq : DataAbstraction
|
||||||
{
|
{
|
||||||
|
@ -7,9 +7,9 @@ namespace NetAdmin.Domain.Enums.Sys;
|
|||||||
public enum VerifyCodeTypes
|
public enum VerifyCodeTypes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 绑定手机号
|
/// 绑定手机号码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ResourceDescription<Ln>(nameof(Ln.绑定手机号))]
|
[ResourceDescription<Ln>(nameof(Ln.绑定手机号码))]
|
||||||
LinkMobile = 1
|
LinkMobile = 1
|
||||||
|
|
||||||
,
|
,
|
||||||
@ -23,9 +23,9 @@ public enum VerifyCodeTypes
|
|||||||
,
|
,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解绑手机号
|
/// 解绑手机号码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ResourceDescription<Ln>(nameof(Ln.解绑手机号))]
|
[ResourceDescription<Ln>(nameof(Ln.解绑手机号码))]
|
||||||
UnlinkMobile = 3
|
UnlinkMobile = 3
|
||||||
|
|
||||||
,
|
,
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<DefineConstants>DBTYPE_SQLITE</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
<Import Project="$(SolutionDir)/build/code.quality.props"/>
|
<Import Project="$(SolutionDir)/build/code.quality.props"/>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="$(SolutionDir)/assets/seed-data/**" LinkBase="SeedData" CopyToOutputDirectory="PreserveNewest"/>
|
<Content Include="$(SolutionDir)/assets/seed-data/**" LinkBase="SeedData" CopyToOutputDirectory="PreserveNewest"/>
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
|
using Furion.FriendlyException;
|
||||||
using NetAdmin.Domain.Dto;
|
using NetAdmin.Domain.Dto;
|
||||||
|
|
||||||
namespace NetAdmin.Host.Filters;
|
namespace NetAdmin.Host.Filters;
|
||||||
|
|
||||||
/// <inheritdoc cref="NetAdmin.Host.Filters.ApiResultHandler{T}" />
|
/// <inheritdoc cref="ApiResultHandler{T}" />
|
||||||
[SuppressSniffer]
|
[SuppressSniffer]
|
||||||
[UnifyModel(typeof(RestfulInfo<>))]
|
[UnifyModel(typeof(RestfulInfo<>))]
|
||||||
public sealed class DefaultApiResultHandler : ApiResultHandler<RestfulInfo<object>>, IUnifyResultProvider;
|
public sealed class DefaultApiResultHandler : ApiResultHandler<RestfulInfo<object>>, IUnifyResultProvider
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IActionResult OnAuthorizeException(DefaultHttpContext context, ExceptionMetadata metadata)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,12 @@ public sealed class RequestAuditMiddleware(
|
|||||||
// 跳过处理的情况:
|
// 跳过处理的情况:
|
||||||
if (!context.Request.Path.StartsWithSegments(_defaultRoutePrefix) // 非api请求
|
if (!context.Request.Path.StartsWithSegments(_defaultRoutePrefix) // 非api请求
|
||||||
|| context.Request.Path.StartsWithSegments(_healthCheckRoutePrefix) // 健康检查
|
|| context.Request.Path.StartsWithSegments(_healthCheckRoutePrefix) // 健康检查
|
||||||
|| context.Request.Method == Chars.FLG_HTTP_METHOD_OPTIONS) { // is options 请求
|
|| context.Request.Method == Chars.FLG_HTTP_METHOD_OPTIONS // is options 请求
|
||||||
|
|| (context.Request.ContentType?.StartsWith("multipart/form-data", true, CultureInfo.InvariantCulture) ??
|
||||||
|
false) // 文件上传
|
||||||
|
#pragma warning disable SA1009
|
||||||
|
) {
|
||||||
|
#pragma warning restore SA1009
|
||||||
await next(context).ConfigureAwait(false);
|
await next(context).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ public static class Chars
|
|||||||
public const string FLG_CONTEXT_OWNER_DEPT_ID = nameof(FLG_CONTEXT_OWNER_DEPT_ID);
|
public const string FLG_CONTEXT_OWNER_DEPT_ID = nameof(FLG_CONTEXT_OWNER_DEPT_ID);
|
||||||
public const string FLG_CONTEXT_USER_ID = nameof(FLG_CONTEXT_USER_ID);
|
public const string FLG_CONTEXT_USER_ID = nameof(FLG_CONTEXT_USER_ID);
|
||||||
public const string FLG_CONTEXT_USER_INFO = nameof(FLG_CONTEXT_USER_INFO);
|
public const string FLG_CONTEXT_USER_INFO = nameof(FLG_CONTEXT_USER_INFO);
|
||||||
|
public const string FLG_CRON_PER_SECS = "* * * * * *";
|
||||||
public const string FLG_DB_EXCEPTION_PRIVATE_KEY_CONFLICT = "PRIMARY KEY";
|
public const string FLG_DB_EXCEPTION_PRIVATE_KEY_CONFLICT = "PRIMARY KEY";
|
||||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR = "nvarchar";
|
public const string FLG_DB_FIELD_TYPE_NVARCHAR = "nvarchar";
|
||||||
public const string FLG_DB_FIELD_TYPE_NVARCHAR_1022 = "nvarchar(1022)";
|
public const string FLG_DB_FIELD_TYPE_NVARCHAR_1022 = "nvarchar(1022)";
|
||||||
@ -46,6 +47,7 @@ public static class Chars
|
|||||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_MEMBER = nameof(FLG_FREE_SQL_GLOBAL_FILTER_MEMBER);
|
public const string FLG_FREE_SQL_GLOBAL_FILTER_MEMBER = nameof(FLG_FREE_SQL_GLOBAL_FILTER_MEMBER);
|
||||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_SELF = nameof(FLG_FREE_SQL_GLOBAL_FILTER_SELF);
|
public const string FLG_FREE_SQL_GLOBAL_FILTER_SELF = nameof(FLG_FREE_SQL_GLOBAL_FILTER_SELF);
|
||||||
public const string FLG_FREE_SQL_GLOBAL_FILTER_TENANT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_TENANT);
|
public const string FLG_FREE_SQL_GLOBAL_FILTER_TENANT = nameof(FLG_FREE_SQL_GLOBAL_FILTER_TENANT);
|
||||||
|
public const string FLG_HTTP_HEADER_KEY_ACCESS_TOKEN = "ACCESS-TOKEN";
|
||||||
public const string FLG_HTTP_HEADER_KEY_AUTHORIZATION = "Authorization";
|
public const string FLG_HTTP_HEADER_KEY_AUTHORIZATION = "Authorization";
|
||||||
public const string FLG_HTTP_HEADER_KEY_REFERER = "Referer";
|
public const string FLG_HTTP_HEADER_KEY_REFERER = "Referer";
|
||||||
public const string FLG_HTTP_HEADER_KEY_USER_AGENT = "User-Agent";
|
public const string FLG_HTTP_HEADER_KEY_USER_AGENT = "User-Agent";
|
||||||
@ -53,7 +55,6 @@ public static class Chars
|
|||||||
public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN_HEADER_KEY = "X-Authorization";
|
public const string FLG_HTTP_HEADER_KEY_X_ACCESS_TOKEN_HEADER_KEY = "X-Authorization";
|
||||||
public const string FLG_HTTP_HEADER_KEY_X_FORWARDED_FOR = "X-Forwarded-For";
|
public const string FLG_HTTP_HEADER_KEY_X_FORWARDED_FOR = "X-Forwarded-For";
|
||||||
public const string FLG_HTTP_HEADER_KEY_X_REAL_IP = "X-Real-IP";
|
public const string FLG_HTTP_HEADER_KEY_X_REAL_IP = "X-Real-IP";
|
||||||
public const string FLG_HTTP_HEADER_VALUE_ACCESS_TOKEN = "ACCESS-TOKEN";
|
|
||||||
public const string FLG_HTTP_HEADER_VALUE_APPLICATION_JSON = "application/json";
|
public const string FLG_HTTP_HEADER_VALUE_APPLICATION_JSON = "application/json";
|
||||||
public const string FLG_HTTP_HEADER_VALUE_APPLICATION_URLENCODED = "application/x-www-form-urlencoded";
|
public const string FLG_HTTP_HEADER_VALUE_APPLICATION_URLENCODED = "application/x-www-form-urlencoded";
|
||||||
public const string FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA = "Bearer";
|
public const string FLG_HTTP_HEADER_VALUE_AUTH_SCHEMA = "Bearer";
|
||||||
|
@ -8,11 +8,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Cronos" Version="0.8.4"/>
|
<PackageReference Include="Cronos" Version="0.8.4"/>
|
||||||
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.821-ns1"/>
|
<PackageReference Include="FreeSql.DbContext.NS" Version="3.2.821-ns1"/>
|
||||||
|
<PackageReference Include="FreeSql.Provider.SqlServer.NS" Version="3.2.821-ns1"/>
|
||||||
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.821-ns1"/>
|
<PackageReference Include="FreeSql.Provider.Sqlite.NS" Version="3.2.821-ns1"/>
|
||||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.2.31"/>
|
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.3"/>
|
||||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.2.31-ns1"/>
|
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster.NS" Version="4.9.3-ns1"/>
|
||||||
<PackageReference Include="Furion.Pure.NS" Version="4.9.2.31-ns1"/>
|
<PackageReference Include="Furion.Pure.NS" Version="4.9.3-ns1"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0-preview.3.24172.13"/>
|
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0-preview.4.24267.6"/>
|
||||||
<PackageReference Include="Minio" Version="6.0.2"/>
|
<PackageReference Include="Minio" Version="6.0.2"/>
|
||||||
<PackageReference Include="NSExt" Version="2.1.0"/>
|
<PackageReference Include="NSExt" Version="2.1.0"/>
|
||||||
<PackageReference Include="RedLock.net" Version="2.3.2"/>
|
<PackageReference Include="RedLock.net" Version="2.3.2"/>
|
||||||
|
@ -20,6 +20,11 @@ public interface IJobModule : ICrudModule<CreateJobReq, QueryJobRsp // 创建类
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Task<QueryJobRsp> EditAsync(UpdateJobReq req);
|
Task<QueryJobRsp> EditAsync(UpdateJobReq req);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行作业
|
||||||
|
/// </summary>
|
||||||
|
Task ExecuteAsync(QueryJobReq req);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取作业记录条形图数据
|
/// 获取作业记录条形图数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,7 +15,7 @@ public interface IUserModule : ICrudModule<CreateUserReq, QueryUserRsp // 创建
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查手机号是否可用
|
/// 检查手机号码是否可用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<bool> CheckMobileAvailableAsync(CheckMobileAvailableReq req);
|
Task<bool> CheckMobileAvailableAsync(CheckMobileAvailableReq req);
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ public interface IUserModule : ICrudModule<CreateUserReq, QueryUserRsp // 创建
|
|||||||
Task SetEnabledAsync(SetUserEnabledReq req);
|
Task SetEnabledAsync(SetUserEnabledReq req);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置手机号
|
/// 设置手机号码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<UserInfoRsp> SetMobileAsync(SetMobileReq req);
|
Task<UserInfoRsp> SetMobileAsync(SetMobileReq req);
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Cronos;
|
using Cronos;
|
||||||
|
using FreeSql.Internal;
|
||||||
using NetAdmin.Application.Repositories;
|
using NetAdmin.Application.Repositories;
|
||||||
using NetAdmin.Application.Services;
|
using NetAdmin.Application.Services;
|
||||||
using NetAdmin.Domain.DbMaps.Sys;
|
using NetAdmin.Domain.DbMaps.Sys;
|
||||||
@ -63,18 +64,60 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo, IJobRecordService
|
|||||||
public async Task<QueryJobRsp> EditAsync(UpdateJobReq req)
|
public async Task<QueryJobRsp> EditAsync(UpdateJobReq req)
|
||||||
{
|
{
|
||||||
req.ThrowIfInvalid();
|
req.ThrowIfInvalid();
|
||||||
var ret = await Rpo.UpdateDiy.Set(a => a.ExecutionCron == req.ExecutionCron)
|
var update = Rpo.UpdateDiy.Set(a => a.ExecutionCron == req.ExecutionCron)
|
||||||
.Set(a => a.HttpMethod == req.HttpMethod)
|
.Set(a => a.HttpMethod == req.HttpMethod)
|
||||||
.Set(a => a.JobName == req.JobName)
|
.Set(a => a.JobName == req.JobName)
|
||||||
.SetIf(req.RequestHeaders == null, a => a.RequestHeader, null)
|
.SetIf(req.RequestHeaders == null, a => a.RequestHeader, null)
|
||||||
.SetIf(req.RequestHeaders != null, a => a.RequestHeader, req.RequestHeaders.Json())
|
.SetIf(req.RequestHeaders != null, a => a.RequestHeader, req.RequestHeaders.Json())
|
||||||
.Set(a => a.RequestBody == req.RequestBody)
|
.Set(a => a.RequestBody == req.RequestBody)
|
||||||
.Set(a => a.RequestUrl == req.RequestUrl)
|
.Set(a => a.RequestUrl == req.RequestUrl)
|
||||||
.Set(a => a.UserId == req.UserId)
|
.Set(a => a.UserId == req.UserId)
|
||||||
.Where(a => a.Id == req.Id)
|
.Where(a => a.Id == req.Id);
|
||||||
.ExecuteUpdatedAsync()
|
|
||||||
.ConfigureAwait(false);
|
#pragma warning disable IDE0046
|
||||||
return ret[0].Adapt<QueryJobRsp>();
|
if (Rpo.Orm.Ado.DataType == DataType.Sqlite) {
|
||||||
|
#pragma warning restore IDE0046
|
||||||
|
return await update.ExecuteAffrowsAsync().ConfigureAwait(false) <= 0
|
||||||
|
? null
|
||||||
|
: await GetAsync(new QueryJobReq { Id = req.Id }).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (await update.ExecuteUpdatedAsync().ConfigureAwait(false))[0].Adapt<QueryJobRsp>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task ExecuteAsync(QueryJobReq req)
|
||||||
|
{
|
||||||
|
req.ThrowIfInvalid();
|
||||||
|
var df = new DynamicFilterInfo {
|
||||||
|
Filters = [
|
||||||
|
new DynamicFilterInfo {
|
||||||
|
Field = nameof(QueryJobReq.Enabled)
|
||||||
|
, Operator = DynamicFilterOperators.Eq
|
||||||
|
, Value = true
|
||||||
|
}
|
||||||
|
, new DynamicFilterInfo {
|
||||||
|
Field = nameof(QueryJobReq.Status)
|
||||||
|
, Operator = DynamicFilterOperators.Eq
|
||||||
|
, Value = JobStatues.Idle
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
var job = await QueryInternal(new QueryReq<QueryJobReq> { Count = 1, Filter = req, DynamicFilter = df })
|
||||||
|
.ToOneAsync()
|
||||||
|
.ConfigureAwait(false) ?? throw new NetAdminInvalidOperationException(Ln.未获取到待执行任务);
|
||||||
|
|
||||||
|
var nextExecTime = GetNextExecTime(Chars.FLG_CRON_PER_SECS);
|
||||||
|
try {
|
||||||
|
_ = await UpdateAsync(job.Adapt<UpdateJobReq>() with {
|
||||||
|
NextExecTime = nextExecTime
|
||||||
|
, NextTimeId = nextExecTime?.TimeUnixUtc()
|
||||||
|
})
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (DbUpdateVersionException) {
|
||||||
|
throw new NetAdminInvalidOperationException(Ln.并发冲突请稍后重试);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -127,14 +170,14 @@ public sealed class JobService(DefaultRepository<Sys_Job> rpo, IJobRecordService
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
var job
|
var job = await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Order = Orders.Random })
|
||||||
= await QueryInternal(new QueryReq<QueryJobReq> { DynamicFilter = df, Count = 1, Order = Orders.Random })
|
.Take(1)
|
||||||
.Where(a => !Rpo.Orm.Select<Sys_JobRecord>()
|
.Where(a => !Rpo.Orm.Select<Sys_JobRecord>()
|
||||||
.As("b")
|
.As("b")
|
||||||
.Where(b => b.JobId == a.Id && b.TimeId == a.NextTimeId)
|
.Where(b => b.JobId == a.Id && b.TimeId == a.NextTimeId)
|
||||||
.Any())
|
.Any())
|
||||||
.ToOneAsync()
|
.ToOneAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
return job == null
|
return job == null
|
||||||
? null
|
? null
|
||||||
: await UpdateAsync(job.Adapt<UpdateJobReq>() with {
|
: await UpdateAsync(job.Adapt<UpdateJobReq>() with {
|
||||||
|
@ -131,11 +131,15 @@ public sealed class MenuService(DefaultRepository<Sys_Menu> rpo, IUserService us
|
|||||||
private ISelect<Sys_Menu> QueryInternal(QueryReq<QueryMenuReq> req)
|
private ISelect<Sys_Menu> QueryInternal(QueryReq<QueryMenuReq> req)
|
||||||
{
|
{
|
||||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter).WhereDynamic(req.Filter);
|
||||||
return req.Order == Orders.Random
|
#pragma warning disable IDE0072
|
||||||
? ret.OrderByRandom()
|
return req.Order switch {
|
||||||
: ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
Orders.None => ret
|
||||||
.OrderByDescending(a => a.Sort)
|
, Orders.Random => ret.OrderByRandom()
|
||||||
.OrderBy(a => a.Name)
|
, _ => ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||||
.OrderBy(a => a.Id);
|
.OrderByDescending(a => a.Sort)
|
||||||
|
.OrderBy(a => a.Name)
|
||||||
|
.OrderBy(a => a.Id)
|
||||||
|
};
|
||||||
|
#pragma warning restore IDE0072
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -124,8 +124,11 @@ public sealed class RoleService(DefaultRepository<Sys_Role> rpo) //
|
|||||||
req.Keywords?.Length > 0
|
req.Keywords?.Length > 0
|
||||||
, a => a.Id == req.Keywords.Int64Try(0) || a.Name.Contains(req.Keywords) ||
|
, a => a.Id == req.Keywords.Int64Try(0) || a.Name.Contains(req.Keywords) ||
|
||||||
a.Summary.Contains(req.Keywords));
|
a.Summary.Contains(req.Keywords));
|
||||||
if (req.Order == Orders.Random) {
|
switch (req.Order) {
|
||||||
return ret.OrderByRandom();
|
case Orders.None:
|
||||||
|
return ret;
|
||||||
|
case Orders.Random:
|
||||||
|
return ret.OrderByRandom();
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
ret = ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||||
|
@ -152,7 +152,7 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
|||||||
private ISelect<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent> QueryInternal(
|
private ISelect<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent> QueryInternal(
|
||||||
QueryReq<QueryUserProfileReq> req)
|
QueryReq<QueryUserProfileReq> req)
|
||||||
{
|
{
|
||||||
#pragma warning disable CA1305
|
#pragma warning disable CA1305,IDE0072
|
||||||
var ret = Rpo.Orm.Select<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent>()
|
var ret = Rpo.Orm.Select<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent>()
|
||||||
.LeftJoin((a, b, _, __, ___) =>
|
.LeftJoin((a, b, _, __, ___) =>
|
||||||
a.NationArea.ToString() == b.Value && b.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
a.NationArea.ToString() == b.Value && b.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
||||||
@ -164,10 +164,13 @@ public sealed class UserProfileService(DefaultRepository<Sys_UserProfile> rpo) /
|
|||||||
.LeftJoin((a, _, __, ___, e) => a.EmergencyContactArea.ToString() == e.Value &&
|
.LeftJoin((a, _, __, ___, e) => a.EmergencyContactArea.ToString() == e.Value &&
|
||||||
e.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
e.CatalogId == Numbers.ID_DIC_CATALOG_GEO_AREA)
|
||||||
.WhereDynamicFilter(req.DynamicFilter);
|
.WhereDynamicFilter(req.DynamicFilter);
|
||||||
return req.Order == Orders.Random
|
|
||||||
? ret.OrderByRandom()
|
return req.Order switch {
|
||||||
: ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
Orders.None => ret
|
||||||
.OrderByDescending((a, _, __, ___, ____) => a.Id);
|
, Orders.Random => ret.OrderByRandom()
|
||||||
#pragma warning restore CA1305
|
, _ => ret.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||||
|
.OrderByDescending((a, _, __, ___, ____) => a.Id)
|
||||||
|
};
|
||||||
|
#pragma warning restore CA1305,IDE0072
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -134,9 +134,9 @@ public sealed class UserService(
|
|||||||
req.ThrowIfInvalid();
|
req.ThrowIfInvalid();
|
||||||
|
|
||||||
// ReSharper disable once MethodHasAsyncOverload
|
// ReSharper disable once MethodHasAsyncOverload
|
||||||
#pragma warning disable VSTHRD103
|
#pragma warning disable VSTHRD103,S6966
|
||||||
return (await QueryInternal(new QueryReq<QueryUserReq> { Filter = req })
|
return (await QueryInternal(new QueryReq<QueryUserReq> { Filter = req })
|
||||||
#pragma warning restore VSTHRD103
|
#pragma warning restore S6966, VSTHRD103
|
||||||
.ForUpdate()
|
.ForUpdate()
|
||||||
.ToOneAsync()
|
.ToOneAsync()
|
||||||
.ConfigureAwait(false)).Adapt<QueryUserRsp>();
|
.ConfigureAwait(false)).Adapt<QueryUserRsp>();
|
||||||
@ -257,7 +257,9 @@ public sealed class UserService(
|
|||||||
if (await Rpo.UpdateDiy
|
if (await Rpo.UpdateDiy
|
||||||
.SetSource(req with {
|
.SetSource(req with {
|
||||||
Id = UserToken.Id
|
Id = UserToken.Id
|
||||||
, Version = Rpo.Where(a => a.Id == UserToken.Id).ToOne(a => a.Version)
|
, Version = await Rpo.Where(a => a.Id == UserToken.Id)
|
||||||
|
.ToOneAsync(a => a.Version)
|
||||||
|
.ConfigureAwait(false)
|
||||||
})
|
})
|
||||||
.UpdateColumns(a => a.Avatar)
|
.UpdateColumns(a => a.Avatar)
|
||||||
.ExecuteAffrowsAsync()
|
.ExecuteAffrowsAsync()
|
||||||
@ -278,9 +280,11 @@ public sealed class UserService(
|
|||||||
public async Task<UserInfoRsp> SetEmailAsync(SetEmailReq req)
|
public async Task<UserInfoRsp> SetEmailAsync(SetEmailReq req)
|
||||||
{
|
{
|
||||||
req.ThrowIfInvalid();
|
req.ThrowIfInvalid();
|
||||||
var user = Rpo.Where(a => a.Id == UserToken.Id).ToOne(a => new { a.Mobile, a.Version, a.Email });
|
var user = await Rpo.Where(a => a.Id == UserToken.Id)
|
||||||
|
.ToOneAsync(a => new { a.Mobile, a.Version, a.Email })
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
// 如果已绑定手机号、需要手机安全验证
|
// 如果已绑定手机号码、需要手机安全验证
|
||||||
if (!user.Mobile.NullOrEmpty()) {
|
if (!user.Mobile.NullOrEmpty()) {
|
||||||
if (!await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq).ConfigureAwait(false)) {
|
if (!await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq).ConfigureAwait(false)) {
|
||||||
throw new NetAdminInvalidOperationException(Ln.验证码不正确);
|
throw new NetAdminInvalidOperationException(Ln.验证码不正确);
|
||||||
@ -324,7 +328,7 @@ public sealed class UserService(
|
|||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (!user.Mobile.NullOrEmpty()) {
|
if (!user.Mobile.NullOrEmpty()) {
|
||||||
// 已有手机号,需验证旧手机
|
// 已有手机号码,需验证旧手机
|
||||||
if (!await verifyCodeService.VerifyAsync(req.OriginVerifySmsCodeReq).ConfigureAwait(false)) {
|
if (!await verifyCodeService.VerifyAsync(req.OriginVerifySmsCodeReq).ConfigureAwait(false)) {
|
||||||
throw new NetAdminInvalidOperationException($"{Ln.旧手机号码验证码不正确}");
|
throw new NetAdminInvalidOperationException($"{Ln.旧手机号码验证码不正确}");
|
||||||
}
|
}
|
||||||
@ -334,7 +338,7 @@ public sealed class UserService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证新手机号
|
// 验证新手机号码
|
||||||
if (!await verifyCodeService.VerifyAsync(req.NewVerifySmsCodeReq).ConfigureAwait(false)) {
|
if (!await verifyCodeService.VerifyAsync(req.NewVerifySmsCodeReq).ConfigureAwait(false)) {
|
||||||
throw new NetAdminInvalidOperationException($"{Ln.新手机号码验证码不正确}");
|
throw new NetAdminInvalidOperationException($"{Ln.新手机号码验证码不正确}");
|
||||||
}
|
}
|
||||||
|
@ -173,8 +173,7 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
|||||||
private Task<Sys_VerifyCode> GetLastSentAsync(string destDevice)
|
private Task<Sys_VerifyCode> GetLastSentAsync(string destDevice)
|
||||||
{
|
{
|
||||||
return QueryInternal(new QueryReq<QueryVerifyCodeReq> {
|
return QueryInternal(new QueryReq<QueryVerifyCodeReq> {
|
||||||
Count = 1
|
DynamicFilter
|
||||||
, DynamicFilter
|
|
||||||
= new DynamicFilterInfo {
|
= new DynamicFilterInfo {
|
||||||
Field = nameof(
|
Field = nameof(
|
||||||
Sys_VerifyCode.DestDevice)
|
Sys_VerifyCode.DestDevice)
|
||||||
@ -182,7 +181,8 @@ public sealed class VerifyCodeService(DefaultRepository<Sys_VerifyCode> rpo, IEv
|
|||||||
, Value = destDevice
|
, Value = destDevice
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ToOneAsync();
|
.Take(1)
|
||||||
|
.ToOneAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISelect<Sys_VerifyCode> QueryInternal(QueryReq<QueryVerifyCodeReq> req)
|
private ISelect<Sys_VerifyCode> QueryInternal(QueryReq<QueryVerifyCodeReq> req)
|
||||||
|
@ -42,6 +42,12 @@ public sealed class JobCache(IDistributedCache cache, IJobService service)
|
|||||||
return Service.EditAsync(req);
|
return Service.EditAsync(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Task ExecuteAsync(QueryJobReq req)
|
||||||
|
{
|
||||||
|
return Service.ExecuteAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<bool> ExistAsync(QueryReq<QueryJobReq> req)
|
public Task<bool> ExistAsync(QueryReq<QueryJobReq> req)
|
||||||
{
|
{
|
||||||
|
@ -60,6 +60,14 @@ public sealed class JobController(IJobCache cache) : ControllerBase<IJobCache, I
|
|||||||
return Cache.EditAsync(req);
|
return Cache.EditAsync(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 执行作业
|
||||||
|
/// </summary>
|
||||||
|
public Task ExecuteAsync(QueryJobReq req)
|
||||||
|
{
|
||||||
|
return Cache.ExecuteAsync(req);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计划作业是否存在
|
/// 计划作业是否存在
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -27,7 +27,7 @@ public sealed class UserController(IUserCache cache, IConfigCache configCache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查手机号是否可用
|
/// 检查手机号码是否可用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public Task<bool> CheckMobileAvailableAsync(CheckMobileAvailableReq req)
|
public Task<bool> CheckMobileAvailableAsync(CheckMobileAvailableReq req)
|
||||||
@ -192,7 +192,7 @@ public sealed class UserController(IUserCache cache, IConfigCache configCache)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置手机号
|
/// 设置手机号码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Transaction]
|
[Transaction]
|
||||||
public Task<UserInfoRsp> SetMobileAsync(SetMobileReq req)
|
public Task<UserInfoRsp> SetMobileAsync(SetMobileReq req)
|
||||||
|
@ -68,7 +68,7 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
|
|||||||
var request = BuildRequest(job);
|
var request = BuildRequest(job);
|
||||||
var sw = new Stopwatch();
|
var sw = new Stopwatch();
|
||||||
sw.Start();
|
sw.Start();
|
||||||
var rsp = await request.SendAsync(cancelToken).ConfigureAwait(false);
|
var rsp = await request.SendAsync(CancellationToken.None).ConfigureAwait(false);
|
||||||
if (rsp.StatusCode == HttpStatusCode.Unauthorized) {
|
if (rsp.StatusCode == HttpStatusCode.Unauthorized) {
|
||||||
var loginRsp = await _userService.LoginByUserIdAsync(job.UserId).ConfigureAwait(false);
|
var loginRsp = await _userService.LoginByUserIdAsync(job.UserId).ConfigureAwait(false);
|
||||||
#pragma warning disable S2696
|
#pragma warning disable S2696
|
||||||
@ -76,12 +76,13 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
|
|||||||
_refreshToken = loginRsp.RefreshToken;
|
_refreshToken = loginRsp.RefreshToken;
|
||||||
#pragma warning restore S2696
|
#pragma warning restore S2696
|
||||||
request = BuildRequest(job);
|
request = BuildRequest(job);
|
||||||
rsp = await request.SendAsync(cancelToken).ConfigureAwait(false);
|
rsp = await request.SendAsync(CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
await UowManager.AtomicOperateAsync(async () => {
|
await UowManager.AtomicOperateAsync(async () => {
|
||||||
var rspBody = await rsp.Content.ReadAsStringAsync(cancelToken).ConfigureAwait(false);
|
var rspBody = await rsp.Content.ReadAsStringAsync(CancellationToken.None)
|
||||||
|
.ConfigureAwait(false);
|
||||||
var jobRecord = new CreateJobRecordReq //
|
var jobRecord = new CreateJobRecordReq //
|
||||||
{
|
{
|
||||||
Duration = sw.ElapsedMilliseconds
|
Duration = sw.ElapsedMilliseconds
|
||||||
@ -97,7 +98,10 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
|
|||||||
};
|
};
|
||||||
_ = await _jobRecordService.CreateAsync(jobRecord).ConfigureAwait(false);
|
_ = await _jobRecordService.CreateAsync(jobRecord).ConfigureAwait(false);
|
||||||
await _jobService
|
await _jobService
|
||||||
.FinishJobAsync(job.Adapt<UpdateJobReq>() with { LastStatusCode = rsp.StatusCode })
|
.FinishJobAsync(job.Adapt<UpdateJobReq>() with {
|
||||||
|
LastStatusCode = rsp.StatusCode
|
||||||
|
, LastDuration = jobRecord.Duration
|
||||||
|
})
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
})
|
})
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@ -128,7 +132,7 @@ public sealed class ScheduledJob : WorkBase<ScheduledJob>, IJob
|
|||||||
ret = ret.SetBody(job.RequestBody);
|
ret = ret.SetBody(job.RequestBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.OnResponsing(GetRequestHeader).OnException(GetRequestHeader);
|
return ret.SetLog(_logger).OnResponsing(GetRequestHeader).OnException(GetRequestHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetRequestHeader(HttpClient _, HttpResponseMessage rsp, string __)
|
private void GetRequestHeader(HttpClient _, HttpResponseMessage rsp, string __)
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
<ProjectReference Include="../NetAdmin.Host/NetAdmin.Host.csproj"/>
|
<ProjectReference Include="../NetAdmin.Host/NetAdmin.Host.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="xunit" Version="2.8.0"/>
|
<PackageReference Include="xunit" Version="2.8.1"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0-preview.3.24172.13"/>
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0-preview.4.24267.6"/>
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
@ -11,14 +11,14 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@tinymce/tinymce-vue": "^5.1.1",
|
"@tinymce/tinymce-vue": "^5.1.1",
|
||||||
"ace-builds": "^1.33.1",
|
"ace-builds": "^1.34.2",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.7.2",
|
||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
"core-js": "^3.37.0",
|
"core-js": "^3.37.1",
|
||||||
"cropperjs": "^1.6.2",
|
"cropperjs": "^1.6.2",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"echarts": "^5.5.0",
|
"echarts": "^5.5.0",
|
||||||
"element-plus": "^2.7.1",
|
"element-plus": "^2.7.4",
|
||||||
"json-bigint": "^1.0.0",
|
"json-bigint": "^1.0.0",
|
||||||
"json5-to-table": "^0.1.8",
|
"json5-to-table": "^0.1.8",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
@ -29,23 +29,23 @@
|
|||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
"tinymce": "^6.8.3",
|
"tinymce": "^6.8.3",
|
||||||
"vkbeautify": "^0.99.3",
|
"vkbeautify": "^0.99.3",
|
||||||
"vue": "^3.4.25",
|
"vue": "^3.4.27",
|
||||||
"vue-i18n": "^9.13.1",
|
"vue-i18n": "^9.13.1",
|
||||||
"vue-router": "^4.3.2",
|
"vue-router": "^4.3.2",
|
||||||
"vue3-ace-editor": "^2.2.4",
|
"vue3-ace-editor": "^2.2.4",
|
||||||
"vue3-json-viewer": "^2.2.2",
|
"vue3-json-viewer": "^2.2.2",
|
||||||
"vuedraggable": "^4.0.3",
|
"vuedraggable": "^4.0.3",
|
||||||
"vuex": "^4.1.0",
|
"vuex": "^4.1.0",
|
||||||
"xgplayer": "^3.0.16",
|
"xgplayer": "^3.0.18",
|
||||||
"xgplayer-hls": "^3.0.16"
|
"xgplayer-hls": "^3.0.18"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^5.0.4",
|
"@vitejs/plugin-vue": "^5.0.5",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.3.0",
|
||||||
"prettier-plugin-organize-attributes": "^1.0.0",
|
"prettier-plugin-organize-attributes": "^1.0.0",
|
||||||
"sass": "^1.75.0",
|
"sass": "^1.77.4",
|
||||||
"terser": "^5.30.4",
|
"terser": "^5.31.0",
|
||||||
"vite": "^5.2.10"
|
"vite": "^5.2.12"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
@ -60,6 +60,17 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行作业
|
||||||
|
*/
|
||||||
|
execute: {
|
||||||
|
url: `${config.API_URL}/api/sys/job/execute`,
|
||||||
|
name: `执行作业`,
|
||||||
|
post: async function (data = {}, config = {}) {
|
||||||
|
return await http.post(this.url, data, config)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计划作业是否存在
|
* 计划作业是否存在
|
||||||
*/
|
*/
|
||||||
|
7
src/frontend/admin/src/assets/icons/Email.vue
Normal file
7
src/frontend/admin/src/assets/icons/Email.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<svg class="icon" height="256" p-id="2661" t="1716619036537" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M874.666667 181.333333H149.333333c-40.533333 0-74.666667 34.133333-74.666666 74.666667v512c0 40.533333 34.133333 74.666667 74.666666 74.666667h725.333334c40.533333 0 74.666667-34.133333 74.666666-74.666667V256c0-40.533333-34.133333-74.666667-74.666666-74.666667z m-725.333334 64h725.333334c6.4 0 10.666667 4.266667 10.666666 10.666667v25.6L512 516.266667l-373.333333-234.666667V256c0-6.4 4.266667-10.666667 10.666666-10.666667z m725.333334 533.333334H149.333333c-6.4 0-10.666667-4.266667-10.666666-10.666667V356.266667l356.266666 224c4.266667 4.266667 10.666667 4.266667 17.066667 4.266666s12.8-2.133333 17.066667-4.266666l356.266666-224V768c0 6.4-4.266667 10.666667-10.666666 10.666667z"
|
||||||
|
p-id="2662"></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
13
src/frontend/admin/src/assets/icons/MailCode.vue
Normal file
13
src/frontend/admin/src/assets/icons/MailCode.vue
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<svg class="icon" height="256" p-id="9218" t="1716619196030" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M642.0992 501.5552a33.28 33.28 0 0 1 52.4288 40.6528l-3.328 4.2496-154.624 168.96a33.28 33.28 0 0 1-41.6256 6.144l-4.3008-3.072-128-107.008a33.28 33.28 0 0 1 38.1952-54.1696l4.4544 3.072 103.5776 86.6304 133.2224-145.4592z"
|
||||||
|
p-id="9219"></path>
|
||||||
|
<path
|
||||||
|
d="M793.6 153.6a102.4 102.4 0 0 1 102.4 102.4v512a102.4 102.4 0 0 1-102.4 102.4h-563.2a102.4 102.4 0 0 1-102.4-102.4V256a102.4 102.4 0 0 1 102.4-102.4h563.2z m0 66.56h-563.2a35.84 35.84 0 0 0-35.5328 30.976L194.56 256v512a35.84 35.84 0 0 0 30.976 35.5328l4.864 0.3072h563.2a35.84 35.84 0 0 0 35.5328-30.976L829.44 768V256a35.84 35.84 0 0 0-30.976-35.5328L793.6 220.16z"
|
||||||
|
p-id="9220"></path>
|
||||||
|
<path
|
||||||
|
d="M821.248 242.176a33.28 33.28 0 0 1 36.352 55.3984l-4.5056 2.9696-300.7488 164.096a84.48 84.48 0 0 1-72.9088 3.84l-7.68-3.6864-304.128-164.1472a33.28 33.28 0 0 1 26.7264-60.7744l4.9152 2.2016 304.128 164.1984a17.92 17.92 0 0 0 13.7728 1.3312l3.2768-1.3824 300.8-164.096z"
|
||||||
|
p-id="9221"></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
7
src/frontend/admin/src/assets/icons/Mobile.vue
Normal file
7
src/frontend/admin/src/assets/icons/Mobile.vue
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<svg class="icon" height="256" p-id="3820" t="1716618918266" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M736 0h-448C235.2 0 192 43.2 192 96v832c0 52.8 43.2 96 96 96h448c52.8 0 96-43.2 96-96v-832c0-52.8-43.2-96-96-96zM384 48h256v32H384v-32zM512 960a64 64 0 1 1 0-128 64 64 0 0 1 0 128z m256-192H256V128h512v640z"
|
||||||
|
p-id="3821"></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
@ -1,15 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<svg
|
<svg class="icon" height="256" p-id="5451" t="1716619102648" version="1.1" viewBox="0 0 1024 1024" width="256" xmlns="http://www.w3.org/2000/svg">
|
||||||
class="icon"
|
|
||||||
height="128"
|
|
||||||
p-id="17757"
|
|
||||||
t="1708507211716"
|
|
||||||
version="1.1"
|
|
||||||
viewBox="0 0 1024 1024"
|
|
||||||
width="128"
|
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
<path
|
||||||
d="M179.2 742.4v102.4c0 26.368 21.6576 48.128 49.408 50.8928l6.0416 0.3072h554.7008c28.5696 0 52.1216-19.968 55.1424-45.6192l0.3072-5.5808v-102.4h51.2v102.4c0 54.1184-44.9536 98.4064-101.888 102.144l-7.8336 0.256H237.7216c-57.9584 0-105.472-41.984-109.4656-95.0784L128 844.8v-102.4h51.2z m682.5984-399.36v45.6192l-65.8944 78.336c49.7664 2.7648 78.336 40.0896 78.336 97.2288 0 61.2864-35.0208 106.9056-102.2976 106.9056-67.7376 0-102.7584-45.1584-102.7584-106.4448v-0.9216l56.6784-3.6864v3.6864c0 40.0896 18.8928 58.5216 46.08 58.5216 26.7264 0 45.6192-18.432 45.6192-58.5216s-17.9712-58.5216-47.0016-58.5216a50.3296 50.3296 0 0 0-22.1184 5.0688l-27.648-30.4128 74.1888-88.0128h-115.6608V343.04h182.4768z m-570.2144 0v273.2544h61.7472V665.6H172.2368v-49.3056h62.6688V403.4048l-62.6688 25.8048V375.7568L243.6608 343.04h47.9232z m220.8256-5.5296c60.8256 0 99.9936 42.3936 99.9936 97.6896 0 32.7168-11.52 52.5312-31.7952 76.032l-92.6208 105.5232h124.416V665.6H412.416v-41.0112l123.9552-142.848c14.7456-17.0496 19.3536-29.952 19.3536-46.08 0-32.256-17.9712-49.3056-43.3152-49.3056-25.8048 0-43.3152 17.0496-43.3152 49.3056v11.0592l-56.6784-3.6864V435.2c0-55.296 37.3248-97.6896 99.9936-97.6896z m273.92-260.7104c57.9072 0 105.3696 41.984 109.4144 95.0784l0.256 7.3216v102.4h-51.2v-102.4c0-26.368-21.6576-48.128-49.408-50.8928l-6.0416-0.3072H234.6496c-28.5696 0-52.1216 19.968-55.1424 45.6192L179.2 179.2v102.4h-51.2v-102.4c0-54.1184 44.9536-98.4064 101.888-102.144l7.8336-0.256h548.5568z"
|
d="M932.8 1024H495.274667c-50.304 0-91.242667-41.088-91.242667-91.562667V588.032a21.333333 21.333333 0 1 1 42.666667 0v344.405333A48.789333 48.789333 0 0 0 495.274667 981.333333h437.525333A48.768 48.768 0 0 0 981.333333 932.437333V310.208a48.768 48.768 0 0 0-48.533333-48.874667H771.2a21.333333 21.333333 0 1 1 0-42.666666h161.578667c50.282667 0 91.2 41.066667 91.2 91.541333v622.229333C1024 982.912 983.082667 1024 932.8 1024z"
|
||||||
p-id="17758"></path>
|
p-id="5452"></path>
|
||||||
|
<path
|
||||||
|
d="M930.133333 876.394667H497.941333a21.333333 21.333333 0 0 1-21.333333-21.333334V599.786667a21.333333 21.333333 0 1 1 42.666667 0v233.941333H908.8V342.656h-121.92a21.333333 21.333333 0 1 1 0-42.666667H930.133333a21.333333 21.333333 0 0 1 21.333334 21.333334v533.738666a21.333333 21.333333 0 0 1-21.333334 21.333334zM745.770667 951.04H682.24a21.333333 21.333333 0 1 1 0-42.666667h63.530667a21.333333 21.333333 0 1 1 0 42.666667z"
|
||||||
|
p-id="5453"></path>
|
||||||
|
<path
|
||||||
|
d="M780.352 699.285333a21.269333 21.269333 0 0 1-5.973333-0.853333l-334.421334-97.621333c-13.866667 1.024-26.688 1.514667-39.104 1.514666C179.818667 602.325333 0 467.221333 0 301.162667S179.818667 0 400.832 0s400.832 135.104 400.832 301.162667c0 6.656-0.32 13.312-0.874667 19.861333-7.36 85.205333-63.552 164.522667-152.170666 216.938667l145.536 123.733333a21.312 21.312 0 0 1-13.802667 37.589333z m-338.154667-141.376c2.026667 0 4.032 0.298667 5.973334 0.853334l242.197333 70.677333-93.141333-79.168a21.312 21.312 0 0 1 4.416-35.392c91.264-44.821333 149.824-118.656 156.650666-197.482667 0.448-5.333333 0.704-10.794667 0.704-16.256C758.997333 158.634667 598.336 42.666667 400.832 42.666667 203.349333 42.666667 42.666667 158.634667 42.666667 301.162667s160.682667 258.496 358.186666 258.496c12.437333 0 25.386667-0.533333 39.658667-1.685334 0.554667-0.042667 1.130667-0.064 1.685333-0.064z"
|
||||||
|
p-id="5454"></path>
|
||||||
|
<path
|
||||||
|
d="M190.528 355.946667a77.802667 77.802667 0 0 0 39.488 11.157333c22.528 0 35.690667-11.904 35.690667-29.141333 0-15.914667-9.130667-25.066667-32.149334-33.877334-27.84-9.898667-45.056-24.32-45.056-48.362666 0-26.581333 22.016-46.314667 55.168-46.314667 17.450667 0 30.144 4.032 37.717334 8.362667l-6.08 17.962666a67.776 67.776 0 0 0-32.405334-8.106666c-23.296 0-32.128 13.930667-32.128 25.557333 0 15.957333 10.368 23.786667 33.898667 32.938667 28.864 11.114667 43.541333 25.024 43.541333 50.069333 0 26.346667-19.498667 49.130667-59.733333 49.130667-16.448 0-34.410667-4.821333-43.541333-10.88l5.589333-18.496zM462.186667 307.882667c-1.258667-23.829333-2.773333-52.394667-2.538667-73.664h-0.768a1007.829333 1007.829333 0 0 1-21.482667 64.789333l-30.144 82.773333h-16.682666l-27.584-81.237333c-8.106667-24.064-14.954667-46.08-19.754667-66.325333h-0.512c-0.490667 21.269333-1.770667 49.834667-3.285333 75.434666l-4.544 73.130667h-21.013334l11.904-170.602667h28.096l29.098667 82.517334c7.082667 21.013333 12.885333 39.722667 17.216 57.450666h0.768c4.309333-17.194667 10.389333-35.946667 17.962667-57.450666l30.378666-82.517334h28.096l10.645334 170.602667h-21.525334l-4.330666-74.901333zM518.997333 355.946667a77.76 77.76 0 0 0 39.509334 11.157333c22.506667 0 35.669333-11.904 35.669333-29.141333 0-15.914667-9.130667-25.066667-32.128-33.877334-27.882667-9.898667-45.077333-24.32-45.077333-48.362666 0-26.581333 22.037333-46.314667 55.146666-46.314667 17.450667 0 30.122667 4.032 37.738667 8.362667l-6.08 17.962666a67.776 67.776 0 0 0-32.405333-8.106666c-23.296 0-32.170667 13.930667-32.170667 25.557333 0 15.957333 10.368 23.786667 33.941333 32.938667 28.864 11.114667 43.541333 25.024 43.541334 50.069333 0 26.346667-19.477333 49.130667-59.733334 49.130667-16.448 0-34.432-4.821333-43.562666-10.88l5.610666-18.496z"
|
||||||
|
p-id="5455"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
@ -44,7 +44,6 @@ export { default as Robot } from './Robot.vue'
|
|||||||
export { default as Role } from './Role.vue'
|
export { default as Role } from './Role.vue'
|
||||||
export { default as ScheduledJob } from './ScheduledJob.vue'
|
export { default as ScheduledJob } from './ScheduledJob.vue'
|
||||||
export { default as Send } from './Send.vue'
|
export { default as Send } from './Send.vue'
|
||||||
export { default as SmsCode } from './SmsCode.vue'
|
|
||||||
export { default as Stats } from './Stats.vue'
|
export { default as Stats } from './Stats.vue'
|
||||||
export { default as Sync } from './Sync.vue'
|
export { default as Sync } from './Sync.vue'
|
||||||
export { default as Task } from './Task.vue'
|
export { default as Task } from './Task.vue'
|
||||||
@ -67,4 +66,8 @@ export { default as Collect } from './Collect.vue'
|
|||||||
export { default as FreeSql } from './FreeSql.vue'
|
export { default as FreeSql } from './FreeSql.vue'
|
||||||
export { default as Performance } from './Performance.vue'
|
export { default as Performance } from './Performance.vue'
|
||||||
export { default as Proxy } from './Proxy.vue'
|
export { default as Proxy } from './Proxy.vue'
|
||||||
export { default as ECharts } from './ECharts.vue'
|
export { default as ECharts } from './ECharts.vue'
|
||||||
|
export { default as Mobile } from './Mobile.vue'
|
||||||
|
export { default as Email } from './Email.vue'
|
||||||
|
export { default as SmsCode } from './SmsCode.vue'
|
||||||
|
export { default as MailCode } from './MailCode.vue'
|
@ -2,7 +2,7 @@
|
|||||||
<el-table-column :label="label" :prop="prop" sortable="custom">
|
<el-table-column :label="label" :prop="prop" sortable="custom">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="avatar">
|
<div class="avatar">
|
||||||
<el-avatar :src="getAvatar(scope)" size="small"></el-avatar>
|
<el-avatar :src="getAvatar(scope, prop)" size="small"></el-avatar>
|
||||||
<span>{{ tool.getNestedProperty(scope.row, prop) }}</span>
|
<span>{{ tool.getNestedProperty(scope.row, prop) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -36,8 +36,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
//获取头像
|
//获取头像
|
||||||
getAvatar(scope) {
|
getAvatar(scope, prop) {
|
||||||
return scope.row.avatar ? scope.row.avatar : this.$CONFIG.DEFAULT_AVATAR
|
return scope.row.avatar ? scope.row.avatar : this.$CONFIG.DEFAULT_AVATAR(tool.getNestedProperty(scope.row, prop))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
33
src/frontend/admin/src/components/naColId/index.vue
Normal file
33
src/frontend/admin/src/components/naColId/index.vue
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<el-table-column v-bind="$attrs">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-text @click="click(scope.row)" style="cursor: pointer" tag="ins">
|
||||||
|
{{ tool.getNestedProperty(scope.row, $attrs.prop) }}
|
||||||
|
</el-text>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import tool from '@/utils/tool'
|
||||||
|
export default {
|
||||||
|
emits: ['click'],
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
created() {},
|
||||||
|
components: {},
|
||||||
|
computed: {
|
||||||
|
tool() {
|
||||||
|
return tool
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async click(row) {
|
||||||
|
this.$emit('click', row)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
@ -2,7 +2,10 @@
|
|||||||
<el-table-column v-bind="$attrs">
|
<el-table-column v-bind="$attrs">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div @click="click(tool.getNestedProperty(scope.row, $attrs.prop))" class="avatar">
|
<div @click="click(tool.getNestedProperty(scope.row, $attrs.prop))" class="avatar">
|
||||||
<el-avatar v-if="tool.getNestedProperty(scope.row, $attrs.nestProp)" :src="getAvatar(scope)" size="small"></el-avatar>
|
<el-avatar
|
||||||
|
v-if="tool.getNestedProperty(scope.row, $attrs.nestProp)"
|
||||||
|
:src="getAvatar(scope, $attrs.nestProp)"
|
||||||
|
size="small"></el-avatar>
|
||||||
<div>
|
<div>
|
||||||
<p>{{ tool.getNestedProperty(scope.row, $attrs.nestProp) }}</p>
|
<p>{{ tool.getNestedProperty(scope.row, $attrs.nestProp) }}</p>
|
||||||
<p v-if="$attrs.nestProp2">{{ tool.getNestedProperty(scope.row, $attrs.nestProp2) }}</p>
|
<p v-if="$attrs.nestProp2">{{ tool.getNestedProperty(scope.row, $attrs.nestProp2) }}</p>
|
||||||
@ -54,8 +57,8 @@ export default {
|
|||||||
await this.$refs.saveDialog.open('view', { id: id })
|
await this.$refs.saveDialog.open('view', { id: id })
|
||||||
},
|
},
|
||||||
//获取头像
|
//获取头像
|
||||||
getAvatar(scope) {
|
getAvatar(scope, prop) {
|
||||||
return scope.row.avatar ? scope.row.avatar : this.$CONFIG.DEFAULT_AVATAR
|
return scope.row.avatar ? scope.row.avatar : this.$CONFIG.DEFAULT_AVATAR(tool.getNestedProperty(scope.row, prop))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
:layout="paginationLayout"
|
:layout="paginationLayout"
|
||||||
:page-size="scPageSize"
|
:page-size="scPageSize"
|
||||||
:page-sizes="pageSizes"
|
:page-sizes="pageSizes"
|
||||||
|
:pager-count="pagerCount"
|
||||||
:small="true"
|
:small="true"
|
||||||
:total="total"
|
:total="total"
|
||||||
@current-change="paginationChange"
|
@current-change="paginationChange"
|
||||||
@ -230,6 +231,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
pagerCount: 10,
|
||||||
current: {
|
current: {
|
||||||
row: null,
|
row: null,
|
||||||
column: null,
|
column: null,
|
||||||
@ -258,6 +260,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.pagerCount = document.body.clientWidth < 1000 ? 3 : 10
|
||||||
//判断是否开启自定义列
|
//判断是否开启自定义列
|
||||||
if (this.column) {
|
if (this.column) {
|
||||||
this.getCustomColumn()
|
this.getCustomColumn()
|
||||||
@ -309,7 +312,7 @@ export default {
|
|||||||
} catch {
|
} catch {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await this.vue.deleteRow(this.current.row)
|
await this.vue.rowDel(this.current.row)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1,5 +1,7 @@
|
|||||||
import MY_CONFIG from './myConfig'
|
import MY_CONFIG from './myConfig'
|
||||||
import APP_CONFIG from './appConfig'
|
import APP_CONFIG from './appConfig'
|
||||||
|
import avatar from '@/utils/avatar'
|
||||||
|
import tool from '@/utils/tool'
|
||||||
|
|
||||||
const DEFAULT_CONFIG = {
|
const DEFAULT_CONFIG = {
|
||||||
//标题
|
//标题
|
||||||
@ -74,8 +76,14 @@ const DEFAULT_CONFIG = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
//默认头像
|
//默认头像
|
||||||
DEFAULT_AVATAR:
|
DEFAULT_AVATAR(name) {
|
||||||
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAflJREFUeNqs1u1P2kAYAHB6B+21UmZbatEAki2+MKIR42TGaHRLjBr/Yj/7wWRb3If5gjHbfIlBjIqCUCq0PmaJLqG9IwdP+qV3vV+v1/Z5Ttg/Ke39tm+q7VD/wlBx/j0J7xzWbccL9TVgosCivrv/Atgw8yI9JuZGVXNQjCkROL2tOpc39q8/D7bj0gcy6NSQvDoTR4LwdidVhOPDyMD29/Jd9YkyFlH6pAhanjb+d19DFvHSlOHX0x09kYpGcOAFMPf0kMxJJ02ZvlyWRjhpWcJ0moiIk240Gf9Rw2lz0o92i04/Nnhpl/Hhhtqux0mnLcZrzCQUTrrV9lh/M++CFM9rtOXyvL+lOif98+T++r4Z1Ht0Vju9anDSEKXbQBqSFH0sgz6+qMGDd7Y/1J96pav1FuTPzvZvxYrrej3REOWK09l4XWkyB7Jp30RBRNwH2jf/MZMimzZi/kk5l1HFMOKnFYK/zMaDqsxqPo6QwENDtd2YtwakwOI5rJO1OZOS0/3p8VR0s2CpMqMoJzSytWAldKmrig7cQk4fMUiX+w14rPVPVvGi9qNYcVpuIP1xVM2PvaOU2sACnYwmTbJ7cHdefssqSJFeXkUYCysz8flJjcN9nf7XvFnIahi/gMCiwphMROFzVstYSu/7sWxaXczpAAL7LMAA6FWV/DBrhrIAAAAASUVORK5CYII=',
|
return (
|
||||||
|
'data:image/svg+xml,' +
|
||||||
|
encodeURIComponent(
|
||||||
|
avatar.createSVG(`#${Math.abs(tool.crypto.hashCode(name)).toString(16).substring(0, 6)}`, name.slice(0, 1).toUpperCase()).outerHTML,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//合并业务配置
|
//合并业务配置
|
||||||
|
@ -49,6 +49,7 @@ import naArea from '@/components/naArea/index.vue'
|
|||||||
import naButtonAdd from '@/components/naButtonAdd/index.vue'
|
import naButtonAdd from '@/components/naButtonAdd/index.vue'
|
||||||
import naButtonBatchDel from '@/components/naButtonBatchDel/index.vue'
|
import naButtonBatchDel from '@/components/naButtonBatchDel/index.vue'
|
||||||
import naColAvatar from '@/components/naColAvatar'
|
import naColAvatar from '@/components/naColAvatar'
|
||||||
|
import naColId from '@/components/naColId/index.vue'
|
||||||
import naColIndicator from '@/components/naColIndicator/index.vue'
|
import naColIndicator from '@/components/naColIndicator/index.vue'
|
||||||
import naColOperation from '@/components/naColOperation'
|
import naColOperation from '@/components/naColOperation'
|
||||||
import naColTags from '@/components/naColTags/index.vue'
|
import naColTags from '@/components/naColTags/index.vue'
|
||||||
@ -89,6 +90,7 @@ export default {
|
|||||||
app.component('naButtonAdd', naButtonAdd)
|
app.component('naButtonAdd', naButtonAdd)
|
||||||
app.component('naButtonBatchDel', naButtonBatchDel)
|
app.component('naButtonBatchDel', naButtonBatchDel)
|
||||||
app.component('naColAvatar', naColAvatar)
|
app.component('naColAvatar', naColAvatar)
|
||||||
|
app.component('naColId', naColId)
|
||||||
app.component('naColIndicator', naColIndicator)
|
app.component('naColIndicator', naColIndicator)
|
||||||
app.component('naColOperation', naColOperation)
|
app.component('naColOperation', naColOperation)
|
||||||
app.component('naColTags', naColTags)
|
app.component('naColTags', naColTags)
|
||||||
|
@ -132,14 +132,13 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.mobile-nav-button {
|
.mobile-nav-button {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 1rem;
|
top: 0;
|
||||||
left: 1rem;
|
left: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
background: #409eff;
|
background: var(--el-color-primary);
|
||||||
box-shadow: 0 0.2rem 1rem 0 rgba(64, 158, 255, 1);
|
box-shadow: 0 0.2rem 1rem 0 var(--el-color-primary);
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -39,7 +39,20 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-dropdown @command="handleUser" class="user panel-item" trigger="click">
|
<el-dropdown @command="handleUser" class="user panel-item" trigger="click">
|
||||||
<div class="user-avatar">
|
<div class="user-avatar">
|
||||||
<el-avatar :size="30" :src="user.avatar ? user.avatar : $CONFIG.DEFAULT_AVATAR"></el-avatar>
|
<el-avatar
|
||||||
|
:size="30"
|
||||||
|
:src="
|
||||||
|
user.avatar
|
||||||
|
? user.avatar
|
||||||
|
: 'data:image/svg+xml,' +
|
||||||
|
encodeURIComponent(
|
||||||
|
avatar.createSVG(
|
||||||
|
`#${Math.abs(this.$TOOL.crypto.hashCode(user.userName)).toString(16).substring(0, 6)}`,
|
||||||
|
user.userName.slice(0, 1).toUpperCase(),
|
||||||
|
).outerHTML,
|
||||||
|
)
|
||||||
|
"></el-avatar>
|
||||||
|
|
||||||
<label>{{ user.userName }}</label>
|
<label>{{ user.userName }}</label>
|
||||||
<el-icon class="el-icon--right">
|
<el-icon class="el-icon--right">
|
||||||
<el-icon-arrow-down />
|
<el-icon-arrow-down />
|
||||||
@ -68,7 +81,14 @@
|
|||||||
import search from './search.vue'
|
import search from './search.vue'
|
||||||
import tasks from './tasks.vue'
|
import tasks from './tasks.vue'
|
||||||
import message from '@/views/profile/message/components/list.vue'
|
import message from '@/views/profile/message/components/list.vue'
|
||||||
|
import avatar from '../../utils/avatar'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
computed: {
|
||||||
|
avatar() {
|
||||||
|
return avatar
|
||||||
|
},
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
search,
|
search,
|
||||||
tasks,
|
tasks,
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
--el-menu-horizontal-height: 4rem;
|
--el-menu-horizontal-height: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-menu--inline {
|
||||||
|
--el-menu-active-color: var(--el-color-primary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
.el-form-item--default {
|
.el-form-item--default {
|
||||||
--font-size: 1rem;
|
--font-size: 1rem;
|
||||||
}
|
}
|
||||||
@ -205,18 +209,14 @@
|
|||||||
border-left: 0;
|
border-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table.el-table--large {
|
.el-table * {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table.el-table--large * {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table.el-table--small {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-table {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-radio-button__inner {
|
.el-radio-button__inner {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
@ -47,10 +47,20 @@
|
|||||||
padding: 0 0.4rem !important;
|
padding: 0 0.4rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-pagination__jump {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.el-pagination__total,
|
.el-pagination__total,
|
||||||
.el-pagination__jump,
|
.el-pagination__jump,
|
||||||
.el-pagination__sizes {
|
.el-pagination__sizes {
|
||||||
display: none !important;
|
.el-select {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scTable-do {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
src/frontend/admin/src/utils/avatar.js
Normal file
42
src/frontend/admin/src/utils/avatar.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
export default {
|
||||||
|
//生成svg矩形
|
||||||
|
createSVG(color, name) {
|
||||||
|
const svg = document.createElement('svg')
|
||||||
|
svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
|
||||||
|
|
||||||
|
svg.setAttribute('width', 50)
|
||||||
|
svg.setAttribute('height', 50)
|
||||||
|
|
||||||
|
// <rect> background
|
||||||
|
const rect = document.createElement('rect')
|
||||||
|
rect.setAttribute('fill', color)
|
||||||
|
rect.setAttribute('x', 0)
|
||||||
|
rect.setAttribute('y', 0)
|
||||||
|
rect.setAttribute('width', '100%')
|
||||||
|
rect.setAttribute('height', '100%')
|
||||||
|
|
||||||
|
svg.appendChild(rect)
|
||||||
|
|
||||||
|
// <text> name
|
||||||
|
const text = document.createElement('text')
|
||||||
|
|
||||||
|
text.setAttribute('fill', '#fff')
|
||||||
|
text.setAttribute('x', '50%')
|
||||||
|
text.setAttribute('y', '50%')
|
||||||
|
text.setAttribute('text-anchor', 'middle')
|
||||||
|
text.setAttribute('font-size', '16')
|
||||||
|
text.setAttribute('font-weight', '900')
|
||||||
|
text.setAttribute('font-family', 'monospace')
|
||||||
|
|
||||||
|
// IE/Edge don't support alignment-baseline
|
||||||
|
// @see https://msdn.microsoft.com/en-us/library/gg558060(v=vs.85).aspx
|
||||||
|
if (document.documentMode || /Edge/.test(navigator.userAgent)) {
|
||||||
|
text.setAttribute('dy', '0.35em')
|
||||||
|
} else {
|
||||||
|
text.setAttribute('alignment-baseline', 'middle')
|
||||||
|
}
|
||||||
|
text.textContent = name
|
||||||
|
svg.appendChild(text)
|
||||||
|
return svg
|
||||||
|
},
|
||||||
|
}
|
@ -15,7 +15,9 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button :loading="isLoading" @click="login" round style="width: 100%" type="primary">{{ $t('登录') }}</el-button>
|
<el-button :loading="isLoading" @click="login" round style="width: 100%" type="primary"
|
||||||
|
>{{ starred ? $t('登录') : $t('Star 后可登录') }}
|
||||||
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="login-reg">
|
<div class="login-reg">
|
||||||
{{ $t('还没有账号?') }}
|
{{ $t('还没有账号?') }}
|
||||||
@ -28,6 +30,7 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
starred: false,
|
||||||
autoLogin: false,
|
autoLogin: false,
|
||||||
form: {
|
form: {
|
||||||
account: 'root',
|
account: 'root',
|
||||||
@ -50,6 +53,12 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async login() {
|
async login() {
|
||||||
|
if (!this.starred) {
|
||||||
|
window.open('https://github.com/nsnail/NetAdmin')
|
||||||
|
this.starred = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const validate = await this.$refs.loginForm.validate().catch(() => {})
|
const validate = await this.$refs.loginForm.validate().catch(() => {})
|
||||||
if (!validate) {
|
if (!validate) {
|
||||||
return false
|
return false
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<img alt="" src="@/assets/img/logo.png" />
|
<img alt="" src="@/assets/img/logo.png" />
|
||||||
<h2>{{ packageJson.name }}</h2>
|
<h2>{{ packageJson.name }}</h2>
|
||||||
<p>{{ ver }}</p>
|
<p>{{ ver }}</p>
|
||||||
|
<el-link href="https://github.com/nsnail/NetAdmin" target="_blank">喜欢就点个 Star⭐️ 吧!</el-link>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<el-container>
|
<el-container>
|
||||||
<el-header>
|
<el-header>
|
||||||
<div class="user-info-top">
|
<div class="user-info-top">
|
||||||
<el-avatar :size="70" :src="user.avatar ? user.avatar : $CONFIG.DEFAULT_AVATAR"></el-avatar>
|
<el-avatar :size="70" :src="user.avatar ? user.avatar : $CONFIG.DEFAULT_AVATAR(user.userName)"></el-avatar>
|
||||||
<h2>{{ user.userName }}</h2>
|
<h2>{{ user.userName }}</h2>
|
||||||
<p>
|
<p>
|
||||||
<el-tag v-for="(item, i) in user.roles" :key="i" effect="dark" round size="large">{{ item.name }}</el-tag>
|
<el-tag v-for="(item, i) in user.roles" :key="i" effect="dark" round size="large">{{ item.name }}</el-tag>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-skeleton v-if="loading" :rows="5" animated />
|
<div v-if="loading" style="padding: 1rem">
|
||||||
|
<el-skeleton :rows="5" animated />
|
||||||
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-container v-if="msgList.length > 0" class="nopadding">
|
<el-container v-if="msgList.length > 0" class="nopadding">
|
||||||
<el-header style="border: none">
|
<el-header style="border: none">
|
||||||
@ -30,9 +32,12 @@
|
|||||||
<div class="msg-title">
|
<div class="msg-title">
|
||||||
<div>
|
<div>
|
||||||
<el-badge v-if="msg.myFlags.userSiteMsgStatus === 0" is-dot type="primary">
|
<el-badge v-if="msg.myFlags.userSiteMsgStatus === 0" is-dot type="primary">
|
||||||
<el-avatar :size="40" :src="msg.sender.avatar ?? $CONFIG.DEFAULT_AVATAR"></el-avatar>
|
<el-avatar :size="40" :src="msg.sender.avatar ?? $CONFIG.DEFAULT_AVATAR(msg.sender.userName)"></el-avatar>
|
||||||
</el-badge>
|
</el-badge>
|
||||||
<el-avatar v-else :size="40" :src="msg.sender.avatar ?? $CONFIG.DEFAULT_AVATAR"></el-avatar>
|
<el-avatar
|
||||||
|
v-else
|
||||||
|
:size="40"
|
||||||
|
:src="msg.sender.avatar ?? $CONFIG.DEFAULT_AVATAR(msg.sender.userName)"></el-avatar>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h2>{{ msg.title }}</h2>
|
<h2>{{ msg.title }}</h2>
|
||||||
|
@ -39,23 +39,22 @@
|
|||||||
row-key="id"
|
row-key="id"
|
||||||
stripe>
|
stripe>
|
||||||
<el-table-column align="center" type="selection"></el-table-column>
|
<el-table-column align="center" type="selection"></el-table-column>
|
||||||
<el-table-column :label="$t('配置编号')" align="center" prop="id"></el-table-column>
|
<el-table-column :label="$t('配置编号')" align="center" prop="id" width="170"></el-table-column>
|
||||||
<el-table-column :label="$t('用户注册')" align="center">
|
<el-table-column :label="$t('用户注册')" align="center">
|
||||||
<el-table-column :label="$t('默认部门')" align="center" prop="userRegisterDept.name"></el-table-column>
|
<el-table-column :label="$t('默认部门')" align="center" prop="userRegisterDept.name" width="150"></el-table-column>
|
||||||
<el-table-column :label="$t('默认角色')" align="center" prop="userRegisterRole.name"></el-table-column>
|
<el-table-column :label="$t('默认角色')" align="center" prop="userRegisterRole.name" width="150"></el-table-column>
|
||||||
<el-table-column :label="$t('人工审核')" align="center" prop="userRegisterConfirm">
|
<el-table-column :label="$t('人工审核')" align="center" prop="userRegisterConfirm" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch v-model="scope.row.userRegisterConfirm" @change="changeSwitch($event, scope.row)"></el-switch>
|
<el-switch v-model="scope.row.userRegisterConfirm" @change="changeSwitch($event, scope.row)"></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('启用')" align="center" prop="enabled" width="100">
|
||||||
<el-table-column :label="$t('启用')" align="center" prop="enabled">
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-switch v-model="scope.row.enabled" @change="changeSwitch($event, scope.row)"></el-switch>
|
<el-switch v-model="scope.row.enabled" @change="changeSwitch($event, scope.row)"></el-switch>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('创建时间')" align="center" prop="createdTime"></el-table-column>
|
<el-table-column :label="$t('创建时间')" align="center" prop="createdTime" width="170"></el-table-column>
|
||||||
<na-col-operation
|
<na-col-operation
|
||||||
:buttons="
|
:buttons="
|
||||||
naColOperation.buttons.concat({
|
naColOperation.buttons.concat({
|
||||||
@ -66,7 +65,8 @@
|
|||||||
type: 'danger',
|
type: 'danger',
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
:vue="this" />
|
:vue="this"
|
||||||
|
width="170" />
|
||||||
</sc-table>
|
</sc-table>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
|
@ -109,20 +109,33 @@
|
|||||||
"
|
"
|
||||||
prop="httpMethod"
|
prop="httpMethod"
|
||||||
width="100" />
|
width="100" />
|
||||||
<el-table-column :label="$t('上次执行时间')" align="right" prop="lastExecTime" sortable="custom" width="120">
|
<el-table-column :label="$t('上次执行')" align="center">
|
||||||
<template #default="scope">
|
<el-table-column :label="$t('状态')" align="center" prop="lastExecTime" sortable="custom" width="150">
|
||||||
<span v-if="scope.row.lastExecTime" v-time.tip="scope.row.lastExecTime"></span>
|
<template #default="scope">
|
||||||
</template>
|
<div class="indicator">
|
||||||
|
<sc-status-indicator :type="scope.row.lastStatusCode === 'ok' ? 'success' : 'danger'" />
|
||||||
|
<span>{{
|
||||||
|
this.$GLOBAL.enums.httpStatusCodes[scope.row.lastStatusCode]
|
||||||
|
? this.$GLOBAL.enums.httpStatusCodes[scope.row.lastStatusCode][1]
|
||||||
|
: scope.row.lastStatusCode
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('时间')" align="right" prop="lastExecTime" sortable="custom" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<span v-if="scope.row.lastExecTime" v-time.tip="scope.row.lastExecTime"></span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
:formatter="(row) => (row.lastDuration ? `${tool.groupSeparator(row.lastDuration.toFixed(0))} ms` : `-`)"
|
||||||
|
:label="$t('耗时')"
|
||||||
|
align="right"
|
||||||
|
prop="lastDuration"
|
||||||
|
sortable="custom"
|
||||||
|
width="100">
|
||||||
|
</el-table-column>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<na-col-indicator
|
|
||||||
:label="$t('上次执行状态')"
|
|
||||||
:options="
|
|
||||||
Object.entries(this.$GLOBAL.enums.httpStatusCodes).map((x) => {
|
|
||||||
return { value: x[0], text: x[1][1], type: x[0] === 'ok' ? 'success' : null }
|
|
||||||
})
|
|
||||||
"
|
|
||||||
prop="lastStatusCode"
|
|
||||||
width="120" />
|
|
||||||
|
|
||||||
<el-table-column :label="$t('下次执行时间')" align="right" prop="nextExecTime" sortable="custom" width="170" />
|
<el-table-column :label="$t('下次执行时间')" align="right" prop="nextExecTime" sortable="custom" width="170" />
|
||||||
<el-table-column :label="$t('启用')" align="center" prop="enabled" sortable="custom" width="80">
|
<el-table-column :label="$t('启用')" align="center" prop="enabled" sortable="custom" width="80">
|
||||||
@ -137,15 +150,22 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<na-col-operation
|
<na-col-operation
|
||||||
:buttons="
|
:buttons="
|
||||||
naColOperation.buttons.concat({
|
naColOperation.buttons.concat(
|
||||||
icon: 'el-icon-delete',
|
{
|
||||||
confirm: true,
|
icon: 'el-icon-video-play',
|
||||||
type: 'danger',
|
click: execute,
|
||||||
title: $t('删除作业'),
|
},
|
||||||
click: rowDel,
|
{
|
||||||
})
|
icon: 'el-icon-delete',
|
||||||
|
confirm: true,
|
||||||
|
type: 'danger',
|
||||||
|
title: $t('删除作业'),
|
||||||
|
click: rowDel,
|
||||||
|
},
|
||||||
|
)
|
||||||
"
|
"
|
||||||
:vue="this" />
|
:vue="this"
|
||||||
|
width="180" />
|
||||||
</sc-table>
|
</sc-table>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
@ -162,6 +182,7 @@ import saveDialog from './save'
|
|||||||
import table from '@/config/table'
|
import table from '@/config/table'
|
||||||
import naColOperation from '@/config/naColOperation'
|
import naColOperation from '@/config/naColOperation'
|
||||||
import ScSelectFilter from '@/components/scSelectFilter/index.vue'
|
import ScSelectFilter from '@/components/scSelectFilter/index.vue'
|
||||||
|
import tool from '@/utils/tool'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -171,6 +192,7 @@ export default {
|
|||||||
inject: ['reload'],
|
inject: ['reload'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
timer: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
query: {
|
query: {
|
||||||
dynamicFilter: {
|
dynamicFilter: {
|
||||||
@ -192,6 +214,9 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
computed: {
|
computed: {
|
||||||
|
tool() {
|
||||||
|
return tool
|
||||||
|
},
|
||||||
naColOperation() {
|
naColOperation() {
|
||||||
return naColOperation
|
return naColOperation
|
||||||
},
|
},
|
||||||
@ -220,6 +245,31 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$refs.table.refresh()
|
this.$refs.table.refresh()
|
||||||
},
|
},
|
||||||
|
async execute(row) {
|
||||||
|
try {
|
||||||
|
await this.$API.sys_job.execute.post({ id: row.id })
|
||||||
|
this.$refs.table.refresh()
|
||||||
|
this.$notify.success({
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
|
message: `<div id="countdown">已发起执行请求,5 秒后弹出执行结果</div>`,
|
||||||
|
onClose: async () => {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.loading = true
|
||||||
|
this.dialog.save = true
|
||||||
|
await this.$nextTick()
|
||||||
|
await this.$refs.saveDialog.open('view', row, 1)
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
const countdown = new RegExp('\\d+').exec(document.getElementById('countdown').innerText)[0]
|
||||||
|
document.getElementById('countdown').innerText = document
|
||||||
|
.getElementById('countdown')
|
||||||
|
.innerText.replace(countdown, `${parseInt(countdown) - 1}`)
|
||||||
|
}, 1000)
|
||||||
|
} catch {}
|
||||||
|
},
|
||||||
//删除
|
//删除
|
||||||
async rowDel(row) {
|
async rowDel(row) {
|
||||||
try {
|
try {
|
||||||
|
@ -57,11 +57,36 @@
|
|||||||
row-key="id"
|
row-key="id"
|
||||||
stripe>
|
stripe>
|
||||||
<el-table-column :label="$t('唯一编码')" prop="id" sortable="custom" width="150" />
|
<el-table-column :label="$t('唯一编码')" prop="id" sortable="custom" width="150" />
|
||||||
<el-table-column :label="$t('执行耗时(毫秒)')" align="right" prop="duration" sortable="custom" width="150" />
|
<el-table-column
|
||||||
<el-table-column :label="$t('请求方法')" prop="httpMethod" sortable="custom" width="100" />
|
:formatter="(row) => `${tool.groupSeparator(row.duration.toFixed(0))} ms`"
|
||||||
<el-table-column :label="$t('HTTP 状态码')" align="right" prop="httpStatusCode" sortable="custom" width="150" />
|
:label="$t('执行耗时')"
|
||||||
|
align="right"
|
||||||
|
prop="duration"
|
||||||
|
sortable="custom"
|
||||||
|
width="150" />
|
||||||
|
<na-col-indicator
|
||||||
|
:label="$t('请求方式')"
|
||||||
|
:options="
|
||||||
|
Object.entries(this.$GLOBAL.enums.httpMethods).map((x) => {
|
||||||
|
return { value: x[0], text: x[1][1] }
|
||||||
|
})
|
||||||
|
"
|
||||||
|
prop="httpMethod"
|
||||||
|
width="100" />
|
||||||
|
<el-table-column :label="$t('响应状态码')" align="center" prop="httpStatusCode" sortable="custom" width="200">
|
||||||
|
<template #default="scope">
|
||||||
|
<div class="indicator">
|
||||||
|
<sc-status-indicator :type="scope.row.httpStatusCode === 'ok' ? 'success' : 'danger'" />
|
||||||
|
<span>{{
|
||||||
|
this.$GLOBAL.enums.httpStatusCodes[scope.row.httpStatusCode]
|
||||||
|
? this.$GLOBAL.enums.httpStatusCodes[scope.row.httpStatusCode][1]
|
||||||
|
: scope.row.httpStatusCode
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column :label="$t('请求的网络地址')" prop="requestUrl" sortable="custom" />
|
<el-table-column :label="$t('请求的网络地址')" prop="requestUrl" sortable="custom" />
|
||||||
<el-table-column :label="$t('创建时间')" prop="createdTime" sortable="custom" width="170" />
|
<el-table-column :label="$t('创建时间')" align="right" prop="createdTime" sortable="custom" width="170" />
|
||||||
<na-col-operation :buttons="[naColOperation.buttons[0]]" :vue="this" width="100" />
|
<na-col-operation :buttons="[naColOperation.buttons[0]]" :vue="this" width="100" />
|
||||||
</sc-table>
|
</sc-table>
|
||||||
</el-main>
|
</el-main>
|
||||||
@ -78,6 +103,7 @@
|
|||||||
import saveDialog from './save'
|
import saveDialog from './save'
|
||||||
import table from '@/config/table'
|
import table from '@/config/table'
|
||||||
import naColOperation from '@/config/naColOperation'
|
import naColOperation from '@/config/naColOperation'
|
||||||
|
import tool from '@/utils/tool'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['keywords'],
|
props: ['keywords'],
|
||||||
@ -101,6 +127,9 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {},
|
watch: {},
|
||||||
computed: {
|
computed: {
|
||||||
|
tool() {
|
||||||
|
return tool
|
||||||
|
},
|
||||||
naColOperation() {
|
naColOperation() {
|
||||||
return naColOperation
|
return naColOperation
|
||||||
},
|
},
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<el-form-item :label="$t('唯一编码')" prop="id"><el-input v-model="form.id" clearable /></el-form-item
|
<el-form-item :label="$t('唯一编码')" prop="id"><el-input v-model="form.id" clearable /></el-form-item
|
||||||
><el-form-item :label="$t('执行耗时(毫秒)')" prop="duration"><el-input v-model="form.duration" clearable /></el-form-item
|
><el-form-item :label="$t('执行耗时(毫秒)')" prop="duration"><el-input v-model="form.duration" clearable /></el-form-item
|
||||||
><el-form-item :label="$t('请求方法')" prop="httpMethod"><el-input v-model="form.httpMethod" clearable /></el-form-item
|
><el-form-item :label="$t('请求方法')" prop="httpMethod"><el-input v-model="form.httpMethod" clearable /></el-form-item
|
||||||
><el-form-item :label="$t('HTTP 状态码')" prop="httpStatusCode"><el-input v-model="form.httpStatusCode" clearable /></el-form-item
|
><el-form-item :label="$t('响应状态码')" prop="httpStatusCode"><el-input v-model="form.httpStatusCode" clearable /></el-form-item
|
||||||
><el-form-item :label="$t('作业编号')" prop="jobId"><el-input v-model="form.jobId" clearable /></el-form-item
|
><el-form-item :label="$t('作业编号')" prop="jobId"><el-input v-model="form.jobId" clearable /></el-form-item
|
||||||
><el-form-item :label="$t('请求体')" prop="requestBody"
|
><el-form-item :label="$t('请求体')" prop="requestBody"
|
||||||
><el-input v-model="form.requestBody" clearable rows="5" type="textarea" /></el-form-item
|
><el-input v-model="form.requestBody" clearable rows="5" type="textarea" /></el-form-item
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
<el-form-item v-if="mode === 'view'" :label="$t('上次执行时间')" prop="lastExecTime">
|
<el-form-item v-if="mode === 'view'" :label="$t('上次执行时间')" prop="lastExecTime">
|
||||||
<el-input v-model="form.lastExecTime" clearable />
|
<el-input v-model="form.lastExecTime" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-if="mode === 'view'" :label="$t('上次执行耗时(毫秒)')" prop="lastExecTime">
|
||||||
|
<el-input v-model="form.lastDuration" clearable />
|
||||||
|
</el-form-item>
|
||||||
<el-form-item v-if="mode === 'view'" :label="$t('下次执行时间')" prop="nextExecTime">
|
<el-form-item v-if="mode === 'view'" :label="$t('下次执行时间')" prop="nextExecTime">
|
||||||
<el-input v-model="form.nextExecTime" clearable />
|
<el-input v-model="form.nextExecTime" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -189,7 +192,7 @@ export default {
|
|||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {
|
methods: {
|
||||||
//显示
|
//显示
|
||||||
async open(mode = 'add', data) {
|
async open(mode = 'add', data, tabIndex = 0) {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.mode = mode
|
this.mode = mode
|
||||||
@ -198,6 +201,7 @@ export default {
|
|||||||
Object.assign(this.form, res.data)
|
Object.assign(this.form, res.data)
|
||||||
}
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
this.tabIndex = tabIndex
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user