Bladeren bron

feat: 增加归档列表

gemercheung 1 jaar geleden
bovenliggende
commit
5226d3494b

+ 2 - 2
.vscode/settings.json

@@ -90,11 +90,11 @@
     "editor.defaultFormatter": "esbenp.prettier-vscode"
   },
   "editor.codeActionsOnSave": {
-    "source.fixAll.eslint": true
+    "source.fixAll.eslint": "explicit"
   },
   "[vue]": {
     "editor.codeActionsOnSave": {
-      "source.fixAll.eslint": false
+      "source.fixAll.eslint": "never"
     }
   },
   "i18n-ally.localesPaths": ["src/locales/lang"],

File diff suppressed because it is too large
+ 2229 - 2087
pnpm-lock.yaml


+ 3 - 2
src/api/scene/model.ts

@@ -12,7 +12,7 @@ export interface bindAnchorListParam {
 export interface SceneDownloadParam {
   sceneNum?: string;
   num?: string;
-  isObj?: number;
+  isObj?: number | null;
 }
 
 export interface SceneEditParam {
@@ -75,7 +75,8 @@ export interface sceneItem {
   updateUserId: number;
 }
 export interface SceneDownloadModel {
-  downloadStatus?: number;
+  downloadStatus: number;
+  downloadUrl: string;
 }
 export interface GetDownloadProcessModel {
   percent: number;

+ 2 - 0
src/locales/lang/ja/routes/dashboard.ts

@@ -31,4 +31,6 @@ export default {
   staffList: '従業員リスト',
   feedback: 'フィードバック',
   feedbackList: 'フィードバックリスト',
+  archive: '归档管理',
+  archiveList: '归档列表',
 };

+ 2 - 0
src/locales/lang/zh-CN/routes/dashboard.ts

@@ -31,4 +31,6 @@ export default {
   staffList: '员工列表',
   feedback: '反馈管理',
   feedbackList: '反馈列表',
+  archive: '归档管理',
+  archiveList: '归档列表',
 };

+ 39 - 0
src/router/routes/modules/archive.ts

@@ -0,0 +1,39 @@
+import type { AppRouteModule } from '/@/router/types';
+import { RoleEnum } from '/@/enums/roleEnum';
+import { LAYOUT } from '/@/router/constant';
+import { t } from '/@/hooks/web/useI18n';
+
+const scenes: AppRouteModule = {
+  path: '/archive',
+  name: 'Archive',
+  component: LAYOUT,
+  redirect: '/archive/list',
+  meta: {
+    icon: 'fluent-mdl2:archive',
+    title: t('routes.dashboard.archive'),
+    orderNo: 108,
+    roles: [RoleEnum.PLAT_ADMIN, RoleEnum.COMPANY_ADMIN],
+  },
+  children: [
+    // {
+    //   path: 'down',
+    //   name: 'ScenesDownload',
+    //   component: () => import('/@/views/scenes/download.vue'),
+    //   meta: {
+    //     title: t('routes.dashboard.scenesDownload'),
+    //     icon: 'mdi:box-download',
+    //   },
+    // },
+    {
+      path: 'list',
+      name: 'ArchiveList',
+      component: () => import('/@/views/archive/list.vue'),
+      meta: {
+        title: t('routes.dashboard.archiveList'),
+        icon: 'gravity-ui:chart-bar',
+      },
+    },
+  ],
+};
+
+export default scenes;

+ 100 - 0
src/views/archive/addLiveModal.vue

@@ -0,0 +1,100 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="register"
+    :title="t('routes.scenes.addLive')"
+    @ok="handleSubmit"
+  >
+    <div class="pt-20px">
+      <BasicForm @register="registerForm">
+        <!-- <template #label="{ model, field }">
+          {{ model[field] }}
+        </template>
+        <template #process> {{ downloadInfo.process }} % </template>
+        <template #status> {{ downloadInfo.status }} </template> -->
+      </BasicForm>
+    </div>
+    <template #centerFooter> </template>
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent, ref } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  // import { BasicTable, useTable, BasicColumn, FormSchema } from '/@/components/Table';
+  // import { useMessage } from '/@/hooks/web/useMessage';
+  // import { checkUserAddAble } from '/@/api/corporation/modal';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { brandTypeListApi } from '/@/api/scene/live';
+  // import { bindAnchorListParam } from '/@/api/scene/model';
+  // import { Time } from '/@/components/Time';
+  // import { useUserStore } from '/@/store/modules/user';
+  const { t } = useI18n();
+  const schemas: FormSchema[] = [
+    {
+      field: 'type',
+      label: t('common.type'),
+      component: 'ApiSelect',
+      colProps: {
+        xl: 5,
+        xxl: 5,
+      },
+      componentProps: {
+        api: brandTypeListApi,
+        resultField: 'list',
+        labelField: 'name',
+        valueField: 'id',
+        params: {
+          page: 1,
+          limit: 1000,
+        },
+      },
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicModal, BasicForm },
+    props: {
+      userData: { type: Object },
+    },
+    emits: ['register', 'success'],
+    setup() {
+      // const { createMessage } = useMessage();
+      const sceneNum = ref('');
+
+      const [registerForm, { setFieldsValue }] = useForm({
+        schemas: schemas,
+        labelWidth: 100,
+        showActionButtonGroup: false,
+
+        actionColOptions: {
+          span: 24,
+        },
+        // submitFunc: handleSubmit,
+      });
+      const [register, { closeModal }] = useModalInner((data) => {
+        data && onDataReceive(data);
+      });
+
+      function onDataReceive(data) {
+        console.log('Data Received', data, data.num);
+
+        setFieldsValue({
+          ...data,
+        });
+
+        sceneNum.value = data.num;
+      }
+      const handleSubmit = async () => {};
+
+      return {
+        t,
+        register,
+        schemas,
+        handleSubmit,
+        closeModal,
+        registerForm,
+      };
+    },
+  });
+</script>

+ 257 - 0
src/views/archive/bindModal.vue

@@ -0,0 +1,257 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="register"
+    :title="t('routes.scenes.bindAnchor')"
+    width="800px"
+    @ok="handleSubmit"
+    @cancel="clearSelectedRowKeys"
+  >
+    <div class="pt-2px pr-3px">
+      <BasicTable
+        @register="registerTable"
+        :searchInfo="searchInfo"
+        :rowSelection="{ type: 'checkbox', onChange: handleSelect }"
+      >
+        <template #headerTop>
+          <div class="pt-4 pb-4">
+            {{ t('routes.scenes.sceneName') }}: {{ headerInfo?.sceneName }}
+            {{ t('routes.scenes.anchorRoom') }}:{{ headerInfo?.name }}</div
+          >
+        </template>
+        <template #canShowSwitch="{ record }">
+          <div>
+            <Switch
+              :disabled="!SelectRowsList.includes(record.id)"
+              v-model:checked="record.canShow"
+              :checkedChildren="t('layout.setting.on')"
+              :unCheckedChildren="t('layout.setting.off')"
+            />
+          </div>
+        </template>
+      </BasicTable>
+      <!-- <BasicForm @register="registerForm" :model="model" /> -->
+    </div>
+    <template #centerFooter>
+      <!-- <a-button>xxxx</a-button> -->
+    </template>
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, h, ref, computed } from 'vue';
+  import { Switch } from 'ant-design-vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  // import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { BasicTable, useTable, BasicColumn, FormSchema } from '/@/components/Table';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  // import { checkUserAddAble } from '/@/api/corporation/modal';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  // bindAnchorListApi
+  import { bindOldAnchorListApi, bindUserApi } from '/@/api/scene/live';
+  import { bindAnchorListParam } from '/@/api/scene/model';
+  import { Time } from '/@/components/Time';
+  // import { useUserStore } from '/@/store/modules/user';
+
+  const { t } = useI18n();
+  const { createMessage } = useMessage();
+  const schemas: FormSchema[] = [
+    {
+      field: 'own',
+      label: t('routes.scenes.own'),
+      component: 'Input',
+    },
+  ];
+  const columns: BasicColumn[] = [
+    {
+      title: 'ID',
+      dataIndex: 'id',
+      fixed: 'left',
+      width: 40,
+    },
+    {
+      title: t('routes.scenes.userName'),
+      dataIndex: 'userName',
+      width: 100,
+    },
+    {
+      title: t('common.roleName'),
+      dataIndex: 'roleName',
+      width: 100,
+    },
+
+    {
+      title: t('common.mobile'),
+      dataIndex: 'phone',
+      width: 100,
+    },
+    {
+      title: t('routes.scenes.canShow'),
+      dataIndex: 'canShow',
+      slots: { customRender: 'canShowSwitch' },
+      width: 140,
+    },
+    {
+      title: t('routes.scenes.bindTime'),
+      dataIndex: 'createTime',
+      width: 100,
+      customRender: ({ record }) => {
+        return (
+          record.createTime &&
+          h(Time, {
+            value: record.createTime,
+            mode: 'datetime',
+          })
+        );
+      },
+    },
+  ];
+  export default defineComponent({
+    components: { BasicModal, BasicTable, Switch },
+    props: {
+      userData: { type: Object },
+    },
+    emits: ['register', 'success'],
+    setup(_, { emit }) {
+      const [register, { closeModal }] = useModalInner((data) => {
+        data && onDataReceive(data);
+      });
+      const SelectRowsList = computed(() => {
+        const data = getSelectRowKeys();
+        return data;
+      });
+      const mapCheckedValue = computed(() => (key) => {
+        return key === 1 ? true : false;
+      });
+      const checked = ref<boolean>(false);
+      const headerInfo = reactive<Recordable>({});
+      const searchInfo = reactive<Recordable>({});
+
+      const [
+        registerTable,
+        {
+          reload,
+          getSelectRows,
+          getSelectRowKeys,
+          clearSelectedRowKeys,
+          setSelectedRowKeys,
+          getRawDataSource,
+        },
+      ] = useTable({
+        title: t('routes.scenes.anchorList'),
+        api: bindOldAnchorListApi,
+        columns: columns,
+        useSearchForm: false,
+        // formConfig: searchForm,
+        showTableSetting: false,
+        tableSetting: { fullScreen: true },
+        showIndexColumn: false,
+        immediate: false,
+        isCanResizeParent: true,
+        rowKey: 'id',
+        pagination: false,
+        clickToRowSelect: false,
+        bordered: true,
+        afterFetch: (data) => {
+          console.log('data', data);
+          const res = data.map((i) => {
+            i.canShow = i.canShow === 1 ? true : false;
+            return i;
+          });
+          console.log('res', res);
+
+          const bindIds = data
+            .filter((i) => i.isBind === 1)
+            .reduce((pre, current) => {
+              return pre.concat(current['id']);
+            }, []);
+          console.log('bindIds', bindIds);
+          data.map((i) => {
+            i.canShow === 1 ? true : false;
+            return i;
+          });
+          setSelectedRowKeys(bindIds);
+        },
+      });
+
+      function onDataReceive(data) {
+        console.log('Data Received', data.id);
+        searchInfo.brandId = data.id;
+        headerInfo.name = data.name;
+        headerInfo.sceneName = data.sceneName;
+        searchInfo.limit = 1000;
+        searchInfo.page = 1;
+        reload();
+        // const rawData = getRawDataSource();
+
+        // if (rawData.list.re) {
+        //   console.log('存在已邦,选择');
+        //   setSelectedRowKeys([Number(data.bindShowerId)]);
+        // }
+      }
+      const handleSubmit = async () => {
+        try {
+          const rows = getSelectRows();
+          const rawData = getRawDataSource();
+          let paramsRow: bindAnchorListParam[];
+          console.log('rows', rows);
+          if (rows?.length > 0) {
+            paramsRow = rows.map((row) => {
+              return {
+                brandId: String(searchInfo.brandId),
+                canShow: row.canShow ? 1 : 0,
+                type: 1,
+                userId: String(row.id),
+              } as bindAnchorListParam;
+            });
+            await bindUserApi(paramsRow);
+            createMessage.success(t('common.optSuccess'));
+          } else {
+            const unBindUser = rawData.list
+              .filter((i) => i.isBind === 1)
+              .map((item) => {
+                let param: bindAnchorListParam = {};
+                param.canShow = item.canShow ? 1 : 0;
+                param.type = -1;
+                param.brandId = searchInfo.brandId;
+                param.userId = String(item.id);
+                return param;
+              });
+            console.log('unBindUser', unBindUser);
+            await bindUserApi(unBindUser);
+            createMessage.success(t('common.optSuccess'));
+          }
+          closeModal();
+          emit('success');
+          clearSelectedRowKeys();
+        } catch (error) {
+          console.log('error', error);
+        }
+      };
+      const handleSelect = async () => {
+        // const keys = getSelectRowKeys();
+        // console.log('key', key);
+      };
+      const handleChange = (val, row) => {
+        console.log('val,row', val, row);
+        // updateTableDataRecord('canShow', values);
+        // updateTableDataRecord
+      };
+      return {
+        register,
+        schemas,
+        registerTable,
+        handleSubmit,
+        searchInfo,
+        closeModal,
+        handleSelect,
+        headerInfo,
+        clearSelectedRowKeys,
+        handleChange,
+        t,
+        checked,
+        SelectRowsList,
+        mapCheckedValue,
+      };
+    },
+  });
+</script>

