Browse Source

feat(release): mqtt: update user,auth

Yi 1 year ago
parent
commit
06b1a744c2

+ 15 - 4
src/constants/business.ts

@@ -191,14 +191,25 @@ export const MqttPastureOptions: Common.OptionWithKey<ApiMqttAuth.IsShowKey>[] =
 ];
 
 /** 主题动作 */
-export const topicAccessLabel: Record<ApiMqttUser.IsAccessKey, string> = {
+export const userTopicAccessLabel: Record<ApiMqttUser.IsAccessKey, string> = {
   1: '发布',
   2: '订阅',
   3: '发布订阅'
 };
 
-export const TopicAccessOptions: Common.OptionWithKey<ApiMqttUser.IsAccessKey>[] = [
+export const UserTopicAccessOptions: Common.OptionWithKey<ApiMqttUser.IsAccessKey>[] = [
+  { value: 1, label: userTopicAccessLabel['1'] },
+  { value: 2, label: userTopicAccessLabel['2'] },
+  { value: 3, label: userTopicAccessLabel['3'] }
+];
+
+/** 主题动作 */
+export const topicAccessLabel: Record<ApiMqttTopic.AccessKey, string> = {
+  1: '发布',
+  2: '订阅'
+};
+
+export const TopicAccessOptions: Common.OptionWithKey<ApiMqttTopic.AccessKey>[] = [
   { value: 1, label: topicAccessLabel['1'] },
-  { value: 2, label: topicAccessLabel['2'] },
-  { value: 3, label: topicAccessLabel['3'] }
+  { value: 2, label: topicAccessLabel['2'] }
 ];

+ 1 - 1
src/locales/lang/zh-cn.ts

@@ -3,7 +3,7 @@ import type { LocaleMessages } from 'vue-i18n';
 const locale: LocaleMessages<I18nType.Schema> = {
   message: {
     system: {
-      title: 'Copartner事件驱动系统'
+      title: 'Copartner后台系统'
     },
     routes: {
       dashboard: {

+ 2 - 0
src/router/modules/about.ts

@@ -1,3 +1,4 @@
+/*
 const about1: AuthRoute.Route = {
   name: 'about',
   path: '/about',
@@ -14,3 +15,4 @@ const about1: AuthRoute.Route = {
 };
 
 export default about1;
+*/

+ 2 - 0
src/router/modules/auth-demo.ts

@@ -1,3 +1,4 @@
+/*
 const authDemo: AuthRoute.Route = {
   name: 'auth-demo',
   path: '/auth-demo',
@@ -33,3 +34,4 @@ const authDemo: AuthRoute.Route = {
 };
 
 export default authDemo;
+*/

+ 2 - 1
src/router/modules/background.ts

@@ -1,4 +1,4 @@
-const background: AuthRoute.Route = {
+/* const background: AuthRoute.Route = {
   name: 'background',
   path: '/background',
   component: 'basic',
@@ -52,3 +52,4 @@ const background: AuthRoute.Route = {
 };
 
 export default background;
+*/

+ 2 - 0
src/router/modules/component.ts

@@ -1,3 +1,4 @@
+/*
 const component: AuthRoute.Route = {
   name: 'component',
   path: '/component',
@@ -42,3 +43,4 @@ const component: AuthRoute.Route = {
 };
 
 export default component;
+*/

+ 2 - 0
src/router/modules/document.ts

@@ -1,3 +1,4 @@
+/*
 const document: AuthRoute.Route = {
   name: 'document',
   path: '/document',
@@ -62,3 +63,4 @@ const document: AuthRoute.Route = {
 };
 
 export default document;
+*/

+ 2 - 0
src/router/modules/exception.ts

@@ -1,3 +1,4 @@
+/*
 const exception: AuthRoute.Route = {
   name: 'exception',
   path: '/exception',
@@ -42,3 +43,4 @@ const exception: AuthRoute.Route = {
 };
 
 export default exception;
+*/

+ 2 - 0
src/router/modules/function.ts

@@ -1,3 +1,4 @@
+/*
 const functionRoute: AuthRoute.Route = {
   name: 'function',
   path: '/function',
@@ -47,3 +48,4 @@ const functionRoute: AuthRoute.Route = {
 };
 
 export default functionRoute;
+*/

+ 2 - 0
src/router/modules/management.ts

@@ -1,3 +1,4 @@
+/*
 const management: AuthRoute.Route = {
   name: 'management',
   path: '/management',
@@ -52,3 +53,4 @@ const management: AuthRoute.Route = {
 };
 
 export default management;
+*/

+ 0 - 10
src/router/modules/mqtt.ts

@@ -13,16 +13,6 @@ const mqtt: AuthRoute.Route = {
         icon: 'icon-park-outline:workbench'
       }
     },
-    {
-      name: 'mqtt_user',
-      path: '/mqtt/user',
-      component: 'self',
-      meta: {
-        title: '用户管理',
-        requiresAuth: true,
-        icon: 'ic:round-manage-accounts'
-      }
-    },
     {
       name: 'mqtt_topic',
       path: '/mqtt/topic',

+ 2 - 0
src/router/modules/multi-menu.ts

@@ -1,3 +1,4 @@
+/*
 const multiMenu: AuthRoute.Route = {
   name: 'multi-menu',
   path: '/multi-menu',
@@ -54,3 +55,4 @@ const multiMenu: AuthRoute.Route = {
 };
 
 export default multiMenu;
+*/

+ 2 - 0
src/router/modules/plugin.ts

@@ -1,3 +1,4 @@
+/*
 const plugin: AuthRoute.Route = {
   name: 'plugin',
   path: '/plugin',
@@ -134,3 +135,4 @@ const plugin: AuthRoute.Route = {
 };
 
 export default plugin;
+*/

+ 18 - 7
src/service/api/mqtt.ts

@@ -12,10 +12,15 @@ import {
 import { backgroundRequest } from '../request';
 
 /** 获取用户鉴权列表 */
-export const fetchMqttAuthList = async (page: number | undefined, pageSize: number | undefined, topic: string) => {
-  const data = await backgroundRequest.post<Mqtt.Auth[] | null>(`/mqtt/auth/list?page=${page}&page_size=${pageSize}`, {
-    topic
-  });
+export const fetchMqttAuthList = async (
+  page: number | undefined,
+  pageSize: number | undefined,
+  params: Mqtt.SearchAuth | null
+) => {
+  const data = await backgroundRequest.post<Mqtt.Auth[] | null>(
+    `/mqtt/auth/list?page=${page}&page_size=${pageSize}`,
+    params
+  );
   return adapter(adapterOfMqttAuthList, data);
 };
 
@@ -35,7 +40,11 @@ export const mqttAuthEdit = (param: Mqtt.Auth) => {
 };
 
 /** 获取topic列表 */
-export const fetchMqttTopicList = async (page: number, pageSize: number, topic_name: string) => {
+export const fetchMqttTopicList = async (
+  page: number | undefined,
+  pageSize: number | undefined,
+  topic_name: string
+) => {
   const data = await backgroundRequest.post<Mqtt.Topic[] | null>(
     `/mqtt/topic/list?page=${page}&page_size=${pageSize}`,
     {
@@ -101,8 +110,10 @@ export const pastureEnumList = async () => {
   return adapter(adapterOfMqttPastureEnumList, data);
 };
 
-export const topicEnumList = async () => {
-  const data = await backgroundRequest.get<Common.OptionWithKey<any>[] | null>('/mqtt/topic/enum/list');
+export const topicEnumList = async (access: number | null) => {
+  const data = await backgroundRequest.get<Common.OptionWithKey<any>[] | null>(
+    `/mqtt/topic/enum/list?access=${access}`
+  );
   return adapter(adapterOfMqttTopicEnumList, data);
 };
 

+ 1 - 0
src/typings/business.d.ts

@@ -161,6 +161,7 @@ declare namespace ApiMqttTopic {
    * 2: 否
    */
   type IsShowKey = NonNullable<Topic['is_show']>;
+  type AccessKey = NonNullable<Topic['access']>;
 }
 
 declare namespace ApiMqttUser {

+ 11 - 12
src/typings/mqtt.d.ts

@@ -1,15 +1,14 @@
 declare namespace Mqtt {
   interface Auth {
-    /** id */
     id: number;
-    /** 字段名 */
     client_id: string | null;
     mount_point: string | null;
     user_name: string | null;
     password: string;
     pasture_id: number | null;
     pasture_name: string | null;
-    topic_ids: string | null;
+    publish_topic_ids: [] | null;
+    subscribe_topic_ids: [] | null;
     access: number | null;
     publish_acl: string | null;
     subscribe_acl: string | null;
@@ -18,10 +17,15 @@ declare namespace Mqtt {
     updated_at_format: string | null;
   }
 
+  interface SearchAuth {
+    pasture_name: string | null;
+    user_name: string | null;
+    publish_topic_name: string | null;
+    subscribe_topic_name: string | null;
+  }
+
   interface User {
-    /** id */
     id: number;
-    /** 字段名 */
     user_name: string | null;
     password: string;
     client_id: string | null;
@@ -34,22 +38,19 @@ declare namespace Mqtt {
   }
 
   interface Topic {
-    /** id */
     id: number;
     category_id: number | null;
     category_name: string | null;
-    /** 字段名 */
     topic_name: string | null;
     topic_template: string | null;
+    access: number | null;
+    is_show: number | null;
     created_at_format: string | null;
     updated_at_format: string | null;
-    is_show: number | null;
   }
 
   interface Pasture {
-    /** id */
     id: number;
-    /** 字段名 */
     name: string | null;
     short_name: string | null;
     address: string | null;
@@ -61,9 +62,7 @@ declare namespace Mqtt {
   }
 
   interface Category {
-    /** id */
     id: number;
-    /** 分类名称 */
     name: string | null;
     is_show: number | null;
     created_at_format: string | null;

+ 2 - 4
src/typings/page-route.d.ts

@@ -60,9 +60,8 @@ declare namespace PageRoute {
     | 'mqtt'
     | 'mqtt_authentication'
     | 'mqtt_pasture'
-    | 'mqtt_topic'
     | 'mqtt_category'
-    | 'mqtt_user'
+    | 'mqtt_topic'
     | 'multi-menu'
     | 'multi-menu_first'
     | 'multi-menu_first_second-new'
@@ -123,9 +122,8 @@ declare namespace PageRoute {
     | 'management_user'
     | 'mqtt_authentication'
     | 'mqtt_pasture'
-    | 'mqtt_topic'
     | 'mqtt_category'
-    | 'mqtt_user'
+    | 'mqtt_topic'
     | 'multi-menu_first_second-new_third'
     | 'multi-menu_first_second'
     | 'plugin_charts_antv'

+ 1 - 2
src/views/index.ts

@@ -39,9 +39,8 @@ export const views: Record<
   management_user: () => import('./management/user/index.vue'),
   mqtt_authentication: () => import('./mqtt/authentication/index.vue'),
   mqtt_pasture: () => import('./mqtt/pasture/index.vue'),
-  mqtt_topic: () => import('./mqtt/topic/index.vue'),
   mqtt_category: () => import('./mqtt/topic-category/index.vue'),
-  mqtt_user: () => import('./mqtt/user/index.vue'),
+  mqtt_topic: () => import('./mqtt/topic/index.vue'),
   'multi-menu_first_second-new_third': () => import('./multi-menu/first/second-new/third/index.vue'),
   'multi-menu_first_second': () => import('./multi-menu/first/second/index.vue'),
   plugin_charts_antv: () => import('./plugin/charts/antv/index.vue'),

+ 13 - 12
src/views/mqtt/authentication/components/table-action-modal.vue

@@ -14,13 +14,11 @@
         <n-form-item-grid-item :span="18" label="用户密码" size="large" path="user_name">
           <n-input v-model:value="formModel.password" type="password" />
         </n-form-item-grid-item>
-        <n-form-item-grid-item :span="18" label="主题名(topic)" size="large" path="topic_ids">
-          <n-select v-model:value="formModel.topic_ids" multiple :options="topicEnumListData" />
+        <n-form-item-grid-item :span="18" label="订阅主题名(topic)" size="large" path="topic_ids">
+          <n-select v-model:value="formModel.subscribe_topic_ids" multiple :options="subscribeTopicEnumListData" />
         </n-form-item-grid-item>
-        <n-form-item-grid-item :span="20" label="主题动作" size="large" path="access">
-          <n-radio-group v-model:value="formModel.access">
-            <n-radio v-for="item in TopicAccessOptions" :key="item.value" :value="item.value">{{ item.label }}</n-radio>
-          </n-radio-group>
+        <n-form-item-grid-item :span="18" label="发布主题名(topic)" size="large" path="topic_ids">
+          <n-select v-model:value="formModel.publish_topic_ids" multiple :options="publishTopicEnumListData" />
         </n-form-item-grid-item>
       </n-grid>
       <n-space class="w-full pt-16px" :size="24" justify="end">
@@ -34,7 +32,6 @@
 <script setup lang="ts">
 import { computed, ref, reactive, watch } from 'vue';
 import type { FormInst, FormItemRule, SelectOption } from 'naive-ui';
-import { TopicAccessOptions } from '@/constants';
 import { createRequiredFormRule } from '@/utils';
 import { mqttAuthAdd, mqttAuthEdit } from '@/service/api/mqtt';
 import { MD5 } from '@/utils/crypto';
@@ -48,9 +45,10 @@ export interface Props {
    */
   type?: 'add' | 'edit';
   /** 编辑的表格行数据 */
-  editData?: Mqtt.User | null;
+  editData?: Mqtt.Auth | null;
   pastureEnumListData: SelectOption[];
-  topicEnumListData: SelectOption[];
+  subscribeTopicEnumListData: SelectOption[];
+  publishTopicEnumListData: SelectOption[];
 }
 
 export type ModalType = NonNullable<Props['type']>;
@@ -101,7 +99,8 @@ type FormModel = Pick<
   | 'user_name'
   | 'password'
   | 'client_id'
-  | 'topic_ids'
+  | 'publish_topic_ids'
+  | 'subscribe_topic_ids'
   | 'publish_acl'
   | 'subscribe_acl'
   | 'access'
@@ -117,7 +116,8 @@ const rules: Record<keyof FormModel, FormItemRule | FormItemRule[]> = {
   user_name: createRequiredFormRule('请输入用户名称'),
   password: createRequiredFormRule('请输入用户密码'),
   client_id: createRequiredFormRule('请输入客户端id'),
-  topic_ids: createRequiredFormRule('请选择topic模板'),
+  publish_topic_ids: createRequiredFormRule('请选择topic模板'),
+  subscribe_topic_ids: createRequiredFormRule('请选择topic模板'),
   access: createRequiredFormRule('请选择topic权限'),
   is_show: createRequiredFormRule(),
   mount_point: createRequiredFormRule(),
@@ -138,7 +138,8 @@ function createDefaultFormModel(): FormModel {
     user_name: '',
     password: '',
     client_id: '',
-    topic_ids: '',
+    publish_topic_ids: [],
+    subscribe_topic_ids: [],
     access: 0,
     is_show: 1,
     publish_acl: '',

+ 45 - 19
src/views/mqtt/authentication/index.vue

@@ -10,7 +10,10 @@
         </n-space>
         <n-space align="center" :size="18">
           <n-input-group>
-            <n-input v-model:value="topic" />
+            <n-input v-model:value="formValue.subscribe_topic_name" placeholder="输入订阅主题名称" />
+            <n-input v-model:value="formValue.publish_topic_name" placeholder="输入发布主题名称" />
+            <n-input v-model:value="formValue.user_name" placeholder="输入用户姓名" />
+            <n-input v-model:value="formValue.pasture_name" placeholder="输入牧场名称" />
             <n-button type="primary" @click="handleSearch">搜索</n-button>
           </n-input-group>
           <n-button size="small" type="primary" @click="getTableData">
@@ -25,7 +28,8 @@
         :type="modalType"
         :edit-data="editData"
         :pasture-enum-list-data="pastureEnumListData"
-        :topic-enum-list-data="topicEnumListData"
+        :subscribe-topic-enum-list-data="subscribeTopicEnumListData"
+        :publish-topic-enum-list-data="publishTopicEnumListData"
       />
     </n-card>
   </div>
@@ -44,19 +48,30 @@ import type { ModalType } from '../authentication/components/table-action-modal.
 
 const { loading, startLoading, endLoading } = useLoading(false);
 const { bool: visible, setTrue: openModal } = useBoolean();
-const topic = ref('');
+const formValue = ref<Mqtt.SearchAuth>({
+  publish_topic_name: '',
+  subscribe_topic_name: '',
+  pasture_name: '',
+  user_name: ''
+});
+
 const tableData = ref<ApiMqttAuth.Auth[]>([]);
 const editData = ref<Mqtt.Auth | null>(null);
 const modalType = ref<ModalType>('add');
 const pastureEnumListData = ref<SelectOption[]>([]);
-const topicEnumListData = ref<SelectOption[]>([]);
+const subscribeTopicEnumListData = ref<SelectOption[]>([]);
+const publishTopicEnumListData = ref<SelectOption[]>([]);
 
 function setPastureList(data: SelectOption[]) {
   pastureEnumListData.value = data;
 }
 
-function setTopicList(data: SelectOption[]) {
-  topicEnumListData.value = data;
+function setSubscribeTopicList(data: SelectOption[]) {
+  subscribeTopicEnumListData.value = data;
+}
+
+function setPublishTopicList(data: SelectOption[]) {
+  publishTopicEnumListData.value = data;
 }
 
 function setEditData(data: Mqtt.Auth | null) {
@@ -74,7 +89,7 @@ function setModalType(type: ModalType) {
 async function getTableData() {
   startLoading();
   // eslint-disable-next-line @typescript-eslint/no-use-before-define
-  const { data } = await fetchMqttAuthList(pagination.page, pagination.pageSize, topic.value);
+  const { data } = await fetchMqttAuthList(pagination.page, pagination.pageSize, formValue.value);
   if (data) {
     setTableData(data);
     endLoading();
@@ -92,12 +107,17 @@ async function getPastureEnumList() {
   }
 }
 
-async function getTopicEnumList() {
-  const { data } = await topicEnumList();
+async function getTopicByPublishEnumList() {
+  const { data } = await topicEnumList(1);
   if (data) {
-    setTimeout(() => {
-      setTopicList(data);
-    }, 1000);
+    setPublishTopicList(data);
+  }
+}
+
+async function getTopicBySubscribeEnumList() {
+  const { data } = await topicEnumList(2);
+  if (data) {
+    setSubscribeTopicList(data);
   }
 }
 
@@ -132,13 +152,18 @@ const columns: Ref<DataTableColumns<ApiMqttAuth.Auth>> = ref([
     align: 'center'
   },
   {
-    key: 'topic_name_stings',
-    title: 'topic名称',
+    key: 'subscribe_topic_name_stings',
+    title: '订阅topic名称',
     align: 'center'
   },
   {
     key: 'subscribe_acl',
-    title: '发布topic',
+    title: '订阅topic',
+    align: 'center'
+  },
+  {
+    key: 'publish_topic_name_stings',
+    title: '发布topic名称',
     align: 'center'
   },
   {
@@ -203,11 +228,11 @@ const pagination: PaginationProps = reactive({
 });
 
 async function handleSearch() {
-  if (!topic.value) {
-    window.$message?.warning('请输入主题名称');
+  if (!formValue.value) {
+    window.$message?.warning('请输入相关名称');
   } else {
     startLoading();
-    const { data } = await fetchMqttAuthList(pagination.page, pagination.pageSize, topic.value);
+    const { data } = await fetchMqttAuthList(pagination.page, pagination.pageSize, formValue.value);
     if (data) {
       setTableData(data);
       endLoading();
@@ -244,7 +269,8 @@ function handleAddTable() {
 function init() {
   getTableData();
   getPastureEnumList();
-  getTopicEnumList();
+  getTopicByPublishEnumList();
+  getTopicBySubscribeEnumList();
 }
 
 // 初始化

+ 14 - 5
src/views/mqtt/topic/components/table-action-modal.vue

@@ -2,7 +2,7 @@
   <n-modal v-model:show="modalVisible" preset="card" :title="title" class="w-700px">
     <n-form ref="formRef" label-placement="left" :label-width="100" :model="formModel" :rules="rules">
       <n-grid :cols="48" :x-gap="18">
-        <n-form-item-grid-item :span="25" label="分类名称" path="category_id">
+        <n-form-item-grid-item :span="25" label="分类名称" size="large" path="category_id">
           <n-select v-model:value="formModel.category_id" size="large" :options="categoryEnumListData" />
         </n-form-item-grid-item>
         <n-form-item-grid-item :span="25" label="topic名称" size="large" path="topic_name">
@@ -11,6 +11,11 @@
         <n-form-item-grid-item :span="25" label="topic模板" size="large" path="topic_template">
           <n-input v-model:value="formModel.topic_template" />
         </n-form-item-grid-item>
+        <n-form-item-grid-item :span="25" label="主题动作" size="large" path="access">
+          <n-radio-group v-model:value="formModel.access">
+            <n-radio v-for="item in TopicAccessOptions" :key="item.value" :value="item.value">{{ item.label }}</n-radio>
+          </n-radio-group>
+        </n-form-item-grid-item>
       </n-grid>
       <n-space class="w-full pt-16px" :size="24" justify="end">
         <n-button class="w-72px" @click="closeModal">取消</n-button>
@@ -23,6 +28,7 @@
 <script setup lang="ts">
 import { computed, ref, reactive, watch } from 'vue';
 import type { FormInst, FormItemRule, SelectOption } from 'naive-ui';
+import { TopicAccessOptions } from '@/constants';
 import { createRequiredFormRule } from '@/utils';
 import { mqttTopicAdd, mqttTopicEdit } from '@/service/api/mqtt';
 export interface Props {
@@ -83,8 +89,9 @@ type FormModel = Pick<
   | 'category_name'
   | 'topic_name'
   | 'topic_template'
-  | 'created_at_format'
   | 'is_show'
+  | 'access'
+  | 'created_at_format'
   | 'updated_at_format'
 >;
 
@@ -94,7 +101,8 @@ const rules: Record<keyof FormModel, FormItemRule | FormItemRule[]> = {
   category_id: createRequiredFormRule('请选择分类名称'),
   category_name: createRequiredFormRule('请选择分类名称1'),
   topic_name: createRequiredFormRule('请输入主题名称'),
-  topic_template: createRequiredFormRule('请输入主题'),
+  topic_template: createRequiredFormRule('请输入topic'),
+  access: createRequiredFormRule('请选择主题动作'),
   is_show: createRequiredFormRule(),
   created_at_format: createRequiredFormRule(),
   updated_at_format: createRequiredFormRule(),
@@ -108,9 +116,10 @@ function createDefaultFormModel(): FormModel {
     category_name: '',
     topic_name: '',
     topic_template: '',
+    is_show: 1,
+    access: 1,
     created_at_format: '',
-    updated_at_format: '',
-    is_show: 1
+    updated_at_format: ''
   };
 }
 

+ 25 - 9
src/views/mqtt/topic/index.vue

@@ -10,7 +10,7 @@
         </n-space>
         <n-space align="center" :size="18">
           <n-input-group>
-            <n-input v-model:value="topicName" />
+            <n-input v-model:value="topicName" placeholder="输入主题名称" />
             <n-button type="primary" @click="handleSearch">搜索</n-button>
           </n-input-group>
           <n-button size="small" type="primary" @click="getTableData">
@@ -33,8 +33,9 @@
 <script setup lang="tsx">
 import { reactive, ref } from 'vue';
 import type { Ref } from 'vue';
-import { NButton, NSpace, NPopconfirm } from 'naive-ui';
+import { NButton, NSpace, NPopconfirm, NTag } from 'naive-ui';
 import type { DataTableColumns, PaginationProps, SelectOption } from 'naive-ui';
+import { topicAccessLabel } from '@/constants';
 import { useBoolean, useLoading } from '@/hooks';
 import { categoryEnumList, fetchMqttTopicList, mqttTopicDelete } from '@/service/api/mqtt';
 import TableActionModal from '../topic/components/table-action-modal.vue';
@@ -101,6 +102,21 @@ const columns: Ref<DataTableColumns<ApiMqttTopic.Topic>> = ref([
     title: 'topic模板',
     align: 'center'
   },
+  {
+    key: 'access',
+    title: '主题动作',
+    align: 'center',
+    render: row => {
+      if (row.access) {
+        const tagTypes: Record<ApiMqttTopic.AccessKey, NaiveUI.ThemeColor> = {
+          1: 'success',
+          2: 'info'
+        };
+        return <NTag type={tagTypes[row.access]}>{topicAccessLabel[row.access]}</NTag>;
+      }
+      return <span></span>;
+    }
+  },
   {
     key: 'created_at_format',
     title: '创建时间',
@@ -155,6 +171,7 @@ function handleEditTable(rowId: number) {
   }
   setModalType('edit');
   openModal();
+  init();
 }
 
 function handleDeleteTable(rowId: number) {
@@ -181,20 +198,19 @@ const pagination: PaginationProps = reactive({
   }
 });
 
-function handleSearch() {
+async function handleSearch() {
   if (!topicName.value) {
     window.$message?.warning('请输入主题名称');
   } else {
     startLoading();
-    /* const { data } = await fetchMqttTopicList(1, 10, topicName.value);
+    startLoading();
+    const { data } = await fetchMqttTopicList(pagination.page, pagination.pageSize, topicName.value.trim());
     if (data) {
-      setTimeout(() => {
-        setTableData(data);
-        endLoading();
-      }, 1000);
+      setTableData(data);
+      endLoading();
     } else {
       endLoading();
-    } */
+    }
   }
 }
 

+ 0 - 191
src/views/mqtt/user/components/table-action-modal.vue

@@ -1,191 +0,0 @@
-<template>
-  <n-modal v-model:show="modalVisible" preset="card" :title="title" class="w-700px">
-    <n-form ref="formRef" label-placement="left" :label-width="90" :model="formModel" :rules="rules">
-      <n-grid :cols="50" :x-gap="18">
-        <n-form-item-grid-item :span="18" label="客户端ID" size="large" path="client_id">
-          <n-input v-model:value="formModel.client_id" />
-        </n-form-item-grid-item>
-        <n-form-item-grid-item :span="18" label="牧场名称" size="large" path="pasture_id">
-          <n-select v-model:value="formModel.pasture_id" :options="pastureEnumListData" />
-        </n-form-item-grid-item>
-        <n-form-item-grid-item :span="18" label="用户名称" size="large" path="user_name">
-          <n-input v-model:value="formModel.user_name" />
-        </n-form-item-grid-item>
-        <n-form-item-grid-item :span="18" label="用户密码" size="large" path="user_name">
-          <n-input v-model:value="formModel.password" type="password" />
-        </n-form-item-grid-item>
-        <n-form-item-grid-item :span="18" label="主题名称(topic)" size="large" path="topic_ids">
-          <n-select v-model:value="formModel.topic_ids" multiple :options="topicEnumListData" />
-        </n-form-item-grid-item>
-        <n-form-item-grid-item :span="20" label="主题动作" size="large" path="access">
-          <n-radio-group v-model:value="formModel.access">
-            <n-radio v-for="item in TopicAccessOptions" :key="item.value" :value="item.value">{{ item.label }}</n-radio>
-          </n-radio-group>
-        </n-form-item-grid-item>
-      </n-grid>
-      <n-space class="w-full pt-16px" :size="24" justify="end">
-        <n-button class="w-72px" @click="closeModal">取消</n-button>
-        <n-button class="w-72px" type="primary" @click="handleSubmit">确定</n-button>
-      </n-space>
-    </n-form>
-  </n-modal>
-</template>
-
-<script setup lang="ts">
-import { computed, ref, reactive, watch } from 'vue';
-import type { FormInst, FormItemRule, SelectOption } from 'naive-ui';
-import { TopicAccessOptions } from '@/constants';
-import { createRequiredFormRule } from '@/utils';
-import { mqttUserAdd, mqttUserEdit } from '@/service/api/mqtt';
-import { MD5 } from '@/utils/crypto';
-export interface Props {
-  /** 弹窗可见性 */
-  visible: boolean;
-  /**
-   * 弹窗类型
-   * add: 新增
-   * edit: 编辑
-   */
-  type?: 'add' | 'edit';
-  /** 编辑的表格行数据 */
-  editData?: Mqtt.User | null;
-  pastureEnumListData: SelectOption[];
-  topicEnumListData: SelectOption[];
-}
-
-export type ModalType = NonNullable<Props['type']>;
-
-defineOptions({ name: 'TableActionModal' });
-
-const props = withDefaults(defineProps<Props>(), {
-  type: 'add',
-  editData: null
-});
-
-interface Emits {
-  (e: 'update:visible', visible: boolean): void;
-}
-
-const emit = defineEmits<Emits>();
-
-const modalVisible = computed({
-  get() {
-    return props.visible;
-  },
-  set(visible) {
-    emit('update:visible', visible);
-  }
-});
-
-const closeModal = () => {
-  modalVisible.value = false;
-};
-
-const titles: Record<ModalType, string> = {
-  add: '添加用户',
-  edit: '编辑用户'
-};
-
-const title = computed(() => {
-  return titles[props.type];
-});
-
-const formRef = ref<HTMLElement & FormInst>();
-
-type FormModel = Pick<
-  Mqtt.User,
-  | 'id'
-  | 'pasture_id'
-  | 'user_name'
-  | 'password'
-  | 'client_id'
-  | 'topic_ids'
-  | 'access'
-  | 'is_show'
-  | 'created_at_format'
-  | 'updated_at_format'
->;
-
-const formModel = reactive<FormModel>(createDefaultFormModel());
-
-const rules: Record<keyof FormModel, FormItemRule | FormItemRule[]> = {
-  pasture_id: createRequiredFormRule('请选择牧场'),
-  user_name: createRequiredFormRule('请输入用户名称'),
-  password: createRequiredFormRule('请输入用户密码'),
-  client_id: createRequiredFormRule('请输入客户端id'),
-  topic_ids: createRequiredFormRule('请选择topic模板'),
-  access: createRequiredFormRule('请选择topic权限'),
-  is_show: createRequiredFormRule(),
-  created_at_format: createRequiredFormRule(),
-  updated_at_format: createRequiredFormRule(),
-  id: createRequiredFormRule()
-};
-
-function createDefaultFormModel(): FormModel {
-  return {
-    id: 0,
-    pasture_id: null,
-    user_name: '',
-    password: '',
-    client_id: '',
-    topic_ids: '',
-    access: 0,
-    is_show: 1,
-    created_at_format: '',
-    updated_at_format: ''
-  };
-}
-
-function handleUpdateFormModel(model: Partial<FormModel>) {
-  Object.assign(formModel, model);
-}
-
-function handleUpdateFormModelByModalType() {
-  const handlers: Record<ModalType, () => void> = {
-    add: () => {
-      const defaultFormModel = createDefaultFormModel();
-      handleUpdateFormModel(defaultFormModel);
-    },
-    edit: () => {
-      if (props.editData) {
-        handleUpdateFormModel(props.editData);
-      }
-    }
-  };
-  handlers[props.type]();
-}
-
-async function handleSubmit() {
-  await formRef.value?.validate();
-  if (props.type === 'add') {
-    formModel.password = MD5(formModel.password).toString();
-    const data = mqttUserAdd(formModel);
-    data.then(res => {
-      if (res.data?.success) {
-        window.$message?.success(`${titles[props.type]}成功!`);
-      }
-    });
-  }
-
-  if (props.type === 'edit') {
-    const data = mqttUserEdit(formModel);
-    data.then(res => {
-      if (res.data?.success) {
-        window.$message?.success(`${titles[props.type]}成功!`);
-      }
-    });
-  }
-  closeModal();
-}
-
-watch(
-  () => props.visible,
-  newValue => {
-    if (newValue) {
-      handleUpdateFormModelByModalType();
-    }
-  }
-);
-</script>
-
-<style scoped></style>

+ 0 - 229
src/views/mqtt/user/index.vue

@@ -1,229 +0,0 @@
-<template>
-  <div class="h-full overflow-hidden">
-    <n-card title="用户管理" :bordered="false" class="rounded-16px shadow-sm">
-      <n-space class="pb-12px" justify="space-between">
-        <n-space>
-          <n-button type="primary" @click="handleAddTable">
-            <icon-ic-round-plus class="mr-4px text-20px" />
-            新增
-          </n-button>
-        </n-space>
-        <n-space align="center" :size="18">
-          <n-input-group>
-            <n-input v-model:value="userName" />
-            <n-button type="primary" @click="handleSearch">搜索</n-button>
-          </n-input-group>
-          <n-button size="small" type="primary" @click="getTableData">
-            <icon-mdi-refresh class="mr-4px text-16px" :class="{ 'animate-spin': loading }" />
-            刷新表格
-          </n-button>
-        </n-space>
-      </n-space>
-      <n-data-table :columns="columns" :data="tableData" :loading="loading" :pagination="pagination" />
-      <table-action-modal
-        v-model:visible="visible"
-        :type="modalType"
-        :edit-data="editData"
-        :pasture-enum-list-data="pastureEnumListData"
-        :topic-enum-list-data="topicEnumListData"
-      />
-    </n-card>
-  </div>
-</template>
-
-<script setup lang="tsx">
-import { reactive, ref } from 'vue';
-import type { Ref } from 'vue';
-import { NButton, NPopconfirm, NSpace, NTag } from 'naive-ui';
-import type { DataTableColumns, PaginationProps, SelectOption } from 'naive-ui';
-import { MqttUserIsShowLabels } from '@/constants';
-import { useBoolean, useLoading } from '@/hooks';
-import { fetchMqttUserList, mqttAuthDelete, pastureEnumList, topicEnumList } from '@/service/api/mqtt';
-import TableActionModal from '../user/components/table-action-modal.vue';
-import type { ModalType } from '../user/components/table-action-modal.vue';
-
-const { loading, startLoading, endLoading } = useLoading(false);
-const { bool: visible, setTrue: openModal } = useBoolean();
-const userName = ref('');
-const tableData = ref<Mqtt.User[]>([]);
-const pastureEnumListData = ref<SelectOption[]>([]);
-const topicEnumListData = ref<SelectOption[]>([]);
-
-function setTableData(data: Mqtt.User[]) {
-  tableData.value = data;
-}
-
-function setPastureList(data: SelectOption[]) {
-  pastureEnumListData.value = data;
-}
-
-function setTopicList(data: SelectOption[]) {
-  topicEnumListData.value = data;
-}
-
-async function getTableData() {
-  startLoading();
-  const { data } = await fetchMqttUserList(1, 10, userName.value);
-  if (data) {
-    setTimeout(() => {
-      setTableData(data);
-      endLoading();
-    }, 1000);
-  } else {
-    endLoading();
-  }
-}
-
-async function getPastureEnumList() {
-  const { data } = await pastureEnumList();
-  if (data) {
-    setTimeout(() => {
-      setPastureList(data);
-    }, 1000);
-  }
-}
-
-async function getTopicEnumList() {
-  const { data } = await topicEnumList();
-  if (data) {
-    setTimeout(() => {
-      setTopicList(data);
-    }, 1000);
-  }
-}
-
-const columns: Ref<DataTableColumns<Mqtt.User>> = ref([
-  {
-    type: 'selection',
-    align: 'center'
-  },
-  {
-    key: 'index',
-    title: '序号',
-    align: 'center'
-  },
-  {
-    key: 'pasture_name',
-    title: '牧场名称',
-    align: 'center'
-  },
-  {
-    key: 'user_name',
-    title: '用户名称',
-    align: 'center'
-  },
-  {
-    key: 'client_id',
-    title: '客户端id',
-    align: 'center'
-  },
-  {
-    key: 'is_show',
-    title: '是否启用',
-    align: 'center',
-    render: row => {
-      if (row.is_show) {
-        const tagTypes: Record<ApiMqttUser.IsShowKey, NaiveUI.ThemeColor> = {
-          '0': 'error',
-          '1': 'success',
-          '2': 'warning'
-        };
-        return <NTag type={tagTypes[row.is_show]}>{MqttUserIsShowLabels[row.is_show]}</NTag>;
-      }
-      return <span></span>;
-    }
-  },
-  {
-    key: 'actions',
-    title: '操作',
-    align: 'center',
-    render: row => {
-      return (
-        <NSpace justify={'center'}>
-          <NButton type="info" size={'small'} onClick={() => handleEditTable(row.id)}>
-            编辑
-          </NButton>
-          <NPopconfirm onPositiveClick={() => handleDeleteTable(row.id)}>
-            {{
-              default: () => '确认删除',
-              trigger: () => (
-                <NButton type="error" size={'small'}>
-                  删除
-                </NButton>
-              )
-            }}
-          </NPopconfirm>
-        </NSpace>
-      );
-    }
-  }
-]) as Ref<DataTableColumns<Mqtt.User>>;
-
-const editData = ref<Mqtt.User | null>(null);
-const modalType = ref<ModalType>('add');
-
-function setModalType(type: ModalType) {
-  modalType.value = type;
-}
-
-function setEditData(data: Mqtt.User | null) {
-  editData.value = data;
-}
-
-function handleAddTable() {
-  openModal();
-  setModalType('add');
-}
-
-function handleEditTable(rowId: number) {
-  const findItem = tableData.value.find(item => item.id === rowId);
-  if (findItem) {
-    setEditData(findItem);
-  }
-  setModalType('edit');
-  openModal();
-}
-
-function handleDeleteTable(rowId: number) {
-  const data = mqttAuthDelete(rowId);
-  data.then(res => {
-    if (res.data) {
-      window.$message?.success('删除成功!');
-    }
-  });
-  init();
-}
-
-const pagination: PaginationProps = reactive({
-  page: 1,
-  pageSize: 10,
-  showSizePicker: true,
-  pageSizes: [10, 15, 20, 25, 30],
-  onChange: (page: number) => {
-    pagination.page = page;
-  },
-  onUpdatePageSize: (pageSize: number) => {
-    pagination.pageSize = pageSize;
-    pagination.page = 1;
-  }
-});
-
-function handleSearch() {
-  if (!userName.value) {
-    window.$message?.warning('请输入主题名称');
-  } else {
-    startLoading();
-  }
-}
-
-function init() {
-  getTableData();
-  getPastureEnumList();
-  getTopicEnumList();
-}
-
-// 初始化
-init();
-</script>
-
-<style scoped></style>