mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-10-28 04:43:46 +08:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c1cc3afc5 | ||
|
|
654057e7a7 | ||
|
|
f4e5265aaf | ||
|
|
85d85fbe10 | ||
|
|
d4bd071487 | ||
|
|
3cee291997 | ||
|
|
1849d3ddaa | ||
|
|
7c6dfa545a | ||
|
|
9a72e51a55 | ||
|
|
c2d5da27e1 | ||
|
|
176e614457 | ||
|
|
a008b89b42 | ||
|
|
fb2108d88b |
47
.github/ISSUE_TEMPLATE/1.bug.yml
vendored
Normal file
47
.github/ISSUE_TEMPLATE/1.bug.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
name: Bug 报告 🐛
|
||||
description: 为 chatgpt-plus 提交错误报告
|
||||
labels: ['Bug']
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: ⚠️ 确认 issue 是否已存在 ⚠️
|
||||
description: 在提交 Issue 之前,请在 issue 列表搜索一下,确保你不是在提交一个重复的 issue。
|
||||
options:
|
||||
- label: 我已经搜索了现有的问题,没有找到跟我问题相关的问题。
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: GPT-3 or GPT-4
|
||||
description: 请选择你使用的 GPT 模型
|
||||
options:
|
||||
- GPT-3.5
|
||||
- GPT-4
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: 操作系统
|
||||
description: 请选择你使用的操作系统
|
||||
options:
|
||||
- Windows
|
||||
- Linux
|
||||
- MacOS
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug 描述 📝
|
||||
description: 请简单描述你发现的问题。
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 重现步骤 🕹
|
||||
description: |
|
||||
**⚠️ 无法重现的 issue 将会被关闭**
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 你的应用配置信息
|
||||
description: 请提供你的配置文档,**请注意数据脱敏**。
|
||||
value: |
|
||||
```toml
|
||||
把你的配置信息粘贴到这里
|
||||
```
|
||||
26
.github/ISSUE_TEMPLATE/2.feature.yml
vendored
Normal file
26
.github/ISSUE_TEMPLATE/2.feature.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: 功能优化 🚀
|
||||
description: 为 chatgpt-plus 提交优化建议
|
||||
labels: ['feature']
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: ⚠️ 确认 issue 是否已存在 ⚠️
|
||||
description: >
|
||||
在提交 Issue 之前,请在 issue 列表搜索一下,确保你不是在提交一个重复的 issue。
|
||||
options:
|
||||
- label: 我已经搜索了现有的问题,没有找到相关 issue。
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 功能描述 📝
|
||||
description: |
|
||||
描述此功能该如何工作。
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 示例 🌈
|
||||
description: 是否可以提供类似的样例,比如提供参考项目的链接或者截图。
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 动机 🔦
|
||||
description: 为什么要新增或者优化这个功能,缺少这个功能会给你或者其他用户带来什么不便?
|
||||
|
||||
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
24
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<!-- 📢 注意:
|
||||
|
||||
在提交的 PR 的时候请确保每个 PR 只包含一个功能修改或者优化,请不要把多个更改组合到一个 PR 提交。保持干净可管理的 git 历史记录至关重要。 为确保我们存储库的质量,我们恳请您在提交 PR 时遵守以下准则:
|
||||
|
||||
1. 每个 PR 专注于一个单一的、具体的改进。
|
||||
2. 不要包括任何不相关或[额外]的修改。
|
||||
3. 为所做的更改提供清晰的文档和解释。
|
||||
-->
|
||||
|
||||
### Background
|
||||
<!-- 简要概述此更改背后的基本原理。 包括相关背景、先前的讨论或相关 issue 的链接。 确保变更与项目的总体方向一致。-->
|
||||
|
||||
### Changes
|
||||
<!-- 简要说明你改动的内容 -->
|
||||
|
||||
### Test Plan
|
||||
<!-- 描述您如何测试此功能。 包括重现步骤、相关测试用例和任何其他相关信息-->
|
||||
|
||||
### PR 规则验证列表
|
||||
- [ ] 确保本次 PR 只包含单一的功能修改。
|
||||
- [ ] 我已经对我的代码更改进行了充分的测试。
|
||||
- [ ] 我已经考虑了我的更改的潜在风险和缓解措施。
|
||||
- [ ] 我已经修正了相关文档
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -26,4 +26,6 @@ src/tmp
|
||||
src/bin
|
||||
src/data
|
||||
web/.env.development
|
||||
web/.env.test
|
||||
web/.env.test2
|
||||
config.toml
|
||||
|
||||
254
README.md
254
README.md
@@ -9,25 +9,6 @@
|
||||
|
||||
**本项目基于 MIT 协议,免费开放全部源代码,可以作为个人学习使用或者商用。如需商用建议联系作者登记,仅做统计使用,优秀项目我们将在项目首页为您展示。**
|
||||
|
||||
## 项目介绍
|
||||
这一套完整的系统,包括两套前端聊天应用和一个后台管理系统。系统有用户鉴权,你可以自己使用,也可以部署直接给 C 端用户提供 ChatGPT 的服务。
|
||||
|
||||
项目的技术架构是
|
||||
|
||||
> Go + Vue3 + element-plus
|
||||
|
||||
后端采用的是 Go 语言开发的 Gin Web 框架。前端用的是 Vue3 + element-plus UI 框架
|
||||
|
||||
目前已经实现了以下功能:
|
||||
1. 通用版的 ChatGPT 聊天界面和功能,聊天记录保存在客户端。
|
||||
2. 口令机制:输入口令才可以访问,支持设置口令的对话次数,有效期。
|
||||
3. 角色版的聊天界面和功能,角色设定,预设一些角色,比如程序员,客服,作家,老师,艺术家...
|
||||
4. 保存聊天记录,支持聊天上下文。
|
||||
5. OpenAI API 负载均衡,限制每个 API Key 每分钟之内调用次数不超过 15次,防止被封。
|
||||
6. 支持配置多个代理,保证高可用。
|
||||
7. 实现 markdown 语法解析和代码高亮,支持复制回复内容功能。
|
||||
8. 后台管理功能,实现系统的动态配置,用户和角色的动态管理。
|
||||
|
||||
## 功能截图
|
||||
|
||||
### 1. 角色版PC端
|
||||
@@ -49,20 +30,243 @@
|
||||

