mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-27 01:23:55 +08:00
@@ -68,7 +68,11 @@ MQTT_SIGNATURE_KEY=test # MQTT签名密钥
|
|||||||
```
|
```
|
||||||
请注意`PUBLIC_IP`配置,确保其与实际公网IP一致,如果有域名就填域名。
|
请注意`PUBLIC_IP`配置,确保其与实际公网IP一致,如果有域名就填域名。
|
||||||
|
|
||||||
`MQTT_SIGNATURE_KEY` 是用于MQTT连接认证的密钥,最好设置成复杂一点的,这个密钥稍后还会用到。
|
`MQTT_SIGNATURE_KEY` 是用于MQTT连接认证的密钥,最好设置成复杂一点的,最好是设置成8个字符以上且同时包含大小写字母,这个密钥稍后还会用到。
|
||||||
|
|
||||||
|
- 注意不要用简单的密码,比如`123456`、`test`等。
|
||||||
|
- 注意不要用简单的密码,比如`123456`、`test`等。
|
||||||
|
- 注意不要用简单的密码,比如`123456`、`test`等。
|
||||||
|
|
||||||
6. 启动MQTT网关
|
6. 启动MQTT网关
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -126,6 +126,11 @@ public interface Constant {
|
|||||||
*/
|
*/
|
||||||
String SERVER_VOICE_PRINT = "server.voice_print";
|
String SERVER_VOICE_PRINT = "server.voice_print";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mqtt密钥
|
||||||
|
*/
|
||||||
|
String SERVER_MQTT_SECRET = "server.mqtt_signature_key";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 无记忆
|
* 无记忆
|
||||||
*/
|
*/
|
||||||
|
|||||||
+22
-1
@@ -107,9 +107,12 @@ public class SysParamsController {
|
|||||||
// 验证MCP地址
|
// 验证MCP地址
|
||||||
validateMcpUrl(dto.getParamCode(), dto.getParamValue());
|
validateMcpUrl(dto.getParamCode(), dto.getParamValue());
|
||||||
|
|
||||||
//
|
// 验证声纹地址
|
||||||
validateVoicePrint(dto.getParamCode(), dto.getParamValue());
|
validateVoicePrint(dto.getParamCode(), dto.getParamValue());
|
||||||
|
|
||||||
|
// 校验mqtt密钥长度
|
||||||
|
validateMqttSecretLength(dto.getParamCode(), dto.getParamValue());
|
||||||
|
|
||||||
sysParamsService.update(dto);
|
sysParamsService.update(dto);
|
||||||
configService.getConfig(false);
|
configService.getConfig(false);
|
||||||
return new Result<Void>();
|
return new Result<Void>();
|
||||||
@@ -231,6 +234,7 @@ public class SysParamsController {
|
|||||||
throw new RenException("MCP接口验证失败:" + e.getMessage());
|
throw new RenException("MCP接口验证失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证声纹接口地址是否正常
|
// 验证声纹接口地址是否正常
|
||||||
private void validateVoicePrint(String paramCode, String url) {
|
private void validateVoicePrint(String paramCode, String url) {
|
||||||
if (!paramCode.equals(Constant.SERVER_VOICE_PRINT)) {
|
if (!paramCode.equals(Constant.SERVER_VOICE_PRINT)) {
|
||||||
@@ -264,4 +268,21 @@ public class SysParamsController {
|
|||||||
throw new RenException("声纹接口验证失败:" + e.getMessage());
|
throw new RenException("声纹接口验证失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 校验mqtt密钥长度和复杂度
|
||||||
|
private void validateMqttSecretLength(String paramCode, String secret) {
|
||||||
|
if (!paramCode.equals(Constant.SERVER_MQTT_SECRET)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(secret) || secret.equals("null")) {
|
||||||
|
throw new RenException("mqtt密钥不能为空");
|
||||||
|
}
|
||||||
|
if (secret.length() < 8) {
|
||||||
|
throw new RenException("您的mqtt密钥长度不安全,字符数需要至少8个字符且必须同时包含大小写字母");
|
||||||
|
}
|
||||||
|
// 检查是否同时包含大小写字母
|
||||||
|
if (!secret.matches(".*[a-z].*") || !secret.matches(".*[A-Z].*")) {
|
||||||
|
throw new RenException("您的mqtt密钥长度不安全,mqtt密钥必须同时包含大小写字母");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export default {
|
|||||||
}).send()
|
}).send()
|
||||||
},
|
},
|
||||||
// 修改
|
// 修改
|
||||||
updateParam(data, callback) {
|
updateParam(data, callback, failCallback) {
|
||||||
RequestService.sendRequest()
|
RequestService.sendRequest()
|
||||||
.url(`${getServiceUrl()}/admin/params`)
|
.url(`${getServiceUrl()}/admin/params`)
|
||||||
.method('PUT')
|
.method('PUT')
|
||||||
@@ -106,6 +106,10 @@ export default {
|
|||||||
RequestService.clearRequestTime()
|
RequestService.clearRequestTime()
|
||||||
callback(res)
|
callback(res)
|
||||||
})
|
})
|
||||||
|
.fail((err) => {
|
||||||
|
RequestService.clearRequestTime()
|
||||||
|
failCallback(err)
|
||||||
|
})
|
||||||
.networkFail((err) => {
|
.networkFail((err) => {
|
||||||
console.error('更新参数失败:', err)
|
console.error('更新参数失败:', err)
|
||||||
RequestService.reAjaxFun(() => {
|
RequestService.reAjaxFun(() => {
|
||||||
|
|||||||
@@ -1,51 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog :title="title"
|
<el-dialog :title="title" :visible.sync="visible" width="520px" class="param-dialog-wrapper" :append-to-body="true"
|
||||||
:visible.sync="visible"
|
:close-on-click-modal="false" :key="dialogKey" custom-class="custom-param-dialog" :show-close="false">
|
||||||
width="520px"
|
|
||||||
class="param-dialog-wrapper"
|
|
||||||
:append-to-body="true"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:key="dialogKey"
|
|
||||||
custom-class="custom-param-dialog"
|
|
||||||
:show-close="false"
|
|
||||||
>
|
|
||||||
<div class="dialog-container">
|
<div class="dialog-container">
|
||||||
<div class="dialog-header">
|
<div class="dialog-header">
|
||||||
<h2 class="dialog-title">{{ title }}</h2>
|
<h2 class="dialog-title">{{ title }}</h2>
|
||||||
<button class="custom-close-btn" @click="cancel">
|
<button class="custom-close-btn" @click="cancel">
|
||||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
<path d="M13 1L1 13M1 1L13 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-form :model="form" :rules="rules" ref="form" label-width="auto" label-position="left" class="param-form">
|
<el-form :model="form" :rules="rules" ref="form" label-width="auto" label-position="left" class="param-form">
|
||||||
<el-form-item :label="$t('paramDialog.paramCode')" prop="paramCode" class="form-item">
|
<el-form-item :label="$t('paramDialog.paramCode')" prop="paramCode" class="form-item">
|
||||||
<el-input v-model="form.paramCode" :placeholder="$t('paramDialog.paramCodePlaceholder')" class="custom-input"></el-input>
|
<el-input v-model="form.paramCode" :placeholder="$t('paramDialog.paramCodePlaceholder')"
|
||||||
|
class="custom-input"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('paramDialog.paramValue')" prop="paramValue" class="form-item">
|
<el-form-item :label="$t('paramDialog.paramValue')" prop="paramValue" class="form-item">
|
||||||
<el-input v-model="form.paramValue" :placeholder="$t('paramDialog.paramValuePlaceholder')" class="custom-input"></el-input>
|
<el-input v-model="form.paramValue" :placeholder="$t('paramDialog.paramValuePlaceholder')"
|
||||||
|
class="custom-input"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('paramDialog.valueType')" prop="valueType" class="form-item">
|
<el-form-item :label="$t('paramDialog.valueType')" prop="valueType" class="form-item">
|
||||||
<el-select v-model="form.valueType" :placeholder="$t('paramDialog.valueTypePlaceholder')" class="custom-select">
|
<el-select v-model="form.valueType" :placeholder="$t('paramDialog.valueTypePlaceholder')"
|
||||||
<el-option v-for="item in valueTypeOptions" :key="item.value" :label="$t(`paramDialog.${item.value}Type`)" :value="item.value"/>
|
class="custom-select">
|
||||||
|
<el-option v-for="item in valueTypeOptions" :key="item.value" :label="$t(`paramDialog.${item.value}Type`)"
|
||||||
|
:value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('paramDialog.remark')" prop="remark" class="form-item remark-item">
|
<el-form-item :label="$t('paramDialog.remark')" prop="remark" class="form-item remark-item">
|
||||||
<el-input type="textarea" v-model="form.remark" :placeholder="$t('paramDialog.remarkPlaceholder')" :rows="3" class="custom-textarea"></el-input>
|
<el-input type="textarea" v-model="form.remark" :placeholder="$t('paramDialog.remarkPlaceholder')" :rows="3"
|
||||||
|
class="custom-textarea"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button
|
<el-button type="primary" @click="submit" class="save-btn" :loading="saving" :disabled="saving">
|
||||||
type="primary"
|
|
||||||
@click="submit"
|
|
||||||
class="save-btn"
|
|
||||||
:loading="saving"
|
|
||||||
:disabled="saving">
|
|
||||||
{{ $t('paramDialog.save') }}
|
{{ $t('paramDialog.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button @click="cancel" class="cancel-btn">
|
<el-button @click="cancel" class="cancel-btn">
|
||||||
@@ -108,14 +100,17 @@ export default {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
this.saving = true; // 开始加载
|
this.saving = true; // 开始加载
|
||||||
this.$emit('submit', this.form);
|
this.$emit('submit', this.form);
|
||||||
|
|
||||||
// 在父组件处理完成后,通过watch visible的变化来重置saving状态
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
this.saving = false; // 取消时重置状态
|
this.saving = false; // 取消时重置状态
|
||||||
this.$emit('cancel');
|
this.$emit('cancel');
|
||||||
|
},
|
||||||
|
|
||||||
|
// 提供给父组件调用以重置saving状态
|
||||||
|
resetSaving() {
|
||||||
|
this.saving = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
@@ -93,8 +93,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 新增/编辑参数对话框 -->
|
<!-- 新增/编辑参数对话框 -->
|
||||||
<param-dialog :title="dialogTitle" :visible.sync="dialogVisible" :form="paramForm" @submit="handleSubmit"
|
<param-dialog ref="paramDialog" :title="dialogTitle" :visible.sync="dialogVisible" :form="paramForm"
|
||||||
@cancel="dialogVisible = false" />
|
@submit="handleSubmit" @cancel="dialogVisible = false" />
|
||||||
<el-footer>
|
<el-footer>
|
||||||
<version-footer />
|
<version-footer />
|
||||||
</el-footer>
|
</el-footer>
|
||||||
@@ -224,18 +224,20 @@ export default {
|
|||||||
if (form.id) {
|
if (form.id) {
|
||||||
// 更新参数
|
// 更新参数
|
||||||
Api.admin.updateParam(form, ({ data }) => {
|
Api.admin.updateParam(form, ({ data }) => {
|
||||||
if (data.code === 0) {
|
this.dialogVisible = false;
|
||||||
this.dialogVisible = false;
|
this.fetchParams();
|
||||||
this.fetchParams();
|
this.$message.success({
|
||||||
this.$message.success({
|
message: this.$t('paramManagement.updateSuccess'),
|
||||||
message: this.$t('paramManagement.updateSuccess'),
|
showClose: true
|
||||||
showClose: true
|
});
|
||||||
});
|
}, ({ data }) => {
|
||||||
} else {
|
this.$message.error({
|
||||||
this.$message.error({
|
message: data.msg || this.$t('paramManagement.updateFailed'),
|
||||||
message: data.msg || this.$t('paramManagement.updateFailed'),
|
showClose: true
|
||||||
showClose: true
|
});
|
||||||
});
|
// 调用ParamDialog的resetSaving方法重置保存状态
|
||||||
|
if (this.$refs.paramDialog && typeof this.$refs.paramDialog.resetSaving === 'function') {
|
||||||
|
this.$refs.paramDialog.resetSaving();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -253,6 +255,10 @@ export default {
|
|||||||
message: data.msg || this.$t('paramManagement.addFailed'),
|
message: data.msg || this.$t('paramManagement.addFailed'),
|
||||||
showClose: true
|
showClose: true
|
||||||
});
|
});
|
||||||
|
// 调用ParamDialog的resetSaving方法重置保存状态
|
||||||
|
if (this.$refs.paramDialog && typeof this.$refs.paramDialog.resetSaving === 'function') {
|
||||||
|
this.$refs.paramDialog.resetSaving();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user