c) {
+ this.onError = c;
+ return this;
+ }
+
+ /**
+ * 关闭会话,try-with-resources / finally 自动调用
+ */
+ @Override
+ public void close() {
+ try {
+ if (session != null && session.isOpen()) {
+ session.close(CloseStatus.NORMAL);
+ }
+ }
+ catch (IOException ignored) {}
+ textMessageQueue.clear();
+ binaryMessageQueue.clear();
+ errorFuture.completeExceptionally(new IOException("WebSocket 已关闭"));
+ }
+
+ private class InternalHandler extends AbstractWebSocketHandler {
+ private final String targetUri;
+ private final StopWatch stopWatch;
+
+ InternalHandler(String targetUri) {
+ this.targetUri = targetUri;
+ this.stopWatch = new StopWatch();
+ }
+
+ /**
+ * 连接建立时回调
+ */
+ @Override
+ public void afterConnectionEstablished(WebSocketSession session) {
+ // 保存会话
+ WebSocketClientManager.this.session = session;
+ this.stopWatch.start();
+ log.info("ws连接成功, 目标URI: {}, 连接时间: {}", targetUri, DateUtils.getDateTimeNow(DateUtils.DATE_TIME_MILLIS_PATTERN));
+ }
+
+ /**
+ * 处理文本消息
+ */
+ @Override
+ protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
+ String payload = message.getPayload();
+ // 入队
+ textMessageQueue.offer(payload);
+ // 回调用户注册的 onText
+ if (onText != null) {
+ CALLBACK_EXECUTOR.submit(() -> onText.accept(payload));
+ }
+ }
+
+ /**
+ * 处理二进制消息
+ */
+ @Override
+ protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
+ ByteBuffer buf = message.getPayload();
+ byte[] data = new byte[buf.remaining()];
+ buf.get(data);
+ // 入队
+ binaryMessageQueue.offer(data);
+ // 回调用户注册的 onBinary
+ if (onBinary != null) {
+ CALLBACK_EXECUTOR.submit(() -> onBinary.accept(data));
+ }
+ }
+
+ /**
+ * 传输错误时回调
+ */
+ @Override
+ public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
+ super.handleTransportError(session, exception);
+ // 保持原有逻辑:完成 errorFuture、回调 onError、关闭会话、异步通知连接失败
+ errorFuture.completeExceptionally(exception);
+ if (onError != null) {
+ CALLBACK_EXECUTOR.submit(() -> onError.accept(exception));
+ }
+ session.close(CloseStatus.SERVER_ERROR);
+ }
+
+ /**
+ * 连接关闭时回调
+ */
+ @Override
+ public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
+ super.afterConnectionClosed(session, status);
+ if (stopWatch.isRunning()) {
+ stopWatch.stop();
+ }
+ log.info("ws连接关闭, 目标URI: {}, 关闭时间: {}, 连接总时长: {}s",
+ targetUri, DateUtils.getDateTimeNow(DateUtils.DATE_TIME_MILLIS_PATTERN), DateUtils.millsToSecond(stopWatch.getTotalTimeMillis()));
+ }
+ }
+
+ public static class Builder {
+ private String uri; // 目标 WS URI
+ private long connectTimeout = 3; // 请求连接等待时间
+ private TimeUnit connectUnit = TimeUnit.SECONDS; // 请求连接等待时间单位
+ private long maxSessionDuration = 5; // 最大连线时间,默认5秒
+ private TimeUnit maxSessionDurationUnit = TimeUnit.SECONDS; // 最大连线时间单位
+ private int queueCapacity = 100; // 消息队列容量
+ private WebSocketHttpHeaders headers; // 请求头
+
+ /**
+ * 目标 WS URI
+ */
+ public Builder uri(String uri) {
+ this.uri = Objects.requireNonNull(uri);
+ return this;
+ }
+
+ public Builder headers(WebSocketHttpHeaders h) {
+ this.headers = h;
+ return this;
+ }
+
+ public Builder connectTimeout(long t, TimeUnit u) {
+ this.connectTimeout = t;
+ this.connectUnit = u;
+ return this;
+ }
+
+ public Builder maxSessionDuration(long t, TimeUnit u) {
+ this.maxSessionDuration = t;
+ this.maxSessionDurationUnit = u;
+ return this;
+ }
+
+ public Builder queueCapacity(int c) {
+ this.queueCapacity = c;
+ return this;
+ }
+
+ public WebSocketClientManager build() throws InterruptedException, ExecutionException, TimeoutException, IOException {
+ return WebSocketClientManager.build(this);
+ }
+
+ }
+}
diff --git a/main/manager-api/src/main/resources/db/changelog/202505091554.sql b/main/manager-api/src/main/resources/db/changelog/202505091555.sql
similarity index 79%
rename from main/manager-api/src/main/resources/db/changelog/202505091554.sql
rename to main/manager-api/src/main/resources/db/changelog/202505091555.sql
index 87d879dd..b7ad91d4 100644
--- a/main/manager-api/src/main/resources/db/changelog/202505091554.sql
+++ b/main/manager-api/src/main/resources/db/changelog/202505091555.sql
@@ -12,4 +12,14 @@ config_json = '{"host": "127.0.0.1", "port": 10096, "type": "fun_server", "is_ss
不要退出容器,继续在容器中执行第四句:nohup bash run_server_2pass.sh --download-model-dir /workspace/models --vad-dir damo/speech_fsmn_vad_zh-cn-16k-common-onnx --model-dir damo/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-onnx --online-model-dir damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-online-onnx --punc-dir damo/punc_ct-transformer_zh-cn-common-vad_realtime-vocab272727-onnx --lm-dir damo/speech_ngram_lm_zh-cn-ai-wesp-fst --itn-dir thuduj12/fst_itn_zh --hotword /workspace/models/hotwords.txt > log.txt 2>&1 &
上一句话执行后会进入到容器,继续第五句:tail -f log.txt
第五句话执行完后,会看到模型下载日志,下载完后就可以连接使用了
-以上是使用CPU推理,如果有GPU,详细参考:https://github.com/modelscope/FunASR/blob/main/runtime/docs/SDK_advanced_guide_online_zh.md' WHERE `id` = 'ASR_FunASRServer';
\ No newline at end of file
+以上是使用CPU推理,如果有GPU,详细参考:https://github.com/modelscope/FunASR/blob/main/runtime/docs/SDK_advanced_guide_online_zh.md' WHERE `id` = 'ASR_FunASRServer';
+
+-- FishSpeech配置说明
+UPDATE `ai_model_config` SET
+`doc_link` = 'https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/fish-speech-integration.md',
+`remark` = 'FishSpeech配置说明:
+1. 需要本地部署FishSpeech服务
+2. 支持自定义音色
+3. 本地推理,无需网络连接
+4. 输出文件保存在tmp/目录
+5. 可参照教程https://github.com/xinnan-tech/xiaozhi-esp32-server/blob/main/docs/fish-speech-integration.md' WHERE `id` = 'TTS_FishSpeech';
diff --git a/main/manager-api/src/main/resources/db/changelog/202505122348.sql b/main/manager-api/src/main/resources/db/changelog/202505122348.sql
new file mode 100644
index 00000000..05bbeb84
--- /dev/null
+++ b/main/manager-api/src/main/resources/db/changelog/202505122348.sql
@@ -0,0 +1,6 @@
+-- 添加总结记忆字段
+ALTER TABLE `ai_agent`
+ADD COLUMN `summary_memory` text COMMENT '总结记忆' AFTER `system_prompt`;
+
+ALTER TABLE `ai_agent_template`
+ADD COLUMN `summary_memory` text COMMENT '总结记忆' AFTER `system_prompt`;
diff --git a/main/manager-api/src/main/resources/db/changelog/202505142037.sql b/main/manager-api/src/main/resources/db/changelog/202505142037.sql
new file mode 100644
index 00000000..37a49013
--- /dev/null
+++ b/main/manager-api/src/main/resources/db/changelog/202505142037.sql
@@ -0,0 +1,7 @@
+update ai_agent_template set system_prompt = replace(system_prompt, '我是', '你是');
+
+delete from sys_params where id in (500,501,402);
+INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (500, 'end_prompt.enable', 'true', 'boolean', 1, '是否开启结束语');
+INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (501, 'end_prompt.prompt', '请你以“时间过得真快”未来头,用富有感情、依依不舍的话来结束这场对话吧!', 'string', 1, '结束提示词');
+
+INSERT INTO `sys_params` (id, param_code, param_value, value_type, param_type, remark) VALUES (402, 'plugins.get_weather.api_host', 'mj7p3y7naa.re.qweatherapi.com', 'string', 1, '开发者apihost');
\ No newline at end of file
diff --git a/main/manager-api/src/main/resources/db/changelog/202505151451.sql b/main/manager-api/src/main/resources/db/changelog/202505151451.sql
new file mode 100644
index 00000000..601de457
--- /dev/null
+++ b/main/manager-api/src/main/resources/db/changelog/202505151451.sql
@@ -0,0 +1,18 @@
+-- 修改自定义TTS接口请求定义
+update `ai_model_provider` set `fields` =
+'[{"key":"url","label":"服务地址","type":"string"},{"key":"method","label":"请求方式","type":"string"},{"key":"params","label":"请求参数","type":"dict","dict_name":"params"},{"key":"headers","label":"请求头","type":"dict","dict_name":"headers"},{"key":"format","label":"音频格式","type":"string"},{"key":"output_dir","label":"输出目录","type":"string"}]'
+where `id` = 'SYSTEM_TTS_custom';
+
+-- 修改自定义TTS配置说明
+UPDATE `ai_model_config` SET
+`doc_link` = NULL,
+`remark` = '自定义TTS配置说明:
+1. 自定义的TTS接口服务,请求参数可自定义,可接入众多TTS服务
+2. 以本地部署的KokoroTTS为例
+3. 如果只有cpu运行:docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:latest
+4. 如果只有gpu运行:docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:latest
+配置说明:
+1. 在params中配置请求参数,使用JSON格式
+ 例如KokoroTTS:{ "input": "{prompt_text}", "speed": 1, "voice": "zm_yunxi", "stream": true, "download_format": "mp3", "response_format": "mp3", "return_download_link": true }
+2. 在headers中配置请求头
+3. 设置返回音频格式' WHERE `id` = 'TTS_CustomTTS';
\ No newline at end of file
diff --git a/main/manager-api/src/main/resources/db/changelog/202505182234.sql b/main/manager-api/src/main/resources/db/changelog/202505182234.sql
new file mode 100644
index 00000000..3873e5d4
--- /dev/null
+++ b/main/manager-api/src/main/resources/db/changelog/202505182234.sql
@@ -0,0 +1,65 @@
+-- 添加手机短信注册功能的需要的参数
+delete from sys_params where id in (108, 109, 110, 111, 112, 113, 114, 115);
+delete from sys_params where id in (610, 611, 612, 613);
+INSERT INTO sys_params
+(id, param_code, param_value, value_type, param_type, remark, creator, create_date, updater, update_date)
+ VALUES
+(108, 'server.name', 'xiaozhi-esp32-server', 'string', 1, '系统名称', NULL, NULL, NULL, NULL),
+(109, 'server.beian_icp_num', 'null', 'string', 1, 'icp备案号,填写null则不设置', NULL, NULL, NULL, NULL),
+(110, 'server.beian_ga_num', 'null', 'string', 1, '公安备案号,填写null则不设置', NULL, NULL, NULL, NULL),
+(111, 'server.enable_mobile_register', 'false', 'boolean', 1, '是否开启手机注册', NULL, NULL, NULL, NULL),
+(112, 'server.sms_max_send_count', '10', 'number', 1, '单号码单日最大短信发送条数', NULL, NULL, NULL, NULL),
+(610, 'aliyun.sms.access_key_id', '', 'string', 1, '阿里云平台access_key', NULL, NULL, NULL, NULL),
+(611, 'aliyun.sms.access_key_secret', '', 'string', 1, '阿里云平台access_key_secret', NULL, NULL, NULL, NULL),
+(612, 'aliyun.sms.sign_name', '', 'string', 1, '阿里云短信签名', NULL, NULL, NULL, NULL),
+(613, 'aliyun.sms.sms_code_template_code', '', 'string', 1, '阿里云短信模板', NULL, NULL, NULL, NULL);
+
+update sys_params set remark = '是否允许管理员以外的人注册' where param_code = 'server.allow_user_register';
+
+-- 增加手机区域字典
+-- 插入固件类型字典类型
+delete from `sys_dict_type` where `id` = 102;
+INSERT INTO `sys_dict_type` (`id`, `dict_type`, `dict_name`, `remark`, `sort`, `creator`, `create_date`, `updater`, `update_date`) VALUES
+(102, 'MOBILE_AREA', '手机区域', '手机区域字典', 0, 1, NOW(), 1, NOW());
+
+-- 插入固件类型字典数据
+delete from `sys_dict_data` where `dict_type_id` = 102;
+INSERT INTO `sys_dict_data` (`id`, `dict_type_id`, `dict_label`, `dict_value`, `remark`, `sort`, `creator`, `create_date`, `updater`, `update_date`) VALUES
+(102001, 102, '中国大陆', '+86', '中国大陆', 1, 1, NOW(), 1, NOW()),
+(102002, 102, '中国香港', '+852', '中国香港', 2, 1, NOW(), 1, NOW()),
+(102003, 102, '中国澳门', '+853', '中国澳门', 3, 1, NOW(), 1, NOW()),
+(102004, 102, '中国台湾', '+886', '中国台湾', 4, 1, NOW(), 1, NOW()),
+(102005, 102, '美国/加拿大', '+1', '美国/加拿大', 5, 1, NOW(), 1, NOW()),
+(102006, 102, '英国', '+44', '英国', 6, 1, NOW(), 1, NOW()),
+(102007, 102, '法国', '+33', '法国', 7, 1, NOW(), 1, NOW()),
+(102008, 102, '意大利', '+39', '意大利', 8, 1, NOW(), 1, NOW()),
+(102009, 102, '德国', '+49', '德国', 9, 1, NOW(), 1, NOW()),
+(102010, 102, '波兰', '+48', '波兰', 10, 1, NOW(), 1, NOW()),
+(102011, 102, '瑞士', '+41', '瑞士', 11, 1, NOW(), 1, NOW()),
+(102012, 102, '西班牙', '+34', '西班牙', 12, 1, NOW(), 1, NOW()),
+(102013, 102, '丹麦', '+45', '丹麦', 13, 1, NOW(), 1, NOW()),
+(102014, 102, '马来西亚', '+60', '马来西亚', 14, 1, NOW(), 1, NOW()),
+(102015, 102, '澳大利亚', '+61', '澳大利亚', 15, 1, NOW(), 1, NOW()),
+(102016, 102, '印度尼西亚', '+62', '印度尼西亚', 16, 1, NOW(), 1, NOW()),
+(102017, 102, '菲律宾', '+63', '菲律宾', 17, 1, NOW(), 1, NOW()),
+(102018, 102, '新西兰', '+64', '新西兰', 18, 1, NOW(), 1, NOW()),
+(102019, 102, '新加坡', '+65', '新加坡', 19, 1, NOW(), 1, NOW()),
+(102020, 102, '泰国', '+66', '泰国', 20, 1, NOW(), 1, NOW()),
+(102021, 102, '日本', '+81', '日本', 21, 1, NOW(), 1, NOW()),
+(102022, 102, '韩国', '+82', '韩国', 22, 1, NOW(), 1, NOW()),
+(102023, 102, '越南', '+84', '越南', 23, 1, NOW(), 1, NOW()),
+(102024, 102, '印度', '+91', '印度', 24, 1, NOW(), 1, NOW()),
+(102025, 102, '巴基斯坦', '+92', '巴基斯坦', 25, 1, NOW(), 1, NOW()),
+(102026, 102, '尼日利亚', '+234', '尼日利亚', 26, 1, NOW(), 1, NOW()),
+(102027, 102, '孟加拉国', '+880', '孟加拉国', 27, 1, NOW(), 1, NOW()),
+(102028, 102, '沙特阿拉伯', '+966', '沙特阿拉伯', 28, 1, NOW(), 1, NOW()),
+(102029, 102, '阿联酋', '+971', '阿联酋', 29, 1, NOW(), 1, NOW()),
+(102030, 102, '巴西', '+55', '巴西', 30, 1, NOW(), 1, NOW()),
+(102031, 102, '墨西哥', '+52', '墨西哥', 31, 1, NOW(), 1, NOW()),
+(102032, 102, '智利', '+56', '智利', 32, 1, NOW(), 1, NOW()),
+(102033, 102, '阿根廷', '+54', '阿根廷', 33, 1, NOW(), 1, NOW()),
+(102034, 102, '埃及', '+20', '埃及', 34, 1, NOW(), 1, NOW()),
+(102035, 102, '南非', '+27', '南非', 35, 1, NOW(), 1, NOW()),
+(102036, 102, '肯尼亚', '+254', '肯尼亚', 36, 1, NOW(), 1, NOW()),
+(102037, 102, '坦桑尼亚', '+255', '坦桑尼亚', 37, 1, NOW(), 1, NOW()),
+(102038, 102, '哈萨克斯坦', '+7', '哈萨克斯坦', 38, 1, NOW(), 1, NOW());
diff --git a/main/manager-api/src/main/resources/db/changelog/202505201744.sql b/main/manager-api/src/main/resources/db/changelog/202505201744.sql
new file mode 100644
index 00000000..7b31b1cc
--- /dev/null
+++ b/main/manager-api/src/main/resources/db/changelog/202505201744.sql
@@ -0,0 +1,3 @@
+-- 更新ai_model_provider的fields字段,将type为dict的改为string
+update ai_model_provider set fields = replace(fields, '"type": "dict"', '"type": "string"') where id not in ('SYSTEM_LLM_fastgpt', 'SYSTEM_TTS_custom');
+update ai_model_provider set fields = replace(fields, '"type":"dict"', '"type": "string"') where id not in ('SYSTEM_LLM_fastgpt', 'SYSTEM_TTS_custom');
\ No newline at end of file
diff --git a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml
index 2d5147c6..9d3808da 100755
--- a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml
+++ b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml
@@ -115,12 +115,12 @@ databaseChangeLog:
encoding: utf8
path: classpath:db/changelog/202505091409.sql
- changeSet:
- id: 202505091554
+ id: 202505091555
author: whosmyqueen
changes:
- sqlFile:
encoding: utf8
- path: classpath:db/changelog/202505091554.sql
+ path: classpath:db/changelog/202505091555.sql
- changeSet:
id: 202505111914
author: hrz
@@ -128,3 +128,38 @@ databaseChangeLog:
- sqlFile:
encoding: utf8
path: classpath:db/changelog/202505111914.sql
+ - changeSet:
+ id: 202505122348
+ author: ljwwd2
+ changes:
+ - sqlFile:
+ encoding: utf8
+ path: classpath:db/changelog/202505122348.sql
+ - changeSet:
+ id: 202505142037
+ author: hrz
+ changes:
+ - sqlFile:
+ encoding: utf8
+ path: classpath:db/changelog/202505142037.sql
+ - changeSet:
+ id: 202505182234
+ author: amen
+ changes:
+ - sqlFile:
+ encoding: utf8
+ path: classpath:db/changelog/202505182234.sql
+ - changeSet:
+ id: 202505201744
+ author: hrz
+ changes:
+ - sqlFile:
+ encoding: utf8
+ path: classpath:db/changelog/202505201744.sql
+ - changeSet:
+ id: 202505151451
+ author: hsoftxl
+ changes:
+ - sqlFile:
+ encoding: utf8
+ path: classpath:db/changelog/202505151451.sql
\ No newline at end of file
diff --git a/main/manager-api/src/main/resources/i18n/messages.properties b/main/manager-api/src/main/resources/i18n/messages.properties
index 5126feb2..8d04c5a0 100644
--- a/main/manager-api/src/main/resources/i18n/messages.properties
+++ b/main/manager-api/src/main/resources/i18n/messages.properties
@@ -9,6 +9,7 @@
10005=\u8D26\u53F7\u5DF2\u88AB\u505C\u7528
10006=\u552F\u4E00\u6807\u8BC6\u4E0D\u80FD\u4E3A\u7A7A
10007=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
+10008=\u624B\u673A\u53F7\u7801\u4E0D\u53EF\u4EE5\u4E3A\u7A7A
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
diff --git a/main/manager-api/src/main/resources/lua/emptyAll.lua b/main/manager-api/src/main/resources/lua/emptyAll.lua
new file mode 100644
index 00000000..1d984cb7
--- /dev/null
+++ b/main/manager-api/src/main/resources/lua/emptyAll.lua
@@ -0,0 +1 @@
+redis.call('FLUSHALL')
\ No newline at end of file
diff --git a/main/manager-api/src/main/resources/lua/getKeyOrCreate.lua b/main/manager-api/src/main/resources/lua/getKeyOrCreate.lua
new file mode 100644
index 00000000..bc375b12
--- /dev/null
+++ b/main/manager-api/src/main/resources/lua/getKeyOrCreate.lua
@@ -0,0 +1,11 @@
+local value = redis.call('GET', KEYS[1])
+-- value 如果为空着设置值
+if not value then
+ local result = redis.call('SET', KEYS[1], ARGV[1])
+ -- 检查 ARGV[2] 是否存在且大于 0
+ local expireTime = tonumber(ARGV[2])
+ if expireTime and expireTime > 0 then
+ redis.call('EXPIRE', KEYS[1], expireTime)
+ end
+end
+return value
\ No newline at end of file
diff --git a/main/manager-api/src/test/java/xiaozhi/modules/sys/loginControllerTest.java b/main/manager-api/src/test/java/xiaozhi/modules/sys/loginControllerTest.java
new file mode 100644
index 00000000..5cc39967
--- /dev/null
+++ b/main/manager-api/src/test/java/xiaozhi/modules/sys/loginControllerTest.java
@@ -0,0 +1,58 @@
+package xiaozhi.modules.sys;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+
+import lombok.extern.slf4j.Slf4j;
+import xiaozhi.modules.security.controller.LoginController;
+import xiaozhi.modules.security.dto.LoginDTO;
+import xiaozhi.modules.security.dto.SmsVerificationDTO;
+import xiaozhi.modules.sys.dto.RetrievePasswordDTO;
+
+@Slf4j
+@SpringBootTest
+@ActiveProfiles("dev")
+class loginControllerTest {
+
+ @Autowired
+ LoginController loginController;
+
+ @Test
+ public void testRegister() {
+ LoginDTO loginDTO = new LoginDTO();
+ loginDTO.setUsername("手机号码");
+ loginDTO.setPassword("密码");
+ loginDTO.setCaptcha("123456");
+ loginController.register(loginDTO);
+ }
+
+ @Test
+ public void testSmsVerification() {
+ try {
+ SmsVerificationDTO smsVerificationDTO = new SmsVerificationDTO();
+ smsVerificationDTO.setPhone("手机号码");
+ smsVerificationDTO.setCaptchaId("123456");
+ smsVerificationDTO.setCaptcha("123456");
+ loginController.smsVerification(smsVerificationDTO);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testRetrievePassword() {
+ try {
+ RetrievePasswordDTO retrievePasswordDTO = new RetrievePasswordDTO();
+ retrievePasswordDTO.setCode("123456");
+ retrievePasswordDTO.setPhone("手机号码");
+ retrievePasswordDTO.setPassword("密码");
+ loginController.retrievePassword(retrievePasswordDTO);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/main/manager-web/src/apis/httpRequest.js b/main/manager-web/src/apis/httpRequest.js
index 43cdf92d..245bf6cc 100755
--- a/main/manager-web/src/apis/httpRequest.js
+++ b/main/manager-web/src/apis/httpRequest.js
@@ -20,6 +20,7 @@ function sendRequest() {
return {
_sucCallback: null,
_failCallback: null,
+ _networkFailCallback: null,
_method: 'GET',
_data: {},
_header: { 'content-type': 'application/json; charset=utf-8' },
@@ -36,7 +37,7 @@ function sendRequest() {
headers: this._header,
responseType: this._responseType
}).then((res) => {
- const error = httpHandlerError(res, this._failCallback);
+ const error = httpHandlerError(res, this._failCallback, this._networkFailCallback);
if (error) {
return
}
@@ -47,7 +48,7 @@ function sendRequest() {
}).catch((res) => {
// 打印失败响应
console.log('catch', res)
- httpHandlerError(res, this._failCallback)
+ httpHandlerError(res, this._failCallback, this._networkFailCallback)
})
return this
},
@@ -59,6 +60,10 @@ function sendRequest() {
this._failCallback = callback
return this
},
+ 'networkFail'(callback) {
+ this._networkFailCallback = callback
+ return this
+ },
'url'(url) {
if (url) {
url = url.replaceAll('$', '/')
@@ -95,11 +100,11 @@ function sendRequest() {
/**
* Info 请求完成后返回信息
- * callBack 回调函数
- * errTip 自定义错误信息
+ * failCallback 回调函数
+ * networkFailCallback 回调函数
*/
// 在错误处理函数中添加日志
-function httpHandlerError(info, callBack) {
+function httpHandlerError(info, failCallback, networkFailCallback) {
/** 请求成功,退出该函数 可以根据项目需求来判断是否请求成功。这里判断的是status为200的时候是成功 */
let networkError = false
@@ -111,12 +116,16 @@ function httpHandlerError(info, callBack) {
goToPage(Constant.PAGE.LOGIN, true);
return true
} else {
- showDanger(info.data.msg)
+ if (failCallback) {
+ failCallback(info)
+ } else {
+ showDanger(info.data.msg)
+ }
return true
}
}
- if (callBack) {
- callBack(info)
+ if (networkFailCallback) {
+ networkFailCallback(info)
} else {
showDanger(`网络请求出现了错误【${info.status}】`)
}
diff --git a/main/manager-web/src/apis/module/admin.js b/main/manager-web/src/apis/module/admin.js
index fecc5877..27c1bc3e 100644
--- a/main/manager-web/src/apis/module/admin.js
+++ b/main/manager-web/src/apis/module/admin.js
@@ -18,7 +18,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('请求失败:', err)
RequestService.reAjaxFun(() => {
this.getUserList(callback)
@@ -34,7 +34,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('删除失败:', err)
RequestService.reAjaxFun(() => {
this.deleteUser(id, callback)
@@ -50,7 +50,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('重置密码失败:', err)
RequestService.reAjaxFun(() => {
this.resetUserPassword(id, callback)
@@ -72,7 +72,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取参数列表失败:', err)
RequestService.reAjaxFun(() => {
this.getParamsList(params, callback)
@@ -89,7 +89,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('添加参数失败:', err)
RequestService.reAjaxFun(() => {
this.addParam(data, callback)
@@ -106,7 +106,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('更新参数失败:', err)
RequestService.reAjaxFun(() => {
this.updateParam(data, callback)
@@ -123,12 +123,44 @@ export default {
RequestService.clearRequestTime()
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('删除参数失败:', err)
RequestService.reAjaxFun(() => {
this.deleteParam(ids, callback)
})
}).send()
},
+ // 获取ws服务端列表
+ getWsServerList(params, callback) {
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/admin/server/server-list`)
+ .method('GET')
+ .success((res) => {
+ RequestService.clearRequestTime()
+ callback(res)
+ })
+ .networkFail((err) => {
+ console.error('获取ws服务端列表失败:', err)
+ RequestService.reAjaxFun(() => {
+ this.getWsServerList(params, callback)
+ })
+ }).send();
+ },
+ // 发送ws服务器动作指令
+ sendWsServerAction(data, callback) {
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/admin/server/emit-action`)
+ .method('POST')
+ .data(data)
+ .success((res) => {
+ RequestService.clearRequestTime()
+ callback(res)
+ })
+ .networkFail((err) => {
+ RequestService.reAjaxFun(() => {
+ this.sendWsServerAction(data, callback)
+ })
+ }).send();
+ }
}
diff --git a/main/manager-web/src/apis/module/agent.js b/main/manager-web/src/apis/module/agent.js
index 756e1bef..7f33d320 100644
--- a/main/manager-web/src/apis/module/agent.js
+++ b/main/manager-web/src/apis/module/agent.js
@@ -12,7 +12,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.getAgentList(callback);
});
@@ -28,7 +28,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.addAgent(agentName, callback);
});
@@ -43,7 +43,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.deleteAgent(agentId, callback);
});
@@ -58,7 +58,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取配置失败:', err);
RequestService.reAjaxFun(() => {
this.getDeviceConfig(agentId, callback);
@@ -75,7 +75,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.updateAgentConfig(agentId, configData, callback);
});
@@ -90,7 +90,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取模板失败:', err);
RequestService.reAjaxFun(() => {
this.getAgentTemplate(callback);
@@ -107,7 +107,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.getAgentSessions(agentId, params, callback);
});
@@ -122,7 +122,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.getAgentChatHistory(agentId, sessionId, callback);
});
@@ -137,7 +137,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.getAudioId(audioId, callback);
});
diff --git a/main/manager-web/src/apis/module/device.js b/main/manager-web/src/apis/module/device.js
index 53738bc6..2f20425d 100644
--- a/main/manager-web/src/apis/module/device.js
+++ b/main/manager-web/src/apis/module/device.js
@@ -11,7 +11,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取设备列表失败:', err);
RequestService.reAjaxFun(() => {
this.getAgentBindDevices(agentId, callback);
@@ -28,7 +28,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('解绑设备失败:', err);
RequestService.reAjaxFun(() => {
this.unbindDevice(device_id, callback);
@@ -44,7 +44,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('绑定设备失败:', err);
RequestService.reAjaxFun(() => {
this.bindDevice(agentId, deviceCode, callback);
@@ -59,7 +59,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('更新OTA状态失败:', err)
this.$message.error(err.msg || '更新OTA状态失败')
RequestService.reAjaxFun(() => {
diff --git a/main/manager-web/src/apis/module/dict.js b/main/manager-web/src/apis/module/dict.js
index caf78279..8919c46b 100644
--- a/main/manager-web/src/apis/module/dict.js
+++ b/main/manager-web/src/apis/module/dict.js
@@ -18,7 +18,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取字典类型列表失败:', err)
this.$message.error(err.msg || '获取字典类型列表失败')
RequestService.reAjaxFun(() => {
@@ -36,7 +36,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取字典类型详情失败:', err)
this.$message.error(err.msg || '获取字典类型详情失败')
RequestService.reAjaxFun(() => {
@@ -55,7 +55,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('新增字典类型失败:', err)
this.$message.error(err.msg || '新增字典类型失败')
RequestService.reAjaxFun(() => {
@@ -74,7 +74,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('更新字典类型失败:', err)
this.$message.error(err.msg || '更新字典类型失败')
RequestService.reAjaxFun(() => {
@@ -93,7 +93,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('删除字典类型失败:', err)
this.$message.error(err.msg || '删除字典类型失败')
RequestService.reAjaxFun(() => {
@@ -119,7 +119,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取字典数据列表失败:', err)
this.$message.error(err.msg || '获取字典数据列表失败')
RequestService.reAjaxFun(() => {
@@ -137,7 +137,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取字典数据详情失败:', err)
this.$message.error(err.msg || '获取字典数据详情失败')
RequestService.reAjaxFun(() => {
@@ -156,7 +156,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('新增字典数据失败:', err)
this.$message.error(err.msg || '新增字典数据失败')
RequestService.reAjaxFun(() => {
@@ -175,7 +175,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('更新字典数据失败:', err)
this.$message.error(err.msg || '更新字典数据失败')
RequestService.reAjaxFun(() => {
@@ -194,7 +194,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('删除字典数据失败:', err)
this.$message.error(err.msg || '删除字典数据失败')
RequestService.reAjaxFun(() => {
@@ -217,7 +217,7 @@ export default {
reject(new Error(res.data?.msg || '获取字典数据列表失败'))
}
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取字典数据列表失败:', err)
reject(err)
}).send()
diff --git a/main/manager-web/src/apis/module/model.js b/main/manager-web/src/apis/module/model.js
index ec0ea32f..badf4174 100644
--- a/main/manager-web/src/apis/module/model.js
+++ b/main/manager-web/src/apis/module/model.js
@@ -18,7 +18,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取模型列表失败:', err)
RequestService.reAjaxFun(() => {
this.getModelList(params, callback)
@@ -34,7 +34,7 @@ export default {
RequestService.clearRequestTime()
callback(res.data?.data || [])
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取供应器列表失败:', err)
this.$message.error('获取供应器列表失败')
RequestService.reAjaxFun(() => {
@@ -65,7 +65,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('新增模型失败:', err)
this.$message.error(err.msg || '新增模型失败')
RequestService.reAjaxFun(() => {
@@ -82,7 +82,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('删除模型失败:', err)
this.$message.error(err.msg || '删除模型失败')
RequestService.reAjaxFun(() => {
@@ -100,7 +100,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.getModelNames(modelType, modelName, callback);
});
@@ -118,7 +118,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail(() => {
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.getModelVoices(modelId, voiceName, callback);
});
@@ -133,7 +133,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取模型配置失败:', err)
this.$message.error(err.msg || '获取模型配置失败')
RequestService.reAjaxFun(() => {
@@ -150,7 +150,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('更新模型状态失败:', err)
this.$message.error(err.msg || '更新模型状态失败')
RequestService.reAjaxFun(() => {
@@ -166,20 +166,20 @@ export default {
configJson: formData.configJson
};
RequestService.sendRequest()
- .url(`${getServiceUrl()}/models/${modelType}/${provideCode}/${id}`)
- .method('PUT')
- .data(payload)
- .success((res) => {
- RequestService.clearRequestTime();
- callback(res);
- })
- .fail((err) => {
- console.error('更新模型失败:', err);
- this.$message.error(err.msg || '更新模型失败');
- RequestService.reAjaxFun(() => {
- this.updateModel(params, callback);
- });
- }).send();
+ .url(`${getServiceUrl()}/models/${modelType}/${provideCode}/${id}`)
+ .method('PUT')
+ .data(payload)
+ .success((res) => {
+ RequestService.clearRequestTime();
+ callback(res);
+ })
+ .networkFail((err) => {
+ console.error('更新模型失败:', err);
+ this.$message.error(err.msg || '更新模型失败');
+ RequestService.reAjaxFun(() => {
+ this.updateModel(params, callback);
+ });
+ }).send();
},
// 设置默认模型
setDefaultModel(id, callback) {
@@ -190,12 +190,119 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('设置默认模型失败:', err)
this.$message.error(err.msg || '设置默认模型失败')
RequestService.reAjaxFun(() => {
this.setDefaultModel(id, callback)
})
}).send()
- }
+ },
+
+ /**
+ * 获取模型配置列表(支持查询参数)
+ * @param {Object} params - 查询参数对象,例如 { name: 'test', modelType: 1 }
+ * @param {Function} callback - 回调函数
+ */
+ getModelProvidersPage(params, callback) {
+ // 构建查询参数
+ const queryParams = new URLSearchParams();
+ if (params.name) queryParams.append('name', params.name);
+ if (params.modelType !== undefined) queryParams.append('modelType', params.modelType);
+ if (params.page !== undefined) queryParams.append('page', params.page);
+ if (params.limit !== undefined) queryParams.append('limit', params.limit);
+
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/models/provider?${queryParams.toString()}`)
+ .method('GET')
+ .success((res) => {
+ RequestService.clearRequestTime();
+ callback(res);
+ })
+ .networkFail((err) => {
+ this.$message.error(err.msg || '获取供应器列表失败');
+ RequestService.reAjaxFun(() => {
+ this.getModelProviders(params, callback);
+ });
+ }).send();
+ },
+
+ /**
+ * 新增模型供应器配置
+ * @param {Object} params - 请求参数对象,例如 { modelType: '1', providerCode: '1', name: '1', fields: '1', sort: 1 }
+ * @param {Function} callback - 成功回调函数
+ */
+ addModelProvider(params, callback) {
+ const postData = {
+ modelType: params.modelType || '',
+ providerCode: params.providerCode || '',
+ name: params.name || '',
+ fields: JSON.stringify(params.fields || []),
+ sort: params.sort || 0
+ };
+
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/models/provider`)
+ .method('POST')
+ .data(postData)
+ .success((res) => {
+ RequestService.clearRequestTime();
+ callback(res);
+ })
+ .networkFail((err) => {
+ console.error('新增模型供应器失败:', err)
+ this.$message.error(err.msg || '新增模型供应器失败')
+ RequestService.reAjaxFun(() => {
+ this.addModelProvider(params, callback);
+ });
+ }).send();
+ },
+
+ /**
+ * 更新模型供应器配置
+ * @param {Object} params - 请求参数对象,例如 { id: '111', modelType: '1', providerCode: '1', name: '1', fields: '1', sort: 1 }
+ * @param {Function} callback - 成功回调函数
+ */
+ updateModelProvider(params, callback) {
+ const putData = {
+ id: params.id || '',
+ modelType: params.modelType || '',
+ providerCode: params.providerCode || '',
+ name: params.name || '',
+ fields: JSON.stringify(params.fields || []),
+ sort: params.sort || 0
+ };
+
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/models/provider`)
+ .method('PUT')
+ .data(putData)
+ .success((res) => {
+ RequestService.clearRequestTime();
+ callback(res);
+ })
+ .networkFail((err) => {
+ this.$message.error(err.msg || '更新模型供应器失败')
+ RequestService.reAjaxFun(() => {
+ this.updateModelProvider(params, callback);
+ });
+ }).send();
+ },
+ // 删除
+ deleteModelProviderByIds(ids, callback) {
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/models/provider/delete`)
+ .method('POST')
+ .data(ids)
+ .success((res) => {
+ RequestService.clearRequestTime()
+ callback(res);
+ })
+ .networkFail((err) => {
+ this.$message.error(err.msg || '删除模型供应器失败')
+ RequestService.reAjaxFun(() => {
+ this.deleteModelProviderByIds(ids, callback)
+ })
+ }).send()
+ },
}
diff --git a/main/manager-web/src/apis/module/ota.js b/main/manager-web/src/apis/module/ota.js
index 438aa3d8..4db86ad7 100644
--- a/main/manager-web/src/apis/module/ota.js
+++ b/main/manager-web/src/apis/module/ota.js
@@ -12,7 +12,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取OTA固件列表失败:', err);
RequestService.reAjaxFun(() => {
this.getOtaList(params, callback);
@@ -28,7 +28,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取OTA固件信息失败:', err);
RequestService.reAjaxFun(() => {
this.getOtaInfo(id, callback);
@@ -45,7 +45,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('保存OTA固件信息失败:', err);
RequestService.reAjaxFun(() => {
this.saveOta(entity, callback);
@@ -62,7 +62,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('更新OTA固件信息失败:', err);
RequestService.reAjaxFun(() => {
this.updateOta(id, entity, callback);
@@ -78,7 +78,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('删除OTA固件失败:', err);
RequestService.reAjaxFun(() => {
this.deleteOta(id, callback);
@@ -97,7 +97,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('上传固件文件失败:', err);
RequestService.reAjaxFun(() => {
this.uploadFirmware(file, callback);
@@ -113,7 +113,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取下载链接失败:', err);
RequestService.reAjaxFun(() => {
this.getDownloadUrl(id, callback);
diff --git a/main/manager-web/src/apis/module/timbre.js b/main/manager-web/src/apis/module/timbre.js
index 91920522..7aa6a711 100644
--- a/main/manager-web/src/apis/module/timbre.js
+++ b/main/manager-web/src/apis/module/timbre.js
@@ -1,4 +1,4 @@
-import {getServiceUrl} from '../api';
+import { getServiceUrl } from '../api';
import RequestService from '../httpRequest';
export default {
@@ -18,7 +18,7 @@ export default {
RequestService.clearRequestTime();
callback(res.data || []);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取音色列表失败:', err);
RequestService.reAjaxFun(() => {
this.getVoiceList(params, callback);
@@ -42,7 +42,7 @@ export default {
.success((res) => {
callback(res.data);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('保存音色失败:', err);
RequestService.reAjaxFun(() => {
this.saveVoice(params, callback);
@@ -59,7 +59,7 @@ export default {
RequestService.clearRequestTime()
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('删除音色失败:', err);
RequestService.reAjaxFun(() => {
this.deleteVoice(ids, callback);
@@ -82,7 +82,7 @@ export default {
.success((res) => {
callback(res.data);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('修改音色失败:', err);
RequestService.reAjaxFun(() => {
this.updateVoice(params, callback);
diff --git a/main/manager-web/src/apis/module/user.js b/main/manager-web/src/apis/module/user.js
index 84d5b7f9..6c16c3e6 100755
--- a/main/manager-web/src/apis/module/user.js
+++ b/main/manager-web/src/apis/module/user.js
@@ -4,7 +4,7 @@ import RequestService from '../httpRequest'
export default {
// 登录
- login(loginForm, callback) {
+ login(loginForm, callback, failCallback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/user/login`)
.method('POST')
@@ -13,7 +13,11 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail(() => {
+ .fail((err) => {
+ RequestService.clearRequestTime()
+ failCallback(err)
+ })
+ .networkFail(() => {
RequestService.reAjaxFun(() => {
this.login(loginForm, callback)
})
@@ -34,12 +38,32 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => { // 添加错误参数
+ .networkFail((err) => { // 添加错误参数
}).send()
},
+ // 发送短信验证码
+ sendSmsVerification(data, callback, failCallback) {
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/user/smsVerification`)
+ .method('POST')
+ .data(data)
+ .success((res) => {
+ RequestService.clearRequestTime()
+ callback(res)
+ })
+ .fail((err) => {
+ RequestService.clearRequestTime()
+ failCallback(err)
+ })
+ .networkFail(() => {
+ RequestService.reAjaxFun(() => {
+ this.sendSmsVerification(data, callback, failCallback)
+ })
+ }).send()
+ },
// 注册账号
- register(registerForm, callback) {
+ register(registerForm, callback, failCallback) {
RequestService.sendRequest()
.url(`${getServiceUrl()}/user/register`)
.method('POST')
@@ -48,7 +72,14 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail(() => {
+ .fail((err) => {
+ RequestService.clearRequestTime()
+ failCallback(err)
+ })
+ .networkFail(() => {
+ RequestService.reAjaxFun(() => {
+ this.register(registerForm, callback, failCallback)
+ })
}).send()
},
// 保存设备配置
@@ -61,7 +92,7 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('保存配置失败:', err);
RequestService.reAjaxFun(() => {
this.saveDeviceConfig(device_id, configData, callback);
@@ -77,7 +108,7 @@ export default {
RequestService.clearRequestTime()
callback(res)
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('接口请求失败:', err)
RequestService.reAjaxFun(() => {
this.getUserInfo(callback)
@@ -97,7 +128,7 @@ export default {
RequestService.clearRequestTime();
successCallback(res);
})
- .fail((error) => {
+ .networkFail((error) => {
RequestService.reAjaxFun(() => {
this.changePassword(oldPassword, newPassword, successCallback, errorCallback);
});
@@ -115,7 +146,7 @@ export default {
RequestService.clearRequestTime()
successCallback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('修改用户状态失败:', err)
RequestService.reAjaxFun(() => {
this.changeUserStatus(status, userIds)
@@ -131,11 +162,35 @@ export default {
RequestService.clearRequestTime();
callback(res);
})
- .fail((err) => {
+ .networkFail((err) => {
console.error('获取公共配置失败:', err);
RequestService.reAjaxFun(() => {
this.getPubConfig(callback);
});
}).send();
},
+ // 找回用户密码
+ retrievePassword(passwordData, callback, failCallback) {
+ RequestService.sendRequest()
+ .url(`${getServiceUrl()}/user/retrieve-password`)
+ .method('PUT')
+ .data({
+ phone: passwordData.phone,
+ code: passwordData.code,
+ password: passwordData.password
+ })
+ .success((res) => {
+ RequestService.clearRequestTime();
+ callback(res);
+ })
+ .fail((err) => {
+ RequestService.clearRequestTime();
+ failCallback(err);
+ })
+ .networkFail(() => {
+ RequestService.reAjaxFun(() => {
+ this.retrievePassword(passwordData, callback, failCallback);
+ });
+ }).send()
+ }
}
diff --git a/main/manager-web/src/components/DeviceItem.vue b/main/manager-web/src/components/DeviceItem.vue
index 0ecbcefa..eeab90a1 100644
--- a/main/manager-web/src/components/DeviceItem.vue
+++ b/main/manager-web/src/components/DeviceItem.vue
@@ -28,7 +28,7 @@
-
+
聊天记录
聊天记录
diff --git a/main/manager-web/src/components/FirmwareDialog.vue b/main/manager-web/src/components/FirmwareDialog.vue
index 4721fdac..56e2f327 100644
--- a/main/manager-web/src/components/FirmwareDialog.vue
+++ b/main/manager-web/src/components/FirmwareDialog.vue
@@ -198,13 +198,13 @@ export default {
if (!this.form.id) { // 只在新增时重置
this.form.firmwarePath = ''
this.form.size = 0
- // 重置上传组件
- this.$nextTick(() => {
- if (this.$refs.upload) {
- this.$refs.upload.clearFiles()
- }
- })
}
+ // 无论是否编辑模式,都重置上传组件
+ this.$nextTick(() => {
+ if (this.$refs.upload) {
+ this.$refs.upload.clearFiles()
+ }
+ })
}
}
}
diff --git a/main/manager-web/src/components/HeaderBar.vue b/main/manager-web/src/components/HeaderBar.vue
index 3d6a62f0..d0a36acb 100644
--- a/main/manager-web/src/components/HeaderBar.vue
+++ b/main/manager-web/src/components/HeaderBar.vue
@@ -35,12 +35,13 @@
OTA管理
+ :class="{ 'active-tab': $route.path === '/dict-management' || $route.path === '/params-management' || $route.path === '/provider-management' || $route.path === '/server-side-management' }"
+ @visible-change="handleParamDropdownVisibleChange">
+ :style="{ filter: $route.path === '/dict-management' || $route.path === '/params-management' || $route.path === '/provider-management' || $route.path === '/server-side-management' ? 'brightness(0) invert(1)' : 'None' }" />
参数字典
-
+
@@ -49,22 +50,29 @@
字典管理
+
+ 字段管理
+
+
+ 服务端管理
+