瀏覽代碼

feat: 新增人脸库模块

曾坤森 3 月之前
父節點
當前提交
fd5319903f

+ 2 - 1
.env.development

@@ -1 +1,2 @@
-VITE_API_BASE_URL= 'http://localhost:8080'
+VITE_NODE_ENV= development
+VITE_API_BASE_URL= 'http://localhost:5173/'

+ 2 - 0
.env.production

@@ -0,0 +1,2 @@
+VITE_NODE_ENV= production
+VITE_API_BASE_URL= 'http://192.168.1.12:8001/'

+ 8 - 0
config/vite.config.dev.ts

@@ -9,6 +9,14 @@ export default mergeConfig(
       fs: {
         strict: true,
       },
+      proxy: {
+        '/api': {
+          // 代理路径前缀
+          target: 'http://192.168.1.12:8001/', // 目标服务器地址
+          changeOrigin: true, // 修改请求头中的 Origin
+          rewrite: (path) => path.replace(/^\/api/, ''), // 重写路径(可选)
+        },
+      },
     },
     plugins: [],
   },

+ 1 - 1
index.html

@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <link rel="shortcut icon" type="image/x-icon" href="https://unpkg.byted-static.com/latest/byted/arco-config/assets/favicon.ico">
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>Arco Design Pro</title>
+    <title>Site Web</title>
   </head>
   <body>
     <div id="app"></div>

+ 21 - 0
src/api/face.ts

@@ -0,0 +1,21 @@
+import type { AxiosResponse } from 'axios';
+import instance from './interceptor';
+
+export interface DataList {
+  position: string;
+  company: string;
+  id: string;
+  name: string;
+  nameCh: string;
+  picture: string;
+}
+
+export interface RecordListRes {
+  data: DataList[];
+  total: number;
+}
+
+export async function queryFaceList(params: object): Promise<RecordListRes> {
+  const res = await instance.post('/api/getUserInfo', params);
+  return res.data;
+}

+ 9 - 43
src/api/interceptor.ts

@@ -8,18 +8,11 @@ import { Message, Modal } from '@arco-design/web-vue';
 import { useUserStore } from '@/store';
 import { getToken } from '@/utils/auth';
 
-export interface HttpResponse<T = unknown> {
-  status: number;
-  msg: string;
-  code: number;
-  data: T;
-}
+const instance = axios.create({
+  baseURL: import.meta.env.VITE_API_BASE_URL,
+});
 