+ 5 - 0
src/views/archive/download.vue

@@ -0,0 +1,5 @@
+<template>
+  <div> 场景下载 </div>
+</template>
+
+<script lang="ts" setup></script>

+ 170 - 0
src/views/archive/downloadModal.vue

@@ -0,0 +1,170 @@
+<template>
+  <BasicModal
+    v-bind="$attrs"
+    @register="register"
+    :title="t('routes.scenes.downloadScene')"
+    :showCancelBtn="false"
+    :okText="downloadInfo.isDownloaded ? t('common.okText') : t('routes.scenes.cancelDownload')"
+    @ok="handleSubmit"
+    @cancel="cancelDownload"
+  >
+    <div class="pt-20px">
+      <BasicForm @register="registerForm">
+        <template #label="{ model, field }">
+          {{ model[field] }}
+        </template>
+        <template #process> {{ downloadInfo.process }} % </template>
+        <template #status> {{ downloadInfo.status }} </template>
+      </BasicForm>
+    </div>
+    <template #centerFooter>
+      <!-- <a-button>xxxx</a-button> -->
+    </template>
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, ref, watch } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  // import { BasicTable, useTable, BasicColumn, FormSchema } from '/@/components/Table';
+  // import { useMessage } from '/@/hooks/web/useMessage';
+  // import { checkUserAddAble } from '/@/api/corporation/modal';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { getDownloadProcessApi } from '/@/api/scene/list';
+  // import { bindAnchorListParam } from '/@/api/scene/model';
+  // import { Time } from '/@/components/Time';
+  // import { useUserStore } from '/@/store/modules/user';
+  import {
+    downloadByUrl,
+    // downloadByData,
+    // downloadByBase64,
+    // downloadByOnlineUrl,
+  } from '/@/utils/file/download';
+  const { t } = useI18n();
+  const schemas: FormSchema[] = [
+    {
+      field: 'sceneName',
+      label: t('routes.scenes.sceneName') + ':',
+      component: 'Input',
+      slot: 'label',
+    },
+    {
+      field: 'process',
+      label: t('routes.scenes.process') + ':',
+      component: 'Input',
+      slot: 'process',
+    },
+    {
+      field: 'status',
+      label: t('component.upload.fileStatue') + ':',
+      component: 'Input',
+      slot: 'status',
+    },
+  ];
+
+  export default defineComponent({
+    components: { BasicModal, BasicForm },
+    props: {
+      userData: { type: Object },
+    },
+    emits: ['register', 'success'],
+    setup() {
+      const { t } = useI18n();
+      // const { createMessage } = useMessage();
+      const sceneNum = ref('');
+      const isObj = ref<Number>(0);
+      const finishDowloadUrl = ref('');
+      const downloadInfo = reactive<Recordable>({});
+      downloadInfo.timer = null;
+      downloadInfo.process = 0;
+      downloadInfo.status = t('component.upload.downloadState');
+      downloadInfo.isDownloaded = false;
+
+      const [registerForm, { setFieldsValue }] = useForm({
+        schemas: schemas,
+        labelWidth: 120,
+        showActionButtonGroup: false,
+
+        actionColOptions: {
+          span: 24,
+        },
+        // submitFunc: handleSubmit,
+      });
+      const [register, { closeModal }] = useModalInner((data) => {
+        data && onDataReceive(data);
+      });
+
+      function onDataReceive(data) {
+        console.log('Data Received', data, data.num);
+        downloadInfo.timer = null;
+        downloadInfo.process = 0;
+        downloadInfo.status = t('component.upload.downloadState');
+        downloadInfo.isDownloaded = false;
+        setFieldsValue({
+          ...data,
+        });
+        isObj.value = data.isObj;
+        sceneNum.value = data.num;
+      }
+      const handleSubmit = async () => {
+        try {
+          cancelDownload();
+          closeModal();
+          if (downloadInfo.isDownloaded) {
+            downloadByUrl({
+              url: finishDowloadUrl.value as any as string,
+              target: '_self',
+            });
+          }
+        } catch (error) {}
+      };
+      async function getDownloadInfo(sceneNum: string) {
+        let param = {
+          num: sceneNum,
+          isObj: isObj.value,
+        };
+        downloadInfo.timer = setInterval(async () => {
+          const res = await getDownloadProcessApi(param);
+          console.log('res', res);
+          const percent = res.percent && Math.round(res.percent);
+          downloadInfo.process = percent;
+          if (res.status === 1000) {
+            downloadInfo.status = t('component.upload.getting');
+          }
+          if (res.status === 1002 && res.url?.length > 0) {
+            cancelDownload();
+            finishDowloadUrl.value = res.url;
+            downloadInfo.isDownloaded = true;
+            downloadInfo.status = t('component.upload.gettingSuccess');
+            handleSubmit();
+          }
+        }, 2000);
+      }
+      function cancelDownload() {
+        clearInterval(downloadInfo.timer);
+        sceneNum.value = '';
+      }
+      watch(
+        () => sceneNum.value,
+        () => {
+          console.log('sceneNum', sceneNum.value);
+          if (sceneNum.value) {
+            getDownloadInfo(sceneNum.value);
+          }
+        },
+      );
+
+      return {
+        t,
+        register,
+        schemas,
+        handleSubmit,
+        closeModal,
+        registerForm,
+        downloadInfo,
+        cancelDownload,
+      };
+    },
+  });
+</script>

