فهرست منبع

feat:"添加MQTT管理功能"

soobin 10 ماه پیش
والد
کامیت
1d73bfbf79

BIN
src/assets/home/M21.png


+ 1 - 0
src/assets/language/en.json

@@ -1078,6 +1078,7 @@
     "relationAdmin": "Associate superior",
     "apkMan": "Apk management",
     "merchantMan": "Merchant management",
+    "mqtt": "MQTT",
     "accountOperation": "Account operation",
     "modifyRole": "Modify Role",
     "whole": "whole",

+ 1 - 0
src/assets/language/ja.json

@@ -1085,6 +1085,7 @@
         "relationAdmin": "関連上位",
         "apkMan": "APK管理",
         "merchantMan": "加盟店管理",
+        "mqtt": "MQTT",
         "accountOperation": "アカウント操作",
         "modifyRole": "役割を変更",
         "whole": "全体",

+ 16 - 0
src/assets/language/zh.json

@@ -1094,6 +1094,7 @@
     "pleaseSelectARole": "请选择角色",
     "pleaseSelectAPattern": "请选择花型",
     "deviceManagement": "设备管理",
+    "mqtt": "MQTT管理",
     "deviceView": "设备查看",
     "distributionSettings": "分销设置",
     "alarmHistory": "报警历史",
@@ -1133,6 +1134,21 @@
     "illThinkAboutItAgain": "我再想想",
     "confirm": "确认"
   },
+  "mqtt": {
+    "title": "MQTT管理",
+    "message": "消息管理",
+    "sendMessage": "发送消息",
+    "topic": "主题",
+    "topicPlaceholder": "请输入主题",
+    "qos": "QoS等级",
+    "send": "发送",
+    "messageContent": "消息内容",
+    "messageContentPlaceholder": "请输入消息内容",
+    "sendSuccess": "发送成功",
+    "sendFailed": "发送失败",
+    "messageList": "消息列表",
+    "receiveTime": "接收时间"
+  },
   "huifuMch": {
     "standbyWithdrawalAccountNo": "备用提现账号",
     "merchantType": "商户类型",

BIN
src/assets/mqtt/message.png


+ 1 - 0
src/common/js/utils.js

@@ -34,6 +34,7 @@ export const $M_Menus = {
   // "M18":t("role.labelMan"),//标签管理
   "M19": t("role.apkMan"),//apk管理
   // "M20":t("role.merchantMan"),//商户管理
+  "M21": t("role.mqtt"),//MQTT
 }
 // 判断值是否是数字 true:数值型的,false:非数值型
 export const $M_IsNaN = (num) => {

+ 14 - 0
src/router/index.js

@@ -583,6 +583,20 @@ const router = createRouter({
       component: () => import("@/views/payWechat"),
       meta: { index: 1, noLogin: true },
     },
+    // MQTT
+    {
+      path: "/mqtt",
+      name: "mqtt",
+      component: () => import("@/views/mqtt/index"),
+      meta: { index: 1 },
+    },
+    // MQTT消息管理
+    {
+      path: "/mqttMessage",
+      name: "mqttMessage",
+      component: () => import("@/views/mqtt/message/index"),
+      meta: { index: 1 },
+    },
   ],
 });
 // 路由守卫处理

+ 11 - 0
src/service/mqtt/index.js

@@ -0,0 +1,11 @@
+import axios from "../../utils/axios";
+
+// MQTT发送消息
+export function sendMqttMessage(params) {
+  return axios.post(`/SZWL-SERVER/mqtt/sendMsg`, params);
+}
+
+// 获取接收消息列表
+export function getMsgList(params) {
+  return axios.post(`/SZWL-SERVER/mqtt/getMsgList`, params);
+}

+ 54 - 0
src/styles/mqtt/index.less

