123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- <template>
- <div class="alarm-history-container">
- <!-- 系统头部 -->
- <s-header :name="$t('alarmHistory.alarmHistory')" :noback="false" />
- <!-- 主要内容区域 -->
- <div class="alarm-history-content">
- <!-- 顶部筛选和统计区(优化版) -->
- <div class="stats-filter-card">
- <!-- 统计信息区 -->
- <div class="stats-area">
- <div class="stats-icon-box">
- <van-icon name="bell" size="20" color="#ff6d59" />
- </div>
- <div class="stats-content">
- <div class="stats-value">
- <span class="highlight-number"
- >{{ alarmHistoryTotal
- }}{{ $t("alarmHistory.recordsTotal") }}</span
- >
- </div>
- </div>
- </div>
- <!-- 搜索功能区 -->
- <div class="filter-area">
- <div class="filter-btn" @click="searchClick">
- <van-icon name="search" size="18" color="#ffffff" />
- <span class="btn-text">{{ $t("alarmHistory.search") }}</span>
- </div>
- </div>
- </div>
- <!-- 报警历史列表 -->
- <van-list
- v-model:loading="loading"
- v-model:error="error"
- :error-text="$t('alarmHistory.requestFailed')"
- :finished="finished"
- :finished-text="$t('alarmHistory.noMore')"
- offset="100"
- :immediate-check="false"
- @load="onLoad"
- >
- <!-- 列表项(卡片式设计) -->
- <div class="history-list">
- <div
- v-for="(item, index) in alarmHistoryList"
- :key="index"
- class="history-card"
- :class="[getAlarmLevelClass(item.level)]"
- >
- <div class="card-header flex-row justify-between align-center">
- <div class="card-title">
- {{ showDeviceName(item.equipmentId) }}
- </div>
- <div class="card-time">
- {{ showDateTime(item.occurrenceTime) }}
- </div>
- </div>
- <!-- 卡片内容 -->
- <div class="card-body">
- <div class="info-row">
- <div class="info-label">
- {{ $t("alarmHistory.affiliatedMerchants") }}:
- </div>
- <div class="info-value">{{ item.adminUserName }}</div>
- </div>
- <div class="info-row">
- <div class="info-label">
- {{ $t("alarmHistory.equipmentNo") }}:
- </div>
- <div class="info-value badge-id">{{ item.clientId }}</div>
- </div>
- <div class="info-row">
- <div class="info-label">
- {{ $t("alarmHistory.alarmContent") }}:
- </div>
- <div class="info-value alarm-content">
- {{ item.alarmContent }}
- </div>
- </div>
- </div>
- <!-- 报警级别标识 -->
- <div class="alarm-level">
- {{ $t(`alarmHistory.level${item.level}`) }}
- </div>
- </div>
- </div>
- </van-list>
- </div>
- <!-- 历史搜索组件 -->
- <history-search ref="searchRef" @search="search($event)" />
- </div>
- </template>
- <script>
- import { onMounted, reactive, ref } from "vue";
- import sHeader from "@/components/SimpleHeader";
- import historySearch from "./historySearch.vue";
- import { getAlarmHistoryList, getEquipmentList } from "@/service/alarmHistory";
- import { getLoginUser } from "@/common/js/utils";
- import dateUtil from "@/utils/dateUtil";
- import { showFailToast } from "vant";
- import { useI18n } from "vue-i18n";
- import { styleUrl } from "../../common/js/utils";
- export default {
- components: { sHeader, historySearch },
- setup() {
- const { t } = useI18n();
- const user = getLoginUser();
- const searchRef = ref(null);
- const loading = ref(false); // 加载状态
- const error = ref(false); // 错误状态
- const finished = ref(false); // 结束翻页状态
- const alarmHistoryList = ref([]); // 列表集合
- const alarmHistoryTotal = ref(0); // 列表总数
- let searchParams = reactive({
- adminId: "", // 当前登录账户的id
- clientId: "", // 设备编号
- current: 1, // 当前页
- size: 20, // 页大小
- name: "", // 机器名称
- // startDate: null, // 开始时间
- // endDate: null, // 结束时间
- });
- const equipmentSourceList = ref([]); // 列表集合
- // 初始化页面获取列表
- onMounted(async () => {
- // 加载样式
- styleUrl("alarmHistory");
- getDeviceListFun();
- if (user) {
- searchParams.adminId = user.id;
- searchGetList();
- }
- });
- // 获取设备列表
- const getDeviceListFun = async () => {
- const { data } = await getEquipmentList({ adminId: user.id });
- if (data.code === "00000") {
- equipmentSourceList.value = data.data;
- equipmentSourceList.value.unshift({
- name: t("alarmHistory.allDevices"),
- id: null,
- });
- console.log(equipmentSourceList);
- }
- };
- // 搜索弹窗触发搜索
- const search = (data) => {
- searchParams = Object.assign(searchParams, data);
- searchGetList();
- };
- // 查询列表
- const searchGetList = () => {
- alarmHistoryList.value = [];
- searchParams.current = 1;
- getList();
- };
- // 滚动加载
- const onLoad = () => {
- if (!finished.value) {
- searchParams.current = searchParams.current + 1;
- getList();
- }
- };
- // 获取报警列表数据
- const getList = async () => {
- const { data } = await getAlarmHistoryList(
- Object.assign({}, searchParams)
- );
- if (data.code === "00000") {
- // 列表值叠加
- alarmHistoryList.value = alarmHistoryList.value.concat(
- data.data.records
- );
- alarmHistoryTotal.value = data.data.total;
- if (alarmHistoryList.value.length === data.data.total) {
- finished.value = true;
- }
- loading.value = false;
- } else {
- showFailToast(data.message);
- }
- };
- const showDateTime = (date) => {
- if (!date) {
- return "";
- }
- const currentDate = new Date(
- dateUtil.formateDate(new Date(date), "yyyy/MM/dd hh:mm:ss")
- );
- return dateUtil.timeZoneDate(currentDate);
- };
- const showDeviceName = (id) => {
- const device = equipmentSourceList.value.filter((v) => v.id === id);
- if (device && device.length > 0) {
- return device[0].name;
- }
- return id;
- };
- // 搜索点击
- const searchClick = () => {
- searchRef.value.showSearch();
- };
- const getAlarmLevelClass = (level) => {
- return `level-${level}`;
- };
- return {
- search,
- searchRef,
- searchClick,
- loading,
- error,
- finished,
- onLoad,
- alarmHistoryList,
- alarmHistoryTotal,
- showDateTime,
- showDeviceName,
- getAlarmLevelClass,
- };
- },
- };
- </script>
- <style lang="less" scoped>
- @theme-color: #4d6add;
- @light-theme: lighten(@theme-color, 20%);
- @text-color: #333;
- @light-text: #666;
- @border-color: #e6e8f0;
- @card-shadow: 0 4px 16px rgba(77, 106, 221, 0.1);
- @highlight-shadow: 0 4px 20px rgba(77, 106, 221, 0.25);
- .alarm-history-container {
- display: flex;
- flex-direction: column;
- height: 100vh;
- background-color: #f5f8ff;
- }
- .alarm-history-content {
- flex: 1;
- padding: 16px;
- overflow-y: auto;
- }
- /* 顶部筛选统计卡片(优化版) */
- .stats-filter-card {
- display: flex;
- justify-content: space-between;
- background: linear-gradient(135deg, @theme-color, #6878eb);
- border-radius: 16px;
- padding: 16px;
- box-shadow: @highlight-shadow;
- margin-bottom: 16px;
- color: white;
- }
- .stats-area {
- display: flex;
- align-items: center;
- flex: 1;
- .stats-icon-box {
- width: 35px;
- height: 35px;
- background: rgba(255, 255, 255, 0.2);
- border-radius: 12px;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 10px;
- }
- .stats-content {
- .stats-title {
- font-size: 14px;
- opacity: 0.9;
- margin-bottom: 4px;
- }
- .stats-value {
- font-size: 20px;
- font-weight: bold;
- display: flex;
- align-items: flex-end;
- .highlight-number {
- font-size: 18px;
- margin: 0 4px;
- }
- }
- }
- }
- .filter-area {
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
- .filter-btn {
- display: flex;
- align-items: center;
- background: rgba(255, 255, 255, 0.2);
- border-radius: 18px;
- padding: 6px 15px 6px 12px;
- font-size: 13px;
- cursor: pointer;
- transition: all 0.3s;
- margin-bottom: 10px;
- &:last-child {
- margin-bottom: 0;
- }
- .van-icon {
- margin-right: 8px;
- }
- &:hover {
- background: rgba(255, 255, 255, 0.3);
- transform: translateY(-2px);
- }
- &:active {
- transform: translateY(0);
- }
- }
- /* 报警历史卡片 */
- .history-list {
- display: grid;
- grid-template-columns: 1fr;
- gap: 16px;
- }
- .history-card {
- background-color: #fff;
- border-radius: 12px;
- padding: 16px;
- box-shadow: @card-shadow;
- position: relative;
- overflow: hidden;
- &.level-5 {
- border-left: 4px solid #ff5252;
- .alarm-level {
- background: linear-gradient(to right, #ff5252, #ff7b7b);
- }
- }
- &.level-4 {
- border-left: 4px solid #ff9800;
- .alarm-level {
- background: linear-gradient(to right, #ff9800, #ffb74d);
- }
- }
- &.level-3 {
- border-left: 4px solid #F1C40F;
- .alarm-level {
- background: linear-gradient(to right, #F1C40F, #e7d488);
- }
- }
- &.level-2 {
- border-left: 4px solid #4caf50;
- .alarm-level {
- background: linear-gradient(to right, #4caf50, #81c784);
- }
- }
- &.level-1 {
- border-left: 4px solid #3498DB;
- .alarm-level {
- background: linear-gradient(to right, #3498DB, #84b3d3);
- }
- }
- }
- .card-header {
- padding-bottom: 12px;
- border-bottom: 1px solid @border-color;
- margin-bottom: 12px;
- }
- .card-title {
- font-weight: bold;
- font-size: 16px;
- color: @text-color;
- max-width: 70%;
- }
- .card-time {
- font-size: 12px;
- color: @light-text;
- }
- .info-row {
- display: flex;
- margin-bottom: 10px;
- font-size: 14px;
- &:last-child {
- margin-bottom: 0;
- }
- }
- .info-label {
- color: @light-text;
- min-width: 100px;
- }
- .info-value {
- color: @text-color;
- flex: 1;
- }
- .badge-id {
- background-color: lighten(@theme-color, 45%);
- color: darken(@theme-color, 10%);
- border-radius: 4px;
- display: inline-block;
- font-weight: bold;
- font-size: 13px;
- }
- .alarm-content {
- font-weight: 500;
- }
- .alarm-level {
- position: absolute;
- top: 0;
- right: 0;
- background: @theme-color;
- color: white;
- font-size: 12px;
- padding: 4px 12px;
- border-bottom-left-radius: 8px;
- font-weight: 500;
- }
- .empty-state {
- text-align: center;
- padding: 40px 20px;
- .empty-icon {
- font-size: 60px;
- color: #d1d8f0;
- margin-bottom: 15px;
- }
- p {
- font-size: 16px;
- color: @light-text;
- }
- }
- /* 筛选菜单弹出框 */
- .filter-popup {
- max-height: 80vh;
- padding: 20px;
- .popup-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding-bottom: 15px;
- border-bottom: 1px solid #f0f0f0;
- margin-bottom: 20px;
- h3 {
- font-size: 18px;
- font-weight: 600;
- color: @text-color;
- margin: 0;
- }
- .van-icon {
- font-size: 20px;
- color: #999;
- }
- }
- .filter-group {
- margin-bottom: 20px;
- h4 {
- font-size: 15px;
- color: @text-color;
- font-weight: 500;
- margin-bottom: 12px;
- }
- .van-checkbox {
- margin-bottom: 12px;
- &:last-child {
- margin-bottom: 0;
- }
- }
- }
- .date-range {
- display: flex;
- align-items: center;
- .van-field {
- flex: 1;
- background: #f9f9f9;
- border-radius: 8px;
- padding: 10px 15px;
- }
- .date-divider {
- margin: 0 10px;
- color: #999;
- }
- }
- .filter-actions {
- display: flex;
- justify-content: space-between;
- margin-top: 20px;
- .van-button {
- flex: 1;
- border-radius: 20px;
- height: 44px;
- font-weight: 500;
- &:first-child {
- margin-right: 15px;
- }
- }
- }
- }
- /* 动画效果 */
- @keyframes fadeIn {
- from {
- opacity: 0;
- transform: translateY(10px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
- }
- .history-card {
- animation: fadeIn 0.3s ease-out;
- animation-fill-mode: both;
- @delay: 0.1s;
- @delay-increment: 0.05s;
- &:nth-child(1) {
- animation-delay: 0.05s;
- }
- &:nth-child(2) {
- animation-delay: 0.1s;
- }
- &:nth-child(3) {
- animation-delay: 0.15s;
- }
- &:nth-child(4) {
- animation-delay: 0.2s;
- }
- &:nth-child(5) {
- animation-delay: 0.25s;
- }
- &:nth-child(6) {
- animation-delay: 0.3s;
- }
- }
- /* 响应式布局 */
- @media (max-width: 480px) {
- .stats-filter-card {
- flex-direction: column;
- gap: 12px;
- }
- .filter-area {
- flex-direction: row;
- justify-content: flex-end;
- gap: 10px;
- .filter-btn {
- margin-bottom: 0;
- }
- }
- .time-filter-group .van-button {
- padding: 0 16px;
- height: 30px;
- }
- }
- </style>
|