Parcourir la source

feat(release): v1.0.1

Yi il y a 1 an
Parent
commit
b1f6a80414

+ 6 - 24
src/constants/business.ts

@@ -161,33 +161,15 @@ export const WorkflowIsShowLabels: Record<BackgroundWorkflow.IsShowKey, string>
   2: '否'
 };
 
-export const MqttAuthIsShowLabels: Record<ApiMqttAuth.IsShowKey, string> = {
+export const MqttPastureIsGroupLabels: Record<ApiMqttPasture.IsGroupKey, string> = {
   0: '无效',
   1: '是',
   2: '否'
 };
 
-export const MqttTopicIsShowLabels: Record<ApiMqttAuth.IsShowKey, string> = {
-  0: '无效',
-  1: '是',
-  2: '否'
-};
-
-export const MqttUserIsShowLabels: Record<ApiMqttAuth.IsShowKey, string> = {
-  0: '无效',
-  1: '是',
-  2: '否'
-};
-
-export const MqttPastureIsShowLabels: Record<ApiMqttAuth.IsShowKey, string> = {
-  0: '无效',
-  1: '是',
-  2: '否'
-};
-
-export const MqttPastureOptions: Common.OptionWithKey<ApiMqttAuth.IsShowKey>[] = [
-  { value: 1, label: MqttPastureIsShowLabels['1'] },
-  { value: 2, label: MqttPastureIsShowLabels['2'] }
+export const MqttPastureIsGroupOptions: Common.OptionWithKey<ApiMqttPasture.IsGroupKey>[] = [
+  { value: 1, label: MqttPastureIsGroupLabels['1'] },
+  { value: 2, label: MqttPastureIsGroupLabels['2'] }
 ];
 
 /** 主题动作 */
@@ -205,8 +187,8 @@ export const UserTopicAccessOptions: Common.OptionWithKey<ApiMqttUser.IsAccessKe
 
 /** 主题动作 */
 export const topicAccessLabel: Record<ApiMqttTopic.AccessKey, string> = {
-  1: '发布',
-  2: '订阅'
+  1: '订阅',
+  2: '发布'
 };
 
 export const TopicAccessOptions: Common.OptionWithKey<ApiMqttTopic.AccessKey>[] = [

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

@@ -23,16 +23,6 @@ const mqtt: AuthRoute.Route = {
         icon: 'icon-park-outline:topic'
       }
     },
-    {
-      name: 'mqtt_category',
-      path: '/mqtt/category',
-      component: 'self',
-      meta: {
-        title: '分类管理',
-        requiresAuth: true,
-        icon: 'carbon:category'
-      }
-    },
     {
       name: 'mqtt_authentication',
       path: '/mqtt/authentication',

+ 17 - 5
src/service/api/mqtt.ts

@@ -87,10 +87,10 @@ export const mqttUserEdit = (param: Mqtt.User) => {
 };
 
 /** 获取牧场列表 */
-export const fetchMqttPastureList = async (page: number, pageSize: number, name: string) => {
+export const fetchMqttPastureList = async (page: number, pageSize: number, group_name: string) => {
   const data = await backgroundRequest.post<Mqtt.Pasture[] | null>(
     `/mqtt/pasture/list?page=${page}&page_size=${pageSize}`,
-    { name }
+    { group_name }
   );
   return adapter(adapterOfMqttPastureList, data);
 };
@@ -110,9 +110,9 @@ export const pastureEnumList = async () => {
   return adapter(adapterOfMqttPastureEnumList, data);
 };
 
-export const topicEnumList = async (access: number | null) => {
+export const topicEnumList = async (access: number | null, groupId: number | null) => {
   const data = await backgroundRequest.get<Common.OptionWithKey<any>[] | null>(
-    `/mqtt/topic/enum/list?access=${access}`
+    `/mqtt/topic/enum/list?access=${access}&group_id=${groupId}`
   );
   return adapter(adapterOfMqttTopicEnumList, data);
 };
@@ -137,6 +137,18 @@ export const mqttCategoryEdit = (param: Mqtt.Category) => {
 };
 
 export const categoryEnumList = async () => {
-  const data = await backgroundRequest.get<Common.OptionWithKey<any>[] | null>('/mqtt/topic-category/enum/list');
+  const data = await backgroundRequest.get<Common.OptionWithKey<any>[] | null>('/mqtt/enum/list?type=2');
+  return adapter(adapterOfMqttCategoryEnumList, data);
+};
+
+export const groupEnumList = async () => {
+  const data = await backgroundRequest.get<Common.OptionWithKey<any>[] | null>('/mqtt/enum/list?type=2');
   return adapter(adapterOfMqttCategoryEnumList, data);
 };
+
+export const groupPastureEnumList = async (group_id: string) => {
+  const groupPastureList = await backgroundRequest.get<Common.OptionWithKey<any>[] | null>(
+    `/mqtt/group/pasture/list/${group_id}`
+  );
+  return adapter(adapterOfMqttTopicEnumList, groupPastureList);
+};

+ 2 - 1
src/service/request/index.ts

@@ -9,4 +9,5 @@ export const request = createRequest({ baseURL: isHttpProxy ? proxyPattern : url
 
 export const mockRequest = createRequest({ baseURL: '/mock' });
 
-export const backgroundRequest = createRequest({ baseURL: 'http://vernamq8085.kptyun.com/api/v1' });
+// export const backgroundRequest = createRequest({ baseURL: 'http://vernamq8085.kptyun.com/api/v1' });
+export const backgroundRequest = createRequest({ baseURL: 'http://192.168.1.96:8000/api/v1' });

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

@@ -136,14 +136,6 @@ declare namespace ApiMqttAuth {
     /** 表格的key(id) */
     key: number;
   }
-
-  /**
-   * 是否启动
-   * 0 无效
-   * 1:是
-   * 2: 否 */
-
-  type IsShowKey = NonNullable<Auth['is_show']>;
 }
 
 declare namespace ApiMqttTopic {

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

@@ -3,16 +3,17 @@ declare namespace Mqtt {
     id: number;
     client_id: string | null;
     mount_point: string | null;
-    user_name: string | null;
+    user_name: string;
     password: string;
     pasture_id: number | null;
     pasture_name: string | null;
+    group_id: number | null;
+    group_name: string | null;
     publish_topic_ids: [] | null;
     subscribe_topic_ids: [] | null;
     access: number | null;
     publish_acl: string | null;
     subscribe_acl: string | null;
-    is_show: number | null;
     created_at_format: string | null;
     updated_at_format: string | null;
   }
@@ -39,8 +40,8 @@ declare namespace Mqtt {
 
   interface Topic {
     id: number;
-    category_id: number | null;
-    category_name: string | null;
+    group_id: number | null;
+    group_name: string | null;
     topic_name: string | null;
     topic_template: string | null;
     access: number | null;
@@ -61,6 +62,13 @@ declare namespace Mqtt {
     updated_at_format: string | null;
   }
 
+  interface PastureData {
+    page: number;
+    page_size: number;
+    list: Pasture[];
+    count: number;
+  }
+
   interface Category {
     id: number;
     name: string | null;

+ 70 - 34
src/views/mqtt/authentication/components/table-action-modal.vue

@@ -1,12 +1,20 @@
 <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-modal v-model:show="modalVisible" preset="card" :title="title" class="w-1200px">
+    <n-form ref="formRef" label-placement="left" :label-width="90" :model="formModel">
       <n-grid :cols="50" :x-gap="18">
-        <n-form-item-grid-item :span="18" label="客户端ID" size="large" path="client_id">
+        <!-- <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="group_id">
+          <n-select
+            v-model:value="formModel.group_id"
+            :options="groupEnumListData"
+            clearable
+            @update:value="handleUpdateValue"
+          />
         </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-select v-model:value="formModel.pasture_id" :options="groupPastureEnumListData" clearable />
         </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" />
@@ -14,10 +22,10 @@
         <n-form-item-grid-item :span="18" label="用户密码" size="large" path="password">
           <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-form-item-grid-item :span="18" label="订阅主题名(sub)" size="large" path="subscribe_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="18" label="发布主题名(topic)" size="large" path="topic_ids">
+        <n-form-item-grid-item :span="18" label="发布主题名(pub)" size="large" path="publish_topic_ids">
           <n-select v-model:value="formModel.publish_topic_ids" multiple :options="publishTopicEnumListData" />
         </n-form-item-grid-item>
       </n-grid>
@@ -31,9 +39,8 @@
 
 <script setup lang="ts">
 import { computed, ref, reactive, watch } from 'vue';
-import type { FormInst, FormItemRule, SelectOption } from 'naive-ui';
-import { createRequiredFormRule } from '@/utils';
-import { mqttAuthAdd, mqttAuthEdit } from '@/service/api/mqtt';
+import type { FormInst, SelectOption } from 'naive-ui';
+import { groupPastureEnumList, mqttAuthAdd, mqttAuthEdit, topicEnumList } from '@/service/api/mqtt';
 import { MD5 } from '@/utils/crypto';
 export interface Props {
   /** 弹窗可见性 */
@@ -46,13 +53,29 @@ export interface Props {
   type?: 'add' | 'edit';
   /** 编辑的表格行数据 */
   editData?: Mqtt.Auth | null;
-  pastureEnumListData: SelectOption[];
-  subscribeTopicEnumListData: SelectOption[];
-  publishTopicEnumListData: SelectOption[];
+  groupEnumListData: SelectOption[];
 }
 
 export type ModalType = NonNullable<Props['type']>;
 
+const groupPastureEnumListData = ref<SelectOption[]>([]);
+const subscribeTopicEnumListData = ref<SelectOption[]>([]);
+const publishTopicEnumListData = ref<SelectOption[]>([]);
+const sub = 1; // 订阅
+const pub = 2; // 发布
+
+function setGroupPastureList(data: SelectOption[]) {
+  groupPastureEnumListData.value = data;
+}
+
+function setSubTopicEnumList(data: SelectOption[]) {
+  subscribeTopicEnumListData.value = data;
+}
+
+function setPubTopicEnumList(data: SelectOption[]) {
+  publishTopicEnumListData.value = data;
+}
+
 defineOptions({ name: 'TableActionModal' });
 
 const props = withDefaults(defineProps<Props>(), {
@@ -80,8 +103,8 @@ const closeModal = () => {
 };
 
 const titles: Record<ModalType, string> = {
-  add: '添加用户',
-  edit: '编辑用户'
+  add: '添加鉴权',
+  edit: '编辑鉴权'
 };
 
 const title = computed(() => {
@@ -96,6 +119,8 @@ type FormModel = Pick<
   | 'mount_point'
   | 'pasture_id'
   | 'pasture_name'
+  | 'group_id'
+  | 'group_name'
   | 'user_name'
   | 'password'
   | 'client_id'
@@ -104,44 +129,26 @@ type FormModel = Pick<
   | 'publish_acl'
   | 'subscribe_acl'
   | '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'),
-  publish_topic_ids: createRequiredFormRule('请选择topic模板'),
-  subscribe_topic_ids: createRequiredFormRule('请选择topic模板'),
-  access: createRequiredFormRule('请选择topic权限'),
-  is_show: createRequiredFormRule(),
-  mount_point: createRequiredFormRule(),
-  pasture_name: createRequiredFormRule(),
-  subscribe_acl: createRequiredFormRule(),
-  publish_acl: createRequiredFormRule(),
-  created_at_format: createRequiredFormRule(),
-  updated_at_format: createRequiredFormRule(),
-  id: createRequiredFormRule()
-};
-
 function createDefaultFormModel(): FormModel {
   return {
     id: 0,
     mount_point: '',
     pasture_id: null,
     pasture_name: '',
+    group_id: null,
+    group_name: '',
     user_name: '',
     password: '',
     client_id: '',
     publish_topic_ids: [],
     subscribe_topic_ids: [],
     access: 0,
-    is_show: 1,
     publish_acl: '',
     subscribe_acl: '',
     created_at_format: '',
@@ -168,6 +175,35 @@ function handleUpdateFormModelByModalType() {
   handlers[props.type]();
 }
 
+async function handleUpdateValue(value: string) {
+  {
+    const { data } = await groupPastureEnumList(value);
+    if (data) {
+      setTimeout(() => {
+        setGroupPastureList(data);
+      }, 100);
+    }
+  }
+
+  {
+    const { data } = await topicEnumList(sub, formModel.group_id);
+    if (data) {
+      setTimeout(() => {
+        setSubTopicEnumList(data);
+      }, 100);
+    }
+  }
+
+  {
+    const { data } = await topicEnumList(pub, formModel.group_id);
+    if (data) {
+      setTimeout(() => {
+        setPubTopicEnumList(data);
+      }, 100);
+    }
+  }
+}
+
 async function handleSubmit() {
   await formRef.value?.validate();
   if (props.type === 'add') {

+ 23 - 56
src/views/mqtt/authentication/index.vue

@@ -27,9 +27,8 @@
         v-model:visible="visible"
         :type="modalType"
         :edit-data="editData"
-        :pasture-enum-list-data="pastureEnumListData"
-        :subscribe-topic-enum-list-data="subscribeTopicEnumListData"
-        :publish-topic-enum-list-data="publishTopicEnumListData"
+        :group-enum-list-data="groupEnumListData"
+        @update:visible="handleModalVisibilityChange"
       />
     </n-card>
   </div>
@@ -38,11 +37,10 @@
 <script setup lang="tsx">
 import { reactive, ref } from 'vue';
 import type { Ref } from 'vue';
-import { NButton, NSpace, NTag, NPopconfirm } from 'naive-ui';
+import { NButton, NSpace, NPopconfirm } from 'naive-ui';
 import type { DataTableColumns, PaginationProps, SelectOption } from 'naive-ui';
-import { MqttAuthIsShowLabels } from '@/constants';
 import { useBoolean, useLoading } from '@/hooks';
-import { fetchMqttAuthList, mqttAuthDelete, pastureEnumList, topicEnumList } from '@/service/api/mqtt';
+import { fetchMqttAuthList, groupEnumList, mqttAuthDelete } from '@/service/api/mqtt';
 import TableActionModal from '../authentication/components/table-action-modal.vue';
 import type { ModalType } from '../authentication/components/table-action-modal.vue';
 
@@ -58,20 +56,10 @@ const formValue = ref<Mqtt.SearchAuth>({
 const tableData = ref<ApiMqttAuth.Auth[]>([]);
 const editData = ref<Mqtt.Auth | null>(null);
 const modalType = ref<ModalType>('add');
-const pastureEnumListData = ref<SelectOption[]>([]);
-const subscribeTopicEnumListData = ref<SelectOption[]>([]);
-const publishTopicEnumListData = ref<SelectOption[]>([]);
+const groupEnumListData = ref<SelectOption[]>([]);
 
-function setPastureList(data: SelectOption[]) {
-  pastureEnumListData.value = data;
-}
-
-function setSubscribeTopicList(data: SelectOption[]) {
-  subscribeTopicEnumListData.value = data;
-}
-
-function setPublishTopicList(data: SelectOption[]) {
-  publishTopicEnumListData.value = data;
+function setGroupList(data: SelectOption[]) {
+  groupEnumListData.value = data;
 }
 
 function setEditData(data: Mqtt.Auth | null) {
@@ -98,26 +86,12 @@ async function getTableData() {
   }
 }
 
-async function getPastureEnumList() {
-  const { data } = await pastureEnumList();
+async function getGroupEnumList() {
+  const { data } = await groupEnumList();
   if (data) {
     setTimeout(() => {
-      setPastureList(data);
-    }, 1000);
-  }
-}
-
-async function getTopicByPublishEnumList() {
-  const { data } = await topicEnumList(1);
-  if (data) {
-    setPublishTopicList(data);
-  }
-}
-
-async function getTopicBySubscribeEnumList() {
-  const { data } = await topicEnumList(2);
-  if (data) {
-    setSubscribeTopicList(data);
+      setGroupList(data);
+    }, 100);
   }
 }
 
@@ -136,6 +110,11 @@ const columns: Ref<DataTableColumns<ApiMqttAuth.Auth>> = ref([
     title: '牧场名称',
     align: 'center'
   },
+  {
+    key: 'group_name',
+    title: '集团名称',
+    align: 'center'
+  },
   {
     key: 'mount_point',
     title: '挂载点',
@@ -171,22 +150,6 @@ const columns: Ref<DataTableColumns<ApiMqttAuth.Auth>> = ref([
     title: '发布topic',
     align: 'center'
   },
-  {
-    key: 'is_show',
-    title: '是否启用',
-    align: 'center',
-    render: row => {
-      if (row.is_show) {
-        const tagTypes: Record<ApiMqttAuth.IsShowKey, NaiveUI.ThemeColor> = {
-          '0': 'error',
-          '1': 'success',
-          '2': 'warning'
-        };
-        return <NTag type={tagTypes[row.is_show]}>{MqttAuthIsShowLabels[row.is_show]}</NTag>;
-      }
-      return <span></span>;
-    }
-  },
   {
     key: 'actions',
     title: '操作',
@@ -261,16 +224,20 @@ function handleDeleteTable(rowId: number) {
   init();
 }
 
+function handleModalVisibilityChange() {
+  setTimeout(() => {
+    getTableData();
+  }, 200);
+}
+
 function handleAddTable() {
+  getGroupEnumList();
   openModal();
   setModalType('add');
 }
 
 function init() {
   getTableData();
-  getPastureEnumList();
-  getTopicByPublishEnumList();
-  getTopicBySubscribeEnumList();
 }
 
 // 初始化

+ 1 - 18
src/views/mqtt/category/index.vue

@@ -28,9 +28,8 @@
 <script setup lang="tsx">
 import { reactive, ref } from 'vue';
 import type { Ref } from 'vue';
-import { NButton, NSpace, NTag } from 'naive-ui';
+import { NButton, NSpace } from 'naive-ui';
 import type { DataTableColumns, PaginationProps } from 'naive-ui';
-import { MqttTopicIsShowLabels } from '@/constants';
 import { useBoolean, useLoading } from '@/hooks';
 import { fetchMqttCategoryList } from '@/service/api/mqtt';
 import TableActionModal from '../category/components/table-action-modal.vue';
@@ -77,22 +76,6 @@ const columns: Ref<DataTableColumns<ApiMqttCategory.Category>> = ref([
     title: '创建时间',
     align: 'center'
   },
-  {
-    key: 'is_show',
-    title: '是否启用',
-    align: 'center',
-    render: row => {
-      if (row.is_show) {
-        const tagTypes: Record<ApiMqttCategory.IsShowKey, NaiveUI.ThemeColor> = {
-          '0': 'error',
-          '1': 'success',
-          '2': 'warning'
-        };
-        return <NTag type={tagTypes[row.is_show]}>{MqttTopicIsShowLabels[row.is_show]}</NTag>;
-      }
-      return <span></span>;
-    }
-  },
   {
     key: 'actions',
     title: '操作',

+ 43 - 12
src/views/mqtt/pasture/components/table-action-modal.vue

@@ -2,20 +2,31 @@
   <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="name">
+        <n-form-item-grid-item :span="25" label="牧场名称" size="large" path="name">
           <n-input v-model:value="formModel.name" />
         </n-form-item-grid-item>
-        <n-form-item-grid-item :span="25" label="牧场简称" path="short_name">
+        <n-form-item-grid-item :span="25" label="牧场简称(英文)" size="large" path="short_name">
           <n-input v-model:value="formModel.short_name" />
         </n-form-item-grid-item>
-        <n-form-item-grid-item :span="25" label="地址" path="address">
+        <!--  <n-form-item-grid-item :span="25" label="地址" size="large" path="address">
           <n-input v-model:value="formModel.address" />
-        </n-form-item-grid-item>
-        <n-form-item-grid-item :span="25" label="是否启用" path="is_show">
-          <n-radio-group v-model:value="formModel.is_show">
-            <n-radio v-for="item in MqttPastureOptions" :key="item.value" :value="item.value">{{ item.label }}</n-radio>
+        </n-form-item-grid-item>-->
+        <n-form-item-grid-item :span="25" label="是否集团" size="large" path="is_group">
+          <n-radio-group v-model:value="formModel.is_group">
+            <n-radio
+              v-for="item in MqttPastureIsGroupOptions"
+              :key="item.value"
+              :value="item.value"
+              @change="checkHandle"
+            >
+              {{ item.label }}
+            </n-radio>
           </n-radio-group>
         </n-form-item-grid-item>
+
+        <n-form-item-grid-item v-if="formModel.is_group === 2" :span="25" label="集团名称" size="large" path="group_id">
+          <n-select v-model:value="formModel.group_id" size="large" :options="groupEnumListData" />
+        </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>
@@ -27,10 +38,11 @@
 
 <script setup lang="ts">
 import { computed, ref, reactive, watch } from 'vue';
-import type { FormInst, FormItemRule } from 'naive-ui';
-import { MqttPastureOptions } from '@/constants';
+import type { FormInst, FormItemRule, SelectOption } from 'naive-ui';
+import { MqttPastureIsGroupOptions } from '@/constants';
 import { createRequiredFormRule } from '@/utils';
-import { mqttPastureAdd, mqttPastureEdit } from '@/service/api/mqtt';
+import { groupEnumList, mqttPastureAdd, mqttPastureEdit } from '@/service/api/mqtt';
+
 export interface Props {
   /** 弹窗可见性 */
   visible: boolean;
@@ -67,9 +79,11 @@ const modalVisible = computed({
     emit('update:visible', visible);
   }
 });
+
 const closeModal = () => {
   modalVisible.value = false;
 };
+
 const titles: Record<ModalType, string> = {
   add: '添加牧场',
   edit: '编辑牧场'
@@ -80,6 +94,11 @@ const title = computed(() => {
 });
 
 const formRef = ref<HTMLElement & FormInst>();
+const groupEnumListData = ref<SelectOption[]>([]);
+
+function setGroupList(data: SelectOption[]) {
+  groupEnumListData.value = data;
+}
 
 type FormModel = Pick<
   Mqtt.Pasture,
@@ -115,8 +134,8 @@ function createDefaultFormModel(): FormModel {
     short_name: '',
     address: '',
     is_show: 1,
-    is_group: 0,
-    group_id: 0,
+    is_group: 2,
+    group_id: null,
     created_at_format: '',
     updated_at_format: ''
   };
@@ -141,6 +160,18 @@ function handleUpdateFormModelByModalType() {
   handlers[props.type]();
 }
 
+async function checkHandle(e: Event) {
+  const radioValue = (e.target as HTMLInputElement).value;
+  if (radioValue === '2') {
+    const { data } = await groupEnumList();
+    if (data) {
+      setTimeout(() => {
+        setGroupList(data);
+      }, 100);
+    }
+  }
+}
+
 async function handleSubmit() {
   await formRef.value?.validate();
   if (props.type === 'add') {

+ 54 - 33
src/views/mqtt/pasture/index.vue

@@ -10,17 +10,26 @@
         </n-space>
         <n-space align="center" :size="18">
           <n-input-group>
-            <n-input v-model:value="PastureName" />
+            <n-input v-model:value="groupName" placeholder="输入集团名称" />
             <n-button type="primary" @click="handleSearch">搜索</n-button>
           </n-input-group>
-          <n-button size="small" type="primary" @click="getTableData">
+          <n-button
+            size="small"
+            type="primary"
+            @click="getTableData(Number(pagination.page), Number(pagination.pageSize))"
+          >
             <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" />
+      <table-action-modal
+        v-model:visible="visible"
+        :type="modalType"
+        :edit-data="editData"
+        @update:visible="handleModalVisibilityChange"
+      />
     </n-card>
   </div>
 </template>
@@ -30,7 +39,7 @@ import { reactive, ref } from 'vue';
 import type { Ref } from 'vue';
 import { NButton, NSpace, NTag } from 'naive-ui';
 import type { DataTableColumns, PaginationProps } from 'naive-ui';
-import { MqttPastureIsShowLabels } from '@/constants';
+import { MqttPastureIsGroupLabels } from '@/constants';
 import { useBoolean, useLoading } from '@/hooks';
 import { fetchMqttPastureList } from '@/service/api/mqtt';
 import TableActionModal from '../pasture/components/table-action-modal.vue';
@@ -38,25 +47,15 @@ import type { ModalType } from '../pasture/components/table-action-modal.vue';
 
 const { loading, startLoading, endLoading } = useLoading(false);
 const { bool: visible, setTrue: openModal } = useBoolean();
-const PastureName = ref('');
+const groupName = ref('');
 const tableData = ref<Mqtt.Pasture[]>([]);
+const defaultPage = ref(1);
+const defaultPageSize = ref(10);
+
 function setTableData(data: Mqtt.Pasture[]) {
   tableData.value = data;
 }
 
-async function getTableData() {
-  startLoading();
-  const { data } = await fetchMqttPastureList(1, 10, PastureName.value);
-  if (data) {
-    setTimeout(() => {
-      setTableData(data);
-      endLoading();
-    }, 1000);
-  } else {
-    endLoading();
-  }
-}
-
 const columns: Ref<DataTableColumns<Mqtt.Pasture>> = ref([
   {
     type: 'selection',
@@ -68,18 +67,18 @@ const columns: Ref<DataTableColumns<Mqtt.Pasture>> = ref([
     align: 'center'
   },
   {
-    key: 'name',
-    title: '名称',
+    key: 'group_name',
+    title: '集团名称',
     align: 'center'
   },
   {
-    key: 'short_name',
-    title: '称',
+    key: 'name',
+    title: '牧场名称',
     align: 'center'
   },
   {
-    key: 'address',
-    title: '地址',
+    key: 'short_name',
+    title: '简称(英文)',
     align: 'center'
   },
   {
@@ -92,7 +91,7 @@ const columns: Ref<DataTableColumns<Mqtt.Pasture>> = ref([
           '1': 'success',
           '2': 'warning'
         };
-        return <NTag type={tagTypes[row.is_group]}>{MqttPastureIsShowLabels[row.is_group]}</NTag>;
+        return <NTag type={tagTypes[row.is_group]}>{MqttPastureIsGroupLabels[row.is_group]}</NTag>;
       }
       return <span></span>;
     }
@@ -126,6 +125,9 @@ function setModalType(type: ModalType) {
 }
 
 function setEditData(data: Mqtt.Pasture | null) {
+  if (data?.group_id === 0) {
+    data.group_id = null;
+  }
   editData.value = data;
 }
 
@@ -144,31 +146,50 @@ function handleEditTable(rowId: number) {
 }
 
 const pagination: PaginationProps = reactive({
-  page: 1,
-  pageSize: 10,
+  page: defaultPage.value,
+  pageSize: defaultPageSize.value,
+  itemCount: 300,
   showSizePicker: true,
-  pageSizes: [10, 15, 20, 25, 30],
+  pageSizes: [10, 15, 20, 30, 50],
   onChange: (page: number) => {
     pagination.page = page;
+    getTableData(page, Number(pagination.pageSize));
   },
   onUpdatePageSize: (pageSize: number) => {
     pagination.pageSize = pageSize;
-    pagination.page = 1;
+    getTableData(Number(pagination.page), pageSize);
   }
 });
 
 function handleSearch() {
-  if (!PastureName.value) {
-    window.$message?.warning('请输入牧场名称');
+  if (!groupName.value) {
+    window.$message?.warning('请输入集团名称');
   } else {
-    startLoading();
+    getTableData(defaultPage.value, defaultPageSize.value);
   }
 }
 
+function handleModalVisibilityChange() {
+  getTableData(defaultPage.value, defaultPageSize.value);
+}
+
 function init() {
-  getTableData();
+  getTableData(defaultPage.value, defaultPageSize.value);
 }
 
+async function getTableData(page: number, pageSize: number) {
+  startLoading();
+  const { data } = await fetchMqttPastureList(page, pageSize, groupName.value.trim());
+  if (data) {
+    setTimeout(() => {
+      pagination.pageCount = 50;
+      setTableData(data);
+      endLoading();
+    }, 100);
+  } else {
+    endLoading();
+  }
+}
 // 初始化
 init();
 </script>

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

@@ -2,8 +2,8 @@
   <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="分类名称" size="large" path="category_id">
-          <n-select v-model:value="formModel.category_id" size="large" :options="categoryEnumListData" />
+        <n-form-item-grid-item :span="25" label="集团名称" size="large" path="group_id">
+          <n-select v-model:value="formModel.group_id" size="large" :options="groupTopicEnumListData" />
         </n-form-item-grid-item>
         <n-form-item-grid-item :span="25" label="topic名称" size="large" path="topic_name">
           <n-input v-model:value="formModel.topic_name" />
@@ -42,7 +42,7 @@ export interface Props {
   type?: 'add' | 'edit';
   /** 编辑的表格行数据 */
   editData?: Mqtt.Topic | null;
-  categoryEnumListData: SelectOption[];
+  groupTopicEnumListData: SelectOption[];
 }
 
 export type ModalType = NonNullable<Props['type']>;
@@ -85,8 +85,8 @@ const formRef = ref<HTMLElement & FormInst>();
 type FormModel = Pick<
   Mqtt.Topic,
   | 'id'
-  | 'category_id'
-  | 'category_name'
+  | 'group_id'
+  | 'group_name'
   | 'topic_name'
   | 'topic_template'
   | 'is_show'
@@ -98,8 +98,8 @@ type FormModel = Pick<
 const formModel = reactive<FormModel>(createDefaultFormModel());
 
 const rules: Record<keyof FormModel, FormItemRule | FormItemRule[]> = {
-  category_id: createRequiredFormRule('请选择分类名称'),
-  category_name: createRequiredFormRule('请选择分类名称1'),
+  group_id: createRequiredFormRule('请选择集团名称'),
+  group_name: createRequiredFormRule('请选择集团名称1'),
   topic_name: createRequiredFormRule('请输入主题名称'),
   topic_template: createRequiredFormRule('请输入topic'),
   access: createRequiredFormRule('请选择主题动作'),
@@ -112,8 +112,8 @@ const rules: Record<keyof FormModel, FormItemRule | FormItemRule[]> = {
 function createDefaultFormModel(): FormModel {
   return {
     id: 0,
-    category_id: null,
-    category_name: '',
+    group_id: null,
+    group_name: '',
     topic_name: '',
     topic_template: '',
     is_show: 1,

+ 20 - 13
src/views/mqtt/topic/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="h-full overflow-hidden">
-    <n-card title="消息主题模板" :bordered="false" class="rounded-16px shadow-sm">
+    <n-card title="topic配置" :bordered="false" class="rounded-16px shadow-sm">
       <n-space class="pb-12px" justify="space-between">
         <n-space>
           <n-button type="primary" @click="handleAddTable">
@@ -10,7 +10,7 @@
         </n-space>
         <n-space align="center" :size="18">
           <n-input-group>
-            <n-input v-model:value="topicName" placeholder="输入主题名称" />
+            <n-input v-model:value="topicName" placeholder="输入topic名称" />
             <n-button type="primary" @click="handleSearch">搜索</n-button>
           </n-input-group>
           <n-button size="small" type="primary" @click="getTableData">
@@ -24,7 +24,8 @@
         v-model:visible="visible"
         :type="modalType"
         :edit-data="editData"
-        :category-enum-list-data="categoryEnumListData"
+        :group-topic-enum-list-data="groupTopicEnumListData"
+        @update:visible="handleModalVisibilityChange"
       />
     </n-card>
   </div>
@@ -45,14 +46,14 @@ const { loading, startLoading, endLoading } = useLoading(false);
 const { bool: visible, setTrue: openModal } = useBoolean();
 const topicName = ref('');
 const tableData = ref<ApiMqttTopic.Topic[]>([]);
-const categoryEnumListData = ref<SelectOption[]>([]);
+const groupTopicEnumListData = ref<SelectOption[]>([]);
 
 function setTableData(data: ApiMqttTopic.Topic[]) {
   tableData.value = data;
 }
 
-function setCategoryList(data: SelectOption[]) {
-  categoryEnumListData.value = data;
+function setGroupTopicList(data: SelectOption[]) {
+  groupTopicEnumListData.value = data;
 }
 
 async function getTableData() {
@@ -62,18 +63,18 @@ async function getTableData() {
     setTimeout(() => {
       setTableData(data);
       endLoading();
-    }, 1000);
+    }, 100);
   } else {
     endLoading();
   }
 }
 
-async function getCategoryEnumList() {
+async function getGroupTopicEnumList() {
   const { data } = await categoryEnumList();
   if (data) {
     setTimeout(() => {
-      setCategoryList(data);
-    }, 1000);
+      setGroupTopicList(data);
+    }, 100);
   }
 }
 
@@ -88,8 +89,8 @@ const columns: Ref<DataTableColumns<ApiMqttTopic.Topic>> = ref([
     align: 'center'
   },
   {
-    key: 'category_name',
-    title: '分类名称',
+    key: 'group_name',
+    title: '集团名称',
     align: 'center'
   },
   {
@@ -214,9 +215,15 @@ async function handleSearch() {
   }
 }
 
+function handleModalVisibilityChange() {
+  setTimeout(() => {
+    getTableData();
+  }, 200);
+}
+
 function init() {
   getTableData();
-  getCategoryEnumList();
+  getGroupTopicEnumList();
 }
 
 // 初始化