pc端100j功能完成
This commit is contained in:
@ -35,11 +35,13 @@
|
|||||||
"image-conversion": "2.1.1",
|
"image-conversion": "2.1.1",
|
||||||
"js-cookie": "3.0.5",
|
"js-cookie": "3.0.5",
|
||||||
"jsencrypt": "3.3.2",
|
"jsencrypt": "3.3.2",
|
||||||
|
"lamejs": "^1.2.1",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"paho-mqtt": "^1.1.0",
|
"paho-mqtt": "^1.1.0",
|
||||||
"pinia": "3.0.2",
|
"pinia": "3.0.2",
|
||||||
"qrcode-vue3": "^1.7.1",
|
"qrcode-vue3": "^1.7.1",
|
||||||
|
"recorder-core": "^1.3.25011100",
|
||||||
"screenfull": "6.0.2",
|
"screenfull": "6.0.2",
|
||||||
"vue": "3.5.13",
|
"vue": "3.5.13",
|
||||||
"vue-cropper": "1.1.1",
|
"vue-cropper": "1.1.1",
|
||||||
@ -72,7 +74,7 @@
|
|||||||
"sass": "1.87.0",
|
"sass": "1.87.0",
|
||||||
"terser": "^5.43.1",
|
"terser": "^5.43.1",
|
||||||
"typescript": "~5.8.3",
|
"typescript": "~5.8.3",
|
||||||
"unocss": "^66.0.0",
|
"unocss": "^0.58.0",
|
||||||
"unplugin-auto-import": "19.1.2",
|
"unplugin-auto-import": "19.1.2",
|
||||||
"unplugin-icons": "22.1.0",
|
"unplugin-icons": "22.1.0",
|
||||||
"unplugin-vue-components": "28.5.0",
|
"unplugin-vue-components": "28.5.0",
|
||||||
|
|||||||
BIN
src/assets/images/hb.png
Normal file
BIN
src/assets/images/hb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/images/hbAc.png
Normal file
BIN
src/assets/images/hbAc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/images/rg1.png
Normal file
BIN
src/assets/images/rg1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 304 B |
BIN
src/assets/images/rg1Ac.png
Normal file
BIN
src/assets/images/rg1Ac.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/assets/images/组 62.png
Normal file
BIN
src/assets/images/组 62.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 992 B |
@ -22,9 +22,9 @@
|
|||||||
<h4 class="section-title">报警模式</h4>
|
<h4 class="section-title">报警模式</h4>
|
||||||
<div class="light-mode">
|
<div class="light-mode">
|
||||||
<!-- 使用v-for循环渲染灯光模式卡片 -->
|
<!-- 使用v-for循环渲染灯光模式卡片 -->
|
||||||
<div class="mode-card" :class="{ 'active': mode.active }"
|
<div class="mode-card" @click.stop="handleVoiceType(mode.id)" v-for="mode in sta_VoiceType"
|
||||||
@click.stop="handleVoiceType(mode.id)" v-for="mode in sta_VoiceType" :key="mode.id">
|
:key="mode.id">
|
||||||
<div class="mode_2">
|
<div class="mode_2" :class="{ 'active': mode.active }">
|
||||||
<img :src="mode.active ? mode.activeIcon : mode.icon" :alt="mode.name"
|
<img :src="mode.active ? mode.activeIcon : mode.icon" :alt="mode.name"
|
||||||
class="mode-icon" />
|
class="mode-icon" />
|
||||||
<div class="mode-name">{{ mode.name }}</div>
|
<div class="mode-name">{{ mode.name }}</div>
|
||||||
@ -40,9 +40,9 @@
|
|||||||
<h4 class="section-title">警示灯爆闪</h4>
|
<h4 class="section-title">警示灯爆闪</h4>
|
||||||
<div class="light-mode">
|
<div class="light-mode">
|
||||||
<!-- 使用v-for循环渲染灯光模式卡片 -->
|
<!-- 使用v-for循环渲染灯光模式卡片 -->
|
||||||
<div class="mode-card" :class="{ 'active': mode.active }"
|
<div class="mode-card" @click.stop="handleModeClick(mode.id)" v-for="mode in lightModes"
|
||||||
@click.stop="handleModeClick(mode.id)" v-for="mode in lightModes" :key="mode.id">
|
:key="mode.id">
|
||||||
<div class="mode_2">
|
<div class="mode_2" :class="{ 'active': mode.active }">
|
||||||
<img :src="mode.active ? mode.activeIcon : mode.icon" :alt="mode.name"
|
<img :src="mode.active ? mode.activeIcon : mode.icon" :alt="mode.name"
|
||||||
class="mode-icon" />
|
class="mode-icon" />
|
||||||
<div class="mode-name">{{ mode.name }}</div>
|
<div class="mode-name">{{ mode.name }}</div>
|
||||||
@ -52,7 +52,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-card1" style="margin-top: 8px;">
|
<div class="content-card2" style="margin-top: 8px;">
|
||||||
<h4 class="section-title">语音播报</h4>
|
<h4 class="section-title">语音播报</h4>
|
||||||
<div class="voice-play-section">
|
<div class="voice-play-section">
|
||||||
<div class="current-voice">
|
<div class="current-voice">
|
||||||
@ -81,19 +81,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="voice-btn-item" @click="handleUploadVoice">
|
<div class="voice-btn-item" @click="handleUploadVoice">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Upload />
|
<Microphone />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span>上传语音</span>
|
<span>上传语音</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="voice-btn-item" @click="handleTextToVoice">
|
<div class="voice-btn-item" @click="handleTextToVoice">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Document />
|
<Microphone />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span>文字转语音</span>
|
<span>文字转语音</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="voice-btn-item" @click="handleAllVoice">
|
<div class="voice-btn-item" @click="handleAllVoice">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<List />
|
<Microphone />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span>所有语音</span>
|
<span>所有语音</span>
|
||||||
</div>
|
</div>
|
||||||
@ -114,19 +114,24 @@
|
|||||||
<div class="location-info">
|
<div class="location-info">
|
||||||
<div class="location-item">
|
<div class="location-item">
|
||||||
<span class="location-icon">📍</span>
|
<span class="location-icon">📍</span>
|
||||||
<span>经纬度 {{ deviceDetail && deviceDetail.longitude ?
|
<div style="font-weight: 600; font-size: 14px;">经纬度
|
||||||
Number(deviceDetail.longitude).toFixed(4) : '无' }}
|
<div style="margin-top: 10px;">{{ deviceDetail && deviceDetail.longitude ?
|
||||||
{{ deviceDetail && deviceDetail.latitude ? Number(deviceDetail.latitude).toFixed(4)
|
Number(deviceDetail.longitude).toFixed(4) : '0.00' }}
|
||||||
: '无' }} </span>
|
{{ deviceDetail && deviceDetail.latitude ?
|
||||||
|
Number(deviceDetail.latitude).toFixed(4)
|
||||||
|
: '0.00' }} </div>
|
||||||
</div>
|
</div>
|
||||||
<div class="location-item">
|
|
||||||
<div>地址 <span class="lacatin_gps">{{ deviceDetail.address || "未获取到地址" }}</span></div>
|
</div>
|
||||||
|
<div class="location-item1">
|
||||||
|
<div>地址</div>
|
||||||
<el-button link type="primary" class="view-btn"
|
<el-button link type="primary" class="view-btn"
|
||||||
@click="lookMap(deviceDetail)">查看</el-button>
|
@click="lookMap(deviceDetail)">查看</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="lacatin_gps">{{ deviceDetail.address || "未获取到地址" }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content-card_gps" style="margin-top: 10px;">
|
<div class="content-card_gps" style="margin-top: 20px;">
|
||||||
<div>
|
<div>
|
||||||
<h4 class="section-title">调节</h4>
|
<h4 class="section-title">调节</h4>
|
||||||
<div class="brightness-alarm">
|
<div class="brightness-alarm">
|
||||||
@ -135,7 +140,7 @@
|
|||||||
<el-input class="inputTFT" v-model="deviceDetail.lightBrightness" :min="10"
|
<el-input class="inputTFT" v-model="deviceDetail.lightBrightness" :min="10"
|
||||||
:max="100" :step="1" />
|
:max="100" :step="1" />
|
||||||
<div class="brightness-value">%</div>
|
<div class="brightness-value">%</div>
|
||||||
<el-button type="primary" class="save-btn" v-loading="lightModesLoading"
|
<el-button type="primary" link class="save-btn" v-loading="lightModesLoading"
|
||||||
@click="saveBtnlight">保存 </el-button>
|
@click="saveBtnlight">保存 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -145,7 +150,7 @@
|
|||||||
<el-input class="inputTFT" v-model="deviceDetail.volume" :min="10" :max="100"
|
<el-input class="inputTFT" v-model="deviceDetail.volume" :min="10" :max="100"
|
||||||
:step="1" />
|
:step="1" />
|
||||||
<div class="brightness-value">%</div>
|
<div class="brightness-value">%</div>
|
||||||
<el-button type="primary" class="save-btn" @click="saveBtnVolume">保存
|
<el-button type="primary" link class="save-btn" @click="saveBtnVolume">保存
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -155,7 +160,7 @@
|
|||||||
<el-input class="inputTFT" v-model="deviceDetail.strobeFrequency" :min="0.5"
|
<el-input class="inputTFT" v-model="deviceDetail.strobeFrequency" :min="0.5"
|
||||||
:max="10" :step="1" />
|
:max="10" :step="1" />
|
||||||
<div class="brightness-value">%</div>
|
<div class="brightness-value">%</div>
|
||||||
<el-button type="primary" class="save-btn" @click="saveBtnstrobe">保存
|
<el-button type="primary" link class="save-btn" @click="saveBtnstrobe">保存
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -322,22 +327,16 @@ import { useRoute, useRouter } from 'vue-router';
|
|||||||
import { useMqtt } from '@/utils/mqtt';
|
import { useMqtt } from '@/utils/mqtt';
|
||||||
import api from '@/api/controlCenter/controlPanel/100J';
|
import api from '@/api/controlCenter/controlPanel/100J';
|
||||||
import { DeviceDetail, LightMode } from '@/api/controlCenter/controlPanel/types';
|
import { DeviceDetail, LightMode } from '@/api/controlCenter/controlPanel/types';
|
||||||
import { getDeviceStatus } from '@/utils/function';
|
|
||||||
|
|
||||||
// 路由和实例
|
// 路由和实例
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
import request from '@/utils/request';
|
|
||||||
// 导入图片资源
|
// 导入图片资源
|
||||||
import closeDefault from '@/assets/images/close.png';
|
import rb from '@/assets/images/rg1.png';
|
||||||
import closeActive from '@/assets/images/close_HL.png';
|
import rbAc from '@/assets/images/rg1Ac.png';
|
||||||
import rb from '@/assets/images/rb.png';
|
import sg from '@/assets/images/hb.png';
|
||||||
import rbAc from '@/assets/images/rbAc.png';
|
import sgAc from '@/assets/images/hbAc.png';
|
||||||
import sg from '@/assets/images/sg.png';
|
|
||||||
import sgAc from '@/assets/images/sgAc.png';
|
|
||||||
import { object } from 'vue-types';
|
|
||||||
|
|
||||||
// 基础状态
|
// 基础状态
|
||||||
const forceAlarmLoading = ref(false);
|
const forceAlarmLoading = ref(false);
|
||||||
const lightModesLoading = ref(false);
|
const lightModesLoading = ref(false);
|
||||||
@ -345,26 +344,17 @@ const centerDialogVisible = ref(false);
|
|||||||
const currentVoiceId = ref(''); // 当前选中的语音ID
|
const currentVoiceId = ref(''); // 当前选中的语音ID
|
||||||
const voiceList = ref<any[]>([]); // 语音列表
|
const voiceList = ref<any[]>([]); // 语音列表
|
||||||
|
|
||||||
// MQTT相关
|
|
||||||
const {
|
|
||||||
connected,
|
|
||||||
connect,
|
|
||||||
subscribe,
|
|
||||||
onConnect,
|
|
||||||
onError,
|
|
||||||
onMessage,
|
|
||||||
disconnect
|
|
||||||
} = useMqtt();
|
|
||||||
|
|
||||||
// ====================== 录制语音 ======================
|
// ====================== 录制语音 ======================
|
||||||
|
import Recorder from 'recorder-core';
|
||||||
|
// 引入 MP3 编码器(核心:生成标准 MP3)
|
||||||
|
import 'recorder-core/src/engine/mp3';
|
||||||
|
import 'recorder-core/src/engine/mp3-engine';
|
||||||
const recordVoiceDialog = ref(false);
|
const recordVoiceDialog = ref(false);
|
||||||
const isRecording = ref(false);
|
const isRecording = ref(false);
|
||||||
const recordDuration = ref(0);
|
const recordDuration = ref(0);
|
||||||
const recordedBlob = ref<Blob | null>(null);
|
const recorderIns = ref<any>(null); // Recorder 实例
|
||||||
const audioChunks = ref<BlobPart[]>([]);
|
|
||||||
const mediaRecorder = ref<MediaRecorder | null>(null);
|
|
||||||
let recordTimer: NodeJS.Timeout | null = null;
|
let recordTimer: NodeJS.Timeout | null = null;
|
||||||
let audioStream: MediaStream | null = null;
|
const recordedBlob = ref()
|
||||||
|
|
||||||
const formatTime = (seconds: number) => {
|
const formatTime = (seconds: number) => {
|
||||||
const min = String(Math.floor(seconds / 60)).padStart(2, '0');
|
const min = String(Math.floor(seconds / 60)).padStart(2, '0');
|
||||||
@ -372,65 +362,100 @@ const formatTime = (seconds: number) => {
|
|||||||
return `${min}:${sec}`;
|
return `${min}:${sec}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ------------- 开始录制语音上传 -------------
|
||||||
const startRecordVoice = async () => {
|
const startRecordVoice = async () => {
|
||||||
try {
|
try {
|
||||||
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
// 1. 重置状态
|
||||||
proxy?.$modal.msgError('当前浏览器不支持麦克风录制,请使用Chrome/Edge/Firefox');
|
resetRecord();
|
||||||
return;
|
recorderIns.value = Recorder({
|
||||||
|
type: 'mp3', // 直接录制为 MP3
|
||||||
|
sampleRate: 44100, // 标准采样率
|
||||||
|
bitRate: 128, // 128kbps(微信兼容)
|
||||||
|
onProcess: (buffers: any, power: number, bufferDuration: number, bufferSampleRate: number) => {
|
||||||
}
|
}
|
||||||
audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
});
|
||||||
mediaRecorder.value = new MediaRecorder(audioStream);
|
recorderIns.value.open(() => {
|
||||||
audioChunks.value = [];
|
// 权限申请成功,开始录制
|
||||||
mediaRecorder.value.ondataavailable = (e) => audioChunks.value.push(e.data);
|
recorderIns.value.start();
|
||||||
mediaRecorder.value.onstop = () => {
|
|
||||||
recordedBlob.value = new Blob(audioChunks.value, { type: 'audio/mp3' });
|
|
||||||
if (audioStream) {
|
|
||||||
audioStream.getTracks().forEach(track => track.stop());
|
|
||||||
audioStream = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mediaRecorder.value.start();
|
|
||||||
isRecording.value = true;
|
isRecording.value = true;
|
||||||
recordDuration.value = 0;
|
recordDuration.value = 0;
|
||||||
recordTimer = setInterval(() => recordDuration.value++, 1000);
|
recordTimer = setInterval(() => recordDuration.value++, 1000);
|
||||||
|
// proxy?.$modal.msgSuccess('开始录制语音...');
|
||||||
|
}, (err: any) => {
|
||||||
|
// 权限申请失败
|
||||||
|
proxy?.$modal.msgError(`麦克风权限申请失败`);
|
||||||
|
resetRecord();
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
proxy?.$modal.msgError('麦克风权限申请失败');
|
proxy?.$modal.msgError('录制异常,请重试');
|
||||||
if (audioStream) {
|
resetRecord();
|
||||||
audioStream.getTracks().forEach(track => track.stop());
|
|
||||||
audioStream = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ------------- 停止录制 -------------
|
||||||
const stopRecordVoice = () => {
|
const stopRecordVoice = () => {
|
||||||
if (!mediaRecorder.value || !isRecording.value) return;
|
if (!recorderIns.value || !isRecording.value) {
|
||||||
mediaRecorder.value.stop();
|
proxy?.$modal.msgWarning('未在录制状态');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 停止录制并获取 MP3 Blob
|
||||||
|
recorderIns.value.stop((blob: Blob, duration: number) => {
|
||||||
|
// blob 是标准 MP3 格式(微信100%兼容)
|
||||||
|
recordedBlob.value = blob;
|
||||||
|
console.log('标准 MP3 生成成功:', blob);
|
||||||
|
|
||||||
isRecording.value = false;
|
isRecording.value = false;
|
||||||
if (recordTimer) {
|
if (recordTimer) clearInterval(recordTimer);
|
||||||
clearInterval(recordTimer);
|
proxy?.$modal.msgSuccess(`录制完成,时长:${Math.round(duration)}秒`);
|
||||||
recordTimer = null;
|
|
||||||
|
// 释放资源
|
||||||
|
recorderIns.value.close();
|
||||||
|
}, (err: any) => {
|
||||||
|
// proxy?.$modal.msgError(`停止录制失败:${err.msg}`);
|
||||||
|
resetRecord();
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
proxy?.$modal.msgError('停止录制异常');
|
||||||
|
resetRecord();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ------------- 重置录制状态 -------------
|
||||||
const resetRecord = () => {
|
const resetRecord = () => {
|
||||||
isRecording.value = false;
|
isRecording.value = false;
|
||||||
recordDuration.value = 0;
|
recordDuration.value = 0;
|
||||||
recordedBlob.value = null;
|
recordedBlob.value = null;
|
||||||
audioChunks.value = [];
|
|
||||||
if (recordTimer) {
|
if (recordTimer) {
|
||||||
clearInterval(recordTimer);
|
clearInterval(recordTimer);
|
||||||
recordTimer = null;
|
recordTimer = null;
|
||||||
}
|
}
|
||||||
|
// 释放 Recorder 资源
|
||||||
|
if (recorderIns.value) {
|
||||||
|
recorderIns.value.close();
|
||||||
|
recorderIns.value = null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
// ------------- 保存/上传标准 MP3 文件 -------------
|
||||||
const saveRecordVoice = () => {
|
const saveRecordVoice = () => {
|
||||||
if (!recordedBlob.value) {
|
// 1. 校验 MP3 Blob 是否有效
|
||||||
proxy?.$modal.msgWarning('暂无录制的语音文件');
|
if (!recordedBlob.value || recordedBlob.value.size === 0) {
|
||||||
|
proxy?.$modal.msgWarning('暂无有效录制的 MP3 文件');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 2. 校验 deviceId
|
||||||
|
const deviceId = route?.params?.deviceId;
|
||||||
|
if (!deviceId || typeof deviceId !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 3. 构建 FormData(上传标准 MP3)
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', recordedBlob.value, `record_${new Date().getTime()}.mp3`);
|
formData.append('deviceId', deviceId);
|
||||||
formData.append('deviceId', route.params.deviceId as string);
|
const fileName = `${new Date().getTime()}.mp3`;
|
||||||
|
formData.append('file', recordedBlob.value, fileName);
|
||||||
|
// 4. 上传接口
|
||||||
proxy?.$modal.loading('保存中...');
|
proxy?.$modal.loading('保存中...');
|
||||||
api.uploadAudioToOss(formData).then(res => {
|
api.uploadAudioToOss(formData).then(res => {
|
||||||
proxy?.$modal.closeLoading();
|
proxy?.$modal.closeLoading();
|
||||||
@ -440,12 +465,15 @@ const saveRecordVoice = () => {
|
|||||||
queryAudioFileInfo();
|
queryAudioFileInfo();
|
||||||
resetRecord();
|
resetRecord();
|
||||||
} else {
|
} else {
|
||||||
proxy?.$modal.msgError('保存语音失败:' + res.msg);
|
proxy?.$modal.msgError('保存语音失败');
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
proxy?.$modal.closeLoading();
|
proxy?.$modal.closeLoading();
|
||||||
proxy?.$modal.msgError('保存语音失败');
|
proxy?.$modal.msgError('保存语音失败');
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRecordVoice = () => {
|
const handleRecordVoice = () => {
|
||||||
@ -884,7 +912,7 @@ const showClose = async () => {
|
|||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
deviceDetail.value.voiceStrobeAlarm = 0;
|
deviceDetail.value.voiceStrobeAlarm = 0;
|
||||||
proxy?.$modal.msgSuccess(res.msg);
|
proxy?.$modal.msgSuccess(res.msg);
|
||||||
await getList();
|
//await getList();
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
proxy?.$modal.msgError(error.msg);
|
proxy?.$modal.msgError(error.msg);
|
||||||
@ -908,7 +936,7 @@ const forceAlarm = async () => {
|
|||||||
deviceDetail.value.voiceStrobeAlarm = 1;
|
deviceDetail.value.voiceStrobeAlarm = 1;
|
||||||
proxy?.$modal.msgSuccess(res.msg);
|
proxy?.$modal.msgSuccess(res.msg);
|
||||||
|
|
||||||
await getList();
|
// await getList();
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
proxy?.$modal.msgError(error.msg);
|
proxy?.$modal.msgError(error.msg);
|
||||||
@ -939,7 +967,7 @@ const playCurrentVoice = async () => {
|
|||||||
proxy?.$modal.msgError(res.msg);
|
proxy?.$modal.msgError(res.msg);
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
proxy?.$modal.msgError(err.msg);
|
// proxy?.$modal.msgError(err.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 2. 非报警中场景:单纯播放/暂停语音
|
// 2. 非报警中场景:单纯播放/暂停语音
|
||||||
@ -958,7 +986,7 @@ const playCurrentVoice = async () => {
|
|||||||
proxy?.$modal.msgError(res.msg);
|
proxy?.$modal.msgError(res.msg);
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
proxy?.$modal.msgError(err.msg);
|
// proxy?.$modal.msgError(err.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1018,18 +1046,27 @@ onUnmounted(() => {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
|
box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
|
||||||
background: white;
|
background: white;
|
||||||
padding: 20px;
|
padding: 1px 20px;
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
min-height: 730px;
|
min-height: 700px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-card1 {
|
.content-card1 {
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
|
box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
|
||||||
background: white;
|
background: white;
|
||||||
padding: 20px;
|
padding: 1px 20px;
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
min-height: 250px;
|
height: 440px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card2 {
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 34, 96, 0.1);
|
||||||
|
background: white;
|
||||||
|
padding: 1px 20px;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-card_gps {
|
.content-card_gps {
|
||||||
@ -1056,11 +1093,12 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
.lacatin_gps {
|
.lacatin_gps {
|
||||||
height: 70px;
|
height: 70px;
|
||||||
border-radius: 4px;
|
background: #F7F8FC;
|
||||||
background: rgba(247, 248, 252, 1);
|
border-radius: 4px 4px 4px 4px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mode_2 {
|
.mode_2 {
|
||||||
@ -1069,8 +1107,17 @@ onUnmounted(() => {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
width: 105px;
|
width: 105px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
border-radius: 4px 4px 4px 4px;
|
||||||
|
border: 1px solid #027CFB;
|
||||||
|
background: rgba(2, 124, 251, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.mode-card {
|
.mode-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -1142,7 +1189,7 @@ onUnmounted(() => {
|
|||||||
.save-btn {
|
.save-btn {
|
||||||
padding: 6px 20px;
|
padding: 6px 20px;
|
||||||
border-radius: 29px;
|
border-radius: 29px;
|
||||||
background: rgba(2, 124, 251, 1);
|
// background: rgba(2, 124, 251, 1);
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,6 +1215,12 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.location-info {
|
.location-info {
|
||||||
|
.location-item1 {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
color: #38404F;
|
||||||
|
}
|
||||||
|
|
||||||
.location-item {
|
.location-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -1235,7 +1288,7 @@ onUnmounted(() => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: 1px solid #dcdfe6;
|
// border: 1px solid #dcdfe6;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
@ -1246,14 +1299,19 @@ onUnmounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.el-icon {
|
.el-icon {
|
||||||
font-size: 20px;
|
font-size: 24px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
color: #409eff;
|
color: #027CFB;
|
||||||
|
border: 1px solid rgba(2, 124, 251, 0.2);
|
||||||
|
border-radius: 6px 6px 6px 6px;
|
||||||
|
width: 37px;
|
||||||
|
height: 37px;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-size: 12px;
|
font-size: 14px;
|
||||||
color: #606266;
|
color: #027CFB;
|
||||||
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user