|
@@ -1,65 +1,122 @@
|
|
|
<template>
|
|
|
- <div class="viewLogsPage flex-col">
|
|
|
- <s-header :name="$t('device.viewLogs')" :noback="false"></s-header>
|
|
|
- <div class="block2 flex-row justify-between">
|
|
|
- <div class="block3 flex-col"></div>
|
|
|
- <span class="info2">{{ $t('device.equipmentName') }}:{{ deviceDetail ? deviceDetail.name : '' }}</span>
|
|
|
+ <div class="log-viewer">
|
|
|
+ <s-header :name="$t('device.viewLogs')" :noback="false" />
|
|
|
+
|
|
|
+ <!-- 设备名称标题 -->
|
|
|
+ <div class="device-header">
|
|
|
+ <div class="vertical-indicator"></div>
|
|
|
+ <h3 class="device-name">
|
|
|
+ {{ $t("device.equipmentName") }}:{{ deviceName }}
|
|
|
+ </h3>
|
|
|
</div>
|
|
|
- <div class="wrap1 flex-col o-pt-15">
|
|
|
- <van-field v-model="logsTime" is-link readonly label="日期" placeholder="点击选择时间" @click="chooseTime()" />
|
|
|
- <van-popup v-model:show="showPicker" round position="bottom">
|
|
|
- <van-date-picker :min-date="minDate" :max-date="maxDate" @confirm="selectTime" @cancel="showPicker = false" />
|
|
|
- </van-popup>
|
|
|
- <van-cell-group>
|
|
|
- <van-field readonly v-model="message" rows="2" autosize label="使用教程" type="textarea" show-word-limit />
|
|
|
- </van-cell-group>
|
|
|
- <div class="button-container">
|
|
|
- <van-button round style="padding: 1em 2em;" type="primary" @click="uploadLogBtn">上传</van-button>
|
|
|
- <van-button round style="padding: 1em 2em;" type="primary" @click="queryLogBtn">查询</van-button>
|
|
|
+
|
|
|
+ <!-- 操作卡片 -->
|
|
|
+ <div class="operation-card">
|
|
|
+ <!-- 时间选择 -->
|
|
|
+ <div class="time-picker-card">
|
|
|
+ <van-field
|
|
|
+ v-model="logsTime"
|
|
|
+ is-link
|
|
|
+ readonly
|
|
|
+ label="选择日期"
|
|
|
+ placeholder="点击选择时间"
|
|
|
+ @click="chooseTime"
|
|
|
+ class="time-field"
|
|
|
+ />
|
|
|
+ <van-popup v-model:show="showPicker" round position="bottom">
|
|
|
+ <van-date-picker
|
|
|
+ :min-date="minDate"
|
|
|
+ :max-date="maxDate"
|
|
|
+ @confirm="selectTime"
|
|
|
+ @cancel="showPicker = false"
|
|
|
+ />
|
|
|
+ </van-popup>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 使用说明 -->
|
|
|
+ <div class="tutorial-card">
|
|
|
+ <van-field
|
|
|
+ v-model="message"
|
|
|
+ readonly
|
|
|
+ rows="2"
|
|
|
+ autosize
|
|
|
+ label="使用教程"
|
|
|
+ type="textarea"
|
|
|
+ class="tutorial-field"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 新增通道选择 -->
|
|
|
+ <div class="channel-selector">
|
|
|
+ <van-radio-group v-model="channelType" direction="horizontal">
|
|
|
+ <van-radio name="1" icon-size="16px" class="channel-option">
|
|
|
+ 默认通道
|
|
|
+ </van-radio>
|
|
|
+ <van-radio name="2" icon-size="16px" class="channel-option">
|
|
|
+ 新通道
|
|
|
+ </van-radio>
|
|
|
+ </van-radio-group>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 操作按钮 -->
|
|
|
+ <div class="action-buttons">
|
|
|
+ <van-button
|
|
|
+ round
|
|
|
+ type="primary"
|
|
|
+ icon="back-top"
|
|
|
+ @click="uploadLogBtn"
|
|
|
+ class="action-btn"
|
|
|
+ >
|
|
|
+ 上传日志
|
|
|
+ </van-button>
|
|
|
+ <van-button
|
|
|
+ round
|
|
|
+ type="success"
|
|
|
+ icon="search"
|
|
|
+ @click="queryLogBtn"
|
|
|
+ class="action-btn"
|
|
|
+ >
|
|
|
+ 查询日志
|
|
|
+ </van-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 文件下载卡片 -->
|
|
|
+ <div v-if="fileName" class="file-card">
|
|
|
+ <van-cell
|
|
|
+ :title="fileName"
|
|
|
+ clickable
|
|
|
+ @click="downloadFile"
|
|
|
+ class="file-item"
|
|
|
+ >
|
|
|
+ <template #right-icon>
|
|
|
+ <van-icon name="down" class="download-icon" />
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
</div>
|
|
|
- <!-- <van-button v-if="!downloading" round :disabled="logsTime === ''" type="primary" class="volumeChangeButton"
|
|
|
- @click="downloadBtn">{{ $t('device.download') }}</van-button>
|
|
|
- <van-button v-else disabled loading round class="volumeChangeButton" type="primary"
|
|
|
- :loading-text="$t('device.downloading')" /> -->
|
|
|
-
|
|
|
- <van-cell v-if="fileName != ''" :title="fileName" :clickable=true @click="downloadFile">
|
|
|
- <!-- 使用 right-icon 插槽来自定义右侧图标 -->
|
|
|
- <template #right-icon>
|
|
|
- <van-icon name="down" class="search-icon" />
|
|
|
- </template>
|
|
|
- </van-cell>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import {
|
|
|
- onMounted,
|
|
|
- computed,
|
|
|
- ref
|
|
|
-} from 'vue';
|
|
|
+import { onMounted, computed, ref } from "vue";
|
|
|
import sHeader from "@/components/SimpleHeader.vue";
|
|
|
import {
|
|
|
downloadLog,
|
|
|
getDeviceDetal,
|
|
|
uploadLog,
|
|
|
- queryLog
|
|
|
+ newUploadLog,
|
|
|
+ queryLog,
|
|
|
} from "@/service/device";
|
|
|
import { $M_ExportFile } from "@/common/js/utils";
|
|
|
-import {
|
|
|
- showFailToast,
|
|
|
- showToast
|
|
|
-} from "vant";
|
|
|
-import {
|
|
|
- useRoute
|
|
|
-} from "vue-router";
|
|
|
+import { showFailToast, showToast } from "vant";
|
|
|
+import { useRoute } from "vue-router";
|
|
|
import dateUtil from "@/utils/dateUtil";
|
|
|
-import { styleUrl } from '../../../common/js/utils';
|
|
|
+// import { styleUrl } from "../../../common/js/utils";
|
|
|
// import {useI18n} from "vue-i18n";
|
|
|
|
|
|
-export default ({
|
|
|
+export default {
|
|
|
components: {
|
|
|
- sHeader
|
|
|
+ sHeader,
|
|
|
},
|
|
|
setup() {
|
|
|
// const { t } = useI18n();
|
|
@@ -69,14 +126,18 @@ export default ({
|
|
|
const showPicker = ref(false);
|
|
|
const downloading = ref(false);
|
|
|
const logsTime = ref(null);
|
|
|
- const fileName = ref(''); // 文件名
|
|
|
- const message = ref('选择日期点击上传,等待几秒后点击查询,找到文件点击下载到本地查看。');
|
|
|
- // const curDate = new Date(); // 获取当前时间日期
|
|
|
+ const fileName = ref(""); // 文件名
|
|
|
+ const message = ref(
|
|
|
+ "选择日期点击上传,等待几秒后点击查询,找到文件点击下载到本地查看。"
|
|
|
+ );
|
|
|
|
|
|
// 计算最小日期为当前日期7天前
|
|
|
const minDate = computed(() => {
|
|
|
- const minTimestamp = (new Date()).getTime() - 6 * 24 * 3600 * 1000;
|
|
|
- const minDate = dateUtil.formateDate(new Date(minTimestamp), "yyyy-MM-dd");
|
|
|
+ const minTimestamp = new Date().getTime() - 6 * 24 * 3600 * 1000;
|
|
|
+ const minDate = dateUtil.formateDate(
|
|
|
+ new Date(minTimestamp),
|
|
|
+ "yyyy-MM-dd"
|
|
|
+ );
|
|
|
return new Date(minDate);
|
|
|
});
|
|
|
|
|
@@ -85,146 +146,139 @@ export default ({
|
|
|
return new Date();
|
|
|
});
|
|
|
|
|
|
+ // 上传通道
|
|
|
+ const channelType = ref("1");
|
|
|
|
|
|
// 初始化页面获取列表
|
|
|
onMounted(async () => {
|
|
|
// 加载样式
|
|
|
- styleUrl('viewLogs');
|
|
|
await getDeviceDetailFun();
|
|
|
- // console.log(deviceDetail.value.name);
|
|
|
});
|
|
|
|
|
|
// 选择时间
|
|
|
const chooseTime = () => {
|
|
|
- // console.log('chooseTime function is called');
|
|
|
showPicker.value = true;
|
|
|
- console.log(showPicker.value);
|
|
|
};
|
|
|
|
|
|
-
|
|
|
const selectTime = ({ selectedValues }) => {
|
|
|
- // console.log('selectTime function is called', time);
|
|
|
- // logsTime.value = dateUtil.formateDate(time, "yyyy-MM-dd");
|
|
|
logsTime.value = selectedValues.join("-");
|
|
|
showPicker.value = false;
|
|
|
};
|
|
|
|
|
|
const getDeviceDetailFun = async () => {
|
|
|
- const {
|
|
|
- data
|
|
|
- } = await getDeviceDetal({
|
|
|
- id: deviceId
|
|
|
+ const { data } = await getDeviceDetal({
|
|
|
+ id: deviceId,
|
|
|
});
|
|
|
- if (data.code === '00000') {
|
|
|
+ if (data.code === "00000") {
|
|
|
deviceDetail.value = data.data;
|
|
|
} else {
|
|
|
showFailToast(data.message);
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
const downloadBtn = async () => {
|
|
|
const pattern = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
if (logsTime.value == null) {
|
|
|
- showToast('请选择日期');
|
|
|
+ showToast("请选择日期");
|
|
|
return;
|
|
|
}
|
|
|
if (!pattern.test(logsTime.value)) {
|
|
|
- showToast('日期格式有误');
|
|
|
+ showToast("日期格式有误");
|
|
|
return;
|
|
|
}
|
|
|
- const formattedDate = logsTime.value.replace(/-/g, '');
|
|
|
+ const formattedDate = logsTime.value.replace(/-/g, "");
|
|
|
downloading.value = true;
|
|
|
try {
|
|
|
- const {
|
|
|
- headers, data
|
|
|
- } = await downloadLog({
|
|
|
+ const { headers, data } = await downloadLog({
|
|
|
equipmentId: deviceId,
|
|
|
day: formattedDate,
|
|
|
});
|
|
|
- console.log('请求成功', headers, data);
|
|
|
+ console.log("请求成功", headers, data);
|
|
|
$M_ExportFile(data, headers);
|
|
|
} catch (error) {
|
|
|
- if (error.code === 'ECONNABORTED') {
|
|
|
+ if (error.code === "ECONNABORTED") {
|
|
|
// 处理请求超时的错误
|
|
|
- console.error('请求超时:', error);
|
|
|
+ console.error("请求超时:", error);
|
|
|
showFailToast("请求超时");
|
|
|
} else {
|
|
|
// 处理其他请求错误
|
|
|
- console.error('请求失败:', error);
|
|
|
+ console.error("请求失败:", error);
|
|
|
showFailToast("请求失败");
|
|
|
}
|
|
|
} finally {
|
|
|
downloading.value = false;
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
const uploadLogBtn = async () => {
|
|
|
const pattern = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
- if (logsTime.value == '') {
|
|
|
- showToast('请选择日期');
|
|
|
+ if (logsTime.value == "") {
|
|
|
+ showToast("请选择日期");
|
|
|
return;
|
|
|
}
|
|
|
if (!pattern.test(logsTime.value)) {
|
|
|
- showToast('日期格式有误');
|
|
|
+ showToast("日期格式有误");
|
|
|
return;
|
|
|
}
|
|
|
- const formattedDate = logsTime.value.replace(/-/g, '');
|
|
|
- const { data } = await uploadLog({
|
|
|
+ const formattedDate = logsTime.value.replace(/-/g, "");
|
|
|
+ const { data } = await (channelType.value == "1"
|
|
|
+ ? uploadLog
|
|
|
+ : newUploadLog)({
|
|
|
equipmentId: deviceId,
|
|
|
day: formattedDate,
|
|
|
});
|
|
|
- if (data.code == '00000') {
|
|
|
- showToast('上传信号发送成功,请等待几秒后查询下载');
|
|
|
+ if (data.code == "00000") {
|
|
|
+ showToast("上传信号发送成功,请等待几秒后查询下载");
|
|
|
} else {
|
|
|
showFailToast(data.message);
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
// 查询日志是否上传成功
|
|
|
const queryLogBtn = async () => {
|
|
|
- if (logsTime.value == '') {
|
|
|
- showToast('请选择日期');
|
|
|
+ if (logsTime.value == "") {
|
|
|
+ showToast("请选择日期");
|
|
|
return;
|
|
|
}
|
|
|
const pattern = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
if (!pattern.test(logsTime.value)) {
|
|
|
- showToast('日期格式有误');
|
|
|
+ showToast("日期格式有误");
|
|
|
return;
|
|
|
}
|
|
|
- const formattedDate = logsTime.value.replace(/-/g, '');
|
|
|
+ const formattedDate = logsTime.value.replace(/-/g, "");
|
|
|
const { data } = await queryLog({
|
|
|
equipmentId: deviceId,
|
|
|
day: formattedDate,
|
|
|
});
|
|
|
- if (data.code == '00000') {
|
|
|
+ if (data.code == "00000") {
|
|
|
// console.log(data.data);
|
|
|
- showToast("查询成功,点击下载")
|
|
|
+ showToast("查询成功,点击下载");
|
|
|
fileName.value = data.data.substring(4);
|
|
|
} else {
|
|
|
- fileName.value = '';
|
|
|
+ fileName.value = "";
|
|
|
showToast("找不到文件,请重试上传或检查机器网络");
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
const downloadFile = async () => {
|
|
|
// 文件链接
|
|
|
- const fileUrl = 'http://qiniuyun.sunzee.com.cn/log/' + fileName.value;
|
|
|
+ const fileUrl = "https://qiniuyun.sunzee.com.cn/log/" + fileName.value;
|
|
|
// 文件名
|
|
|
const newFileName = fileName.value;
|
|
|
try {
|
|
|
const response = await fetch(fileUrl, {
|
|
|
headers: {
|
|
|
- 'Cache-Control': 'no-store', // 禁用缓存
|
|
|
- 'Pragma': 'no-cache',
|
|
|
- }
|
|
|
+ "Cache-Control": "no-store", // 禁用缓存
|
|
|
+ Pragma: "no-cache",
|
|
|
+ },
|
|
|
});
|
|
|
- console.log('response', response);
|
|
|
+ console.log("response", response);
|
|
|
|
|
|
// 将文件内容创建为Blob
|
|
|
const fileBlob = await response.blob();
|
|
|
|
|
|
// 创建一个下载链接
|
|
|
- const downloadLink = document.createElement('a');
|
|
|
+ const downloadLink = document.createElement("a");
|
|
|
downloadLink.href = URL.createObjectURL(fileBlob);
|
|
|
downloadLink.download = newFileName;
|
|
|
|
|
@@ -235,9 +289,9 @@ export default ({
|
|
|
// 清理添加的链接元素
|
|
|
document.body.removeChild(downloadLink);
|
|
|
} catch (error) {
|
|
|
- console.error('请求超时:', error);
|
|
|
+ console.error("请求超时:", error);
|
|
|
}
|
|
|
- }
|
|
|
+ };
|
|
|
|
|
|
return {
|
|
|
deviceDetail,
|
|
@@ -253,28 +307,167 @@ export default ({
|
|
|
uploadLogBtn,
|
|
|
queryLogBtn,
|
|
|
fileName,
|
|
|
- message
|
|
|
- }
|
|
|
+ message,
|
|
|
+ channelType,
|
|
|
+ };
|
|
|
},
|
|
|
-
|
|
|
-});
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style lang="less" scoped>
|
|
|
@import "../../../common/style/common";
|
|
|
|
|
|
-.search-icon {
|
|
|
- font-size: 16px;
|
|
|
- line-height: inherit;
|
|
|
+@primary-color: #4dc294;
|
|
|
+@card-bg: #ffffff;
|
|
|
+@text-primary: #2d3436;
|
|
|
+@border-color: #e4e7ec;
|
|
|
+
|
|
|
+.log-viewer {
|
|
|
+ background: #f8fafb;
|
|
|
+ min-height: 100vh;
|
|
|
}
|
|
|
|
|
|
-.button-container {
|
|
|
+.device-header {
|
|
|
display: flex;
|
|
|
- justify-content: center;
|
|
|
align-items: center;
|
|
|
- margin-top: 20px;
|
|
|
- /* 根据需要添加上下边距 */
|
|
|
- margin-bottom: 30px;
|
|
|
- gap: 20px;
|
|
|
+ padding: 12px 15px;
|
|
|
+ background: #fff;
|
|
|
+ margin: 10px;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
|
+
|
|
|
+ .vertical-indicator {
|
|
|
+ width: 4px;
|
|
|
+ height: 15px;
|
|
|
+ background: var(--active-color, #4d6add);
|
|
|
+ border-radius: 2px;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .device-name {
|
|
|
+ margin: 0;
|
|
|
+ font-size: 15px;
|
|
|
+ color: #404d74;
|
|
|
+ font-weight: 550;
|
|
|
+
|
|
|
+ // 长名称处理
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ max-width: 70vw;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.operation-card {
|
|
|
+ background: @card-bg;
|
|
|
+ border-radius: 12px;
|
|
|
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
|
|
+ padding: 16px;
|
|
|
+ margin: 10px;
|
|
|
+
|
|
|
+ .time-picker-card {
|
|
|
+ margin-bottom: 16px;
|
|
|
+
|
|
|
+ .time-field {
|
|
|
+ :deep(.van-field__label) {
|
|
|
+ width: 80px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tutorial-card {
|
|
|
+ border: 1px solid @border-color;
|
|
|
+ border-radius: 8px;
|
|
|
+ margin-bottom: 24px;
|
|
|
+
|
|
|
+ .tutorial-field {
|
|
|
+ :deep(.van-field__label) {
|
|
|
+ color: @primary-color;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ :deep(textarea) {
|
|
|
+ color: #666;
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .channel-selector {
|
|
|
+ margin: 16px 0;
|
|
|
+ padding: 12px 16px;
|
|
|
+ background: #f8fafb;
|
|
|
+ border-radius: 8px;
|
|
|
+
|
|
|
+ .van-radio-group {
|
|
|
+ display: flex;
|
|
|
+ gap: 24px;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .channel-option {
|
|
|
+ :deep(.van-radio__label) {
|
|
|
+ color: #2d3436;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.van-radio__icon) {
|
|
|
+ color: #4dc294;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-buttons {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
+ gap: 12px;
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ height: 44px;
|
|
|
+ font-size: 15px;
|
|
|
+ box-shadow: 0 4px 12px rgba(77, 194, 148, 0.2);
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ transform: scale(0.98);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.file-card {
|
|
|
+ background: #666;
|
|
|
+ border-radius: 12px;
|
|
|
+ margin: 16px 0;
|
|
|
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
|
|
+
|
|
|
+ .file-item {
|
|
|
+ :deep(.van-cell__title) {
|
|
|
+ color: @text-primary;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .download-icon {
|
|
|
+ color: @primary-color;
|
|
|
+ font-size: 18px;
|
|
|
+ margin-left: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: #f8fafb;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 480px) {
|
|
|
+ .action-buttons {
|
|
|
+ grid-template-columns: 1fr !important;
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .operation-card {
|
|
|
+ padding: 12px;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|