|
|
@@ -0,0 +1,298 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <!-- 顶部说明 -->
|
|
|
+ <el-alert
|
|
|
+ title="欢迎语配置"
|
|
|
+ type="info"
|
|
|
+ :closable="false"
|
|
|
+ show-icon
|
|
|
+ class="form-tip"
|
|
|
+ >
|
|
|
+ <template #default>
|
|
|
+ 用于配置机器人检测到访客时的默认欢迎语、语音播报及重复播报冷却策略。
|
|
|
+ </template>
|
|
|
+ </el-alert>
|
|
|
+
|
|
|
+ <!-- 配置表单卡片 -->
|
|
|
+ <el-card v-loading="loading" class="welcome-config-card">
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="form"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="150px"
|
|
|
+ class="welcome-config-form"
|
|
|
+ >
|
|
|
+ <el-form-item label="欢迎语文本" prop="welcomeText">
|
|
|
+ <el-input
|
|
|
+ v-model="form.welcomeText"
|
|
|
+ type="textarea"
|
|
|
+ :rows="4"
|
|
|
+ maxlength="200"
|
|
|
+ show-word-limit
|
|
|
+ placeholder="请输入欢迎语文本"
|
|
|
+ />
|
|
|
+ <div class="form-tip">
|
|
|
+ 用于机器人检测到访客时展示或播报的欢迎语内容。
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="启用欢迎语" prop="status">
|
|
|
+ <el-switch
|
|
|
+ v-model="form.status"
|
|
|
+ active-value="1"
|
|
|
+ inactive-value="0"
|
|
|
+ />
|
|
|
+ <div v-if="form.status === '0'" class="form-warning">
|
|
|
+ 当前欢迎语功能已停用,机器人检测到访客时不会触发欢迎语。
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="语音播报" prop="voiceEnabled">
|
|
|
+ <el-switch
|
|
|
+ v-model="form.voiceEnabled"
|
|
|
+ active-value="1"
|
|
|
+ inactive-value="0"
|
|
|
+ />
|
|
|
+ <div class="form-tip">
|
|
|
+ 启用后,欢迎语触发时进行语音播报;关闭后仅用于屏幕展示。
|
|
|
+ </div>
|
|
|
+ <div v-if="form.voiceEnabled === '0'" class="form-warning">
|
|
|
+ 当前仅用于屏幕展示,不进行语音播报
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="语音播报冷却时间" prop="cooldownSeconds">
|
|
|
+ <el-input-number
|
|
|
+ v-model="form.cooldownSeconds"
|
|
|
+ :min="5"
|
|
|
+ :max="3600"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ style="width: 200px"
|
|
|
+ />
|
|
|
+ <span class="form-unit">秒</span>
|
|
|
+ <div class="form-tip">
|
|
|
+ 机器人语音播报欢迎语后,在该时间内不重复语音播报。冷却期内再次检测到访客时,可仅做屏幕展示。
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="备注" prop="remark">
|
|
|
+ <el-input
|
|
|
+ v-model="form.remark"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ maxlength="500"
|
|
|
+ show-word-limit
|
|
|
+ placeholder="请输入备注"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <!-- 按钮区 -->
|
|
|
+ <div class="action-bar">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ :loading="saveLoading"
|
|
|
+ @click="handleSave"
|
|
|
+ v-hasPermi="['base:welcomeConfig:edit']"
|
|
|
+ >
|
|
|
+ 保存配置
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="warning"
|
|
|
+ :loading="testLoading"
|
|
|
+ @click="handleTest"
|
|
|
+ v-hasPermi="['base:welcomeConfig:test']"
|
|
|
+ >
|
|
|
+ 测试播报
|
|
|
+ </el-button>
|
|
|
+ <el-button @click="handleReset">
|
|
|
+ 恢复默认
|
|
|
+ </el-button>
|
|
|
+ <el-button icon="Refresh" :loading="loading" @click="handleRefresh">
|
|
|
+ 刷新
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { getWelcomeConfig, saveWelcomeConfig, testWelcomeBroadcast } from '@/api/base/welcomeConfig'
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance()
|
|
|
+
|
|
|
+const loading = ref(false)
|
|
|
+const saveLoading = ref(false)
|
|
|
+const testLoading = ref(false)
|
|
|
+const formRef = ref(null)
|
|
|
+
|
|
|
+const defaultConfig = {
|
|
|
+ configKey: 'default',
|
|
|
+ welcomeText: '您好,欢迎光临!我是迎宾巡逻安防机器人,很高兴为您服务。',
|
|
|
+ status: '1',
|
|
|
+ voiceEnabled: '1',
|
|
|
+ cooldownSeconds: 30,
|
|
|
+ remark: ''
|
|
|
+}
|
|
|
+
|
|
|
+const form = ref({ ...defaultConfig })
|
|
|
+
|
|
|
+const rules = {
|
|
|
+ welcomeText: [
|
|
|
+ { required: true, message: '请输入欢迎语文本', trigger: 'blur' },
|
|
|
+ { max: 200, message: '欢迎语文本不能超过 200 字', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ status: [
|
|
|
+ { required: true, message: '请选择启用状态', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ voiceEnabled: [
|
|
|
+ { required: true, message: '请选择是否语音播报', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ cooldownSeconds: [
|
|
|
+ { required: true, message: '请输入语音播报冷却时间', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ remark: [
|
|
|
+ { max: 500, message: '备注不能超过 500 字', trigger: 'blur' }
|
|
|
+ ]
|
|
|
+}
|
|
|
+
|
|
|
+/** 加载配置 */
|
|
|
+function loadConfig() {
|
|
|
+ loading.value = true
|
|
|
+ getWelcomeConfig()
|
|
|
+ .then(response => {
|
|
|
+ const data = response.data || response
|
|
|
+ if (data && Object.keys(data).length > 0) {
|
|
|
+ form.value = {
|
|
|
+ configKey: data.configKey || 'default',
|
|
|
+ welcomeText: data.welcomeText || defaultConfig.welcomeText,
|
|
|
+ status: String(data.status ?? '1'),
|
|
|
+ voiceEnabled: String(data.voiceEnabled ?? '1'),
|
|
|
+ cooldownSeconds: Number(data.cooldownSeconds || 30),
|
|
|
+ remark: data.remark || ''
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ form.value = { ...defaultConfig }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ proxy.$modal.msgWarning('获取欢迎语配置失败,已加载默认配置')
|
|
|
+ form.value = { ...defaultConfig }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ loading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/** 保存配置 */
|
|
|
+function handleSave() {
|
|
|
+ if (!formRef.value) return
|
|
|
+ formRef.value.validate(valid => {
|
|
|
+ if (!valid) return
|
|
|
+ saveLoading.value = true
|
|
|
+ const payload = {
|
|
|
+ configKey: form.value.configKey || 'default',
|
|
|
+ welcomeText: form.value.welcomeText,
|
|
|
+ status: String(form.value.status),
|
|
|
+ voiceEnabled: String(form.value.voiceEnabled),
|
|
|
+ cooldownSeconds: Number(form.value.cooldownSeconds || 30),
|
|
|
+ remark: form.value.remark || ''
|
|
|
+ }
|
|
|
+ saveWelcomeConfig(payload)
|
|
|
+ .then(() => {
|
|
|
+ proxy.$modal.msgSuccess('保存成功')
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ proxy.$modal.msgError('保存失败,请稍后重试')
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ saveLoading.value = false
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/** 测试播报 */
|
|
|
+function handleTest() {
|
|
|
+ if (!formRef.value) return
|
|
|
+ formRef.value.validateField('welcomeText').then(() => {
|
|
|
+ if (form.value.voiceEnabled === '0') {
|
|
|
+ proxy.$modal.confirm('当前语音播报已关闭,本次测试将仅测试欢迎语内容下发。是否继续?')
|
|
|
+ .then(() => {
|
|
|
+ doTest()
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+ } else {
|
|
|
+ doTest()
|
|
|
+ }
|
|
|
+ }).catch(() => {})
|
|
|
+}
|
|
|
+
|
|
|
+function doTest() {
|
|
|
+ testLoading.value = true
|
|
|
+ testWelcomeBroadcast({
|
|
|
+ configKey: form.value.configKey || 'default',
|
|
|
+ welcomeText: form.value.welcomeText,
|
|
|
+ status: String(form.value.status),
|
|
|
+ voiceEnabled: String(form.value.voiceEnabled)
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ proxy.$modal.msgSuccess('测试播报指令已下发')
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ proxy.$modal.msgError('测试播报失败,请稍后重试')
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ testLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/** 恢复默认 */
|
|
|
+function handleReset() {
|
|
|
+ proxy.$modal.confirm('确认恢复为系统默认欢迎语配置吗?恢复后需点击“保存配置”才会生效。')
|
|
|
+ .then(() => {
|
|
|
+ form.value = { ...defaultConfig }
|
|
|
+ if (formRef.value) {
|
|
|
+ formRef.value.clearValidate()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(() => {})
|
|
|
+}
|
|
|
+
|
|
|
+/** 刷新 */
|
|
|
+function handleRefresh() {
|
|
|
+ loadConfig()
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ loadConfig()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.welcome-config-card {
|
|
|
+ max-width: 860px;
|
|
|
+}
|
|
|
+.welcome-config-form {
|
|
|
+ max-width: 700px;
|
|
|
+}
|
|
|
+.form-tip {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+}
|
|
|
+.form-warning {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #e6a23c;
|
|
|
+}
|
|
|
+.form-unit {
|
|
|
+ margin-left: 8px;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+.action-bar {
|
|
|
+ margin-top: 30px;
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+</style>
|