+ 402 - 0
src/views/archive/list.vue

@@ -0,0 +1,402 @@
+<template>
+  <PageWrapper contentBackground>
+    <template #footer>
+      <a-tabs v-model:activeKey="tableType" @change="changeTable">
+        <a-tab-pane :key="0" :tab="t('routes.scenes.4dkk')" :disabled="loading" />
+        <a-tab-pane :key="1" :tab="t('routes.scenes.4dkj')" :disabled="loading" />
+        <a-tab-pane :key="2" :tab="t('routes.scenes.4dssdy')" :disabled="loading" />
+        <a-tab-pane :key="4" :tab="t('routes.scenes.obj')" :disabled="loading" />
+        <!-- <a-tab-pane :key="3" tab="四维双目Lite" :disabled="loading"/>  -->
+      </a-tabs>
+    </template>
+    <div class="desc-wrap-BasicTable">
+      <BasicTable
+        @register="registerTable"
+        :rowSelection="{ type: 'checkbox', onChange: handleSelect }"
+      >
+        <template #toolbar>
+          <!-- <a-button type="primary" @click="() => {}"> 新增</a-button> -->
+          <!-- <a-button type="primary" color="warning" @click="() => {}"> 编辑</a-button>
+        <a-button type="primary" color="error" @click="() => {}"> 删除</a-button> -->
+        </template>
+
+        <template #cover="{ record }">
+          <TableImg
+            :size="120"
+            :simpleShow="true"
+            :imgList="[record.thumb || '/resource/img/header.jpg']"
+          />
+        </template>
+        <template #link="{ record }">
+          <!-- <a
+            v-if="record.status != 0"
+            :href="record.webSite + `&lang=${isJA ? 'ja' : 'zh'}`"
+            target="_blank"
+          >
+            {{ record.webSite }}
+          </a> -->
+          <span>{{ record.webSite }}</span>
+        </template>
+        <template #action="{ record }">
+          <TableAction
+            :actions="[
+              {
+                color: 'success',
+                label: '复原',
+                // disabled: record.status != -2,
+                onClick: openSceneEditor.bind(null, record),
+              },
+            ]"
+          />
+        </template>
+      </BasicTable>
+      <DownloadModal @register="registerDownloadModal" />
+    </div>
+  </PageWrapper>
+</template>
+<script lang="ts">
+  import { defineComponent, computed, h, ref } from 'vue';
+  import { openUrl } from '/@/utils/auth';
+  import { PageWrapper } from '/@/components/Page';
+  import {
+    BasicTable,
+    useTable,
+    BasicColumn,
+    FormProps,
+    TableAction,
+    TableImg,
+  } from '/@/components/Table';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useModal } from '/@/components/Modal';
+  import { Tabs } from 'ant-design-vue';
+  import { sceneDetail, buildSceneObj } from '/@/api/lastApi/index';
+  // import { Progress } from 'ant-design-vue';
+  // import { h } from 'vue';
+  // addDownloadNumApi,
+  // checkDownloadApi,
+  // generateSceneEditTokenApi,
+  import {
+    ListApi,
+    downloadSceneDataAPi,
+    addDownloadNumApi,
+    checkDownloadApi,
+    DeleteApi,
+    UpgradeToV4,
+    sceneCopy,
+  } from '/@/api/scene/list';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import {
+    downloadByUrl,
+    // downloadByData,
+    // downloadByBase64,
+    // downloadByOnlineUrl,
+  } from '/@/utils/file/download';
+
+  import { useUserStore } from '/@/store/modules/user';
+  import DownloadModal from './downloadModal.vue';
+  import { useLocaleStore } from '/@/store/modules/locale';
+  import { SceneDownloadParam } from '/@/api/scene/model';
+  const localeStore = useLocaleStore();
+  console.log('localeStore', localeStore);
+  const userStore = useUserStore();
+
+  export default defineComponent({
+    components: {
+      BasicTable,
+      TableAction,
+      TableImg,
+      DownloadModal,
+      PageWrapper,
+      [Tabs.name]: Tabs,
+      [Tabs.TabPane.name]: Tabs.TabPane,
+    },
+    setup() {
+      const { createMessage, createConfirm } = useMessage();
+      const [registerDownloadModal, { openModal: openDownloadModal }] = useModal();
+      const { t } = useI18n();
+      const loading = ref(false);
+      const tableType = ref<Number>(0); //0看看 、1看见、2深时
+      const isJA = computed(() => localeStore.getLocale === 'ja');
+      const columns: BasicColumn[] = [
+        {
+          title: 'ID',
+          dataIndex: 'id',
+          width: 80,
+          defaultHidden: true,
+        },
+        {
+          title: t('routes.scenes.sceneName'),
+          dataIndex: 'sceneName',
+          ellipsis: false,
+          width: 120,
+        },
+        {
+          title: t('routes.corporation.enterpriseName'),
+          dataIndex: 'companyName',
+          ellipsis: false,
+          width: 120,
+        },
+        {
+          title: t('routes.scenes.webSite'),
+          dataIndex: 'webSite',
+          ellipsis: false,
+          slots: { customRender: 'link' },
+          width: 180,
+        },
+        {
+          title: t('routes.scenes.appListPicUrl'),
+          dataIndex: 'thumb',
+          ellipsis: true,
+          slots: { customRender: 'cover' },
+          width: 150,
+        },
+        {
+          title: t('routes.scenes.childName'),
+          dataIndex: 'childName',
+          width: 120,
+        },
+        {
+          title: t('routes.scenes.viewCount'),
+          dataIndex: 'viewCount',
+          width: 100,
+        },
+        {
+          title: t('routes.scenes.createTime'),
+          dataIndex: 'createTime',
+          width: 140,
+        },
+
+        {
+          title: t('routes.scenes.num'),
+          dataIndex: 'num',
+          width: 180,
+        },
+
+        // {
+        //   title: t('routes.scenes.process'),
+        //   dataIndex: '',
+        //   width: 180,
+        //   slots: { customRender: 'process' },
+        //   ifShow: false,
+        // },
+
+        {
+          title: t('common.operation'),
+          dataIndex: '',
+          slots: { customRender: 'action' },
+          width: isJA.value ? 100 : 100,
+          fixed: 'right',
+        },
+      ];
+
+      const searchForm: Partial<FormProps> = {
+        labelWidth: 100,
+        schemas: [
+          {
+            field: 'companyName',
+            label: t('routes.corporation.enterpriseName'),
+            component: 'Input',
+            colProps: {
+              lg: 6,
+              xl: 6,
+              xxl: 6,
+              sm: 12,
+              xs: 24,
+            },
+          },
+          {
+            field: 'sceneName',
+            label: t('routes.scenes.sceneName'),
+            component: 'Input',
+            colProps: {
+              lg: 6,
+              xl: 6,
+              xxl: 6,
+              sm: 12,
+              xs: 24,
+            },
+          },
+          {
+            field: 'childName',
+            label: t('routes.scenes.childName'),
+            component: 'Input',
+            colProps: {
+              lg: 6,
+              xl: 6,
+              xxl: 6,
+              sm: 12,
+              xs: 24,
+            },
+          },
+        ],
+      };
+      // { getForm }
+      const [registerTable, { reload, getSelectRowKeys }] = useTable({
+        title: t('routes.scenes.sceneList'),
+        api: ListApi,
+        columns: columns,
+        useSearchForm: true,
+        formConfig: searchForm,
+        showTableSetting: true,
+        searchInfo: { type: tableType },
+        tableSetting: { fullScreen: true },
+        clickToRowSelect: true,
+        showIndexColumn: true,
+        rowKey: 'num',
+        beforeFetch: (T) => {
+          loading.value = true;
+          return T;
+        },
+        afterFetch: (T) => {
+          loading.value = false;
+          return T;
+        },
+      });
+      async function handleGenerate(record: Recordable) {
+        let { data } = await sceneDetail({ id: record.id });
+        let { buildObjStatus } = data.data;
+        let toastText =
+          buildObjStatus == 2
+            ? t('routes.scenes.objTips.Modifying')
+            : buildObjStatus == 1
+            ? t('routes.scenes.objTips.coverData')
+            : t('routes.scenes.objTips.updateSuccess');
+        console.log('buildObjStatus', data);
+        if (data.code === 200) {
+          createConfirm({
+            iconType: 'warning',
+            title: () => h('span', t('routes.scenes.creatobj')),
+            content: () => h('span', toastText),
+            onOk: async () => {
+              if (buildObjStatus !== 2) {
+                await buildSceneObj({ id: record.id });
+              }
+              createMessage.success(t('common.optSuccess'));
+              reload();
+            },
+          });
+        } else {
+          createMessage.error(t(`apiCode.errCode${data.code}`));
+        }
+      }
+      function handleLivestream(item) {
+        let url = item.webSite;
+        let page = url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.html'));
+        url = url.replace(page, 'rtc-live');
+        window.open(url.replace('http://', 'https://') + (isJA.value ? '&lang=ja' : ''), '_blank');
+      }
+      function handleCopy(item) {
+        createConfirm({
+          iconType: 'warning',
+          title: () => h('span', t('routes.scenes.copyInfi.title')),
+          content: () => h('span', t('routes.scenes.copyInfi.content')),
+          onOk: async () => {
+            await sceneCopy(item.num);
+            createMessage.success(t('common.optSuccess'));
+            reload();
+          },
+        });
+      }
+      function handleUpgrade(item) {
+        createConfirm({
+          iconType: 'warning',
+          title: () => h('span', t('routes.scenes.upgradeMessg.title')),
+          content: () => h('span', t('routes.scenes.upgradeMessg.text')),
+          onOk: async () => {
+            console.log('item', item);
+            let res = await UpgradeToV4(item.num);
+            console.log('res', res);
+            createMessage.success(t('common.optSuccess'));
+            reload();
+          },
+        });
+      }
+      async function openSceneEditor(record: Recordable) {
+        try {
+          const langtext = isJA.value ? 'ja' : 'zh';
+          const token = userStore.getToken; //&token=${token}
+          let url = record.webSite.replace('smobile', 'epc') + `&lang=${langtext}`;
+          if (tableType.value == 4 || tableType.value == 2) {
+            url = url + `&token=${token}`;
+          }
+          if (record.isUpgrade == 1) {
+            url = url.replace('smg', 'epg');
+          }
+          openUrl(url);
+        } catch (error) {
+          console.log('error', error);
+        }
+      }
+      async function handleDelete(record: Recordable) {
+        console.log('DeleteApi', record);
+        await DeleteApi(record.num);
+        createMessage.success(t('common.optSuccess'));
+        reload();
+      }
+
+      async function handleDownloadScene(record: Recordable) {
+        let param: SceneDownloadParam = {
+          num: record.num,
+          isObj: null,
+        };
+        if (tableType.value == 4 || tableType.value == 2) {
+          param.isObj = tableType.value == 4 ? 1 : 0;
+        }
+        await addDownloadNumApi(param);
+        // SceneDownloadModel
+        const checker = await checkDownloadApi(param);
+        if (checker.downloadStatus < 3) {
+          const res = await downloadSceneDataAPi(param);
+          console.log('res', res);
+          openDownloadModal(true, { ...record, isObj: param.isObj });
+        } else {
+          downloadByUrl({
+            url: checker.downloadUrl,
+            target: '_self',
+          });
+        }
+      }
+      function changeTable(val: Number) {
+        tableType.value = val;
+        reload();
+      }
+      const handleSelect = async () => {
+        const keys = getSelectRowKeys();
+        console.log('key', keys);
+      };
+      return {
+        registerTable,
+        createMessage,
+        t,
+        handleGenerate,
+        openSceneEditor,
+        handleDownloadScene,
+        handleDelete,
+        handleLivestream,
+        handleUpgrade,
+        registerDownloadModal,
+        changeTable,
+        handleCopy,
+        tableType,
+        loading,
+        isJA,
+        handleSelect,
+      };
+    },
+  });
+</script>
+<style scoped>
+  :deep(.ant-table-tbody > tr > td:not(.ant-table-selection-column, .ant-table-cell-fix-right)) {
+    /* background-color: gray; */
+    opacity: 0.5;
+  }
+  :deep(.ant-table-tbody
+      > tr.ant-table-row-selected
+      > td:not(.ant-table-selection-column, .ant-table-cell-fix-right)) {
+    /* background-color: gray; */
+    opacity: 0.6;
+  }
+  /* :deep(.ant-table-tbody > tr.ant-table-row-selected > td) {
+    background-color: red !important;
+  } */
+</style>

