Browse Source

feat: 完成设备列表页功能模块

曾坤森 3 months ago
parent
commit
24d76fbb76

+ 41 - 15
src/api/dashboard.ts

@@ -1,22 +1,48 @@
 import axios from 'axios';
 import type { TableData } from '@arco-design/web-vue/es/table/interface';
-
-export interface ContentDataRecord {
-  x: string;
-  y: number;
+import instance from './interceptor';
+export interface RootObject {
+  pageIndex: number;
+  pageSize: number;
+  name: string;
+  address: string;
+  status: number;
+  startTime: string;
+  endTime: string;
+  entityType: number;
 }
-
-export function queryContentData() {
-  return axios.get<ContentDataRecord[]>('/api/content-data');
+export interface Data {
+  id: number;
+  entityType: number;
+  name: string;
+  address: string;
+  status: number;
+  time: string;
+  data: string;
 }
 
-export interface PopularRecord {
-  key: number;
-  clickNumber: string;
-  title: string;
-  increases: number;
+export interface DashboardList {
+  success: boolean;
+  message: string;
+  code: string;
+  data: Data[];
+  totalCount: number;
+  totalPage: number;
 }
-
-export function queryPopularList(params: { type: string }) {
-  return axios.get<TableData[]>('/api/popular/list', { params });
+export interface DashboardParams {
+  pageIndex: number;
+  pageSize: number;
+  name: string | null;
+  address: string | null;
+  status: number | null;
+  time: [string, string];
+  startTime: string | null;
+  endTime: string | null;
+  entityType: number | null;
+}
+export async function queryDashboardList(
+  params: object
+): Promise<DashboardList> {
+  const res = await instance.post('/api/Author/GetDeviceList', params);
+  return res.data;
 }

+ 0 - 1
src/api/interceptor.ts

@@ -49,7 +49,6 @@ instance.interceptors.response.use(
         },
       });
     }
-    console.log('resaaaa', response);
     return response;
   },
   error => {

+ 78 - 0
src/components/business/b-tag/index.vue

@@ -0,0 +1,78 @@
+<template>
+  <Tag
+    :color="color || statusColor"
+    :size="size"
+    :bordered="bordered"
+    :loading="loading"
+    :closable="closable"
+    :defaultChecked="defaultChecked"
+    :nowrap="nowrap"
+    @check="onCheck"
+    @close="onClose"
+  >
+    <div v-if="$slots.icon" class="icon-left">
+      <slot name="icon" />
+    </div>
+    <slot></slot>
+    <div v-if="$slots['close-icon']" class="icon-right">
+      <slot name="close-icon" />
+    </div>
+  </Tag>
+</template>
+<script lang="ts" setup name="BTag">
+import { computed, toRefs } from 'vue';
+import { Tag } from '@arco-design/web-vue';
+import type { TagProps, TagColor } from '@arco-design/web-vue';
+
+interface BagProps extends TagProps {
+  color?: TagColor | string;
+  status?: number;
+  title?: string;
+  nowrap?: boolean;
+  bordered?: boolean;
+}
+interface BagEmits {
+  (e: 'close'): void;
+  (e: 'check'): void;
+}
+const props = withDefaults(defineProps<BagProps>(), {
+  status: 0,
+  title: '',
+  size: 'medium',
+  bordered: false,
+  loading: false,
+  closable: false,
+  defaultChecked: false,
+  nowrap: false,
+});
+const emits = defineEmits<BagEmits>();
+const onCheck = () => {
+  emits('check');
+};
+const onClose = () => {
+  emits('close');
+};
+const statusColor = computed(() => {
+  switch (props.status) {
+    case -1:
+      return 'gray';
+    case 0:
+      return 'green';
+    case 1:
+      return 'orange';
+    case 2:
+      return 'red';
+    default:
+      return 'green';
+  }
+});
+</script>
+<style lang="less" scoped>
+.icon-left {
+  margin-right: 4px;
+}
+
+.icon-right {
+  margin-left: 4px;
+}
+</style>

+ 0 - 5
src/locale/en-US.ts

@@ -3,9 +3,6 @@ import localeLogin from '@/views/login/locale/en-US';
 
 import localeWorkplace from '@/views/dashboard/workplace/locale/en-US';
 
-import localeSearchTable from '@/views/list/search-table/locale/en-US';
-import localeCardList from '@/views/list/card/locale/en-US';
-
 import locale403 from '@/views/exception/403/locale/en-US';
 import locale404 from '@/views/exception/404/locale/en-US';
 import locale500 from '@/views/exception/500/locale/en-US';
@@ -29,8 +26,6 @@ export default {
   ...localeMessageBox,
   ...localeLogin,
   ...localeWorkplace,
-  ...localeSearchTable,
-  ...localeCardList,
   ...locale403,
   ...locale404,
   ...locale500,

+ 0 - 5
src/locale/zh-CN.ts

@@ -3,9 +3,6 @@ import localeLogin from '@/views/login/locale/zh-CN';
 
 import localeWorkplace from '@/views/dashboard/workplace/locale/zh-CN';
 
-import localeSearchTable from '@/views/list/search-table/locale/zh-CN';
-import localeCardList from '@/views/list/card/locale/zh-CN';
-
 import locale403 from '@/views/exception/403/locale/zh-CN';
 import locale404 from '@/views/exception/404/locale/zh-CN';
 import locale500 from '@/views/exception/500/locale/zh-CN';
@@ -28,8 +25,6 @@ export default {
   ...localeMessageBox,
   ...localeLogin,
   ...localeWorkplace,
-  ...localeSearchTable,
-  ...localeCardList,
   ...locale403,
   ...locale404,
   ...locale500,

+ 0 - 5
src/mock/index.ts

@@ -3,11 +3,6 @@ import Mock from 'mockjs';
 import './user';
 import './message-box';
 
-import '@/views/dashboard/workplace/mock';
-
-import '@/views/list/card/mock';
-import '@/views/list/search-table/mock';
-
 import '@/views/user/info/mock';
 import '@/views/user/setting/mock';
 

+ 1 - 1
src/router/routes/modules/dashboard.ts

@@ -8,7 +8,7 @@ const DASHBOARD: AppRouteRecordRaw = {
   meta: {
     locale: 'menu.dashboard',
     requiresAuth: true,
-    icon: 'icon-dashboard',
+    icon: 'icon-list',
     order: 0,
   },
   children: [

+ 0 - 38
src/router/routes/modules/list.ts

@@ -1,38 +0,0 @@
-import { DEFAULT_LAYOUT } from '../base';
-import { AppRouteRecordRaw } from '../types';
-
-const LIST: AppRouteRecordRaw = {
-  path: '/list',
-  name: 'list',
-  component: DEFAULT_LAYOUT,
-  meta: {
-    locale: 'menu.list',
-    requiresAuth: true,
-    icon: 'icon-list',
-    order: 2,
-  },
-  children: [
-    {
-      path: 'search-table', // The midline path complies with SEO specifications
-      name: 'SearchTable',
-      component: () => import('@/views/list/search-table/index.vue'),
-      meta: {
-        locale: 'menu.list.searchTable',
-        requiresAuth: true,
-        roles: ['*'],
-      },
-    },
-    {
-      path: 'card',
-      name: 'Card',
-      component: () => import('@/views/list/card/index.vue'),
-      meta: {
-        locale: 'menu.list.cardList',
-        requiresAuth: true,
-        roles: ['*'],
-      },
-    },
-  ],
-};
-
-export default LIST;

+ 1 - 0
src/types/global.ts

@@ -35,3 +35,4 @@ export interface GeneralChart {
   xAxis: string[];
   data: Array<{ name: string; value: number[] }>;
 }
+export type SizeProps = 'mini' | 'small' | 'medium' | 'large';

+ 15 - 0
src/views/dashboard/workplace/conf.ts

@@ -0,0 +1,15 @@
+export interface DeviceInfo {
+  label: string;
+  value: string;
+}
+export const entityTypeList = [
+  { value: 1, label: '摄像头' },
+  { value: 2, label: '服务器' },
+  { value: 3, label: '温度传感器' },
+];
+export const statusTypeList = [
+  { value: -1, label: '离线', color: 'gray' },
+  { value: 0, label: '正常', color: 'green' },
+  { value: 1, label: '警告', color: 'orange' },
+  { value: 2, label: '报警', color: 'red' },
+];

+ 293 - 6
src/views/dashboard/workplace/index.vue

@@ -1,14 +1,301 @@
 <template>
-  <div class="container"></div>
+  <div class="container">
+    <a-card class="general-card">
+      <a-row>
+        <a-col :flex="1">
+          <a-form
+            :model="formModel"
+            :label-col-props="{ span: 4 }"
+            :wrapper-col-props="{ span: 18 }"
+            label-align="left"
+          >
+            <a-row :gutter="16">
+              <a-col :span="6">
+                <a-form-item
+                  field="address"
+                  label="IP地址"
+                  label-col-flex="50px"
+                >
+                  <a-input
+                    v-model="formModel.address"
+                    placeholder="IP地址"
+                    allow-clear
+                  />
+                </a-form-item>
+              </a-col>
+              <a-col :span="6">
+                <a-form-item field="name" label="名称" label-col-flex="50px">
+                  <a-input
+                    v-model="formModel.name"
+                    placeholder="名称"
+                    allow-clear
+                  />
+                </a-form-item>
+              </a-col>
+              <a-col :span="6">
+                <a-form-item
+                  field="entityType"
+                  label="设备类型"
+                  label-col-flex="60px"
+                >
+                  <a-select
+                    v-model="formModel.entityType"
+                    placeholder="设备类型"
+                    allow-clear
+                  >
+                    <a-option
+                      v-for="item of entityTypeList"
+                      :value="item.value"
+                      :label="item.label"
+                    />
+                  </a-select>
+                </a-form-item>
+              </a-col>
+              <a-col :span="6">
+                <a-form-item
+                  field="statusTypeList"
+                  label="状态"
+                  label-col-flex="60px"
+                >
+                  <a-select
+                    v-model="formModel.status"
+                    placeholder="状态"
+                    allow-clear
+                  >
+                    <a-option
+                      v-for="item of statusTypeList"
+                      :value="item.value"
+                      :label="item.label"
+                    />
+                  </a-select>
+                </a-form-item>
+              </a-col>
+              <a-col :span="6">
+                <a-form-item label="时间范围" label-col-flex="60px">
+                  <a-range-picker v-model="formModel.time" />
+                </a-form-item>
+              </a-col>
+            </a-row>
+          </a-form>
+        </a-col>
+        <a-divider :style="{ height: '84px' }" direction="vertical" />
+        <a-col :flex="'86px'">
+          <a-space direction="vertical" :size="18">
+            <a-button type="primary" @click="search">
+              <template #icon>
+                <icon-search />
+              </template>
+              {{ $t('searchTable.form.search') }}
+            </a-button>
+            <a-button @click="reset">
+              <template #icon>
+                <icon-refresh />
+              </template>
+              {{ $t('searchTable.form.reset') }}
+            </a-button>
+          </a-space>
+        </a-col>
+      </a-row>
+      <a-table
+        class="table-list"
+        row-key="name"
+        :loading="loading"
+        :pagination="pagination"
+        :columns="(cloneColumns as TableColumnData[])"
+        :data="renderData"
+        :bordered="false"
+        :size="size"
+        @page-change="onPageChange"
+        @row-dblclick="handleClick"
+      >
+        <template #index="{ rowIndex }">
+          {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
+        </template>
+
+        <template #entityType="{ record }">
+          <span>
+            {{
+              entityTypeList.find(item => item.value === record.entityType)
+                ?.label
+            }}
+          </span>
+        </template>
+        <template #status="{ record }">
+          <BTag :status="record.status">
+            {{
+              statusTypeList.find(item => item.value === record.status)?.label
+            }}
+          </BTag>
+        </template>
+        <template #time="{ record }">
+          <span>{{
+            record.time && dayjs(record.time).format('YYYY-MM-DD HH:mm:ss')
+          }}</span>
+        </template>
+      </a-table>
+    </a-card>
+    <a-modal
+      v-model:visible="visible"
+      title-align="start"
+      @cancel="handleCancel"
+    >
+      <template #title>Device Information</template>
+      <div>
+        <a-descriptions :data="deviceInfo" bordered :column="2" />
+      </div>
+      <template #footer>
+        <a-button @click="handleCancel">取消</a-button>
+        <!-- 只保留取消按钮,确认按钮被隐藏 -->
+      </template>
+    </a-modal>
+  </div>
 </template>
 
-<script lang="ts" setup name="Dashboard"></script>
+<script lang="ts" setup name="Dashboard">
+import { ref, reactive, shallowRef, h, getCurrentInstance } from 'vue';
+import { queryDashboardList } from '@/api/dashboard';
+import type { DashboardParams, Data } from '@/api/dashboard';
+import { SizeProps, Pagination } from '@/types/global';
+import BTag from '@/components/business/b-tag/index.vue';
+import type { TableColumnData } from '@arco-design/web-vue';
+import useLoading from '@/hooks/loading';
+import { useI18n } from 'vue-i18n';
+import { entityTypeList, statusTypeList, DeviceInfo } from './conf';
+import dayjs from 'dayjs';
+
+const { t } = useI18n();
+
+const { loading, setLoading } = useLoading(true);
+
+const cloneColumns = ref<TableColumnData[]>([
+  {
+    title: '序号',
+    dataIndex: 'index',
+    slotName: 'index',
+    ellipsis: true,
+    tooltip: true,
+    width: 60,
+  },
+  {
+    title: '设备类型',
+    dataIndex: 'entityType',
+    slotName: 'entityType',
+  },
+  {
+    title: '名称',
+    dataIndex: 'name',
+    slotName: 'name',
+  },
+  {
+    title: 'IP地址',
+    dataIndex: 'address',
+    ellipsis: true,
+    tooltip: true,
+  },
+
+  {
+    title: '状态',
+    dataIndex: 'status',
+    slotName: 'status',
+    width: 120,
+  },
+  {
+    title: '修改时间',
+    dataIndex: 'time',
+    slotName: 'time',
+    ellipsis: true,
+  },
+]);
+
+const basePagination: Pagination = {
+  current: 1,
+  pageSize: 20,
+};
+const pagination = reactive({
+  ...basePagination,
+});
+const generateFormModel = () => {
+  return {
+    pageIndex: 1,
+    pageSize: 20,
+    name: null,
+    address: null,
+    status: null,
+    startTime: null,
+    endTime: null,
+    time: ['', ''],
+    entityType: null,
+  } as DashboardParams;
+};
+const renderData = ref<Data[]>([] as Data[]);
+const size = ref<SizeProps>('medium');
+const formModel = ref<DashboardParams>(generateFormModel());
+const visible = shallowRef<boolean>(false);
+const this_ = getCurrentInstance()?.appContext.config.globalProperties;
+const deviceInfo = ref<DeviceInfo[]>([] as DeviceInfo[]);
+function searchTable() {
+  setLoading(true);
+  const [startTime, endTime] = formModel.value.time;
+  formModel.value.startTime = startTime ? startTime : null;
+  formModel.value.endTime = endTime ? startTime : null;
+  queryDashboardList(formModel.value)
+    .then(res => {
+      console.log('res', res);
+      pagination.current = formModel.value.pageIndex;
+      pagination.pageSize = pagination.pageSize;
+      pagination.total = res.totalCount;
+      renderData.value = res.data;
+    })
+    .finally(() => {
+      setLoading(false);
+    });
+}
+searchTable();
+const search = () => {
+  searchTable();
+};
+const reset = () => {
+  formModel.value = generateFormModel();
+};
+const onPageChange = (current: number) => {
+  formModel.value.pageIndex = current;
+  searchTable();
+};
+
+const handleClick = (value: Data) => {
+  console.log('e', value);
+  if (value.data) {
+    const obj = JSON.parse(value.data);
+    for (const key in obj) {
+      deviceInfo.value.push({
+        label: key,
+        value: obj[key],
+      });
+    }
+    visible.value = true;
+  } else {
+    this_ &&
+      this_.$message.warning('No device information available at the moment');
+  }
+};
+const handleOk = () => {
+  visible.value = false;
+};
+const handleCancel = () => {
+  visible.value = false;
+};
+</script>
 
 <style lang="less" scoped>
 .container {
-  display: flex;
-  padding: 10px;
-  padding-bottom: 0;
-  background-color: var(--color-fill-2);
+  padding: 10px 10px 20px;
+
+  .general-card {
+    padding-top: 20px;
+  }
+
+  .table-list {
+    margin-top: 10px;
+  }
 }
 </style>

+ 2 - 0
src/views/dashboard/workplace/locale/en-US.ts

@@ -1,4 +1,6 @@
 export default {
   'menu.dashboard.workplace': 'Workplace',
   'workplace.welcome': 'Welcome!',
+  'searchTable.form.search': 'Search',
+  'searchTable.form.reset': 'Reset',
 };

+ 2 - 0
src/views/dashboard/workplace/locale/zh-CN.ts

@@ -1,4 +1,6 @@
 export default {
   'menu.dashboard.workplace': '工作台',
   'workplace.welcome': '欢迎回来!',
+  'searchTable.form.search': '查询',
+  'searchTable.form.reset': '重置',
 };

+ 0 - 129
src/views/dashboard/workplace/mock.ts

@@ -1,129 +0,0 @@
-import Mock from 'mockjs';
-import qs from 'query-string';
-import dayjs from 'dayjs';
-import { GetParams } from '@/types/global';
-import setupMock, { successResponseWrap } from '@/utils/setup-mock';
-
-const textList = [
-  {
-    key: 1,
-    clickNumber: '346.3w+',
-    title: '经济日报:财政政策要精准提升…',
-    increases: 35,
-  },
-  {
-    key: 2,
-    clickNumber: '324.2w+',
-    title: '双12遇冷,消费者厌倦了电商平…',
-    increases: 22,
-  },
-  {
-    key: 3,
-    clickNumber: '318.9w+',
-    title: '致敬坚守战“疫”一线的社区工作…',
-    increases: 9,
-  },
-  {
-    key: 4,
-    clickNumber: '257.9w+',
-    title: '普高还是职高?家长们陷入选择…',
-    increases: 17,
-  },
-  {
-    key: 5,
-    clickNumber: '124.2w+',
-    title: '人民快评:没想到“浓眉大眼”的…',
-    increases: 37,
-  },
-];
-const imageList = [
-  {
-    key: 1,
-    clickNumber: '15.3w+',
-    title: '杨涛接替陆慷出任外交部美大司…',
-    increases: 15,
-  },
-  {
-    key: 2,
-    clickNumber: '12.2w+',
-    title: '图集:龙卷风袭击美国多州房屋…',
-    increases: 26,
-  },
-  {
-    key: 3,
-    clickNumber: '18.9w+',
-    title: '52岁大姐贴钱照顾自闭症儿童八…',
-    increases: 9,
-  },
-  {
-    key: 4,
-    clickNumber: '7.9w+',
-    title: '杭州一家三口公园宿营取暖中毒',
-    increases: 0,
-  },
-  {
-    key: 5,
-    clickNumber: '5.2w+',
-    title: '派出所副所长威胁市民?警方调…',
-    increases: 4,
-  },
-];
-const videoList = [
-  {
-    key: 1,
-    clickNumber: '367.6w+',
-    title: '这是今日10点的南京',
-    increases: 5,
-  },
-  {
-    key: 2,
-    clickNumber: '352.2w+',
-    title: '立陶宛不断挑衅致经济受损民众…',
-    increases: 17,
-  },
-  {
-    key: 3,
-    clickNumber: '348.9w+',
-    title: '韩国艺人刘在石确诊新冠',
-    increases: 30,
-  },
-  {
-    key: 4,
-    clickNumber: '346.3w+',
-    title: '关于北京冬奥会,文在寅表态',
-    increases: 12,
-  },
-  {
-    key: 5,
-    clickNumber: '271.2w+',
-    title: '95后现役军人荣立一等功',
-    increases: 2,
-  },
-];
-setupMock({
-  setup() {
-    Mock.mock(new RegExp('/api/content-data'), () => {
-      const presetData = [58, 81, 53, 90, 64, 88, 49, 79];
-      const getLineData = () => {
-        const count = 8;
-        return new Array(count).fill(0).map((el, idx) => ({
-          x: dayjs()
-            .day(idx - 2)
-            .format('YYYY-MM-DD'),
-          y: presetData[idx],
-        }));
-      };
-      return successResponseWrap([...getLineData()]);
-    });
-    Mock.mock(new RegExp('/api/popular/list'), (params: GetParams) => {
-      const { type = 'text' } = qs.parseUrl(params.url).query;
-      if (type === 'image') {
-        return successResponseWrap([...videoList]);
-      }
-      if (type === 'video') {
-        return successResponseWrap([...imageList]);
-      }
-      return successResponseWrap([...textList]);
-    });
-  },
-});

+ 0 - 216
src/views/list/card/components/card-wrap.vue

@@ -1,216 +0,0 @@
-<template>
-  <div class="card-wrap">
-    <a-card v-if="loading" :bordered="false" hoverable>
-      <slot name="skeleton"></slot>
-    </a-card>
-    <a-card v-else :bordered="false" hoverable>
-      <a-space align="start">
-        <a-avatar
-          v-if="icon"
-          :size="24"
-          style="margin-right: 8px; background-color: #626aea"
-        >
-          <icon-filter />
-        </a-avatar>
-        <a-card-meta>
-          <template #title>
-            <a-typography-text style="margin-right: 10px">
-              {{ title }}
-            </a-typography-text>
-            <template v-if="showTag">
-              <a-tag
-                v-if="open && isExpires === false"
-                size="small"
-                color="green"
-              >
-                <template #icon>
-                  <icon-check-circle-fill />
-                </template>
-                <span>{{ tagText }}</span>
-              </a-tag>
-              <a-tag v-else-if="isExpires" size="small" color="red">
-                <template #icon>
-                  <icon-check-circle-fill />
-                </template>
-                <span>{{ expiresTagText }}</span>
-              </a-tag>
-            </template>
-          </template>
-          <template #description>
-            {{ description }}
-            <slot></slot>
-          </template>
-        </a-card-meta>
-      </a-space>
-      <template #actions>
-        <a-switch v-if="actionType === 'switch'" v-model="open" />
-        <a-space v-else-if="actionType === 'button'">
-          <template v-if="isExpires">
-            <a-button type="outline" @click="renew">
-              {{ expiresText }}
-            </a-button>
-          </template>
-          <template v-else>
-            <a-button v-if="open" @click="handleToggle">
-              {{ closeTxt }}
-            </a-button>
-            <a-button v-else-if="!open" type="outline" @click="handleToggle">
-              {{ openTxt }}
-            </a-button>
-          </template>
-        </a-space>
-        <div v-else>
-          <a-space>
-            <a-button @click="toggle(false)">
-              {{ closeTxt }}
-            </a-button>
-            <a-button type="primary" @click="toggle(true)">
-              {{ openTxt }}
-            </a-button>
-          </a-space>
-        </div>
-      </template>
-    </a-card>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { ref } from 'vue';
-  import { useToggle } from '@vueuse/core';
-
-  const props = defineProps({
-    loading: {
-      type: Boolean,
-      default: false,
-    },
-    title: {
-      type: String,
-      default: '',
-    },
-    description: {
-      type: String,
-      default: '',
-    },
-    actionType: {
-      type: String,
-      default: '',
-    },
-    defaultValue: {
-      type: Boolean,
-      default: false,
-    },
-    openTxt: {
-      type: String,
-      default: '',
-    },
-    closeTxt: {
-      type: String,
-      default: '',
-    },
-    expiresText: {
-      type: String,
-      default: '',
-    },
-    icon: {
-      type: String,
-      default: '',
-    },
-    showTag: {
-      type: Boolean,
-      default: true,
-    },
-    tagText: {
-      type: String,
-      default: '',
-    },
-    expires: {
-      type: Boolean,
-      default: false,
-    },
-    expiresTagText: {
-      type: String,
-      default: '',
-    },
-  });
-  const [open, toggle] = useToggle(props.defaultValue);
-  const handleToggle = () => {
-    toggle();
-  };
-  const isExpires = ref(props.expires);
-  const renew = () => {
-    isExpires.value = false;
-  };
-</script>
-
-<style scoped lang="less">
-  .card-wrap {
-    height: 100%;
-    border: 1px solid var(--color-neutral-3);
-    border-radius: 4px;
-    transition: all 0.3s;
-
-    &:hover {
-      transform: translateY(-4px);
-      // box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.1);
-    }
-
-    :deep(.arco-card) {
-      height: 100%;
-      border-radius: 4px;
-
-      .arco-card-body {
-        height: 100%;
-
-        .arco-space {
-          width: 100%;
-          height: 100%;
-
-          .arco-space-item {
-            height: 100%;
-
-            &:last-child {
-              flex: 1;
-            }
-
-            .arco-card-meta {
-              display: flex;
-              flex-flow: column;
-              height: 100%;
-
-              .arco-card-meta-content {
-                flex: 1;
-
-                .arco-card-meta-description {
-                  margin-top: 8px;
-                  color: rgb(var(--gray-6));
-                  font-size: 12px;
-                  line-height: 20px;
-                }
-              }
-
-              .arco-card-meta-footer {
-                margin-top: 0;
-              }
-            }
-          }
-        }
-      }
-    }
-
-    :deep(.arco-card-meta-title) {
-      display: flex;
-      align-items: center;
-
-      // To prevent the shaking
-      line-height: 28px;
-    }
-
-    :deep(.arco-skeleton-line) {
-      &:last-child {
-        display: flex;
-        justify-content: flex-end;
-        margin-top: 20px;
-      }
-    }
-  }
-</style>

+ 0 - 122
src/views/list/card/components/quality-inspection.vue

@@ -1,122 +0,0 @@
-<template>
-  <div class="list-wrap">
-    <a-typography-title class="block-title" :heading="6">
-      {{ $t('cardList.tab.title.content') }}
-    </a-typography-title>
-    <a-row class="list-row" :gutter="24">
-      <a-col
-        :xs="12"
-        :sm="12"
-        :md="12"
-        :lg="6"
-        :xl="6"
-        :xxl="6"
-        class="list-col"
-      >
-        <div class="card-wrap empty-wrap">
-          <a-card :bordered="false" hoverable>
-            <a-result :status="null" :title="$t('cardList.content.action')">
-              <template #icon>
-                <icon-plus style="font-size: 20px" />
-              </template>
-            </a-result>
-          </a-card>
-        </div>
-      </a-col>
-      <a-col
-        v-for="item in renderData"
-        :key="item.id"
-        class="list-col"
-        :xs="12"
-        :sm="12"
-        :md="12"
-        :lg="6"
-        :xl="6"
-        :xxl="6"
-      >
-        <CardWrap
-          :loading="loading"
-          :title="item.title"
-          :description="item.description"
-          :default-value="item.enable"
-          :action-type="item.actionType"
-          :icon="item.icon"
-          :open-txt="$t('cardList.content.inspection')"
-          :close-txt="$t('cardList.content.delete')"
-          :show-tag="false"
-        >
-          <a-descriptions
-            style="margin-top: 16px"
-            :data="item.data"
-            layout="inline-horizontal"
-            :column="2"
-          />
-          <template #skeleton>
-            <a-skeleton :animation="true">
-              <a-skeleton-line
-                :widths="['50%', '50%', '100%', '40%']"
-                :rows="4"
-              />
-              <a-skeleton-line :widths="['40%']" :rows="1" />
-            </a-skeleton>
-          </template>
-        </CardWrap>
-      </a-col>
-    </a-row>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { queryInspectionList, ServiceRecord } from '@/api/list';
-  import useRequest from '@/hooks/request';
-  import CardWrap from './card-wrap.vue';
-
-  const defaultValue: ServiceRecord[] = new Array(3).fill({});
-  const { loading, response: renderData } = useRequest<ServiceRecord[]>(
-    queryInspectionList,
-    defaultValue
-  );
-</script>
-
-<style scoped lang="less">
-  .card-wrap {
-    height: 100%;
-    border: 1px solid var(--color-neutral-3);
-    transition: all 0.3s;
-
-    &:hover {
-      transform: translateY(-4px);
-    }
-
-    :deep(.arco-card-meta-description) {
-      color: rgb(var(--gray-6));
-
-      .arco-descriptions-item-label-inline {
-        color: rgb(var(--gray-6));
-        font-weight: normal;
-        font-size: 12px;
-      }
-
-      .arco-descriptions-item-value-inline {
-        color: rgb(var(--gray-8));
-      }
-    }
-  }
-
-  .empty-wrap {
-    height: 200px;
-    border-radius: 4px;
-
-    :deep(.arco-card) {
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      height: 100%;
-      border-radius: 4px;
-
-      .arco-result-title {
-        color: rgb(var(--gray-6));
-      }
-    }
-  }
-</style>

+ 0 - 51
src/views/list/card/components/rules-preset.vue

@@ -1,51 +0,0 @@
-<template>
-  <div class="list-wrap">
-    <a-typography-title class="block-title" :heading="6">
-      {{ $t('cardList.tab.title.preset') }}
-    </a-typography-title>
-    <a-row class="list-row" :gutter="24">
-      <a-col
-        v-for="item in renderData"
-        :key="item.id"
-        :xs="12"
-        :sm="12"
-        :md="12"
-        :lg="6"
-        :xl="6"
-        :xxl="6"
-        class="list-col"
-        style="min-height: 140px"
-      >
-        <CardWrap
-          :loading="loading"
-          :title="item.title"
-          :description="item.description"
-          :default-value="item.enable"
-          :action-type="item.actionType"
-          :tag-text="$t('cardList.preset.tag')"
-        >
-          <template #skeleton>
-            <a-skeleton :animation="true">
-              <a-skeleton-line :widths="['100%', '40%']" :rows="2" />
-              <a-skeleton-line :widths="['40%']" :rows="1" />
-            </a-skeleton>
-          </template>
-        </CardWrap>
-      </a-col>
-    </a-row>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { queryRulesPresetList, ServiceRecord } from '@/api/list';
-  import useRequest from '@/hooks/request';
-  import CardWrap from './card-wrap.vue';
-
-  const defaultValue: ServiceRecord[] = new Array(6).fill({});
-  const { loading, response: renderData } = useRequest<ServiceRecord[]>(
-    queryRulesPresetList,
-    defaultValue
-  );
-</script>
-
-<style scoped lang="less"></style>

+ 0 - 57
src/views/list/card/components/the-service.vue

@@ -1,57 +0,0 @@
-<template>
-  <div class="list-wrap">
-    <a-typography-title class="block-title" :heading="6">
-      {{ $t('cardList.tab.title.service') }}
-    </a-typography-title>
-    <a-row class="list-row" :gutter="24">
-      <a-col
-        v-for="item in renderData"
-        :key="item.id"
-        :xs="12"
-        :sm="12"
-        :md="12"
-        :lg="6"
-        :xl="6"
-        :xxl="6"
-        class="list-col"
-        style="min-height: 162px"
-      >
-        <CardWrap
-          :loading="loading"
-          :title="item.title"
-          :description="item.description"
-          :default-value="item.enable"
-          :action-type="item.actionType"
-          :expires="item.expires"
-          :open-txt="$t('cardList.service.open')"
-          :close-txt="$t('cardList.service.cancel')"
-          :expires-text="$t('cardList.service.renew')"
-          :tag-text="$t('cardList.service.tag')"
-          :expires-tag-text="$t('cardList.service.expiresTag')"
-          :icon="item.icon"
-        >
-          <template #skeleton>
-            <a-skeleton :animation="true">
-              <a-skeleton-line :widths="['100%', '40%', '100%']" :rows="3" />
-              <a-skeleton-line :widths="['40%']" :rows="1" />
-            </a-skeleton>
-          </template>
-        </CardWrap>
-      </a-col>
-    </a-row>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { queryTheServiceList, ServiceRecord } from '@/api/list';
-  import useRequest from '@/hooks/request';
-  import CardWrap from './card-wrap.vue';
-
-  const defaultValue: ServiceRecord[] = new Array(4).fill({});
-  const { loading, response: renderData } = useRequest<ServiceRecord[]>(
-    queryTheServiceList,
-    defaultValue
-  );
-</script>
-
-<style scoped lang="less"></style>

+ 0 - 97
src/views/list/card/index.vue

@@ -1,97 +0,0 @@
-<template>
-  <div class="container">
-    <Breadcrumb :items="['menu.list', 'menu.list.cardList']" />
-    <a-row :gutter="20" align="stretch">
-      <a-col :span="24">
-        <a-card class="general-card" :title="$t('menu.list.cardList')">
-          <a-row justify="space-between">
-            <a-col :span="24">
-              <a-tabs :default-active-tab="1" type="rounded">
-                <a-tab-pane key="1" :title="$t('cardList.tab.title.all')">
-                  <QualityInspection />
-                  <TheService />
-                  <RulesPreset />
-                </a-tab-pane>
-                <a-tab-pane key="2" :title="$t('cardList.tab.title.content')">
-                  <QualityInspection />
-                </a-tab-pane>
-                <a-tab-pane key="3" :title="$t('cardList.tab.title.service')">
-                  <TheService />
-                </a-tab-pane>
-                <a-tab-pane key="4" :title="$t('cardList.tab.title.preset')">
-                  <RulesPreset />
-                </a-tab-pane>
-              </a-tabs>
-            </a-col>
-            <a-input-search
-              :placeholder="$t('cardList.searchInput.placeholder')"
-              style="position: absolute; top: 60px; right: 20px; width: 240px"
-            />
-          </a-row>
-        </a-card>
-      </a-col>
-    </a-row>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import QualityInspection from './components/quality-inspection.vue';
-  import TheService from './components/the-service.vue';
-  import RulesPreset from './components/rules-preset.vue';
-</script>
-
-<script lang="ts">
-  export default {
-    name: 'Card',
-  };
-</script>
-
-<style scoped lang="less">
-  .container {
-    padding: 0 10px 20px;
-
-    :deep(.arco-list-content) {
-      overflow-x: hidden;
-    }
-
-    :deep(.arco-card-meta-title) {
-      font-size: 14px;
-    }
-  }
-
-  :deep(.arco-list-col) {
-    display: flex;
-    flex-flow: row wrap;
-    justify-content: space-between;
-  }
-
-  :deep(.arco-list-item) {
-    width: 33%;
-  }
-
-  :deep(.block-title) {
-    margin: 0 0 12px;
-    font-size: 14px;
-  }
-
-  :deep(.list-wrap) {
-    // min-height: 140px;
-    .list-row {
-      align-items: stretch;
-
-      .list-col {
-        margin-bottom: 16px;
-      }
-    }
-
-    :deep(.arco-space) {
-      width: 100%;
-
-      .arco-space-item {
-        &:last-child {
-          flex: 1;
-        }
-      }
-    }
-  }
-</style>

+ 0 - 19
src/views/list/card/locale/en-US.ts

@@ -1,19 +0,0 @@
-export default {
-  'menu.list.cardList': 'Card List',
-  'cardList.tab.title.all': 'All',
-  'cardList.tab.title.content': 'Quality Inspection',
-  'cardList.tab.title.service': 'The service',
-  'cardList.tab.title.preset': 'Rules Preset',
-  'cardList.searchInput.placeholder': 'Search',
-  'cardList.enable': 'Enable',
-  'cardList.disable': 'Disable',
-  'cardList.content.delete': 'Delete',
-  'cardList.content.inspection': 'Inspection',
-  'cardList.content.action': 'Click Create Qc Content queue',
-  'cardList.service.open': 'Open',
-  'cardList.service.cancel': 'Cancel',
-  'cardList.service.renew': 'Contract of service',
-  'cardList.service.tag': 'Opened',
-  'cardList.service.expiresTag': 'Expired',
-  'cardList.preset.tag': 'Enable',
-};

+ 0 - 19
src/views/list/card/locale/zh-CN.ts

@@ -1,19 +0,0 @@
-export default {
-  'menu.list.cardList': '卡片列表',
-  'cardList.tab.title.all': '全部',
-  'cardList.tab.title.content': '内容质检',
-  'cardList.tab.title.service': '开通服务',
-  'cardList.tab.title.preset': '规则预置',
-  'cardList.searchInput.placeholder': '搜索',
-  // 'cardList.statistic.enable': '已启用',
-  // 'cardList.statistic.disable': '未启用',
-  'cardList.content.delete': '删除',
-  'cardList.content.inspection': '质检',
-  'cardList.content.action': '点击创建质检内容队列',
-  'cardList.service.open': '开通服务',
-  'cardList.service.cancel': '取消服务',
-  'cardList.service.renew': '续约服务',
-  'cardList.service.tag': '已开通',
-  'cardList.service.expiresTag': '已过期',
-  'cardList.preset.tag': '已启用',
-};

+ 0 - 186
src/views/list/card/mock.ts

@@ -1,186 +0,0 @@
-import Mock from 'mockjs';
-import setupMock, { successResponseWrap } from '@/utils/setup-mock';
-import { ServiceRecord } from '@/api/list';
-
-const qualityInspectionList: ServiceRecord[] = [
-  {
-    id: 1,
-    name: 'quality',
-    title: '视频类-历史导入',
-    description: '2021-10-12 00:00:00',
-    data: [
-      {
-        label: '待质检数',
-        value: '120',
-      },
-      {
-        label: '积压时长',
-        value: '60s',
-      },
-      {
-        label: '待抽检数',
-        value: '0',
-      },
-    ],
-  },
-  {
-    id: 2,
-    name: 'quality',
-    title: '图文类-图片版权',
-    description: '2021-12-11 18:30:00',
-    data: [
-      {
-        label: '待质检数',
-        value: '120',
-      },
-      {
-        label: '积压时长',
-        value: '60s',
-      },
-      {
-        label: '待抽检数',
-        value: '0',
-      },
-    ],
-  },
-  {
-    id: 3,
-    name: 'quality',
-    title: '图文类-高清图片',
-    description: '2021-10-15 08:10:00',
-    data: [
-      {
-        label: '待质检数',
-        value: '120',
-      },
-      {
-        label: '积压时长',
-        value: '60s',
-      },
-      {
-        label: '待抽检数',
-        value: '0',
-      },
-    ],
-  },
-];
-const theServiceList: ServiceRecord[] = [
-  {
-    id: 1,
-    icon: 'code',
-    title: '漏斗分析',
-    description:
-      '用户行为分析之漏斗分析模型是企业实现精细化运营、进行用户行为分析的重要数据分析模型。',
-    enable: true,
-    actionType: 'button',
-  },
-  {
-    id: 2,
-    icon: 'edit',
-    title: '用户分布',
-    description:
-      '快速诊断用户人群,地域细分情况,了解数据分布的集中度,以及主要的数据分布的区间段是什么。',
-    enable: true,
-    actionType: 'button',
-    expires: true,
-  },
-  {
-    id: 3,
-    icon: 'user',
-    title: '资源分发',
-    description:
-      '移动端动态化资源分发解决方案。提供稳定大流量服务支持、灵活定制的分发圈选规则,通过离线化预加载。',
-    enable: false,
-    actionType: 'button',
-  },
-  {
-    id: 4,
-    icon: 'user',
-    title: '用户画像分析',
-    description:
-      '用户画像就是将典型用户信息标签化,根据用户特征、业务场景和用户行为等信息,构建一个标签化的用户模型。',
-    enable: true,
-    actionType: 'button',
-  },
-];
-const rulesPresetList: ServiceRecord[] = [
-  {
-    id: 1,
-    title: '内容屏蔽规则',
-    description:
-      '用户在执行特定的内容分发任务时,可使用内容屏蔽规则根据特定标签,过滤内容集合。',
-    enable: true,
-    actionType: 'switch',
-  },
-  {
-    id: 2,
-    title: '内容置顶规则',
-    description:
-      '该规则支持用户在执行特定内容分发任务时,对固定的几条内容置顶。',
-    enable: true,
-    actionType: 'switch',
-  },
-  {
-    id: 3,
-    title: '内容加权规则',
-    description: '选定内容加权规则后可自定义从不同内容集合获取内容的概率。',
-    enable: false,
-    actionType: 'switch',
-  },
-  {
-    id: 4,
-    title: '内容分发规则',
-    description: '内容分发时,对某些内容需要固定在C端展示的位置。',
-    enable: true,
-    actionType: 'switch',
-  },
-  {
-    id: 5,
-    title: '违禁内容识别',
-    description: '精准识别赌博、刀枪、毒品、造假、贩假等违规物品和违规行为。',
-    enable: false,
-    actionType: 'switch',
-  },
-  {
-    id: 6,
-    title: '多语言文字符号识别',
-    description:
-      '精准识别英语、维语、藏语、蒙古语、朝鲜语等多种语言以及emoji表情形态的语义识别。',
-    enable: false,
-    actionType: 'switch',
-  },
-];
-
-setupMock({
-  setup() {
-    // Quality Inspection
-    Mock.mock(new RegExp('/api/list/quality-inspection'), () => {
-      return successResponseWrap(
-        qualityInspectionList.map((_, index) => ({
-          ...qualityInspectionList[index % qualityInspectionList.length],
-          id: Mock.Random.guid(),
-        }))
-      );
-    });
-
-    // the service
-    Mock.mock(new RegExp('/api/list/the-service'), () => {
-      return successResponseWrap(
-        theServiceList.map((_, index) => ({
-          ...theServiceList[index % theServiceList.length],
-          id: Mock.Random.guid(),
-        }))
-      );
-    });
-
-    // rules preset
-    Mock.mock(new RegExp('/api/list/rules-preset'), () => {
-      return successResponseWrap(
-        rulesPresetList.map((_, index) => ({
-          ...rulesPresetList[index % rulesPresetList.length],
-          id: Mock.Random.guid(),
-        }))
-      );
-    });
-  },
-});

+ 0 - 519
src/views/list/search-table/index.vue

@@ -1,519 +0,0 @@
-<template>
-  <div class="container">
-    <Breadcrumb :items="['menu.list', 'menu.list.searchTable']" />
-    <a-card class="general-card" :title="$t('menu.list.searchTable')">
-      <a-row>
-        <a-col :flex="1">
-          <a-form
-            :model="formModel"
-            :label-col-props="{ span: 6 }"
-            :wrapper-col-props="{ span: 18 }"
-            label-align="left"
-          >
-            <a-row :gutter="16">
-              <a-col :span="8">
-                <a-form-item
-                  field="number"
-                  :label="$t('searchTable.form.number')"
-                >
-                  <a-input
-                    v-model="formModel.number"
-                    :placeholder="$t('searchTable.form.number.placeholder')"
-                  />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item field="name" :label="$t('searchTable.form.name')">
-                  <a-input
-                    v-model="formModel.name"
-                    :placeholder="$t('searchTable.form.name.placeholder')"
-                  />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item
-                  field="contentType"
-                  :label="$t('searchTable.form.contentType')"
-                >
-                  <a-select
-                    v-model="formModel.contentType"
-                    :options="contentTypeOptions"
-                    :placeholder="$t('searchTable.form.selectDefault')"
-                  />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item
-                  field="filterType"
-                  :label="$t('searchTable.form.filterType')"
-                >
-                  <a-select
-                    v-model="formModel.filterType"
-                    :options="filterTypeOptions"
-                    :placeholder="$t('searchTable.form.selectDefault')"
-                  />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item
-                  field="createdTime"
-                  :label="$t('searchTable.form.createdTime')"
-                >
-                  <a-range-picker
-                    v-model="formModel.createdTime"
-                    style="width: 100%"
-                  />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item
-                  field="status"
-                  :label="$t('searchTable.form.status')"
-                >
-                  <a-select
-                    v-model="formModel.status"
-                    :options="statusOptions"
-                    :placeholder="$t('searchTable.form.selectDefault')"
-                  />
-                </a-form-item>
-              </a-col>
-            </a-row>
-          </a-form>
-        </a-col>
-        <a-divider style="height: 84px" direction="vertical" />
-        <a-col :flex="'86px'" style="text-align: right">
-          <a-space direction="vertical" :size="18">
-            <a-button type="primary" @click="search">
-              <template #icon>
-                <icon-search />
-              </template>
-              {{ $t('searchTable.form.search') }}
-            </a-button>
-            <a-button @click="reset">
-              <template #icon>
-                <icon-refresh />
-              </template>
-              {{ $t('searchTable.form.reset') }}
-            </a-button>
-          </a-space>
-        </a-col>
-      </a-row>
-      <a-divider style="margin-top: 0" />
-      <a-row style="margin-bottom: 16px">
-        <a-col :span="12">
-          <a-space>
-            <a-button type="primary">
-              <template #icon>
-                <icon-plus />
-              </template>
-              {{ $t('searchTable.operation.create') }}
-            </a-button>
-            <a-upload action="/">
-              <template #upload-button>
-                <a-button>
-                  {{ $t('searchTable.operation.import') }}
-                </a-button>
-              </template>
-            </a-upload>
-          </a-space>
-        </a-col>
-        <a-col
-          :span="12"
-          style="display: flex; align-items: center; justify-content: end"
-        >
-          <a-button>
-            <template #icon>
-              <icon-download />
-            </template>
-            {{ $t('searchTable.operation.download') }}
-          </a-button>
-          <a-tooltip :content="$t('searchTable.actions.refresh')">
-            <div class="action-icon" @click="search"
-              ><icon-refresh size="18"
-            /></div>
-          </a-tooltip>
-          <a-dropdown @select="handleSelectDensity">
-            <a-tooltip :content="$t('searchTable.actions.density')">
-              <div class="action-icon"><icon-line-height size="18" /></div>
-            </a-tooltip>
-            <template #content>
-              <a-doption
-                v-for="item in densityList"
-                :key="item.value"
-                :value="item.value"
-                :class="{ active: item.value === size }"
-              >
-                <span>{{ item.name }}</span>
-              </a-doption>
-            </template>
-          </a-dropdown>
-          <a-tooltip :content="$t('searchTable.actions.columnSetting')">
-            <a-popover
-              trigger="click"
-              position="bl"
-              @popup-visible-change="popupVisibleChange"
-            >
-              <div class="action-icon"><icon-settings size="18" /></div>
-              <template #content>
-                <div id="tableSetting">
-                  <div
-                    v-for="(item, index) in showColumns"
-                    :key="item.dataIndex"
-                    class="setting"
-                  >
-                    <div style="margin-right: 4px; cursor: move">
-                      <icon-drag-arrow />
-                    </div>
-                    <div>
-                      <a-checkbox
-                        v-model="item.checked"
-                        @change="
-                          handleChange($event, item as TableColumnData, index)
-                        "
-                      >
-                      </a-checkbox>
-                    </div>
-                    <div class="title">
-                      {{ item.title === '#' ? '序列号' : item.title }}
-                    </div>
-                  </div>
-                </div>
-              </template>
-            </a-popover>
-          </a-tooltip>
-        </a-col>
-      </a-row>
-      <a-table
-        row-key="id"
-        :loading="loading"
-        :pagination="pagination"
-        :columns="(cloneColumns as TableColumnData[])"
-        :data="renderData"
-        :bordered="false"
-        :size="size"
-        @page-change="onPageChange"
-      >
-        <template #index="{ rowIndex }">
-          {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
-        </template>
-        <template #contentType="{ record }">
-          <a-space>
-            <a-avatar
-              v-if="record.contentType === 'img'"
-              :size="16"
-              shape="square"
-            >
-              <img
-                alt="avatar"
-                src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/581b17753093199839f2e327e726b157.svg~tplv-49unhts6dw-image.image"
-              />
-            </a-avatar>
-            <a-avatar
-              v-else-if="record.contentType === 'horizontalVideo'"
-              :size="16"
-              shape="square"
-            >
-              <img
-                alt="avatar"
-                src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/77721e365eb2ab786c889682cbc721c1.svg~tplv-49unhts6dw-image.image"
-              />
-            </a-avatar>
-            <a-avatar v-else :size="16" shape="square">
-              <img
-                alt="avatar"
-                src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/ea8b09190046da0ea7e070d83c5d1731.svg~tplv-49unhts6dw-image.image"
-              />
-            </a-avatar>
-            {{ $t(`searchTable.form.contentType.${record.contentType}`) }}
-          </a-space>
-        </template>
-        <template #filterType="{ record }">
-          {{ $t(`searchTable.form.filterType.${record.filterType}`) }}
-        </template>
-        <template #status="{ record }">
-          <span v-if="record.status === 'offline'" class="circle"></span>
-          <span v-else class="circle pass"></span>
-          {{ $t(`searchTable.form.status.${record.status}`) }}
-        </template>
-        <template #operations>
-          <a-button v-permission="['admin']" type="text" size="small">
-            {{ $t('searchTable.columns.operations.view') }}
-          </a-button>
-        </template>
-      </a-table>
-    </a-card>
-  </div>
-</template>
-
-<script lang="ts" setup>
-  import { computed, ref, reactive, watch, nextTick } from 'vue';
-  import { useI18n } from 'vue-i18n';
-  import useLoading from '@/hooks/loading';
-  import { queryPolicyList, PolicyRecord, PolicyParams } from '@/api/list';
-  import { Pagination } from '@/types/global';
-  import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
-  import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
-  import cloneDeep from 'lodash/cloneDeep';
-  import Sortable from 'sortablejs';
-
-  type SizeProps = 'mini' | 'small' | 'medium' | 'large';
-  type Column = TableColumnData & { checked?: true };
-
-  const generateFormModel = () => {
-    return {
-      number: '',
-      name: '',
-      contentType: '',
-      filterType: '',
-      createdTime: [],
-      status: '',
-    };
-  };
-  const { loading, setLoading } = useLoading(true);
-  const { t } = useI18n();
-  const renderData = ref<PolicyRecord[]>([]);
-  const formModel = ref(generateFormModel());
-  const cloneColumns = ref<Column[]>([]);
-  const showColumns = ref<Column[]>([]);
-
-  const size = ref<SizeProps>('medium');
-
-  const basePagination: Pagination = {
-    current: 1,
-    pageSize: 20,
-  };
-  const pagination = reactive({
-    ...basePagination,
-  });
-  const densityList = computed(() => [
-    {
-      name: t('searchTable.size.mini'),
-      value: 'mini',
-    },
-    {
-      name: t('searchTable.size.small'),
-      value: 'small',
-    },
-    {
-      name: t('searchTable.size.medium'),
-      value: 'medium',
-    },
-    {
-      name: t('searchTable.size.large'),
-      value: 'large',
-    },
-  ]);
-  const columns = computed<TableColumnData[]>(() => [
-    {
-      title: t('searchTable.columns.index'),
-      dataIndex: 'index',
-      slotName: 'index',
-    },
-    {
-      title: t('searchTable.columns.number'),
-      dataIndex: 'number',
-    },
-    {
-      title: t('searchTable.columns.name'),
-      dataIndex: 'name',
-    },
-    {
-      title: t('searchTable.columns.contentType'),
-      dataIndex: 'contentType',
-      slotName: 'contentType',
-    },
-    {
-      title: t('searchTable.columns.filterType'),
-      dataIndex: 'filterType',
-    },
-    {
-      title: t('searchTable.columns.count'),
-      dataIndex: 'count',
-    },
-    {
-      title: t('searchTable.columns.createdTime'),
-      dataIndex: 'createdTime',
-    },
-    {
-      title: t('searchTable.columns.status'),
-      dataIndex: 'status',
-      slotName: 'status',
-    },
-    {
-      title: t('searchTable.columns.operations'),
-      dataIndex: 'operations',
-      slotName: 'operations',
-    },
-  ]);
-  const contentTypeOptions = computed<SelectOptionData[]>(() => [
-    {
-      label: t('searchTable.form.contentType.img'),
-      value: 'img',
-    },
-    {
-      label: t('searchTable.form.contentType.horizontalVideo'),
-      value: 'horizontalVideo',
-    },
-    {
-      label: t('searchTable.form.contentType.verticalVideo'),
-      value: 'verticalVideo',
-    },
-  ]);
-  const filterTypeOptions = computed<SelectOptionData[]>(() => [
-    {
-      label: t('searchTable.form.filterType.artificial'),
-      value: 'artificial',
-    },
-    {
-      label: t('searchTable.form.filterType.rules'),
-      value: 'rules',
-    },
-  ]);
-  const statusOptions = computed<SelectOptionData[]>(() => [
-    {
-      label: t('searchTable.form.status.online'),
-      value: 'online',
-    },
-    {
-      label: t('searchTable.form.status.offline'),
-      value: 'offline',
-    },
-  ]);
-  const fetchData = async (
-    params: PolicyParams = { current: 1, pageSize: 20 }
-  ) => {
-    setLoading(true);
-    try {
-      const { data } = await queryPolicyList(params);
-      renderData.value = data.list;
-      pagination.current = params.current;
-      pagination.total = data.total;
-    } catch (err) {
-      // you can report use errorHandler or other
-    } finally {
-      setLoading(false);
-    }
-  };
-
-  const search = () => {
-    fetchData({
-      ...basePagination,
-      ...formModel.value,
-    } as unknown as PolicyParams);
-  };
-  const onPageChange = (current: number) => {
-    fetchData({ ...basePagination, current });
-  };
-
-  fetchData();
-  const reset = () => {
-    formModel.value = generateFormModel();
-  };
-
-  const handleSelectDensity = (
-    val: string | number | Record<string, any> | undefined,
-    e: Event
-  ) => {
-    size.value = val as SizeProps;
-  };
-
-  const handleChange = (
-    checked: boolean | (string | boolean | number)[],
-    column: Column,
-    index: number
-  ) => {
-    if (!checked) {
-      cloneColumns.value = showColumns.value.filter(
-        (item) => item.dataIndex !== column.dataIndex
-      );
-    } else {
-      cloneColumns.value.splice(index, 0, column);
-    }
-  };
-
-  const exchangeArray = <T extends Array<any>>(
-    array: T,
-    beforeIdx: number,
-    newIdx: number,
-    isDeep = false
-  ): T => {
-    const newArray = isDeep ? cloneDeep(array) : array;
-    if (beforeIdx > -1 && newIdx > -1) {
-      // 先替换后面的,然后拿到替换的结果替换前面的
-      newArray.splice(
-        beforeIdx,
-        1,
-        newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
-      );
-    }
-    return newArray;
-  };
-
-  const popupVisibleChange = (val: boolean) => {
-    if (val) {
-      nextTick(() => {
-        const el = document.getElementById('tableSetting') as HTMLElement;
-        const sortable = new Sortable(el, {
-          onEnd(e: any) {
-            const { oldIndex, newIndex } = e;
-            exchangeArray(cloneColumns.value, oldIndex, newIndex);
-            exchangeArray(showColumns.value, oldIndex, newIndex);
-          },
-        });
-      });
-    }
-  };
-
-  watch(
-    () => columns.value,
-    (val) => {
-      cloneColumns.value = cloneDeep(val);
-      cloneColumns.value.forEach((item, index) => {
-        item.checked = true;
-      });
-      showColumns.value = cloneDeep(cloneColumns.value);
-    },
-    { deep: true, immediate: true }
-  );
-</script>
-
-<script lang="ts">
-  export default {
-    name: 'SearchTable',
-  };
-</script>
-
-<style scoped lang="less">
-  .container {
-    padding: 0 10px 20px;
-  }
-
-  :deep(.arco-table-th) {
-    &:last-child {
-      .arco-table-th-item-title {
-        margin-left: 16px;
-      }
-    }
-  }
-
-  .action-icon {
-    margin-left: 12px;
-    cursor: pointer;
-  }
-
-  .active {
-    color: #0960bd;
-    background-color: #e3f4fc;
-  }
-
-  .setting {
-    display: flex;
-    align-items: center;
-    width: 200px;
-
-    .title {
-      margin-left: 12px;
-      cursor: pointer;
-    }
-  }
-</style>

+ 0 - 44
src/views/list/search-table/locale/en-US.ts

@@ -1,44 +0,0 @@
-export default {
-  'menu.list.searchTable': 'Search Table',
-  'searchTable.form.number': 'Set Number',
-  'searchTable.form.number.placeholder': 'Please enter Set Number',
-  'searchTable.form.name': 'Set Name',
-  'searchTable.form.name.placeholder': 'Please enter Set Name',
-  'searchTable.form.contentType': 'Content Type',
-  'searchTable.form.contentType.img': 'image-text',
-  'searchTable.form.contentType.horizontalVideo': 'Horizontal short video',
-  'searchTable.form.contentType.verticalVideo': 'Vertical short video',
-  'searchTable.form.filterType': 'Filter Type',
-  'searchTable.form.filterType.artificial': 'artificial',
-  'searchTable.form.filterType.rules': 'Rules',
-  'searchTable.form.createdTime': 'Create Date',
-  'searchTable.form.status': 'Status',
-  'searchTable.form.status.online': 'Online',
-  'searchTable.form.status.offline': 'Offline',
-  'searchTable.form.search': 'Search',
-  'searchTable.form.reset': 'Reset',
-  'searchTable.form.selectDefault': 'All',
-  'searchTable.operation.create': 'Create',
-  'searchTable.operation.import': 'Import',
-  'searchTable.operation.download': 'Download',
-  // columns
-  'searchTable.columns.index': '#',
-  'searchTable.columns.number': 'Set Number',
-  'searchTable.columns.name': 'Set Name',
-  'searchTable.columns.contentType': 'Content Type',
-  'searchTable.columns.filterType': 'Filter Type',
-  'searchTable.columns.count': 'Count',
-  'searchTable.columns.createdTime': 'CreatedTime',
-  'searchTable.columns.status': 'Status',
-  'searchTable.columns.operations': 'Operations',
-  'searchTable.columns.operations.view': 'View',
-  // size
-  'searchTable.size.mini': 'mini',
-  'searchTable.size.small': 'small',
-  'searchTable.size.medium': 'middle',
-  'searchTable.size.large': 'large',
-  // actions
-  'searchTable.actions.refresh': 'refresh',
-  'searchTable.actions.density': 'density',
-  'searchTable.actions.columnSetting': 'columnSetting',
-};

+ 0 - 45
src/views/list/search-table/locale/zh-CN.ts

@@ -1,45 +0,0 @@
-export default {
-  'menu.list.searchTable': '查询表格',
-  'searchTable.form.number': '集合编号',
-  'searchTable.form.number.placeholder': '请输入集合编号',
-  'searchTable.form.name': '集合名称',
-  'searchTable.form.name.placeholder': '请输入集合名称',
-  'searchTable.form.contentType': '内容体裁',
-  'searchTable.form.contentType.img': '图文',
-  'searchTable.form.contentType.horizontalVideo': '横版短视频',
-  'searchTable.form.contentType.verticalVideo': '竖版小视频',
-  'searchTable.form.filterType': '筛选方式',
-  'searchTable.form.filterType.artificial': '人工筛选',
-  'searchTable.form.filterType.rules': '规则筛选',
-  'searchTable.form.createdTime': '创建时间',
-  'searchTable.form.status': '状态',
-  'searchTable.form.status.online': '已上线',
-  'searchTable.form.status.offline': '已下线',
-  'searchTable.form.search': '查询',
-  'searchTable.form.reset': '重置',
-  'searchTable.form.selectDefault': '全部',
-  'searchTable.operation.create': '新建',
-  'searchTable.operation.import': '批量导入',
-  'searchTable.operation.download': '下载',
-  // columns
-  'searchTable.columns.index': '#',
-  'searchTable.columns.number': '集合编号',
-  'searchTable.columns.name': '集合名称',
-  'searchTable.columns.contentType': '内容体裁',
-  'searchTable.columns.filterType': '筛选方式',
-  'searchTable.columns.count': '内容量',
-  'searchTable.columns.createdTime': '创建时间',
-  'searchTable.columns.status': '状态',
-  'searchTable.columns.operations': '操作',
-  'searchTable.columns.operations.view': '查看',
-
-  // size
-  'searchTable.size.mini': '迷你',
-  'searchTable.size.small': '偏小',
-  'searchTable.size.medium': '中等',
-  'searchTable.size.large': '偏大',
-  // actions
-  'searchTable.actions.refresh': '刷新',
-  'searchTable.actions.density': '密度',
-  'searchTable.actions.columnSetting': '列设置',
-};

+ 0 - 35
src/views/list/search-table/mock.ts

@@ -1,35 +0,0 @@
-import Mock from 'mockjs';
-import qs from 'query-string';
-import setupMock, { successResponseWrap } from '@/utils/setup-mock';
-import { GetParams } from '@/types/global';
-
-const { Random } = Mock;
-
-const data = Mock.mock({
-  'list|55': [
-    {
-      'id|8': /[A-Z][a-z][-][0-9]/,
-      'number|2-3': /[0-9]/,
-      'name|4-8': /[A-Z]/,
-      'contentType|1': ['img', 'horizontalVideo', 'verticalVideo'],
-      'count|2-3': /[0-9]/,
-      'status|1': ['online', 'offline'],
-      'filterType|1': ['artificial', 'rules'],
-      'createdTime': Random.datetime(),
-    },
-  ],
-});
-
-setupMock({
-  setup() {
-    Mock.mock(new RegExp('/api/list/policy'), (params: GetParams) => {
-      const { current = 1, pageSize = 10 } = qs.parseUrl(params.url).query;
-      const p = current as number;
-      const ps = pageSize as number;
-      return successResponseWrap({
-        list: data.list.slice((p - 1) * ps, p * ps),
-        total: 55,
-      });
-    });
-  },
-});