Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
497def8055 | ||
|
|
62be26ff47 | ||
|
|
6a81d80778 | ||
|
|
60c38a8dea | ||
|
|
4e0934debf | ||
|
|
17126303fa | ||
|
|
98fa95190c | ||
|
|
3a2261107c | ||
|
|
b1b64abed9 | ||
|
|
05356b6652 | ||
|
|
cbd0c6615d | ||
|
|
90e389efa2 | ||
|
|
00a0b26797 | ||
|
|
69b5ffe3bf | ||
|
|
31539294eb | ||
|
|
d1a2307134 | ||
|
|
97b777f1b2 | ||
|
|
a63137abc9 | ||
|
|
3ca06f8d50 | ||
|
|
e5b0e202be | ||
|
|
c66385d1f7 | ||
|
|
b0304fd875 | ||
|
|
5bfc3efc9c | ||
|
|
62845cfcf1 | ||
|
|
5c536e72df | ||
|
|
7cfece1592 | ||
|
|
f393b2c9ba | ||
|
|
164f2e5472 | ||
|
|
1434ecbc2e | ||
|
|
c2e443d4ac | ||
|
|
c079125458 | ||
|
|
4c1d7b34b9 | ||
|
|
53772b3fe3 | ||
|
|
28d3c40835 | ||
|
|
a01faecd0c | ||
|
|
a1b071e38e | ||
|
|
571622a0f4 | ||
|
|
4ab84d7209 | ||
|
|
30a938e348 | ||
|
|
f6f4384e42 | ||
|
|
911b11211e | ||
|
|
8bb596c74f | ||
|
|
d0fdeb33e0 | ||
|
|
ae7f41032e | ||
|
|
f30cb6badb | ||
|
|
97a9c1e08a | ||
|
|
1e699c027d | ||
|
|
9bd731729d | ||
|
|
dc17eccf76 | ||
|
|
3649a33afb | ||
|
|
d76bcc1366 | ||
|
|
2987f1c680 | ||
|
|
ab93ee0406 | ||
|
|
69dd933a7d | ||
|
|
5440de0453 | ||
|
|
f2e130c70e | ||
|
|
4c845c26f7 | ||
|
|
a43acca375 | ||
|
|
635520aa85 | ||
|
|
fce9759e93 | ||
|
|
18243cd4b0 | ||
|
|
75a6e51e68 | ||
|
|
312edd4b15 | ||
|
|
be3e67b2c1 | ||
|
|
a5765f81fe | ||
|
|
4bee92abb0 | ||
|
|
d9dcb90745 | ||
|
|
fbd25353d5 | ||
|
|
44c3e73577 | ||
|
|
9cbad1a448 | ||
|
|
3a3ddbc2bc | ||
|
|
63a3c33df9 | ||
|
|
32d7400f7d | ||
|
|
38191f976b | ||
|
|
c380e0e110 | ||
|
|
2199b8eca7 | ||
|
|
88455604a2 | ||
|
|
63eb69091f | ||
|
|
fc668810bd | ||
|
|
2773e3a48a | ||
|
|
18a03f6ccc | ||
|
|
e9348f5512 | ||
|
|
ce65226ea4 | ||
|
|
a3b3079b63 | ||
|
|
22de4bb13b | ||
|
|
eef7bb0cad | ||
|
|
8f1fbbdeef | ||
|
|
f3562e091f | ||
|
|
2001258ef4 | ||
|
|
52a66ea304 | ||
|
|
21ddb1541f | ||
|
|
a3ec6d79b0 | ||
|
|
bb8c315ffc | ||
|
|
f2ae398d3f | ||
|
|
02e33f68b4 | ||
|
|
8c4c9d88da | ||
|
|
49cb98a606 | ||
|
|
32ab716f0d | ||
|
|
fe24529fce | ||
|
|
b59c097bca | ||
|
|
6d6414eb62 | ||
|
|
5b1c20d625 | ||
|
|
af6c8ab935 | ||
|
|
4acb5f924a | ||
|
|
b1b99f1066 | ||
|
|
004ee6f143 | ||
|
|
19455f89d3 | ||
|
|
18d98e3bd0 | ||
|
|
af038b7fc8 | ||
|
|
4a9297dc65 | ||
|
|
49fefb41a6 | ||
|
|
2fa64dfdd0 | ||
|
|
e0f777b9b4 | ||
|
|
dfe3de14d8 | ||
|
|
abe234c7ce | ||
|
|
d7bf67fd0e | ||
|
|
8218996f04 | ||
|
|
ed91e5d607 | ||
|
|
0bf0b0d381 | ||
|
|
d88559f5de | ||
|
|
f398115df3 | ||
|
|
82413fecab | ||
|
|
d5a5b24223 | ||
|
|
472dba2665 | ||
|
|
a5444b11b3 | ||
|
|
5a05a68524 | ||
|
|
36be61bbe1 | ||
|
|
ec6ab983f7 | ||
|
|
69630c2be0 | ||
|
|
8e605dd1d4 | ||
|
|
8bb0cf02ad | ||
|
|
60c054f457 | ||
|
|
5648ee974a | ||
|
|
dc4968f961 | ||
|
|
36d1370720 | ||
|
|
7ead5537f6 | ||
|
|
7fe797d44d | ||
|
|
a1e959420d | ||
|
|
4c99b40257 | ||
|
|
ead0958d18 | ||
|
|
220af8068e | ||
|
|
a1730b2d52 | ||
|
|
1a1d6c0835 | ||
|
|
06cbffdea4 | ||
|
|
c45e1faf42 | ||
|
|
732d42f174 | ||
|
|
524fde99f8 | ||
|
|
649246dc6a | ||
|
|
6c7ac25388 | ||
|
|
cb1d6ddeec | ||
|
|
58313889ee | ||
|
|
5ebc62a084 | ||
|
|
fcba384a15 | ||
|
|
3ea95ffa48 | ||
|
|
898fd36eca | ||
|
|
6cd88fb98f | ||
|
|
396de72c5d | ||
|
|
9932d60dee | ||
|
|
1ad93ce1fd | ||
|
|
2041513676 | ||
|
|
3ea1a2bf2f | ||
|
|
2b81ebca8e | ||
|
|
27df97d710 | ||
|
|
a25b7b9b3f | ||
|
|
de9809ca5a | ||
|
|
8504c181c0 | ||
|
|
8a005ffb00 | ||
|
|
80ffa7a577 | ||
|
|
ca8f9a7e4a | ||
|
|
8d19d78297 | ||
|
|
483e5eb85a | ||
|
|
a4b4f491d2 | ||
|
|
08093f509a | ||
|
|
9a96223d12 | ||
|
|
0c2b194444 | ||
|
|
a06055168f | ||
|
|
e04546a9ae | ||
|
|
f6da1a045d | ||
|
|
acd386bb09 | ||
|
|
45225c0ce1 | ||
|
|
0bd884d309 | ||
|
|
aea2ae8d79 | ||
|
|
99ec5ab161 | ||
|
|
4431e7470f | ||
|
|
ed775405c6 | ||
|
|
4aefbe5aa8 | ||
|
|
786c467464 | ||
|
|
50182ef940 | ||
|
|
bf3aa2df09 | ||
|
|
0b744a2599 | ||
|
|
a75b8b40e2 | ||
|
|
2e23c08608 | ||
|
|
178f45ee26 | ||
|
|
7b16edc99c | ||
|
|
f3738a1630 | ||
|
|
34fa65132d | ||
|
|
19fe2d2f03 | ||
|
|
c796af7d07 | ||
|
|
b7251e2be2 | ||
|
|
6efede79c7 | ||
|
|
e58da80f8e | ||
|
|
bd556c33a0 | ||
|
|
878809ecb4 | ||
|
|
ea4966f494 | ||
|
|
f5d9b478d5 | ||
|
|
3d97fab16d | ||
|
|
af2ae11eb1 | ||
|
|
2c1fc30bfb | ||
|
|
5aa4199dfb | ||
|
|
773790c8ec | ||
|
|
c7dec8045e | ||
|
|
5d7d12415c | ||
|
|
8a066163fe | ||
|
|
08e57936fc | ||
|
|
7d474e17fa | ||
|
|
6eac25425c | ||
|
|
c0f1981d6f | ||
|
|
d3571942d7 | ||
|
|
8376b6f0f2 | ||
|
|
490a66d3fe | ||
|
|
2e182626b9 | ||
|
|
66f5f8ab12 | ||
|
|
50ecee99cc | ||
|
|
fc3f982309 | ||
|
|
b8e9aded6b | ||
|
|
74ce9f7a86 | ||
|
|
5b2957e7eb | ||
|
|
55a464f1f6 | ||
|
|
72ec6beb99 | ||
|
|
40eb4ea4ec | ||
|
|
895f3d9cb3 | ||
|
|
ae758da449 | ||
|
|
a8f06f5718 | ||
|
|
c458a1b59a | ||
|
|
29d59b3974 | ||
|
|
27f267cb3d | ||
|
|
0f41039b99 | ||
|
|
8f76db9e41 | ||
|
|
fc922e996c | ||
|
|
0a26ad8925 | ||
|
|
a8c6c7cb36 | ||
|
|
81fee53085 | ||
|
|
7c5f2d95a4 | ||
|
|
3d6bd0e23e | ||
|
|
8064e84276 | ||
|
|
f8ece2d984 | ||
|
|
442eef36ba | ||
|
|
7d737ad312 | ||
|
|
6142d325c8 | ||
|
|
aa21aa686d | ||
|
|
ec2719a572 | ||
|
|
a466126d63 | ||
|
|
568f322a25 | ||
|
|
1b64959e2c |
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
name: Bug 报告(Bug Report)
|
||||||
|
about: 反馈项目中的缺陷或问题
|
||||||
|
title: "[Bug] 简短描述问题"
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 问题描述
|
||||||
|
<!-- 清晰简洁地描述问题是什么 -->
|
||||||
|
|
||||||
|
## 🔍 复现步骤
|
||||||
|
<!-- 详细描述复现问题的步骤 -->
|
||||||
|
1. 打开 '...'
|
||||||
|
2. 点击 '...'
|
||||||
|
3. 滚动到 '...'
|
||||||
|
4. 看到错误
|
||||||
|
|
||||||
|
## 🤔 预期行为
|
||||||
|
<!-- 简要描述预期的正确行为 -->
|
||||||
|
|
||||||
|
## 😯 截图
|
||||||
|
<!-- 如果适用,添加问题的截图 -->
|
||||||
|
|
||||||
|
## 🖥️ 环境信息
|
||||||
|
- 操作系统: [例如 Windows 10]
|
||||||
|
- 浏览器: [例如 Chrome 89]
|
||||||
|
- 项目版本: [例如 1.0.0]
|
||||||
|
- Python版本: [例如 3.9.13]
|
||||||
|
- Jdk版本:[例如 java 21.0.5 2024-10-15 LTS]
|
||||||
|
- Nodejs版本:[例如 v20.14.0]
|
||||||
|
|
||||||
|
## 📋 其他信息
|
||||||
|
<!-- 在此添加关于此问题的任何其他上下文信息 -->
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
name: 代码优化建议(Code Improvement)
|
||||||
|
about: 提出对现有代码的优化或改进建议
|
||||||
|
title: "[Improvement] 简短描述改进内容"
|
||||||
|
labels: refactor
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 改进描述
|
||||||
|
<!-- 描述需要改进的代码部分以及存在的问题 -->
|
||||||
|
|
||||||
|
## 🌟 改进建议
|
||||||
|
<!-- 提出具体的改进方案或思路 -->
|
||||||
|
|
||||||
|
## 🛠️ 相关代码
|
||||||
|
<!-- 如果可能,提供相关代码片段或链接 -->
|
||||||
|
|
||||||
|
## 📋 其他信息
|
||||||
|
<!-- 在此添加任何其他相关信息 -->
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
name: 文档改进建议(Documentation Improvement)
|
||||||
|
about: 提出对项目文档的改进或补充建议
|
||||||
|
title: "[Docs] 简短描述改进内容"
|
||||||
|
labels: documentation
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 改进描述
|
||||||
|
<!-- 描述需要改进的文档部分以及存在的问题 -->
|
||||||
|
|
||||||
|
## ✨ 改进建议
|
||||||
|
<!-- 提出具体的改进方案或内容 -->
|
||||||
|
|
||||||
|
## 📋 其他信息
|
||||||
|
<!-- 在此添加任何其他相关信息 -->
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
name: 功能请求(Feature Request)
|
||||||
|
about: 提出新的功能或改进建议
|
||||||
|
title: "[Feature] 简短描述功能"
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 需求描述
|
||||||
|
<!-- 清晰简洁地描述你希望发生什么 -->
|
||||||
|
|
||||||
|
## 🎯 解决方案
|
||||||
|
<!-- 描述你认为可行的解决方案或实现方式 -->
|
||||||
|
|
||||||
|
## 📝 备选方案
|
||||||
|
<!-- 描述你考虑过的替代方案或功能 -->
|
||||||
|
|
||||||
|
## 📋 其他信息
|
||||||
|
<!-- 在此添加关于需求的任何其他上下文信息 -->
|
||||||
@@ -141,13 +141,18 @@ music/
|
|||||||
# Cython debug symbols
|
# Cython debug symbols
|
||||||
cython_debug/
|
cython_debug/
|
||||||
*.iml
|
*.iml
|
||||||
model.pt
|
|
||||||
tmp
|
tmp
|
||||||
|
.history
|
||||||
.DS_Store
|
.DS_Store
|
||||||
main/xiaozhi-server/data
|
main/xiaozhi-server/data
|
||||||
|
main/xiaozhi-server/config/assets/wakeup_words.*
|
||||||
main/manager-web/node_modules
|
main/manager-web/node_modules
|
||||||
.config.yaml
|
.config.yaml
|
||||||
.secrets.yaml
|
.secrets.yaml
|
||||||
.private_config.yaml
|
.private_config.yaml
|
||||||
.env.development
|
.env.development
|
||||||
|
|
||||||
|
# model files
|
||||||
|
main/xiaozhi-server/models/SenseVoiceSmall/model.pt
|
||||||
|
main/xiaozhi-server/models/sherpa-onnx*
|
||||||
|
my_wakeup_words.mp3
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ WORKDIR /app
|
|||||||
|
|
||||||
COPY main/xiaozhi-server/requirements.txt .
|
COPY main/xiaozhi-server/requirements.txt .
|
||||||
|
|
||||||
# 优化apt安装
|
# 安装Python依赖
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# 第三阶段:生产镜像
|
# 第二阶段:生产镜像
|
||||||
FROM python:3.10-slim
|
FROM python:3.10-slim
|
||||||
|
|
||||||
WORKDIR /opt/xiaozhi-esp32-server
|
WORKDIR /opt/xiaozhi-esp32-server
|
||||||
|
|
||||||
# 优化apt安装
|
# 安装系统依赖
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends libopus0 ffmpeg && \
|
apt-get install -y --no-install-recommends libopus0 ffmpeg && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
|
|||||||
@@ -51,12 +51,19 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://www.bilibili.com/video/av114036381327149" target="_blank">
|
<a href="https://www.bilibili.com/video/BV1pNXWYGEx1" target="_blank">
|
||||||
<picture>
|
<picture>
|
||||||
<img alt="控制家电开关" src="docs/images/demo5.png" />
|
<img alt="控制家电开关" src="docs/images/demo5.png" />
|
||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://www.bilibili.com/video/BV1kgA2eYEQ9" target="_blank">
|
||||||
|
<picture>
|
||||||
|
<img alt="成本最低配置" src="docs/images/demo4.png" />
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@@ -74,13 +81,25 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="https://www.bilibili.com/video/BV1kgA2eYEQ9" target="_blank">
|
<a href="https://www.bilibili.com/video/BV1Z8XuYZEAS" target="_blank">
|
||||||
<picture>
|
<picture>
|
||||||
<img alt="成本最低配置" src="docs/images/demo4.png" />
|
<img alt="天气插件" src="docs/images/demo8.png" />
|
||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
<a href="https://www.bilibili.com/video/BV178XuYfEpi" target="_blank">
|
||||||
|
<picture>
|
||||||
|
<img alt="IOT指令控制设备" src="docs/images/demo9.png" />
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="https://www.bilibili.com/video/BV17LXWYvENb" target="_blank">
|
||||||
|
<picture>
|
||||||
|
<img alt="播报新闻" src="docs/images/demo0.png" />
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@@ -92,14 +111,18 @@
|
|||||||
- **硬件**:一套兼容 `xiaozhi-esp32`
|
- **硬件**:一套兼容 `xiaozhi-esp32`
|
||||||
的硬件设备(具体型号请参考 [此处](https://rcnv1t9vps13.feishu.cn/wiki/DdgIw4BUgivWDPkhMj1cGIYCnRf))。
|
的硬件设备(具体型号请参考 [此处](https://rcnv1t9vps13.feishu.cn/wiki/DdgIw4BUgivWDPkhMj1cGIYCnRf))。
|
||||||
|
|
||||||
- **电脑或服务器**:至少 4 核 CPU、8G 内存的电脑。
|
- **电脑或服务器**:建议 4 核 CPU、8G 内存的电脑。如果开启ASR也使用API,可运行在2核CPU、2G内存的服务器中。
|
||||||
- **固件编译**:请将本后端服务的接口地址更新至 `xiaozhi-esp32` 项目中,再重新编译`xiaozhi-esp32`固件并烧录到设备上。
|
- **固件编译**:请将本后端服务的接口地址更新至 `xiaozhi-esp32` 项目中,再重新编译`xiaozhi-esp32`固件并烧录到设备上。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
如果你没有esp32相关的硬件设备,但是非常想体验该项目,可以使用以下的项目让你的电脑、手机模拟成esp32设备。
|
如果你没有esp32相关的硬件设备,但是非常想体验该项目,可以使用以下的项目让你的电脑、手机模拟成esp32设备。
|
||||||
|
|
||||||
- [小智安卓端](https://github.com/TOM88812/xiaozhi-android-client)
|
- [小智安卓端](https://github.com/TOM88812/xiaozhi-android-client)
|
||||||
- [小智电脑端](https://github.com/Huang-junsen/py-xiaozhi)
|
- [小智电脑端](https://github.com/Huang-junsen/py-xiaozhi)
|
||||||
|
|
||||||
|
如果你是一名软件开发者,这里有一份[《致开发者的公开信》](docs/contributor_open_letter.md),欢迎加入!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 警告 ⚠️
|
## 警告 ⚠️
|
||||||
@@ -139,12 +162,15 @@ server:
|
|||||||
支持 EdgeTTS(默认)、火山引擎豆包 TTS 等多种 TTS 接口,满足语音合成需求。
|
支持 EdgeTTS(默认)、火山引擎豆包 TTS 等多种 TTS 接口,满足语音合成需求。
|
||||||
- **记忆功能**
|
- **记忆功能**
|
||||||
支持超长记忆、本地总结记忆、无记忆三种模式,满足不同场景需求。
|
支持超长记忆、本地总结记忆、无记忆三种模式,满足不同场景需求。
|
||||||
|
- **IOT功能**
|
||||||
|
支持管理注册设备IOT功能,支持基于对话上下文语境下的智能物联网控制。
|
||||||
|
|
||||||
### 正在开发 🚧
|
### 正在开发 🚧
|
||||||
|
|
||||||
- 多种心情模式
|
- 多种心情模式
|
||||||
- 智控台webui
|
- 智控台webui
|
||||||
- iot功能
|
|
||||||
|
想了解具体开发进度,[请点击这里](https://github.com/users/xinnan-tech/projects/3)
|
||||||
|
|
||||||

|

|
||||||
---
|
---
|
||||||
@@ -164,7 +190,6 @@ server:
|
|||||||
| LLM | FastgptLLM | fastgpt 接口调用 | 免费/消耗 token | 本地化部署,注意配置提示词需在 Fastgpt 控制台设置 |
|
| LLM | FastgptLLM | fastgpt 接口调用 | 免费/消耗 token | 本地化部署,注意配置提示词需在 Fastgpt 控制台设置 |
|
||||||
| LLM | GeminiLLM | gemini 接口调用 | 免费 | [点击申请密钥](https://aistudio.google.com/apikey) |
|
| LLM | GeminiLLM | gemini 接口调用 | 免费 | [点击申请密钥](https://aistudio.google.com/apikey) |
|
||||||
| LLM | CozeLLM | coze 接口调用 | 消耗 token | 需提供 bot_id、user_id 及个人令牌 |
|
| LLM | CozeLLM | coze 接口调用 | 消耗 token | 需提供 bot_id、user_id 及个人令牌 |
|
||||||
| LLM | Home Assistant | homeassistant语音助手接口调用 | 免费 | 需提供home assistant令牌 |
|
|
||||||
|
|
||||||
实际上,任何支持 openai 接口调用的 LLM 均可接入使用。
|
实际上,任何支持 openai 接口调用的 LLM 均可接入使用。
|
||||||
|
|
||||||
@@ -180,6 +205,7 @@ server:
|
|||||||
| TTS | CosyVoiceSiliconflow | 接口调用 | 消耗 token | 需申请硅基流动 API 密钥;输出格式为 wav |
|
| TTS | CosyVoiceSiliconflow | 接口调用 | 消耗 token | 需申请硅基流动 API 密钥;输出格式为 wav |
|
||||||
| TTS | TTS302AI | 接口调用 | 消耗 token | [点击创建密钥](https://dash.302.ai/apis/list) |
|
| TTS | TTS302AI | 接口调用 | 消耗 token | [点击创建密钥](https://dash.302.ai/apis/list) |
|
||||||
| TTS | CozeCnTTS | 接口调用 | 消耗 token | 需提供 Coze API key;输出格式为 wav |
|
| TTS | CozeCnTTS | 接口调用 | 消耗 token | 需提供 Coze API key;输出格式为 wav |
|
||||||
|
| TTS | GizwitsTTS | 接口调用 | 消耗 token | [点击创建密钥](https://agentrouter.gizwitsapi.com) |
|
||||||
| TTS | ACGNTTS | 接口调用 | 消耗 token | [联系网站管理员购买密钥](www.ttson.cn) |
|
| TTS | ACGNTTS | 接口调用 | 消耗 token | [联系网站管理员购买密钥](www.ttson.cn) |
|
||||||
| TTS | OpenAITTS | 接口调用 | 消耗 token | 境外使用,境外购买 |
|
| TTS | OpenAITTS | 接口调用 | 消耗 token | 境外使用,境外购买 |
|
||||||
| TTS | FishSpeech | 接口调用 | 免费/自定义 | 本地启动 TTS 服务;启动方法见配置文件内说明 |
|
| TTS | FishSpeech | 接口调用 | 免费/自定义 | 本地启动 TTS 服务;启动方法见配置文件内说明 |
|
||||||
@@ -202,16 +228,18 @@ server:
|
|||||||
| 类型 | 平台名称 | 使用方式 | 收费模式 | 备注 |
|
| 类型 | 平台名称 | 使用方式 | 收费模式 | 备注 |
|
||||||
|:---:|:---------:|:----:|:----:|:--:|
|
|:---:|:---------:|:----:|:----:|:--:|
|
||||||
| ASR | FunASR | 本地使用 | 免费 | |
|
| ASR | FunASR | 本地使用 | 免费 | |
|
||||||
|
| ASR | SherpaASR | 本地使用 | 免费 | |
|
||||||
| ASR | DoubaoASR | 接口调用 | 收费 | |
|
| ASR | DoubaoASR | 接口调用 | 收费 | |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Memory 记忆存储
|
### Memory 记忆存储
|
||||||
|
|
||||||
| 类型 | 平台名称 | 使用方式 | 收费模式 | 备注 |
|
| 类型 | 平台名称 | 使用方式 | 收费模式 | 备注 |
|
||||||
|:------:|:---------------:|:----:|:--------:|:--:|
|
|:------:|:---------------:|:----:|:---------:|:--:|
|
||||||
| Memory | mem0ai | 接口调用 | 100次/月额度 | |
|
| Memory | mem0ai | 接口调用 | 1000次/月额度 | |
|
||||||
| Memory | mem_local_short | 本地总结 | 免费 | |
|
| Memory | mem_local_short | 本地总结 | 免费 | |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -230,14 +258,9 @@ server:
|
|||||||
|
|
||||||
本项目支持以下三种部署方式,您可根据实际需求选择。
|
本项目支持以下三种部署方式,您可根据实际需求选择。
|
||||||
|
|
||||||
本项目的文档主要是`文字版本`的教程,如果你想要`视频版本`
|
|
||||||
的教程,您可以学习一下[这个大佬的手把手教程](https://www.bilibili.com/video/BV1gePuejEvT)。
|
|
||||||
|
|
||||||
如果你能把`文字版本的教程`和`视频版本的教程`结合起来一起看,可以让你更快上手。
|
|
||||||
|
|
||||||
1. [Docker 快速部署](./docs/Deployment.md)
|
1. [Docker 快速部署](./docs/Deployment.md)
|
||||||
|
|
||||||
适合快速体验的普通用户,不需过多环境配置。缺点是,拉取镜像有点慢。
|
适合快速体验的普通用户,不需过多环境配置。缺点是,拉取镜像有点慢。视频教程可参考[美女大佬教你Docker部署](https://www.bilibili.com/video/BV1RNQnYDE5t)
|
||||||
|
|
||||||
2. [借助 Docker 环境运行部署](./docs/Deployment.md#%E6%96%B9%E5%BC%8F%E4%BA%8C%E5%80%9F%E5%8A%A9docker%E7%8E%AF%E5%A2%83%E8%BF%90%E8%A1%8C%E9%83%A8%E7%BD%B2)
|
2. [借助 Docker 环境运行部署](./docs/Deployment.md#%E6%96%B9%E5%BC%8F%E4%BA%8C%E5%80%9F%E5%8A%A9docker%E7%8E%AF%E5%A2%83%E8%BF%90%E8%A1%8C%E9%83%A8%E7%BD%B2)
|
||||||
|
|
||||||
@@ -247,7 +270,7 @@ server:
|
|||||||
|
|
||||||
适合熟悉`Conda` 环境或希望从零搭建运行环境的用户。
|
适合熟悉`Conda` 环境或希望从零搭建运行环境的用户。
|
||||||
|
|
||||||
对于对响应速度要求较高的场景,推荐使用本地源码运行方式以降低额外开销。
|
对于对响应速度要求较高的场景,推荐使用本地源码运行方式以降低额外开销。视频教程可参考[帅哥大佬教你源码部署](https://www.bilibili.com/video/BV1GvQWYZEd2)
|
||||||
|
|
||||||
### 二、[固件编译](./docs/firmware-build.md)
|
### 二、[固件编译](./docs/firmware-build.md)
|
||||||
|
|
||||||
@@ -351,7 +374,41 @@ VAD:
|
|||||||
|
|
||||||
### 6、我想通过小智控制电灯、空调、远程开关机等操作 💡
|
### 6、我想通过小智控制电灯、空调、远程开关机等操作 💡
|
||||||
|
|
||||||
建议:在配置文件中将 `LLM` 设置为 `HomeAssistant`,通过 调用`HomeAssistant`接口实现相关控制。
|
本项目,支持以工具调用的方式控制HomeAssistant设备
|
||||||
|
|
||||||
|
1、首先选择一款支持function call支持的LLM,例如`ChatGLMLLM`。
|
||||||
|
|
||||||
|
2、在配置文件中,将 `selected_module.Intent` 设置为 `function_call`。
|
||||||
|
|
||||||
|
3、登录`HomeAssistant`,点击`左下角个人`,切换`安全`导航栏,划到底部`长期访问令牌`生成api_key。
|
||||||
|
|
||||||
|
在配置文件中,配置好你的home assistant的`devices`(被控制的设备)和`api_key`和`base_url`等信息。例如:
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
plugins
|
||||||
|
home_assistant:
|
||||||
|
devices:
|
||||||
|
- 客厅,玩具灯,switch.cuco_cn_460494544_cp1_on_p_2_1
|
||||||
|
- 卧室,台灯,switch.iot_cn_831898993_socn1_on_p_2_1
|
||||||
|
base_url: http://你的homeassistant地址:8123
|
||||||
|
api_key: 你的home assistant api访问令牌
|
||||||
|
```
|
||||||
|
|
||||||
|
最后,允许function_call 插件在配置文件中启用`hass_get_state`(必须)、`hass_set_state`(必须)、`hass_play_music`(不想用ha听音乐可以不启动),例如:
|
||||||
|
|
||||||
|
``` yaml
|
||||||
|
Intent:
|
||||||
|
...
|
||||||
|
function_call:
|
||||||
|
type: nointent
|
||||||
|
functions:
|
||||||
|
- change_role
|
||||||
|
- get_weather
|
||||||
|
- get_news
|
||||||
|
- hass_get_state
|
||||||
|
- hass_set_state
|
||||||
|
- hass_play_music
|
||||||
|
```
|
||||||
|
|
||||||
### 7、更多问题,可联系我们反馈 💬
|
### 7、更多问题,可联系我们反馈 💬
|
||||||
|
|
||||||
@@ -376,4 +433,4 @@ VAD:
|
|||||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=xinnan-tech/xiaozhi-esp32-server&type=Date" />
|
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=xinnan-tech/xiaozhi-esp32-server&type=Date" />
|
||||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=xinnan-tech/xiaozhi-esp32-server&type=Date" />
|
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=xinnan-tech/xiaozhi-esp32-server&type=Date" />
|
||||||
</picture>
|
</picture>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ In fact, any LLM that supports OpenAI API calls can be integrated.
|
|||||||
| Type | Platform Name | Usage Method | Pricing Model | Remarks |
|
| Type | Platform Name | Usage Method | Pricing Model | Remarks |
|
||||||
|:----:|:-------------------:|:------------:|:-------------:|:-------:|
|
|:----:|:-------------------:|:------------:|:-------------:|:-------:|
|
||||||
| ASR | FunASR | Local | Free | |
|
| ASR | FunASR | Local | Free | |
|
||||||
|
| ASR | SherpaASR | Local | Free | |
|
||||||
| ASR | DoubaoASR | API call | Paid | |
|
| ASR | DoubaoASR | API call | Paid | |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# 本文件是用于一键自动下载本项目所需文件,自动创建好目录
|
||||||
|
# 所需条件(否则无法使用):
|
||||||
|
# 1、请确保你的环境可以正常访问 GitHub 否则无法下载脚本
|
||||||
|
#
|
||||||
|
# 检测操作系统类型
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Linux*) OS=Linux;;
|
||||||
|
Darwin*) OS=Mac;;
|
||||||
|
CYGWIN*) OS=Windows;;
|
||||||
|
MINGW*) OS=Windows;;
|
||||||
|
MSYS*) OS=Windows;;
|
||||||
|
*) OS=UNKNOWN;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# 设置颜色(Windows CMD 不支持,但不影响使用)
|
||||||
|
if [ "$OS" = "Windows" ]; then
|
||||||
|
GREEN=""
|
||||||
|
RED=""
|
||||||
|
NC=""
|
||||||
|
else
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m'
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${GREEN}开始安装小智服务端...${NC}"
|
||||||
|
|
||||||
|
# 创建必要的目录
|
||||||
|
echo "创建目录结构..."
|
||||||
|
mkdir -p xiaozhi-server/data xiaozhi-server/models/SenseVoiceSmall
|
||||||
|
cd xiaozhi-server || exit
|
||||||
|
|
||||||
|
# 根据操作系统选择下载命令
|
||||||
|
if [ "$OS" = "Windows" ]; then
|
||||||
|
DOWNLOAD_CMD="curl -L -o"
|
||||||
|
if ! command -v curl >/dev/null 2>&1; then
|
||||||
|
DOWNLOAD_CMD="powershell -Command Invoke-WebRequest -Uri"
|
||||||
|
DOWNLOAD_CMD_SUFFIX="-OutFile"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if command -v curl >/dev/null 2>&1; then
|
||||||
|
DOWNLOAD_CMD="curl -L -o"
|
||||||
|
elif command -v wget >/dev/null 2>&1; then
|
||||||
|
DOWNLOAD_CMD="wget -O"
|
||||||
|
else
|
||||||
|
echo "${RED}错误: 需要安装 curl 或 wget${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 下载语音识别模型
|
||||||
|
echo "下载语音识别模型..."
|
||||||
|
if [ "$DOWNLOAD_CMD" = "powershell -Command Invoke-WebRequest -Uri" ]; then
|
||||||
|
$DOWNLOAD_CMD "https://modelscope.cn/models/iic/SenseVoiceSmall/resolve/master/model.pt" $DOWNLOAD_CMD_SUFFIX "models/SenseVoiceSmall/model.pt"
|
||||||
|
else
|
||||||
|
$DOWNLOAD_CMD "models/SenseVoiceSmall/model.pt" "https://modelscope.cn/models/iic/SenseVoiceSmall/resolve/master/model.pt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "${RED}模型下载失败。请手动从以下地址下载:${NC}"
|
||||||
|
echo "1. https://modelscope.cn/models/iic/SenseVoiceSmall/resolve/master/model.pt"
|
||||||
|
echo "2. 百度网盘: https://pan.baidu.com/share/init?surl=QlgM58FHhYv1tFnUT_A8Sg (提取码: qvna)"
|
||||||
|
echo "下载后请将文件放置在 models/SenseVoiceSmall/model.pt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 下载配置文件
|
||||||
|
echo "下载配置文件..."
|
||||||
|
if [ "$DOWNLOAD_CMD" = "powershell -Command Invoke-WebRequest -Uri" ]; then
|
||||||
|
$DOWNLOAD_CMD "https://raw.githubusercontent.com/xinnan-tech/xiaozhi-esp32-server/main/main/xiaozhi-server/docker-compose.yml" $DOWNLOAD_CMD_SUFFIX "docker-compose.yml"
|
||||||
|
$DOWNLOAD_CMD "https://raw.githubusercontent.com/xinnan-tech/xiaozhi-esp32-server/main/main/xiaozhi-server/config.yaml" $DOWNLOAD_CMD_SUFFIX "data/.config.yaml"
|
||||||
|
else
|
||||||
|
$DOWNLOAD_CMD "docker-compose.yml" "https://raw.githubusercontent.com/xinnan-tech/xiaozhi-esp32-server/main/main/xiaozhi-server/docker-compose.yml"
|
||||||
|
$DOWNLOAD_CMD "data/.config.yaml" "https://raw.githubusercontent.com/xinnan-tech/xiaozhi-esp32-server/main/main/xiaozhi-server/config.yaml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查文件是否存在
|
||||||
|
echo "检查文件完整性..."
|
||||||
|
FILES_TO_CHECK="docker-compose.yml data/.config.yaml models/SenseVoiceSmall/model.pt"
|
||||||
|
ALL_FILES_EXIST=true
|
||||||
|
|
||||||
|
for FILE in $FILES_TO_CHECK; do
|
||||||
|
if [ ! -f "$FILE" ]; then
|
||||||
|
echo "${RED}错误: $FILE 不存在${NC}"
|
||||||
|
ALL_FILES_EXIST=false
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$ALL_FILES_EXIST" = false ]; then
|
||||||
|
echo "${RED}某些文件下载失败,请检查上述错误信息并手动下载缺失的文件。${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${GREEN}文件下载完成!${NC}"
|
||||||
|
echo "请编辑 data/.config.yaml 文件配置你的API密钥。"
|
||||||
|
echo "配置完成后,运行以下命令启动服务:"
|
||||||
|
echo "${GREEN}docker-compose up -d${NC}"
|
||||||
|
echo "查看日志请运行:"
|
||||||
|
echo "${GREEN}docker logs -f xiaozhi-esp32-server${NC}"
|
||||||
|
|
||||||
|
# 提示用户编辑配置文件
|
||||||
|
echo "\n${RED}重要提示:${NC}"
|
||||||
|
echo "1. 请确保编辑 data/.config.yaml 文件,配置必要的API密钥"
|
||||||
|
echo "2. 特别是 ChatGLM 和 mem0ai 的密钥必须配置"
|
||||||
|
echo "3. 配置完成后再启动 docker 服务"
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# 部署方案参考
|
||||||
|

|
||||||
# 方式一:docker快速部署
|
# 方式一:docker快速部署
|
||||||
|
|
||||||
docker镜像已支持x86架构、arm64架构的CPU,支持在国产操作系统上运行。
|
docker镜像已支持x86架构、arm64架构的CPU,支持在国产操作系统上运行。
|
||||||
@@ -6,7 +8,45 @@ docker镜像已支持x86架构、arm64架构的CPU,支持在国产操作系统
|
|||||||
|
|
||||||
如果您的电脑还没安装docker,可以按照这里的教程安装:[docker安装](https://www.runoob.com/docker/ubuntu-docker-install.html)
|
如果您的电脑还没安装docker,可以按照这里的教程安装:[docker安装](https://www.runoob.com/docker/ubuntu-docker-install.html)
|
||||||
|
|
||||||
## 2. 创建目录
|
如果你已经安装好docker,你可以[1.1使用懒人脚本](#11-懒人脚本)自动帮你下载所需的文件和配置文件,你可以使用docker[1.2手动部署](#12-手动部署)。
|
||||||
|
|
||||||
|
### 1.1 懒人脚本
|
||||||
|
|
||||||
|
你可以使用以下命令一键下载并执行部署脚本:
|
||||||
|
请确保你的环境可以正常访问 GitHub 否则无法下载脚本。
|
||||||
|
```bash
|
||||||
|
curl -L -o docker-setup.sh https://raw.githubusercontent.com/xinnan-tech/xiaozhi-esp32-server/main/docker-setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
如果您的电脑是windows系统,请使用使用 Git Bash、WSL、PowerShell 或 CMD 运行以下命令:
|
||||||
|
```bash
|
||||||
|
# Git Bash 或 WSL
|
||||||
|
sh docker-setup.sh
|
||||||
|
# PowerShell 或 CMD
|
||||||
|
.\docker-setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
如果您的电脑是linux 或者 macos 系统,请使用终端运行以下命令:
|
||||||
|
```bash
|
||||||
|
chmod +x docker-setup.sh
|
||||||
|
./docker-setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
脚本会自动完成以下操作:
|
||||||
|
> 1. 创建必要的目录结构
|
||||||
|
> 2. 下载语音识别模型
|
||||||
|
> 3. 下载配置文件
|
||||||
|
> 4. 检查文件完整性
|
||||||
|
>
|
||||||
|
> 执行完成后,请按照提示配置 API 密钥。
|
||||||
|
|
||||||
|
当你一切顺利完成以上操作后,继续操作[配置项目文件](#3-配置项目文件)
|
||||||
|
|
||||||
|
### 1.2 手动部署
|
||||||
|
|
||||||
|
如果懒人脚本无法正常运行,请按本章节1.2进行手动部署。
|
||||||
|
|
||||||
|
#### 1.2.1 创建目录
|
||||||
|
|
||||||
安装完后,你需要为这个项目找一个安放配置文件的目录,例如我们可以新建一个文件夹叫`xiaozhi-server`。
|
安装完后,你需要为这个项目找一个安放配置文件的目录,例如我们可以新建一个文件夹叫`xiaozhi-server`。
|
||||||
|
|
||||||
@@ -21,14 +61,18 @@ xiaozhi-server
|
|||||||
├─ SenseVoiceSmall
|
├─ SenseVoiceSmall
|
||||||
```
|
```
|
||||||
|
|
||||||
## 4. 下载语音识别模型文件
|
#### 1.2.2 下载语音识别模型文件
|
||||||
|
|
||||||
你需要下载语音识别的模型文件,因为本项目的默认语音识别用的是本地离线语音识别方案。可通过这个方式下载
|
你需要下载语音识别的模型文件,因为本项目的默认语音识别用的是本地离线语音识别方案。可通过这个方式下载
|
||||||
[跳转到下载语音识别模型文件](#模型文件)
|
[跳转到下载语音识别模型文件](#模型文件)
|
||||||
|
|
||||||
下载完后,回到本教程。
|
下载完后,回到本教程。
|
||||||
|
|
||||||
## 3. 下载docker-compose.yaml
|
#### 1.2.3 下载配置文件
|
||||||
|
|
||||||
|
你需要下载两个配置文件:`docker-compose.yaml` 和 `config.yaml`。需要从项目仓库下载这两个文件。
|
||||||
|
|
||||||
|
##### 1.2.3.1 下载 docker-compose.yaml
|
||||||
|
|
||||||
用浏览器打开[这个链接](../main/xiaozhi-server/docker-compose.yml)。
|
用浏览器打开[这个链接](../main/xiaozhi-server/docker-compose.yml)。
|
||||||
|
|
||||||
@@ -37,7 +81,7 @@ xiaozhi-server
|
|||||||
|
|
||||||
下载完后,回到本教程继续往下。
|
下载完后,回到本教程继续往下。
|
||||||
|
|
||||||
## 3. 下载配置文件
|
##### 1.2.3.2 下载 config.yaml
|
||||||
|
|
||||||
用浏览器打开[这个链接](../main/xiaozhi-server/config.yaml)。
|
用浏览器打开[这个链接](../main/xiaozhi-server/config.yaml)。
|
||||||
|
|
||||||
@@ -58,14 +102,14 @@ xiaozhi-server
|
|||||||
|
|
||||||
如果你的文件目录结构也是上面的,就继续往下。如果不是,你就再仔细看看是不是漏操作了什么。
|
如果你的文件目录结构也是上面的,就继续往下。如果不是,你就再仔细看看是不是漏操作了什么。
|
||||||
|
|
||||||
## 4. 配置项目文件
|
## 3. 配置项目文件
|
||||||
|
|
||||||
接下里,程序还不能直接运行,你需要配置一下,你到底使用的是什么模型。你可以看这个教程:
|
接下里,程序还不能直接运行,你需要配置一下,你到底使用的是什么模型。你可以看这个教程:
|
||||||
[跳转到配置项目文件](#配置项目)
|
[跳转到配置项目文件](#配置项目)
|
||||||
|
|
||||||
配置完项目文件后,回到本教程继续往下。
|
配置完项目文件后,回到本教程继续往下。
|
||||||
|
|
||||||
## 5. 执行docker命令
|
## 4. 执行docker命令
|
||||||
|
|
||||||
打开命令行工具,使用`终端`或`命令行`工具 进入到你的`xiaozhi-server`,执行以下命令
|
打开命令行工具,使用`终端`或`命令行`工具 进入到你的`xiaozhi-server`,执行以下命令
|
||||||
|
|
||||||
@@ -81,14 +125,14 @@ docker logs -f xiaozhi-esp32-server
|
|||||||
|
|
||||||
这时,你就要留意日志信息,可以根据这个教程,判断是否成功了。[跳转到运行状态确认](#运行状态确认)
|
这时,你就要留意日志信息,可以根据这个教程,判断是否成功了。[跳转到运行状态确认](#运行状态确认)
|
||||||
|
|
||||||
## 6.版本升级操作
|
## 5. 版本升级操作
|
||||||
|
|
||||||
如果后期想升级版本,可以这么操作
|
如果后期想升级版本,可以这么操作
|
||||||
|
|
||||||
1、备份好`data`文件夹中的`.config.yaml`文件,一些关键的配置到时复制到新的`.config.yaml`文件里。
|
5.1、备份好`data`文件夹中的`.config.yaml`文件,一些关键的配置到时复制到新的`.config.yaml`文件里。
|
||||||
请注意是对关键密钥逐个复制,不要直接覆盖。因为新的`.config.yaml`文件可能有一些新的配置项,旧的`.config.yaml`文件不一定有。
|
请注意是对关键密钥逐个复制,不要直接覆盖。因为新的`.config.yaml`文件可能有一些新的配置项,旧的`.config.yaml`文件不一定有。
|
||||||
|
|
||||||
2、执行以下命令
|
5.2、执行以下命令
|
||||||
|
|
||||||
```
|
```
|
||||||
docker stop xiaozhi-esp32-server
|
docker stop xiaozhi-esp32-server
|
||||||
@@ -96,7 +140,7 @@ docker rm xiaozhi-esp32-server
|
|||||||
docker rmi ghcr.nju.edu.cn/xinnan-tech/xiaozhi-esp32-server:server_latest
|
docker rmi ghcr.nju.edu.cn/xinnan-tech/xiaozhi-esp32-server:server_latest
|
||||||
```
|
```
|
||||||
|
|
||||||
3、重新按docker方式部署
|
5.3、重新按docker方式部署
|
||||||
|
|
||||||
# 方式二:借助Docker环境运行部署
|
# 方式二:借助Docker环境运行部署
|
||||||
|
|
||||||
@@ -117,7 +161,7 @@ docker run -it --name xiaozhi-env --restart always --security-opt seccomp:unconf
|
|||||||
-p 8000:8000 \
|
-p 8000:8000 \
|
||||||
-p 8002:8002 \
|
-p 8002:8002 \
|
||||||
-v ./:/app \
|
-v ./:/app \
|
||||||
kalicyh/poetry:v3.10_xiaozhi
|
kalicyh/python:xiaozhi
|
||||||
```
|
```
|
||||||
|
|
||||||
然后就和正常开发一样了
|
然后就和正常开发一样了
|
||||||
@@ -127,29 +171,13 @@ docker run -it --name xiaozhi-env --restart always --security-opt seccomp:unconf
|
|||||||
在刚刚的打开的终端运行
|
在刚刚的打开的终端运行
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
poetry install --no-root
|
pip install -r requirements.txt
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y --no-install-recommends libopus0 ffmpeg
|
|
||||||
```
|
|
||||||
|
|
||||||
速度慢可以尝试使用清华镜像
|
|
||||||
|
|
||||||
```sh
|
|
||||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware" > /etc/apt/sources.list
|
|
||||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-firmware" >> /etc/apt/sources.list
|
|
||||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free non-free-firmware" >> /etc/apt/sources.list
|
|
||||||
echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian-security bookworm-security main contrib non-free non-free-firmware" >> /etc/apt/sources.list
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y --no-install-recommends libopus0 ffmpeg
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 6.运行项目
|
## 6.运行项目
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
poetry run python app.py
|
python app.py
|
||||||
```
|
```
|
||||||
|
|
||||||
# 方式三:本地源码运行
|
# 方式三:本地源码运行
|
||||||
@@ -233,20 +261,23 @@ python app.py
|
|||||||
如果你的`xiaozhi-server`目录没有`data`,你需要创建`data`目录。
|
如果你的`xiaozhi-server`目录没有`data`,你需要创建`data`目录。
|
||||||
如果你的`data`下面没有`.config.yaml`文件,你可以把源码目录下的`config.yaml`文件复制一份,重命名为`.config.yaml`
|
如果你的`data`下面没有`.config.yaml`文件,你可以把源码目录下的`config.yaml`文件复制一份,重命名为`.config.yaml`
|
||||||
|
|
||||||
修改`xiaozhi-server`下`data`目录下的`.config.yaml`文件,配置本项目必须的两个配置。
|
修改`xiaozhi-server`下`data`目录下的`.config.yaml`文件,配置本项目必须的一个配置。
|
||||||
|
|
||||||
- 默认的LLM使用的是`ChatGLMLLM`,你需要配置密钥,因为他们的模型,虽然有免费的,但是仍要去[官网](https://bigmodel.cn/usercenter/proj-mgmt/apikeys)注册密钥,才能启动。
|
- 默认的LLM使用的是`ChatGLMLLM`,你需要配置密钥,因为他们的模型,虽然有免费的,但是仍要去[官网](https://bigmodel.cn/usercenter/proj-mgmt/apikeys)注册密钥,才能启动。
|
||||||
- 默认的记忆层`mem0ai`,你需要配置密钥,因为他们的API,虽然有免费额度,但是仍要去[官网](https://app.mem0.ai/dashboard/api-keys)注册密钥,才能启动。
|
|
||||||
|
|
||||||
配置说明:这里是各个功能使用的默认组件,例如LLM默认使用`ChatGLMLLM`模型。如果需要切换模型,就是改对应的名称。
|
配置说明:这里是各个功能使用的默认组件,例如LLM默认使用`ChatGLMLLM`模型。如果需要切换模型,就是改对应的名称。
|
||||||
本项目的默认配置仅是成本最低配置(`glm-4-flash`和`EdgeTTS`都是免费的),如果需要更优的更快的搭配,需要自己结合部署环境切换各组件的使用。
|
本项目的默认配置仅是成本最低配置(`glm-4-flash`和`EdgeTTS`都是免费的),如果需要更优的更快的搭配,需要自己结合部署环境切换各组件的使用。
|
||||||
|
|
||||||
```
|
```
|
||||||
selected_module:
|
selected_module:
|
||||||
ASR: FunASR
|
|
||||||
VAD: SileroVAD
|
VAD: SileroVAD
|
||||||
|
ASR: FunASR
|
||||||
LLM: ChatGLMLLM
|
LLM: ChatGLMLLM
|
||||||
TTS: EdgeTTS
|
TTS: EdgeTTS
|
||||||
|
# 默认不开启记忆,如需开启请看配置文件里的描述
|
||||||
|
Memory: nomem
|
||||||
|
# 默认不开启意图识别,如需开启请看配置文件里的描述
|
||||||
|
Intent: nointent
|
||||||
```
|
```
|
||||||
|
|
||||||
比如修改`LLM`使用的组件,就看本项目支持哪些`LLM` API接口,当前支持的是`openai`、`dify`。欢迎验证和支持更多LLM平台的接口。
|
比如修改`LLM`使用的组件,就看本项目支持哪些`LLM` API接口,当前支持的是`openai`、`dify`。欢迎验证和支持更多LLM平台的接口。
|
||||||
@@ -265,8 +296,6 @@ LLM:
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
有些服务,比如如果你使用`Dify`、`豆包的TTS`,是需要密钥的,记得在配置文件加上哦!
|
|
||||||
|
|
||||||
## 模型文件
|
## 模型文件
|
||||||
|
|
||||||
本项目语音识别模型,默认使用`SenseVoiceSmall`模型,进行语音转文字。因为模型较大,需要独立下载,下载后把`model.pt`
|
本项目语音识别模型,默认使用`SenseVoiceSmall`模型,进行语音转文字。因为模型较大,需要独立下载,下载后把`model.pt`
|
||||||
@@ -309,4 +338,4 @@ LLM:
|
|||||||
|
|
||||||
[5、我说话很慢,停顿时小智老是抢话](../README.md#1%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E8%AF%B4%E7%9A%84%E8%AF%9D%E5%B0%8F%E6%99%BA%E8%AF%86%E5%88%AB%E5%87%BA%E6%9D%A5%E5%BE%88%E5%A4%9A%E9%9F%A9%E6%96%87%E6%97%A5%E6%96%87%E8%8B%B1%E6%96%87)
|
[5、我说话很慢,停顿时小智老是抢话](../README.md#1%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E8%AF%B4%E7%9A%84%E8%AF%9D%E5%B0%8F%E6%99%BA%E8%AF%86%E5%88%AB%E5%87%BA%E6%9D%A5%E5%BE%88%E5%A4%9A%E9%9F%A9%E6%96%87%E6%97%A5%E6%96%87%E8%8B%B1%E6%96%87)
|
||||||
|
|
||||||
[6、我想通过小智控制电灯、空调、远程开关机等操作](../README.md#1%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E8%AF%B4%E7%9A%84%E8%AF%9D%E5%B0%8F%E6%99%BA%E8%AF%86%E5%88%AB%E5%87%BA%E6%9D%A5%E5%BE%88%E5%A4%9A%E9%9F%A9%E6%96%87%E6%97%A5%E6%96%87%E8%8B%B1%E6%96%87)
|
[6、我想通过小智控制电灯、空调、远程开关机等操作](../README.md#1%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E8%AF%B4%E7%9A%84%E8%AF%9D%E5%B0%8F%E6%99%BA%E8%AF%86%E5%88%AB%E5%87%BA%E6%9D%A5%E5%BE%88%E5%A4%9A%E9%9F%A9%E6%96%87%E6%97%A5%E6%96%87%E8%8B%B1%E6%96%87)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# 致开发者的公开信
|
||||||
|
|
||||||
|
"春江水暖鸭先知,正是河豚欲上时!"
|
||||||
|
|
||||||
|
亲爱的朋友,我是John,是一名普通公司里的Java程序员,今天,我怀着无比真挚的心情,向热爱AI技术与创新的你发出这封公开信。
|
||||||
|
|
||||||
|
半年前我看到很多优秀的项目,比如`Dify`、`Chat2DB`等人工智能相关的项目,我在想,我要是能参与这些项目多好,可惜“报国无门,空打十年代码”。
|
||||||
|
|
||||||
|
我是2025年初刷到虾哥团队的视频,我非常好奇他是怎么实现的,我想复刻他们的后端服务,打造一个低成本民用贾维斯。很可惜现在做的作品依然只是一个人工智障,它并发低、没有灵魂,响应很慢,bug很多。
|
||||||
|
|
||||||
|
虾哥团队是我们学习的对象,我很想拥有像虾哥团队一样智能的小智后端服务。但是我也能理解虾哥不开源的决定。“一花独放不是春,百花齐放春满园”,人工智能遍地开花的时代,也许就在我们这代实现,我们可以用自己的双手,实现低成本民用贾维斯。我个人认为,他能实现的,我们也能实现,只是时间问题而已,我称之为“我们的取经之路”。
|
||||||
|
|
||||||
|
那么这条取经之路,我们会遇到什么困难?我想应该不少于八十一难。这一路必然会出现各种妖怪,当然也有神仙暗中帮助我们,也有人加入取经队伍。
|
||||||
|
|
||||||
|
以上内容,如果你觉得好笑。那我也觉得非常的幸运。我能够在你人生3万多天里博你笑五秒,也算是为你做了一次贡献。
|
||||||
|
|
||||||
|
民用低成本贾维斯这个想法,会失败吗,我不知道,但是我们普通人的一生,这种失败不是很常见吗?
|
||||||
|
|
||||||
|
未来,有一点是可以确定的,就一定会有人完全复刻虾哥团队的功能,实现民用低成本贾维斯。这个项目会是我们吗?
|
||||||
|
|
||||||
|
期待与你携手前行,共创未来。
|
||||||
|
|
||||||
|
John,2025.3.11,广州
|
||||||
|
|
||||||
|
# 附 开发贡献指南
|
||||||
|
## 项目目标
|
||||||
|
|
||||||
|
1. **民用低成本贾维斯解决方案**
|
||||||
|
|
||||||
|
2. **智能联动周边硬件的解决方案**
|
||||||
|
|
||||||
|
## 加入我们
|
||||||
|
|
||||||
|
我们热忱欢迎志同道合的朋友加入,共同为项目贡献力量。您可在[这个链接](https://github.com/users/xinnan-tech/projects/3)查看我们近期要实现的功能,功能列表中还没指派相关人员处理的,正是急需您的参与。参与方式如下:
|
||||||
|
|
||||||
|
### 1、成为普通贡献者
|
||||||
|
|
||||||
|
Fork 项目,提交 PR,由开发者审核后合入主分支。
|
||||||
|
|
||||||
|
### 2、成为开发者
|
||||||
|
|
||||||
|
当你累计提交 3 次有效 PR 后,可以联系群主申请成为开发者,群主将邀请你加入独立的开发者群,共同探讨项目未来。
|
||||||
|
|
||||||
|
## 开发者开发流程
|
||||||
|
|
||||||
|
1. **创建新分支**
|
||||||
|
每个功能点请以新分支方式开发,分支名称应简洁明了,让人一眼看出所实现的功能,避免功能撞车。
|
||||||
|
|
||||||
|
2. **提交 PR 审核**
|
||||||
|
功能开发完成后,请在 GitHub 上提交 PR,由其他开发者审核,审核通过后合并入主分支。
|
||||||
|
After Width: | Height: | Size: 289 KiB |
|
Before Width: | Height: | Size: 288 KiB After Width: | Height: | Size: 338 KiB |
|
After Width: | Height: | Size: 280 KiB |
|
After Width: | Height: | Size: 298 KiB |
|
After Width: | Height: | Size: 576 KiB |
@@ -3,7 +3,7 @@
|
|||||||
# 项目目录介绍
|
# 项目目录介绍
|
||||||
当你看到这份文件的时候,这个这个项目还没完善好。我们还有很多东西要做。
|
当你看到这份文件的时候,这个这个项目还没完善好。我们还有很多东西要做。
|
||||||
|
|
||||||
如果你会开发,我们非常欢迎您的加入。
|
如果你是一名软件开发者,这里有一份[《致开发者的公开信》](../docs/contributor_open_letter.md),欢迎归队!
|
||||||
|
|
||||||
```
|
```
|
||||||
xiaozhi-esp32-server
|
xiaozhi-esp32-server
|
||||||
@@ -18,6 +18,6 @@ xiaozhi-esp32-server
|
|||||||
|
|
||||||
# manager-web 、manager-api接口协议
|
# manager-web 、manager-api接口协议
|
||||||
|
|
||||||
[manager前后端接口协议](https://app.apifox.com/invite/project?token=H_8qhgfjUeaAL0wybghgU)
|
[manager前后端接口协议](https://app.apifox.com/invite/project?token=eXg2_tUv85q-gc3ZRowmn)
|
||||||
|
|
||||||
[前端页面设计图](https://codesign.qq.com/app/s/526108506410828)
|
[前端页面设计图](https://codesign.qq.com/app/s/526108506410828)
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ public class AdminApplication {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(AdminApplication.class, args);
|
SpringApplication.run(AdminApplication.class, args);
|
||||||
System.out.println("http://localhost:8002/xiaozhi-esp32-api/doc.html");
|
System.out.println("http://localhost:8002/xiaozhi-esp32-api/api/v1/doc.html");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
package xiaozhi.common.aspect;
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import xiaozhi.common.annotation.DataFilter;
|
|
||||||
import xiaozhi.common.constant.Constant;
|
|
||||||
import xiaozhi.common.exception.ErrorCode;
|
|
||||||
import xiaozhi.common.exception.RenException;
|
|
||||||
import xiaozhi.common.interceptor.DataScope;
|
|
||||||
import xiaozhi.common.user.UserDetail;
|
|
||||||
import xiaozhi.modules.security.user.SecurityUser;
|
|
||||||
import xiaozhi.modules.sys.enums.SuperAdminEnum;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.aspectj.lang.JoinPoint;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
|
||||||
import org.aspectj.lang.annotation.Before;
|
|
||||||
import org.aspectj.lang.annotation.Pointcut;
|
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据过滤,切面处理类
|
|
||||||
* Copyright (c) 人人开源 All rights reserved.
|
|
||||||
* Website: https://www.renren.io
|
|
||||||
*/
|
|
||||||
@Aspect
|
|
||||||
@Component
|
|
||||||
public class DataFilterAspect {
|
|
||||||
|
|
||||||
@Pointcut("@annotation(xiaozhi.common.annotation.DataFilter)")
|
|
||||||
public void dataFilterCut() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before("dataFilterCut()")
|
|
||||||
public void dataFilter(JoinPoint point) {
|
|
||||||
Object params = point.getArgs()[0];
|
|
||||||
if (params != null && params instanceof Map) {
|
|
||||||
UserDetail user = SecurityUser.getUser();
|
|
||||||
|
|
||||||
//如果是超级管理员,则不进行数据过滤
|
|
||||||
if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
//否则进行数据过滤
|
|
||||||
Map map = (Map) params;
|
|
||||||
String sqlFilter = getSqlFilter(user, point);
|
|
||||||
map.put(Constant.SQL_FILTER, new DataScope(sqlFilter));
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new RenException(ErrorCode.DATA_SCOPE_PARAMS_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取数据过滤的SQL
|
|
||||||
*/
|
|
||||||
private String getSqlFilter(UserDetail user, JoinPoint point) throws Exception {
|
|
||||||
MethodSignature signature = (MethodSignature) point.getSignature();
|
|
||||||
Method method = point.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
|
|
||||||
DataFilter dataFilter = method.getAnnotation(DataFilter.class);
|
|
||||||
|
|
||||||
//获取表的别名
|
|
||||||
String tableAlias = dataFilter.tableAlias();
|
|
||||||
if (StringUtils.isNotBlank(tableAlias)) {
|
|
||||||
tableAlias += ".";
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder sqlFilter = new StringBuilder();
|
|
||||||
sqlFilter.append(" (");
|
|
||||||
|
|
||||||
//部门ID列表
|
|
||||||
List<Long> deptIdList = user.getDeptIdList();
|
|
||||||
if (CollUtil.isNotEmpty(deptIdList)) {
|
|
||||||
sqlFilter.append(tableAlias).append(dataFilter.deptId());
|
|
||||||
|
|
||||||
sqlFilter.append(" in(").append(StringUtils.join(deptIdList, ",")).append(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
//查询本人数据
|
|
||||||
if (CollUtil.isNotEmpty(deptIdList)) {
|
|
||||||
sqlFilter.append(" or ");
|
|
||||||
}
|
|
||||||
sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getId());
|
|
||||||
|
|
||||||
sqlFilter.append(")");
|
|
||||||
|
|
||||||
return sqlFilter.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -73,10 +73,8 @@ public interface Constant {
|
|||||||
* 排序方式
|
* 排序方式
|
||||||
*/
|
*/
|
||||||
String ORDER = "order";
|
String ORDER = "order";
|
||||||
/**
|
|
||||||
* token header
|
String AUTHORIZATION = "Authorization";
|
||||||
*/
|
|
||||||
String TOKEN_HEADER = "token";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 路径分割符
|
* 路径分割符
|
||||||
|
|||||||
@@ -22,24 +22,25 @@ public interface ErrorCode {
|
|||||||
int CAPTCHA_ERROR = 10007;
|
int CAPTCHA_ERROR = 10007;
|
||||||
int SUB_MENU_EXIST = 10008;
|
int SUB_MENU_EXIST = 10008;
|
||||||
int PASSWORD_ERROR = 10009;
|
int PASSWORD_ERROR = 10009;
|
||||||
|
|
||||||
int SUPERIOR_DEPT_ERROR = 10011;
|
int SUPERIOR_DEPT_ERROR = 10011;
|
||||||
int SUPERIOR_MENU_ERROR = 10012;
|
int SUPERIOR_MENU_ERROR = 10012;
|
||||||
int DATA_SCOPE_PARAMS_ERROR = 10013;
|
int DATA_SCOPE_PARAMS_ERROR = 10013;
|
||||||
int DEPT_SUB_DELETE_ERROR = 10014;
|
int DEPT_SUB_DELETE_ERROR = 10014;
|
||||||
int DEPT_USER_DELETE_ERROR = 10015;
|
int DEPT_USER_DELETE_ERROR = 10015;
|
||||||
|
|
||||||
int UPLOAD_FILE_EMPTY = 10019;
|
int UPLOAD_FILE_EMPTY = 10019;
|
||||||
int TOKEN_NOT_EMPTY = 10020;
|
int TOKEN_NOT_EMPTY = 10020;
|
||||||
int TOKEN_INVALID = 10021;
|
int TOKEN_INVALID = 10021;
|
||||||
int ACCOUNT_LOCK = 10022;
|
int ACCOUNT_LOCK = 10022;
|
||||||
|
|
||||||
int OSS_UPLOAD_FILE_ERROR = 10024;
|
int OSS_UPLOAD_FILE_ERROR = 10024;
|
||||||
|
|
||||||
int REDIS_ERROR = 10027;
|
int REDIS_ERROR = 10027;
|
||||||
int JOB_ERROR = 10028;
|
int JOB_ERROR = 10028;
|
||||||
int INVALID_SYMBOL = 10029;
|
int INVALID_SYMBOL = 10029;
|
||||||
|
|
||||||
// 密码相关错误码
|
|
||||||
int PASSWORD_LENGTH_ERROR = 10030;
|
int PASSWORD_LENGTH_ERROR = 10030;
|
||||||
int PASSWORD_WEAK_ERROR = 10031;
|
int PASSWORD_WEAK_ERROR = 10031;
|
||||||
int DEL_MYSELF_ERROR = 10032;
|
int DEL_MYSELF_ERROR = 10032;
|
||||||
// 验证码错误
|
int DEVICE_CAPTCHA_ERROR = 10033;
|
||||||
int VERIFICATION_CODE = 10033;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ public class FieldMetaObjectHandler implements MetaObjectHandler {
|
|||||||
//创建时间
|
//创建时间
|
||||||
strictInsertFill(metaObject, CREATE_DATE, Date.class, date);
|
strictInsertFill(metaObject, CREATE_DATE, Date.class, date);
|
||||||
|
|
||||||
//创建者所属部门
|
|
||||||
strictInsertFill(metaObject, DEPT_ID, Long.class, user.getDeptId());
|
|
||||||
|
|
||||||
//更新者
|
//更新者
|
||||||
strictInsertFill(metaObject, UPDATER, Long.class, user.getId());
|
strictInsertFill(metaObject, UPDATER, Long.class, user.getId());
|
||||||
//更新时间
|
//更新时间
|
||||||
|
|||||||
@@ -21,60 +21,9 @@ public class RedisKeys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录用户Key
|
* 未注册设备验证码Key
|
||||||
*/
|
*/
|
||||||
public static String getSecurityUserKey(Long id) {
|
public static String getDeviceCaptchaKey(String captcha) {
|
||||||
return "sys:security:user:" + id;
|
return "sys:device:captcha:" + captcha;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 系统日志Key
|
|
||||||
*/
|
|
||||||
public static String getSysLogKey() {
|
|
||||||
return "sys:log";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 系统资源Key
|
|
||||||
*/
|
|
||||||
public static String getSysResourceKey() {
|
|
||||||
return "sys:resource";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户菜单导航Key
|
|
||||||
*/
|
|
||||||
public static String getUserMenuNavKey(Long userId) {
|
|
||||||
return "sys:user:nav:" + userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户权限标识Key
|
|
||||||
*/
|
|
||||||
public static String getUserPermissionsKey(Long userId) {
|
|
||||||
return "sys:user:permissions:" + userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用户登陆错误次数
|
|
||||||
*
|
|
||||||
* @param username
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getUserLoginErrorCountKey(String username) {
|
|
||||||
return "sys:user:login:error:" + username;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getUserInfoKey(Long userId) {
|
|
||||||
return "sys:user:" + userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDataScopeListKey(Long userId) {
|
|
||||||
return "sys:user:data:scope:" + userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getSysUserName(Long id) {
|
|
||||||
return "sys:user:name" + id;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package xiaozhi.common.user;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录用户信息
|
* 登录用户信息
|
||||||
@@ -14,19 +13,7 @@ import java.util.List;
|
|||||||
public class UserDetail implements Serializable {
|
public class UserDetail implements Serializable {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String username;
|
private String username;
|
||||||
private String realName;
|
|
||||||
private String headUrl;
|
|
||||||
private Integer gender;
|
|
||||||
private String email;
|
|
||||||
private String mobile;
|
|
||||||
private Long deptId;
|
|
||||||
private String password;
|
|
||||||
private Integer status;
|
|
||||||
private Integer superAdmin;
|
private Integer superAdmin;
|
||||||
private String token;
|
private String token;
|
||||||
/**
|
private Integer status;
|
||||||
* 部门数据权限
|
|
||||||
*/
|
|
||||||
private List<Long> deptIdList;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package xiaozhi.common.utils;
|
package xiaozhi.common.utils;
|
||||||
|
|
||||||
import xiaozhi.common.constant.Constant;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
@@ -8,6 +7,8 @@ import org.springframework.util.DigestUtils;
|
|||||||
import org.springframework.web.context.request.RequestAttributes;
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
|
import xiaozhi.common.exception.RenException;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
@@ -30,13 +31,14 @@ public class HttpContextUtils {
|
|||||||
return ((ServletRequestAttributes) requestAttributes).getRequest();
|
return ((ServletRequestAttributes) requestAttributes).getRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getToken() {
|
public static String getToken(String authorization) {
|
||||||
HttpServletRequest httpRequest = getHttpServletRequest();
|
String token;
|
||||||
String token = httpRequest.getHeader(Constant.TOKEN_HEADER);
|
if (StringUtils.isBlank(authorization) && authorization.contains("Bearer ")) {
|
||||||
|
throw new RenException(ErrorCode.UNAUTHORIZED);
|
||||||
//如果header中不存在token,则从参数中获取token
|
}
|
||||||
|
token = authorization.replace("Bearer ", "");
|
||||||
if (StringUtils.isBlank(token)) {
|
if (StringUtils.isBlank(token)) {
|
||||||
token = httpRequest.getParameter(Constant.TOKEN_HEADER);
|
throw new RenException(ErrorCode.TOKEN_NOT_EMPTY);
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
package xiaozhi.common.utils;
|
package xiaozhi.common.utils;
|
||||||
|
|
||||||
import xiaozhi.common.exception.ErrorCode;
|
|
||||||
import xiaozhi.common.page.PageData;
|
|
||||||
import xiaozhi.modules.security.user.SecurityUser;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 响应数据
|
* 响应数据
|
||||||
@@ -42,9 +36,6 @@ public class Result<T> implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean success() {
|
|
||||||
return code == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<T> error() {
|
public Result<T> error() {
|
||||||
this.code = ErrorCode.INTERNAL_SERVER_ERROR;
|
this.code = ErrorCode.INTERNAL_SERVER_ERROR;
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package xiaozhi.modules.admin.contrloler;
|
||||||
|
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xiaozhi.common.constant.Constant;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.utils.Result;
|
||||||
|
import xiaozhi.common.validator.ValidatorUtils;
|
||||||
|
import xiaozhi.modules.sys.dto.AdminPageUserDTO;
|
||||||
|
import xiaozhi.modules.sys.service.SysUserService;
|
||||||
|
import xiaozhi.modules.sys.vo.AdminPageUserVO;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员控制层
|
||||||
|
*
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-25
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/admin")
|
||||||
|
@Tag(name = "管理员管理")
|
||||||
|
public class AdminController {
|
||||||
|
private final SysUserService sysUserService;
|
||||||
|
|
||||||
|
@GetMapping("/users")
|
||||||
|
@Operation(summary = "分页查找用户")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = "mobile", description = "用户手机号码", required = true),
|
||||||
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true),
|
||||||
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true),
|
||||||
|
})
|
||||||
|
public Result<PageData<AdminPageUserVO>> pageUser(
|
||||||
|
@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
AdminPageUserDTO dto = new AdminPageUserDTO();
|
||||||
|
dto.setMobile((String) params.get("mobile"));
|
||||||
|
dto.setLimit((String) params.get(Constant.LIMIT));
|
||||||
|
dto.setPage((String) params.get("pages"));
|
||||||
|
|
||||||
|
ValidatorUtils.validateEntity(dto);
|
||||||
|
PageData<AdminPageUserVO> page = sysUserService.page(dto);
|
||||||
|
return new Result<PageData<AdminPageUserVO>>().ok(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/users/{id}")
|
||||||
|
@Operation(summary = "重置密码")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<String> update(
|
||||||
|
@PathVariable Long id) {
|
||||||
|
String password = sysUserService.resetPassword(id);
|
||||||
|
return new Result<String>().ok(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/users/{id}")
|
||||||
|
@Operation(summary = "用户删除")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<Void> delete(@PathVariable Long id) {
|
||||||
|
sysUserService.delete(new Long[]{id});
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/device/all")
|
||||||
|
@Operation(summary = "分页查找设备")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = "keywords", description = "用户手机号码", required = true),
|
||||||
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true),
|
||||||
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true),
|
||||||
|
})
|
||||||
|
public Result<Void> pageDevice(
|
||||||
|
@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
//TODO 等设备功能模块写好
|
||||||
|
return new Result<Void>().error(600,"等设备功能模块写好");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package xiaozhi.modules.agent.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xiaozhi.common.constant.Constant;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.user.UserDetail;
|
||||||
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
|
import xiaozhi.common.utils.Result;
|
||||||
|
import xiaozhi.modules.agent.dto.AgentCreateDTO;
|
||||||
|
import xiaozhi.modules.agent.dto.AgentUpdateDTO;
|
||||||
|
import xiaozhi.modules.agent.entity.AgentEntity;
|
||||||
|
import xiaozhi.modules.agent.service.AgentService;
|
||||||
|
import xiaozhi.modules.security.user.SecurityUser;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Tag(name = "智能体管理")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/agent")
|
||||||
|
public class AgentController {
|
||||||
|
private final AgentService agentService;
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
@Operation(summary = "获取用户智能体列表")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<List<AgentEntity>> getUserAgents() {
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
List<AgentEntity> agents = agentService.getUserAgents(user.getId());
|
||||||
|
return new Result<List<AgentEntity>>().ok(agents);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/all")
|
||||||
|
@Operation(summary = "智能体列表(管理员)")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true),
|
||||||
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true),
|
||||||
|
})
|
||||||
|
public Result<PageData<AgentEntity>> adminAgentList(
|
||||||
|
@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
PageData<AgentEntity> page = agentService.adminAgentList(params);
|
||||||
|
return new Result<PageData<AgentEntity>>().ok(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
@Operation(summary = "获取智能体详情")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<AgentEntity> getAgentById(@PathVariable("id") String id) {
|
||||||
|
AgentEntity agent = agentService.getAgentById(id);
|
||||||
|
return new Result<AgentEntity>().ok(agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@Operation(summary = "创建智能体")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<Void> save(@RequestBody @Valid AgentCreateDTO dto) {
|
||||||
|
AgentEntity entity = ConvertUtils.sourceToTarget(dto, AgentEntity.class);
|
||||||
|
|
||||||
|
// 设置用户ID和创建者信息
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
entity.setUserId(user.getId());
|
||||||
|
entity.setCreator(user.getId());
|
||||||
|
entity.setCreatedAt(new Date());
|
||||||
|
|
||||||
|
// ID、智能体编码和排序会在Service层自动生成
|
||||||
|
agentService.insert(entity);
|
||||||
|
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
@Operation(summary = "更新智能体")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<Void> update(@RequestBody @Valid AgentUpdateDTO dto) {
|
||||||
|
// 先查询现有实体
|
||||||
|
AgentEntity existingEntity = agentService.getAgentById(dto.getId());
|
||||||
|
if (existingEntity == null) {
|
||||||
|
return new Result<Void>().error("智能体不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只更新提供的非空字段
|
||||||
|
if (dto.getAgentName() != null) {
|
||||||
|
existingEntity.setAgentName(dto.getAgentName());
|
||||||
|
}
|
||||||
|
if (dto.getAgentCode() != null) {
|
||||||
|
existingEntity.setAgentCode(dto.getAgentCode());
|
||||||
|
}
|
||||||
|
if (dto.getAsrModelId() != null) {
|
||||||
|
existingEntity.setAsrModelId(dto.getAsrModelId());
|
||||||
|
}
|
||||||
|
if (dto.getVadModelId() != null) {
|
||||||
|
existingEntity.setVadModelId(dto.getVadModelId());
|
||||||
|
}
|
||||||
|
if (dto.getLlmModelId() != null) {
|
||||||
|
existingEntity.setLlmModelId(dto.getLlmModelId());
|
||||||
|
}
|
||||||
|
if (dto.getTtsModelId() != null) {
|
||||||
|
existingEntity.setTtsModelId(dto.getTtsModelId());
|
||||||
|
}
|
||||||
|
if (dto.getTtsVoiceId() != null) {
|
||||||
|
existingEntity.setTtsVoiceId(dto.getTtsVoiceId());
|
||||||
|
}
|
||||||
|
if (dto.getMemModelId() != null) {
|
||||||
|
existingEntity.setMemModelId(dto.getMemModelId());
|
||||||
|
}
|
||||||
|
if (dto.getIntentModelId() != null) {
|
||||||
|
existingEntity.setIntentModelId(dto.getIntentModelId());
|
||||||
|
}
|
||||||
|
if (dto.getSystemPrompt() != null) {
|
||||||
|
existingEntity.setSystemPrompt(dto.getSystemPrompt());
|
||||||
|
}
|
||||||
|
if (dto.getLangCode() != null) {
|
||||||
|
existingEntity.setLangCode(dto.getLangCode());
|
||||||
|
}
|
||||||
|
if (dto.getLanguage() != null) {
|
||||||
|
existingEntity.setLanguage(dto.getLanguage());
|
||||||
|
}
|
||||||
|
if (dto.getSort() != null) {
|
||||||
|
existingEntity.setSort(dto.getSort());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置更新者信息
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
existingEntity.setUpdater(user.getId());
|
||||||
|
existingEntity.setUpdatedAt(new Date());
|
||||||
|
|
||||||
|
agentService.updateById(existingEntity);
|
||||||
|
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@Operation(summary = "删除智能体")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<Void> delete(@PathVariable String id) {
|
||||||
|
agentService.deleteById(id);
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package xiaozhi.modules.agent.dao;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xiaozhi.common.dao.BaseDao;
|
||||||
|
import xiaozhi.modules.agent.entity.AgentEntity;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface AgentDao extends BaseDao<AgentEntity> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package xiaozhi.modules.agent.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体创建DTO
|
||||||
|
* 专用于新增智能体,不包含id、agentCode和sort字段,这些字段由系统自动生成/设置默认值
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "智能体创建对象")
|
||||||
|
public class AgentCreateDTO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "智能体名称", example = "客服助手")
|
||||||
|
@NotBlank(message = "智能体名称不能为空")
|
||||||
|
private String agentName;
|
||||||
|
|
||||||
|
@Schema(description = "语音识别模型标识", example = "asr_model_01")
|
||||||
|
private String asrModelId;
|
||||||
|
|
||||||
|
@Schema(description = "语音活动检测标识", example = "vad_model_01")
|
||||||
|
private String vadModelId;
|
||||||
|
|
||||||
|
@Schema(description = "大语言模型标识", example = "llm_model_01")
|
||||||
|
private String llmModelId;
|
||||||
|
|
||||||
|
@Schema(description = "语音合成模型标识", example = "tts_model_01")
|
||||||
|
private String ttsModelId;
|
||||||
|
|
||||||
|
@Schema(description = "音色标识", example = "voice_01")
|
||||||
|
private String ttsVoiceId;
|
||||||
|
|
||||||
|
@Schema(description = "记忆模型标识", example = "mem_model_01")
|
||||||
|
private String memModelId;
|
||||||
|
|
||||||
|
@Schema(description = "意图模型标识", example = "intent_model_01")
|
||||||
|
private String intentModelId;
|
||||||
|
|
||||||
|
@Schema(description = "角色设定参数", example = "你是一个专业的客服助手,负责回答用户问题")
|
||||||
|
private String systemPrompt;
|
||||||
|
|
||||||
|
@Schema(description = "语言编码", example = "zh_CN")
|
||||||
|
private String langCode;
|
||||||
|
|
||||||
|
@Schema(description = "交互语种", example = "中文")
|
||||||
|
private String language;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package xiaozhi.modules.agent.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 智能体更新DTO
|
||||||
|
* 专用于更新智能体,id字段是必需的,用于标识要更新的智能体
|
||||||
|
* 其他字段均为非必填,只更新提供的字段
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "智能体更新对象")
|
||||||
|
public class AgentUpdateDTO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "智能体唯一标识", example = "a1b2c3d4e5f6", required = true)
|
||||||
|
@NotBlank(message = "智能体ID不能为空")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "智能体编码", example = "AGT_1234567890", required = false)
|
||||||
|
private String agentCode;
|
||||||
|
|
||||||
|
@Schema(description = "智能体名称", example = "客服助手", required = false)
|
||||||
|
private String agentName;
|
||||||
|
|
||||||
|
@Schema(description = "语音识别模型标识", example = "asr_model_02", required = false)
|
||||||
|
private String asrModelId;
|
||||||
|
|
||||||
|
@Schema(description = "语音活动检测标识", example = "vad_model_02", required = false)
|
||||||
|
private String vadModelId;
|
||||||
|
|
||||||
|
@Schema(description = "大语言模型标识", example = "llm_model_02", required = false)
|
||||||
|
private String llmModelId;
|
||||||
|
|
||||||
|
@Schema(description = "语音合成模型标识", example = "tts_model_02", required = false)
|
||||||
|
private String ttsModelId;
|
||||||
|
|
||||||
|
@Schema(description = "音色标识", example = "voice_02", required = false)
|
||||||
|
private String ttsVoiceId;
|
||||||
|
|
||||||
|
@Schema(description = "记忆模型标识", example = "mem_model_02", required = false)
|
||||||
|
private String memModelId;
|
||||||
|
|
||||||
|
@Schema(description = "意图模型标识", example = "intent_model_02", required = false)
|
||||||
|
private String intentModelId;
|
||||||
|
|
||||||
|
@Schema(description = "角色设定参数", example = "你是一个专业的客服助手,负责回答用户问题并提供帮助", required = false)
|
||||||
|
private String systemPrompt;
|
||||||
|
|
||||||
|
@Schema(description = "语言编码", example = "zh_CN", required = false)
|
||||||
|
private String langCode;
|
||||||
|
|
||||||
|
@Schema(description = "交互语种", example = "中文", required = false)
|
||||||
|
private String language;
|
||||||
|
|
||||||
|
@Schema(description = "排序", example = "1", required = false)
|
||||||
|
private Integer sort;
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package xiaozhi.modules.agent.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("ai_agent")
|
||||||
|
@Schema(description = "智能体信息")
|
||||||
|
public class AgentEntity {
|
||||||
|
@Schema(description = "智能体唯一标识")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "所属用户ID")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "智能体编码")
|
||||||
|
private String agentCode;
|
||||||
|
|
||||||
|
@Schema(description = "智能体名称")
|
||||||
|
private String agentName;
|
||||||
|
|
||||||
|
@Schema(description = "语音识别模型标识")
|
||||||
|
private String asrModelId;
|
||||||
|
|
||||||
|
@Schema(description = "语音活动检测标识")
|
||||||
|
private String vadModelId;
|
||||||
|
|
||||||
|
@Schema(description = "大语言模型标识")
|
||||||
|
private String llmModelId;
|
||||||
|
|
||||||
|
@Schema(description = "语音合成模型标识")
|
||||||
|
private String ttsModelId;
|
||||||
|
|
||||||
|
@Schema(description = "音色标识")
|
||||||
|
private String ttsVoiceId;
|
||||||
|
|
||||||
|
@Schema(description = "记忆模型标识")
|
||||||
|
private String memModelId;
|
||||||
|
|
||||||
|
@Schema(description = "意图模型标识")
|
||||||
|
private String intentModelId;
|
||||||
|
|
||||||
|
@Schema(description = "角色设定参数")
|
||||||
|
private String systemPrompt;
|
||||||
|
|
||||||
|
@Schema(description = "语言编码")
|
||||||
|
private String langCode;
|
||||||
|
|
||||||
|
@Schema(description = "交互语种")
|
||||||
|
private String language;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "创建者")
|
||||||
|
private Long creator;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private Date createdAt;
|
||||||
|
|
||||||
|
@Schema(description = "更新者")
|
||||||
|
private Long updater;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updatedAt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package xiaozhi.modules.agent.service;
|
||||||
|
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.service.BaseService;
|
||||||
|
import xiaozhi.modules.agent.entity.AgentEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface AgentService extends BaseService<AgentEntity> {
|
||||||
|
/**
|
||||||
|
* 根据用户ID获取智能体列表
|
||||||
|
*/
|
||||||
|
List<AgentEntity> getUserAgents(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员获取所有智能体列表(分页)
|
||||||
|
*/
|
||||||
|
PageData<AgentEntity> adminAgentList(Map<String, Object> params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取智能体详情
|
||||||
|
*/
|
||||||
|
AgentEntity getAgentById(String id);
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package xiaozhi.modules.agent.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
|
import xiaozhi.modules.agent.dao.AgentDao;
|
||||||
|
import xiaozhi.modules.agent.entity.AgentEntity;
|
||||||
|
import xiaozhi.modules.agent.service.AgentService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class AgentServiceImpl extends BaseServiceImpl<AgentDao, AgentEntity> implements AgentService {
|
||||||
|
private final AgentDao agentDao;
|
||||||
|
|
||||||
|
public AgentServiceImpl(AgentDao agentDao) {
|
||||||
|
this.agentDao = agentDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<AgentEntity> getUserAgents(Long userId) {
|
||||||
|
QueryWrapper<AgentEntity> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("user_id", userId);
|
||||||
|
return agentDao.selectList(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<AgentEntity> adminAgentList(Map<String, Object> params) {
|
||||||
|
IPage<AgentEntity> page = agentDao.selectPage(
|
||||||
|
getPage(params, "sort", true),
|
||||||
|
new QueryWrapper<>()
|
||||||
|
);
|
||||||
|
return new PageData<>(page.getRecords(), page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AgentEntity getAgentById(String id) {
|
||||||
|
return agentDao.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean insert(AgentEntity entity) {
|
||||||
|
// 如果ID为空,自动生成一个UUID作为ID
|
||||||
|
if (entity.getId() == null || entity.getId().trim().isEmpty()) {
|
||||||
|
entity.setId(UUID.randomUUID().toString().replace("-", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果智能体编码为空,自动生成一个带前缀的编码
|
||||||
|
if (entity.getAgentCode() == null || entity.getAgentCode().trim().isEmpty()) {
|
||||||
|
entity.setAgentCode("AGT_" + System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果排序字段为空,设置默认值0
|
||||||
|
if (entity.getSort() == null) {
|
||||||
|
entity.setSort(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.insert(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
package xiaozhi.modules.device.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xiaozhi.common.constant.Constant;
|
||||||
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.redis.RedisKeys;
|
||||||
|
import xiaozhi.common.redis.RedisUtils;
|
||||||
|
import xiaozhi.common.user.UserDetail;
|
||||||
|
import xiaozhi.common.utils.JsonUtils;
|
||||||
|
import xiaozhi.common.utils.Result;
|
||||||
|
import xiaozhi.modules.device.dto.DeviceHeaderDTO;
|
||||||
|
import xiaozhi.modules.device.dto.DeviceUnBindDTO;
|
||||||
|
import xiaozhi.modules.device.entity.DeviceEntity;
|
||||||
|
import xiaozhi.modules.device.service.DeviceService;
|
||||||
|
import xiaozhi.modules.security.user.SecurityUser;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Tag(name = "设备管理")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/device")
|
||||||
|
public class DeviceController {
|
||||||
|
private final DeviceService deviceService;
|
||||||
|
private final RedisUtils redisUtils;
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/bind/{deviceCode}")
|
||||||
|
@Operation(summary = "绑定设备")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<DeviceEntity> bindDevice(@PathVariable String deviceCode) {
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
|
||||||
|
String deviceHeaders = (String) redisUtils.get(RedisKeys.getDeviceCaptchaKey(deviceCode));
|
||||||
|
if (StringUtils.isBlank(deviceHeaders)) {
|
||||||
|
return new Result<DeviceEntity>().error(ErrorCode.DEVICE_CAPTCHA_ERROR);
|
||||||
|
}
|
||||||
|
DeviceHeaderDTO deviceHeader = JsonUtils.parseObject(deviceHeaders.getBytes(), DeviceHeaderDTO.class);
|
||||||
|
DeviceEntity device = deviceService.bindDevice(user.getId(), deviceHeader);
|
||||||
|
return new Result<DeviceEntity>().ok(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/bind")
|
||||||
|
@Operation(summary = "获取已绑定设备")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<List<DeviceEntity>> getUserDevices() {
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
List<DeviceEntity> devices = deviceService.getUserDevices(user.getId());
|
||||||
|
return new Result<List<DeviceEntity>>().ok(devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/unbind")
|
||||||
|
@Operation(summary = "解绑设备")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result unbindDevice(@RequestBody DeviceUnBindDTO unDeviveBind) {
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
deviceService.unbindDevice(user.getId(), unDeviveBind.getDeviceId());
|
||||||
|
return new Result();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/all")
|
||||||
|
@Operation(summary = "设备列表(管理员)")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true),
|
||||||
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true),
|
||||||
|
})
|
||||||
|
public Result<PageData<DeviceEntity>> adminDeviceList(
|
||||||
|
@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
PageData<DeviceEntity> page = deviceService.adminDeviceList(params);
|
||||||
|
return new Result<PageData<DeviceEntity>>().ok(page);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package xiaozhi.modules.device.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xiaozhi.modules.device.entity.DeviceEntity;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface DeviceDao extends BaseMapper<DeviceEntity> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package xiaozhi.modules.device.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "设备连接头信息")
|
||||||
|
public class DeviceHeaderDTO {
|
||||||
|
|
||||||
|
@Schema(description = "设备ID")
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
@Schema(description = "协议版本号")
|
||||||
|
private Long protocolVersion;
|
||||||
|
|
||||||
|
@Schema(description = "认证信息")
|
||||||
|
private String authorization;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package xiaozhi.modules.device.dto;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备解绑表单
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "设备解绑表单")
|
||||||
|
public class DeviceUnBindDTO implements Serializable {
|
||||||
|
|
||||||
|
@Schema(description = "设备ID")
|
||||||
|
@NotBlank(message = "设备ID不能为空")
|
||||||
|
private Long deviceId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package xiaozhi.modules.device.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("ai_device")
|
||||||
|
@Schema(description = "设备信息")
|
||||||
|
public class DeviceEntity {
|
||||||
|
@Schema(description = "设备ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "关联用户ID")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
@Schema(description = "MAC地址")
|
||||||
|
private String macAddress;
|
||||||
|
|
||||||
|
@Schema(description = "最后连接时间")
|
||||||
|
private Date lastConnectedAt;
|
||||||
|
|
||||||
|
@Schema(description = "自动更新开关(0关闭/1开启)")
|
||||||
|
private Integer autoUpdate;
|
||||||
|
|
||||||
|
@Schema(description = "设备硬件型号")
|
||||||
|
private String board;
|
||||||
|
|
||||||
|
@Schema(description = "设备别名")
|
||||||
|
private String alias;
|
||||||
|
|
||||||
|
@Schema(description = "智能体ID")
|
||||||
|
private String agentId;
|
||||||
|
|
||||||
|
@Schema(description = "固件版本号")
|
||||||
|
private String appVersion;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "创建者")
|
||||||
|
private Long creator;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
@Schema(description = "更新者")
|
||||||
|
private Long updater;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updateDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package xiaozhi.modules.device.service;
|
||||||
|
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.modules.device.dto.DeviceHeaderDTO;
|
||||||
|
import xiaozhi.modules.device.entity.DeviceEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface DeviceService {
|
||||||
|
DeviceEntity bindDevice(Long userId, DeviceHeaderDTO deviceHeader);
|
||||||
|
|
||||||
|
List<DeviceEntity> getUserDevices(Long userId);
|
||||||
|
|
||||||
|
void unbindDevice(Long userId, Long deviceId);
|
||||||
|
|
||||||
|
PageData<DeviceEntity> adminDeviceList(Map<String, Object> params);
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package xiaozhi.modules.device.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
|
import xiaozhi.modules.device.dao.DeviceDao;
|
||||||
|
import xiaozhi.modules.device.dto.DeviceHeaderDTO;
|
||||||
|
import xiaozhi.modules.device.entity.DeviceEntity;
|
||||||
|
import xiaozhi.modules.device.service.DeviceService;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DeviceServiceImpl extends BaseServiceImpl<DeviceDao, DeviceEntity> implements DeviceService {
|
||||||
|
private final DeviceDao deviceDao;
|
||||||
|
|
||||||
|
// 添加构造函数来初始化 deviceMapper
|
||||||
|
public DeviceServiceImpl(DeviceDao deviceDao) {
|
||||||
|
this.deviceDao = deviceDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeviceEntity bindDevice(Long userId, DeviceHeaderDTO deviceHeader) {
|
||||||
|
DeviceEntity device = new DeviceEntity();
|
||||||
|
device.setUserId(userId);
|
||||||
|
device.setMacAddress(deviceHeader.getDeviceId());
|
||||||
|
device.setCreateDate(new Date());
|
||||||
|
deviceDao.insert(device);
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DeviceEntity> getUserDevices(Long userId) {
|
||||||
|
QueryWrapper<DeviceEntity> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("user_id", userId);
|
||||||
|
return deviceDao.selectList(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unbindDevice(Long userId, Long deviceId) {
|
||||||
|
deviceDao.deleteById(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<DeviceEntity> adminDeviceList(Map<String, Object> params) {
|
||||||
|
IPage<DeviceEntity> page = deviceDao.selectPage(
|
||||||
|
getPage(params, "sort", true),
|
||||||
|
new QueryWrapper<>()
|
||||||
|
);
|
||||||
|
return new PageData<>(page.getRecords(), page.getTotal());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
package xiaozhi.modules.model.controller;public class ModelConfigController {
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package xiaozhi.modules.model.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.utils.Result;
|
||||||
|
import xiaozhi.modules.model.dto.ModelConfigBodyDTO;
|
||||||
|
import xiaozhi.modules.model.dto.ModelConfigDTO;
|
||||||
|
import xiaozhi.modules.model.dto.ModelProviderDTO;
|
||||||
|
import xiaozhi.modules.model.service.ModelConfigService;
|
||||||
|
import xiaozhi.modules.model.service.ModelProviderService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/models")
|
||||||
|
@Tag(name = "模型配置")
|
||||||
|
public class ModelController {
|
||||||
|
|
||||||
|
private final ModelProviderService modelProviderService;
|
||||||
|
|
||||||
|
private final ModelConfigService modelConfigService;
|
||||||
|
|
||||||
|
@GetMapping("/models/names")
|
||||||
|
@Operation(summary = "获取所有模型名称")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<List<String>> getModelNames(@RequestParam String modelType,
|
||||||
|
@RequestParam(required = false) String modelName) {
|
||||||
|
List<String> modelNameList = modelConfigService.getModelCodeList(modelType, modelName);
|
||||||
|
return new Result<List<String>>().ok(modelNameList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{modelType}/provideTypes")
|
||||||
|
@Operation(summary = "获取模型供应器列表")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<List<ModelProviderDTO>> getModelProviderList(@PathVariable String modelType) {
|
||||||
|
List<ModelProviderDTO> modelProviderDTOS = modelProviderService.getListByModelType(modelType);
|
||||||
|
return new Result<List<ModelProviderDTO>>().ok(modelProviderDTOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{modelType}/{provideCode}/fields")
|
||||||
|
@Operation(summary = "获取模型供应器字段")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<List<String>> getModelProviderFields(@PathVariable String modelType, @PathVariable String provideCode) {
|
||||||
|
List<String> fieldList = modelProviderService.getFieldList(modelType, provideCode);
|
||||||
|
return new Result<List<String>>().ok(fieldList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/models/list")
|
||||||
|
@Operation(summary = "获取模型配置列表")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<PageData<ModelConfigDTO>> getModelConfigList(@RequestParam String modelType,
|
||||||
|
@RequestParam(required = false) String modelName,
|
||||||
|
@RequestParam(required = false, defaultValue = "0") Integer page,
|
||||||
|
@RequestParam(required = false,defaultValue = "10") Integer limit) {
|
||||||
|
PageData<ModelConfigDTO> pageList = modelConfigService.getPageList(modelType, modelName, page, limit);
|
||||||
|
return new Result<PageData<ModelConfigDTO>>().ok(pageList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/models/{modelType}/{provideCode}")
|
||||||
|
@Operation(summary = "新增模型配置")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<ModelConfigDTO> addModelConfig(@PathVariable String modelType,
|
||||||
|
@PathVariable String provideCode,
|
||||||
|
@RequestBody ModelConfigBodyDTO modelConfigBodyDTO) {
|
||||||
|
ModelConfigDTO modelConfigDTO = modelConfigService.add(modelType, provideCode, modelConfigBodyDTO);
|
||||||
|
return new Result<ModelConfigDTO>().ok(modelConfigDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PutMapping("/models/{modelType}/{provideCode}/{id}")
|
||||||
|
@Operation(summary = "编辑模型配置")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<ModelConfigDTO> editModelConfig(@PathVariable String modelType,
|
||||||
|
@PathVariable String provideCode,
|
||||||
|
@PathVariable String id,
|
||||||
|
@RequestBody ModelConfigBodyDTO modelConfigBodyDTO) {
|
||||||
|
ModelConfigDTO modelConfigDTO = modelConfigService.edit(modelType, provideCode, id, modelConfigBodyDTO);
|
||||||
|
return new Result<ModelConfigDTO>().ok(modelConfigDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@DeleteMapping("/models/{modelType}/{provideCode}/{id}")
|
||||||
|
@Operation(summary = "删除模型配置")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<Void> deleteModelConfig(@PathVariable String modelType, @PathVariable String provideCode, @PathVariable String id) {
|
||||||
|
modelConfigService.delete(modelType, provideCode, id);
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/models/{modelName}/voices")
|
||||||
|
@Operation(summary = "获取模型音色")
|
||||||
|
@RequiresPermissions("sys:role:normal")
|
||||||
|
public Result<List<String>> getVoiceList(@PathVariable String modelName,
|
||||||
|
@RequestParam(required = false) String voiceName) {
|
||||||
|
|
||||||
|
List<String> voiceList = modelConfigService.getVoiceList(modelName, voiceName);
|
||||||
|
return new Result<List<String>>().ok(voiceList);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package xiaozhi.modules.model.dao;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import xiaozhi.common.dao.BaseDao;
|
||||||
|
import xiaozhi.modules.model.entity.ModelConfigEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ModelConfigDao extends BaseDao<ModelConfigEntity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get model_code list
|
||||||
|
*/
|
||||||
|
List<String> getModelCodeList(@Param("modelType") String modelType, @Param("modelName") String modelName);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package xiaozhi.modules.model.dao;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import xiaozhi.common.dao.BaseDao;
|
||||||
|
import xiaozhi.modules.model.entity.ModelProviderEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface ModelProviderDao extends BaseDao<ModelProviderEntity> {
|
||||||
|
|
||||||
|
List<String> getFieldList(@Param("modelType") String modelType, @Param("provideCode") String provideCode);
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package xiaozhi.modules.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "模型供应器/商")
|
||||||
|
public class ModelConfigBodyDTO {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// @Schema(description = "模型类型(Memory/ASR/VAD/LLM/TTS)")
|
||||||
|
// private String modelType;
|
||||||
|
//
|
||||||
|
@Schema(description = "模型编码(如AliLLM、DoubaoTTS)")
|
||||||
|
private String modelCode;
|
||||||
|
|
||||||
|
@Schema(description = "模型名称")
|
||||||
|
private String modelName;
|
||||||
|
|
||||||
|
@Schema(description = "是否默认配置(0否 1是)")
|
||||||
|
private Integer isDefault;
|
||||||
|
|
||||||
|
@Schema(description = "是否启用")
|
||||||
|
private Integer isEnabled;
|
||||||
|
|
||||||
|
@Schema(description = "模型配置(JSON格式)")
|
||||||
|
private String configJson;
|
||||||
|
|
||||||
|
@Schema(description = "官方文档链接")
|
||||||
|
private String docLink;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package xiaozhi.modules.model.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "模型供应器/商")
|
||||||
|
public class ModelConfigDTO implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "主键")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "模型类型(Memory/ASR/VAD/LLM/TTS)")
|
||||||
|
private String modelType;
|
||||||
|
|
||||||
|
@Schema(description = "模型编码(如AliLLM、DoubaoTTS)")
|
||||||
|
private String modelCode;
|
||||||
|
|
||||||
|
@Schema(description = "模型名称")
|
||||||
|
private String modelName;
|
||||||
|
|
||||||
|
@Schema(description = "是否默认配置(0否 1是)")
|
||||||
|
private Integer isDefault;
|
||||||
|
|
||||||
|
@Schema(description = "是否启用")
|
||||||
|
private Integer isEnabled;
|
||||||
|
|
||||||
|
@Schema(description = "模型配置(JSON格式)")
|
||||||
|
private String configJson;
|
||||||
|
|
||||||
|
@Schema(description = "官方文档链接")
|
||||||
|
private String docLink;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package xiaozhi.modules.model.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Schema(description = "模型供应器/商")
|
||||||
|
public class ModelProviderDTO implements Serializable {
|
||||||
|
//
|
||||||
|
// @Schema(description = "主键")
|
||||||
|
// private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "模型类型(Memory/ASR/VAD/LLM/TTS)")
|
||||||
|
private String modelType;
|
||||||
|
|
||||||
|
@Schema(description = "供应器类型")
|
||||||
|
private String providerCode;
|
||||||
|
|
||||||
|
@Schema(description = "供应器名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "供应器字段列表(JSON格式)")
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private String fields;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "创建者")
|
||||||
|
private Long creator;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
@Schema(description = "更新者")
|
||||||
|
private Long updater;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updateDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package xiaozhi.modules.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("ai_model_config")
|
||||||
|
@Schema(description = "模型配置表")
|
||||||
|
public class ModelConfigEntity {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
|
@Schema(description = "主键")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "模型类型(Memory/ASR/VAD/LLM/TTS)")
|
||||||
|
private String modelType;
|
||||||
|
|
||||||
|
@Schema(description = "模型编码(如AliLLM、DoubaoTTS)")
|
||||||
|
private String modelCode;
|
||||||
|
|
||||||
|
@Schema(description = "模型名称")
|
||||||
|
private String modelName;
|
||||||
|
|
||||||
|
@Schema(description = "是否默认配置(0否 1是)")
|
||||||
|
private Integer isDefault;
|
||||||
|
|
||||||
|
@Schema(description = "是否启用")
|
||||||
|
private Integer isEnabled;
|
||||||
|
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
@Schema(description = "模型配置(JSON格式)")
|
||||||
|
private String configJson;
|
||||||
|
|
||||||
|
@Schema(description = "官方文档链接")
|
||||||
|
private String docLink;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "创建者")
|
||||||
|
private Long creator;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
@Schema(description = "更新者")
|
||||||
|
private Long updater;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updateDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package xiaozhi.modules.model.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("ai_model_provider")
|
||||||
|
@Schema(description = "模型供应器表")
|
||||||
|
public class ModelProviderEntity {
|
||||||
|
|
||||||
|
@TableId(type = IdType.ASSIGN_UUID)
|
||||||
|
@Schema(description = "主键")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@Schema(description = "模型类型(Memory/ASR/VAD/LLM/TTS)")
|
||||||
|
private String modelType;
|
||||||
|
|
||||||
|
@Schema(description = "供应器类型,如 openai、")
|
||||||
|
private String providerCode;
|
||||||
|
|
||||||
|
@Schema(description = "供应器名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "供应器字段列表(JSON格式)")
|
||||||
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
|
private String fields;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
@Schema(description = "创建者")
|
||||||
|
private Long creator;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
@Schema(description = "更新者")
|
||||||
|
private Long updater;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updateDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xiaozhi.modules.model.service;
|
||||||
|
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.modules.model.dto.ModelConfigBodyDTO;
|
||||||
|
import xiaozhi.modules.model.dto.ModelConfigDTO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ModelConfigService {
|
||||||
|
|
||||||
|
List<String> getModelCodeList(String modelType, String modelName);
|
||||||
|
|
||||||
|
PageData<ModelConfigDTO> getPageList(String modelType, String modelName, Integer page, Integer limit);
|
||||||
|
|
||||||
|
ModelConfigDTO add(String modelType, String provideCode, ModelConfigBodyDTO modelConfigBodyDTO);
|
||||||
|
|
||||||
|
ModelConfigDTO edit(String modelType, String provideCode, String id, ModelConfigBodyDTO modelConfigBodyDTO);
|
||||||
|
|
||||||
|
void delete(String modelType, String provideCode, String id);
|
||||||
|
|
||||||
|
List<String> getVoiceList(String modelName, String voiceName);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package xiaozhi.modules.model.service;
|
||||||
|
|
||||||
|
import xiaozhi.modules.model.dto.ModelProviderDTO;
|
||||||
|
import xiaozhi.modules.model.entity.ModelProviderEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface ModelProviderService {
|
||||||
|
|
||||||
|
// List<String> getModelNames(String modelType, String modelName);
|
||||||
|
|
||||||
|
List<ModelProviderDTO> getListByModelType(String modelType);
|
||||||
|
|
||||||
|
ModelProviderDTO add(ModelProviderEntity modelProviderEntity);
|
||||||
|
|
||||||
|
ModelProviderDTO edit(ModelProviderEntity modelProviderEntity);
|
||||||
|
|
||||||
|
void delete();
|
||||||
|
|
||||||
|
List<ModelProviderDTO> getList(String modelType, String provideCode);
|
||||||
|
|
||||||
|
List<String> getFieldList(String modelType, String provideCode);
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package xiaozhi.modules.model.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xiaozhi.common.constant.Constant;
|
||||||
|
import xiaozhi.common.exception.RenException;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
|
import xiaozhi.modules.model.dao.ModelConfigDao;
|
||||||
|
import xiaozhi.modules.model.dto.ModelConfigBodyDTO;
|
||||||
|
import xiaozhi.modules.model.dto.ModelConfigDTO;
|
||||||
|
import xiaozhi.modules.model.dto.ModelProviderDTO;
|
||||||
|
import xiaozhi.modules.model.entity.ModelConfigEntity;
|
||||||
|
import xiaozhi.modules.model.service.ModelConfigService;
|
||||||
|
import xiaozhi.modules.model.service.ModelProviderService;
|
||||||
|
import xiaozhi.modules.timbre.service.TimbreService;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ModelConfigServiceImpl extends BaseServiceImpl<ModelConfigDao, ModelConfigEntity> implements ModelConfigService {
|
||||||
|
|
||||||
|
private final ModelConfigDao modelConfigDao;
|
||||||
|
private final ModelProviderService modelProviderService;
|
||||||
|
private final TimbreService timbreService;
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ModelConfigServiceImpl.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getModelCodeList(String modelType, String modelName) {
|
||||||
|
return modelConfigDao.getModelCodeList(modelType, modelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<ModelConfigDTO> getPageList(String modelType, String modelName, Integer page, Integer limit) {
|
||||||
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
params.put(Constant.PAGE, page);
|
||||||
|
params.put(Constant.LIMIT, limit);
|
||||||
|
IPage<ModelConfigEntity> modelConfigEntityIPage = modelConfigDao.selectPage(
|
||||||
|
getPage(params, "sort", true),
|
||||||
|
new QueryWrapper<ModelConfigEntity>()
|
||||||
|
.eq("model_type", modelType)
|
||||||
|
.like(StringUtils.isNotBlank(modelName), "model_name", modelName)
|
||||||
|
);
|
||||||
|
return getPageData(modelConfigEntityIPage, ModelConfigDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelConfigDTO add(String modelType, String provideCode, ModelConfigBodyDTO modelConfigBodyDTO) {
|
||||||
|
// 先验证有没有供应器
|
||||||
|
if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
|
||||||
|
throw new RenException("modelType和provideCode不能为空");
|
||||||
|
}
|
||||||
|
List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
|
||||||
|
if (CollectionUtil.isEmpty(providerList)) {
|
||||||
|
throw new RenException("供应器不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再保存供应器提供的模型
|
||||||
|
ModelConfigEntity modelConfigEntity = ConvertUtils.sourceToTarget(modelConfigBodyDTO, ModelConfigEntity.class);
|
||||||
|
modelConfigEntity.setModelType(modelType);
|
||||||
|
modelConfigDao.insert(modelConfigEntity);
|
||||||
|
return ConvertUtils.sourceToTarget(modelConfigEntity, ModelConfigDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelConfigDTO edit(String modelType, String provideCode, String id, ModelConfigBodyDTO modelConfigBodyDTO) {
|
||||||
|
// 先验证有没有供应器
|
||||||
|
if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
|
||||||
|
throw new RenException("modelType和provideCode不能为空");
|
||||||
|
}
|
||||||
|
List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
|
||||||
|
if (CollectionUtil.isEmpty(providerList)) {
|
||||||
|
throw new RenException("供应器不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再更新供应器提供的模型
|
||||||
|
ModelConfigEntity modelConfigEntity = ConvertUtils.sourceToTarget(modelConfigBodyDTO, ModelConfigEntity.class);
|
||||||
|
modelConfigEntity.setId(id);
|
||||||
|
modelConfigEntity.setModelType(modelType);
|
||||||
|
modelConfigDao.updateById(modelConfigEntity);
|
||||||
|
return ConvertUtils.sourceToTarget(modelConfigEntity, ModelConfigDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String modelType, String provideCode, String id) {
|
||||||
|
// 先验证有没有供应器
|
||||||
|
if (StringUtils.isBlank(modelType) || StringUtils.isBlank(provideCode)) {
|
||||||
|
throw new RenException("modelType和provideCode不能为空");
|
||||||
|
}
|
||||||
|
List<ModelProviderDTO> providerList = modelProviderService.getList(modelType, provideCode);
|
||||||
|
if (CollectionUtil.isEmpty(providerList)) {
|
||||||
|
throw new RenException("供应器不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
modelConfigDao.deleteById(Long.getLong(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getVoiceList(String modelName, String voiceName) {
|
||||||
|
QueryWrapper<ModelConfigEntity> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("model_name", StringUtils.isBlank(modelName) ? "" : modelName);
|
||||||
|
queryWrapper.eq("model_type", "TTS");
|
||||||
|
List<ModelConfigEntity> modelConfigEntities = modelConfigDao.selectList(queryWrapper);
|
||||||
|
if (CollectionUtil.isEmpty(modelConfigEntities)) {
|
||||||
|
logger.warn("没有找到模型配置信息");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ModelConfigEntity modelConfigEntity = modelConfigEntities.get(0);
|
||||||
|
String id = modelConfigEntity.getId();
|
||||||
|
|
||||||
|
return timbreService.getVoiceNames(id, voiceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package xiaozhi.modules.model.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
|
import xiaozhi.modules.model.dao.ModelProviderDao;
|
||||||
|
import xiaozhi.modules.model.dto.ModelProviderDTO;
|
||||||
|
import xiaozhi.modules.model.entity.ModelProviderEntity;
|
||||||
|
import xiaozhi.modules.model.service.ModelProviderService;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class ModelProviderServiceImpl extends BaseServiceImpl<ModelProviderDao, ModelProviderEntity> implements ModelProviderService {
|
||||||
|
|
||||||
|
private final ModelProviderDao modelProviderDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ModelProviderDTO> getListByModelType(String modelType) {
|
||||||
|
|
||||||
|
QueryWrapper<ModelProviderEntity> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("model_type", StringUtils.isBlank(modelType) ? "" : modelType);
|
||||||
|
List<ModelProviderEntity> providerEntities = modelProviderDao.selectList(queryWrapper);
|
||||||
|
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelProviderDTO add(ModelProviderEntity modelProviderEntity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModelProviderDTO edit(ModelProviderEntity modelProviderEntity) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ModelProviderDTO> getList(String modelType, String provideCode) {
|
||||||
|
QueryWrapper<ModelProviderEntity> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("model_type", StringUtils.isBlank(modelType) ? "" : modelType);
|
||||||
|
queryWrapper.eq("provide_code", StringUtils.isBlank(provideCode) ? "" : provideCode);
|
||||||
|
List<ModelProviderEntity> providerEntities = modelProviderDao.selectList(queryWrapper);
|
||||||
|
return ConvertUtils.sourceToTarget(providerEntities, ModelProviderDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFieldList(String modelType, String provideCode) {
|
||||||
|
return modelProviderDao.getFieldList(modelType, provideCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -58,17 +58,21 @@ public class ShiroConfig {
|
|||||||
filters.put("oauth2", new Oauth2Filter());
|
filters.put("oauth2", new Oauth2Filter());
|
||||||
shiroFilter.setFilters(filters);
|
shiroFilter.setFilters(filters);
|
||||||
|
|
||||||
|
//添加Shiro的内置过滤器
|
||||||
|
/*anon:无需认证就可以访问
|
||||||
|
authc:必须认证了才能让问
|
||||||
|
user:必须拥有,记住我功能,才能访问
|
||||||
|
perms:拥有对某个资源的权限才能访问
|
||||||
|
role:拥有某个角色权限才能访问*/
|
||||||
Map<String, String> filterMap = new LinkedHashMap<>();
|
Map<String, String> filterMap = new LinkedHashMap<>();
|
||||||
filterMap.put("/webjars/**", "anon");
|
filterMap.put("/webjars/**", "anon");
|
||||||
filterMap.put("/druid/**", "anon");
|
filterMap.put("/druid/**", "anon");
|
||||||
filterMap.put("/login", "anon");
|
|
||||||
filterMap.put("/publicKey", "anon");
|
|
||||||
filterMap.put("/v3/api-docs/**", "anon");
|
filterMap.put("/v3/api-docs/**", "anon");
|
||||||
filterMap.put("/doc.html", "anon");
|
filterMap.put("/doc.html", "anon");
|
||||||
filterMap.put("/sys/oss/download/**", "anon");
|
|
||||||
filterMap.put("/captcha", "anon");
|
|
||||||
filterMap.put("/favicon.ico", "anon");
|
filterMap.put("/favicon.ico", "anon");
|
||||||
filterMap.put("/mobile/**", "anon");
|
filterMap.put("/user/captcha", "anon");
|
||||||
|
filterMap.put("/user/login", "anon");
|
||||||
|
filterMap.put("/user/register", "anon");
|
||||||
filterMap.put("/**", "oauth2");
|
filterMap.put("/**", "oauth2");
|
||||||
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
||||||
|
|
||||||
|
|||||||
@@ -2,41 +2,42 @@ package xiaozhi.modules.security.controller;
|
|||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.slf4j.Logger;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import xiaozhi.common.exception.ErrorCode;
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
import xiaozhi.common.redis.RedisUtils;
|
import xiaozhi.common.exception.RenException;
|
||||||
import xiaozhi.common.utils.PropertiesUtils;
|
import xiaozhi.common.page.TokenDTO;
|
||||||
|
import xiaozhi.common.user.UserDetail;
|
||||||
import xiaozhi.common.utils.Result;
|
import xiaozhi.common.utils.Result;
|
||||||
import xiaozhi.common.validator.AssertUtils;
|
import xiaozhi.common.validator.AssertUtils;
|
||||||
import xiaozhi.modules.security.dto.LoginDTO;
|
import xiaozhi.modules.security.dto.LoginDTO;
|
||||||
|
import xiaozhi.modules.security.password.PasswordUtils;
|
||||||
import xiaozhi.modules.security.service.CaptchaService;
|
import xiaozhi.modules.security.service.CaptchaService;
|
||||||
import xiaozhi.modules.security.service.SysUserTokenService;
|
import xiaozhi.modules.security.service.SysUserTokenService;
|
||||||
import xiaozhi.modules.sys.service.SysParamsService;
|
import xiaozhi.modules.security.user.SecurityUser;
|
||||||
|
import xiaozhi.modules.sys.dto.PasswordDTO;
|
||||||
|
import xiaozhi.modules.sys.dto.SysUserDTO;
|
||||||
import xiaozhi.modules.sys.service.SysUserService;
|
import xiaozhi.modules.sys.service.SysUserService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录
|
* 登录控制层
|
||||||
*/
|
*/
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@RestController
|
@RestController
|
||||||
|
@RequestMapping("/user")
|
||||||
@Tag(name = "登录管理")
|
@Tag(name = "登录管理")
|
||||||
public class LoginController {
|
public class LoginController {
|
||||||
private final SysUserService sysUserService;
|
private final SysUserService sysUserService;
|
||||||
private final SysUserTokenService sysUserTokenService;
|
private final SysUserTokenService sysUserTokenService;
|
||||||
private final CaptchaService captchaService;
|
private final CaptchaService captchaService;
|
||||||
private final RedisUtils redisUtils;
|
|
||||||
private final SysParamsService sysParamsService;
|
|
||||||
private final PropertiesUtils propertiesUtils;
|
|
||||||
|
|
||||||
@GetMapping("captcha")
|
|
||||||
|
@GetMapping("/captcha")
|
||||||
@Operation(summary = "验证码")
|
@Operation(summary = "验证码")
|
||||||
public void captcha(HttpServletResponse response, String uuid) throws IOException {
|
public void captcha(HttpServletResponse response, String uuid) throws IOException {
|
||||||
//uuid不能为空
|
//uuid不能为空
|
||||||
@@ -46,10 +47,62 @@ public class LoginController {
|
|||||||
captchaService.create(response, uuid);
|
captchaService.create(response, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("login")
|
@PostMapping("/login")
|
||||||
@Operation(summary = "登录")
|
@Operation(summary = "登录")
|
||||||
public Result login(HttpServletRequest request, @RequestBody LoginDTO login) {
|
public Result<TokenDTO> login(@RequestBody LoginDTO login) {
|
||||||
return sysUserTokenService.createToken(1L);
|
// 验证是否正确输入验证码
|
||||||
|
boolean validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha());
|
||||||
|
if (!validate) {
|
||||||
|
throw new RenException("验证码错误,请重新获取");
|
||||||
|
}
|
||||||
|
// 按照用户名获取用户
|
||||||
|
SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername());
|
||||||
|
// 判断用户是否存在
|
||||||
|
if (userDTO == null) {
|
||||||
|
throw new RenException("请检测用户和密码是否输入错误");
|
||||||
|
}
|
||||||
|
// 判断密码是否正确,不一样则进入if
|
||||||
|
if (!PasswordUtils.matches(login.getPassword(), userDTO.getPassword())) {
|
||||||
|
throw new RenException("请检测用户和密码是否输入错误");
|
||||||
|
}
|
||||||
|
return sysUserTokenService.createToken(userDTO.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/register")
|
||||||
|
@Operation(summary = "注册")
|
||||||
|
public Result<Void> register(@RequestBody LoginDTO login) {
|
||||||
|
// 验证是否正确输入验证码
|
||||||
|
boolean validate = captchaService.validate(login.getCaptchaId(), login.getCaptcha());
|
||||||
|
if (!validate) {
|
||||||
|
throw new RenException("验证码错误,请重新获取");
|
||||||
|
}
|
||||||
|
// 按照用户名获取用户
|
||||||
|
SysUserDTO userDTO = sysUserService.getByUsername(login.getUsername());
|
||||||
|
if (userDTO != null) {
|
||||||
|
throw new RenException("此手机号码已经注册过");
|
||||||
|
}
|
||||||
|
userDTO = new SysUserDTO();
|
||||||
|
userDTO.setUsername(login.getUsername());
|
||||||
|
userDTO.setPassword(login.getPassword());
|
||||||
|
sysUserService.save(userDTO);
|
||||||
|
return new Result<>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/info")
|
||||||
|
@Operation(summary = "用户信息获取")
|
||||||
|
public Result<UserDetail> info() {
|
||||||
|
UserDetail user = SecurityUser.getUser();
|
||||||
|
Result<UserDetail> result = new Result<>();
|
||||||
|
result.setData(user);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/change-password")
|
||||||
|
@Operation(summary = "修改用户密码")
|
||||||
|
public Result<?> changePassword(@RequestBody PasswordDTO passwordDTO) {
|
||||||
|
Long userId = SecurityUser.getUserId();
|
||||||
|
sysUserTokenService.changePassword(userId, passwordDTO);
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ import java.io.Serializable;
|
|||||||
@Schema(description = "登录表单")
|
@Schema(description = "登录表单")
|
||||||
public class LoginDTO implements Serializable {
|
public class LoginDTO implements Serializable {
|
||||||
|
|
||||||
@Schema(description = "用户名", required = true)
|
@Schema(description = "手机号码")
|
||||||
@NotBlank(message = "{sysuser.username.require}")
|
@NotBlank(message = "{sysuser.username.require}")
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@@ -27,6 +27,6 @@ public class LoginDTO implements Serializable {
|
|||||||
|
|
||||||
@Schema(description = "唯一标识")
|
@Schema(description = "唯一标识")
|
||||||
@NotBlank(message = "{sysuser.uuid.require}")
|
@NotBlank(message = "{sysuser.uuid.require}")
|
||||||
private String uuid;
|
private String captchaId;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,8 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.apache.shiro.authc.AuthenticationException;
|
import org.apache.shiro.authc.AuthenticationException;
|
||||||
import org.apache.shiro.authc.AuthenticationToken;
|
import org.apache.shiro.authc.AuthenticationToken;
|
||||||
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
|
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import xiaozhi.common.constant.Constant;
|
import xiaozhi.common.constant.Constant;
|
||||||
import xiaozhi.common.exception.ErrorCode;
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
@@ -24,12 +26,15 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class Oauth2Filter extends AuthenticatingFilter {
|
public class Oauth2Filter extends AuthenticatingFilter {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Oauth2Filter.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
|
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
|
||||||
//获取请求token
|
//获取请求token
|
||||||
String token = getRequestToken((HttpServletRequest) request);
|
String token = getRequestToken((HttpServletRequest) request);
|
||||||
|
|
||||||
if (StringUtils.isBlank(token)) {
|
if (StringUtils.isBlank(token)) {
|
||||||
|
logger.warn("createToken:token is empty");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +54,15 @@ public class Oauth2Filter extends AuthenticatingFilter {
|
|||||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
|
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
|
||||||
//获取请求token,如果token不存在,直接返回401
|
//获取请求token,如果token不存在,直接返回401
|
||||||
String token = getRequestToken((HttpServletRequest) request);
|
String token = getRequestToken((HttpServletRequest) request);
|
||||||
|
|
||||||
|
// TODO 调试接口,临时取消登录限制,需要 token 参数的除外
|
||||||
|
if (true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(token)) {
|
if (StringUtils.isBlank(token)) {
|
||||||
|
logger.warn("onAccessDenied:token is empty");
|
||||||
|
|
||||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||||
httpResponse.setContentType("application/json;charset=utf-8");
|
httpResponse.setContentType("application/json;charset=utf-8");
|
||||||
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
|
httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
|
||||||
@@ -73,13 +86,14 @@ public class Oauth2Filter extends AuthenticatingFilter {
|
|||||||
httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
|
httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
|
||||||
try {
|
try {
|
||||||
//处理登录失败的异常
|
//处理登录失败的异常
|
||||||
|
logger.error("onLoginFailure:登录失败!", e);
|
||||||
Throwable throwable = e.getCause() == null ? e : e.getCause();
|
Throwable throwable = e.getCause() == null ? e : e.getCause();
|
||||||
Result r = new Result().error(ErrorCode.UNAUTHORIZED, throwable.getMessage());
|
Result r = new Result().error(ErrorCode.UNAUTHORIZED, throwable.getMessage());
|
||||||
|
|
||||||
String json = JsonUtils.toJsonString(r);
|
String json = JsonUtils.toJsonString(r);
|
||||||
httpResponse.getWriter().print(json);
|
httpResponse.getWriter().print(json);
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
|
logger.error("onLoginFailure:登录失败! msg:{}", e1.getMessage(), e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -89,12 +103,11 @@ public class Oauth2Filter extends AuthenticatingFilter {
|
|||||||
* 获取请求的token
|
* 获取请求的token
|
||||||
*/
|
*/
|
||||||
private String getRequestToken(HttpServletRequest httpRequest) {
|
private String getRequestToken(HttpServletRequest httpRequest) {
|
||||||
|
String token = null;
|
||||||
//从header中获取token
|
//从header中获取token
|
||||||
String token = httpRequest.getHeader(Constant.TOKEN_HEADER);
|
String authorization = httpRequest.getHeader(Constant.AUTHORIZATION);
|
||||||
|
if (StringUtils.isNotBlank(authorization) && authorization.startsWith("Bearer ")) {
|
||||||
//如果header中不存在token,则从参数中获取token
|
token = authorization.replace("Bearer ", "");
|
||||||
if (StringUtils.isBlank(token)) {
|
|
||||||
token = httpRequest.getParameter(Constant.TOKEN_HEADER);
|
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
package xiaozhi.modules.security.oauth2;
|
package xiaozhi.modules.security.oauth2;
|
||||||
|
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.shiro.authc.*;
|
||||||
|
import org.apache.shiro.authz.AuthorizationInfo;
|
||||||
|
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
||||||
|
import org.apache.shiro.realm.AuthorizingRealm;
|
||||||
|
import org.apache.shiro.subject.PrincipalCollection;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
import xiaozhi.common.exception.ErrorCode;
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
import xiaozhi.common.user.UserDetail;
|
import xiaozhi.common.user.UserDetail;
|
||||||
import xiaozhi.common.utils.ConvertUtils;
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
@@ -7,16 +17,9 @@ import xiaozhi.common.utils.MessageUtils;
|
|||||||
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
||||||
import xiaozhi.modules.security.service.ShiroService;
|
import xiaozhi.modules.security.service.ShiroService;
|
||||||
import xiaozhi.modules.sys.entity.SysUserEntity;
|
import xiaozhi.modules.sys.entity.SysUserEntity;
|
||||||
import jakarta.annotation.Resource;
|
import xiaozhi.modules.sys.enums.SuperAdminEnum;
|
||||||
import org.apache.shiro.authc.*;
|
|
||||||
import org.apache.shiro.authz.AuthorizationInfo;
|
|
||||||
import org.apache.shiro.authz.SimpleAuthorizationInfo;
|
|
||||||
import org.apache.shiro.realm.AuthorizingRealm;
|
|
||||||
import org.apache.shiro.subject.PrincipalCollection;
|
|
||||||
import org.springframework.context.annotation.Lazy;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +33,8 @@ public class Oauth2Realm extends AuthorizingRealm {
|
|||||||
@Resource
|
@Resource
|
||||||
private ShiroService shiroService;
|
private ShiroService shiroService;
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Oauth2Realm.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(AuthenticationToken token) {
|
public boolean supports(AuthenticationToken token) {
|
||||||
return token instanceof Oauth2Token;
|
return token instanceof Oauth2Token;
|
||||||
@@ -43,7 +48,14 @@ public class Oauth2Realm extends AuthorizingRealm {
|
|||||||
UserDetail user = (UserDetail) principals.getPrimaryPrincipal();
|
UserDetail user = (UserDetail) principals.getPrimaryPrincipal();
|
||||||
|
|
||||||
//用户权限列表
|
//用户权限列表
|
||||||
Set<String> permsSet = shiroService.getUserPermissions(user);
|
Set<String> permsSet = new HashSet<>();
|
||||||
|
|
||||||
|
if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) {
|
||||||
|
permsSet.add("sys:role:superAdmin");
|
||||||
|
permsSet.add("sys:role:normal");
|
||||||
|
} else {
|
||||||
|
permsSet.add("sys:role:normal");
|
||||||
|
}
|
||||||
|
|
||||||
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
|
||||||
info.setStringPermissions(permsSet);
|
info.setStringPermissions(permsSet);
|
||||||
@@ -70,11 +82,14 @@ public class Oauth2Realm extends AuthorizingRealm {
|
|||||||
//转换成UserDetail对象
|
//转换成UserDetail对象
|
||||||
UserDetail userDetail = ConvertUtils.sourceToTarget(userEntity, UserDetail.class);
|
UserDetail userDetail = ConvertUtils.sourceToTarget(userEntity, UserDetail.class);
|
||||||
|
|
||||||
//获取用户对应的部门数据权限
|
|
||||||
userDetail.setDeptIdList(null);
|
|
||||||
userDetail.setToken(accessToken);
|
userDetail.setToken(accessToken);
|
||||||
|
|
||||||
//账号锁定
|
//账号锁定
|
||||||
|
if (userDetail.getStatus() == null) {
|
||||||
|
logger.error("账号状态异常,status 不能为空");
|
||||||
|
throw new DisabledAccountException(MessageUtils.getMessage(ErrorCode.ACCOUNT_DISABLE));
|
||||||
|
}
|
||||||
|
|
||||||
if (userDetail.getStatus() == 0) {
|
if (userDetail.getStatus() == 0) {
|
||||||
throw new LockedAccountException(MessageUtils.getMessage(ErrorCode.ACCOUNT_LOCK));
|
throw new LockedAccountException(MessageUtils.getMessage(ErrorCode.ACCOUNT_LOCK));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,14 @@
|
|||||||
package xiaozhi.modules.security.service;
|
package xiaozhi.modules.security.service;
|
||||||
|
|
||||||
import xiaozhi.common.user.UserDetail;
|
|
||||||
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
||||||
import xiaozhi.modules.sys.entity.SysUserEntity;
|
import xiaozhi.modules.sys.entity.SysUserEntity;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shiro相关接口
|
* shiro相关接口
|
||||||
* Copyright (c) 人人开源 All rights reserved.
|
* Copyright (c) 人人开源 All rights reserved.
|
||||||
* Website: https://www.renren.io
|
* Website: https://www.renren.io
|
||||||
*/
|
*/
|
||||||
public interface ShiroService {
|
public interface ShiroService {
|
||||||
/**
|
|
||||||
* 获取用户权限列表
|
|
||||||
*/
|
|
||||||
Set<String> getUserPermissions(UserDetail user);
|
|
||||||
|
|
||||||
SysUserTokenEntity getByToken(String token);
|
SysUserTokenEntity getByToken(String token);
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package xiaozhi.modules.security.service;
|
package xiaozhi.modules.security.service;
|
||||||
|
|
||||||
import xiaozhi.common.page.PageData;
|
import xiaozhi.common.page.TokenDTO;
|
||||||
import xiaozhi.common.service.BaseService;
|
import xiaozhi.common.service.BaseService;
|
||||||
import xiaozhi.common.utils.Result;
|
import xiaozhi.common.utils.Result;
|
||||||
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
||||||
|
import xiaozhi.modules.sys.dto.PasswordDTO;
|
||||||
import java.util.Map;
|
import xiaozhi.modules.sys.dto.SysUserDTO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户Token
|
* 用户Token
|
||||||
@@ -19,7 +19,9 @@ public interface SysUserTokenService extends BaseService<SysUserTokenEntity> {
|
|||||||
*
|
*
|
||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
*/
|
*/
|
||||||
Result createToken(Long userId);
|
Result<TokenDTO> createToken(Long userId);
|
||||||
|
|
||||||
|
SysUserDTO getUserByToken(String token);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退出
|
* 退出
|
||||||
@@ -28,4 +30,12 @@ public interface SysUserTokenService extends BaseService<SysUserTokenEntity> {
|
|||||||
*/
|
*/
|
||||||
void logout(Long userId);
|
void logout(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改密码
|
||||||
|
*
|
||||||
|
* @param userId
|
||||||
|
* @param passwordDTO
|
||||||
|
*/
|
||||||
|
void changePassword(Long userId, PasswordDTO passwordDTO);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,11 @@ import com.google.common.cache.Cache;
|
|||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.wf.captcha.SpecCaptcha;
|
import com.wf.captcha.SpecCaptcha;
|
||||||
import com.wf.captcha.base.Captcha;
|
import com.wf.captcha.base.Captcha;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import xiaozhi.common.redis.RedisKeys;
|
import xiaozhi.common.redis.RedisKeys;
|
||||||
import xiaozhi.common.redis.RedisUtils;
|
import xiaozhi.common.redis.RedisUtils;
|
||||||
|
import xiaozhi.modules.security.oauth2.Oauth2Realm;
|
||||||
import xiaozhi.modules.security.service.CaptchaService;
|
import xiaozhi.modules.security.service.CaptchaService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
@@ -29,6 +32,7 @@ public class CaptchaServiceImpl implements CaptchaService {
|
|||||||
* Local Cache 5分钟过期
|
* Local Cache 5分钟过期
|
||||||
*/
|
*/
|
||||||
Cache<String, String> localCache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(5, TimeUnit.MINUTES).build();
|
Cache<String, String> localCache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(5, TimeUnit.MINUTES).build();
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(Oauth2Realm.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void create(HttpServletResponse response, String uuid) throws IOException {
|
public void create(HttpServletResponse response, String uuid) throws IOException {
|
||||||
|
|||||||
@@ -19,22 +19,6 @@ public class ShiroServiceImpl implements ShiroService {
|
|||||||
private final SysUserDao sysUserDao;
|
private final SysUserDao sysUserDao;
|
||||||
private final SysUserTokenDao sysUserTokenDao;
|
private final SysUserTokenDao sysUserTokenDao;
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getUserPermissions(UserDetail user) {
|
|
||||||
//系统管理员,拥有最高权限
|
|
||||||
// TODO: 暂时写死,后续改成从数据库查询
|
|
||||||
List<String> permissionsList = new ArrayList<>();
|
|
||||||
//用户权限列表
|
|
||||||
Set<String> permsSet = new HashSet<>();
|
|
||||||
for (String permissions : permissionsList) {
|
|
||||||
if (StringUtils.isBlank(permissions)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
permsSet.addAll(Arrays.asList(permissions.trim().split(",")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return permsSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SysUserTokenEntity getByToken(String token) {
|
public SysUserTokenEntity getByToken(String token) {
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package xiaozhi.modules.security.service.impl;
|
package xiaozhi.modules.security.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
|
import xiaozhi.common.exception.RenException;
|
||||||
import xiaozhi.common.page.TokenDTO;
|
import xiaozhi.common.page.TokenDTO;
|
||||||
import xiaozhi.common.service.impl.BaseServiceImpl;
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
import xiaozhi.common.utils.HttpContextUtils;
|
import xiaozhi.common.utils.HttpContextUtils;
|
||||||
@@ -9,19 +13,24 @@ import xiaozhi.modules.security.dao.SysUserTokenDao;
|
|||||||
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
import xiaozhi.modules.security.entity.SysUserTokenEntity;
|
||||||
import xiaozhi.modules.security.oauth2.TokenGenerator;
|
import xiaozhi.modules.security.oauth2.TokenGenerator;
|
||||||
import xiaozhi.modules.security.service.SysUserTokenService;
|
import xiaozhi.modules.security.service.SysUserTokenService;
|
||||||
import org.springframework.stereotype.Service;
|
import xiaozhi.modules.sys.dto.PasswordDTO;
|
||||||
|
import xiaozhi.modules.sys.dto.SysUserDTO;
|
||||||
|
import xiaozhi.modules.sys.service.SysUserService;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
@Service
|
@Service
|
||||||
public class SysUserTokenServiceImpl extends BaseServiceImpl<SysUserTokenDao, SysUserTokenEntity> implements SysUserTokenService {
|
public class SysUserTokenServiceImpl extends BaseServiceImpl<SysUserTokenDao, SysUserTokenEntity> implements SysUserTokenService {
|
||||||
|
|
||||||
|
private final SysUserService sysUserService;
|
||||||
/**
|
/**
|
||||||
* 12小时后过期
|
* 12小时后过期
|
||||||
*/
|
*/
|
||||||
private final static int EXPIRE = 3600 * 12;
|
private final static int EXPIRE = 3600 * 12;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result createToken(Long userId) {
|
public Result<TokenDTO> createToken(Long userId) {
|
||||||
//用户token
|
//用户token
|
||||||
String token;
|
String token;
|
||||||
|
|
||||||
@@ -70,9 +79,36 @@ public class SysUserTokenServiceImpl extends BaseServiceImpl<SysUserTokenDao, Sy
|
|||||||
return new Result().ok(tokenDTO);
|
return new Result().ok(tokenDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SysUserDTO getUserByToken(String token) {
|
||||||
|
SysUserTokenEntity userToken = baseDao.getByToken(token);
|
||||||
|
if (null == userToken) {
|
||||||
|
throw new RenException(ErrorCode.TOKEN_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Date now = new Date();
|
||||||
|
if (userToken.getExpireDate().before(now)) {
|
||||||
|
throw new RenException(ErrorCode.UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
SysUserDTO userDTO = sysUserService.getByUserId(userToken.getUserId());
|
||||||
|
userDTO.setPassword("");
|
||||||
|
return userDTO;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void logout(Long userId) {
|
public void logout(Long userId) {
|
||||||
Date expireDate = DateUtil.offsetMinute(new Date(), -1);
|
Date expireDate = DateUtil.offsetMinute(new Date(), -1);
|
||||||
baseDao.logout(userId, expireDate);
|
baseDao.logout(userId, expireDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changePassword(Long userId, PasswordDTO passwordDTO) {
|
||||||
|
// 修改密码
|
||||||
|
sysUserService.changePassword(userId, passwordDTO);
|
||||||
|
|
||||||
|
// 使 token 失效,后需要重新登录
|
||||||
|
Date expireDate = DateUtil.offsetMinute(new Date(), -1);
|
||||||
|
baseDao.logout(userId, expireDate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -46,11 +46,4 @@ public class SecurityUser {
|
|||||||
public static Long getUserId() {
|
public static Long getUserId() {
|
||||||
return getUser().getId();
|
return getUser().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取部门ID
|
|
||||||
*/
|
|
||||||
public static Long getDeptId() {
|
|
||||||
return getUser().getDeptId();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,9 @@
|
|||||||
package xiaozhi.modules.sys.controller;
|
package xiaozhi.modules.sys.controller;
|
||||||
|
|
||||||
import xiaozhi.common.annotation.LogOperation;
|
|
||||||
import xiaozhi.common.constant.Constant;
|
|
||||||
import xiaozhi.common.exception.ErrorCode;
|
|
||||||
import xiaozhi.common.exception.RenException;
|
|
||||||
import xiaozhi.common.page.PageData;
|
|
||||||
import xiaozhi.common.user.UserDetail;
|
|
||||||
import xiaozhi.common.utils.ConvertUtils;
|
|
||||||
import xiaozhi.common.utils.Result;
|
|
||||||
import xiaozhi.common.validator.AssertUtils;
|
|
||||||
import xiaozhi.common.validator.ValidatorUtils;
|
|
||||||
import xiaozhi.common.validator.group.AddGroup;
|
|
||||||
import xiaozhi.common.validator.group.DefaultGroup;
|
|
||||||
import xiaozhi.common.validator.group.UpdateGroup;
|
|
||||||
import xiaozhi.modules.security.password.PasswordUtils;
|
|
||||||
import xiaozhi.modules.security.user.SecurityUser;
|
|
||||||
import xiaozhi.modules.sys.dto.PasswordDTO;
|
|
||||||
import xiaozhi.modules.sys.dto.SysUserDTO;
|
|
||||||
import xiaozhi.modules.sys.service.SysUserService;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameters;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户管理
|
* 用户管理
|
||||||
@@ -38,119 +13,5 @@ import java.util.Map;
|
|||||||
@RequestMapping("/sys/user")
|
@RequestMapping("/sys/user")
|
||||||
@Tag(name = "用户管理")
|
@Tag(name = "用户管理")
|
||||||
public class SysUserController {
|
public class SysUserController {
|
||||||
private final SysUserService sysUserService;
|
|
||||||
|
|
||||||
@GetMapping("page")
|
|
||||||
@Operation(summary = "分页")
|
|
||||||
@Parameters({
|
|
||||||
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true),
|
|
||||||
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true),
|
|
||||||
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段"),
|
|
||||||
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
|
|
||||||
@Parameter(name = "username", description = "用户名"),
|
|
||||||
@Parameter(name = "gender", description = "性别"),
|
|
||||||
@Parameter(name = "deptId", description = "部门ID")
|
|
||||||
})
|
|
||||||
@RequiresPermissions("sys:user:page")
|
|
||||||
public Result<PageData<SysUserDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
|
||||||
PageData<SysUserDTO> page = sysUserService.page(params);
|
|
||||||
|
|
||||||
return new Result<PageData<SysUserDTO>>().ok(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("{id}")
|
|
||||||
@Operation(summary = "信息")
|
|
||||||
@RequiresPermissions("sys:user:info")
|
|
||||||
public Result<SysUserDTO> get(@PathVariable("id") Long id) {
|
|
||||||
SysUserDTO data = sysUserService.get(id);
|
|
||||||
return new Result<SysUserDTO>().ok(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("info")
|
|
||||||
@Operation(summary = "登录用户信息")
|
|
||||||
public Result<SysUserDTO> info() {
|
|
||||||
SysUserDTO data = ConvertUtils.sourceToTarget(SecurityUser.getUser(), SysUserDTO.class);
|
|
||||||
return new Result<SysUserDTO>().ok(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("password")
|
|
||||||
@Operation(summary = "修改密码")
|
|
||||||
@LogOperation("修改密码")
|
|
||||||
public Result password(@RequestBody PasswordDTO dto) {
|
|
||||||
//效验数据
|
|
||||||
ValidatorUtils.validateEntity(dto);
|
|
||||||
String newPassword = dto.getNewPassword();
|
|
||||||
String password = dto.getPassword();
|
|
||||||
|
|
||||||
//密码的强度
|
|
||||||
if (newPassword == null || newPassword.length() < 8) {
|
|
||||||
return new Result().error(ErrorCode.PASSWORD_LENGTH_ERROR);
|
|
||||||
}
|
|
||||||
if (!sysUserService.isStrongPassword(newPassword)) {
|
|
||||||
return new Result().error(ErrorCode.PASSWORD_WEAK_ERROR);
|
|
||||||
}
|
|
||||||
UserDetail user = SecurityUser.getUser();
|
|
||||||
//原密码不正确
|
|
||||||
if (!PasswordUtils.matches(dto.getPassword(), user.getPassword())) {
|
|
||||||
return new Result().error(ErrorCode.PASSWORD_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
sysUserService.updatePassword(user.getId(), dto.getNewPassword());
|
|
||||||
|
|
||||||
return new Result();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping
|
|
||||||
@Operation(summary = "保存")
|
|
||||||
@LogOperation("保存")
|
|
||||||
@RequiresPermissions("sys:user:save")
|
|
||||||
public Result save(@RequestBody SysUserDTO dto) {
|
|
||||||
//效验数据
|
|
||||||
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
|
|
||||||
|
|
||||||
sysUserService.save(dto);
|
|
||||||
|
|
||||||
return new Result();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping
|
|
||||||
@Operation(summary = "修改")
|
|
||||||
@LogOperation("修改")
|
|
||||||
@RequiresPermissions("sys:user:update")
|
|
||||||
public Result update(@RequestBody SysUserDTO dto) {
|
|
||||||
//效验数据
|
|
||||||
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
|
|
||||||
|
|
||||||
sysUserService.update(dto);
|
|
||||||
|
|
||||||
return new Result();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("app")
|
|
||||||
@Operation(summary = "修改")
|
|
||||||
@LogOperation("修改")
|
|
||||||
@RequiresPermissions("sys:user:update")
|
|
||||||
public Result updateUserInfo(@RequestBody SysUserDTO dto) {
|
|
||||||
sysUserService.updateUserInfo(dto);
|
|
||||||
|
|
||||||
return new Result();
|
|
||||||
}
|
|
||||||
|
|
||||||
@DeleteMapping
|
|
||||||
@Operation(summary = "删除")
|
|
||||||
@LogOperation("删除")
|
|
||||||
@RequiresPermissions("sys:user:delete")
|
|
||||||
public Result delete(@RequestBody Long[] ids) {
|
|
||||||
//效验数据
|
|
||||||
AssertUtils.isArrayEmpty(ids, "id");
|
|
||||||
|
|
||||||
List<Long> idList = Arrays.asList(ids);
|
|
||||||
if (idList.contains(SecurityUser.getUserId())) {
|
|
||||||
throw new RenException(ErrorCode.DEL_MYSELF_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
sysUserService.deleteBatchIds(idList);
|
|
||||||
|
|
||||||
return new Result();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,8 @@
|
|||||||
package xiaozhi.modules.sys.dao;
|
package xiaozhi.modules.sys.dao;
|
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import xiaozhi.common.dao.BaseDao;
|
import xiaozhi.common.dao.BaseDao;
|
||||||
import xiaozhi.modules.sys.entity.SysUserEntity;
|
import xiaozhi.modules.sys.entity.SysUserEntity;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
|
||||||
import org.apache.ibatis.annotations.Param;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统用户
|
* 系统用户
|
||||||
@@ -14,21 +10,4 @@ import java.util.Map;
|
|||||||
@Mapper
|
@Mapper
|
||||||
public interface SysUserDao extends BaseDao<SysUserEntity> {
|
public interface SysUserDao extends BaseDao<SysUserEntity> {
|
||||||
|
|
||||||
List<SysUserEntity> getList(Map<String, Object> params);
|
|
||||||
|
|
||||||
SysUserEntity getById(Long id);
|
|
||||||
|
|
||||||
SysUserEntity getByUsername(String username);
|
|
||||||
|
|
||||||
int updatePassword(@Param("id") Long id, @Param("newPassword") String newPassword);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据部门ID,查询用户数
|
|
||||||
*/
|
|
||||||
int getCountByDeptId(Long deptId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据部门ID,查询用户ID列表
|
|
||||||
*/
|
|
||||||
List<Long> getUserIdListByDeptId(List<Long> deptIdList);
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package xiaozhi.modules.sys.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员分页用户的参数DTO
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "音色分页参数")
|
||||||
|
public class AdminPageUserDTO {
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(description = "手机号码")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
@Schema(description = "页数")
|
||||||
|
private String page;
|
||||||
|
|
||||||
|
@Schema(description = "显示列数")
|
||||||
|
private String limit;
|
||||||
|
}
|
||||||
@@ -3,9 +3,9 @@ package xiaozhi.modules.sys.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.FieldFill;
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import xiaozhi.common.entity.BaseEntity;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import xiaozhi.common.entity.BaseEntity;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@@ -24,30 +24,6 @@ public class SysUserEntity extends BaseEntity {
|
|||||||
* 密码
|
* 密码
|
||||||
*/
|
*/
|
||||||
private String password;
|
private String password;
|
||||||
/**
|
|
||||||
* 姓名
|
|
||||||
*/
|
|
||||||
private String realName;
|
|
||||||
/**
|
|
||||||
* 头像
|
|
||||||
*/
|
|
||||||
private String headUrl;
|
|
||||||
/**
|
|
||||||
* 性别 0:男 1:女 2:保密
|
|
||||||
*/
|
|
||||||
private Integer gender;
|
|
||||||
/**
|
|
||||||
* 邮箱
|
|
||||||
*/
|
|
||||||
private String email;
|
|
||||||
/**
|
|
||||||
* 手机号
|
|
||||||
*/
|
|
||||||
private String mobile;
|
|
||||||
/**
|
|
||||||
* 部门ID
|
|
||||||
*/
|
|
||||||
private Long deptId;
|
|
||||||
/**
|
/**
|
||||||
* 超级管理员 0:否 1:是
|
* 超级管理员 0:否 1:是
|
||||||
*/
|
*/
|
||||||
@@ -66,10 +42,5 @@ public class SysUserEntity extends BaseEntity {
|
|||||||
*/
|
*/
|
||||||
@TableField(fill = FieldFill.INSERT_UPDATE)
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
private Date updateDate;
|
private Date updateDate;
|
||||||
/**
|
|
||||||
* 部门名称
|
|
||||||
*/
|
|
||||||
@TableField(exist = false)
|
|
||||||
private String deptName;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,11 +2,11 @@ package xiaozhi.modules.sys.service;
|
|||||||
|
|
||||||
import xiaozhi.common.page.PageData;
|
import xiaozhi.common.page.PageData;
|
||||||
import xiaozhi.common.service.BaseService;
|
import xiaozhi.common.service.BaseService;
|
||||||
|
import xiaozhi.modules.sys.dto.AdminPageUserDTO;
|
||||||
|
import xiaozhi.modules.sys.dto.PasswordDTO;
|
||||||
import xiaozhi.modules.sys.dto.SysUserDTO;
|
import xiaozhi.modules.sys.dto.SysUserDTO;
|
||||||
import xiaozhi.modules.sys.entity.SysUserEntity;
|
import xiaozhi.modules.sys.entity.SysUserEntity;
|
||||||
|
import xiaozhi.modules.sys.vo.AdminPageUserVO;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,54 +14,38 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public interface SysUserService extends BaseService<SysUserEntity> {
|
public interface SysUserService extends BaseService<SysUserEntity> {
|
||||||
|
|
||||||
PageData<SysUserDTO> page(Map<String, Object> params);
|
|
||||||
|
|
||||||
List<SysUserDTO> list(Map<String, Object> params);
|
|
||||||
|
|
||||||
SysUserDTO get(Long id);
|
|
||||||
|
|
||||||
SysUserDTO getByUsername(String username);
|
SysUserDTO getByUsername(String username);
|
||||||
|
|
||||||
|
SysUserDTO getByUserId(Long userId);
|
||||||
|
|
||||||
void save(SysUserDTO dto);
|
void save(SysUserDTO dto);
|
||||||
|
|
||||||
void update(SysUserDTO dto);
|
|
||||||
|
|
||||||
void updateUserInfo(SysUserDTO dto);
|
|
||||||
|
|
||||||
void delete(Long[] ids);
|
void delete(Long[] ids);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改密码
|
* 验证是否允许修改密码更改
|
||||||
*
|
* @param userId 用户id
|
||||||
* @param id 用户ID
|
* @param passwordDTO 验证密码的参数
|
||||||
* @param newPassword 新密码
|
|
||||||
*/
|
*/
|
||||||
void updatePassword(Long id, String newPassword);
|
void changePassword(Long userId, PasswordDTO passwordDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据部门ID,查询用户数
|
* 直接修改密码,不需要验证
|
||||||
|
* @param userId 用户id
|
||||||
|
* @param password 密码
|
||||||
*/
|
*/
|
||||||
int getCountByDeptId(Long deptId);
|
void changePasswordDirectly(Long userId, String password);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据部门ID,查询用户Id列表
|
* 重置密码
|
||||||
|
* @param userId 用户id
|
||||||
|
* @return 随机生成符合规范的密码
|
||||||
*/
|
*/
|
||||||
List<Long> getUserIdListByDeptId(List<Long> deptIdList);
|
String resetPassword(Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除用户缓存
|
* 管理员分页用户信息
|
||||||
*
|
* @param dto 分页查找参数
|
||||||
* @param userId
|
* @return 用户列表分页数据
|
||||||
*/
|
*/
|
||||||
void deleteUserCache(Long userId);
|
PageData<AdminPageUserVO> page(AdminPageUserDTO dto);
|
||||||
|
|
||||||
/**
|
|
||||||
* 验证密码强度
|
|
||||||
*
|
|
||||||
* @param newPassword
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
boolean isStrongPassword(String newPassword);
|
|
||||||
|
|
||||||
String getName(Long creator);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,28 @@
|
|||||||
package xiaozhi.modules.sys.service.impl;
|
package xiaozhi.modules.sys.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import xiaozhi.common.exception.ErrorCode;
|
|
||||||
import xiaozhi.common.exception.RenException;
|
|
||||||
import xiaozhi.common.page.PageData;
|
|
||||||
import xiaozhi.common.redis.RedisKeys;
|
|
||||||
import xiaozhi.common.redis.RedisUtils;
|
|
||||||
import xiaozhi.common.service.impl.BaseServiceImpl;
|
|
||||||
import xiaozhi.common.user.UserDetail;
|
|
||||||
import xiaozhi.common.utils.ConvertUtils;
|
|
||||||
import xiaozhi.modules.security.password.PasswordUtils;
|
|
||||||
import xiaozhi.modules.security.user.SecurityUser;
|
|
||||||
import xiaozhi.modules.sys.dao.SysUserDao;
|
|
||||||
import xiaozhi.modules.sys.dto.SysUserDTO;
|
|
||||||
import xiaozhi.modules.sys.entity.SysUserEntity;
|
|
||||||
import xiaozhi.modules.sys.enums.SuperAdminEnum;
|
|
||||||
import xiaozhi.modules.sys.service.SysUserService;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xiaozhi.common.constant.Constant;
|
||||||
|
import xiaozhi.common.exception.ErrorCode;
|
||||||
|
import xiaozhi.common.exception.RenException;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
|
import xiaozhi.modules.security.password.PasswordUtils;
|
||||||
|
import xiaozhi.modules.sys.dao.SysUserDao;
|
||||||
|
import xiaozhi.modules.sys.dto.AdminPageUserDTO;
|
||||||
|
import xiaozhi.modules.sys.dto.PasswordDTO;
|
||||||
|
import xiaozhi.modules.sys.dto.SysUserDTO;
|
||||||
|
import xiaozhi.modules.sys.entity.SysUserEntity;
|
||||||
|
import xiaozhi.modules.sys.enums.SuperAdminEnum;
|
||||||
|
import xiaozhi.modules.sys.service.SysUserService;
|
||||||
|
import xiaozhi.modules.sys.vo.AdminPageUserVO;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -34,43 +33,27 @@ import java.util.regex.Pattern;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Service
|
@Service
|
||||||
public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {
|
public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {
|
||||||
private final RedisUtils redisUtils;
|
private final SysUserDao sysUserDao;
|
||||||
|
|
||||||
@Override
|
|
||||||
public PageData<SysUserDTO> page(Map<String, Object> params) {
|
|
||||||
//转换成like
|
|
||||||
paramsToLike(params, "username");
|
|
||||||
|
|
||||||
//分页
|
|
||||||
IPage<SysUserEntity> page = getPage(params, "t1.create_date", false);
|
|
||||||
|
|
||||||
//查询
|
|
||||||
List<SysUserEntity> list = baseDao.getList(params);
|
|
||||||
|
|
||||||
return getPageData(list, page.getTotal(), SysUserDTO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<SysUserDTO> list(Map<String, Object> params) {
|
|
||||||
|
|
||||||
List<SysUserEntity> entityList = baseDao.getList(params);
|
|
||||||
|
|
||||||
return ConvertUtils.sourceToTarget(entityList, SysUserDTO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SysUserDTO get(Long id) {
|
|
||||||
SysUserEntity entity = baseDao.getById(id);
|
|
||||||
|
|
||||||
return ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SysUserDTO getByUsername(String username) {
|
public SysUserDTO getByUsername(String username) {
|
||||||
SysUserEntity entity = baseDao.getByUsername(username);
|
QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("username", username);
|
||||||
|
List<SysUserEntity> users = sysUserDao.selectList(queryWrapper);
|
||||||
|
if (users == null || users.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
SysUserEntity entity = users.getFirst();
|
||||||
return ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
|
return ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SysUserDTO getByUserId(Long userId) {
|
||||||
|
SysUserEntity sysUserEntity = sysUserDao.selectById(userId);
|
||||||
|
|
||||||
|
return ConvertUtils.sourceToTarget(sysUserEntity, SysUserDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void save(SysUserDTO dto) {
|
public void save(SysUserDTO dto) {
|
||||||
@@ -86,42 +69,15 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntit
|
|||||||
entity.setPassword(password);
|
entity.setPassword(password);
|
||||||
|
|
||||||
//保存用户
|
//保存用户
|
||||||
entity.setSuperAdmin(SuperAdminEnum.NO.value());
|
Long userCount = getUserCount();
|
||||||
insert(entity);
|
if (userCount == 0) {
|
||||||
}
|
entity.setSuperAdmin(SuperAdminEnum.YES.value());
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void update(SysUserDTO dto) {
|
|
||||||
SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);
|
|
||||||
|
|
||||||
//密码加密
|
|
||||||
if (StringUtils.isBlank(dto.getPassword())) {
|
|
||||||
entity.setPassword(null);
|
|
||||||
} else {
|
} else {
|
||||||
//密码强度
|
entity.setSuperAdmin(SuperAdminEnum.NO.value());
|
||||||
if (!isStrongPassword(entity.getPassword())) {
|
|
||||||
throw new RenException(ErrorCode.PASSWORD_WEAK_ERROR);
|
|
||||||
}
|
|
||||||
String password = PasswordUtils.encode(entity.getPassword());
|
|
||||||
entity.setPassword(password);
|
|
||||||
}
|
}
|
||||||
|
entity.setStatus(1);
|
||||||
|
|
||||||
//更新用户
|
insert(entity);
|
||||||
updateById(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void updateUserInfo(SysUserDTO dto) {
|
|
||||||
SysUserEntity entity = selectById(dto.getId());
|
|
||||||
entity.setHeadUrl(dto.getHeadUrl());
|
|
||||||
entity.setRealName(dto.getRealName());
|
|
||||||
entity.setGender(dto.getGender());
|
|
||||||
entity.setMobile(dto.getMobile());
|
|
||||||
entity.setEmail(dto.getEmail());
|
|
||||||
|
|
||||||
updateById(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -129,36 +85,81 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntit
|
|||||||
public void delete(Long[] ids) {
|
public void delete(Long[] ids) {
|
||||||
//删除用户
|
//删除用户
|
||||||
baseDao.deleteBatchIds(Arrays.asList(ids));
|
baseDao.deleteBatchIds(Arrays.asList(ids));
|
||||||
|
//TODO 除了要删除用户还要删除用户关联的设备,对话,智能体。等此3个功能完善在添加
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void updatePassword(Long id, String newPassword) {
|
public void changePassword(Long userId, PasswordDTO passwordDTO) {
|
||||||
newPassword = PasswordUtils.encode(newPassword);
|
SysUserEntity sysUserEntity = sysUserDao.selectById(userId);
|
||||||
|
|
||||||
baseDao.updatePassword(id, newPassword);
|
if (null == sysUserEntity) {
|
||||||
|
throw new RenException(ErrorCode.TOKEN_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断旧密码是否正确
|
||||||
|
if (!PasswordUtils.matches(passwordDTO.getPassword(), sysUserEntity.getPassword())) {
|
||||||
|
throw new RenException("旧密码输入错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
//新密码强度
|
||||||
|
if (!isStrongPassword(passwordDTO.getNewPassword())) {
|
||||||
|
throw new RenException(ErrorCode.PASSWORD_WEAK_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
//密码加密
|
||||||
|
String password = PasswordUtils.encode(passwordDTO.getNewPassword());
|
||||||
|
sysUserEntity.setPassword(password);
|
||||||
|
|
||||||
|
updateById(sysUserEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void changePasswordDirectly(Long userId, String password) {
|
||||||
|
SysUserEntity sysUserEntity = new SysUserEntity();
|
||||||
|
sysUserEntity.setId(userId);
|
||||||
|
sysUserEntity.setPassword(PasswordUtils.encode(password));
|
||||||
|
updateById(sysUserEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCountByDeptId(Long deptId) {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
return baseDao.getCountByDeptId(deptId);
|
public String resetPassword(Long userId) {
|
||||||
|
String password = generatePassword();
|
||||||
|
changePasswordDirectly(userId,password);
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long getUserCount() {
|
||||||
|
QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
|
||||||
|
return baseDao.selectCount(queryWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Long> getUserIdListByDeptId(List<Long> deptIdList) {
|
public PageData<AdminPageUserVO> page(AdminPageUserDTO dto) {
|
||||||
return baseDao.getUserIdListByDeptId(deptIdList);
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
params.put(Constant.PAGE, dto.getPage());
|
||||||
|
params.put(Constant.LIMIT,dto.getLimit());
|
||||||
|
IPage<SysUserEntity> page = baseDao.selectPage(
|
||||||
|
getPage(params, "id", true),
|
||||||
|
//定义查询条件
|
||||||
|
new QueryWrapper<SysUserEntity>()
|
||||||
|
//必须按照手机号码查找
|
||||||
|
.eq(StringUtils.isNotBlank(dto.getMobile()),"username",dto.getMobile()));
|
||||||
|
List<AdminPageUserVO> list = page.getRecords().stream().map(user -> {
|
||||||
|
AdminPageUserVO adminPageUserVO = new AdminPageUserVO();
|
||||||
|
adminPageUserVO.setUserid(user.getId().toString());
|
||||||
|
adminPageUserVO.setMobile(user.getUsername());
|
||||||
|
//TODO 2. 等设备功能写好,获取对应数据
|
||||||
|
adminPageUserVO.setDeviceCount("0");
|
||||||
|
return adminPageUserVO;
|
||||||
|
}).toList();
|
||||||
|
return new PageData<>(list, page.getTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private boolean isStrongPassword(String password) {
|
||||||
public void deleteUserCache(Long userId) {
|
|
||||||
// 删除缓存
|
|
||||||
redisUtils.delete(RedisKeys.getUserInfoKey(userId));
|
|
||||||
redisUtils.delete(RedisKeys.getDataScopeListKey(userId));
|
|
||||||
redisUtils.delete(RedisKeys.getSysUserName(userId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isStrongPassword(String password) {
|
|
||||||
// 弱密码的正则表达式
|
// 弱密码的正则表达式
|
||||||
String weakPasswordRegex = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).+$";
|
String weakPasswordRegex = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).+$";
|
||||||
Pattern pattern = Pattern.compile(weakPasswordRegex);
|
Pattern pattern = Pattern.compile(weakPasswordRegex);
|
||||||
@@ -166,16 +167,18 @@ public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntit
|
|||||||
return matcher.matches();
|
return matcher.matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
|
||||||
public String getName(Long id) {
|
private static final Random random = new Random();
|
||||||
String name = (String) redisUtils.get(RedisKeys.getSysUserName(id));
|
/**
|
||||||
if (StringUtils.isBlank(name)) {
|
* 生成随机密码
|
||||||
SysUserEntity sysUserEntity = selectById(id);
|
* @return 随机生成的密码
|
||||||
if (sysUserEntity != null) {
|
*/
|
||||||
redisUtils.set(RedisKeys.getSysUserName(id), sysUserEntity.getUsername());
|
private String generatePassword(){
|
||||||
return sysUserEntity.getUsername();
|
StringBuilder password = new StringBuilder();
|
||||||
}
|
for (int i = 0; i < 10; i++) {
|
||||||
|
int randomIndex = random.nextInt(CHARACTERS.length());
|
||||||
|
password.append(CHARACTERS.charAt(randomIndex));
|
||||||
}
|
}
|
||||||
return name;
|
return password.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package xiaozhi.modules.sys.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理员分页展示用户的VO
|
||||||
|
* @ zjy
|
||||||
|
* @since 2025-3-25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AdminPageUserVO {
|
||||||
|
|
||||||
|
@Schema(description = "设备数量")
|
||||||
|
private String deviceCount;
|
||||||
|
|
||||||
|
@Schema(description = "手机号码")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
@Schema(description = "用户id")
|
||||||
|
private String userid;
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package xiaozhi.modules.timbre.controller;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import xiaozhi.common.constant.Constant;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.utils.Result;
|
||||||
|
import xiaozhi.common.validator.ValidatorUtils;
|
||||||
|
import xiaozhi.modules.timbre.dto.TimbreDataDTO;
|
||||||
|
import xiaozhi.modules.timbre.dto.TimbrePageDTO;
|
||||||
|
import xiaozhi.modules.timbre.service.TimbreService;
|
||||||
|
import xiaozhi.modules.timbre.vo.TimbreDetailsVO;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色控制层
|
||||||
|
*
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/ttsVoice")
|
||||||
|
@Tag(name = "音色管理")
|
||||||
|
public class TimbreController {
|
||||||
|
private final TimbreService timbreService;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
@Operation(summary = "分页查找")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = "ttsModelId", description = "对应 TTS 模型主键", required = true),
|
||||||
|
@Parameter(name = "name", description = "音色名称"),
|
||||||
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true),
|
||||||
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true),
|
||||||
|
})
|
||||||
|
public Result<PageData<TimbreDetailsVO>> page(
|
||||||
|
@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
TimbrePageDTO dto = new TimbrePageDTO();
|
||||||
|
dto.setTtsModelId((String) params.get("ttsModelId"));
|
||||||
|
dto.setName((String) params.get("name"));
|
||||||
|
dto.setLimit((String) params.get(Constant.LIMIT));
|
||||||
|
dto.setPage((String) params.get(Constant.PAGE));
|
||||||
|
|
||||||
|
ValidatorUtils.validateEntity(dto);
|
||||||
|
PageData<TimbreDetailsVO> page = timbreService.page(dto);
|
||||||
|
return new Result<PageData<TimbreDetailsVO>>().ok(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@Operation(summary = "音色保存")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<Void> save(@RequestBody TimbreDataDTO dto) {
|
||||||
|
ValidatorUtils.validateEntity(dto);
|
||||||
|
timbreService.save(dto);
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/{id}")
|
||||||
|
@Operation(summary = "音色修改")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<Void> update(
|
||||||
|
@PathVariable Long id,
|
||||||
|
@RequestBody TimbreDataDTO dto) {
|
||||||
|
ValidatorUtils.validateEntity(dto);
|
||||||
|
timbreService.update(id, dto);
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@Operation(summary = "音色删除")
|
||||||
|
@RequiresPermissions("sys:role:superAdmin")
|
||||||
|
public Result<Void> delete(@PathVariable Long id) {
|
||||||
|
timbreService.delete(new Long[]{id});
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package xiaozhi.modules.timbre.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import xiaozhi.modules.timbre.entity.TimbreEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色持久层定义
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface TimbreDao extends BaseMapper<TimbreEntity> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package xiaozhi.modules.timbre.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色表数据DTO
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "音色表信息")
|
||||||
|
public class TimbreDataDTO {
|
||||||
|
|
||||||
|
@Schema(description = "语言")
|
||||||
|
@NotBlank(message = "{timbre.languages.require}")
|
||||||
|
private String languages;
|
||||||
|
|
||||||
|
@Schema(description = "音色名称")
|
||||||
|
@NotBlank(message = "{timbre.name.require}")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
@NotBlank(message = "{timbre.remark.require}")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
@Min(value = 0, message = "{sort.number}")
|
||||||
|
private long sort;
|
||||||
|
|
||||||
|
@Schema(description = "对应 TTS 模型主键")
|
||||||
|
@NotBlank(message = "{timbre.ttsModelId.require}")
|
||||||
|
private String ttsModelId;
|
||||||
|
|
||||||
|
@Schema(description = "音色编码")
|
||||||
|
@NotBlank(message = "{timbre.ttsVoice.require}")
|
||||||
|
private String ttsVoice;
|
||||||
|
|
||||||
|
@Schema(description = "音频播放地址")
|
||||||
|
@NotBlank(message = "{timbre.voiceDemo.require}")
|
||||||
|
private String voiceDemo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package xiaozhi.modules.timbre.dto;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色分页参数DTO
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "音色分页参数")
|
||||||
|
public class TimbrePageDTO {
|
||||||
|
|
||||||
|
@Schema(description = "对应 TTS 模型主键")
|
||||||
|
@NotBlank(message = "{timbre.ttsModelId.require}")
|
||||||
|
private String ttsModelId;
|
||||||
|
|
||||||
|
@Schema(description = "音色名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "页数")
|
||||||
|
private String page;
|
||||||
|
|
||||||
|
@Schema(description = "显示列数")
|
||||||
|
private String limit;
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package xiaozhi.modules.timbre.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import xiaozhi.common.entity.BaseEntity;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色表实体类
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
@TableName("ai_tts_voice")
|
||||||
|
@Schema(description = "音色信息")
|
||||||
|
public class TimbreEntity extends BaseEntity {
|
||||||
|
|
||||||
|
@Schema(description = "语言")
|
||||||
|
private String languages;
|
||||||
|
|
||||||
|
@Schema(description = "音色名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private long sort;
|
||||||
|
|
||||||
|
@Schema(description = "对应 TTS 模型主键")
|
||||||
|
private String ttsModelId;
|
||||||
|
|
||||||
|
@Schema(description = "音色编码")
|
||||||
|
private String ttsVoice;
|
||||||
|
|
||||||
|
@Schema(description = "音频播放地址")
|
||||||
|
private String voiceDemo;
|
||||||
|
|
||||||
|
@Schema(description = "更新者")
|
||||||
|
private Long updater;
|
||||||
|
|
||||||
|
@Schema(description = "更新时间")
|
||||||
|
private Date updateDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package xiaozhi.modules.timbre.service;
|
||||||
|
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.service.BaseService;
|
||||||
|
import xiaozhi.modules.timbre.dto.TimbreDataDTO;
|
||||||
|
import xiaozhi.modules.timbre.dto.TimbrePageDTO;
|
||||||
|
import xiaozhi.modules.timbre.entity.TimbreEntity;
|
||||||
|
import xiaozhi.modules.timbre.vo.TimbreDetailsVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色的业务层的定义
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
public interface TimbreService extends BaseService<TimbreEntity> {
|
||||||
|
/**
|
||||||
|
* 分页获取音色指定tts的下的音色
|
||||||
|
* @param dto 分页查找参数
|
||||||
|
* @return 音色列表分页数据
|
||||||
|
*/
|
||||||
|
PageData<TimbreDetailsVO> page(TimbrePageDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取音色指定id的详情信息
|
||||||
|
* @param timbreId 音色表id
|
||||||
|
* @return 音色信息
|
||||||
|
*/
|
||||||
|
TimbreDetailsVO get(Long timbreId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存音色信息
|
||||||
|
* @param dto 需要保存数据
|
||||||
|
*/
|
||||||
|
void save(TimbreDataDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存音色信息
|
||||||
|
* @param timbreId 需要修改的id
|
||||||
|
* @param dto 需要修改的数据
|
||||||
|
*/
|
||||||
|
void update(Long timbreId,TimbreDataDTO dto);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除音色
|
||||||
|
* @param ids 需要被删除的音色id列表
|
||||||
|
*/
|
||||||
|
void delete(Long[] ids);
|
||||||
|
|
||||||
|
List<String> getVoiceNames(String ttsModelId, String voiceName);
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package xiaozhi.modules.timbre.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import xiaozhi.common.constant.Constant;
|
||||||
|
import xiaozhi.common.page.PageData;
|
||||||
|
import xiaozhi.common.service.impl.BaseServiceImpl;
|
||||||
|
import xiaozhi.common.utils.ConvertUtils;
|
||||||
|
import xiaozhi.modules.timbre.dao.TimbreDao;
|
||||||
|
import xiaozhi.modules.timbre.dto.TimbreDataDTO;
|
||||||
|
import xiaozhi.modules.timbre.dto.TimbrePageDTO;
|
||||||
|
import xiaozhi.modules.timbre.entity.TimbreEntity;
|
||||||
|
import xiaozhi.modules.timbre.service.TimbreService;
|
||||||
|
import xiaozhi.modules.timbre.vo.TimbreDetailsVO;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色的业务层的实现
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Service
|
||||||
|
public class TimbreServiceImpl extends BaseServiceImpl<TimbreDao, TimbreEntity> implements TimbreService {
|
||||||
|
|
||||||
|
private final TimbreDao timbreDao;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<TimbreDetailsVO> page(TimbrePageDTO dto) {
|
||||||
|
Map<String, Object> params = new HashMap<String, Object>();
|
||||||
|
params.put(Constant.PAGE, dto.getPage());
|
||||||
|
params.put(Constant.LIMIT,dto.getLimit());
|
||||||
|
IPage<TimbreEntity> page = baseDao.selectPage(
|
||||||
|
getPage(params, "sort", true),
|
||||||
|
//定义查询条件
|
||||||
|
new QueryWrapper<TimbreEntity>()
|
||||||
|
//必须按照ttsID查找
|
||||||
|
.eq("tts_model_id",dto.getTtsModelId())
|
||||||
|
//如果有音色名字,按照音色名模糊查找
|
||||||
|
.like(StringUtils.isNotBlank(dto.getName()),"name",dto.getName())
|
||||||
|
);
|
||||||
|
|
||||||
|
return getPageData(page, TimbreDetailsVO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimbreDetailsVO get(Long timbreId) {
|
||||||
|
TimbreEntity entity = baseDao.selectById(timbreId);
|
||||||
|
return ConvertUtils.sourceToTarget(entity, TimbreDetailsVO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void save(TimbreDataDTO dto) {
|
||||||
|
isTtsModelId(dto.getTtsModelId());
|
||||||
|
TimbreEntity timbreEntity = ConvertUtils.sourceToTarget(dto, TimbreEntity.class);
|
||||||
|
baseDao.insert(timbreEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void update(Long timbreId, TimbreDataDTO dto) {
|
||||||
|
isTtsModelId(dto.getTtsModelId());
|
||||||
|
TimbreEntity timbreEntity = ConvertUtils.sourceToTarget(dto, TimbreEntity.class);
|
||||||
|
timbreEntity.setId(timbreId);
|
||||||
|
baseDao.updateById(timbreEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void delete(Long[] ids) {
|
||||||
|
baseDao.deleteBatchIds(Arrays.asList(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getVoiceNames(String ttsModelId, String voiceName) {
|
||||||
|
QueryWrapper<TimbreEntity> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("ttsModelId", StringUtils.isBlank(ttsModelId) ? "" : ttsModelId);
|
||||||
|
if (StringUtils.isNotBlank(voiceName)) {
|
||||||
|
queryWrapper.like("name", voiceName);
|
||||||
|
}
|
||||||
|
List<TimbreEntity> timbreEntities = timbreDao.selectList(queryWrapper);
|
||||||
|
if (CollectionUtil.isEmpty(timbreEntities)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timbreEntities.stream().map(TimbreEntity::getName).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理是不是tts模型的id
|
||||||
|
*/
|
||||||
|
private void isTtsModelId(String ttsModelId){
|
||||||
|
//等模型配置那边写好调用方法判断
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package xiaozhi.modules.timbre.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 音色详情展示VO
|
||||||
|
* @author zjy
|
||||||
|
* @since 2025-3-21
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TimbreDetailsVO implements Serializable {
|
||||||
|
@Schema(description = "音色id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "语言")
|
||||||
|
private String languages;
|
||||||
|
|
||||||
|
@Schema(description = "音色名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@Schema(description = "排序")
|
||||||
|
private long sort;
|
||||||
|
|
||||||
|
@Schema(description = "对应 TTS 模型主键")
|
||||||
|
private String ttsModelId;
|
||||||
|
|
||||||
|
@Schema(description = "音色编码")
|
||||||
|
private String ttsVoice;
|
||||||
|
|
||||||
|
@Schema(description = "音频播放地址")
|
||||||
|
private String voiceDemo;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ server:
|
|||||||
min-spare: 30
|
min-spare: 30
|
||||||
port: 8002
|
port: 8002
|
||||||
servlet:
|
servlet:
|
||||||
context-path: /xiaozhi-esp32-api
|
context-path: /xiaozhi-esp32-api/api/v1
|
||||||
session:
|
session:
|
||||||
cookie:
|
cookie:
|
||||||
http-only: true
|
http-only: true
|
||||||
@@ -29,7 +29,7 @@ spring:
|
|||||||
database: 0
|
database: 0
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 6379
|
port: 6379
|
||||||
password: # 密码(默认为空)
|
password: # 密码(默认为空)
|
||||||
timeout: 6000ms # 连接超时时长(毫秒)
|
timeout: 6000ms # 连接超时时长(毫秒)
|
||||||
lettuce:
|
lettuce:
|
||||||
pool:
|
pool:
|
||||||
@@ -39,7 +39,6 @@ spring:
|
|||||||
min-idle: 5 # 连接池中的最小空闲连接
|
min-idle: 5 # 连接池中的最小空闲连接
|
||||||
main:
|
main:
|
||||||
allow-bean-definition-overriding: true
|
allow-bean-definition-overriding: true
|
||||||
|
|
||||||
knife4j:
|
knife4j:
|
||||||
enable: true
|
enable: true
|
||||||
basic:
|
basic:
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ CREATE TABLE sys_user (
|
|||||||
status tinyint COMMENT '状态 0:停用 1:正常',
|
status tinyint COMMENT '状态 0:停用 1:正常',
|
||||||
create_date datetime COMMENT '创建时间',
|
create_date datetime COMMENT '创建时间',
|
||||||
updater bigint COMMENT '更新者',
|
updater bigint COMMENT '更新者',
|
||||||
|
creator bigint COMMENT '创建者',
|
||||||
update_date datetime COMMENT '更新时间',
|
update_date datetime COMMENT '更新时间',
|
||||||
primary key (id),
|
primary key (id),
|
||||||
unique key uk_username (username),
|
unique key uk_username (username)
|
||||||
key idx_create_date (create_date)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户';
|
||||||
|
|
||||||
-- 系统用户Token
|
-- 系统用户Token
|
||||||
@@ -45,8 +45,7 @@ create table sys_params
|
|||||||
updater bigint COMMENT '更新者',
|
updater bigint COMMENT '更新者',
|
||||||
update_date datetime COMMENT '更新时间',
|
update_date datetime COMMENT '更新时间',
|
||||||
primary key (id),
|
primary key (id),
|
||||||
unique key uk_param_code (param_code),
|
unique key uk_param_code (param_code)
|
||||||
key idx_create_date (create_date)
|
|
||||||
)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='参数管理';
|
)ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4 COMMENT='参数管理';
|
||||||
|
|
||||||
-- 字典类型
|
-- 字典类型
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
-- 模型供应器表
|
||||||
|
DROP TABLE IF EXISTS `ai_model_provider`;
|
||||||
|
CREATE TABLE `ai_model_provider` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '主键',
|
||||||
|
`model_type` VARCHAR(20) COMMENT '模型类型(Memory/ASR/VAD/LLM/TTS)',
|
||||||
|
`provider_code` VARCHAR(50) COMMENT '供应器类型',
|
||||||
|
`name` VARCHAR(50) COMMENT '供应器名称',
|
||||||
|
`fields` JSON COMMENT '供应器字段列表(JSON格式)',
|
||||||
|
`sort` INT UNSIGNED DEFAULT 0 COMMENT '排序',
|
||||||
|
`creator` BIGINT COMMENT '创建者',
|
||||||
|
`create_date` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者',
|
||||||
|
`update_date` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
INDEX `idx_ai_model_provider_model_type` (`model_type`) COMMENT '创建模型类型的索引,用于快速查找特定类型下的所有供应器信息'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型配置表';
|
||||||
|
|
||||||
|
-- 模型配置表
|
||||||
|
DROP TABLE IF EXISTS `ai_model_config`;
|
||||||
|
CREATE TABLE `ai_model_config` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '主键',
|
||||||
|
`model_type` VARCHAR(20) COMMENT '模型类型(Memory/ASR/VAD/LLM/TTS)',
|
||||||
|
`model_code` VARCHAR(50) COMMENT '模型编码(如AliLLM、DoubaoTTS)',
|
||||||
|
`model_name` VARCHAR(50) COMMENT '模型名称',
|
||||||
|
`is_default` TINYINT(1) DEFAULT 0 COMMENT '是否默认配置(0否 1是)',
|
||||||
|
`is_enabled` TINYINT(1) DEFAULT 0 COMMENT '是否启用',
|
||||||
|
`config_json` JSON COMMENT '模型配置(JSON格式)',
|
||||||
|
`doc_link` VARCHAR(200) COMMENT '官方文档链接',
|
||||||
|
`remark` VARCHAR(255) COMMENT '备注',
|
||||||
|
`sort` INT UNSIGNED DEFAULT 0 COMMENT '排序',
|
||||||
|
`creator` BIGINT COMMENT '创建者',
|
||||||
|
`create_date` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者',
|
||||||
|
`update_date` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
INDEX `idx_ai_model_config_model_type` (`model_type`) COMMENT '创建模型类型的索引,用于快速查找特定类型下的所有配置信息'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='模型配置表';
|
||||||
|
|
||||||
|
-- TTS 音色表
|
||||||
|
DROP TABLE IF EXISTS `ai_tts_voice`;
|
||||||
|
CREATE TABLE `ai_tts_voice` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '主键',
|
||||||
|
`tts_model_id` VARCHAR(32) COMMENT '对应 TTS 模型主键',
|
||||||
|
`name` VARCHAR(20) COMMENT '音色名称',
|
||||||
|
`tts_voice` VARCHAR(50) COMMENT '音色编码',
|
||||||
|
`languages` VARCHAR(50) COMMENT '语言',
|
||||||
|
`voice_demo` VARCHAR(500) DEFAULT NULL COMMENT '音色 Demo',
|
||||||
|
`remark` VARCHAR(255) COMMENT '备注',
|
||||||
|
`sort` INT UNSIGNED DEFAULT 0 COMMENT '排序',
|
||||||
|
`creator` BIGINT COMMENT '创建者',
|
||||||
|
`create_date` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者',
|
||||||
|
`update_date` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
INDEX `idx_ai_tts_voice_tts_model_id` (`tts_model_id`) COMMENT '创建 TTS 模型主键的索引,用于快速查找对应模型的音色信息'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='TTS 音色表';
|
||||||
|
|
||||||
|
-- 智能体配置模板表
|
||||||
|
DROP TABLE IF EXISTS `ai_agent_template`;
|
||||||
|
CREATE TABLE `ai_agent_template` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '智能体唯一标识',
|
||||||
|
`agent_code` VARCHAR(36) COMMENT '智能体编码',
|
||||||
|
`agent_name` VARCHAR(64) COMMENT '智能体名称',
|
||||||
|
`asr_model_id` VARCHAR(32) COMMENT '语音识别模型标识',
|
||||||
|
`vad_model_id` VARCHAR(64) COMMENT '语音活动检测标识',
|
||||||
|
`llm_model_id` VARCHAR(32) COMMENT '大语言模型标识',
|
||||||
|
`tts_model_id` VARCHAR(32) COMMENT '语音合成模型标识',
|
||||||
|
`tts_voice_id` VARCHAR(32) COMMENT '音色标识',
|
||||||
|
`mem_model_id` VARCHAR(32) COMMENT '记忆模型标识',
|
||||||
|
`intent_model_id` VARCHAR(32) COMMENT '意图模型标识',
|
||||||
|
`system_prompt` TEXT COMMENT '角色设定参数',
|
||||||
|
`lang_code` VARCHAR(10) COMMENT '语言编码',
|
||||||
|
`language` VARCHAR(10) COMMENT '交互语种',
|
||||||
|
`sort` INT UNSIGNED DEFAULT 0 COMMENT '排序权重',
|
||||||
|
`creator` BIGINT COMMENT '创建者 ID',
|
||||||
|
`created_at` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者 ID',
|
||||||
|
`updated_at` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='智能体配置模板表';
|
||||||
|
|
||||||
|
-- 智能体配置表
|
||||||
|
DROP TABLE IF EXISTS `ai_agent`;
|
||||||
|
CREATE TABLE `ai_agent` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '智能体唯一标识',
|
||||||
|
`user_id` BIGINT COMMENT '所属用户 ID',
|
||||||
|
`agent_code` VARCHAR(36) COMMENT '智能体编码',
|
||||||
|
`agent_name` VARCHAR(64) COMMENT '智能体名称',
|
||||||
|
`asr_model_id` VARCHAR(32) COMMENT '语音识别模型标识',
|
||||||
|
`vad_model_id` VARCHAR(64) COMMENT '语音活动检测标识',
|
||||||
|
`llm_model_id` VARCHAR(32) COMMENT '大语言模型标识',
|
||||||
|
`tts_model_id` VARCHAR(32) COMMENT '语音合成模型标识',
|
||||||
|
`tts_voice_id` VARCHAR(32) COMMENT '音色标识',
|
||||||
|
`mem_model_id` VARCHAR(32) COMMENT '记忆模型标识',
|
||||||
|
`intent_model_id` VARCHAR(32) COMMENT '意图模型标识',
|
||||||
|
`system_prompt` TEXT COMMENT '角色设定参数',
|
||||||
|
`lang_code` VARCHAR(10) COMMENT '语言编码',
|
||||||
|
`language` VARCHAR(10) COMMENT '交互语种',
|
||||||
|
`sort` INT UNSIGNED DEFAULT 0 COMMENT '排序权重',
|
||||||
|
`creator` BIGINT COMMENT '创建者 ID',
|
||||||
|
`created_at` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者 ID',
|
||||||
|
`updated_at` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
INDEX `idx_ai_agent_user_id` (`user_id`) COMMENT '创建用户的索引,用于快速查找用户下的智能体信息'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='智能体配置表';
|
||||||
|
|
||||||
|
-- 设备信息表
|
||||||
|
DROP TABLE IF EXISTS `ai_device`;
|
||||||
|
CREATE TABLE `ai_device` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '设备唯一标识',
|
||||||
|
`user_id` BIGINT COMMENT '关联用户 ID',
|
||||||
|
`mac_address` VARCHAR(50) COMMENT 'MAC 地址',
|
||||||
|
`last_connected_at` DATETIME COMMENT '最后连接时间',
|
||||||
|
`auto_update` TINYINT UNSIGNED DEFAULT 0 COMMENT '自动更新开关(0 关闭/1 开启)',
|
||||||
|
`board` VARCHAR(50) COMMENT '设备硬件型号',
|
||||||
|
`alias` VARCHAR(64) DEFAULT NULL COMMENT '设备别名',
|
||||||
|
`agent_id` VARCHAR(32) COMMENT '智能体 ID',
|
||||||
|
`app_version` VARCHAR(20) COMMENT '固件版本号',
|
||||||
|
`sort` INT UNSIGNED DEFAULT 0 COMMENT '排序',
|
||||||
|
`creator` BIGINT COMMENT '创建者',
|
||||||
|
`create_date` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者',
|
||||||
|
`update_date` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
INDEX `idx_ai_device_created_at` (`mac_address`) COMMENT '创建mac的索引,用于快速查找设备信息'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='设备信息表';
|
||||||
|
|
||||||
|
-- 声纹识别表
|
||||||
|
DROP TABLE IF EXISTS `ai_voiceprint`;
|
||||||
|
CREATE TABLE `ai_voiceprint` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '声纹唯一标识',
|
||||||
|
`name` VARCHAR(64) COMMENT '声纹名称',
|
||||||
|
`user_id` BIGINT COMMENT '用户 ID(关联用户表)',
|
||||||
|
`agent_id` VARCHAR(32) COMMENT '关联智能体 ID',
|
||||||
|
`agent_code` VARCHAR(36) COMMENT '关联智能体编码',
|
||||||
|
`agent_name` VARCHAR(36) COMMENT '关联智能体名称',
|
||||||
|
`description` VARCHAR(255) COMMENT '声纹描述',
|
||||||
|
`embedding` LONGTEXT COMMENT '声纹特征向量(JSON 数组格式)',
|
||||||
|
`memory` TEXT COMMENT '关联记忆数据',
|
||||||
|
`sort` INT UNSIGNED DEFAULT 0 COMMENT '排序权重',
|
||||||
|
`creator` BIGINT COMMENT '创建者 ID',
|
||||||
|
`created_at` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者 ID',
|
||||||
|
`updated_at` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='声纹识别表';
|
||||||
|
|
||||||
|
-- 对话历史表
|
||||||
|
DROP TABLE IF EXISTS `ai_chat_history`;
|
||||||
|
CREATE TABLE `ai_chat_history` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '对话编号',
|
||||||
|
`user_id` BIGINT COMMENT '用户编号',
|
||||||
|
`agent_id` VARCHAR(32) DEFAULT NULL COMMENT '聊天角色',
|
||||||
|
`device_id` VARCHAR(32) DEFAULT NULL COMMENT '设备编号',
|
||||||
|
`message_count` INT COMMENT '信息汇总',
|
||||||
|
`creator` BIGINT COMMENT '创建者',
|
||||||
|
`create_date` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者',
|
||||||
|
`update_date` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='对话历史表';
|
||||||
|
|
||||||
|
-- 对话信息表
|
||||||
|
DROP TABLE IF EXISTS `ai_chat_message`;
|
||||||
|
CREATE TABLE `ai_chat_message` (
|
||||||
|
`id` VARCHAR(32) NOT NULL COMMENT '对话记录唯一标识',
|
||||||
|
`user_id` BIGINT COMMENT '用户唯一标识',
|
||||||
|
`chat_id` VARCHAR(64) COMMENT '对话历史 ID',
|
||||||
|
`role` ENUM('user', 'assistant') COMMENT '角色(用户或助理)',
|
||||||
|
`content` TEXT COMMENT '对话内容',
|
||||||
|
`prompt_tokens` INT UNSIGNED DEFAULT 0 COMMENT '提示令牌数',
|
||||||
|
`total_tokens` INT UNSIGNED DEFAULT 0 COMMENT '总令牌数',
|
||||||
|
`completion_tokens` INT UNSIGNED DEFAULT 0 COMMENT '完成令牌数',
|
||||||
|
`prompt_ms` INT UNSIGNED DEFAULT 0 COMMENT '提示耗时(毫秒)',
|
||||||
|
`total_ms` INT UNSIGNED DEFAULT 0 COMMENT '总耗时(毫秒)',
|
||||||
|
`completion_ms` INT UNSIGNED DEFAULT 0 COMMENT '完成耗时(毫秒)',
|
||||||
|
`creator` BIGINT COMMENT '创建者',
|
||||||
|
`create_date` DATETIME COMMENT '创建时间',
|
||||||
|
`updater` BIGINT COMMENT '更新者',
|
||||||
|
`update_date` DATETIME COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
INDEX `idx_ai_chat_message_user_id_chat_id_role` (`user_id`, `chat_id`) COMMENT '用户 ID、聊天会话 ID 和角色的联合索引,用于快速检索对话记录',
|
||||||
|
INDEX `idx_ai_chat_message_created_at` (`create_date`) COMMENT '创建时间的索引,用于按时间排序或检索对话记录'
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='对话信息表';
|
||||||
@@ -3,9 +3,16 @@
|
|||||||
# 每次对数据表进行改动时,只允许新建新对changeSet,不允许对上一个changeSet配置及文件进行修改
|
# 每次对数据表进行改动时,只允许新建新对changeSet,不允许对上一个changeSet配置及文件进行修改
|
||||||
databaseChangeLog:
|
databaseChangeLog:
|
||||||
- changeSet:
|
- changeSet:
|
||||||
id: 001create_sys
|
id: 202503141335
|
||||||
author: John
|
author: John
|
||||||
changes:
|
changes:
|
||||||
- sqlFile:
|
- sqlFile:
|
||||||
encoding: utf8
|
encoding: utf8
|
||||||
path: classpath:db/changelog/001create_sys.sql
|
path: classpath:db/changelog/202503141335.sql
|
||||||
|
- changeSet:
|
||||||
|
id: 202503141346
|
||||||
|
author: czc
|
||||||
|
changes:
|
||||||
|
- sqlFile:
|
||||||
|
encoding: utf8
|
||||||
|
path: classpath:db/changelog/202503141346.sql
|
||||||
@@ -9,7 +9,6 @@
|
|||||||
10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528
|
10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528
|
||||||
10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
|
10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
|
||||||
10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE
|
|
||||||
10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E
|
10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E
|
||||||
10010=\u8D26\u53F7\u6216\u5BC6\u7801\u4E0D\u6B63\u786E,\u60A8\u8FD8\u6709\u53EF\u4EE5\u5C1D\u8BD5{0}\u6B21
|
10010=\u8D26\u53F7\u6216\u5BC6\u7801\u4E0D\u6B63\u786E,\u60A8\u8FD8\u6709\u53EF\u4EE5\u5C1D\u8BD5{0}\u6B21
|
||||||
10011=\u4E0A\u7EA7\u90E8\u95E8\u9009\u62E9\u9519\u8BEF
|
10011=\u4E0A\u7EA7\u90E8\u95E8\u9009\u62E9\u9519\u8BEF
|
||||||
@@ -31,24 +30,7 @@
|
|||||||
10027=Redis\u670D\u52A1\u5F02\u5E38
|
10027=Redis\u670D\u52A1\u5F02\u5E38
|
||||||
10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25
|
10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25
|
||||||
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
|
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
|
||||||
10030=\u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u4F7F\u7528JSON\u683C\u5F0F
|
10030=\u5BC6\u7801\u957F\u5EA6\u4E0D\u8DB3{0}\u4F4D
|
||||||
10031=\u8BF7\u5148\u5B8C\u6210\u77ED\u4FE1\u914D\u7F6E
|
10031=\u5F31\u5BC6\u7801
|
||||||
10032=\u4EFB\u52A1\u5DF2\u88AB\u7B7E\u6536\uFF0C\u64CD\u4F5C\u5931\u8D25
|
10032=\u5220\u9664\u672C\u6570\u636E\u5F02\u5E38
|
||||||
10033=\u4E0D\u5B58\u5728\u7684\u6D41\u7A0B\u5B9A\u4E49
|
10033=\u8BBE\u5907\u9A8C\u8BC1\u7801\u9519\u8BEF
|
||||||
10034=\u4E0A\u7EA7\u8282\u70B9\u4E0D\u5B58\u5728
|
|
||||||
10035=\u9A73\u56DE
|
|
||||||
10036=\u56DE\u9000
|
|
||||||
10037=\u4EFB\u52A1\u6CA1\u6709\u5206\u7EC4\uFF0C\u65E0\u6CD5\u53D6\u6D88\u8BA4\u9886
|
|
||||||
10038=\u4E0A\u7EA7\u533A\u57DF\u9009\u62E9\u9519\u8BEF
|
|
||||||
10039=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u533A\u57DF
|
|
||||||
10040=\u6D41\u7A0B\u5DF2\u6302\u8D77\uFF0C\u4E0D\u80FD\u542F\u52A8\u5B9E\u4F8B
|
|
||||||
10041=\u591A\u5B9E\u4F8B\u4EFB\u52A1\u4E0D\u80FD\u9A73\u56DE
|
|
||||||
10042=\u5B58\u5728\u591A\u4E2A\u5904\u7406\u4E2D\u7684\u4EFB\u52A1\uFF0C\u4E0D\u80FD\u9A73\u56DE
|
|
||||||
10043=\u591A\u5B9E\u4F8B\u4EFB\u52A1\u4E0D\u80FD\u7EC8\u6B62
|
|
||||||
10044=\u5B58\u5728\u591A\u4E2A\u5904\u7406\u4E2D\u7684\u4EFB\u52A1\uFF0C\u4E0D\u80FD\u7EC8\u6B62\u6D41\u7A0B
|
|
||||||
10045=\u7EC8\u6B62
|
|
||||||
10046=\u591A\u5B9E\u4F8B\u4EFB\u52A1\u4E0D\u80FD\u56DE\u9000
|
|
||||||
10047=\u5B58\u5728\u591A\u4E2A\u5E76\u884C\u6267\u884C\u7684\u4EFB\u52A1\uFF0C\u4E0D\u80FD\u56DE\u9000
|
|
||||||
10048=\u767B\u5F55\u8D26\u53F7\uFF0C\u65E0\u6743\u5220\u9664
|
|
||||||
10055=\u60A8\u7684\u5BC6\u7801\u957F\u5EA6\u4E0D\u591F8\u4F4D
|
|
||||||
10056=\u60A8\u7684\u5BC6\u7801\u590D\u6742\u5EA6\u4E0D\u591F\uFF0C\u9700\u8981\u540C\u65F6\u5305\u542B\u6570\u5B57,\u5C0F\u5199\u82F1\u6587,\u5927\u5199\u82F1\u6587
|
|
||||||
|
|||||||
@@ -11,44 +11,25 @@
|
|||||||
10007=The verification code is incorrect
|
10007=The verification code is incorrect
|
||||||
10008=First delete submenu or button
|
10008=First delete submenu or button
|
||||||
10009=The original password is incorrect
|
10009=The original password is incorrect
|
||||||
10010=password error,you can try {0} times
|
|
||||||
10011=The superior department made a wrong choice
|
10011=The superior department made a wrong choice
|
||||||
10012=Upper menu cannot be for itself
|
10012=Upper menu cannot be for itself
|
||||||
10013=Data permission interface, which can only be a Map type parameter.
|
10013=Data permission interface, which can only be a Map type parameter.
|
||||||
10014=Please delete the subordinate department first
|
10014=Please delete the subordinate department first
|
||||||
10015=Please delete the user under the department first
|
10015=Please delete the user under the department first
|
||||||
10016=Deployment failed, no process
|
|
||||||
10017=Model diagram is incorrect, please check
|
|
||||||
10018=The export failed with the model ID {0}
|
|
||||||
10019=Please upload a file
|
10019=Please upload a file
|
||||||
10020=token cannot be empty
|
10020=token cannot be empty
|
||||||
10021=token is invalid, please log in again
|
10021=token is invalid, please log in again
|
||||||
10022=The account has been locked
|
10022=The account has been locked
|
||||||
10023=Please upload zip, bar, bpmn, bpmn20.xml format file
|
|
||||||
10024=Failed to upload file {0}
|
10024=Failed to upload file {0}
|
||||||
10025=Failed to send SMS {0}
|
|
||||||
10026=Mail template does not exist
|
|
||||||
10027=Redis service exception
|
10027=Redis service exception
|
||||||
10028=Timed task failed
|
10028=Timed task failed
|
||||||
10029=Cannot contain illegal characters
|
10029=Cannot contain illegal characters
|
||||||
10030=The parameter format is incorrect. Please use JSON format.
|
|
||||||
10031=Please complete the SMS configuration first.
|
10030=The password is less than {0} digits.
|
||||||
10032=Task has been signed and operation failed
|
10031=The password must consist of numbers, uppercase and lowercase letters, and special characters at the same time
|
||||||
10033=Non-existent process definition
|
10032=Exception in deleting this data
|
||||||
10034=Superior node does not exist
|
10033=Device verification code error
|
||||||
10035=Reject
|
|
||||||
10036=Rollback
|
|
||||||
10037=Tasks are not grouped and cannot be cancelled
|
|
||||||
10038=Upper area selection error
|
|
||||||
10039=Please delete the subordinate area first
|
|
||||||
10040=The process has been suspended and the instance cannot be started
|
|
||||||
10041=Multi-instance tasks cannot be rejected
|
|
||||||
10042=Tasks in multiple processes cannot be rejected
|
|
||||||
10043=Multi-instance tasks cannot be terminated
|
|
||||||
10044=There are tasks in multiple processes that cannot terminate the process
|
|
||||||
10045=END
|
|
||||||
10046=Multi-instance tasks cannot be rolled back
|
|
||||||
10047=There are multiple parallel tasks that cannot be rolled back
|
|
||||||
10048 = Login account, no right to delete
|
|
||||||
10055=Your password length is less than 8 digits
|
|
||||||
10056=Your password is not complex enough and needs to include both numbers, lowercase English, and uppercase English
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
500=\u670D\u52A1\u5668\u5185\u90E8\u5F02\u5E38
|
500=\u670D\u52A1\u5668\u5185\u90E8\u5F02\u5E38
|
||||||
401=\u672A\u6388\u6743
|
401=\u672A\u6388\u6743
|
||||||
403=\u62D2\u7EDD\u8BBF\u95EE\uFF0C\u6CA1\u6709\u6743\u9650
|
403=\u62D2\u7EDD\u8BBF\u95EE\uFF0C\u6CA1\u6709\u6743\u9650
|
||||||
|
|
||||||
10001={0}\u4E0D\u80FD\u4E3A\u7A7A
|
10001={0}\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
10002=\u6570\u636E\u5E93\u4E2D\u5DF2\u5B58\u5728\u8BE5\u8BB0\u5F55
|
10002=\u6570\u636E\u5E93\u4E2D\u5DF2\u5B58\u5728\u8BE5\u8BB0\u5F55
|
||||||
10003=\u83B7\u53D6\u53C2\u6570\u5931\u8D25
|
10003=\u83B7\u53D6\u53C2\u6570\u5931\u8D25
|
||||||
@@ -11,44 +12,24 @@
|
|||||||
10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
|
10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
|
||||||
10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE
|
10008=\u5148\u5220\u9664\u5B50\u83DC\u5355\u6216\u6309\u94AE
|
||||||
10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E
|
10009=\u539F\u5BC6\u7801\u4E0D\u6B63\u786E
|
||||||
10010=\u8D26\u53F7\u6216\u5BC6\u7801\u4E0D\u6B63\u786E,\u60A8\u8FD8\u6709\u53EF\u4EE5\u5C1D\u8BD5{0}\u6B21
|
|
||||||
10011=\u4E0A\u7EA7\u90E8\u95E8\u9009\u62E9\u9519\u8BEF
|
10011=\u4E0A\u7EA7\u90E8\u95E8\u9009\u62E9\u9519\u8BEF
|
||||||
10012=\u4E0A\u7EA7\u83DC\u5355\u4E0D\u80FD\u4E3A\u81EA\u8EAB
|
10012=\u4E0A\u7EA7\u83DC\u5355\u4E0D\u80FD\u4E3A\u81EA\u8EAB
|
||||||
10013=\u6570\u636E\u6743\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u7C7B\u578B\u53C2\u6570
|
10013=\u6570\u636E\u6743\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u7C7B\u578B\u53C2\u6570
|
||||||
10014=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u90E8\u95E8
|
10014=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u90E8\u95E8
|
||||||
10015=\u8BF7\u5148\u5220\u9664\u90E8\u95E8\u4E0B\u7684\u7528\u6237
|
10015=\u8BF7\u5148\u5220\u9664\u90E8\u95E8\u4E0B\u7684\u7528\u6237
|
||||||
10016=\u90E8\u7F72\u5931\u8D25\uFF0C\u6CA1\u6709\u6D41\u7A0B
|
|
||||||
10017=\u6A21\u578B\u56FE\u4E0D\u6B63\u786E\uFF0C\u8BF7\u68C0\u67E5
|
|
||||||
10018=\u5BFC\u51FA\u5931\u8D25\uFF0C\u6A21\u578BID\u4E3A{0}
|
|
||||||
10019=\u8BF7\u4E0A\u4F20\u6587\u4EF6
|
10019=\u8BF7\u4E0A\u4F20\u6587\u4EF6
|
||||||
10020=token\u4E0D\u80FD\u4E3A\u7A7A
|
10020=token\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
10021=token\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
|
10021=token\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
|
||||||
10022=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A
|
10022=\u8D26\u53F7\u5DF2\u88AB\u9501\u5B9A
|
||||||
10023=\u8BF7\u4E0A\u4F20zip\u3001bar\u3001bpmn\u3001bpmn20.xml\u683C\u5F0F\u6587\u4EF6
|
|
||||||
10024=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25{0}
|
10024=\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25{0}
|
||||||
10025=\u53D1\u9001\u77ED\u4FE1\u5931\u8D25{0}
|
|
||||||
10026=\u90AE\u4EF6\u6A21\u677F\u4E0D\u5B58\u5728
|
|
||||||
10027=Redis\u670D\u52A1\u5F02\u5E38
|
10027=Redis\u670D\u52A1\u5F02\u5E38
|
||||||
10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25
|
10028=\u5B9A\u65F6\u4EFB\u52A1\u5931\u8D25
|
||||||
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
|
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
|
||||||
10030=\u53C2\u6570\u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u8BF7\u4F7F\u7528JSON\u683C\u5F0F
|
10030=\u5BC6\u7801\u957F\u5EA6\u4E0D\u8DB3{0}\u4F4D
|
||||||
10031=\u8BF7\u5148\u5B8C\u6210\u77ED\u4FE1\u914D\u7F6E
|
10031=\u5BC6\u7801\u5FC5\u987B\u540C\u65F6\u5305\u542B\u6570\u5B57\u3001\u5927\u5C0F\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\u7EC4\u6210
|
||||||
10032=\u4EFB\u52A1\u5DF2\u88AB\u7B7E\u6536\uFF0C\u64CD\u4F5C\u5931\u8D25
|
10032=\u5220\u9664\u672C\u6570\u636E\u5F02\u5E38
|
||||||
10033=\u4E0D\u5B58\u5728\u7684\u6D41\u7A0B\u5B9A\u4E49
|
10033=\u8BBE\u5907\u9A8C\u8BC1\u7801\u9519\u8BEF
|
||||||
10034=\u4E0A\u7EA7\u8282\u70B9\u4E0D\u5B58\u5728
|
|
||||||
10035=\u9A73\u56DE
|
|
||||||
10036=\u56DE\u9000
|
|
||||||
10037=\u4EFB\u52A1\u6CA1\u6709\u5206\u7EC4\uFF0C\u65E0\u6CD5\u53D6\u6D88\u8BA4\u9886
|
|
||||||
10038=\u4E0A\u7EA7\u533A\u57DF\u9009\u62E9\u9519\u8BEF
|
|
||||||
10039=\u8BF7\u5148\u5220\u9664\u4E0B\u7EA7\u533A\u57DF
|
|
||||||
10040=\u6D41\u7A0B\u5DF2\u6302\u8D77\uFF0C\u4E0D\u80FD\u542F\u52A8\u5B9E\u4F8B
|
|
||||||
10041=\u591A\u5B9E\u4F8B\u4EFB\u52A1\u4E0D\u80FD\u9A73\u56DE
|
|
||||||
10042=\u5B58\u5728\u591A\u4E2A\u5904\u7406\u4E2D\u7684\u4EFB\u52A1\uFF0C\u4E0D\u80FD\u9A73\u56DE
|
|
||||||
10043=\u591A\u5B9E\u4F8B\u4EFB\u52A1\u4E0D\u80FD\u7EC8\u6B62
|
|
||||||
10044=\u5B58\u5728\u591A\u4E2A\u5904\u7406\u4E2D\u7684\u4EFB\u52A1\uFF0C\u4E0D\u80FD\u7EC8\u6B62\u6D41\u7A0B
|
|
||||||
10045=\u7EC8\u6B62
|
|
||||||
10046=\u591A\u5B9E\u4F8B\u4EFB\u52A1\u4E0D\u80FD\u56DE\u9000
|
|
||||||
10047=\u5B58\u5728\u591A\u4E2A\u5E76\u884C\u6267\u884C\u7684\u4EFB\u52A1\uFF0C\u4E0D\u80FD\u56DE\u9000
|
|
||||||
10048=\u767B\u5F55\u8D26\u53F7\uFF0C\u65E0\u6743\u5220\u9664
|
|
||||||
10055=\u60A8\u7684\u5BC6\u7801\u957F\u5EA6\u4E0D\u591F8\u4F4D
|
|
||||||
10056=\u60A8\u7684\u5BC6\u7801\u590D\u6742\u5EA6\u4E0D\u591F\uFF0C\u9700\u8981\u540C\u65F6\u5305\u542B\u6570\u5B57,\u5C0F\u5199\u82F1\u6587,\u5927\u5199\u82F1\u6587
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
500=\u670D\u52D9\u5668\u5167\u90E8\u7570\u5E38
|
500=\u670D\u52D9\u5668\u5167\u90E8\u7570\u5E38
|
||||||
401=\u672A\u6388\u6B0A
|
401=\u672A\u6388\u6B0A
|
||||||
403=\u62D2\u7D55\u8A2A\u554F\uFF0C\u6C92\u6709\u6B0A\u9650
|
403=\u62D2\u7D55\u8A2A\u554F\uFF0C\u6C92\u6709\u6B0A\u9650
|
||||||
|
|
||||||
10001={0}\u4E0D\u80FD\u70BA\u7A7A
|
10001={0}\u4E0D\u80FD\u70BA\u7A7A
|
||||||
10002=\u6578\u64DA\u5EAB\u4E2D\u5DF2\u5B58\u5728\u8A72\u8A18\u9304
|
10002=\u6578\u64DA\u5EAB\u4E2D\u5DF2\u5B58\u5728\u8A72\u8A18\u9304
|
||||||
10003=\u7372\u53D6\u53C3\u6578\u5931\u6557
|
10003=\u7372\u53D6\u53C3\u6578\u5931\u6557
|
||||||
@@ -11,44 +12,24 @@
|
|||||||
10007=\u9A57\u8B49\u78BC\u4E0D\u6B63\u78BA
|
10007=\u9A57\u8B49\u78BC\u4E0D\u6B63\u78BA
|
||||||
10008=\u5148\u522A\u9664\u5B50\u83DC\u55AE\u6216\u6309\u9215
|
10008=\u5148\u522A\u9664\u5B50\u83DC\u55AE\u6216\u6309\u9215
|
||||||
10009=\u539F\u5BC6\u78BC\u4E0D\u6B63\u78BA
|
10009=\u539F\u5BC6\u78BC\u4E0D\u6B63\u78BA
|
||||||
10010=\u8CEC\u865F\u6216\u5BC6\u78BC\u4E0D\u6B63\u78BA,\u60A8\u9084\u6709\u53EF\u4EE5\u5617\u8A66{0}\u6B21
|
|
||||||
10011=\u4E0A\u7D1A\u90E8\u9580\u9078\u64C7\u932F\u8AA4
|
10011=\u4E0A\u7D1A\u90E8\u9580\u9078\u64C7\u932F\u8AA4
|
||||||
10012=\u4E0A\u7D1A\u83DC\u55AE\u4E0D\u80FD\u70BA\u81EA\u8EAB
|
10012=\u4E0A\u7D1A\u83DC\u55AE\u4E0D\u80FD\u70BA\u81EA\u8EAB
|
||||||
10013=\u6578\u64DA\u6B0A\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u985E\u578B\u53C3\u6578
|
10013=\u6578\u64DA\u6B0A\u9650\u63A5\u53E3\uFF0C\u53EA\u80FD\u662FMap\u985E\u578B\u53C3\u6578
|
||||||
10014=\u8ACB\u5148\u522A\u9664\u4E0B\u7D1A\u90E8\u9580
|
10014=\u8ACB\u5148\u522A\u9664\u4E0B\u7D1A\u90E8\u9580
|
||||||
10015=\u8ACB\u5148\u522A\u9664\u90E8\u9580\u4E0B\u7684\u7528\u6236
|
10015=\u8ACB\u5148\u522A\u9664\u90E8\u9580\u4E0B\u7684\u7528\u6236
|
||||||
10016=\u90E8\u7F72\u5931\u6557\uFF0C\u6C92\u6709\u6D41\u7A0B
|
|
||||||
10017=\u6A21\u578B\u5716\u4E0D\u6B63\u78BA\uFF0C\u8ACB\u6AA2\u67E5
|
|
||||||
10018=\u5C0E\u51FA\u5931\u6557\uFF0C\u6A21\u578BID\u70BA{0}
|
|
||||||
10019=\u8ACB\u4E0A\u50B3\u6587\u4EF6
|
10019=\u8ACB\u4E0A\u50B3\u6587\u4EF6
|
||||||
10020=token\u4E0D\u80FD\u70BA\u7A7A
|
10020=token\u4E0D\u80FD\u70BA\u7A7A
|
||||||
10021=token\u5931\u6548\uFF0C\u8ACB\u91CD\u65B0\u767B\u9304
|
10021=token\u5931\u6548\uFF0C\u8ACB\u91CD\u65B0\u767B\u9304
|
||||||
10022=\u8CEC\u865F\u5DF2\u88AB\u9396\u5B9A
|
10022=\u8CEC\u865F\u5DF2\u88AB\u9396\u5B9A
|
||||||
10023=\u8ACB\u4E0A\u50B3zip\u3001bar\u3001bpmn\u3001bpmn20.xml\u683C\u5F0F\u6587\u4EF6
|
|
||||||
10024=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557{0}
|
10024=\u4E0A\u50B3\u6587\u4EF6\u5931\u6557{0}
|
||||||
10025=\u767C\u9001\u77ED\u4FE1\u5931\u6557{0}
|
|
||||||
10026=\u90F5\u4EF6\u6A21\u677F\u4E0D\u5B58\u5728
|
|
||||||
10027=Redis\u670D\u52D9\u7570\u5E38
|
10027=Redis\u670D\u52D9\u7570\u5E38
|
||||||
10028=\u5B9A\u6642\u4EFB\u52D9\u5931\u6557
|
10028=\u5B9A\u6642\u4EFB\u52D9\u5931\u6557
|
||||||
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
|
10029=\u4E0D\u80FD\u5305\u542B\u975E\u6CD5\u5B57\u7B26
|
||||||
10030=\u53C3\u6578\u683C\u5F0F\u4E0D\u6B63\u78BA\uFF0C\u8ACB\u4F7F\u7528JSON\u683C\u5F0F
|
10030=\u5BC6\u78BC\u9577\u5EA6\u4E0D\u8DB3{0}\u4F4D
|
||||||
10031=\u8ACB\u5148\u5B8C\u6210\u77ED\u4FE1\u914D\u7F6E
|
10031=\u5BC6\u78BC\u5FC5\u9808\u540C\u6642\u5305\u542B\u6578\u5B57\u3001\u5927\u5C0F\u5B57\u6BCD\u548C\u7279\u6B8A\u5B57\u7B26\u7D44\u6210
|
||||||
10032=\u4EFB\u52D9\u5DF2\u88AB\u7C3D\u6536\uFF0C\u64CD\u4F5C\u5931\u6557
|
10032=\u522A\u9664\u6B64\u6578\u64DA\u7570\u5E38
|
||||||
10033=\u4E0D\u5B58\u5728\u7684\u6D41\u7A0B\u5B9A\u7FA9
|
10033=\u8A2D\u5099\u9A57\u8B49\u78BC\u932F\u8AA4
|
||||||
10034=\u4E0A\u7D1A\u7BC0\u9EDE\u4E0D\u5B58\u5728
|
|
||||||
10035=\u99C1\u56DE
|
|
||||||
10036=\u56DE\u9000
|
|
||||||
10037=\u4EFB\u52D9\u6C92\u6709\u5206\u7D44\uFF0C\u7121\u6CD5\u53D6\u6D88\u8A8D\u9818
|
|
||||||
10038=\u4E0A\u7D1A\u5340\u57DF\u9078\u64C7\u932F\u8AA4
|
|
||||||
10039=\u8ACB\u5148\u522A\u9664\u4E0B\u7D1A\u5340\u57DF
|
|
||||||
10040=\u6D41\u7A0B\u5DF2\u639B\u8D77\uFF0C\u4E0D\u80FD\u555F\u52D5\u5BE6\u4F8B
|
|
||||||
10041=\u591A\u5BE6\u4F8B\u4EFB\u52D9\u4E0D\u80FD\u99C1\u56DE
|
|
||||||
10042=\u5B58\u5728\u591A\u500B\u8655\u7406\u4E2D\u7684\u4EFB\u52D9\uFF0C\u4E0D\u80FD\u99C1\u56DE
|
|
||||||
10043=\u591A\u5BE6\u4F8B\u4EFB\u52D9\u4E0D\u80FD\u7D42\u6B62
|
|
||||||
10044=\u5B58\u5728\u591A\u500B\u8655\u7406\u4E2D\u7684\u4EFB\u52D9\uFF0C\u4E0D\u80FD\u7D42\u6B62\u6D41\u7A0B
|
|
||||||
10045=\u7D42\u6B62
|
|
||||||
10046=\u591A\u5BE6\u4F8B\u4EFB\u52D9\u4E0D\u80FD\u56DE\u9000
|
|
||||||
10047=\u5B58\u5728\u591A\u500B\u4E26\u884C\u57F7\u884C\u7684\u4EFB\u52D9\uFF0C\u4E0D\u80FD\u56DE\u9000
|
|
||||||
10048=\u767B\u5165\u5E33\u865F\uFF0C\u7121\u6B0A\u5220\u9664
|
|
||||||
10055=\u60A8\u7684\u5BC6\u78BC\u9577\u5EA6\u4E0D\u59208\u4F4D
|
|
||||||
10056=\u60A8\u7684\u5BC6\u78BC\u5FA9\u96DC\u5EA6\u4E0D\u5920\uFF0C\u9700\u8981\u540C\u6642\u5305\u542B\u6578\u5B57,\u5C0F\u5BEB\u82F1\u6587,\u5927\u5BEB\u82F1\u6587
|
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
#\u7B80\u4F53\u4E2D\u6587
|
#\u7B80\u4F53\u4E2D\u6587
|
||||||
id.require=ID\u4E0D\u80FD\u4E3A\u7A7A
|
id.require=ID\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
id.null=ID\u5FC5\u987B\u4E3A\u7A7A
|
id.null=ID\u5FC5\u987B\u4E3A\u7A7A
|
||||||
pid.require=\u4E0A\u7EA7ID\uFF0C\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0
|
sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0
|
||||||
|
|
||||||
|
sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysdict.label.require=\u5B57\u5178\u6807\u7B7E\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A
|
sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
@@ -11,99 +15,17 @@ sysuser.username.require=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|||||||
sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2
|
sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2
|
||||||
sysuser.email.require=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
|
sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
|
||||||
sysuser.mobile.require=\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.superadmin.range=\u8D85\u7EA7\u7BA1\u7406\u5458\u53D6\u503C\u8303\u56F40~1
|
|
||||||
sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
|
sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
|
||||||
sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
sysmenu.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u83DC\u5355
|
|
||||||
sysmenu.name.require=\u83DC\u5355\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysmenu.type.range=\u83DC\u5355\u7C7B\u578B\u53D6\u503C\u8303\u56F40~1
|
|
||||||
sysmenu.openstyle.range=\u83DC\u5355\u6253\u5F00\u65B9\u5F0F\u53D6\u503C\u8303\u56F40~1
|
|
||||||
|
|
||||||
sysdept.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u90E8\u95E8
|
timbre.languages.require=\u97F3\u8272\u7684\u8BED\u8A00\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
sysdept.name.require=\u90E8\u95E8\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
timbre.name.require=\u97F3\u8272\u7684\u540D\u79F0\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
|
timbre.remark.require=\u97F3\u8272\u7684\u5907\u6CE8\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
|
timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u952E\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
|
timbre.ttsVoice.require=\u97F3\u8272\u7684\u7F16\u7801\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
|
timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653EDemo\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
|
|
||||||
sysrole.name.require=\u89D2\u8272\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysdict.label.require=\u5B57\u5178\u6807\u7B7E\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
schedule.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
|
|
||||||
schedule.cron.require=cron\u8868\u8FBE\u5F0F\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
schedule.bean.require=bean\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
oss.type.range=\u7C7B\u578B\u53D6\u503C\u8303\u56F41~5
|
|
||||||
|
|
||||||
aliyun.accesskeyid.require=\u963F\u91CC\u4E91AccessKeyId\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.accesskeysecret.require=\u963F\u91CC\u4E91AccessKeySecret\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.signname.require=\u963F\u91CC\u4E91\u77ED\u4FE1\u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.templatecode.require=\u963F\u91CC\u4E91\u77ED\u4FE1\u6A21\u677F\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.domain.require=\u963F\u91CC\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.domain.url=\u963F\u91CC\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
aliyun.endPoint.require=\u963F\u91CC\u4E91EndPoint\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.bucketname.require=\u963F\u91CC\u4E91BucketName\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
qcloud.appid.require=\u817E\u8BAF\u4E91AppId\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.appkey.require=\u817E\u8BAF\u4E91AppKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.secretId.require=\u817E\u8BAF\u4E91SecretId\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.secretkey.require=\u817E\u8BAF\u4E91SecretKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.signname.require=\u817E\u8BAF\u4E91\u77ED\u4FE1\u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.templateid.require=\u817E\u8BAF\u4E91\u77ED\u4FE1\u6A21\u677FID\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.domain.require=\u817E\u8BAF\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.domain.url=\u817E\u8BAF\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
qcloud.bucketname.require=\u817E\u8BAF\u4E91BucketName\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.region.require=\u6240\u5C5E\u5730\u533A\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
qiniu.domain.require=\u4E03\u725B\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.domain.url=\u4E03\u725B\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
qiniu.accesskey.require=\u4E03\u725BAccessKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.secretkey.require=\u4E03\u725BSecretKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.bucketname.require=\u4E03\u725B\u7A7A\u95F4\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.templateId.require=\u4E03\u725B\u6A21\u677FID\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
fastdfs.domain.require=FastDFS\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
fastdfs.domain.url=FastDFS\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
|
|
||||||
local.domain.require=\u672C\u5730\u4E0A\u4F20\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
local.domain.url=\u672C\u5730\u4E0A\u4F20\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
local.path.url=\u5B58\u50A8\u76EE\u5F55\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
minio.endPoint.require=Minio EndPoint\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
minio.accesskey.require=Minio AccessKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
minio.secretkey.require=Minio SecretKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
minio.bucketname.require=Minio BucketName\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
sms.platform.range=\u5E73\u53F0\u7C7B\u578B\u53D6\u503C\u8303\u56F41~2
|
|
||||||
email.smtp.require=SMTP\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
email.port.require=\u7AEF\u53E3\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
email.username.require=\u90AE\u7BB1\u8D26\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
email.password.require=\u90AE\u7BB1\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
mail.name.require=\u6A21\u677F\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
mail.subject.require=\u90AE\u4EF6\u4E3B\u9898\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
mail.content.require=\u90AE\u4EF6\u6B63\u6587\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
model.name.require=\u6A21\u578B\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
model.key.require=\u6A21\u578B\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
news.title.require=\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
news.content.require=\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
news.pubdate.require=\u53D1\u5E03\u65F6\u95F4\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
region.id.require=\u533A\u57DF\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
region.pid.require=\u4E0A\u7EA7\u533A\u57DF\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
region.name.require=\u533A\u57DF\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
processBizRoute.procDefId.require=\u6D41\u7A0B\u5B9A\u4E49ID\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
processBizRoute.bizRoute.require=\u4E1A\u52A1\u8DEF\u7531\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
processBizRoute.procDefKey.require=\u6D41\u7A0B\u5B9A\u4E49KEY\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
processBizRoute.version.require=\u6D41\u7A0B\u5B9A\u4E49\u7248\u672C\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
ProcessStart.processDefinitionKey.require=\u6D41\u7A0B\u5B9A\u4E49KEY\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
ProcessStart.businessKey.require=\u4E1A\u52A1KEY\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
#English
|
#English
|
||||||
id.require=ID can not be empty
|
id.require=ID can not be empty
|
||||||
id.null=ID has to be empty
|
id.null=ID has to be empty
|
||||||
pid.require=Parent ID, cannot be empty
|
|
||||||
sort.number=The sort value cannot be less than 0
|
sort.number=The sort value cannot be less than 0
|
||||||
|
|
||||||
|
sysdict.type.require=The dictionary type cannot be empty
|
||||||
|
sysdict.name.require=The dictionary name cannot be empty
|
||||||
|
sysdict.label.require=Dictionary tag cannot be empty
|
||||||
|
|
||||||
sysparams.paramcode.require=Parameter encoding cannot be empty
|
sysparams.paramcode.require=Parameter encoding cannot be empty
|
||||||
sysparams.paramvalue.require=Parameter values cannot be empty
|
sysparams.paramvalue.require=Parameter values cannot be empty
|
||||||
|
|
||||||
@@ -11,100 +15,16 @@ sysuser.username.require=The username cannot be empty
|
|||||||
sysuser.password.require=The password cannot be empty
|
sysuser.password.require=The password cannot be empty
|
||||||
sysuser.realname.require=The realname cannot be empty
|
sysuser.realname.require=The realname cannot be empty
|
||||||
sysuser.gender.range=Gender ranges from 0 to 2
|
sysuser.gender.range=Gender ranges from 0 to 2
|
||||||
sysuser.email.require=Mailbox cannot be empty
|
|
||||||
sysuser.email.error=Incorrect email format
|
sysuser.email.error=Incorrect email format
|
||||||
sysuser.mobile.require=The phone number cannot be empty
|
|
||||||
sysuser.deptId.require=Departments cannot be empty
|
sysuser.deptId.require=Departments cannot be empty
|
||||||
sysuser.superadmin.range=Super administrator values range from 0 to 1
|
|
||||||
sysuser.status.range=State ranges from 0 to 1
|
sysuser.status.range=State ranges from 0 to 1
|
||||||
sysuser.captcha.require=The captcha cannot be empty
|
sysuser.captcha.require=The captcha cannot be empty
|
||||||
sysuser.uuid.require=The unique identifier cannot be empty
|
sysuser.uuid.require=The unique identifier cannot be empty
|
||||||
|
|
||||||
sysmenu.pid.require=Please select superior menu
|
timbre.languages.require=The language of the timbre cannot be empty
|
||||||
sysmenu.name.require=Menu name cannot be empty
|
timbre.name.require=The name of the timbre cannot be empty
|
||||||
sysmenu.type.range=Menu type ranges from 0 to 1
|
timbre.remark.require=The remark of the timbre cannot be empty
|
||||||
sysmenu.openstyle.range=Menu open style ranges from 0 to 1
|
timbre.ttsModelId.require=The TTS model ID of the timbre cannot be empty
|
||||||
|
timbre.ttsVoice.require=The TTS voice of the timbre cannot be empty
|
||||||
|
timbre.voiceDemo.require=The voice demo of the timbre cannot be empty
|
||||||
|
|
||||||
sysdept.pid.require=Please select superior department
|
|
||||||
sysdept.name.require=The department name cannot be empty
|
|
||||||
|
|
||||||
sysrole.name.require=The role name cannot be empty
|
|
||||||
|
|
||||||
sysdict.type.require=The dictionary type cannot be empty
|
|
||||||
sysdict.name.require=The dictionary name cannot be empty
|
|
||||||
sysdict.label.require=Dictionary tag cannot be empty
|
|
||||||
|
|
||||||
schedule.status.range=Status ranges from 0 to 1
|
|
||||||
schedule.cron.require=Cron expression cannot be empty
|
|
||||||
schedule.bean.require=Bean name cannot be empty
|
|
||||||
|
|
||||||
oss.type.range=Type ranges from 1 to 5
|
|
||||||
|
|
||||||
aliyun.accesskeyid.require=Aliyun AccessKeyId cannot be empty
|
|
||||||
aliyun.accesskeysecret.require=Aliyun AccessKeySecret cannot be empty
|
|
||||||
aliyun.signname.require=Aliyun message signature cannot be empty
|
|
||||||
aliyun.templatecode.require=Aliyun message template cannot be empty
|
|
||||||
aliyun.domain.require=Aliyun bound domain name cannot be empty
|
|
||||||
aliyun.domain.url=Aliyun binding domain name format is incorrect
|
|
||||||
aliyun.endPoint.require=The aliyun EndPoint cannot be empty
|
|
||||||
aliyun.bucketname.require=Aliyun BucketName cannot be empty
|
|
||||||
|
|
||||||
qcloud.appid.require=Tencent cloud AppId cannot be empty
|
|
||||||
qcloud.appkey.require=Tencent cloud AppKey cannot be empty
|
|
||||||
qcloud.secretId.require=Tencent cloud SecretId cannot be empty
|
|
||||||
qcloud.secretkey.require=Tencent cloud SecretKey cannot be empty
|
|
||||||
qcloud.signname.require=Tencent cloud SMS signature cannot be empty
|
|
||||||
qcloud.templateid.require=Tencent cloud SMS template ID cannot be empty
|
|
||||||
qcloud.domain.require=Tencent cloud bound domain name cannot be empty
|
|
||||||
qcloud.domain.url=Tencent cloud binding domain name format is incorrect
|
|
||||||
qcloud.bucketname.require=Tencent cloud BucketName cannot be empty
|
|
||||||
qcloud.region.require=The region cannot be empty
|
|
||||||
|
|
||||||
qiniu.domain.require=Bound domain name cannot be empty
|
|
||||||
qiniu.domain.url=Binding domain name format is incorrect
|
|
||||||
qiniu.accesskey.require=The AccessKey cannot be empty
|
|
||||||
qiniu.secretkey.require=The SecretKey of seven cows cannot be empty
|
|
||||||
qiniu.bucketname.require=Space names cannot be empty
|
|
||||||
qiniu.templateId.require=Template ID cannot be empty
|
|
||||||
|
|
||||||
fastdfs.domain.require=FastDFS bound domain name cannot be empty
|
|
||||||
fastdfs.domain.url=FastDFS bound domain name format is incorrect
|
|
||||||
|
|
||||||
local.domain.require=Local upload bound domain name cannot be empty
|
|
||||||
local.domain.url=The domain name bound for local upload is not formatted correctly
|
|
||||||
local.path.url=The storage directory cannot be empty
|
|
||||||
|
|
||||||
minio.endPoint.require=Minio EndPoint cannot be empty
|
|
||||||
minio.accesskey.require=Minio AccessKey cannot be empty
|
|
||||||
minio.secretkey.require=Minio SecretKey cannot be empty
|
|
||||||
minio.bucketname.require=Minio BucketName cannot be empty
|
|
||||||
|
|
||||||
sms.platform.range=Platform type ranges from 1 to 2
|
|
||||||
|
|
||||||
email.smtp.require=SMTP cannot be empty
|
|
||||||
email.port.require=Port number cannot be empty
|
|
||||||
email.username.require=The email account cannot be empty
|
|
||||||
email.password.require=The password cannot be empty
|
|
||||||
|
|
||||||
mail.name.require=The template name cannot be empty
|
|
||||||
mail.subject.require=Mail subject cannot be empty
|
|
||||||
mail.content.require=Message text cannot be empty
|
|
||||||
|
|
||||||
model.name.require=The model name cannot be empty
|
|
||||||
model.key.require=The model key cannot be empty
|
|
||||||
|
|
||||||
news.title.require=The title cannot be empty
|
|
||||||
news.content.require=Content cannot be empty
|
|
||||||
news.pubdate.require=The release time cannot be empty
|
|
||||||
|
|
||||||
region.id.require=Region ID cannot be empty
|
|
||||||
region.pid.require=Upper area cannot be empty
|
|
||||||
region.name.require=Region name cannot be empty
|
|
||||||
|
|
||||||
processBizRoute.procDefId.require=Process Definition ID cannot be empty
|
|
||||||
processBizRoute.bizRoute.require=Service routing cannot be empty
|
|
||||||
processBizRoute.procDefKey.require=Process Definition KEY cannot be empty
|
|
||||||
processBizRoute.version.require=Process Definition Version number cannot be empty
|
|
||||||
|
|
||||||
ProcessStart.processDefinitionKey.require=Process Definition KEY cannot be empty
|
|
||||||
ProcessStart.businessKey.require=Business KEY cannot be empty
|
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
#\u7B80\u4F53\u4E2D\u6587
|
#\u7B80\u4F53\u4E2D\u6587
|
||||||
id.require=ID\u4E0D\u80FD\u4E3A\u7A7A
|
id.require=ID\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
id.null=ID\u5FC5\u987B\u4E3A\u7A7A
|
id.null=ID\u5FC5\u987B\u4E3A\u7A7A
|
||||||
pid.require=\u4E0A\u7EA7ID\uFF0C\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0
|
sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0
|
||||||
|
|
||||||
|
sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysdict.label.require=\u5B57\u5178\u6807\u7B7E\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A
|
sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
@@ -11,99 +15,16 @@ sysuser.username.require=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|||||||
sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2
|
sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2
|
||||||
sysuser.email.require=\u90AE\u7BB1\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
|
sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
|
||||||
sysuser.mobile.require=\u624B\u673A\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.superadmin.range=\u8D85\u7EA7\u7BA1\u7406\u5458\u53D6\u503C\u8303\u56F40~1
|
|
||||||
sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
|
sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
|
||||||
sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
sysmenu.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u83DC\u5355
|
timbre.languages.require=\u97F3\u8272\u7684\u8A9E\u8A00\u4E0D\u53EF\u4EE5\u70BA\u7A7A
|
||||||
sysmenu.name.require=\u83DC\u5355\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
timbre.name.require=\u97F3\u8272\u7684\u540D\u7A31\u4E0D\u53EF\u4EE5\u70BA\u7A7A
|
||||||
sysmenu.type.range=\u83DC\u5355\u7C7B\u578B\u53D6\u503C\u8303\u56F40~1
|
timbre.remark.require=\u97F3\u8272\u7684\u5099\u6CE8\u4E0D\u53EF\u4EE5\u70BA\u7A7A
|
||||||
sysmenu.openstyle.range=\u83DC\u5355\u6253\u5F00\u65B9\u5F0F\u53D6\u503C\u8303\u56F40~1
|
timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u9375\u4E0D\u53EF\u4EE5\u70BA\u7A7A
|
||||||
|
timbre.ttsVoice.require=\u97F3\u8272\u7684\u7DE8\u78BC\u4E0D\u53EF\u4EE5\u70BA\u7A7A
|
||||||
|
timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653E\u5730\u5740\u4E0D\u53EF\u4EE5\u70BA\u7A7A
|
||||||
|
|
||||||
sysdept.pid.require=\u8BF7\u9009\u62E9\u4E0A\u7EA7\u90E8\u95E8
|
|
||||||
sysdept.name.require=\u90E8\u95E8\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
sysrole.name.require=\u89D2\u8272\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
sysdict.label.require=\u5B57\u5178\u6807\u7B7E\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
schedule.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
|
|
||||||
schedule.cron.require=cron\u8868\u8FBE\u5F0F\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
schedule.bean.require=bean\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
oss.type.range=\u7C7B\u578B\u53D6\u503C\u8303\u56F41~5
|
|
||||||
|
|
||||||
aliyun.accesskeyid.require=\u963F\u91CC\u4E91AccessKeyId\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.accesskeysecret.require=\u963F\u91CC\u4E91AccessKeySecret\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.signname.require=\u963F\u91CC\u4E91\u77ED\u4FE1\u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.templatecode.require=\u963F\u91CC\u4E91\u77ED\u4FE1\u6A21\u677F\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.domain.require=\u963F\u91CC\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.domain.url=\u963F\u91CC\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
aliyun.endPoint.require=\u963F\u91CC\u4E91EndPoint\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
aliyun.bucketname.require=\u963F\u91CC\u4E91BucketName\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
qcloud.appid.require=\u817E\u8BAF\u4E91AppId\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.appkey.require=\u817E\u8BAF\u4E91AppKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.secretId.require=\u817E\u8BAF\u4E91SecretId\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.secretkey.require=\u817E\u8BAF\u4E91SecretKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.signname.require=\u817E\u8BAF\u4E91\u77ED\u4FE1\u7B7E\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.templateid.require=\u817E\u8BAF\u4E91\u77ED\u4FE1\u6A21\u677FID\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.domain.require=\u817E\u8BAF\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.domain.url=\u817E\u8BAF\u4E91\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
qcloud.bucketname.require=\u817E\u8BAF\u4E91BucketName\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qcloud.region.require=\u6240\u5C5E\u5730\u533A\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
qiniu.domain.require=\u4E03\u725B\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.domain.url=\u4E03\u725B\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
qiniu.accesskey.require=\u4E03\u725BAccessKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.secretkey.require=\u4E03\u725BSecretKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.bucketname.require=\u4E03\u725B\u7A7A\u95F4\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
qiniu.templateId.require=\u4E03\u725B\u6A21\u677FID\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
fastdfs.domain.require=FastDFS\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
fastdfs.domain.url=FastDFS\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
|
|
||||||
local.domain.require=\u672C\u5730\u4E0A\u4F20\u7ED1\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
local.domain.url=\u672C\u5730\u4E0A\u4F20\u7ED1\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u786E
|
|
||||||
local.path.url=\u5B58\u50A8\u76EE\u5F55\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
minio.endPoint.require=Minio EndPoint\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
minio.accesskey.require=Minio AccessKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
minio.secretkey.require=Minio SecretKey\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
minio.bucketname.require=Minio BucketName\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
sms.platform.range=\u5E73\u53F0\u7C7B\u578B\u53D6\u503C\u8303\u56F41~2
|
|
||||||
email.smtp.require=SMTP\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
email.port.require=\u7AEF\u53E3\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
email.username.require=\u90AE\u7BB1\u8D26\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
email.password.require=\u90AE\u7BB1\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
mail.name.require=\u6A21\u677F\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
mail.subject.require=\u90AE\u4EF6\u4E3B\u9898\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
mail.content.require=\u90AE\u4EF6\u6B63\u6587\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
model.name.require=\u6A21\u578B\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
model.key.require=\u6A21\u578B\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
news.title.require=\u6807\u9898\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
news.content.require=\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
news.pubdate.require=\u53D1\u5E03\u65F6\u95F4\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
region.id.require=\u533A\u57DF\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
region.pid.require=\u4E0A\u7EA7\u533A\u57DF\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
region.name.require=\u533A\u57DF\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
processBizRoute.procDefId.require=\u6D41\u7A0B\u5B9A\u4E49ID\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
processBizRoute.bizRoute.require=\u4E1A\u52A1\u8DEF\u7531\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
processBizRoute.procDefKey.require=\u6D41\u7A0B\u5B9A\u4E49KEY\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
processBizRoute.version.require=\u6D41\u7A0B\u5B9A\u4E49\u7248\u672C\u53F7\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
|
|
||||||
ProcessStart.processDefinitionKey.require=\u6D41\u7A0B\u5B9A\u4E49KEY\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
ProcessStart.businessKey.require=\u4E1A\u52A1KEY\u4E0D\u80FD\u4E3A\u7A7A
|
|
||||||
@@ -1,110 +1,29 @@
|
|||||||
#\u7E41\u4F53\u4E2D\u6587
|
#\u7B80\u4F53\u4E2D\u6587
|
||||||
id.require=ID\u4E0D\u80FD\u70BA\u7A7A
|
id.require=ID\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
id.null=ID\u5FC5\u9808\u70BA\u7A7A
|
id.null=ID\u5FC5\u987B\u4E3A\u7A7A
|
||||||
pid.require=\u4E0A\u7D1AID\uFF0C\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u65BC0
|
|
||||||
|
|
||||||
sysparams.paramcode.require=\u53C3\u6578\u7DE8\u78BC\u4E0D\u80FD\u70BA\u7A7A
|
sort.number=\u6392\u5E8F\u503C\u4E0D\u80FD\u5C0F\u4E8E0
|
||||||
sysparams.paramvalue.require=\u53C3\u6578\u503C\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
sysuser.username.require=\u7528\u6236\u540D\u4E0D\u80FD\u70BA\u7A7A
|
sysdict.type.require=\u5B57\u5178\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.password.require=\u5BC6\u78BC\u4E0D\u80FD\u70BA\u7A7A
|
sysdict.name.require=\u5B57\u5178\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u70BA\u7A7A
|
sysdict.label.require=\u5B57\u5178\u6807\u7B7E\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysuser.gender.range=\u6027\u5225\u53D6\u503C\u7BC4\u570D0~2
|
|
||||||
sysuser.email.require=\u90F5\u7BB1\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
sysuser.email.error=\u90F5\u7BB1\u683C\u5F0F\u4E0D\u6B63\u78BA
|
|
||||||
sysuser.mobile.require=\u624B\u6A5F\u865F\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
sysuser.deptId.require=\u90E8\u9580\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
sysuser.superadmin.range=\u8D85\u7D1A\u7BA1\u7406\u54E1\u53D6\u503C\u7BC4\u570D0~1
|
|
||||||
sysuser.status.range=\u72C0\u614B\u53D6\u503C\u7BC4\u570D0~1
|
|
||||||
sysuser.captcha.require=\u9A57\u8B49\u78BC\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
sysuser.uuid.require=\u552F\u4E00\u6A19\u8B58\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
sysmenu.pid.require=\u8ACB\u9078\u64C7\u4E0A\u7D1A\u83DC\u55AE
|
sysparams.paramcode.require=\u53C2\u6570\u7F16\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysmenu.name.require=\u83DC\u55AE\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
sysparams.paramvalue.require=\u53C2\u6570\u503C\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysmenu.type.range=\u83DC\u55AE\u985E\u578B\u53D6\u503C\u7BC4\u570D0~1
|
|
||||||
sysmenu.openstyle.range=\u83DC\u55AE\u6253\u958B\u65B9\u5F0F\u53D6\u503C\u7BC4\u570D0~1
|
|
||||||
|
|
||||||
sysdept.pid.require=\u8ACB\u9078\u64C7\u4E0A\u7D1A\u90E8\u9580
|
sysuser.username.require=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
sysdept.name.require=\u90E8\u9580\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
sysuser.password.require=\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysuser.realname.require=\u59D3\u540D\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysuser.gender.range=\u6027\u522B\u53D6\u503C\u8303\u56F40~2
|
||||||
|
sysuser.email.error=\u90AE\u7BB1\u683C\u5F0F\u4E0D\u6B63\u786E
|
||||||
|
sysuser.deptId.require=\u90E8\u95E8\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysuser.status.range=\u72B6\u6001\u53D6\u503C\u8303\u56F40~1
|
||||||
|
sysuser.captcha.require=\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
sysuser.uuid.require=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
|
||||||
|
|
||||||
sysrole.name.require=\u89D2\u8272\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
timbre.languages.require=\u97F3\u8272\u7684\u8BED\u8A00\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
|
timbre.name.require=\u97F3\u8272\u7684\u540D\u79F0\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
sysdict.type.require=\u5B57\u5178\u985E\u578B\u4E0D\u80FD\u70BA\u7A7A
|
timbre.remark.require=\u97F3\u8272\u7684\u5907\u6CE8\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
sysdict.name.require=\u5B57\u5178\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
timbre.ttsModelId.require=\u97F3\u8272\u7684tts\u4E3B\u952E\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
sysdict.label.require=\u5B57\u5178\u6A19\u7C64\u4E0D\u80FD\u70BA\u7A7A
|
timbre.ttsVoice.require=\u97F3\u8272\u7684\u7F16\u7801\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
|
timbre.voiceDemo.require=\u97F3\u8272\u7684\u64AD\u653EDemo\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
|
||||||
schedule.status.range=\u72C0\u614B\u53D6\u503C\u7BC4\u570D0~1
|
|
||||||
schedule.cron.require=cron\u8868\u9054\u5F0F\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
schedule.bean.require=bean\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
oss.type.range=\u985E\u578B\u53D6\u503C\u7BC4\u570D1~5
|
|
||||||
|
|
||||||
aliyun.accesskeyid.require=\u963F\u91CC\u96F2AccessKeyId\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
aliyun.accesskeysecret.require=\u963F\u91CC\u96F2AccessKeySecret\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
aliyun.signname.require=\u963F\u91CC\u96F2\u77ED\u4FE1\u7C3D\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
aliyun.templatecode.require=\u963F\u91CC\u96F2\u77ED\u4FE1\u6A21\u677F\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
aliyun.domain.require=\u963F\u91CC\u96F2\u7D81\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
aliyun.domain.url=\u963F\u91CC\u96F2\u7D81\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u78BA
|
|
||||||
aliyun.endPoint.require=\u963F\u91CC\u96F2EndPoint\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
aliyun.bucketname.require=\u963F\u91CC\u96F2BucketName\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
qcloud.appid.require=\u9A30\u8A0A\u96F2AppId\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.appkey.require=\u9A30\u8A0A\u96F2AppKey\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.secretId.require=\u9A30\u8A0A\u96F2SecretId\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.secretkey.require=\u9A30\u8A0A\u96F2SecretKey\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.signname.require=\u9A30\u8A0A\u96F2\u77ED\u4FE1\u7C3D\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.templateid.require=\u9A30\u8A0A\u96F2\u77ED\u4FE1\u6A21\u677FID\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.domain.require=\u9A30\u8A0A\u96F2\u7D81\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.domain.url=\u9A30\u8A0A\u96F2\u7D81\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u78BA
|
|
||||||
qcloud.bucketname.require=\u9A30\u8A0A\u96F2BucketName\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qcloud.region.require=\u6240\u5C6C\u5730\u5340\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
qiniu.domain.require=\u4E03\u725B\u7D81\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qiniu.domain.url=\u4E03\u725B\u7D81\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u78BA
|
|
||||||
qiniu.accesskey.require=\u4E03\u725BAccessKey\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qiniu.secretkey.require=\u4E03\u725BSecretKey\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qiniu.bucketname.require=\u4E03\u725B\u7A7A\u9593\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
qiniu.templateId.require=\u4E03\u725B\u6A21\u677FID\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
fastdfs.domain.require=FastDFS\u7D81\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
fastdfs.domain.url=FastDFS\u7D81\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u78BA
|
|
||||||
|
|
||||||
local.domain.require=\u672C\u5730\u4E0A\u50B3\u7D81\u5B9A\u7684\u57DF\u540D\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
local.domain.url=\u672C\u5730\u4E0A\u50B3\u7D81\u5B9A\u7684\u57DF\u540D\u683C\u5F0F\u4E0D\u6B63\u78BA
|
|
||||||
local.path.url=\u5B58\u5132\u76EE\u9304\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
minio.endPoint.require=Minio EndPoint\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
minio.accesskey.require=Minio AccessKey\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
minio.secretkey.require=Minio SecretKey\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
minio.bucketname.require=Minio BucketName\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
sms.platform.range=\u5E73\u53F0\u985E\u578B\u53D6\u503C\u7BC4\u570D1~2
|
|
||||||
|
|
||||||
email.smtp.require=SMTP\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
email.port.require=\u7AEF\u53E3\u865F\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
email.username.require=\u90F5\u7BB1\u8CEC\u865F\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
email.password.require=\u90F5\u7BB1\u5BC6\u78BC\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
mail.name.require=\u6A21\u677F\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
mail.subject.require=\u90F5\u4EF6\u4E3B\u984C\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
mail.content.require=\u90F5\u4EF6\u6B63\u6587\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
model.name.require=\u6A21\u578B\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
model.key.require=\u6A21\u578B\u6A19\u8B58\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
news.title.require=\u6A19\u984C\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
news.content.require=\u5167\u5BB9\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
news.pubdate.require=\u767C\u4F48\u6642\u9593\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
region.id.require=\u5340\u57DF\u6A19\u8B58\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
region.pid.require=\u4E0A\u7D1A\u5340\u57DF\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
region.name.require=\u5340\u57DF\u540D\u7A31\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
processBizRoute.procDefId.require=\u6D41\u7A0B\u5B9A\u7FA9ID\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
processBizRoute.bizRoute.require=\u696D\u52D9\u8DEF\u7531\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
processBizRoute.procDefKey.require=\u6D41\u7A0B\u5B9A\u7FA9KEY\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
processBizRoute.version.require=\u6D41\u7A0B\u5B9A\u7FA9\u7248\u672C\u865F\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|
||||||
ProcessStart.processDefinitionKey.require=\u6D41\u7A0B\u5B9A\u7FA9KEY\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
ProcessStart.businessKey.require=\u696D\u52D9KEY\u4E0D\u80FD\u70BA\u7A7A
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="xiaozhi.modules.model.dao.ModelConfigDao">
|
||||||
|
<!-- 获取模型供应器字段 -->
|
||||||
|
<select id="getModelCodeList" resultType="String">
|
||||||
|
select model_name from ai_model_config where model_type = #{modelType}
|
||||||
|
<if test="modelName != null">and model_name = #{modelName}</if>
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="xiaozhi.modules.model.dao.ModelProviderDao">
|
||||||
|
<!-- 获取模型供应器字段 -->
|
||||||
|
<select id="getFieldList" resultType="string">
|
||||||
|
select fields from ai_model_provider where model_type = #{modelType} and provider_code = #{providerCode};
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@@ -3,48 +3,4 @@
|
|||||||
|
|
||||||
<mapper namespace="xiaozhi.modules.sys.dao.SysUserDao">
|
<mapper namespace="xiaozhi.modules.sys.dao.SysUserDao">
|
||||||
|
|
||||||
<select id="getList" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
|
||||||
select t1.*, (select t2.name from sys_dept t2 where t2.id=t1.dept_id) deptName
|
|
||||||
from sys_user t1 where t1.super_admin = 0
|
|
||||||
<if test="username != null and username.trim() != ''">
|
|
||||||
and t1.username like #{username}
|
|
||||||
</if>
|
|
||||||
<if test="deptId != null and deptId.trim() != ''">
|
|
||||||
and t1.dept_id = #{deptId}
|
|
||||||
</if>
|
|
||||||
<if test="gender != null and gender.trim() != ''">
|
|
||||||
and t1.gender = #{gender}
|
|
||||||
</if>
|
|
||||||
<if test="deptIdList != null">
|
|
||||||
and t1.dept_id in
|
|
||||||
<foreach item="id" collection="deptIdList" open="(" separator="," close=")">
|
|
||||||
#{id}
|
|
||||||
</foreach>
|
|
||||||
</if>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getById" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
|
||||||
select t1.*, (select t2.name from sys_dept t2 where t2.id=t1.dept_id) deptName from sys_user t1
|
|
||||||
where t1.id = #{value}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getByUsername" resultType="xiaozhi.modules.sys.entity.SysUserEntity">
|
|
||||||
select * from sys_user where username = #{value}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<update id="updatePassword">
|
|
||||||
update sys_user set password = #{newPassword} where id = #{id}
|
|
||||||
</update>
|
|
||||||
|
|
||||||
<select id="getCountByDeptId" resultType="int">
|
|
||||||
select count(*) from sys_user where dept_id = #{value}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<select id="getUserIdListByDeptId" resultType="Long">
|
|
||||||
select id from sys_user where dept_id in
|
|
||||||
<foreach item="deptId" collection="list" open="(" separator="," close=")">
|
|
||||||
#{deptId}
|
|
||||||
</foreach>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -8,14 +8,14 @@
|
|||||||
"name": "xiaozhi",
|
"name": "xiaozhi",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.8.1",
|
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"flyio": "^0.6.14",
|
"flyio": "^0.6.14",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-axios": "^3.5.2",
|
"vue-axios": "^3.5.2",
|
||||||
"vue-router": "^3.6.5",
|
"vue-router": "^3.6.5",
|
||||||
"vuex": "^3.6.2"
|
"vuex": "^3.6.2",
|
||||||
|
"xiaozhi": "file:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-router": "~5.0.0",
|
"@vue/cli-plugin-router": "~5.0.0",
|
||||||
@@ -325,48 +325,6 @@
|
|||||||
"@parcel/watcher-win32-x64": "2.5.1"
|
"@parcel/watcher-win32-x64": "2.5.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-android-arm64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-darwin-x64": {
|
"node_modules/@parcel/watcher-darwin-x64": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
|
"resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
|
||||||
@@ -388,216 +346,6 @@
|
|||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-win32-arm64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-win32-ia32": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
|
|
||||||
"cpu": [
|
|
||||||
"ia32"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@parcel/watcher-win32-x64": {
|
|
||||||
"version": "2.5.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
|
|
||||||
"integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/parcel"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@polka/url": {
|
"node_modules/@polka/url": {
|
||||||
"version": "1.0.0-next.28",
|
"version": "1.0.0-next.28",
|
||||||
"resolved": "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.28.tgz",
|
"resolved": "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.28.tgz",
|
||||||
@@ -1777,6 +1525,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.8.2.tgz",
|
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.8.2.tgz",
|
||||||
"integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
|
"integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
@@ -3488,6 +3237,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es-errors": "^1.3.0",
|
"es-errors": "^1.3.0",
|
||||||
"get-intrinsic": "^1.2.6",
|
"get-intrinsic": "^1.2.6",
|
||||||
@@ -3934,6 +3684,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
|
||||||
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
"integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
@@ -4256,6 +4007,7 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-symbols": "^1.0.3"
|
"has-symbols": "^1.0.3"
|
||||||
},
|
},
|
||||||
@@ -7031,7 +6783,8 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/pseudomap": {
|
"node_modules/pseudomap": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -9405,6 +9158,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/xiaozhi": {
|
||||||
|
"resolved": "",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
"build": "vue-cli-service build"
|
"build": "vue-cli-service build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.8.1",
|
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"flyio": "^0.6.14",
|
"flyio": "^0.6.14",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-axios": "^3.5.2",
|
"vue-axios": "^3.5.2",
|
||||||
"vue-router": "^3.6.5",
|
"vue-router": "^3.6.5",
|
||||||
"vuex": "^3.6.2"
|
"vuex": "^3.6.2",
|
||||||
|
"xiaozhi": "file:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-router": "~5.0.0",
|
"@vue/cli-plugin-router": "~5.0.0",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
@@ -5,7 +5,7 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title>小智-智控台</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
|||||||