+ 268 - 0
src/views/archive/live.vue

@@ -0,0 +1,268 @@
+<template>
+  <div class="p-4">
+    <BasicTable @register="registerTable" :rowSelection="{ type: 'checkbox' }">
+      <template #toolbar>
+        <a-button type="primary" @click="handleLiveOpen"> 新增</a-button>
+        <!-- <a-button type="primary" color="warning" @click="() => {}"> 编辑</a-button>
+        <a-button type="primary" color="error" @click="() => {}"> 删除</a-button> -->
+      </template>
+      <template #cover="{ record }">
+        <TableImg
+          v-if="record.appListPicUrl"
+          :size="150"
+          :simpleShow="true"
+          :imgList="[record.appListPicUrl]"
+        />
+      </template>
+      <template #houseType="{ record }">
+        {{ renderHouseType(record.houseType) }}
+      </template>
+      <template #action="{ record }">
+        <TableAction
+          :actions="[
+            {
+              icon: 'eos-icons:role-binding',
+              label: t('routes.scenes.bindAnchor'),
+              color: 'success',
+              onClick: handleBindAnchor.bind(null, record),
+            },
+            {
+              icon: 'ant-design:delete-outlined',
+              color: 'warning',
+              label: '编辑',
+              onClick: () => {},
+            },
+            {
+              icon: 'ant-design:delete-outlined',
+              color: 'error',
+              label: '删除',
+              popConfirm: {
+                title: '是否确认删除',
+                confirm: () => {
+                  createMessage.info(`暂未接入`);
+                },
+              },
+            },
+          ]"
+        />
+      </template>
+    </BasicTable>
+    <bindModal @register="registerBindModal" @success="reload" />
+    <!-- <addLiveModal @register="registeraddLiveModal" /> -->
+    <LiveDrawer @register="registerLiveDrawer" />
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import {
+    BasicTable,
+    useTable,
+    BasicColumn,
+    // FormSchema,
+    FormProps,
+    TableAction,
+    TableImg,
+  } from '/@/components/Table';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  // import { uploadApi } from '/@/api/sys/upload';
+  import { Tag } from 'ant-design-vue';
+  import { h } from 'vue';
+  import { ListApi, brandTypeListApi } from '/@/api/scene/live';
+  import { useI18n } from '/@/hooks/web/useI18n';
+  import { useModal } from '/@/components/Modal';
+  import { useDrawer } from '/@/components/Drawer';
+  import bindModal from './bindModal.vue';
+
+  import LiveDrawer from './liveDrawer.vue';
+  export default defineComponent({
+    components: { BasicTable, TableAction, TableImg, bindModal, LiveDrawer },
+    setup() {
+      const { createMessage } = useMessage();
+      const { t } = useI18n();
+      const [registerBindModal, { openModal: openBindModal }] = useModal();
+
+      const [registerLiveDrawer, { openDrawer: openLiveDrawer }] = useDrawer();
+
+      const columns: BasicColumn[] = [
+        {
+          title: 'ID',
+          dataIndex: 'id',
+          fixed: 'left',
+          width: 100,
+        },
+        {
+          title: t('routes.scenes.anchorRoom'),
+          dataIndex: 'name',
+          ellipsis: false,
+          width: 130,
+        },
+        {
+          title: t('common.type'),
+          dataIndex: 'houseType',
+          slots: { customRender: 'houseType' },
+          width: 100,
+        },
+        {
+          title: t('routes.scenes.appListPicUrl'),
+          dataIndex: 'appListPicUrl',
+          slots: { customRender: 'cover' },
+          width: 150,
+        },
+        {
+          title: t('routes.scenes.sortOrder'),
+          dataIndex: 'sortOrder',
+          width: 150,
+          sorter: true,
+        },
+        {
+          title: t('routes.scenes.webSite'),
+          dataIndex: 'liveRoomUrl',
+          slots: { customRender: 'link' },
+          width: 180,
+        },
+        {
+          title: t('routes.scenes.bindShowerNameList'),
+          dataIndex: 'bindShowerNameList',
+          ellipsis: false,
+          width: 180,
+        },
+
+        {
+          title: t('routes.scenes.livestreamStatus'),
+          dataIndex: 'livestreamStatus',
+          width: 180,
+          customRender: ({ record }) => {
+            const enable = record.livestreamStatus === 1;
+            const color = enable ? 'green' : 'red';
+            const text = enable ? t('common.yes') : t('common.no');
+            return h(Tag, { color: color }, () => text);
+          },
+        },
+
+        {
+          title: t('common.operation'),
+          dataIndex: '',
+          slots: { customRender: 'action' },
+          width: 250,
+          fixed: 'right',
+        },
+      ];
+
+      const searchForm: Partial<FormProps> = {
+        labelWidth: 100,
+        schemas: [
+          {
+            field: 'sceneName',
+            label: t('routes.scenes.anchorRoom'),
+            component: 'Input',
+
+            colProps: {
+              xl: 5,
+              xxl: 5,
+            },
+          },
+          {
+            field: 'type',
+            label: t('common.type'),
+            component: 'ApiSelect',
+            colProps: {
+              xl: 5,
+              xxl: 5,
+            },
+            componentProps: {
+              api: brandTypeListApi,
+              resultField: 'list',
+              labelField: 'name',
+              valueField: 'id',
+              params: {
+                page: 1,
+                limit: 1000,
+              },
+            },
+          },
+          {
+            field: 'livestreamStatus',
+            label: t('routes.scenes.livestreamStatus'),
+            component: 'Select',
+            colProps: {
+              xl: 5,
+              xxl: 5,
+            },
+            componentProps: {
+              options: [
+                {
+                  label: t('common.all'),
+                  value: '',
+                  key: '0',
+                },
+                {
+                  label: t('common.yes'),
+                  value: 1,
+                  key: '1',
+                },
+                {
+                  label: t('common.no'),
+                  value: 0,
+                  key: '2',
+                },
+              ],
+            },
+          },
+        ],
+      };
+      function renderHouseType(type: number): string {
+        switch (type) {
+          case 0:
+            return t(`routes.scenes.houseType.0`);
+          case 1:
+            return t(`routes.scenes.houseType.1`);
+          case 2:
+            return t(`routes.scenes.houseType.2`);
+          case 3:
+            return t(`routes.scenes.houseType.3`);
+          default:
+            return t(`routes.scenes.houseType.9`);
+        }
+      }
+
+      const [registerTable, { reload }] = useTable({
+        title: t(`routes.scenes.liveBroadcast`),
+        api: ListApi,
+        columns: columns,
+        useSearchForm: true,
+        formConfig: searchForm,
+        showTableSetting: true,
+        tableSetting: { fullScreen: true },
+        showIndexColumn: false,
+        rowKey: 'id',
+        pagination: { pageSize: 20 },
+        clickToRowSelect: false,
+        defSort: {
+          field: 'order',
+          order: 'asc',
+        },
+      });
+
+      function handleBindAnchor(record: Recordable) {
+        console.log('record', record);
+        openBindModal(true, record);
+      }
+      function handleLiveOpen(record: Recordable) {
+        console.log('record', record);
+        openLiveDrawer(true, record);
+      }
+      return {
+        registerTable,
+        createMessage,
+        renderHouseType,
+        t,
+        registerBindModal,
+        handleBindAnchor,
+
+        reload,
+        registerLiveDrawer,
+        handleLiveOpen,
+      };
+    },
+  });
+</script>