@@ -0,0 +1,54 @@
+.taskMessagePage {
+    width: 100%;
+  
+    .taskMessageBox {
+      width: 100%;
+      height: calc(100% - 60px);
+      overflow: auto;
+  
+      .taskListRow {
+        height: 53px;
+        flex-wrap: wrap;
+  
+        .taskIcon {
+          width: 13%;
+          height: 100%;
+          position: relative;
+  
+          &.messageIcon::after {
+            content: '';
+            position: absolute;
+            background: #fff url('../../assets/mqtt/message.png') top center no-repeat;
+            background-size: 100%;
+            width: 0.6rem;
+            height: 0.6rem;
+            right: 0.18rem;
+            top: 0.45rem;
+          }
+  
+        }
+  
+        .taskRight {
+          width: 87%;
+          height: 100%;
+          position: relative;
+          border-bottom: 1px solid #e7eaf7;
+  
+          &::after {
+            content: '';
+            position: absolute;
+            width: 6px;
+            height: 12px;
+            background: url('../../assets/accountOperation/right.png') top center no-repeat;
+            background-size: 100%;
+            right: 0.55rem;
+            top: 0.5rem;
+          }
+  
+          .taskTitle {
+            line-height: 53px;
+          }
+        }
+      }
+    }
+  }

+ 11 - 0
src/views/home/index.vue

@@ -662,6 +662,7 @@ export default {
         return item === "M4";
       })
 
+
       // 查询是否有订单导出权限
       // const isOrderExport = user.menuCodeList.some((item) => {
       //   return item === "M9";
@@ -683,6 +684,13 @@ export default {
         // }
       }
 
+      if (user.type === 0) {
+        pushToolList.value.push({
+          label: t("role.mqtt"),
+          value: "M21"
+        });
+      }
+
       // 如果没有账号权限
       if (!isAccount) {
         //  如果是公司人type=0,要把账号权限添加上去
@@ -757,6 +765,9 @@ export default {
         case "M20":
           router.push({ path: "/merchantManage" });
           break;
+        case "M21":
+          router.push({ path: "/mqtt" });
+          break;
       }
     };
 

+ 42 - 0
src/views/mqtt/index.vue

@@ -0,0 +1,42 @@
+<template>
+    <!-- MQTT管理 -->
+    <div class="taskMessagePage flex-col">
+        <s-header :name="$t('mqtt.title')" :noback="false"></s-header>
+        <div class="taskMessageBox flex-col">
+            <!-- 消息管理 -->
+            <div class="taskListRow flex-col" @click="pushPageList('/mqttMessage')">
+                <div class="taskIcon messageIcon"></div>
+                <div class="taskRight">
+                    <div class="taskTitle">{{ $t('mqtt.message') }}</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import { onMounted } from 'vue';
+import sHeader from "../../components/SimpleHeader";
+import { styleUrl } from "../../common/js/utils";
+import { useRouter } from "vue-router";
+
+export default {
+    components: { sHeader },
+    setup() {
+        styleUrl('mqtt');
+        const router = useRouter();
+        // 初始化页面获取列表
+        const pushPageList = (url) => {
+            router.push(url);
+        };
+        onMounted(async () => { });
+        return {
+            pushPageList,
+        };
+    }
+};
+</script>
+
+<style lang="less" scoped>
+@import "../../common/style/common.less";
+</style>

+ 294 - 0
src/views/mqtt/message/index.vue