-if (import.meta.env.VITE_API_BASE_URL) {
-  axios.defaults.baseURL = import.meta.env.VITE_API_BASE_URL;
-}
-
-axios.interceptors.request.use(
+instance.interceptors.request.use(
   (config: InternalAxiosRequestConfig) => {
     // let each request carry token
     // this example using the JWT token
@@ -40,39 +33,11 @@ axios.interceptors.request.use(
   }
 );
 // 响应拦截器修复版本
-axios.interceptors.response.use(
-  (response: AxiosResponse<HttpResponse>): any => {
+instance.interceptors.response.use(
+  (response: AxiosResponse) => {
     const res = response.data;
-
-    if (res.code !== 20000) {
-      Message.error({
-        content: res.msg || 'Error',
-        duration: 5 * 1000,
-      });
-
-      if (
-        [50008, 50012, 50014].includes(res.code) &&
-        response.config.url !== '/api/user/info'
-      ) {
-        Modal.error({
-          title: 'Confirm logout',
-          content:
-            'You have been logged out, you can cancel to stay on this page, or log in again',
-          okText: 'Re-Login',
-          async onOk() {
-            const userStore = useUserStore();
-            await userStore.logout();
-            window.location.reload();
-          },
-        });
-      }
-
-      // 修复点:仍需返回 AxiosResponse 类型,不能直接返回 res
-      return Promise.reject(new Error(res.msg || 'Error'));
-    }
-
-    // 修复点:返回完整的 response,而不是 response.data
-    return res;
+    console.log('resaaaa', response);
+    return response;
   },
   (error) => {
     Message.error({
@@ -82,3 +47,4 @@ axios.interceptors.response.use(
     return Promise.reject(error);
   }
 );
+export default instance;

+ 26 - 0
src/api/record.ts

@@ -0,0 +1,26 @@
+import instance from './interceptor';
+
+interface HttpResponse<T> {
+  code: number;
+  data: T;
+  message: string;
+}
+interface RecordListRes {
+  list: any[];
+  total: number;
+}
+export interface RecordParams {
+  pageIndex: number;
+  personNumber: number;
+}
+export function queryRecordList(params: RecordParams) {
+  return instance.post<HttpResponse<RecordListRes>>(
+    '/api/getPassengerRecord',
+    params
+  );
+}
+export function queryRecordExpo(params: RecordParams) {
+  return instance.get<HttpResponse<RecordListRes>>('/api/record', {
+    params,
+  });
+}

+ 2 - 3
src/types/global.ts

@@ -24,9 +24,8 @@ export interface PostData {
 }
 
 export interface Pagination {
-  current: number;
-  pageSize: number;
-  total?: number;
+  pageIndex: number;
+  personNumber: number;
 }
 
 export type TimeRanger = [string, string];

+ 110 - 3
src/views/dashboard/face-list/index.vue

@@ -1,12 +1,115 @@
 <template>
-  <div class="container"> dddd </div>
+  <div class="container">
+    <a-card class="general-card" title="">
+      <a-table
+        :loading="loading"
+        :pagination="pagination"
+        :columns="(cloneColumns as TableColumnData[])"
+        :data="renderData"
+        :bordered="false"
+        :size="size"
+      >
+        <template #index="{ rowIndex }">
+          {{
+            rowIndex + 1 + (pagination.pageIndex - 1) * pagination.personNumber
+          }}
+        </template>
+        <template #picture="{ record }">
+          <a-image width="200" :src="record.picture" />
+        </template>
+      </a-table>
+    </a-card>
+  </div>
 </template>
 
-<script lang="ts" name="FaceList" setup></script>
+<script lang="ts" name="FaceListPage" setup>
+  import { computed, ref, reactive, watch, nextTick } from 'vue';
+  import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
+  import { useI18n } from 'vue-i18n';
+  import useLoading from '@/hooks/loading';
+  import { Pagination } from '@/types/global';
+  import type { RecordParams } from '@/api/record';
+  import { queryFaceList } from '@/api/face';
+  import type { DataList } from '@/api/face';
+
+  type SizeProps = 'mini' | 'small' | 'medium' | 'large';
+  type Column = TableColumnData & { checked?: true };
+
+  const { loading, setLoading } = useLoading(true);
+  const { t } = useI18n();
+  const renderData = ref<DataList[]>([] as DataList[]);
+  const cloneColumns = ref<Column[]>([
+    {
+      title: t('faceList.columns.index'),
+      dataIndex: 'index',
+      ellipsis: true,
+      tooltip: true,
+      width: 60,
+    },
+    {
+      title: t('faceList.columns.picture'),
+      dataIndex: 'picture',
+    },
+    {
+      title: t('faceList.columns.name'),
+      dataIndex: 'name',
+      ellipsis: true,
+      tooltip: true,
+    },
+    {
+      title: t('faceList.columns.nameCh'),
+      dataIndex: 'nameCh',
+    },
+    {
+      title: t('faceList.columns.company'),
+      dataIndex: 'company',
+      ellipsis: true,
+    },
+    {
+      title: t('faceList.columns.Position'),
+      dataIndex: 'Position',
+      ellipsis: true,
+      tooltip: { position: 'left' },
+    },
+    {
+      title: t('faceList.columns.company'),
+      dataIndex: 'company',
+      ellipsis: true,
+    },
+  ]);
+
+  const size = ref<SizeProps>('medium');
+
+  const basePagination: Pagination = {
+    pageIndex: 1,
+    personNumber: 20,
+  };
+  const pagination = reactive({
+    ...basePagination,
+  });
+  const fetchData = async (
+    params: RecordParams = { pageIndex: 1, personNumber: 20 }
+  ) => {
+    setLoading(true);
+    try {
+      queryFaceList(params).then((res) => {
+        console.log('res', res);
+        renderData.value = res.data;
+        pagination.pageIndex = params.pageIndex;
+        pagination.personNumber = res.total;
+      });
+    } catch (err) {
+      // you can report use errorHandler or other
+    } finally {
+      setLoading(false);
+    }
+  };
+  fetchData();
+</script>
 
 <style scoped lang="less">
   .container {
-    padding: 0 10px 20px;
+    padding: 10px;
 
     :deep(.arco-list-content) {
       overflow-x: hidden;
@@ -15,5 +118,9 @@
     :deep(.arco-card-meta-title) {
       font-size: 14px;
     }
+
+    .general-card {
+      padding-top: 10px;
+    }
   }
 </style>

+ 8 - 2
src/views/dashboard/face-list/locale/en-US.ts

@@ -1,4 +1,10 @@
 export default {
-  'menu.manage.face': '人脸库',
-  'faceList.columns.title': '历史记录',
+  'menu.manage.face': 'Enrollment',
+  'faceList.columns.index': '#',
+  'faceList.columns.name': 'EnglishName',
+  'faceList.columns.nameCh': 'Name',
+  'faceList.columns.picture': 'Photo',
+  'faceList.columns.company': 'Company',
+  'faceList.columns.Position': 'Position',
+  'faceList.columns.id': 'WorkerRegistrationID',
 };

+ 7 - 1
src/views/dashboard/face-list/locale/zh-CN.ts

@@ -1,4 +1,10 @@
 export default {
   'menu.manage.face': '人脸库',
-  'faceList.columns.title': '历史记录',
+  'faceList.columns.index': '序号',
+  'faceList.columns.name': '英文名',
+  'faceList.columns.nameCh': '中文名',
+  'faceList.columns.picture': '图片',
+  'faceList.columns.company': '公司',
+  'faceList.columns.Position': '职位',
+  'faceList.columns.id': '工作证件号',
 };

+ 17 - 7
src/views/dashboard/record-list/index.vue

@@ -12,7 +12,9 @@
         @page-change="onPageChange"
       >
         <template #index="{ rowIndex }">
-          {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
+          {{
+            rowIndex + 1 + (pagination.pageIndex - 1) * pagination.personNumber
+          }}
         </template>
       </a-table>
     </a-card>
@@ -26,6 +28,8 @@
   import useLoading from '@/hooks/loading';
   import { Pagination } from '@/types/global';
   import { queryPolicyList, PolicyRecord, PolicyParams } from '@/api/list';
+  import { queryRecordList } from '@/api/record';
+  import type { RecordParams } from '@/api/record';
 
   type SizeProps = 'mini' | 'small' | 'medium' | 'large';
   type Column = TableColumnData & { checked?: true };
@@ -74,17 +78,23 @@
   const size = ref<SizeProps>('medium');
 
   const basePagination: Pagination = {
-    current: 1,
-    pageSize: 20,
+    pageIndex: 1,
+    personNumber: 20,
   };
   const pagination = reactive({
     ...basePagination,
   });
   const fetchData = async (
-    params: PolicyParams = { current: 1, pageSize: 20 }
+    params: RecordParams = { pageIndex: 1, personNumber: 20 }
   ) => {
     setLoading(true);
     try {
+      queryRecordList(params).then((res) => {
+        console.log('res', res);
+        // renderData.value = res.data.list;
+        // pagination.current = params.current;
+        // pagination.total = res.data.total;
+      });
       // const { data } = await queryPolicyList(params);
       // renderData.value = data.list;
       // pagination.current = params.current;
@@ -100,10 +110,10 @@
     fetchData({
       ...basePagination,
       ...formModel.value,
-    } as unknown as PolicyParams);
+    } as unknown as RecordParams);
   };
-  const onPageChange = (current: number) => {
-    fetchData({ ...basePagination, current });
+  const onPageChange = (pageIndex: number) => {
+    fetchData({ ...basePagination, pageIndex });
   };
 </script>
 

+ 2 - 2
src/views/list/search-table/index.vue

@@ -278,7 +278,7 @@
 
   const size = ref<SizeProps>('medium');
 
-  const basePagination: Pagination = {
+  const basePagination = {
     current: 1,
     pageSize: 20,
   };
@@ -387,7 +387,7 @@
       const { data } = await queryPolicyList(params);
       renderData.value = data.list;
       pagination.current = params.current;
-      pagination.total = data.total;
+      pagination.pageSize = data.total;
     } catch (err) {
       // you can report use errorHandler or other
     } finally {