+ 228 - 0
src/views/archive/liveDrawer.vue

@@ -0,0 +1,228 @@
+<template>
+  <BasicDrawer
+    v-bind="$attrs"
+    @register="registerDrawer"
+    showFooter
+    :title="getTitle"
+    width="60%"
+    @ok="handleSubmit"
+  >
+    <div class="entry-x">
+      <BasicForm @register="registerForm">
+        <template #map>
+          <!-- <Card style="width: 300px; height: 300px"> -->
+          <div ref="wrapRef" style="width: 100%; height: 400px"></div>
+          <!-- </Card> -->
+        </template>
+      </BasicForm>
+    </div>
+  </BasicDrawer>
+</template>
+<script lang="ts">
+  import { defineComponent, ref, computed, unref, nextTick, onMounted, reactive } from 'vue';
+  import { BasicForm, useForm, FormSchema } from '/@/components/Form/index';
+  // import { Card } from 'ant-design-vue';
+  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+
+  // import { useMessage } from '/@/hooks/web/useMessage';
+  import { useI18n } from '/@/hooks/web/useI18n';
+
+  import { brandTypeListApi, uploadLiveApi, getAllSceneApi } from '/@/api/scene/live';
+  import { data as CascaderData } from '/@/utils/cascaderData';
+
+  import { useScript } from '/@/hooks/web/useScript';
+  const A_MAP_URL = 'https://webapi.amap.com/maps?v=2.0&key=e661b00bdf2c44cccf71ef6070ef41b8';
+  // const A_MAP_URL = 'https://webapi.amap.com/maps?v=2.0&key=5a2d384532ae531bf99bd8487c4f03d2';
+  // const A_MAP_URL = 'https://webapi.amap.com/maps?v=1.4.10&key=e661b00bdf2c44cccf71ef6070ef41b8';
+
+  //webapi.amap.com/maps?v=1.4.10&key=e661b00bdf2c44cccf71ef6070ef41b8
+
+  // Card
+  export default defineComponent({
+    name: 'MenuDrawer',
+    components: { BasicDrawer, BasicForm },
+    emits: ['success', 'register'],
+    setup() {
+      const isUpdate = ref(true);
+      const wrapRef = ref<HTMLDivElement | null>(null);
+      const defaultAddress = reactive({
+        address: '山阴路688号恒隆广场B座1217',
+        longt: '山阴路688号恒隆广场B座1217',
+      });
+      console.log('defaultAddress', defaultAddress);
+      const { toPromise } = useScript({ src: A_MAP_URL });
+
+      const { t } = useI18n();
+      // const { createMessage } = useMessage();
+      const schemas: FormSchema[] = [
+        {
+          field: 'type',
+          label: t('routes.scenes.liveType'),
+          component: 'ApiSelect',
+          // colProps: {
+          //   xl: 5,
+          //   xxl: 5,
+          // },
+          componentProps: {
+            api: brandTypeListApi,
+            resultField: 'list',
+            labelField: 'name',
+            valueField: 'id',
+            params: {
+              page: 1,
+              limit: 1000,
+            },
+          },
+        },
+        {
+          field: 'name',
+          component: 'Input',
+          label: t('routes.scenes.liveName'),
+
+          required: true,
+        },
+        {
+          field: 'appListPicUrl',
+          label: t('routes.scenes.appListPicUrl'),
+          component: 'Upload',
+          helpMessage: '推荐大小:400 * 400 像素',
+          required: true,
+          colProps: {
+            span: 10,
+          },
+          componentProps: {
+            api: uploadLiveApi,
+            maxgoodsNumber: 1,
+            afterFetch: function (data) {
+              Reflect.set(data, 'url', data.message.url);
+              return data;
+            },
+            onChange: async () => {
+              await validateFields(['wapBannerUrl']);
+            },
+          },
+        },
+        {
+          field: 'sceneUrl',
+          label: t('routes.scenes.sceneUrl'),
+          component: 'ApiSelect',
+          required: true,
+          colProps: {
+            span: 10,
+          },
+          componentProps: {
+            api: getAllSceneApi,
+          },
+        },
+        // :fieldNames="{ label: 'name', value: 'code', children: 'children' }"
+        {
+          field: 'location',
+          label: '直播间位置',
+          component: 'ApiCascader',
+          labelWidth: 100,
+          componentProps: {
+            api: () => {
+              return CascaderData;
+            },
+            apiParamKey: 'provinceCode',
+            dataField: 'children',
+            labelField: 'name',
+            valueField: 'code',
+            isLeaf: (record) => {
+              return !(record.levelType < 3);
+            },
+          },
+          colProps: {
+            span: 20,
+          },
+        },
+        {
+          field: 'map',
+          label: '地图位置',
+          component: 'Input',
+          labelWidth: 100,
+          slot: 'map',
+          colProps: {
+            span: 20,
+          },
+        },
+      ];
+      // updateSchema, validate
+      const [registerForm, { resetFields, setFieldsValue, validateFields }] = useForm({
+        labelWidth: 120,
+        schemas: schemas,
+        showActionButtonGroup: false,
+        baseColProps: { lg: 24, md: 24 },
+      });
+      // closeDrawer;
+      const [registerDrawer, { setDrawerProps }] = useDrawerInner(async (data) => {
+        resetFields();
+        setDrawerProps({ confirmLoading: false });
+        isUpdate.value = !!data?.isUpdate;
+
+        if (unref(isUpdate)) {
+          console.log('data.record', data);
+
+          setFieldsValue({
+            ...data.record,
+          });
+        }
+        initMap();
+        // updateSchema({
+        //   field: 'parentId',
+        //   componentProps: {
+        //     treeData,
+        //   },
+        // });
+      });
+
+      async function initMap() {
+        await toPromise();
+        await nextTick();
+        const wrapEl = unref(wrapRef);
+        console.log('wrapEl', wrapEl);
+        if (!wrapEl) return;
+        const AMap = (window as any).AMap;
+        console.log('AMap', AMap);
+        // center: [this.longitude || 120.262337, this.latitude || 30.178285],
+        // const geocoder = new AMap.Geocoder({});
+        const map = new AMap.Map(wrapEl, {
+          zoom: 18,
+          center: [120.262337, 30.178285],
+          viewMode: '3D',
+          resizeEnable: true,
+          floorControl: true,
+          showIndoorMap: true,
+        });
+        AMap.plugin('AMap.Geocoder', function () {
+          var geocoder = new AMap.Geocoder({
+            // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
+            city: '010',
+          });
+
+          geocoder.getLocation('北京市海淀区苏州街', function (status, result) {
+            if (status === 'complete' && result.info === 'OK') {
+              // result中对应详细地理坐标信息
+              console.log('result', result);
+            }
+          });
+        });
+
+        const marker = new AMap.Marker({
+          position: new AMap.LngLat(120.262337, 30.178285),
+          title: 'lala',
+        });
+        map.add(marker);
+      }
+      onMounted(() => {
+        initMap();
+      });
+
+      const getTitle = computed(() => (!unref(isUpdate) ? '新增直播间' : '编辑直播间'));
+
+      async function handleSubmit() {}
+
+      return { registerDrawer, registerForm, getTitle, handleSubmit, wrapRef };
+    },
+  });
+</script>