@@ -0,0 +1,294 @@
+<template>
+    <!-- MQTT管理 -->
+    <div class="flex-col">
+        <s-header :name="$t('mqtt.message')" :noback="false"></s-header>
+        <div class="outer flex-col justify-center ">
+            <div class="l-flex-RC">
+                <div class="outer1 flex-col"></div>
+                <div class="TextGroup flex-col">
+                    <span class="txt">{{ $t("mqtt.sendMessage") }}</span>
+                </div>
+            </div>
+        </div>
+        <van-form @submit="sendMessage">
+            <van-cell-group inset>
+                <van-field v-model="params.topic" :label="$t('mqtt.topic')" :placeholder="$t('mqtt.topicPlaceholder')"
+                    :rules="[{ required: true, message: $t('mqtt.topicPlaceholder') }]" />
+                <van-field name="radio" :label="$t('mqtt.qos')">
+                    <template #input>
+                        <van-radio-group v-model="params.qos" direction="horizontal">
+                            <van-radio :name="0">0</van-radio>
+                            <van-radio :name="1">1</van-radio>
+                            <van-radio :name="2">2</van-radio>
+                        </van-radio-group>
+                    </template>
+                </van-field>
+                <van-field v-model="params.message" rows="5" autosize :label="$t('mqtt.messageContent')" type="textarea" :placeholder="$t('mqtt.messageContentPlaceholder')"
+                    :rules="[{ required: true, message: $t('mqtt.messageContentPlaceholder') }]" />
+                <br>
+            </van-cell-group>
+            <div style="margin: 10px 100px;">
+                <van-button round block type="primary" native-type="submit">
+                    {{ $t('mqtt.send') }}
+                </van-button>
+            </div>
+        </van-form>
+        <div class="taskMessageBox flex-col">
+            <van-list v-model:loading="loading" v-model:error="error" :error-text="$t('common.reqFailClkReload')"
+                :finished="finished" :finished-text="$t('common.noMoreTxt')" offset="300" :immediate-check="false"
+                @load="onLoad">
+                <div class="searchRow flex-row justify-between">
+                    <div class="flex-col">
+                        <div class="flex-row justify-between bd3">
+                            <div class="flex-col outer4"></div>
+                            <span class="flex-col txt2">{{ $t("mqtt.messageList") }},{{ $t('taskMessage.total')
+                                }}<span class="discountNumber">{{
+            alarmHistoryTotal
+        }}</span>{{ $t('taskMessage.recordsInTotal') }}</span>
+                        </div>
+                    </div>
+                    <!-- <div @click="noticeClk" class="main5 l-flex-RC">
+                            <img class="label2 o-mr-5" src="../../../assets/device/searchIcon.png" />
+                        </div> -->
+                </div>
+                <div class="listBox">
+                    <div v-for="(item, index) in alarmHistoryList" :key="index" class="listItem">
+                        <div class="itemBox">
+                            <div class="itemRow">
+                                <span class="itemTitle">{{ $t('mqtt.topic') }}:&nbsp;</span>
+                                {{ item.topic }}
+                            </div>
+                            <div class="itemRow">
+                                <span class="itemTitle">{{ $t('taskMessage.clientId') }}:&nbsp;</span>
+                                {{ item.clientId }}
+                            </div>
+                            <div class="itemRow">
+                                <span class="itemTitle">{{ $t('mqtt.messageContent') }}:&nbsp;</span>
+                                {{ item.message }}
+                            </div>
+                            <div class="itemRow">
+                                <span class="itemTitle">{{ $t('mqtt.receiveTime') }}:&nbsp;</span>
+                                {{ showDateTime(item.createDate) }}
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </van-list>
+        </div>
+    </div>
+</template>
+
+<script>
+import { onMounted, reactive, ref } from 'vue';
+import sHeader from "../../../components/SimpleHeader";
+import { sendMqttMessage, getMsgList } from '@/service/mqtt';
+import { showFailToast, showSuccessToast } from "vant";
+import dateUtil from "@/utils/dateUtil";
+import { useI18n } from "vue-i18n";
+
+
+export default {
+    components: { sHeader },
+    setup() {
+        const { t } = useI18n();
+        // 发送消息参数
+        const params = reactive({
+            topic: '',
+            qos: 0,
+            message: '',
+        });
+        // 发送消息
+        const sendMessage = async () => {
+            const { data } = await sendMqttMessage(params);
+            if (data.code === "00000") {
+                showSuccessToast(t("mqtt.sendSuccess"));
+            } else {
+                showFailToast(t("mqtt.sendFailed"));
+            }
+        };
+        // 查询消息参数
+        const loading = ref(false); // 加载状态
+        const error = ref(false); // 错误状态
+        const finished = ref(false); // 结束翻页状态
+        const alarmHistoryList = ref([]); // 列表集合
+        const alarmHistoryTotal = ref(0); // 列表总数
+        const searchParams = reactive({
+            topic: "", // 主题名
+            current: 1, // 当前页
+            size: 20, // 页大小
+            username: "", // 商家名称
+            startTime: "", // 开始时间
+            endTime: "", // 结束时间
+            clientId: "", // 设备编号
+        });
+        // 滚动加载
+        const onLoad = () => {
+            if (!finished.value) {
+                searchParams.current = searchParams.current + 1;
+                getList();
+            }
+        };
+        // 查询消息记录
+        const searchRecordList = () => {
+            alarmHistoryList.value = [];
+            searchParams.current = 1;
+            getList();
+        };
+        // 获取消息列表
+        const getList = async () => {
+            const { data } = await getMsgList(
+                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;
+                console.log(alarmHistoryList);
+            } else {
+                showFailToast(data.message);
+            }
+        };
+        // 格式化时间
+        const showDateTime = (date) => {
+            return date
+                ? dateUtil.formateDate(new Date(date), "yyyy/MM/dd hh:mm:ss")
+                : "";
+        };
+
+        // 初始化页面获取列表
+        onMounted(async () => {
+            // styleUrl('taskMessage');
+            searchRecordList();
+        });
+        return {
+            params,
+            sendMessage,
+            loading,
+            error,
+            finished,
+            onLoad,
+            alarmHistoryList,
+            alarmHistoryTotal,
+            showDateTime,
+        };
+    }
+};
+</script>
+
+<style lang="less" scoped>
+@import "../../../common/style/common.less";
+
+.outer {
+    background: rgba(255, 255, 255, 1) url("../../../assets/home/line.png") bottom center no-repeat;
+    background-size: 100% auto;
+    padding: 20px 20px;
+
+    .outer1 {
+        position: relative;
+        width: 15px;
+        height: 15px;
+        margin-right: 5px;
+        background: url("../../../assets/home/machineSales.png") center no-repeat;
+        background-size: 100%;
+    }
+
+    .TextGroup {
+
+        .txt {
+            overflow-wrap: break-word;
+            color: rgba(64, 77, 116, 1);
+            font-size: 0.4rem;
+            font-family: PingFangSC-Semibold;
+            text-align: left;
+            white-space: nowrap;
+            line-height: 0.4rem;
+            display: block;
+        }
+
+    }
+}
+
+.searchRow {
+    padding: 0.5rem 0.5rem;
+    background: rgba(255, 255, 255, 1) url("../../../assets/home/line.png") bottom center no-repeat;
+    background-size: 100%;
+    align-items: center;
+
+    .bd3 {
+
+
+        .outer4 {
+            width: 19px;
+            height: 19px;
+            margin-right: 5px;
+            background: url("../../../assets/taskMessage/retailIcon.png") top center no-repeat;
+            background-size: 100%;
+        }
+
+        .txt2 {
+            overflow-wrap: break-word;
+            color: rgba(64, 77, 116, 1);
+            font-size: 0.4rem;
+            font-family: PingFangSC-Semibold;
+            text-align: left;
+            white-space: nowrap;
+            line-height: 0.4rem;
+            display: block;
+
+            .discountNumber {
+                font-size: 18px;
+                color: #df5e4c;
+            }
+        }
+    }
+
+    .label3 {
+        color: #4d6add;
+    }
+
+    .main5 {
+        width: auto;
+
+        .label2 {
+            width: 0.5rem;
+            height: 0.5rem;
+            margin-right: 5px;
+            cursor: pointer;
+        }
+    }
+}
+
+.listBox {
+    .listItem {
+        width: 100%;
+        background: url("../../../assets/home/line.png") bottom center no-repeat;
+        background-size: 100%;
+        position: relative;
+        display: inline-block;
+
+        .itemBox {
+            margin: 20px 30px;
+            line-height: 20px;
+
+            .itemRow {
+                width: 100%;
+            }
+
+            .itemTitle {
+                color: #8787a6;
+                font-size: 13px;
+            }
+
+            .discount {
+                padding-left: 2em;
+            }
+        }
+    }
+}
+</style>

+ 2 - 2
src/views/taskMessage/refundReminder/index.vue

@@ -43,8 +43,8 @@
                                 {{ item.remark }}
                             </div>
                             <div class="itemRow" style="display: flex; justify-content: flex-end">
-                                <span v-if="item.status === 0 && user.type > 1" style="color: #FFA500"> {{
-            $t('taskMessage.toBeApproved') }}</span>
+                                <span v-if="item.status === 0" style="color: #FFA500"> {{
+            $t('taskMessage.sendWait') }}</span>
                                 <span v-if="item.status === 1" style="color: #1989fa"> {{ $t('taskMessage.sendSucess')
                                     }}</span>
                                 <span v-if="item.checkType === 2" style="color: #ff0033"> {{ $t('taskMessage.sendFail')