|
||||
|
||||
### 5. 体验地址
|
||||
> 体验地址:[https://www.chat-plus.net/chat/#/free](https://www.chat-plus.net/chat/#/free) </br>
|
||||
> 口令:GeekMaster
|
||||
> 体验地址:[https://www.chat-plus.net/chat](https://www.chat-plus.net/chat) <br/>
|
||||
> 涉及到数据隐私问题,没有提供共享账号,大家自己快速注册一个账号就可以免费体验
|
||||
|
||||
## 项目介绍
|
||||
这一套完整的系统,包括两套前端聊天应用和一个后台管理系统。系统有用户鉴权,你可以自己使用,也可以部署直接给 C 端用户提供 ChatGPT 的服务。
|
||||
|
||||
项目的技术架构是
|
||||
|
||||
> Go + Vue3 + element-plus
|
||||
|
||||
后端采用的是 Go 语言开发的 Gin Web 框架。前端用的是 Vue3 + element-plus UI 框架
|
||||
|
||||
目前已经实现了以下功能:
|
||||
1. 通用版的 ChatGPT 聊天界面和功能,聊天记录保存在客户端。
|
||||
2. 口令机制:输入口令才可以访问,支持设置口令的对话次数,有效期。
|
||||
3. 角色版的聊天界面和功能,角色设定,预设一些角色,比如程序员,客服,作家,老师,艺术家...
|
||||
4. 保存聊天记录,支持聊天上下文。
|
||||
5. OpenAI API 负载均衡,限制每个 API Key 每分钟之内调用次数不超过 15次,防止被封。
|
||||
6. 支持配置多个代理,保证高可用。
|
||||
7. 实现 markdown 语法解析和代码高亮,支持复制回复内容功能。
|
||||
8. 后台管理功能,实现系统的动态配置,口令和角色的动态管理。
|
||||
|
||||
## 项目地址
|
||||
* Github 地址:https://github.com/yangjian102621/chatgpt-plus
|
||||
* 码云地址:https://gitee.com/blackfox/chatgpt-plus
|
||||
|
||||
## TODOLIST
|
||||
* [ ] 让用户配置自己的 API KEY,调用自己的 API Key,将不记 Token 的使用次数
|
||||
* [ ] 让用户配置自己的 API KEY,调用自己的 API Key,将不消耗口令的对话次数
|
||||
* [ ] 嵌入 AI 绘画功能,支持根据描述词生成图片
|
||||
* [ ] 接入自己训练的开源大语言模型
|
||||
* [ ] 接入 Google 语音 API,支持语音聊天
|
||||
|
||||
## 本地部署
|
||||
## 线上发布
|
||||
## 快速本地部署
|
||||
如果你想在本地快速尝鲜一下,你可以直接下载我打包好的一键运行包,然后直接运行就好了,就这么简单。
|
||||
支持 windows, linux 和 Mac 系统,[GitHub 下载地址](https://github.com/yangjian102621/chatgpt-plus/releases)。
|
||||
|
||||
我这里以 linux 系统为例,演示一下部署过程:
|
||||
|
||||
## 注意事项
|
||||
```shell
|
||||
# 1. 下载程序
|
||||
wget https://github.com/yangjian102621/chatgpt-plus/releases/download/v2.0.0/wechatGPT-amd64-linux
|
||||
# 2. 添加执行权限
|
||||
chmod +x wechatGPT-amd64-linux
|
||||
# 3. 运行程序
|
||||
./wechatGPT-amd64-linux
|
||||
```
|
||||
服务启动成功之后直接访问后台管理页面(http://localhost:5678/chat/#/admin),初始用户名和密码分别为 `admin` 和 `admin123`。
|
||||
|
||||
修改系统配置。这里主要配置 OpenAI 的 [API KEY](https://platform.openai.com/account/api-keys) 和魔法,因为调用 OpenAI 的 API 需要魔法。
|
||||
|
||||

|
||||
|
||||
最后,你还需要一个口令来访问 ChatGPT 前端应用。直接在【后台管理系统->口令管理】新增一个口令就好了。
|
||||
|
||||

|
||||
|
||||
**切记要先退出后台登录,再登录前端应用!!!前后端账号权限不一致。**
|
||||
|
||||
然后直接使用口令名称登录前端应用:
|
||||
|
||||
* 角色版:http://localhost:5678/chat/#/plus
|
||||
* 普通版:http://localhost:5678/chat/#/free
|
||||
|
||||
祝你使用愉快!
|
||||
|
||||
## 本地开发调试
|
||||
本项目的技术架构是
|
||||
|
||||
> Go + Vue3 + element-plus
|
||||
|
||||
所以你需要提前安装好 Go(1.19以上)语言环境和 Nodejs 环境。
|
||||
|
||||
### 1. 运行后端程序
|
||||
|
||||
首先,我们需要拷贝默认的配置文档:
|
||||
```shell
|
||||
cd src
|
||||
cp config.sample.toml config.toml
|
||||
```
|
||||
然后,我们需要修改配置文档,需要修改的有三处,一个是魔法,第二个是 API KEY,第三个是修改 Session 跨域的域名。因为我们前后端是分离的,所以必须解决前端访问跨域的问题。
|
||||
|
||||
```toml
|
||||
ProxyURL = ["YOUR_PROXY_URL"] # 替换成你本地代理,如:http://127.0.0.1:7777
|
||||
|
||||
[Session]
|
||||
SecretKey = "azyehq3ivunjhbntz78isj00i4hz2mt9xtddysfucxakadq4qbfrt0b7q3lnvg80"
|
||||
Name = "CHAT_SESSION_ID"
|
||||
Path = "/"
|
||||
Domain = "172.22.11.200" # 这里需要改成你当前机器的内网 IP 地址
|
||||
MaxAge = 86400
|
||||
Secure = false
|
||||
HttpOnly = false
|
||||
SameSite = 2
|
||||
|
||||
[[Chat.ApiKeys]] # API KEY 可以添加多个,自动负载均衡
|
||||
Value = "YOUR_OPENAI_API_KEY" # 这里替换成你的 OpenAI API KEY: sk-xxxx
|
||||
LastUsed = 0
|
||||
```
|
||||
|
||||
修改之后运行后端程序:
|
||||
|
||||
```shell
|
||||
# 1. 先下载依赖
|
||||
go mod tidy
|
||||
# 2. 运行程序
|
||||
go run main.go
|
||||
```
|
||||
|
||||
### 2. 运行前端程序
|
||||
同样先拷贝配置文档:
|
||||
```shell
|
||||
cd web
|
||||
cp .env.production .env.development
|
||||
```
|
||||
编辑 `.env.development` 文件,修改后端 API 的访问路径:
|
||||
|
||||
```ini
|
||||
VUE_APP_API_HOST=http://172.22.11.200:5678 # 这里也是需要把 IP 替换成你本地的内网 IP 地址
|
||||
VUE_APP_WS_HOST=ws://172.22.11.200:5678
|
||||
```
|
||||
|
||||
配置好了之后就可以运行前端应用了:
|
||||
```
|
||||
# 安装依赖
|
||||
npm install
|
||||
# 运行
|
||||
npm run dev
|
||||
```
|
||||
|
||||
启动之后通过**内网地址**访问后台管理页面:http://172.22.11.200:8888/chat/#/admin ,添加一个口令就可以开始测试了。
|
||||
|
||||
## 项目打包
|
||||
由于本项目是采用异构开发的方式,所项目打包分成两步:首先打包前端应用,然后再将打包后前端文件打包进后端应用,最后打成一个包。
|
||||
|
||||
### 打包前端
|
||||
首先你还是需要修改配置文档 `.env.production`,指定你线上部署的域名。
|
||||
|
||||
```ini
|
||||
VUE_APP_API_HOST=https://www.chat-plus.net # API 请求主机
|
||||
VUE_APP_WS_HOST=wss://www.chat-plus.net # websocket 请求主机
|
||||
```
|
||||
|
||||
执行打包
|
||||
```shell
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 打包后端
|
||||
你可以根据个人需求将项目打包成 windows/linux/darwin 平台项目。
|
||||
```shell
|
||||
# for all platforms
|
||||
make all
|
||||
# for linux only
|
||||
make linux
|
||||
```
|
||||
打包后的可执行文件在 `src/bin` 目录下。
|
||||
|
||||
### 线上部署
|
||||
部署方式跟 [快速本地部署](#快速本地部署) 一样,将打包好的可执行文件在线上服务器运行即可。
|
||||
|
||||
> **特别注意:** 线上发布请记得修改配置文档中的 AccessKey, 以免给你的应用造成风险!!!
|
||||
|
||||
**另外,如果你部署在国外的服务器,那么就不需要配置代理,直接留空就行了。**
|
||||
|
||||
```shell
|
||||
ProxyURL = []
|
||||
```
|
||||
### 使用 Nginx 代理
|
||||
|
||||
```nginx
|
||||
# 这里需要配置允许 Websocket 请求转发,非常重要
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'websocket' upgrade;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name www.chat-plus.net;
|
||||
|
||||
ssl_certificate xxx.pem; # SSL 证书
|
||||
ssl_certificate_key xxx.key;
|
||||
ssl_session_timeout 5m;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
underscores_in_headers on;
|
||||
access_log /var/log/chatgpt/access.log;
|
||||
error_log /var/log/chatgpt/error.log;
|
||||
|
||||
location / {
|
||||
proxy_http_version 1.1;
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_pass http://127.0.0.1:5678;
|
||||
|
||||
|
||||
}
|
||||
|
||||
# 关闭静态资源日志
|
||||
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ {
|
||||
proxy_pass http://127.0.0.1:5678;
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 参与贡献
|
||||
|
||||
个人的力量始终有限,任何形式的贡献都是欢迎的,包括但不限于贡献代码,优化文档,提交 issue 和 PR 等。
|
||||
|
||||
如果有兴趣的话,也可以加微信进入微信讨论群。
|
||||
|
||||

|
||||
|
||||
#### 特此声明:不接受在微信或者微信群给开发者提 Bug,有问题或者优化建议请提交 Issue 和 PR。非常感谢您的配合!
|
||||
|
||||
### Commit 类型
|
||||
* feat: 新特性或功能
|
||||
* fix: 缺陷修复
|
||||
* docs: 文档更新
|
||||
* style: 代码风格或者组件样式更新
|
||||
* refactor: 代码重构,不引入新功能和缺陷修复
|
||||
* opt: 性能优化
|
||||
* chore: 一些不涉及到功能变动的小提交,比如修改文字表述,修改注释等
|
||||
|
||||
|
||||
## 打赏
|
||||
如果你觉得这个项目对你有帮助,并且情况允许的话,可以请作者喝杯咖啡,非常感谢你的支持~
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
BIN
docs/imgs/config.png
Normal file
BIN
docs/imgs/config.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
BIN
docs/imgs/new-user.png
Normal file
BIN
docs/imgs/new-user.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
docs/imgs/wechat-pay.png
Normal file
BIN
docs/imgs/wechat-pay.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
BIN
docs/imgs/wx.png
Normal file
BIN
docs/imgs/wx.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
@@ -52,6 +52,8 @@ func (s *Server) ChatHandle(c *gin.Context) {
|
||||
_, err = GetChatHistory(session.Username, roleKey)
|
||||
if err != nil {
|
||||
replyMessage(client, chatRole.HelloMsg, true)
|
||||
// 发送项目地址
|
||||
replyMessage(client, "本项目已开放全部源代码:https://github.com/yangjian102621/chatgpt-plus,一分钟搭建自己的 ChatGPT 应用。", false)
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
@@ -90,26 +92,26 @@ func (s *Server) sendMessage(ctx context.Context, session types.ChatSession, rol
|
||||
|
||||
user, err := GetUser(session.Username)
|
||||
if err != nil {
|
||||
replyMessage(ws, "当前 TOKEN 无效,请使用合法的 TOKEN 登录!", false)
|
||||
replyMessage(ws, "当前口令无效,请使用合法的口令登录!", false)
|
||||
return err
|
||||
}
|
||||
|
||||
if user.Status == false {
|
||||
replyMessage(ws, "当前 TOKEN 已经被禁用,如果疑问,请联系管理员!", false)
|
||||
replyMessage(ws, "当前口令已经被禁用,如果疑问,请联系管理员!", false)
|
||||
replyMessage(ws, "", false)
|
||||
return errors.New("当前 TOKEN " + user.Name + "已经被禁用")
|
||||
return errors.New("当前口令" + user.Name + "已经被禁用")
|
||||
}
|
||||
|
||||
if time.Now().Unix() > user.ExpiredTime {
|
||||
exTime := time.Unix(user.ExpiredTime, 0).Format("2006-01-02 15:04:05")
|
||||
replyMessage(ws, "当前 TOKEN 已过期,过期时间为:"+exTime+",如果疑问,请联系管理员!", false)
|
||||
replyMessage(ws, "当前口令已过期,过期时间为:"+exTime+",如果疑问,请联系管理员!", false)
|
||||
replyMessage(ws, "", false)
|
||||
return errors.New("当前 TOKEN " + user.Name + "已过期")
|
||||
return errors.New("当前口令" + user.Name + "已过期")
|
||||
}
|
||||
|
||||
if user.MaxCalls > 0 && user.RemainingCalls <= 0 {
|
||||
replyMessage(ws, "当前 TOKEN 点数已经用尽,加入我们的知识星球可以免费领取点卡!", false)
|
||||
replyMessage(ws, "", false)
|
||||
replyMessage(ws, "当前口令点数已经用尽,请联系管理员领取新的免费口令!", false)
|
||||
replyMessage(ws, "", false)
|
||||
return nil
|
||||
}
|
||||
var req = types.ApiRequest{
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
NODE_ENV = 'production'
|
||||
VUE_APP_API_HOST=https://www.r9it.com
|
||||
VUE_APP_WS_HOST=wss://www.r9it.com
|
||||
VUE_APP_API_HOST=http://localhost:5678
|
||||
VUE_APP_WS_HOST=ws://localhost:5678
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"test": "vue-cli-service build --mode test ",
|
||||
"test": "vue-cli-service build --mode test",
|
||||
"test2": "vue-cli-service build --mode test2",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<sys-config v-if="curTab==='config'"/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="用户管理" name="user" v-if="arrayContains(tabs, 'user')">
|
||||
<el-tab-pane label="口令管理" name="user" v-if="arrayContains(tabs, 'user')">
|
||||
<user-list v-if="curTab==='user'"/>
|
||||
</el-tab-pane>
|
||||
|
||||
@@ -149,7 +149,7 @@ export default defineComponent({
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '用户管理',
|
||||
title: '口令管理',
|
||||
tab: 'user',
|
||||
active: false,
|
||||
},
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
<el-icon>
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
新增用户
|
||||
新增口令
|
||||
</el-button>
|
||||
|
||||
<el-button type="success" @click="showBatchAddUserDialog = true">
|
||||
<el-icon>
|
||||
<Plus/>
|
||||
</el-icon>
|
||||
批量新增
|
||||
批量生成口令
|
||||
</el-button>
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
<el-table :data="users">
|
||||
<el-table-column prop="name" label="用户名"/>
|
||||
<el-table-column prop="name" label="口令名称"/>
|
||||
<el-table-column prop="max_calls" label="最大提问次数"/>
|
||||
<el-table-column prop="remaining_calls" label="剩余提问次数"/>
|
||||
<el-table-column label="激活时间" width="180">
|
||||
@@ -63,16 +63,16 @@
|
||||
|
||||
<el-dialog
|
||||
v-model="showUserDialog"
|
||||
title="新增用户"
|
||||
title="新增口令"
|
||||
width="50%"
|
||||
:destroy-on-close="true"
|
||||
>
|
||||
<el-form :model="form1" label-width="100px" ref="userAddFormRef" :rules="rules">
|
||||
<el-form-item label="用户名:" prop="name">
|
||||
<el-form-item label="口令名称:" prop="name">
|
||||
<el-input
|
||||
v-model="form1.name"
|
||||
autocomplete="off"
|
||||
placeholder="请输入用户名"
|
||||
placeholder="请输入口令名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
|
||||
<el-dialog
|
||||
v-model="showBatchAddUserDialog"
|
||||
title="批量生成用户"
|
||||
title="批量生成口令"
|
||||
width="50%"
|
||||
:destroy-on-close="true"
|
||||
|
||||
@@ -135,15 +135,15 @@
|
||||
<el-input
|
||||
v-model.number="form3.max_calls"
|
||||
autocomplete="off"
|
||||
placeholder="最大提问次数"
|
||||
placeholder="生成口令的最大提问次数"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="用户数量:" prop="number">
|
||||
<el-form-item label="口令数量:" prop="number">
|
||||
<el-input
|
||||
v-model.number="form3.number"
|
||||
autocomplete="off"
|
||||
placeholder="批量生成的用户数量"
|
||||
placeholder="批量生成的口令数量"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
@@ -188,15 +188,15 @@
|
||||
|
||||
<el-dialog
|
||||
v-model="showUserEditDialog"
|
||||
title="编辑用户"
|
||||
title="编辑口令"
|
||||
width="50%"
|
||||
>
|
||||
<el-form :model="form2" label-width="100px" ref="userEditFormRef" :rules="rules">
|
||||
<el-form-item label="用户名:" prop="name">
|
||||
<el-form-item label="口令名称:" prop="name">
|
||||
<el-input
|
||||
v-model="form2.name"
|
||||
autocomplete="off"
|
||||
placeholder="请输入用户名"
|
||||
placeholder="请输入口令名称"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -271,7 +271,7 @@ const roles = ref([])
|
||||
const showUserDialog = ref(false)
|
||||
const showUserEditDialog = ref(false)
|
||||
const rules = reactive({
|
||||
name: [{required: true, message: '请输入用户名', trigger: 'change',}],
|
||||
name: [{required: true, message: '请输入口令名称', trigger: 'change',}],
|
||||
max_calls: [
|
||||
{required: true, message: '请输入提问次数'},
|
||||
{type: 'number', message: '请输入有效数字'},
|
||||
@@ -285,7 +285,7 @@ const rules = reactive({
|
||||
{type: 'number', message: '请输入有效数字'},
|
||||
],
|
||||
number: [
|
||||
{required: true, message: '请输入用户数量', trigger: 'change'},
|
||||
{required: true, message: '请输入口令数量', trigger: 'change'},
|
||||
{type: 'number', message: '请输入有效数字'},
|
||||
],
|
||||
chat_roles: [{required: true, message: '请选择聊天角色', trigger: 'change'}],
|
||||
@@ -296,7 +296,7 @@ const userAddFormRef = ref(null)
|
||||
const userEditFormRef = ref(null)
|
||||
|
||||
onMounted(() => {
|
||||
// 获取用户列表
|
||||
// 获取口令列表
|
||||
httpPost('/api/admin/user/list').then((res) => {
|
||||
users.value = res.data;
|
||||
}).catch(() => {
|
||||
@@ -316,7 +316,7 @@ onMounted(() => {
|
||||
})
|
||||
})
|
||||
|
||||
// 新增用户
|
||||
// 新增口令
|
||||
const addUser = () => {
|
||||
userAddFormRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
@@ -324,11 +324,11 @@ const addUser = () => {
|
||||
form1.value.term = parseInt(form1.value.term)
|
||||
form1.value.max_calls = parseInt(form1.value.max_calls)
|
||||
httpPost('/api/admin/user/add', form1.value).then((res) => {
|
||||
ElMessage.success('添加用户成功')
|
||||
ElMessage.success('添加口令成功')
|
||||
form1.value = {chat_roles: []}
|
||||
users.value.unshift(res.data)
|
||||
}).catch((e) => {
|
||||
ElMessage.error('添加用户失败,' + e.message)
|
||||
ElMessage.error('添加口令失败,' + e.message)
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
@@ -359,15 +359,15 @@ const selectRole = function (items) {
|
||||
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
// 删除口令
|
||||
const removeUser = function (user) {
|
||||
httpPost('/api/admin/user/remove', {name: user.name}).then(() => {
|
||||
ElMessage.success('删除用户成功')
|
||||
ElMessage.success('删除口令成功')
|
||||
users.value = removeArrayItem(users.value, user, function (v1, v2) {
|
||||
return v1.name === v2.name
|
||||
})
|
||||
}).catch((e) => {
|
||||
ElMessage.error('删除用户失败,' + e.message)
|
||||
ElMessage.error('删除口令失败,' + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ const userEdit = function (user) {
|
||||
showUserEditDialog.value = true
|
||||
}
|
||||
|
||||
// 更新用户
|
||||
// 更新口令
|
||||
const updateUser = function () {
|
||||
userEditFormRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
@@ -384,9 +384,9 @@ const updateUser = function () {
|
||||
form2.value.term = parseInt(form2.value.term)
|
||||
form2.value.remaining_calls = parseInt(form2.value.remaining_calls)
|
||||
httpPost('/api/admin/user/set', form2.value).then(() => {
|
||||
ElMessage.success('更新用户成功')
|
||||
ElMessage.success('更新口令成功')
|
||||
}).catch((e) => {
|
||||
ElMessage.error('更新用户失败,' + e.message)
|
||||
ElMessage.error('更新口令失败,' + e.message)
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
@@ -400,11 +400,11 @@ const form3 = ref({chat_roles: []})
|
||||
const batchAddUser = function () {
|
||||
httpPost('api/admin/user/batch-add', form3.value).then((res) => {
|
||||
console.log(res.data)
|
||||
ElMessage.success('添加用户成功')
|
||||
ElMessage.success('添加口令成功')
|
||||
users.value = [...res.data, ...users.value]
|
||||
showBatchAddUserDialog.value = false
|
||||
}).catch((e) => {
|
||||
console.log('添加用户失败,' + e.message)
|
||||
console.log('添加口令失败,' + e.message)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user