Selaa lähdekoodia

feat(views): 添加“网关协议列表管理”页面

wangcong 3 kuukautta sitten
vanhempi
sitoutus
f37efb3e30

+ 17 - 6
src/api/index.ts

@@ -37,13 +37,15 @@ import type {
   ProtocolGatewayListListItem,
   ProtocolItemData,
   ProtocolList,
+  ProtocolListData,
   ProtocolListItem,
+  ProtocolListQuery,
   ProtocolParamData,
   ProtocolParamInfo,
   ProtocolParamSearchParams,
   ProtocolReset,
   ProtocolStandardParamData,
-  ProtocolStandardParamSearchParams,
+  ProtocolStandardParamQuery,
   SerialNumberItemData,
   SubmitSorting,
   VerificationAgreement,
@@ -347,7 +349,7 @@ export const orgGatewaySerialNumber = async (protocolList: ProtocolList) => {
 
 // 协议标准参数
 
-export const getProtocolStandardParamList = async (params: ProtocolStandardParamSearchParams) => {
+export const getProtocolStandardParamList = async (params: ProtocolStandardParamQuery) => {
   const data = await request<ProtocolStandardParamData>(apiBiz('/protocolStandardParam/getPageList'), {
     method: 'POST',
     body: JSON.stringify(params),
@@ -384,10 +386,12 @@ export const batchDeleleProtocolParam = async (params: number[]) => {
 // 协议基本信息
 
 export const addProtocolBaseInfo = async (params: Partial<ProtocolBaseInfo>) => {
-  await request(apiBiz('/protocolBaseInfo/add'), {
+  const data = await request<number>(apiBiz('/protocolBaseInfo/add'), {
     method: 'POST',
     body: JSON.stringify(params),
   });
+
+  return data;
 };
 
 export const downloadProtocolTemplate = async (fileName: string) => {
@@ -456,17 +460,24 @@ export const updateProtocolBaseInfo = async (params: Partial<ProtocolBaseInfo>)
   });
 };
 
+export const deleteProtocolBaseInfo = async (id: number) => {
+  await request(apiBiz(`/protocolBaseInfo/delete/${id}`), {
+    method: 'POST',
+  });
+};
+
 export const completeProtocolConfig = async (id: number) => {
   await request(apiBiz(`/protocolBaseInfo/completeConfiguration/${id}`), {
     method: 'POST',
   });
 };
 
-export const postProtocolList = async (protocolList: ProtocolList) => {
-  const data = await request<ProtocolItemData>(apiBiz('/protocolBaseInfo/getPageList'), {
+export const getProtocolList = async (params: ProtocolListQuery) => {
+  const data = await request<ProtocolListData>(apiBiz('/protocolBaseInfo/getPageList'), {
     method: 'POST',
-    body: JSON.stringify(protocolList),
+    body: JSON.stringify(params),
   });
+
   return data;
 };
 

+ 12 - 0
src/i18n/locales/zh.json

@@ -1,6 +1,7 @@
 {
   "common": {
     "add": "添加",
+    "addNew": "新增",
     "advancedSettings": "高级设置",
     "aiCtrl": "AI智控",
     "basicInfo": "基础信息",
@@ -25,19 +26,23 @@
     "pleaseEnter": "请输入",
     "plzEnter": "请输入{name}",
     "plzSelect": "请选择{name}",
+    "query": "查询",
     "reLogin": "你已被登出,请重新登录",
     "requestTimedOut": "请求超时",
     "return": "返回",
     "revise": "修改",
     "save": "保存",
+    "search": "搜索",
     "selected": "已选",
     "serialNumber": "序列号",
     "settings": "设置",
     "skip": "跳过",
     "status": "状态",
+    "templateImport": "模板导入",
     "tip": "提示",
     "turnOff": "关闭",
     "unimatIoT": "亿维物联",
+    "updateTime": "更新时间",
     "verification": "验证",
     "viewDoc": "查看文档",
     "warning": "警告"
@@ -114,6 +119,12 @@
     "setupProtocol": "按项目点表配置协议"
   },
   "gatewayList": {},
+  "gatewayProtocol": {
+    "confirmDeleteProtocol": "确定要删除协议:{name}?",
+    "deleteProtocolSuccessful": "删除协议成功",
+    "protocolName": "网关协议名称",
+    "searchTip": "请输入协议编号、协议名称、项目"
+  },
   "hvacHome": {},
   "keywordLibrary": {},
   "navigation": {
@@ -121,6 +132,7 @@
     "deviceManage": "设备管理",
     "gatewayList": "网关列表",
     "gatewayManage": "网关管理",
+    "gatewayProtocol": "网关协议管理",
     "hvacHome": "首页",
     "keywordLibrary": "关键词词库",
     "protocolManage": "协议管理",

+ 13 - 4
src/router/index.ts

@@ -53,11 +53,11 @@ const routes: Readonly<RouteRecordRaw[]> = [
     },
     children: [
       {
-        path: 'keyword-library',
-        name: 'keywordLibrary',
-        component: () => import('@/views/keyword-library/KeywordLibrary.vue'),
+        path: 'gateway-protocol',
+        name: 'gatewayProtocol',
+        component: () => import('@/views/gateway-protocol/GatewayProtocol.vue'),
         meta: {
-          title: 'keywordLibrary',
+          title: 'gatewayProtocol',
           requiresAuth: true,
         },
       },
@@ -70,6 +70,15 @@ const routes: Readonly<RouteRecordRaw[]> = [
           requiresAuth: true,
         },
       },
+      {
+        path: 'keyword-library',
+        name: 'keywordLibrary',
+        component: () => import('@/views/keyword-library/KeywordLibrary.vue'),
+        meta: {
+          title: 'keywordLibrary',
+          requiresAuth: true,
+        },
+      },
     ],
   },
   {

+ 7 - 1
src/types/index.ts

@@ -130,6 +130,8 @@ export interface CustomParamsForm {
   contiguousAddressingRange: number;
 }
 
+export type ProtocolListData = PageData<ProtocolBaseInfo>;
+
 export interface ProtocolBaseInfo {
   id: number;
   protocolName: string;
@@ -154,6 +156,10 @@ export interface ProtocolBaseInfo {
   addrOrderCode: string;
 }
 
+export interface ProtocolListQuery extends PageParams {
+  searchContent: string;
+}
+
 export type ProtocolParamData = PageData<ProtocolParamInfo>;
 
 export interface ProtocolParamInfo {
@@ -216,7 +222,7 @@ export interface ProtocolStandardParam {
   enabled: string;
 }
 
-export interface ProtocolStandardParamSearchParams extends PageParams {
+export interface ProtocolStandardParamQuery extends PageParams {
   paramCode?: string;
   paramName?: string;
 }

+ 205 - 0
src/views/gateway-protocol/GatewayProtocol.vue

@@ -0,0 +1,205 @@
+<script setup lang="ts">
+import { computed, onMounted, ref } from 'vue';
+import { message, Modal } from 'ant-design-vue';
+
+import SvgIcon from '@/components/SvgIcon.vue';
+import { useRequest } from '@/hooks/request';
+import { t } from '@/i18n';
+import { deleteProtocolBaseInfo, getProtocolList } from '@/api';
+
+import type { ColumnType } from 'ant-design-vue/es/table';
+import type { PageParams, ProtocolBaseInfo } from '@/types';
+
+const protocolList = ref<ProtocolBaseInfo[]>([]);
+const protocolTotal = ref(0);
+const searchContent = ref('');
+const pageParams = ref<PageParams>({
+  pageIndex: 1,
+  pageSize: 10,
+  pageSorts: [
+    {
+      column: 'id',
+      asc: true,
+    },
+  ],
+});
+
+const columns = computed<ColumnType<ProtocolBaseInfo>[]>(() => {
+  return [
+    {
+      title: t('gatewayProtocol.protocolName'),
+      dataIndex: 'protocolName',
+      key: 'protocolName',
+    },
+    {
+      title: t('setupProtocol.protocolType'),
+      dataIndex: 'protocolType',
+      key: 'protocolType',
+    },
+    {
+      title: t('setupProtocol.deviceType'),
+      dataIndex: 'deviceType',
+      key: 'deviceType',
+    },
+    {
+      title: t('common.updateTime'),
+      dataIndex: 'updateTime',
+      key: 'updateTime',
+    },
+    {
+      title: t('common.operation'),
+      key: 'action',
+    },
+  ];
+});
+
+onMounted(() => {
+  getProtocolData();
+});
+
+const { isLoading, handleRequest } = useRequest();
+
+const getProtocolData = () => {
+  handleRequest(async () => {
+    const { records, total } = await getProtocolList({
+      ...pageParams.value,
+      searchContent: searchContent.value,
+    });
+
+    protocolList.value = records;
+    protocolTotal.value = total;
+  });
+};
+
+const handleSearch = () => {
+  pageParams.value.pageIndex = 1;
+  getProtocolData();
+};
+
+const handleAdd = () => {
+  console.log('Add new item');
+};
+
+const handleImportTemplate = () => {
+  console.log('Import template');
+};
+
+const handleEdit = (record: ProtocolBaseInfo) => {
+  console.log('Edit item:', record);
+};
+
+const handleDelete = (record: ProtocolBaseInfo) => {
+  Modal.confirm({
+    title: t('gatewayProtocol.confirmDeleteProtocol', { name: record.protocolName }),
+    async onOk() {
+      try {
+        await deleteProtocolBaseInfo(record.id);
+        message.success(t('gatewayProtocol.deleteProtocolSuccessful'));
+        pageParams.value.pageIndex = 1;
+        getProtocolData();
+      } catch (err) {
+        message.error((err as Error).message);
+        console.error(err);
+      }
+    },
+  });
+};
+
+const handlePageChange = (page: number, pageSize: number) => {
+  pageParams.value.pageIndex = page;
+  pageParams.value.pageSize = pageSize;
+  getProtocolData();
+};
+</script>
+
+<template>
+  <div class="protocol-list-container">
+    <div class="protocol-search">
+      <div>
+        <span class="protocol-search-label">{{ $t('common.search') }}:</span>
+        <AInput
+          v-model:value="searchContent"
+          class="protocol-search-input"
+          :placeholder="$t('gatewayProtocol.searchTip')"
+          allow-clear
+        />
+      </div>
+      <AButton type="primary" @click="handleSearch">{{ $t('common.query') }}</AButton>
+    </div>
+    <div class="protocol-add-container">
+      <AButton class="icon-button add-button" type="primary" @click="handleAdd">
+        <SvgIcon name="plus" />
+        {{ $t('common.addNew') }}
+      </AButton>
+      <AButton @click="handleImportTemplate">{{ $t('common.templateImport') }}</AButton>
+    </div>
+    <ATable
+      class="protocol-table"
+      :data-source="protocolList"
+      :columns="columns"
+      row-key="id"
+      :loading="isLoading"
+      :pagination="{
+        current: pageParams.pageIndex,
+        pageSize: pageParams.pageSize,
+        total: protocolTotal,
+        showSizeChanger: false,
+        hideOnSinglePage: false,
+        onChange: handlePageChange,
+      }"
+    >
+      <template #bodyCell="{ column, record }">
+        <span v-if="column.key === 'action'">
+          <a @click="handleEdit(record as ProtocolBaseInfo)">{{ $t('common.revise') }}</a>
+          <ADivider type="vertical" />
+          <a @click="handleDelete(record as ProtocolBaseInfo)">{{ $t('common.delete') }}</a>
+        </span>
+      </template>
+    </ATable>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.protocol-list-container {
+  height: 100%;
+  padding: 32px;
+  background: var(--antd-color-bg-base);
+  border-radius: 18px;
+}
+
+.protocol-search {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  margin-bottom: 24px;
+}
+
+.protocol-search-label {
+  margin-right: 10px;
+  font-size: 14px;
+  line-height: 22px;
+  color: var(--antd-color-text);
+}
+
+.protocol-search-input {
+  width: 272px;
+}
+
+.protocol-add-container {
+  display: flex;
+  align-items: center;
+}
+
+.add-button {
+  margin-right: 8px;
+  font-size: 14px;
+}
+
+.protocol-table {
+  margin-top: 72px;
+
+  a {
+    color: var(--antd-color-primary);
+  }
+}
+</style>