+ 0 - 23
src/views/member/list.vue

@@ -1,26 +1,3 @@
-<!-- 
-avatar: "https://thirdwx.qlogo.cn/mmopen/vi_32/dTbT3X0Fm7BnUA4DoQhBy14smppF5eBibqPSOib3ou5elGuJ1eYZ9sib2ZALDMs1icYupWIxiaJwWETTV8we9brCHhQ/132"
-bindBrandId: null
-bindBrandName: null
-birthday: 631123200000
-brandId: null
-brandName: null
-city: ""
-gender: 1
-id: 25
-isAdmin: 0
-lastLoginIp: "117.136.32.65"
-lastLoginTime: 1631504271000
-levelName: null
-mobile: "13536501128"
-nickname: "波仔"
-password: "oeADe5U9uLeMYsNigq98zdu8J96A"
-registerIp: "117.136.32.65"
-registerTime: 1631504271000
-userLevelId: null
-username: "微信用户f8f4igi4j9ks"
-weixinOpenid: "oeADe5U9uLeMYsNigq98zdu8J96A" 
--->
 <template>
   <div class="p-4">
     <BasicTable @register="registerTable">

+ 2 - 1
src/views/product/category.vue

@@ -79,7 +79,8 @@
           dataIndex: 'isShow',
           width: 80,
           customRender: ({ record }) => {
-            const status = record.isShow;
+            const res = record as unknown as any;
+            const status = res.isShow;
             const enable = status === 1;
             const color = enable ? 'green' : 'red';
             const text = enable ? '启用' : '停用';

+ 4 - 4
src/views/scenes/list.vue

@@ -136,6 +136,7 @@
   import { useUserStore } from '/@/store/modules/user';
   import DownloadModal from './downloadModal.vue';
   import { useLocaleStore } from '/@/store/modules/locale';
+  import { SceneDownloadParam } from '/@/api/scene/model';
   const localeStore = useLocaleStore();
   console.log('localeStore', localeStore);
   const userStore = useUserStore();
@@ -375,7 +376,7 @@
       }
 
       async function handleDownloadScene(record: Recordable) {
-        let param = {
+        let param: SceneDownloadParam = {
           num: record.num,
           isObj: null,
         };
@@ -383,13 +384,12 @@
           param.isObj = tableType.value == 4 ? 1 : 0;
         }
         await addDownloadNumApi(param);
+        // SceneDownloadModel
         const checker = await checkDownloadApi(param);
-        console.log('');
-
         if (checker.downloadStatus < 3) {
           const res = await downloadSceneDataAPi(param);
           console.log('res', res);
-          await openDownloadModal(true, { ...record, isObj: param.isObj });
+          openDownloadModal(true, { ...record, isObj: param.isObj });
         } else {
           downloadByUrl({
             url: checker.downloadUrl,

+ 0 - 31
src/views/scenes/live.vue

@@ -1,34 +1,3 @@
-<!-- address: "浙江省,杭州市,萧山区 山阴路688号恒隆广场B座1217"
-adminId: null
-appListPicUrl: "https://4dkk.4dage.com/shop/huafa/20211206/150212290bc34b.jpg?x-oss-process=image/resize,m_fixed,w_400,h_400"
-bindShowerId: null
-bindShowerName: null
-bindShowerNameList: null
-city: null
-contractPhone: "15975119071"
-createTime: null
-createUserDeptId: 178
-createUserId: 266
-deleted: 0
-id: 1046768
-introduceVideo: null
-introduceVideoCover: null
-latitude: 30.178317
-liveRoomUrl: "https://zfb.4dkankan.com/shop.html?m=zfb-Vs6EY33Ql"
-livestreamStatus: 0
-longitude: 120.262421
-name: "eliaukd"
-picList: ""
-sceneNum: "zfb-Vs6EY33Ql"
-sceneUrl: "https://zfb.4dkankan.com/smobile.html?m=zfb-Vs6EY33Ql"
-shareWxQrCode: "https://houseoss.4dkankan.com/domain/shop/image/zfb-Vs6EY33Ql1638771871311_QRCode.png"
-simpleDesc: "eliauk"
-sortOrder: 101
-token: null
-type: 0
-updateTime: null
-updateUserDeptId: 178
-updateUserId: 427 -->
 <template>
   <div class="p-4">
     <BasicTable @register="registerTable" :rowSelection="{ type: 'checkbox' }">