gemercheung 2 lat temu
rodzic
commit
7b5800b806
57 zmienionych plików z 7895 dodań i 4504 usunięć
  1. 2 2
      .env
  2. 80 0
      .eslintrc.js
  3. 20 2
      package.json
  4. 3534 138
      pnpm-lock.yaml
  5. 10 0
      prettier.config.js
  6. 132 135
      src/App.vue
  7. 216 216
      src/components/basic/FloorSwitch.vue
  8. 4 4
      src/components/basic/button/index.ts
  9. 37 38
      src/components/basic/button/index.vue
  10. 39 39
      src/components/basic/dialog/Alert.vue
  11. 44 46
      src/components/basic/dialog/Confirm.vue
  12. 11 11
      src/components/basic/dialog/Dialog-content.vue
  13. 17 17
      src/components/basic/dialog/Dialog.vue
  14. 53 57
      src/components/basic/dialog/Toast.vue
  15. 58 56
      src/components/basic/dialog/Window.vue
  16. 23 25
      src/components/basic/dialog/index.ts
  17. 42 42
      src/components/basic/dialog/utils.ts
  18. 64 81
      src/components/basic/floorplan.vue
  19. 200 200
      src/components/basic/guide.vue
  20. 40 26
      src/components/basic/icon/images/index.ts
  21. 14 14
      src/components/basic/icon/index.vue
  22. 461 476
      src/components/basic/loading.vue
  23. 47 48
      src/components/basic/miniMap.vue
  24. 605 608
      src/components/basic/title.vue
  25. 63 67
      src/components/chatRoom/chat.vue
  26. 176 181
      src/components/chatRoom/controls/actions.ts
  27. 4 4
      src/components/chatRoom/controls/index.ts
  28. 45 48
      src/components/chatRoom/controls/join.ts
  29. 8 8
      src/components/chatRoom/controls/paint.ts
  30. 11 15
      src/components/chatRoom/controls/sync.ts
  31. 208 236
      src/components/chatRoom/index.vue
  32. 49 55
      src/components/chatRoom/memberList.vue
  33. 47 48
      src/components/chatRoom/roomControl.ts
  34. 17 18
      src/components/chatRoom/roomEvent.ts
  35. 71 71
      src/components/chatRoom/sceneList.vue
  36. 136 143
      src/components/chatRoom/share.vue
  37. 55 59
      src/components/custom/panel.vue
  38. 11 13
      src/components/custom/tagView.vue
  39. 17 19
      src/components/registerComponent.ts
  40. 10 10
      src/hooks/useDraw.ts
  41. 56 56
      src/hooks/useRoom.ts
  42. 337 355
      src/hooks/useTRTC.ts
  43. 38 38
      src/hooks/userApp.ts
  44. 30 34
      src/hooks/userSocket.ts
  45. 44 46
      src/hooks/userTourPlayer.ts
  46. 9 9
      src/main.ts
  47. 2 2
      src/store/index.ts
  48. 110 116
      src/store/modules/app.ts
  49. 226 230
      src/store/modules/rtc.ts
  50. 51 51
      src/store/modules/scene.ts
  51. 33 38
      src/store/modules/tour.ts
  52. 128 104
      src/utils/browser.ts
  53. 20 23
      src/utils/install.ts
  54. 119 118
      src/utils/request.ts
  55. 4 4
      src/utils/typescript.ts
  56. 3 3
      src/vite-env.d.ts
  57. 4 1
      vite.config.ts

+ 2 - 2
.env

@@ -9,6 +9,6 @@ VITE_APP_SOCKET_URL=wss://ws.4dkankan.com
 # 静态资源目录
 VITE_APP_STATIC_DIR=viewer
 # 接口请求地址
-# VITE_APP_APIS_URL=https://test.4dkankan.com/
-VITE_APP_APIS_URL=https://v4-uat.4dkankan.com/
+VITE_APP_APIS_URL=https://test.4dkankan.com/
+# VITE_APP_APIS_URL=https://v4-uat.4dkankan.com/
 VITE_USE_HTTPS=1

+ 80 - 0
.eslintrc.js

@@ -0,0 +1,80 @@
+const { defineConfig } = require('eslint-define-config');
+module.exports = defineConfig({
+  root: true,
+  env: {
+    browser: true,
+    node: true,
+    es6: true,
+  },
+  parser: 'vue-eslint-parser',
+  parserOptions: {
+    parser: '@typescript-eslint/parser',
+    ecmaVersion: 2020,
+    sourceType: 'module',
+    jsxPragma: 'React',
+    ecmaFeatures: {
+      jsx: true,
+    },
+  },
+  extends: [
+    'plugin:vue/vue3-recommended',
+    'plugin:@typescript-eslint/recommended',
+    'prettier',
+    'plugin:prettier/recommended',
+    'plugin:jest/recommended',
+  ],
+  rules: {
+    'vue/script-setup-uses-vars': 'error',
+    '@typescript-eslint/ban-ts-ignore': 'off',
+    '@typescript-eslint/explicit-function-return-type': 'off',
+    '@typescript-eslint/no-explicit-any': 'off',
+    '@typescript-eslint/no-var-requires': 'off',
+    '@typescript-eslint/no-empty-function': 'off',
+    'vue/custom-event-name-casing': 'off',
+    'no-use-before-define': 'off',
+    '@typescript-eslint/no-use-before-define': 'off',
+    '@typescript-eslint/ban-ts-comment': 'off',
+    '@typescript-eslint/ban-types': 'off',
+    '@typescript-eslint/no-non-null-assertion': 'off',
+    '@typescript-eslint/explicit-module-boundary-types': 'off',
+    '@typescript-eslint/no-unused-vars': [
+      'error',
+      {
+        argsIgnorePattern: '^_',
+        varsIgnorePattern: '^_',
+      },
+    ],
+    'no-unused-vars': [
+      'error',
+      {
+        argsIgnorePattern: '^_',
+        varsIgnorePattern: '^_',
+      },
+    ],
+    'space-before-function-paren': 'off',
+
+    'vue/attributes-order': 'off',
+    'vue/one-component-per-file': 'off',
+    'vue/html-closing-bracket-newline': 'off',
+    'vue/max-attributes-per-line': 'off',
+    'vue/multiline-html-element-content-newline': 'off',
+    'vue/singleline-html-element-content-newline': 'off',
+    'vue/attribute-hyphenation': 'off',
+    'vue/require-default-prop': 'off',
+    'vue/require-explicit-emits': 'off',
+    'vue/no-useless-template-attributes': 'off',
+    'vue/html-self-closing': [
+      'error',
+      {
+        html: {
+          void: 'always',
+          normal: 'never',
+          component: 'always',
+        },
+        svg: 'always',
+        math: 'always',
+      },
+    ],
+    'vue/multi-word-component-names': 'off',
+  },
+});

+ 20 - 2
package.json

@@ -6,7 +6,10 @@
     "dev": "vite",
     "build": "vue-tsc  --noEmit && vite build ",
     "preview": "vite preview",
-    "commit": "git add . && git cz"
+    "commit": "git add . && git cz",
+    "lint:eslint": "eslint --max-warnings 0  \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
+    "lint:prettier": "prettier --write  \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
+    "lint:lint-staged": "lint-staged"
   },
   "dependencies": {
     "axios": "^1.1.3",
@@ -23,18 +26,33 @@
   "devDependencies": {
     "@types/node": "^18.11.7",
     "@types/uuid": "^8.3.4",
+    "@typescript-eslint/eslint-plugin": "^5.42.1",
+    "@typescript-eslint/parser": "^5.42.1",
     "@vitejs/plugin-vue": "^3.2.0",
+    "add": "^2.0.6",
     "commitizen": "^4.2.5",
     "cz-customizable": "^7.0.0",
+    "prettier": "^2.7.1",
     "sass": "^1.55.0",
     "typescript": "^4.8.4",
     "vite": "^3.2.0",
+    "vite-plugin-eslint": "^1.8.1",
     "vite-plugin-html-env": "^1.2.7",
     "vite-plugin-mkcert": "^1.10.1",
     "vite-plugin-require-transform": "^1.0.4",
     "vite-plugin-windicss": "^1.8.8",
+    "vue-eslint-parser": "^9.1.0",
     "vue-tsc": "^1.0.9",
-    "windicss": "^3.5.6"
+    "windicss": "^3.5.6",
+    "eslint": "^8.23.1",
+    "eslint-config-prettier": "^8.5.0",
+    "eslint-define-config": "^1.7.0",
+    "eslint-plugin-jest": "^25.7.0",
+    "eslint-plugin-prettier": "^4.2.1",
+    "eslint-plugin-vue": "^8.7.1",
+    "jest": "^27.5.1",
+    "lint-staged": "12.1.4",
+    "npm-run-all": "^4.1.5"
   },
   "config": {
     "commitizen": {

Plik diff jest za duży
+ 3534 - 138
pnpm-lock.yaml


+ 10 - 0
prettier.config.js

@@ -0,0 +1,10 @@
+module.exports = {
+  printWidth: 100,
+  semi: true,
+  vueIndentScriptAndStyle: true,
+  singleQuote: true,
+  trailingComma: 'all',
+  proseWrap: 'never',
+  htmlWhitespaceSensitivity: 'strict',
+  endOfLine: 'auto',
+};

+ 132 - 135
src/App.vue

@@ -1,145 +1,146 @@
 <script setup lang="ts">
-import { onMounted, ref, h, computed, unref, watchEffect } from "vue";
-import { createApp } from "/@/hooks/userApp";
-import tagView from "/@/components/custom/tagView.vue";
-import LoadingLogo from "/@/components/basic/loading.vue";
-import MiniMap from "/@/components/basic/miniMap.vue";
-import FloorplanView from "/@/components/basic/floorplan.vue";
-import { useSceneStore } from "/@/store/modules/scene";
-import type { FloorsType } from "/@/store/modules/scene";
-import { useAppStore } from "./store/modules/app";
-import Guideline from "/@/components/basic/guide.vue";
-import ChatRoom from "/@/components/chatRoom/index.vue";
-import Title from "/@/components/basic/title.vue";
-import FloorSwitch from "/@/components/basic/FloorSwitch.vue";
-import GuidePanel from "/@/components/custom/panel.vue";
-import browser from "/@/utils/browser";
-import { useRtcStore } from "./store/modules/rtc";
-import { useTourPlayer } from "./hooks/userTourPlayer";
+  import { onMounted, ref, h, computed, unref, watchEffect } from 'vue';
+  import { createApp } from '/@/hooks/userApp';
+  import tagView from '/@/components/custom/tagView.vue';
+  import LoadingLogo from '/@/components/basic/loading.vue';
+  import MiniMap from '/@/components/basic/miniMap.vue';
+  import FloorplanView from '/@/components/basic/floorplan.vue';
+  import { useSceneStore } from '/@/store/modules/scene';
+  import type { FloorsType } from '/@/store/modules/scene';
+  import { useAppStore } from './store/modules/app';
+  import Guideline from '/@/components/basic/guide.vue';
+  import ChatRoom from '/@/components/chatRoom/index.vue';
+  import Title from '/@/components/basic/title.vue';
+  import FloorSwitch from '/@/components/basic/FloorSwitch.vue';
+  import GuidePanel from '/@/components/custom/panel.vue';
+  import browser from '/@/utils/browser';
+  import { useRtcStore } from './store/modules/rtc';
+  import { useTourPlayer } from './hooks/userTourPlayer';
+import { KankanMetaDataType } from '/#/sdk';
 
-const { createTourPlayer } = useTourPlayer();
+  const { createTourPlayer } = useTourPlayer();
 
-const sceneStore = useSceneStore();
-const appStore = useAppStore();
-const rtcStore = useRtcStore();
-const dataLoaded = ref(false);
-const scene$ = ref<Nullable<HTMLElement>>(null);
-const refMiniMap = ref<Nullable<string>>(null);
-const flying = computed(() => appStore.flying);
-const player = computed(() => appStore.player);
-const metadata = computed(() => sceneStore.metadata);
-const mode = computed(() => appStore.mode);
-const isJoined = computed(() => rtcStore.isJoined);
-const isLoaded = computed(() => appStore.isLoaded);
-const controls = computed(() => {
-  return metadata.value.controls;
-});
-const floorplanViewShow = computed(() => {
-  return (
-    Boolean(controls.value.showDollhouse) &&
-    Boolean(controls.value.showFloorplan) &&
-    mode.value !== "panorama"
-  );
-});
-const show = ref(false);
-const isTourMode = computed(() => appStore.isTourMode);
-
-watchEffect(() => {
-  console.warn("mode", mode);
-});
-
-onMounted(async () => {
-  const app = await createApp({
-    dom: scene$.value as HTMLElement,
-    num: browser.getURLParam("m"),
-    mobile: true,
+  const sceneStore = useSceneStore();
+  const appStore = useAppStore();
+  const rtcStore = useRtcStore();
+  const dataLoaded = ref(false);
+  const scene$ = ref<Nullable<HTMLElement>>(null);
+  const refMiniMap = ref<Nullable<string>>(null);
+  const flying = computed(() => appStore.flying);
+  const player = computed(() => appStore.player);
+  const metadata = computed(() => sceneStore.metadata);
+  const mode = computed(() => appStore.mode);
+  const isJoined = computed(() => rtcStore.isJoined);
+  const isLoaded = computed(() => appStore.isLoaded);
+  const controls = computed(() => {
+    return metadata.value.controls;
   });
-  // SDK初始化
-  app.use("MinMap", { theme: { camera_fillStyle: "#ED5D18" } });
-  app.use("Tag");
-
-  createTourPlayer();
-
-  app.use("TagView", {
-    render(data) {
-      if (data.media["image"] && data.media["image"].length) {
-        return h(tagView, {
-          sid: data.sid,
-          url: app.resource.getUserResourceURL(data.media["image"][0].src),
-          content: data.content,
-          title: data.title,
-        });
-      }
-      return `<span class="tag-icon animate" style="display:none"></span>`;
-    },
+  const floorplanViewShow = computed(() => {
+    return (
+      Boolean(controls.value.showDollhouse) &&
+      Boolean(controls.value.showFloorplan) &&
+      mode.value !== 'panorama'
+    );
   });
-  app.render();
-  // SDK初始化结束
-  // 暂时isTours url frag 做为 1自由观看模式与带看模式0
+  const show = ref(false);
+  const isTourMode = computed(() => appStore.isTourMode);
 
-  if (Number(browser.getURLParam("isTour")) === 1) {
-    appStore.setIsTourMode(true);
-  } else {
-    appStore.setIsTourMode(false);
-  }
-  // SDK global Event start
-  app.Scene.on("ready", () => {
-    show.value = true;
+  watchEffect(() => {
+    console.warn('mode', mode);
   });
-  app.Scene.on("loaded", (pano) => {
-    refMiniMap.value = "[xui_min_map]";
-    appStore.setFloorId(pano.floorIndex);
 
-    // store.commit("setFloorId", pano.floorIndex);
-    // store.commit("rtc/setShowdaogou", true);
+  onMounted(async () => {
+    const app = await createApp({
+      dom: scene$.value as HTMLElement,
+      num: browser.getURLParam('m'),
+      mobile: true,
+    });
+    // SDK初始化
+    app.use('MinMap', { theme: { camera_fillStyle: '#ED5D18' } });
+    app.use('Tag');
 
-    // if (browser.getURLParam("roomId") && browser.getURLParam("vruserId") && browser.getURLParam("name")) {
-    //   store.commit("showShoppingguide", true);
-    // }
-  });
-  app.store.on("metadata", (metadata: KankanMetaDataType) => {
-    sceneStore.load(metadata);
-    if (!metadata.controls.showMap) {
-      app.MinMap.hide(true);
-    }
-    dataLoaded.value = true;
-    appStore.isLoad();
-  });
-  app.store.on("floorcad", ({ floors }: { floors: FloorsType[] }) => {
-    if (floors?.length) {
-      sceneStore.loadFloorData(floors);
-    }
-  });
-  app.Camera.on("mode.beforeChange", ({ toMode, floorIndex, fromMode }) => {
-    appStore.setMode(toMode);
-    if (toMode != "dollhouse") {
-      appStore.setFloorId(floorIndex);
+    createTourPlayer();
+
+    app.use('TagView', {
+      render(data) {
+        if (data.media['image'] && data.media['image'].length) {
+          return h(tagView, {
+            sid: data.sid,
+            url: app.resource.getUserResourceURL(data.media['image'][0].src),
+            content: data.content,
+            title: data.title,
+          });
+        }
+        return `<span class="tag-icon animate" style="display:none"></span>`;
+      },
+    });
+    app.render();
+    // SDK初始化结束
+    // 暂时isTours url frag 做为 1自由观看模式与带看模式0
+
+    if (Number(browser.getURLParam('isTour')) === 1) {
+      appStore.setIsTourMode(true);
+    } else {
+      appStore.setIsTourMode(false);
     }
-    if (fromMode) {
+    // SDK global Event start
+    app.Scene.on('ready', () => {
+      show.value = true;
+    });
+    app.Scene.on('loaded', (pano) => {
+      refMiniMap.value = '[xui_min_map]';
+      appStore.setFloorId(pano.floorIndex);
+
+      // store.commit("setFloorId", pano.floorIndex);
+      // store.commit("rtc/setShowdaogou", true);
+
+      // if (browser.getURLParam("roomId") && browser.getURLParam("vruserId") && browser.getURLParam("name")) {
+      //   store.commit("showShoppingguide", true);
+      // }
+    });
+    app.store.on('metadata', (metadata: KankanMetaDataType) => {
+      sceneStore.load(metadata);
+      if (!metadata.controls.showMap) {
+        app.MinMap.hide(true);
+      }
+      dataLoaded.value = true;
+      appStore.isLoad();
+    });
+    app.store.on('floorcad', ({ floors }: { floors: FloorsType[] }) => {
+      if (floors?.length) {
+        sceneStore.loadFloorData(floors);
+      }
+    });
+    app.Camera.on('mode.beforeChange', ({ toMode, floorIndex, fromMode }) => {
+      appStore.setMode(toMode);
+      if (toMode != 'dollhouse') {
+        appStore.setFloorId(floorIndex);
+      }
+      if (fromMode) {
+        appStore.setFlying(true);
+      }
+    });
+    app.Camera.on('mode.afterChange', () => {
+      appStore.setFlying(false);
+    });
+    app.Camera.on('flying.started', () => {
       appStore.setFlying(true);
-    }
+    });
+    app.Camera.on('flying.ended', ({ targetPano }) => {
+      appStore.setFlying(false);
+      appStore.setFloorId(targetPano.id);
+    });
   });
-  app.Camera.on("mode.afterChange", () => {
-    appStore.setFlying(false);
-  });
-  app.Camera.on("flying.started", () => {
-    appStore.setFlying(true);
-  });
-  app.Camera.on("flying.ended", ({ targetPano }) => {
-    appStore.setFlying(false);
-    appStore.setFloorId(targetPano.id);
-  });
-});
-// SDK global Event end
+  // SDK global Event end
 
-// method
-const changeMode = (name: string) => {
-  if (!flying.value) {
-    appStore.setMode(name);
-  } else {
-    appStore.setMode(name);
-  }
-};
+  // method
+  const changeMode = (name: string) => {
+    if (!flying.value) {
+      appStore.setMode(name);
+    } else {
+      appStore.setMode(name);
+    }
+  };
 </script>
 
 <template>
@@ -159,11 +160,7 @@ const changeMode = (name: string) => {
       />
       <!-- 小地图 end -->
       <!-- 平面图 start -->
-      <FloorplanView
-        :show="floorplanViewShow"
-        :mode="mode"
-        @change-mode="changeMode"
-      />
+      <FloorplanView :show="floorplanViewShow" :mode="mode" @change-mode="changeMode" />
       <!-- 平面图 end -->
       <!-- 聊天 start-->
       <ChatRoom v-if="!isTourMode" />
@@ -179,5 +176,5 @@ const changeMode = (name: string) => {
 </template>
 
 <style lang="scss">
-@import "./app.scss";
+  @import './app.scss';
 </style>

+ 216 - 216
src/components/basic/FloorSwitch.vue

@@ -24,284 +24,284 @@
   </div>
 </template>
 <script setup lang="ts">
-import { computed } from "vue";
-import { useApp } from "/@/hooks/userApp";
-import { useAppStore } from "/@/store/modules/app";
-import { useSceneStore } from "/@/store/modules/scene";
-import { useTourStore } from "/@/store/modules/tour";
-const appStore = useAppStore();
-const sceneStore = useSceneStore();
-const tourStore = useTourStore();
-const mode = computed(() => appStore.mode);
-const flying = computed(() => appStore.flying);
-const floors = computed(() => sceneStore.floors.reverse());
-const floorId = computed(() => appStore.floorId);
-const showTours = computed(() => tourStore.showTours);
+  import { computed } from 'vue';
+  import { useApp } from '/@/hooks/userApp';
+  import { useAppStore } from '/@/store/modules/app';
+  import { useSceneStore } from '/@/store/modules/scene';
+  import { useTourStore } from '/@/store/modules/tour';
+  const appStore = useAppStore();
+  const sceneStore = useSceneStore();
+  const tourStore = useTourStore();
+  const mode = computed(() => appStore.mode);
+  const flying = computed(() => appStore.flying);
+  const floors = computed(() => sceneStore.floors.reverse());
+  const floorId = computed(() => appStore.floorId);
+  const showTours = computed(() => tourStore.showTours);
 
-const onGotoFloor = (id) => {
-  //   store.commit("setFloor", id);
-  appStore.setFloor(id);
-};
-useApp().then((sdk) =>
-  sdk.Camera.on("mode.beforeChange", ({ toMode, floorIndex }) => {
-    // store.commit("mode", toMode);
-    appStore.setMode(toMode);
-    if (toMode != "dollhouse") {
-      //   store.commit("setFloorId", floorIndex);
-      appStore.setFloorId(floorIndex);
-    }
-  })
-);
+  const onGotoFloor = (id) => {
+    //   store.commit("setFloor", id);
+    appStore.setFloor(id);
+  };
+  useApp().then((sdk) =>
+    sdk.Camera.on('mode.beforeChange', ({ toMode, floorIndex }) => {
+      // store.commit("mode", toMode);
+      appStore.setMode(toMode);
+      if (toMode != 'dollhouse') {
+        //   store.commit("setFloorId", floorIndex);
+        appStore.setFloorId(floorIndex);
+      }
+    }),
+  );
 </script>
 
 <style lang="scss" scoped>
-.floor-switch {
-  pointer-events: all;
-  position: absolute;
-  bottom: calc(100% + 5px);
-  left: 20px;
-  z-index: 10;
-  transition: bottom 0.1s;
-  ul,
-  li {
-    padding: 0;
-    margin: 0;
-  }
-  ul {
-    position: relative;
-    z-index: 2;
-  }
-  li {
-    cursor: pointer;
-    display: flex;
-    align-items: center;
-    position: relative;
-    height: 50px;
-    &:first-child {
-      b {
-        &::before {
-          display: none;
-        }
-      }
-      &.active {
-        b {
-          &::after {
-            bottom: -10px;
-          }
-        }
-      }
-    }
-    &:last-child {
-      b {
-        &::after {
-          display: none;
-        }
-      }
-      &.active {
-        b {
-          &::before {
-            top: -10px;
-          }
-        }
-      }
+  .floor-switch {
+    pointer-events: all;
+    position: absolute;
+    bottom: calc(100% + 5px);
+    left: 20px;
+    z-index: 10;
+    transition: bottom 0.1s;
+    ul,
+    li {
+      padding: 0;
+      margin: 0;
     }
-    b {
+    ul {
       position: relative;
-      width: 16px;
-      height: 16px;
-      background-color: #1c1c1c;
-      border-radius: 50%;
-      box-shadow: 0px 0px 2px 1px #404040;
-      cursor: pointer;
-      &::before {
-        content: "";
-        position: absolute;
-        top: -5px;
-        left: 50%;
-        margin-left: -3px;
-        background: #1c1c1c;
-        width: 6px;
-        height: 6px;
-      }
-      &::after {
-        content: "";
-        position: absolute;
-        bottom: -5px;
-        left: 50%;
-        margin-left: -3px;
-        background: #1c1c1c;
-        width: 6px;
-        height: 6px;
-      }
-    }
-    span {
-      margin-left: 10px;
-      font-size: 14px;
-      //color: #939393;
-      cursor: pointer;
-      color: #eeeeee;
-      text-shadow: 0px 0px 4px rgba(0, 0, 0, 0.5);
-    }
-    &.active {
-      b {
-        left: -6px;
-        width: 28px;
-        height: 28px;
-        border: solid 6px #1c1c1c;
-        background-color: #404040;
-        box-shadow: 0px 0px 2px 1px #404040;
-        &::before {
-          top: -10px;
-        }
-        &::after {
-          bottom: -10px;
-        }
-      }
-      span {
-        margin-left: 0;
-        position: relative;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        height: 32px;
-        color: rgba(255, 255, 255, 0.88);
-        border: solid 4px #1c1c1c;
-        background-color: #404040;
-        border-radius: 32px;
-        box-shadow: 0px 0px 2px 1px #404040;
-        padding: 0px 10px;
-        text-shadow: none;
-        &::before {
-          content: "";
-          position: absolute;
-          left: -10px;
-          background: #1c1c1c;
-          width: 7px;
-          height: 4px;
-          box-shadow: -2px 0px 2px 1px #404040;
-        }
-        &::after {
-          content: "";
-          position: absolute;
-          left: -16px;
-          background: #1c1c1c;
-          width: 6px;
-          height: 11px;
-          border-radius: 50%;
-        }
-      }
-    }
-  }
-  &::after {
-    content: "";
-    position: absolute;
-    left: 5px;
-    top: 20px;
-    bottom: 20px;
-    width: 6px;
-    background: #1c1c1c;
-    box-shadow: 0px 0px 2px 1px #404040;
-    z-index: 1;
-  }
-}
-[is-mobile] {
-  .floor-switch {
-    bottom: 2.5rem;
-    &.showTours {
-      bottom: 5rem;
+      z-index: 2;
     }
     li {
-      height: 45px;
+      cursor: pointer;
+      display: flex;
+      align-items: center;
+      position: relative;
+      height: 50px;
       &:first-child {
+        b {
+          &::before {
+            display: none;
+          }
+        }
         &.active {
           b {
             &::after {
-              bottom: -6px;
+              bottom: -10px;
             }
           }
         }
       }
       &:last-child {
+        b {
+          &::after {
+            display: none;
+          }
+        }
         &.active {
           b {
             &::before {
-              top: -6px;
+              top: -10px;
             }
           }
         }
       }
       b {
-        width: 14px;
-        height: 14px;
+        position: relative;
+        width: 16px;
+        height: 16px;
+        background-color: #1c1c1c;
+        border-radius: 50%;
+        box-shadow: 0px 0px 2px 1px #404040;
+        cursor: pointer;
         &::before {
-          top: -3px;
+          content: '';
+          position: absolute;
+          top: -5px;
           left: 50%;
-          margin-left: -2px;
-          width: 4px;
-          height: 4px;
+          margin-left: -3px;
+          background: #1c1c1c;
+          width: 6px;
+          height: 6px;
         }
         &::after {
-          bottom: -3px;
+          content: '';
+          position: absolute;
+          bottom: -5px;
           left: 50%;
-          margin-left: -2px;
-          width: 4px;
-          height: 4px;
+          margin-left: -3px;
+          background: #1c1c1c;
+          width: 6px;
+          height: 6px;
         }
       }
       span {
-        font-size: 0.36842rem;
+        margin-left: 10px;
+        font-size: 14px;
+        //color: #939393;
+        cursor: pointer;
+        color: #eeeeee;
+        text-shadow: 0px 0px 4px rgba(0, 0, 0, 0.5);
       }
       &.active {
         b {
-          left: -3px;
-          width: 20px;
-          height: 20px;
-          border: solid 4px #1c1c1c;
+          left: -6px;
+          width: 28px;
+          height: 28px;
+          border: solid 6px #1c1c1c;
+          background-color: #404040;
+          box-shadow: 0px 0px 2px 1px #404040;
           &::before {
-            top: -6px;
+            top: -10px;
           }
           &::after {
-            bottom: -6px;
+            bottom: -10px;
           }
         }
         span {
-          height: 30px;
-          border: solid 3px #1c1c1c;
-          border-radius: 30px;
+          margin-left: 0;
+          position: relative;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          height: 32px;
+          color: rgba(255, 255, 255, 0.88);
+          border: solid 4px #1c1c1c;
+          background-color: #404040;
+          border-radius: 32px;
+          box-shadow: 0px 0px 2px 1px #404040;
           padding: 0px 10px;
-          margin-left: 5px;
+          text-shadow: none;
           &::before {
-            left: -11px;
-            width: 10px;
+            content: '';
+            position: absolute;
+            left: -10px;
+            background: #1c1c1c;
+            width: 7px;
             height: 4px;
-            box-shadow: -2px 0px 1px 1px #404040;
+            box-shadow: -2px 0px 2px 1px #404040;
           }
           &::after {
-            left: -14px;
-            width: 3px;
-            height: 6px;
-            border-radius: 40%;
+            content: '';
+            position: absolute;
+            left: -16px;
+            background: #1c1c1c;
+            width: 6px;
+            height: 11px;
+            border-radius: 50%;
           }
         }
       }
     }
     &::after {
+      content: '';
+      position: absolute;
       left: 5px;
       top: 20px;
       bottom: 20px;
-      width: 4px;
+      width: 6px;
+      background: #1c1c1c;
+      box-shadow: 0px 0px 2px 1px #404040;
+      z-index: 1;
     }
   }
-
-  @media (orientation: landscape) {
+  [is-mobile] {
     .floor-switch {
-      bottom: 1rem;
+      bottom: 2.5rem;
+      &.showTours {
+        bottom: 5rem;
+      }
       li {
+        height: 45px;
+        &:first-child {
+          &.active {
+            b {
+              &::after {
+                bottom: -6px;
+              }
+            }
+          }
+        }
+        &:last-child {
+          &.active {
+            b {
+              &::before {
+                top: -6px;
+              }
+            }
+          }
+        }
+        b {
+          width: 14px;
+          height: 14px;
+          &::before {
+            top: -3px;
+            left: 50%;
+            margin-left: -2px;
+            width: 4px;
+            height: 4px;
+          }
+          &::after {
+            bottom: -3px;
+            left: 50%;
+            margin-left: -2px;
+            width: 4px;
+            height: 4px;
+          }
+        }
         span {
-          font-size: 0.25rem;
+          font-size: 0.36842rem;
+        }
+        &.active {
+          b {
+            left: -3px;
+            width: 20px;
+            height: 20px;
+            border: solid 4px #1c1c1c;
+            &::before {
+              top: -6px;
+            }
+            &::after {
+              bottom: -6px;
+            }
+          }
+          span {
+            height: 30px;
+            border: solid 3px #1c1c1c;
+            border-radius: 30px;
+            padding: 0px 10px;
+            margin-left: 5px;
+            &::before {
+              left: -11px;
+              width: 10px;
+              height: 4px;
+              box-shadow: -2px 0px 1px 1px #404040;
+            }
+            &::after {
+              left: -14px;
+              width: 3px;
+              height: 6px;
+              border-radius: 40%;
+            }
+          }
+        }
+      }
+      &::after {
+        left: 5px;
+        top: 20px;
+        bottom: 20px;
+        width: 4px;
+      }
+    }
+
+    @media (orientation: landscape) {
+      .floor-switch {
+        bottom: 1rem;
+        li {
+          span {
+            font-size: 0.25rem;
+          }
         }
       }
     }
   }
-}
 </style>

+ 4 - 4
src/components/basic/button/index.ts

@@ -1,4 +1,4 @@
-import Button from './index.vue'
-import { withInstall } from '/@/utils/install'
-const UIButton = withInstall(Button)
-export default UIButton
+import Button from './index.vue';
+import { withInstall } from '/@/utils/install';
+const UIButton = withInstall(Button);
+export default UIButton;

+ 37 - 38
src/components/basic/button/index.vue

@@ -6,46 +6,45 @@
 </template>
 
 <script lang="ts">
-import { computed, defineComponent } from "vue";
-// import { normalizeUnitToStyle } from '../../utils/index'
-// import UIIcon from '../icon'
+  import { computed, defineComponent } from 'vue';
+  // import { normalizeUnitToStyle } from '../../utils/index'
+  // import UIIcon from '../icon'
 
-export default defineComponent({
-  name: "ui-button",
-  props: {
-    type: {
-      type: String,
-      default: "normal",
+  export default defineComponent({
+    name: 'UiButton',
+    props: {
+      type: {
+        type: String,
+        default: 'normal',
+      },
+      color: {
+        type: String,
+      },
+      width: {
+        type: [String, Number],
+      },
+      icon: {
+        type: String,
+      },
     },
-    color: {
-      type: String,
-    },
-    width: {
-      type: [String, Number],
-    },
-    icon: {
-      type: String,
-    },
-  },
-  setup(props) {
-    const custom = `customize`;
-    const className = computed(() => (props.color ? custom : props.type));
+    setup(props) {
+      const custom = `customize`;
+      const className = computed(() => (props.color ? custom : props.type));
 
-    const style = computed(() => {
-      const style = {
-        width: props.width + "px",
-      };
+      const style = computed(() => {
+        const style = {
+          width: props.width + 'px',
+        };
 
-      if (className.value === custom) {
-        style["--color"] = props.color;
-      }
-      return style;
-    });
-    return {
-      className,
-      style,
-    };
-  },
-});
+        if (className.value === custom) {
+          style['--color'] = props.color;
+        }
+        return style;
+      });
+      return {
+        className,
+        style,
+      };
+    },
+  });
 </script>
-

+ 39 - 39
src/components/basic/dialog/Alert.vue

@@ -1,54 +1,54 @@
 <template>
   <ui-dialog>
-    <template v-slot:header>
+    <template #header>
       <span>{{ title }}</span>
       <i v-if="showCloseIcon" class="iconfont icon-close" @click="close"></i>
     </template>
     <span v-html="content"></span>
-    <template v-slot:footer v-if="showFooter">
+    <template #footer v-if="showFooter">
       <ui-button type="submit" @click="close">{{ okText }}</ui-button>
     </template>
   </ui-dialog>
 </template>
 
 <script lang="ts">
-// @ts-nocheck
-import { defineComponent } from "vue";
-import { isFunction, omit } from "./utils";
-export default defineComponent({
-  name: "ui-alert",
-  props: {
-    showCloseIcon: {
-      type: Boolean,
-      default: true,
+  // @ts-nocheck
+  import { defineComponent } from 'vue';
+  import { isFunction, omit } from './utils';
+  export default defineComponent({
+    name: 'UiAlert',
+    props: {
+      showCloseIcon: {
+        type: Boolean,
+        default: true,
+      },
+      showFooter: {
+        type: Boolean,
+        default: true,
+      },
+      title: {
+        type: String,
+        default: '提示',
+      },
+      okText: {
+        type: String,
+        default: '确定',
+      },
+      func: Function,
+      content: String,
+      destroy: Function,
     },
-    showFooter: {
-      type: Boolean,
-      default: true,
+    setup: function (props, ctx) {
+      const close = () => {
+        if (isFunction(props.func) && props.func() === false) {
+          return;
+        }
+        isFunction(props.destroy) && props.destroy();
+      };
+      return {
+        ...omit(props, 'destroy', 'func'),
+        close,
+      };
     },
-    title: {
-      type: String,
-      default: "提示",
-    },
-    okText: {
-      type: String,
-      default: "确定",
-    },
-    func: Function,
-    content: String,
-    destroy: Function,
-  },
-  setup: function (props, ctx) {
-    const close = () => {
-      if (isFunction(props.func) && props.func() === false) {
-        return;
-      }
-      isFunction(props.destroy) && props.destroy();
-    };
-    return {
-      ...omit(props, "destroy", "func"),
-      close,
-    };
-  },
-});
+  });
 </script>

+ 44 - 46
src/components/basic/dialog/Confirm.vue

@@ -1,64 +1,62 @@
 <template>
   <ui-dialog>
-    <template v-slot:header>
+    <template #header>
       <span>{{ title }}</span>
       <i class="iconfont icon-close" @click="close('no')"></i>
     </template>
     <template v-if="$slots.content">
-      <slot name="content" />
+      <slot name="content"></slot>
     </template>
     <template v-else>
       <div class="message" v-html="content"></div>
     </template>
-    <template v-slot:footer>
-      <UIbutton v-if="!single" type="cancel" @click="close('no')">{{
-        noText
-      }}</UIbutton>
+    <template #footer>
+      <UIbutton v-if="!single" type="cancel" @click="close('no')">{{ noText }}</UIbutton>
       <UIbutton type="primary" @click="close('ok')">{{ okText }}</UIbutton>
     </template>
   </ui-dialog>
 </template>
 <script lang="ts">
-// @ts-nocheck
-import { defineComponent } from "vue";
-import { isFunction, omit } from "./utils";
-import UIbutton from "../button";
-export default defineComponent({
-  name: "ui-confirm",
-  components: { UIbutton },
-  props: {
-    title: {
-      type: String,
-      default: "提示",
+  // @ts-nocheck
+  import { defineComponent } from 'vue';
+  import { isFunction, omit } from './utils';
+  import UIbutton from '../button';
+  export default defineComponent({
+    name: 'UiConfirm',
+    components: { UIbutton },
+    props: {
+      title: {
+        type: String,
+        default: '提示',
+      },
+      okText: {
+        type: String,
+        default: '确定',
+      },
+      noText: {
+        type: String,
+        default: '取消',
+      },
+      single: {
+        type: Boolean,
+        default: false,
+      },
+      func: Function,
+      content: String,
+      destroy: Function,
+      showCloseIcon: Function,
     },
-    okText: {
-      type: String,
-      default: "确定",
+    setup: function (props, ctx) {
+      const close = (result) => {
+        if (isFunction(props.func) && props.func(result) === false) {
+          return;
+        }
+        isFunction(props.destroy) && props.destroy();
+      };
+      return {
+        ...omit(props, 'destroy', 'func'),
+        close,
+      };
     },
-    noText: {
-      type: String,
-      default: "取消",
-    },
-    single: {
-      type: Boolean,
-      default: false,
-    },
-    func: Function,
-    content: String,
-    destroy: Function,
-    showCloseIcon: Function,
-  },
-  setup: function (props, ctx) {
-    const close = (result) => {
-      if (isFunction(props.func) && props.func(result) === false) {
-        return;
-      }
-      isFunction(props.destroy) && props.destroy();
-    };
-    return {
-      ...omit(props, "destroy", "func"),
-      close,
-    };
-  },
-});
+  });
 </script>

+ 11 - 11
src/components/basic/dialog/Dialog-content.vue

@@ -1,17 +1,17 @@
 <template>
   <div class="ui-dialog__box">
-      <header v-if="$slots.header">
-          <slot name="header"></slot>
-      </header>
-      <section>
-          <slot></slot>
-      </section>
-      <footer v-if="$slots.footer">
-          <slot name="footer"></slot>
-      </footer>
+    <header v-if="$slots.header">
+      <slot name="header"></slot>
+    </header>
+    <section>
+      <slot></slot>
+    </section>
+    <footer v-if="$slots.footer">
+      <slot name="footer"></slot>
+    </footer>
   </div>
 </template>
 
 <script>
-export default { name: 'ui-dialog-content' }
-</script>
+  export default { name: 'UiDialogContent' };
+</script>

+ 17 - 17
src/components/basic/dialog/Dialog.vue

@@ -2,27 +2,27 @@
   <teleport to="body">
     <div class="ui-dialog" :style="{ zIndex: zIndex }" v-if="show">
       <dialog-content>
-        <template v-for="(slot, name) in $slots" v-slot:[name]="raw">
-          <slot :name="name" v-bind="raw" />
+        <template v-for="(slot, name) in $slots" #[name]="raw">
+          <slot :name="name" v-bind="raw"></slot>
         </template>
       </dialog-content>
     </div>
   </teleport>
 </template>
 <script lang="ts">
-// @ts-nocheck
-import { defineComponent, ref } from "vue";
-import { getZIndex } from "./utils";
-import DialogContent from "./Dialog-content.vue";
-export default defineComponent({
-  name: "ui-dialog",
-  setup: function (props, ctx) {
-    const show = ref(true);
-    return {
-      show,
-      zIndex: getZIndex(),
-    };
-  },
-  components: { DialogContent },
-});
+  // @ts-nocheck
+  import { defineComponent, ref } from 'vue';
+  import { getZIndex } from './utils';
+  import DialogContent from './Dialog-content.vue';
+  export default defineComponent({
+    name: 'UiDialog',
+    components: { DialogContent },
+    setup: function (props, ctx) {
+      const show = ref(true);
+      return {
+        show,
+        zIndex: getZIndex(),
+      };
+    },
+  });
 </script>

+ 53 - 57
src/components/basic/dialog/Toast.vue

@@ -5,70 +5,66 @@
         <div class="ui-toast__box" :class="[type]">
           <i v-if="type !== 'fixed' && type" class="icon"></i>
           <div class="ui-toast__msg" v-html="content"></div>
-          <i
-            class="iconfont icon-close close"
-            @click="close"
-            v-if="showClose"
-          ></i>
+          <i class="iconfont icon-close close" @click="close" v-if="showClose"></i>
         </div>
       </div>
     </transition>
   </teleport>
 </template>
 <script>
-import { defineComponent, onMounted, nextTick, ref } from "vue";
-import { getZIndex } from "./utils";
-export default defineComponent({
-  name: "ui-toast",
-  props: {
-    type: String,
-    delay: Number,
-    content: String,
-    destroy: Function,
-    close: Function,
-    showClose: Boolean,
-  },
-  setup: function (props, ctx) {
-    const show = ref(true);
-    const close = () => {
-      show.value = false;
-      nextTick(() => {
-        if (typeof props.close == "function") {
-          props.close();
-        }
-        typeof props.destroy === "function" && props.destroy();
-      });
-    };
+  import { defineComponent, onMounted, nextTick, ref } from 'vue';
+  import { getZIndex } from './utils';
+  export default defineComponent({
+    name: 'UiToast',
+    props: {
+      type: String,
+      delay: Number,
+      content: String,
+      destroy: Function,
+      close: Function,
+      showClose: Boolean,
+    },
+    setup: function (props, ctx) {
+      const show = ref(true);
+      const close = () => {
+        show.value = false;
+        nextTick(() => {
+          if (typeof props.close == 'function') {
+            props.close();
+          }
+          typeof props.destroy === 'function' && props.destroy();
+        });
+      };
 
-    if (props.type !== "fixed") {
-      setTimeout(() => close(), props.delay || 3000);
-    }
-    return {
-      show,
-      type: props.type,
-      close,
-      content: props.content,
-      zIndex: getZIndex(),
-    };
-  },
-});
+      if (props.type !== 'fixed') {
+        setTimeout(() => close(), props.delay || 3000);
+      }
+      return {
+        show,
+        type: props.type,
+        close,
+        content: props.content,
+        zIndex: getZIndex(),
+      };
+    },
+  });
 </script>
 <style lang="scss" scoped>
-.slide-down-enter-active,
-.slide-down-leave-active {
-  will-change: transform;
-  transition: all 0.35s ease-in-out;
-}
-.slide-down-enter-from {
-  opacity: 0;
-  transform: translate3d(0, -100%, 0);
-}
-.slide-down-enter {
-  opacity: 1;
-  transform: translate3d(-50%, 100%, 0);
-}
-.slide-down-leave-active {
-  opacity: 0;
-  transform: translate3d(0, -100%, 0);
-}
+  .slide-down-enter-active,
+  .slide-down-leave-active {
+    will-change: transform;
+    transition: all 0.35s ease-in-out;
+  }
+  .slide-down-enter-from {
+    opacity: 0;
+    transform: translate3d(0, -100%, 0);
+  }
+  .slide-down-enter {
+    opacity: 1;
+    transform: translate3d(-50%, 100%, 0);
+  }
+  .slide-down-leave-active {
+    opacity: 0;
+    transform: translate3d(0, -100%, 0);
+  }
 </style>

+ 58 - 56
src/components/basic/dialog/Window.vue

@@ -1,63 +1,65 @@
 <template>
-    <ui-dialog>
-        <template v-slot:header>
-            <span style="font-size: 16px">{{ title }}</span>
-            <i class="iconfont icon-close" @click="onNo" v-if="showCloseIcon"></i>
-        </template>
-        <template v-if="$slots.content">
-            <slot name="content" />
-        </template>
-        <template v-else>
-            {{ content }}
-        </template>
-        <template v-slot:footer>
-            <ui-button type="cancel" @click="onNo" v-if="showCancelButton">{{ noText }}</ui-button>
-            <ui-button :class="{ disabled: !canSubmit }" type="submit primary" @click="onOk">{{ okText }}</ui-button>
-        </template>
-    </ui-dialog>
+  <ui-dialog>
+    <template #header>
+      <span style="font-size: 16px">{{ title }}</span>
+      <i class="iconfont icon-close" @click="onNo" v-if="showCloseIcon"></i>
+    </template>
+    <template v-if="$slots.content">
+      <slot name="content"></slot>
+    </template>
+    <template v-else>
+      {{ content }}
+    </template>
+    <template #footer>
+      <ui-button type="cancel" @click="onNo" v-if="showCancelButton">{{ noText }}</ui-button>
+      <ui-button :class="{ disabled: !canSubmit }" type="submit primary" @click="onOk">{{
+        okText
+      }}</ui-button>
+    </template>
+  </ui-dialog>
 </template>
 <script>
-import { defineComponent } from 'vue'
-export default defineComponent({
-    name: 'ui-window',
+  import { defineComponent } from 'vue';
+  export default defineComponent({
+    name: 'UiWindow',
     props: {
-        title: {
-            type: String,
-            default: '提示'
-        },
-        okText: {
-            type: String,
-            default: '确定'
-        },
-        noText: {
-            type: String,
-            default: '取消'
-        },
-        showCloseIcon: {
-            type: Boolean,
-            default: true
-        },
-        showCancelButton: {
-            type: Boolean,
-            default: true
-        },
-        canSubmit: {
-            type: Boolean,
-            default: true
-        }
+      title: {
+        type: String,
+        default: '提示',
+      },
+      okText: {
+        type: String,
+        default: '确定',
+      },
+      noText: {
+        type: String,
+        default: '取消',
+      },
+      showCloseIcon: {
+        type: Boolean,
+        default: true,
+      },
+      showCancelButton: {
+        type: Boolean,
+        default: true,
+      },
+      canSubmit: {
+        type: Boolean,
+        default: true,
+      },
     },
     emits: ['ok', 'no'],
-    setup: function(props, ctx) {
-        const onNo = () => {
-            ctx.emit('no')
-        }
-        const onOk = () => {
-            ctx.emit('ok')
-        }
-        return {
-            onNo,
-            onOk
-        }
-    }
-})
+    setup: function (props, ctx) {
+      const onNo = () => {
+        ctx.emit('no');
+      };
+      const onOk = () => {
+        ctx.emit('ok');
+      };
+      return {
+        onNo,
+        onOk,
+      };
+    },
+  });
 </script>

+ 23 - 25
src/components/basic/dialog/index.ts

@@ -1,37 +1,35 @@
-// @ts-nocheck 
-import Dialog from "./Dialog.vue";
-import Window from "./Window.vue";
-import Toast from "./Toast.vue";
-import Alert from "./Alert.vue";
-import Confirm from "./Confirm.vue";
-import DialogContent from "./Dialog-content.vue";
-import { createVNode, render } from 'vue'
+// @ts-nocheck
+import Dialog from './Dialog.vue';
+import Window from './Window.vue';
+import Toast from './Toast.vue';
+import Alert from './Alert.vue';
+import Confirm from './Confirm.vue';
+import DialogContent from './Dialog-content.vue';
+import { createVNode, render } from 'vue';
 
 function mount(component, { props, children, element, app } = {}) {
-  let el = element
-  let vNode = createVNode(component, props, children)
+  let el = element;
+  let vNode = createVNode(component, props, children);
 
-  if (app && app._context) vNode.appContext = app._context
-  if (el) render(vNode, el)
+  if (app && app._context) vNode.appContext = app._context;
+  if (el) render(vNode, el);
   else if (typeof document !== 'undefined') {
-    render(vNode, (el = document.createElement('div')))
+    render(vNode, (el = document.createElement('div')));
   }
 
   const destroy = () => {
-    if (el) render(null, el)
-    el = null
-    vNode = null
-  }
-  
+    if (el) render(null, el);
+    el = null;
+    vNode = null;
+  };
 
-  return { vNode, destroy, el }
+  return { vNode, destroy, el };
 }
 // const Dialog =window
 
 Dialog.use = function use(app) {
-
   Dialog.toast = function (options) {
-    if (typeof options == "string") {
+    if (typeof options == 'string') {
       options = {
         content: options,
       };
@@ -58,12 +56,12 @@ Dialog.use = function use(app) {
   };
   Dialog.toast.hide = function () {
     if (Dialog.toast._destroys && Dialog.toast._destroys.length) {
-      let destroy = Dialog.toast._destroys.pop();
+      const destroy = Dialog.toast._destroys.pop();
       destroy && destroy();
     }
   };
   Dialog.alert = function (options) {
-    if (typeof options == "string") {
+    if (typeof options == 'string') {
       options = {
         content: options,
       };
@@ -82,7 +80,7 @@ Dialog.use = function use(app) {
   };
 
   Dialog.confirm = function (options) {
-    if (typeof options == "string") {
+    if (typeof options == 'string') {
       options = {
         content: options,
       };
@@ -91,7 +89,7 @@ Dialog.use = function use(app) {
     let promise;
     if (!options.func) {
       promise = new Promise((resolve) => {
-        options.func = (result) => resolve(result === "ok");
+        options.func = (result) => resolve(result === 'ok');
       });
     }
 

+ 42 - 42
src/components/basic/dialog/utils.ts

@@ -1,57 +1,57 @@
-// @ts-nocheck 
-let zindex = 10000
-import { createVNode, render } from 'vue'
-export const getZIndex = (): number => ++zindex
+// @ts-nocheck
+let zindex = 10000;
+import { createVNode, render } from 'vue';
+export const getZIndex = (): number => ++zindex;
 
 export function mount(component, { props, children, element, app } = {}) {
-    let el = element
-    let vNode = createVNode(component, props, children)
-
-    if (app && app._context) vNode.appContext = app._context
-    if (el) render(vNode, el)
-    else if (typeof document !== 'undefined') {
-        render(vNode, (el = document.createElement('div')))
-    }
-
-    const destroy = () => {
-        if (el) render(null, el)
-        el = null
-        vNode = null
-    }
-
-    return { vNode, destroy, el }
+  let el = element;
+  let vNode = createVNode(component, props, children);
+
+  if (app && app._context) vNode.appContext = app._context;
+  if (el) render(vNode, el);
+  else if (typeof document !== 'undefined') {
+    render(vNode, (el = document.createElement('div')));
+  }
+
+  const destroy = () => {
+    if (el) render(null, el);
+    el = null;
+    vNode = null;
+  };
+
+  return { vNode, destroy, el };
 }
 
 export function setup(...Components) {
-    Components.forEach(Component => {
-        Component.install = function (app) {
-            Component.use && Component.use(app)
-            app.component(Component.name, Component)
-        }
-    })
-
-    return Components
+  Components.forEach((Component) => {
+    Component.install = function (app) {
+      Component.use && Component.use(app);
+      app.component(Component.name, Component);
+    };
+  });
+
+  return Components;
 }
-export const objectToString = Object.prototype.toString
-export const toTypeString = value => objectToString.call(value)
+export const objectToString = Object.prototype.toString;
+export const toTypeString = (value) => objectToString.call(value);
 // 获取制定对象的类型比如toRawType(1) Number
-export const toRawType = value => toTypeString(value).slice(8, -1)
+export const toRawType = (value) => toTypeString(value).slice(8, -1);
 
 /**
  * 判断是否函数
  * @param {any} target 参数对象
  */
-export const isFunction = target => toRawType(target) === 'Function'
+export const isFunction = (target) => toRawType(target) === 'Function';
 
 /**
-* 获取忽略指定属性的对象
-* @param {Object} obj 源对象
-* @param  {...any} props 忽略属性
-*/
+ * 获取忽略指定属性的对象
+ * @param {Object} obj 源对象
+ * @param  {...any} props 忽略属性
+ */
 export function omit(obj, ...props) {
-    const result = { ...obj }
-    props.forEach(function (prop) {
-        delete result[prop]
-    })
-    return result
-}
+  const result = { ...obj };
+  props.forEach(function (prop) {
+    delete result[prop];
+  });
+  return result;
+}

+ 64 - 81
src/components/basic/floorplan.vue

@@ -7,11 +7,7 @@
     class="tab-layer"
   >
     <div class="tabs" v-if="show">
-      <span
-        :class="{ active: isFloorplan }"
-        ref="floorplan_ref"
-        @click="changeMode('floorplan')"
-      >
+      <span :class="{ active: isFloorplan }" ref="floorplan_ref" @click="changeMode('floorplan')">
         <i
           :class="{
             'icon-show_plane_selected': isFloorplan,
@@ -27,11 +23,7 @@
         ></ui-icon> -->
         二维
       </span>
-      <span
-        :class="{ active: isDollhouse }"
-        ref="dollhouse_ref"
-        @click="changeMode('dollhouse')"
-      >
+      <span :class="{ active: isDollhouse }" ref="dollhouse_ref" @click="changeMode('dollhouse')">
         <i
           :class="{
             'icon-show_3d_selected': isDollhouse,
@@ -50,81 +42,72 @@
 </template>
 
 <script lang="ts">
-import {
-  computed,
-  defineComponent,
-  ref,
-  watchEffect,
-  watch,
-  unref,
-} from "vue";
-import { propTypes } from "/@/utils/propTypes";
+  import { computed, defineComponent, ref, watchEffect, watch, unref } from 'vue';
+  import { propTypes } from '/@/utils/propTypes';
 
-export default defineComponent({
-  name: "floorplan",
-  props: {
-    mode: propTypes.string.def(""),
-    disabled: propTypes.bool.def(false),
-    show: propTypes.bool.def(false),
-  },
-  emits: ["changeMode", "toggleMap"],
-  setup(props, { emit }) {
-    const refMiniMap = ref<Nullable<string>>(null);
-    const ifShow = ref(false);
-    const background = ref<Nullable<HTMLElement>>(null);
-    const floorplan_ref = ref<Nullable<HTMLElement>>(null);
-    const dollhouse_ref = ref<Nullable<HTMLElement>>(null);
-    const isFloorplan = computed(() => props.mode === "floorplan");
-    const isDollhouse = computed(() => props.mode === "dollhouse");
-    watchEffect(() => {
-      console.log("floorplan", isFloorplan);
-    });
+  export default defineComponent({
+    name: 'Floorplan',
+    props: {
+      mode: propTypes.string.def(''),
+      disabled: propTypes.bool.def(false),
+      show: propTypes.bool.def(false),
+    },
+    emits: ['changeMode', 'toggleMap'],
+    setup(props, { emit }) {
+      const refMiniMap = ref<Nullable<string>>(null);
+      const ifShow = ref(false);
+      const background = ref<Nullable<HTMLElement>>(null);
+      const floorplan_ref = ref<Nullable<HTMLElement>>(null);
+      const dollhouse_ref = ref<Nullable<HTMLElement>>(null);
+      const isFloorplan = computed(() => props.mode === 'floorplan');
+      const isDollhouse = computed(() => props.mode === 'dollhouse');
+      watchEffect(() => {
+        console.log('floorplan', isFloorplan);
+      });
 
-    watch(
-      () => props.mode,
-      (val, _) => {
-        console.log(val);
-        let timer = setTimeout(() => {
-          clearTimeout(timer);
-          if (val == "floorplan") {
-            if (unref(floorplan_ref) && background.value) {
-              const width =
-                unref(floorplan_ref)?.getBoundingClientRect().width + "px";
-              const offsetLeft = unref(floorplan_ref)?.offsetLeft + "px";
-              background.value.style.width = width;
-              background.value.style.left = offsetLeft;
-            }
-          } else if (val == "dollhouse") {
-            if (unref(dollhouse_ref) && background.value) {
-              const width =
-                unref(dollhouse_ref)?.getBoundingClientRect().width + "px";
-              const offsetLeft = unref(dollhouse_ref)?.offsetLeft + "px";
+      watch(
+        () => props.mode,
+        (val, _) => {
+          console.log(val);
+          let timer = setTimeout(() => {
+            clearTimeout(timer);
+            if (val == 'floorplan') {
+              if (unref(floorplan_ref) && background.value) {
+                const width = unref(floorplan_ref)?.getBoundingClientRect().width + 'px';
+                const offsetLeft = unref(floorplan_ref)?.offsetLeft + 'px';
+                background.value.style.width = width;
+                background.value.style.left = offsetLeft;
+              }
+            } else if (val == 'dollhouse') {
+              if (unref(dollhouse_ref) && background.value) {
+                const width = unref(dollhouse_ref)?.getBoundingClientRect().width + 'px';
+                const offsetLeft = unref(dollhouse_ref)?.offsetLeft + 'px';
 
-              background.value.style.width = width;
-              background.value.style.left = offsetLeft;
+                background.value.style.width = width;
+                background.value.style.left = offsetLeft;
+              }
             }
-          }
-        }, 0);
-      },
-      {
-        deep: true,
-      }
-    );
+          }, 0);
+        },
+        {
+          deep: true,
+        },
+      );
 
-    const changeMode = (eventName: string) => {
-      emit("changeMode", eventName);
-    };
+      const changeMode = (eventName: string) => {
+        emit('changeMode', eventName);
+      };
 
-    return {
-      changeMode,
-      refMiniMap,
-      ifShow,
-      isFloorplan,
-      isDollhouse,
-      floorplan_ref,
-      background,
-      dollhouse_ref
-    };
-  },
-});
+      return {
+        changeMode,
+        refMiniMap,
+        ifShow,
+        isFloorplan,
+        isDollhouse,
+        floorplan_ref,
+        background,
+        dollhouse_ref,
+      };
+    },
+  });
 </script>

+ 200 - 200
src/components/basic/guide.vue

@@ -8,255 +8,255 @@
   </div>
 </template>
 <script lang="ts" setup>
-import { computed } from "vue";
-import { useApp } from "/@/hooks/userApp";
-import { useAppStore } from "/@/store/modules/app";
-import browser from "/@/utils/browser";
+  import { computed } from 'vue';
+  import { useApp } from '/@/hooks/userApp';
+  import { useAppStore } from '/@/store/modules/app';
+  import browser from '/@/utils/browser';
 
-const appStore = useAppStore();
-const isMobile = browser.isMobile();
+  const appStore = useAppStore();
+  const isMobile = browser.isMobile();
 
-const show = computed(() => appStore.player.showUserGuide);
-// const store = useStore();
+  const show = computed(() => appStore.player.showUserGuide);
+  // const store = useStore();
 
-const onSet = () => {
-  // store.commit("showUserGuide", false);
-  // localStorage.setItem("user_guide", Date.now());
-};
-// const getTips = (tips) => {
-//   let text = tips.split("<br />");
-//   return `<span>${text[0]}</span><div>${text[1]}</div>`;
-// };
-useApp().then((app) => {
-  app.Scene.on("loaded", () => {
-    if (!localStorage.getItem("user_guide")) {
-      // store.commit("showUserGuide", true);
-    }
+  const onSet = () => {
+    // store.commit("showUserGuide", false);
+    // localStorage.setItem("user_guide", Date.now());
+  };
+  // const getTips = (tips) => {
+  //   let text = tips.split("<br />");
+  //   return `<span>${text[0]}</span><div>${text[1]}</div>`;
+  // };
+  useApp().then((app) => {
+    app.Scene.on('loaded', () => {
+      if (!localStorage.getItem('user_guide')) {
+        // store.commit("showUserGuide", true);
+      }
+    });
   });
-});
 </script>
 <style lang="scss" scoped>
-.user-guide-overlay {
-  position: fixed;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  z-index: 1099999;
-  background-color: rgba(0, 0, 0, 0.7);
-}
-.user-guide {
-  white-space: normal;
-  position: absolute;
-  top: 50%;
-  left: 1.2rem;
-  right: 1.2rem;
-  border-radius: 0.15rem;
-  color: #fff;
-  transform: translateY(-50%);
-  background-color: rgba(0, 0, 0, 0.7);
-  z-index: 999999;
-  .main {
-    padding: 0.8rem;
-    padding-bottom: 0;
-    h4 {
-      margin: 0;
-      font-size: 0.5rem;
-      text-align: center;
-    }
-    ul,
-    li {
-      list-style: none;
-      padding: 0;
-      margin: 0;
-      width: 100%;
-    }
-    ul {
-      margin: 0.4rem 0;
-    }
-    li {
-      display: flex;
-      align-items: center;
-      padding: 0.6rem 0;
-      i {
-        font-size: 1.2rem;
-      }
-      > div {
-        line-height: 1.6;
-        font-size: 0.4rem;
-        margin-left: 0.35rem;
-      }
-    }
-
-    button {
-      width: 100%;
-      margin-bottom: 0.5rem;
-      background-color: #fff;
-      font-size: 0.4rem;
-      color: #444;
-      height: 1.1rem;
-      border: none;
-      border-radius: 0.15rem;
-      &[type="submit"] {
-        color: #fff;
-        background-color: transparent;
-      }
-    }
+  .user-guide-overlay {
+    position: fixed;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 1099999;
+    background-color: rgba(0, 0, 0, 0.7);
   }
-
-  @media (orientation: landscape) {
-    width: 400px;
-    left: 50% !important;
-    right: auto !important;
-    margin-left: -200px;
+  .user-guide {
+    white-space: normal;
+    position: absolute;
+    top: 50%;
+    left: 1.2rem;
+    right: 1.2rem;
+    border-radius: 0.15rem;
+    color: #fff;
+    transform: translateY(-50%);
+    background-color: rgba(0, 0, 0, 0.7);
+    z-index: 999999;
     .main {
-      padding: 0.5rem;
+      padding: 0.8rem;
+      padding-bottom: 0;
       h4 {
-        font-size: 0.35rem;
+        margin: 0;
+        font-size: 0.5rem;
+        text-align: center;
+      }
+      ul,
+      li {
+        list-style: none;
+        padding: 0;
+        margin: 0;
+        width: 100%;
       }
       ul {
-        margin: 0.3rem 0;
+        margin: 0.4rem 0;
       }
       li {
-        padding: 0.1rem 0;
+        display: flex;
+        align-items: center;
+        padding: 0.6rem 0;
         i {
-          font-size: 0.6rem;
+          font-size: 1.2rem;
         }
         > div {
-          font-size: 0.25rem;
+          line-height: 1.6;
+          font-size: 0.4rem;
+          margin-left: 0.35rem;
         }
       }
 
       button {
-        margin-bottom: 0rem;
-        font-size: 0.3rem;
-        height: 0.8rem;
-      }
-    }
-  }
-}
-.user-guide-mobile {
-  position: absolute;
-  top: 3.15789rem;
-  left: 50%;
-  width: 7.89474rem;
-  transform: translateX(-50%);
-  .zh {
-    width: 100%;
-    height: 7rem;
-    background-image: url(~@/assets/images/guide/novice_guide_text@2x.png);
-    background-size: contain;
-    background-position: center top;
-    background-repeat: no-repeat;
-  }
-  .en {
-    width: 100%;
-    color: #fff;
-    ul,
-    li {
-      list-style: none;
-      padding: 0;
-      margin: 0;
-      width: 100%;
-    }
-    ul {
-      margin: 0;
-    }
-    li {
-      display: flex;
-      align-items: flex-start;
-      padding: 0.5rem 0;
-      &:first-child {
-        padding-top: 0;
-      }
-      i {
-        font-size: 1.32rem;
-      }
-      > div {
+        width: 100%;
+        margin-bottom: 0.5rem;
+        background-color: #fff;
         font-size: 0.4rem;
-        margin-left: 0.3rem;
-        :deep(span) {
-          font-size: 0.6rem;
-          color: #00c2c4;
-        }
-        :deep(div) {
-          font-size: 0.5rem;
-          margin-top: 0.1rem;
-          white-space: pre-line;
-          line-height: 1.3;
+        color: #444;
+        height: 1.1rem;
+        border: none;
+        border-radius: 0.15rem;
+        &[type='submit'] {
+          color: #fff;
+          background-color: transparent;
         }
       }
     }
 
-    .btn {
-      background-image: none;
-      color: #00c2c4;
-      line-height: 1.2rem;
-      text-align: center;
-      font-size: 0.52632rem;
-      background-image: url(~@/assets/images/guide/novice_guide_button_empty@2x.png);
+    @media (orientation: landscape) {
+      width: 400px;
+      left: 50% !important;
+      right: auto !important;
+      margin-left: -200px;
+      .main {
+        padding: 0.5rem;
+        h4 {
+          font-size: 0.35rem;
+        }
+        ul {
+          margin: 0.3rem 0;
+        }
+        li {
+          padding: 0.1rem 0;
+          i {
+            font-size: 0.6rem;
+          }
+          > div {
+            font-size: 0.25rem;
+          }
+        }
+
+        button {
+          margin-bottom: 0rem;
+          font-size: 0.3rem;
+          height: 0.8rem;
+        }
+      }
     }
   }
-  .btn {
+  .user-guide-mobile {
     position: absolute;
-    bottom: -3.15789rem;
+    top: 3.15789rem;
     left: 50%;
-    width: 3.5rem;
-    height: 1.31579rem;
-    background-image: url(~@/assets/images/guide/novice_guide_button@2x.png);
-    background-size: contain;
-    background-position: center top;
-    background-repeat: no-repeat;
+    width: 7.89474rem;
     transform: translateX(-50%);
-  }
-
-  .guide-tips {
-    font-size: 16px;
-    margin-top: 1rem;
-    line-height: 1.5;
-  }
-
-  @media (orientation: landscape) {
-    top: 0.5rem;
     .zh {
-      height: 4rem;
-      .btn {
-        width: 2.5rem;
-        height: 0.8rem;
-        bottom: -1.4rem;
-      }
+      width: 100%;
+      height: 7rem;
+      background-image: url(~@/assets/images/guide/novice_guide_text@2x.png);
+      background-size: contain;
+      background-position: center top;
+      background-repeat: no-repeat;
     }
-
     .en {
+      width: 100%;
+      color: #fff;
+      ul,
       li {
-        padding: 0.15rem 0;
+        list-style: none;
+        padding: 0;
+        margin: 0;
+        width: 100%;
+      }
+      ul {
+        margin: 0;
+      }
+      li {
+        display: flex;
+        align-items: flex-start;
+        padding: 0.5rem 0;
+        &:first-child {
+          padding-top: 0;
+        }
         i {
-          font-size: 1rem;
+          font-size: 1.32rem;
         }
         > div {
+          font-size: 0.4rem;
           margin-left: 0.3rem;
           :deep(span) {
-            font-size: 0.3rem;
+            font-size: 0.6rem;
+            color: #00c2c4;
           }
           :deep(div) {
-            font-size: 0.25rem;
+            font-size: 0.5rem;
             margin-top: 0.1rem;
+            white-space: pre-line;
+            line-height: 1.3;
           }
         }
       }
+
       .btn {
-        height: 0.7rem;
-        line-height: 0.63rem;
-        font-size: 0.25rem;
-        bottom: -0.7rem;
+        background-image: none;
+        color: #00c2c4;
+        line-height: 1.2rem;
+        text-align: center;
+        font-size: 0.52632rem;
+        background-image: url(~@/assets/images/guide/novice_guide_button_empty@2x.png);
+      }
+    }
+    .btn {
+      position: absolute;
+      bottom: -3.15789rem;
+      left: 50%;
+      width: 3.5rem;
+      height: 1.31579rem;
+      background-image: url(~@/assets/images/guide/novice_guide_button@2x.png);
+      background-size: contain;
+      background-position: center top;
+      background-repeat: no-repeat;
+      transform: translateX(-50%);
+    }
+
+    .guide-tips {
+      font-size: 16px;
+      margin-top: 1rem;
+      line-height: 1.5;
+    }
+
+    @media (orientation: landscape) {
+      top: 0.5rem;
+      .zh {
+        height: 4rem;
+        .btn {
+          width: 2.5rem;
+          height: 0.8rem;
+          bottom: -1.4rem;
+        }
+      }
+
+      .en {
+        li {
+          padding: 0.15rem 0;
+          i {
+            font-size: 1rem;
+          }
+          > div {
+            margin-left: 0.3rem;
+            :deep(span) {
+              font-size: 0.3rem;
+            }
+            :deep(div) {
+              font-size: 0.25rem;
+              margin-top: 0.1rem;
+            }
+          }
+        }
+        .btn {
+          height: 0.7rem;
+          line-height: 0.63rem;
+          font-size: 0.25rem;
+          bottom: -0.7rem;
+        }
       }
     }
   }
-}
 
-@media (orientation: landscape) {
-  .user-guide-mobile {
-    overflow-y: auto;
+  @media (orientation: landscape) {
+    .user-guide-mobile {
+      overflow-y: auto;
+    }
   }
-}
 </style>

+ 40 - 26
src/components/basic/icon/images/index.ts

@@ -1,28 +1,42 @@
-import arrow from './arrow@2x.png'
-import arrows from './arrows@2x.png'
-import brushes_selected from './brushes_selected@2x.png'
-import brushes from './brushes@2x.png'
-import chat_off from './chat_off@2x.png'
-import chat_on from './chat_on@2x.png'
-import cross from './cross@2x.png'
-import invitation from './invitation@2x.png'
-import members from './members@2x.png'
-import mic_off_50 from './mic_off_50@2x.png'
-import mic_off from './mic_off@2x.png'
-import mic_on from './mic_on@2x.png'
-import play from './play.png'
-import pop_up_screen_off from './pop-up_screen_off@2x.png'
-import pop_up_screen_on from './pop-up_screen_on@2x.png'
-import revocation_50 from './revocation_50@2x.png'
-import revocation from './revocation@2x.png'
-import scene from './scene.png'
-import show from './show@2x.png'
+import arrow from './arrow@2x.png';
+import arrows from './arrows@2x.png';
+import brushes_selected from './brushes_selected@2x.png';
+import brushes from './brushes@2x.png';
+import chat_off from './chat_off@2x.png';
+import chat_on from './chat_on@2x.png';
+import cross from './cross@2x.png';
+import invitation from './invitation@2x.png';
+import members from './members@2x.png';
+import mic_off_50 from './mic_off_50@2x.png';
+import mic_off from './mic_off@2x.png';
+import mic_on from './mic_on@2x.png';
+import play from './play.png';
+import pop_up_screen_off from './pop-up_screen_off@2x.png';
+import pop_up_screen_on from './pop-up_screen_on@2x.png';
+import revocation_50 from './revocation_50@2x.png';
+import revocation from './revocation@2x.png';
+import scene from './scene.png';
+import show from './show@2x.png';
 
 const icons = {
-    arrow, arrows, brushes_selected,
-    brushes, chat_off, chat_on, cross,
-    invitation, members, mic_off_50, mic_off,
-    mic_on, play, pop_up_screen_off, pop_up_screen_on,
-    revocation_50, revocation, scene, show
-}
-export { icons }
+  arrow,
+  arrows,
+  brushes_selected,
+  brushes,
+  chat_off,
+  chat_on,
+  cross,
+  invitation,
+  members,
+  mic_off_50,
+  mic_off,
+  mic_on,
+  play,
+  pop_up_screen_off,
+  pop_up_screen_on,
+  revocation_50,
+  revocation,
+  scene,
+  show,
+};
+export { icons };

+ 14 - 14
src/components/basic/icon/index.vue

@@ -5,24 +5,24 @@
 </template>
 
 <script setup lang="ts">
-import { computed } from "vue";
-import { icons } from "./images";
+  import { computed } from 'vue';
+  import { icons } from './images';
 
-const props = defineProps({ type: { default: "" } });
-const imageUrl = computed(() => icons[props.type]);
+  const props = defineProps({ type: { default: '' } });
+  const imageUrl = computed(() => icons[props.type]);
 </script>
 
 <style scoped lang="scss">
-.iii-icon {
-  width: 1em;
-  height: 1em;
-  display: inline-block;
+  .iii-icon {
+    width: 1em;
+    height: 1em;
+    display: inline-block;
 
-  img {
-    width: 100%;
-    height: 100%;
-    display: block;
-    object-fit: cover;
+    img {
+      width: 100%;
+      height: 100%;
+      display: block;
+      object-fit: cover;
+    }
   }
-}
 </style>

Plik diff jest za duży
+ 461 - 476
src/components/basic/loading.vue


+ 47 - 48
src/components/basic/miniMap.vue

@@ -3,67 +3,66 @@
     <span class="button-switch" @click.stop="toggleMap">
       <i
         class="iconfont ui-kankan-icon icon tip-h-center tip-v-bottom icon-show_map_collect iconzm-show_map_collect"
-      />
+      ></i>
     </span>
     <div v-if="showDollhouse" class="change" @click="changeMode">
       <i
         class="iconfont ui-kankan-icon icon tip-h-center tip-v-bottom icon-show_3d_normal iconzm-show_3d_normal"
-      />
+      ></i>
       <span> 3D模型</span>
     </div>
   </teleport>
 </template>
 <script lang="ts">
-import { defineComponent, onMounted, watchEffect, ref } from "vue";
-import { propTypes } from "/@/utils/propTypes";
-const refMiniMap = ref<Nullable<string>>(null);
-const ifShow = ref(false);
-const isCollapse = ref(false);
+  import { defineComponent, onMounted, watchEffect, ref } from 'vue';
+  import { propTypes } from '/@/utils/propTypes';
+  const refMiniMap = ref<Nullable<string>>(null);
+  const ifShow = ref(false);
+  const isCollapse = ref(false);
 
-export default defineComponent({
-  name: "minMap",
-  props: {
-    show: propTypes.bool.def(true),
-    showDollhouse: propTypes.bool.def(false),
-    to: {
-      type: String as PropType<Nullable<string>>,
-      default: null,
+  export default defineComponent({
+    name: 'MinMap',
+    props: {
+      show: propTypes.bool.def(true),
+      showDollhouse: propTypes.bool.def(false),
+      to: {
+        type: String as PropType<Nullable<string>>,
+        default: null,
+      },
     },
-  },
-  emits: ["changeMode", "toggleMap"],
-  setup(props, { emit }) {
-    onMounted(() => {
-      watchEffect(() => {
-        if (props.to?.length) {
-          ifShow.value = true;
-          refMiniMap.value = props.to;
-        }
+    emits: ['changeMode', 'toggleMap'],
+    setup(props, { emit }) {
+      onMounted(() => {
+        watchEffect(() => {
+          if (props.to?.length) {
+            ifShow.value = true;
+            refMiniMap.value = props.to;
+          }
+        });
       });
-    });
 
-    
-    const toggleMap = () => {
-      isCollapse.value = !isCollapse.value;
-      emit("toggleMap", isCollapse.value);
-      let $minmap = document.querySelector("[xui_min_map]");
-      if ($minmap) {
-        if (!isCollapse.value) {
-          $minmap.classList.remove("collapse");
-        } else {
-          $minmap.classList.add("collapse");
+      const toggleMap = () => {
+        isCollapse.value = !isCollapse.value;
+        emit('toggleMap', isCollapse.value);
+        let $minmap = document.querySelector('[xui_min_map]');
+        if ($minmap) {
+          if (!isCollapse.value) {
+            $minmap.classList.remove('collapse');
+          } else {
+            $minmap.classList.add('collapse');
+          }
         }
-      }
-    };
-    const changeMode = () => {
-      emit("changeMode", "dollhouse");
-    };
+      };
+      const changeMode = () => {
+        emit('changeMode', 'dollhouse');
+      };
 
-    return {
-      toggleMap,
-      changeMode,
-      refMiniMap,
-      ifShow,
-    };
-  },
-});
+      return {
+        toggleMap,
+        changeMode,
+        refMiniMap,
+        ifShow,
+      };
+    },
+  });
 </script>

Plik diff jest za duży
+ 605 - 608
src/components/basic/title.vue


+ 63 - 67
src/components/chatRoom/chat.vue

@@ -7,9 +7,7 @@
           <!-- <span :class="{ my: i.UserId == user_info.UserId }" class="chat-name">
             {{ i.Nickname }} &nbsp;
           </span> -->
-          <span class="chat-name" :class="{ my: isMe(i.UserId) }">
-            {{ i.Nickname }} &nbsp;
-          </span>
+          <span class="chat-name" :class="{ my: isMe(i.UserId) }"> {{ i.Nickname }} &nbsp; </span>
           <span class="chat-content"> {{ i.text }}</span>
         </div>
       </div>
@@ -18,80 +16,78 @@
 </template>
 
 <script setup lang="ts">
-// import { propTypes } from "/@/utils/propTypes";
+  // import { propTypes } from "/@/utils/propTypes";
 
-import { computed, watch } from "vue";
-import { ChatContentType } from "/@/store/modules/rtc";
-import { propTypes } from "/@/utils/propTypes";
-const props = defineProps({
-  currentUser: propTypes.string.def(""),
-  chatList: {
-    type: Array as PropType<ChatContentType[]>,
-    default: () => [],
-  },
-});
+  import { computed, watch } from 'vue';
+  import { ChatContentType } from '/@/store/modules/rtc';
+  import { propTypes } from '/@/utils/propTypes';
+  const props = defineProps({
+    currentUser: propTypes.string.def(''),
+    chatList: {
+      type: Array as PropType<ChatContentType[]>,
+      default: () => [],
+    },
+  });
 
-const isMe = computed(
-  () => (currentUser: string) => props.currentUser === currentUser
-);
+  const isMe = computed(() => (currentUser: string) => props.currentUser === currentUser);
 
-const chatAutoScroll = () => {
-  let el = document.getElementById("chat");
-  let client_h = document.getElementById("chat")?.clientHeight;
-  let all = document.getElementById("contents")?.clientHeight;
-  // console.log("chatAutoScroll", client_h, all);
-  el?.scrollTo(0, (client_h || 0) + (all || 0));
-};
+  const chatAutoScroll = () => {
+    let el = document.getElementById('chat');
+    let client_h = document.getElementById('chat')?.clientHeight;
+    let all = document.getElementById('contents')?.clientHeight;
+    // console.log("chatAutoScroll", client_h, all);
+    el?.scrollTo(0, (client_h || 0) + (all || 0));
+  };
 
-watch(
-  () => props.chatList,
-  (_) => {
-    chatAutoScroll();
-  },
-  {
-    deep: true,
-    immediate: true,
-  }
-);
+  watch(
+    () => props.chatList,
+    (_) => {
+      chatAutoScroll();
+    },
+    {
+      deep: true,
+      immediate: true,
+    },
+  );
 </script>
 
 <style scoped lang="scss">
-#chat {
-  // width: 7.03rem;
-  width: 50%;
-  max-width: 4rem;
-  max-height: 4.58rem;
-  overflow: auto;
-  position: fixed;
-  left: 0.44rem;
-  bottom: 2.83rem;
-  .chat-item {
-  }
-  .chat-msg {
-    width: auto;
-    border-radius: 0.44rem;
-    background: rgba(0, 0, 0, 0.3);
-    padding: 0.17rem 0.28rem;
-    box-sizing: border-box;
+  #chat {
+    // width: 7.03rem;
+    width: 50%;
+    max-width: 4rem;
+    max-height: 4.58rem;
+    overflow: auto;
+    position: fixed;
+    left: 0.44rem;
+    bottom: 2.83rem;
+    .chat-item {
+    }
+    .chat-msg {
+      width: auto;
+      border-radius: 0.44rem;
+      background: rgba(0, 0, 0, 0.3);
+      padding: 0.17rem 0.28rem;
+      box-sizing: border-box;
 
-    display: inline-block;
-    // margin-bottom: 0.17rem;
-    margin-bottom: 0.1rem;
-    .chat-name {
-      color: #70bbff;
-      font-size: 0.28rem;
-      &.my {
-        color: #ff9a6a;
+      display: inline-block;
+      // margin-bottom: 0.17rem;
+      margin-bottom: 0.1rem;
+      .chat-name {
+        color: #70bbff;
+        font-size: 0.28rem;
+        &.my {
+          color: #ff9a6a;
+        }
+      }
+      .chat-content {
+        color: #fff;
+        font-size: 0.28rem;
+        word-break: break-all;
       }
     }
-    .chat-content {
-      color: #fff;
-      font-size: 0.28rem;
-      word-break: break-all;
+    &::-webkit-scrollbar {
+      display: none;
     }
   }
-  &::-webkit-scrollbar {
-    display: none;
-  }
-}
 </style>

+ 176 - 181
src/components/chatRoom/controls/actions.ts

@@ -1,213 +1,208 @@
-import { useRtcStore } from "/@/store/modules/rtc";
-import type { ChatContentType, UserInfoType } from "/@/store/modules/rtc";
-import Dialog from '/@/components/basic/dialog'
-import { getApp, useApp } from "/@/hooks/userApp";
-import consola from 'consola'
-import { useSocket } from "/@/hooks/userSocket";
-import { useRoom } from "/@/hooks/useRoom";
-
+import { useRtcStore } from '/@/store/modules/rtc';
+import type { ChatContentType, UserInfoType } from '/@/store/modules/rtc';
+import Dialog from '/@/components/basic/dialog';
+import { getApp, useApp } from '/@/hooks/userApp';
+import consola from 'consola';
+import { useSocket } from '/@/hooks/userSocket';
+import { useRoom } from '/@/hooks/useRoom';
 
 interface ActionDataType {
-    type: string;
-    data: any,
-    members?: UserInfoType[],
-    open?: boolean,
-    user?: UserInfoType,
-    userId?: string,
-    words?: boolean
-    muted?: boolean
-
+  type: string;
+  data: any;
+  members?: UserInfoType[];
+  open?: boolean;
+  user?: UserInfoType;
+  userId?: string;
+  words?: boolean;
+  muted?: boolean;
 }
 
-export function handleActions({ data, type, members, open, user, userId, words, muted }: ActionDataType) {
-    switch (type) {
-        case 'user-init':
-            handleUserInit()
-            break;
-        case 'danmumsg':
-            handleDanMumSg(data)
-            break;
-
-        case "changeScene":
-            handleChangeScene(data)
-            break;
-
-        case 'user-join':
-            handleUserJoin(members, user)
-            break;
-        case "user-leave":
-            break;
-
-        case "users-muted":
-            handleUserMuted(userId, muted, members)
-            break
-
-        case "users-words":
-            handleUserSetWords(userId, words, members)
-            break;
-        case "leader-dismiss":
-            handleUserLeave(user, members)
-            break;
-        case "user-paint":
-            handleUserPaint(open)
-            break;
-        case 'tagclick':
-            break;
-        case 'tagclose':
-            break;
-        case 'tag-image-index':
-            handleTagImageIndex(data)
-            break;
-        case 'ask-currentscene':
-            handleAskCurrentscene(data)
-            break;
-        case 'error':
-            Dialog.toast({ content: `房间未找到`, type: "error" });
-        default:
-            break;
-    }
-    if (members?.length) {
-        console.log('发烧的', members)
-    }
-
+export function handleActions({
+  data,
+  type,
+  members,
+  open,
+  user,
+  userId,
+  words,
+  muted,
+}: ActionDataType) {
+  switch (type) {
+    case 'user-init':
+      handleUserInit();
+      break;
+    case 'danmumsg':
+      handleDanMumSg(data);
+      break;
+
+    case 'changeScene':
+      handleChangeScene(data);
+      break;
+
+    case 'user-join':
+      handleUserJoin(members, user);
+      break;
+    case 'user-leave':
+      break;
+
+    case 'users-muted':
+      handleUserMuted(userId, muted, members);
+      break;
+
+    case 'users-words':
+      handleUserSetWords(userId, words, members);
+      break;
+    case 'leader-dismiss':
+      handleUserLeave(user, members);
+      break;
+    case 'user-paint':
+      handleUserPaint(open);
+      break;
+    case 'tagclick':
+      break;
+    case 'tagclose':
+      break;
+    case 'tag-image-index':
+      handleTagImageIndex(data);
+      break;
+    case 'ask-currentscene':
+      handleAskCurrentscene(data);
+      break;
+    case 'error':
+      Dialog.toast({ content: `房间未找到`, type: 'error' });
+    default:
+      break;
+  }
+  if (members?.length) {
+    console.log('发烧的', members);
+  }
 }
 
 //被动处理初始化
 async function handleUserInit() {
-    const rtcStore = useRtcStore();
-    if (rtcStore.role === 'leader') {
-        const app = await useApp();
-        app.Connect.follow.sync();
-        // setTimeout(() => {
-        //     socket.value.emit("action", {
-        //       type: "leader-avatar",
-        //       data: { avatar: leaderAvatar.value },
-        //     });
-        //     if (tagclick.value && tagclick.value.type == "goodlist") {
-        //       socket.value.emit("action", {
-        //         type: "tagclick",
-        //         data: {
-        //           sid: tagclick.value.data.sid,
-        //         },
-        //       });
-        //       if (tagImageIndex.value != null) {
-        //         setTimeout(() => {
-        //           socket.value.emit("action", {
-        //             type: "tag-image-index",
-        //             data: {
-        //               index: tagImageIndex.value,
-        //             },
-        //           });
-        //         }, 200);
-        //       }
-        //     }
-        //   }, 200);
-    }
-
+  const rtcStore = useRtcStore();
+  if (rtcStore.role === 'leader') {
+    const app = await useApp();
+    app.Connect.follow.sync();
+    // setTimeout(() => {
+    //     socket.value.emit("action", {
+    //       type: "leader-avatar",
+    //       data: { avatar: leaderAvatar.value },
+    //     });
+    //     if (tagclick.value && tagclick.value.type == "goodlist") {
+    //       socket.value.emit("action", {
+    //         type: "tagclick",
+    //         data: {
+    //           sid: tagclick.value.data.sid,
+    //         },
+    //       });
+    //       if (tagImageIndex.value != null) {
+    //         setTimeout(() => {
+    //           socket.value.emit("action", {
+    //             type: "tag-image-index",
+    //             data: {
+    //               index: tagImageIndex.value,
+    //             },
+    //           });
+    //         }, 200);
+    //       }
+    //     }
+    //   }, 200);
+  }
 }
 
 // 被动处理弹幕
 function handleDanMumSg(data: ChatContentType) {
-    const rtcStore = useRtcStore();
-    if (data.role == "leader") {
-        data.Nickname = "主持人";
-    }
-    rtcStore.addToChatList(data)
+  const rtcStore = useRtcStore();
+  if (data.role == 'leader') {
+    data.Nickname = '主持人';
+  }
+  rtcStore.addToChatList(data);
 }
 // 其他用户进入
 function handleUserJoin(members?: UserInfoType[], user?: UserInfoType) {
-
-    consola.info({
-        tag: 'socket',
-        message: '有人进来了'
-    })
-    const rtcStore = useRtcStore();
-
-    members && rtcStore.setMemberList(members)
-    if (user) {
-        let name = user.Nickname;
-        if (user.Role === 'leader') {
-            const { socket } = useSocket()
-            name = "主持人";
-            Dialog.toast({ content: `主持人进入房间` });
-            socket.emit("action", { type: "user-init" });
-        }
-        let data: ChatContentType = {
-            role: user?.Role,
-            mode: rtcStore.mode,
-            Nickname: name,
-            UserId: user?.UserId,
-            text: "进入房间",
-        };
-        if (rtcStore.isLeader) {
-            rtcStore.addToChatList(data)
-        }
+  consola.info({
+    tag: 'socket',
+    message: '有人进来了',
+  });
+  const rtcStore = useRtcStore();
+
+  members && rtcStore.setMemberList(members);
+  if (user) {
+    let name = user.Nickname;
+    if (user.Role === 'leader') {
+      const { socket } = useSocket();
+      name = '主持人';
+      Dialog.toast({ content: `主持人进入房间` });
+      socket.emit('action', { type: 'user-init' });
     }
-
+    const data: ChatContentType = {
+      role: user?.Role,
+      mode: rtcStore.mode,
+      Nickname: name,
+      UserId: user?.UserId,
+      text: '进入房间',
+    };
+    if (rtcStore.isLeader) {
+      rtcStore.addToChatList(data);
+    }
+  }
 }
 
 // 其他用户开起画笔通知
 
 async function handleUserPaint(open: boolean | undefined) {
-    const app = await useApp();
-    const rtcStore = useRtcStore();
-    if (!rtcStore.isLeader) {
-        if (open) {
-            console.log(open)
-            app.Connect.paint.show({
-                role: rtcStore.role,
-                paint: false,
-            })
-            Dialog.toast({ content: `主持人开启画笔` });
-        } else {
-            Dialog.toast({ content: `主持人关闭画笔` });
-            app.Connect.paint.hide();
-        }
+  const app = await useApp();
+  const rtcStore = useRtcStore();
+  if (!rtcStore.isLeader) {
+    if (open) {
+      console.log(open);
+      app.Connect.paint.show({
+        role: rtcStore.role,
+        paint: false,
+      });
+      Dialog.toast({ content: `主持人开启画笔` });
+    } else {
+      Dialog.toast({ content: `主持人关闭画笔` });
+      app.Connect.paint.hide();
     }
-
+  }
 }
 
 const handleChangeScene = (data) => {
-    const { changeScene } = useRoom()
-    // debugger
-    changeScene(data)
-
-}
+  const { changeScene } = useRoom();
+  // debugger
+  changeScene(data);
+};
 //
-const handleAskCurrentscene = (data) => {
-
-}
+const handleAskCurrentscene = (data) => {};
 
-const handleTagImageIndex = (data) => {
-
-}
+const handleTagImageIndex = (data) => {};
 
 const handleUserSetWords = (UserId?: string, words?: boolean, members?: UserInfoType[]) => {
-    const rtcStore = useRtcStore();
-    console.log('handleUserSetWords', UserId, words)
-    UserId && rtcStore.updateMemberDatabyId(UserId, {
-        IsWords: words
-    })
-    if (UserId == rtcStore.userId) {
-        Dialog.toast({
-            content: !words
-                ? `主持人设置了禁言`
-                : `主持人已解除禁言`,
-        });
-    }
-}
+  const rtcStore = useRtcStore();
+  console.log('handleUserSetWords', UserId, words);
+  UserId &&
+    rtcStore.updateMemberDatabyId(UserId, {
+      IsWords: words,
+    });
+  if (UserId == rtcStore.userId) {
+    Dialog.toast({
+      content: !words ? `主持人设置了禁言` : `主持人已解除禁言`,
+    });
+  }
+};
 const handleUserMuted = (UserId?: string, muted?: boolean, members?: UserInfoType[]) => {
-    const rtcStore = useRtcStore();
-    console.log('handleUserSetWords', UserId, muted)
-    UserId && rtcStore.updateMemberDatabyId(UserId, {
-        IsMuted: muted
-    })
-    if (UserId == rtcStore.userId) {
-        rtcStore.setMute(!!muted)
-    }
-}
+  const rtcStore = useRtcStore();
+  console.log('handleUserSetWords', UserId, muted);
+  UserId &&
+    rtcStore.updateMemberDatabyId(UserId, {
+      IsMuted: muted,
+    });
+  if (UserId == rtcStore.userId) {
+    rtcStore.setMute(!!muted);
+  }
+};
 
 //被动处理用离开
-const handleUserLeave = (user, members) => {
-
-}
+const handleUserLeave = (user, members) => {};

+ 4 - 4
src/components/chatRoom/controls/index.ts

@@ -1,4 +1,4 @@
-export * from './actions'
-export * from './sync'
-export * from './paint'
-export * from './join'
+export * from './actions';
+export * from './sync';
+export * from './paint';
+export * from './join';

+ 45 - 48
src/components/chatRoom/controls/join.ts

@@ -1,53 +1,50 @@
-import consolaGlobalInstance from "consola";
-import Dialog from "/@/components/basic/dialog";
-import { getApp } from "/@/hooks/userApp";
-import { useRoom } from "/@/hooks/useRoom";
-import { useSocket } from "/@/hooks/userSocket";
-import { UserInfoType, useRtcStore } from "/@/store/modules/rtc";
-const { enterRoom } = useRoom()
+import consolaGlobalInstance from 'consola';
+import Dialog from '/@/components/basic/dialog';
+import { getApp } from '/@/hooks/userApp';
+import { useRoom } from '/@/hooks/useRoom';
+import { useSocket } from '/@/hooks/userSocket';
+import { UserInfoType, useRtcStore } from '/@/store/modules/rtc';
+const { enterRoom } = useRoom();
 
 // 自已join的方法
 export function handleJoin(data: any) {
-    const app = getApp();
-    const  {socket }= useSocket()
-    const members = data?.members as any as UserInfoType[]
-    const user = data?.user as any as UserInfoType
-    enterRoom();
+  const app = getApp();
+  const { socket } = useSocket();
+  const members = data?.members as any as UserInfoType[];
+  const user = data?.user as any as UserInfoType;
+  enterRoom();
 
-    const rtcStore = useRtcStore();
-    rtcStore.setIsJoined(true)
-    consolaGlobalInstance.info({
-        message: data,
-        tag: "socket:enter"
-    })
-    // if (user) {
-    //     console.log('sortList 1 ', rtcStore.userId)
-    //     console.log('sortList 2', rtcStore.memberList)
-    //     const userExsit = rtcStore.checkUserInMemberList(rtcStore.userId)
-    //     console.log('sortList3 ', userExsit)
-    //     console.log('sortList4', user.Id !== userExsit?.Id)
-    //     if (userExsit) {
-    //         Dialog.confirm({
-    //             showCloseIcon: false,
-    //             okText: '我知道了',
-    //             content: "<span style='font-size: 16px; line-height: 1.5;'>您已有登录端在登录,请不要重复登录<span/>",
-    //             title: '隱私條款:',
-    //             single: true,
-    //             func: (state) => {
-    //             },
-    //         });
-    //     }
-    // }
+  const rtcStore = useRtcStore();
+  rtcStore.setIsJoined(true);
+  consolaGlobalInstance.info({
+    message: data,
+    tag: 'socket:enter',
+  });
+  // if (user) {
+  //     console.log('sortList 1 ', rtcStore.userId)
+  //     console.log('sortList 2', rtcStore.memberList)
+  //     const userExsit = rtcStore.checkUserInMemberList(rtcStore.userId)
+  //     console.log('sortList3 ', userExsit)
+  //     console.log('sortList4', user.Id !== userExsit?.Id)
+  //     if (userExsit) {
+  //         Dialog.confirm({
+  //             showCloseIcon: false,
+  //             okText: '我知道了',
+  //             content: "<span style='font-size: 16px; line-height: 1.5;'>您已有登录端在登录,请不要重复登录<span/>",
+  //             title: '隱私條款:',
+  //             single: true,
+  //             func: (state) => {
+  //             },
+  //         });
+  //     }
+  // }
 
-    members && rtcStore.setMemberList(members)
-    if (!rtcStore.isLeader) {
-        setTimeout(() => {
-            socket.emit("action", {
-                type: "user-init",
-            });
-        }, 1500);
-    }
-
-
-
-}
+  members && rtcStore.setMemberList(members);
+  if (!rtcStore.isLeader) {
+    setTimeout(() => {
+      socket.emit('action', {
+        type: 'user-init',
+      });
+    }, 1500);
+  }
+}

+ 8 - 8
src/components/chatRoom/controls/paint.ts

@@ -1,11 +1,11 @@
-import { getApp } from "/@/hooks/userApp";
-import { useRtcStore } from "/@/store/modules/rtc";
+import { getApp } from '/@/hooks/userApp';
+import { useRtcStore } from '/@/store/modules/rtc';
 
 // 畫筆
 export function handleReceivePaint(data: any) {
-    const app = getApp();
-    const rtcStore = useRtcStore();
-    if (!rtcStore.isLeader) {
-        app.Connect.paint.receive(data);
-    }
-}
+  const app = getApp();
+  const rtcStore = useRtcStore();
+  if (!rtcStore.isLeader) {
+    app.Connect.paint.receive(data);
+  }
+}

+ 11 - 15
src/components/chatRoom/controls/sync.ts

@@ -1,19 +1,15 @@
-import { getApp } from "/@/hooks/userApp";
-import { useRtcStore } from "/@/store/modules/rtc";
+import { getApp } from '/@/hooks/userApp';
+import { useRtcStore } from '/@/store/modules/rtc';
 
 // 同屏帶看
 export async function handleSync(data: any) {
-    try {
-        const app = getApp();
-        const rtcStore = useRtcStore();
-        if (!rtcStore.isLeader) {
-            // app.Connect.follow.start({ follow: false });
-            // console.log('app.Connect.follow', app.Connect.follow.started)
-            app.Connect.follow.receive(data);
-        }
-    } catch (error) {
-
+  try {
+    const app = getApp();
+    const rtcStore = useRtcStore();
+    if (!rtcStore.isLeader) {
+      // app.Connect.follow.start({ follow: false });
+      // console.log('app.Connect.follow', app.Connect.follow.started)
+      app.Connect.follow.receive(data);
     }
-
-
-}
+  } catch (error) {}
+}

+ 208 - 236
src/components/chatRoom/index.vue

@@ -1,11 +1,7 @@
 <template>
   <!-- 主区域 start  -->
   <div id="PageRtcLive">
-    <chat
-      v-show="chatShow"
-      :chatList="chatList"
-      :currentUser="currentUser"
-    ></chat>
+    <chat v-show="chatShow" :chatList="chatList" :currentUser="currentUser" />
     <!-- 当前人数 start -->
     <div class="member_number">
       <div class="members"></div>
@@ -14,11 +10,7 @@
     <!-- 当前人数 end -->
     <!-- 控制条 start -->
     <div class="controlBar" v-if="!showInput">
-      <div
-        class="saySomething"
-        @click="onFocus"
-        :class="{ disabled: !inputStatus }"
-      >
+      <div class="saySomething" @click="onFocus" :class="{ disabled: !inputStatus }">
         <!-- <i class="speakIcon"
            :class="{'dis':!user_info.IsWords}"></i> -->
         <span v-if="inputStatus">说点什么~</span>
@@ -72,10 +64,7 @@
             v-model.trim="text"
             :placeholder="`说点什么~`"
           />
-          <span
-            class="iconsend_icon"
-            :class="{ disable: text == '' }"
-            @click.stop="sendText"
+          <span class="iconsend_icon" :class="{ disable: text == '' }" @click.stop="sendText"
             >发送</span
           >
         </div>
@@ -112,254 +101,237 @@
   </template>
   <!-- trtc相关  end -->
 
-  <ShareContainer
-    :share-link="shareLink"
-    @close="shareLink = ''"
-  ></ShareContainer>
+  <ShareContainer :share-link="shareLink" @close="shareLink = ''" />
 </template>
 
 <script lang="ts" setup>
-import {
-  computed,
-  nextTick,
-  onMounted,
-  onUnmounted,
-  ref,
-  unref,
-  watch,
-  watchEffect,
-} from "vue";
-import { getApp, useApp } from "/@/hooks/userApp";
-import { initSocketEvent } from "./roomControl";
-import { createSocket, useSocket } from "/@/hooks/userSocket";
-import { useRtcSdk } from "/@/hooks/useTRTC";
-import { useDraw } from "/@/hooks/useDraw";
-import browser from "/@/utils/browser";
-import ImageIcon from "/@/components/basic/icon/index.vue";
-import { useRtcStore } from "/@/store/modules/rtc";
-import type { SocketParams, RoleType } from "/@/store/modules/rtc";
-import chat from "./chat.vue";
-import memberList from "./memberList.vue";
-import SceneList from "./sceneList.vue";
-import { useRoom } from "/@/hooks/useRoom";
-import consola from "consola";
-import Dialog from "../basic/dialog";
-import { storeToRefs } from "pinia";
-import ShareContainer from "./share.vue";
-// hook
-const { isDrawing, setDraw, setCloseDraw } = useDraw();
-const { initialRoom } = useRoom();
+  import { computed, nextTick, onMounted, onUnmounted, ref, unref, watch, watchEffect } from 'vue';
+  import { getApp, useApp } from '/@/hooks/userApp';
+  import { initSocketEvent } from './roomControl';
+  import { createSocket, useSocket } from '/@/hooks/userSocket';
+  import { useRtcSdk } from '/@/hooks/useTRTC';
+  import { useDraw } from '/@/hooks/useDraw';
+  import browser from '/@/utils/browser';
+  import ImageIcon from '/@/components/basic/icon/index.vue';
+  import { useRtcStore } from '/@/store/modules/rtc';
+  import type { SocketParams, RoleType } from '/@/store/modules/rtc';
+  import chat from './chat.vue';
+  import memberList from './memberList.vue';
+  import SceneList from './sceneList.vue';
+  import { useRoom } from '/@/hooks/useRoom';
+  import consola from 'consola';
+  import Dialog from '../basic/dialog';
+  import { storeToRefs } from 'pinia';
+  import ShareContainer from './share.vue';
+  // hook
+  const { isDrawing, setDraw, setCloseDraw } = useDraw();
+  const { initialRoom } = useRoom();
 
-const rtcStore = useRtcStore();
-const isNativeLeader = computed(() => rtcStore.role == "leader");
+  const rtcStore = useRtcStore();
+  const isNativeLeader = computed(() => rtcStore.role == 'leader');
 
-const showInput = ref(false);
-const chatShow = ref(true);
-const isBrushes = isDrawing;
-const canUndo = ref(false);
-const animateActive = ref(false);
-const showMember = ref(false);
-const disableMic = ref(false);
-const isJoined = computed(() => rtcStore.isJoined);
-const role = computed(() => rtcStore.role);
-const text = ref<string>("");
-const chatList = computed(() => rtcStore.chatList);
-const currentUser = computed(() => rtcStore.userId);
-const inputStatus = computed(() => rtcStore.inputStatus);
+  const showInput = ref(false);
+  const chatShow = ref(true);
+  const isBrushes = isDrawing;
+  const canUndo = ref(false);
+  const animateActive = ref(false);
+  const showMember = ref(false);
+  // const disableMic = ref(false);
+  const isJoined = computed(() => rtcStore.isJoined);
+  const role = computed(() => rtcStore.role);
+  const text = ref<string>('');
+  const chatList = computed(() => rtcStore.chatList);
+  const currentUser = computed(() => rtcStore.userId);
+  const inputStatus = computed(() => rtcStore.inputStatus);
 
-const members = computed(() => rtcStore.memberList);
-const showScenes = ref(false);
-const audioMuted = computed(() => rtcStore.audioMuted);
-const remoteStreams = computed(() => rtcStore.remoteStreams);
-const currentSession = computed(() => rtcStore.currentSession);
+  const members = computed(() => rtcStore.memberList);
+  const showScenes = ref(false);
+  const audioMuted = computed(() => rtcStore.audioMuted);
+  const remoteStreams = computed(() => rtcStore.remoteStreams);
+  const currentSession = computed(() => rtcStore.currentSession);
 
-const shareLink = ref<string>("");
+  const shareLink = ref<string>('');
 
-// watchEffect(() => {
+  // watchEffect(() => {
 
-// });
-watch(
-  () => currentSession,
-  (val) => {
-    console.log("当前currentSession", val.value?.IsWords);
-    rtcStore.setinputStatus(!!val.value?.IsWords);
-  },
-  { deep: true, immediate: true }
-);
-//设置socket 参数
-const initParams: SocketParams = {
-  userId:
-    browser.getURLParam("vruserId") ||
-    `user_${browser.getURLParam("role")}${Math.floor(
-      Math.random() * 100000000
-    )}`,
-  roomId:
-    browser.getURLParam("roomId") ||
-    `room_${Math.floor(Math.random() * 100000000)}`,
-  role: (browser.getURLParam("role") as RoleType) || "leader",
-  avatar: browser.getURLParam("avatar"),
-  nickname: browser.getURLParam("name"),
-  mode: browser.getURLParam("mode"),
-};
-consola.info({
-  message: initParams,
-  tag: "socket参数",
-});
-rtcStore.setSocketParams(initParams);
+  // });
+  watch(
+    () => currentSession,
+    (val) => {
+      console.log('当前currentSession', val.value?.IsWords);
+      rtcStore.setinputStatus(!!val.value?.IsWords);
+    },
+    { deep: true, immediate: true },
+  );
+  //设置socket 参数
+  const initParams: SocketParams = {
+    userId:
+      browser.getURLParam('vruserId') ||
+      `user_${browser.getURLParam('role')}${Math.floor(Math.random() * 100000000)}`,
+    roomId: browser.getURLParam('roomId') || `room_${Math.floor(Math.random() * 100000000)}`,
+    role: (browser.getURLParam('role') as RoleType) || 'leader',
+    avatar: browser.getURLParam('avatar'),
+    nickname: browser.getURLParam('name'),
+    mode: browser.getURLParam('mode'),
+  };
+  consola.info({
+    message: initParams,
+    tag: 'socket参数',
+  });
+  rtcStore.setSocketParams(initParams);
 
-const socket = createSocket();
-initSocketEvent(socket);
-const { createRTCSocket, handleLeave } = useRtcSdk();
+  const socket = createSocket();
+  initSocketEvent(socket);
+  const { createRTCSocket, handleLeave } = useRtcSdk();
 
-(async () => {
-  await createRTCSocket();
-})();
-initialRoom();
-onMounted(async () => {
-  const app = await useApp();
-  // app.Connect.follow.start({ follow: !unref(isNativeLeader) });
-  watchEffect(() => {
-    if (unref(isNativeLeader)) {
-      app.Connect.follow.start({ follow: false });
-      app.Connect.follow.on("data", leaderSync);
-      app.Connect.paint.on("data", leaderPaint);
-    }
+  (async () => {
+    await createRTCSocket();
+  })();
+  initialRoom();
+  onMounted(async () => {
+    const app = await useApp();
+    // app.Connect.follow.start({ follow: !unref(isNativeLeader) });
+    watchEffect(() => {
+      if (unref(isNativeLeader)) {
+        app.Connect.follow.start({ follow: false });
+        app.Connect.follow.on('data', leaderSync);
+        app.Connect.paint.on('data', leaderPaint);
+      }
+    });
+  });
+  onUnmounted(async () => {
+    const app = await useApp();
+    app.Connect.follow.off('data', leaderSync);
+    app.Connect.paint.off('data', leaderPaint);
+    handleLeave();
   });
-});
-onUnmounted(async () => {
-  const app = await useApp();
-  app.Connect.follow.off("data", leaderSync);
-  app.Connect.paint.off("data", leaderPaint);
-  handleLeave();
-});
 
-/* method 方法*/
+  /* method 方法*/
 
-const leaderSync = (data) => {
-  if (unref(isNativeLeader) && unref(isJoined)) {
-    socket.emit("sync", data);
-  }
-};
-const leaderPaint = (data) => {
-  if (unref(isNativeLeader) && unref(isJoined)) {
-    const records = getApp().Connect.paint.records;
-    canUndo.value = records?.length;
-    socket.emit("paint", data);
-  }
-};
+  const leaderSync = (data) => {
+    if (unref(isNativeLeader) && unref(isJoined)) {
+      socket.emit('sync', data);
+    }
+  };
+  const leaderPaint = (data) => {
+    if (unref(isNativeLeader) && unref(isJoined)) {
+      const records = getApp().Connect.paint.records;
+      canUndo.value = records?.length;
+      socket.emit('paint', data);
+    }
+  };
 
-const onDrawUndo = async () => {
-  let app = getApp();
-  app.Connect.paint.undo();
-  canUndo.value = app.Connect.paint.records.length > 0;
+  const onDrawUndo = async () => {
+    let app = getApp();
+    app.Connect.paint.undo();
+    canUndo.value = app.Connect.paint.records.length > 0;
 
-  console.log(app.Connect.paint.records, "app.Connect.paint.records");
-};
+    console.log(app.Connect.paint.records, 'app.Connect.paint.records');
+  };
 
-const onDraw = async (status: boolean) => {
-  // isBrushes.value = status;
-  status && setDraw();
-  !status && setCloseDraw();
-  if (unref(isBrushes)) {
-    const app = await useApp();
-    console.log("app", app.Connect.paint);
-    app.Connect.paint.show({
-      role: unref(role),
-      paint: isNativeLeader ? true : false,
-    });
-    if (unref(role) == "leader") {
-      socket.emit("action", { type: "user-paint", open: true });
-    }
-  } else {
-    const app = await useApp();
-    app.Connect.paint.hide();
-    if (unref(role) == "leader") {
-      socket.emit("action", { type: "user-paint", open: false });
+  const onDraw = async (status: boolean) => {
+    // isBrushes.value = status;
+    status && setDraw();
+    !status && setCloseDraw();
+    if (unref(isBrushes)) {
+      const app = await useApp();
+      console.log('app', app.Connect.paint);
+      app.Connect.paint.show({
+        role: unref(role),
+        paint: isNativeLeader.value ? true : false,
+      });
+      if (unref(role) == 'leader') {
+        socket.emit('action', { type: 'user-paint', open: true });
+      }
+    } else {
+      const app = await useApp();
+      app.Connect.paint.hide();
+      if (unref(role) == 'leader') {
+        socket.emit('action', { type: 'user-paint', open: false });
+      }
     }
-  }
-};
+  };
 
-function closeText(): void {
-  showInput.value = false;
-  text.value = "";
-}
+  function closeText(): void {
+    showInput.value = false;
+    text.value = '';
+  }
 
-function sendText(): void {
-  if (text.value == "") {
-    return;
+  function sendText(): void {
+    if (text.value == '') {
+      return;
+    }
+    let data = {
+      role: rtcStore.role,
+      mode: rtcStore.mode,
+      Nickname: rtcStore.nickname,
+      UserId: rtcStore.userId,
+      text: text.value,
+    };
+    consola.info({
+      message: data,
+      tag: '发送信息',
+    });
+    socket.emit('action', {
+      type: 'danmumsg',
+      data,
+    });
+    rtcStore.addToChatList(data);
+    document.getElementById('input_msg')?.blur();
+    closeText();
+  }
+  function onFocus(): void {
+    showInput.value = true;
+    nextTick(() => {
+      document.getElementById('input_msg')?.focus();
+    });
   }
-  let data = {
-    role: rtcStore.role,
-    mode: rtcStore.mode,
-    Nickname: rtcStore.nickname,
-    UserId: rtcStore.userId,
-    text: text.value,
+  const openMember = () => {
+    showMember.value = true;
+    animateActive.value = true;
+  };
+  const closeMember = () => {
+    animateActive.value = false;
+    let t = setTimeout(() => {
+      clearTimeout(t);
+      showMember.value = false;
+    }, 200);
   };
-  consola.info({
-    message: data,
-    tag: "发送信息",
-  });
-  socket.emit("action", {
-    type: "danmumsg",
-    data,
-  });
-  rtcStore.addToChatList(data);
-  document.getElementById("input_msg")?.blur();
-  closeText();
-}
-function onFocus(): void {
-  showInput.value = true;
-  nextTick(() => {
-    document.getElementById("input_msg")?.focus();
-  });
-}
-const openMember = () => {
-  showMember.value = true;
-  animateActive.value = true;
-};
-const closeMember = () => {
-  animateActive.value = false;
-  let t = setTimeout(() => {
-    clearTimeout(t);
-    showMember.value = false;
-  }, 200);
-};
 
-const handleNoMute = () => {
-  const { localStream } = useRtcSdk();
-  console.log("localStream", localStream);
-  rtcStore.unmute();
-  localStream.unmuteAudio();
-};
-const handleMute = () => {
-  const { localStream } = useRtcSdk();
-  console.log("localStream", localStream);
-  rtcStore.mute();
-  localStream.muteVideo();
-};
+  const handleNoMute = () => {
+    const { localStream } = useRtcSdk();
+    console.log('localStream', localStream);
+    rtcStore.unmute();
+    localStream.unmuteAudio();
+  };
+  const handleMute = () => {
+    const { localStream } = useRtcSdk();
+    console.log('localStream', localStream);
+    rtcStore.mute();
+    localStream.muteVideo();
+  };
 
-const handleCloseRoom = () => {
-  Dialog.confirm({
-    showCloseIcon: false,
-    okText: "立即結束",
-    content:
-      "<span style='font-size: 16px; line-height: 1.5;'>是否結束帶看。<span/>",
-    title: "溫馨提示",
-    single: false,
-    func: (state: string) => {
-      if (state == "ok") {
-        const { closeSocket } = useSocket();
-        closeSocket();
-      }
-    },
-  });
-};
+  const handleCloseRoom = () => {
+    Dialog.confirm({
+      showCloseIcon: false,
+      okText: '立即結束',
+      content: "<span style='font-size: 16px; line-height: 1.5;'>是否結束帶看。<span/>",
+      title: '溫馨提示',
+      single: false,
+      func: (state: string) => {
+        if (state == 'ok') {
+          const { closeSocket } = useSocket();
+          closeSocket();
+        }
+      },
+    });
+  };
 
-const handleCreateShare = () => {
-  shareLink.value = location.href;
-};
+  const handleCreateShare = () => {
+    shareLink.value = location.href;
+  };
 </script>
 
 <style scoped lang="scss">
-@import "./chatroom.scss";
+  @import './chatroom.scss';
 </style>

+ 49 - 55
src/components/chatRoom/memberList.vue

@@ -1,9 +1,6 @@
 <template>
   <div class="layer" v-if="show" @click.self="closeMember">
-    <div
-      class="memberContent animated"
-      :class="animateActive ? 'fadeInUpBig' : 'fadeOutDownBig'"
-    >
+    <div class="memberContent animated" :class="animateActive ? 'fadeInUpBig' : 'fadeOutDownBig'">
       <div class="blurBox"></div>
       <div class="content">
         <div class="memberHeader">
@@ -15,10 +12,7 @@
             <div class="userMsg">
               <div class="avatar" :class="`${role}`">
                 <img
-                  :src="
-                    i?.Avatar ||
-                    require('@/assets/images/rtcLive/avatar_small@2x.png')
-                  "
+                  :src="i?.Avatar || require('@/assets/images/rtcLive/avatar_small@2x.png')"
                   alt=""
                 />
                 <div class="avatar-crown" v-show="i.Role === 'leader'"></div>
@@ -56,59 +50,59 @@
 </template>
 
 <script lang="ts" setup>
-import { propTypes } from "/@/utils/propTypes";
-import { UserInfoType, useRtcStore } from "/@/store/modules/rtc";
-// import avatarSmall from "/@/assets/images/rtcLive/avatar_small@2x.png";
-import { computed, watchEffect } from "vue";
-import { useSocket } from "/@/hooks/userSocket";
-const rtcStore = useRtcStore();
+  import { propTypes } from '/@/utils/propTypes';
+  import { UserInfoType, useRtcStore } from '/@/store/modules/rtc';
+  // import avatarSmall from "/@/assets/images/rtcLive/avatar_small@2x.png";
+  import { computed, watchEffect } from 'vue';
+  import { useSocket } from '/@/hooks/userSocket';
+  const rtcStore = useRtcStore();
 
-const role = computed(() => rtcStore.role);
-const isNativeLeader = computed(() => rtcStore.isLeader);
+  const role = computed(() => rtcStore.role);
+  const isNativeLeader = computed(() => rtcStore.isLeader);
 
-// const animateActive = ref(false);
-const props = defineProps({
-  show: propTypes.bool.def(false),
-  animateActive: propTypes.bool.def(false),
-  data: {
-    type: Array as PropType<UserInfoType[]>,
-    default: () => [],
-  },
-  currentListUser: {
-    type: Object as PropType<UserInfoType>,
-    default: () => {},
-  },
-});
-
-watchEffect(() => {
-  console.log("memberList", props.data);
-});
-const emit = defineEmits(["openMember", "closeMember"]);
-
-function closeMember(): void {
-  emit("closeMember");
-}
-function userCanInput(member: UserInfoType) {
-  const { socket } = useSocket();
-  member.IsWords = !member.IsWords;
-  socket.emit("action", {
-    type: "users-words",
-    words: member.IsWords,
-    userId: member.UserId,
+  // const animateActive = ref(false);
+  const props = defineProps({
+    show: propTypes.bool.def(false),
+    animateActive: propTypes.bool.def(false),
+    data: {
+      type: Array as PropType<UserInfoType[]>,
+      default: () => [],
+    },
+    currentListUser: {
+      type: Object as PropType<UserInfoType>,
+      default: () => {},
+    },
   });
-}
 
-function userCanSpeak(member: UserInfoType) {
-  const { socket } = useSocket();
-  member.IsMuted = !member.IsMuted;
-  socket.emit("action", {
-    type: "users-muted",
-    muted: member.IsMuted,
-    userId: member.UserId,
+  watchEffect(() => {
+    console.log('memberList', props.data);
   });
-}
+  const emit = defineEmits(['openMember', 'closeMember']);
+
+  function closeMember(): void {
+    emit('closeMember');
+  }
+  function userCanInput(member: UserInfoType) {
+    const { socket } = useSocket();
+    member.IsWords = !member.IsWords;
+    socket.emit('action', {
+      type: 'users-words',
+      words: member.IsWords,
+      userId: member.UserId,
+    });
+  }
+
+  function userCanSpeak(member: UserInfoType) {
+    const { socket } = useSocket();
+    member.IsMuted = !member.IsMuted;
+    socket.emit('action', {
+      type: 'users-muted',
+      muted: member.IsMuted,
+      userId: member.UserId,
+    });
+  }
 </script>
 
 <style lang="scss">
-@import "./chatroom.scss";
+  @import './chatroom.scss';
 </style>

+ 47 - 48
src/components/chatRoom/roomControl.ts

@@ -1,54 +1,53 @@
-import { useRtcStore } from "/@/store/modules/rtc";
-import consola from 'consola'
-import type { ConsolaLogObject } from 'consola'
-import { handleActions, handleSync, handleReceivePaint, handleJoin } from './controls'
+import { useRtcStore } from '/@/store/modules/rtc';
+import consola from 'consola';
+import type { ConsolaLogObject } from 'consola';
+import { handleActions, handleSync, handleReceivePaint, handleJoin } from './controls';
 
 // 所有socket业务事件集中点
 
 export function initSocketEvent(socket: SocketIOClient.Socket): void {
-    if (socket) {
-        socket.on('connect', () => {
-            const rtcStore = useRtcStore();
-            let params = {
-                userId: rtcStore.userId,
-                roomId: rtcStore.roomId,
-                role: rtcStore.role || "leader",
-                avatar: rtcStore.avatar,
-                nickname: rtcStore.nickname,
-            };
-            socket.emit('join', params)
-            rtcStore.setIsJoined(true)
-        })
+  if (socket) {
+    socket.on('connect', () => {
+      const rtcStore = useRtcStore();
+      const params = {
+        userId: rtcStore.userId,
+        roomId: rtcStore.roomId,
+        role: rtcStore.role || 'leader',
+        avatar: rtcStore.avatar,
+        nickname: rtcStore.nickname,
+      };
+      socket.emit('join', params);
+      rtcStore.setIsJoined(true);
+    });
 
+    socket.on('action', (data: any) => {
+      const actionLog: ConsolaLogObject = {
+        message: data,
+        tag: `action-${data.type || ''}`,
+        level: 3,
+      };
+      consola.info(actionLog);
+      handleActions(data);
+    });
+    // 自已进入逻辑
+    socket.on('join', handleJoin);
+    // 同屏帶看
+    socket.on('sync', handleSync);
+    // 畫筆
+    socket.on('paint', handleReceivePaint);
 
-        socket.on('action', (data: any) => {
-            const actionLog: ConsolaLogObject = {
-                message: data,
-                tag: `action-${data.type || ''}`,
-                level: 3
-            }
-            consola.info(actionLog)
-            handleActions(data)
-        })
-        // 自已进入逻辑
-        socket.on('join', handleJoin)
-        // 同屏帶看
-        socket.on('sync', handleSync)
-        // 畫筆
-        socket.on('paint', handleReceivePaint)
-
-        socket.on('onAny', (event: any) => {
-            console.error('onAny:-->', event)
-        })
-        socket.on('error', (error: any) => {
-            const actionLog: ConsolaLogObject = {
-                message: error,
-                tag: 'socket',
-                level: 0
-            }
-            consola.error(actionLog)
-        })
-    } else {
-        throw new Error('socket没有初始化!')
-    }
-}
+    socket.on('onAny', (event: any) => {
+      console.error('onAny:-->', event);
+    });
+    socket.on('error', (error: any) => {
+      const actionLog: ConsolaLogObject = {
+        message: error,
+        tag: 'socket',
+        level: 0,
+      };
+      consola.error(actionLog);
+    });
+  } else {
+    throw new Error('socket没有初始化!');
+  }
+}

+ 17 - 18
src/components/chatRoom/roomEvent.ts

@@ -1,22 +1,21 @@
-import { useRtcStore } from "/@/store/modules/rtc";
-
+import { useRtcStore } from '/@/store/modules/rtc';
 
 // 所有socket业务事件集中点
 
 export function initSocketEvent(socket: SocketIOClient.Socket): void {
-    if (socket) {
-        socket.on('connect', () => {
-            const rtcStore = useRtcStore();
-            let params = {
-                userId: rtcStore.userId,
-                roomId: rtcStore.roomId,
-                role: rtcStore.role || "leader",
-                avatar: rtcStore.avatar,
-                nickname: rtcStore.nickname,
-            };
-            socket.emit('join', params)
-        })
-    } else {
-        throw new Error('socket没有初始化!')
-    }
-}
+  if (socket) {
+    socket.on('connect', () => {
+      const rtcStore = useRtcStore();
+      const params = {
+        userId: rtcStore.userId,
+        roomId: rtcStore.roomId,
+        role: rtcStore.role || 'leader',
+        avatar: rtcStore.avatar,
+        nickname: rtcStore.nickname,
+      };
+      socket.emit('join', params);
+    });
+  } else {
+    throw new Error('socket没有初始化!');
+  }
+}

+ 71 - 71
src/components/chatRoom/sceneList.vue

@@ -27,95 +27,95 @@
 </template>
 
 <script lang="ts" setup>
-import { unref } from "vue";
-import Icon from "/@/components/basic/icon/index.vue";
-import { useRoom } from "/@/hooks/useRoom";
-// import { currentScene } from "@/store/room";
-const { currentScene, sceneList } = useRoom();
+  import { unref } from 'vue';
+  import Icon from '/@/components/basic/icon/index.vue';
+  import { useRoom } from '/@/hooks/useRoom';
+  // import { currentScene } from "@/store/room";
+  const { currentScene, sceneList } = useRoom();
 
-console.log("sceneList", unref(sceneList));
+  console.log('sceneList', unref(sceneList));
 
-const emit = defineEmits(["close", "changeScene"]);
+  const emit = defineEmits(['close', 'changeScene']);
 </script>
 
 <style scoped lang="scss">
-.scene-list {
-  max-height: 80%;
-  background: rgba(0, 0, 0, 0.8);
-  border-radius: 10px 10px 0px 0px;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  display: flex;
-  flex-direction: column;
-  z-index: 99999;
-  position: absolute;
-}
+  .scene-list {
+    max-height: 80%;
+    background: rgba(0, 0, 0, 0.8);
+    border-radius: 10px 10px 0px 0px;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    display: flex;
+    flex-direction: column;
+    z-index: 99999;
+    position: absolute;
+  }
 
-.header {
-  flex: none;
-  text-align: center;
-  height: 46px;
-  line-height: 46px;
-  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+  .header {
+    flex: none;
+    text-align: center;
+    height: 46px;
+    line-height: 46px;
+    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
 
-  p {
-    font-size: 16px;
-    font-weight: 500;
-    color: #ffffff;
-  }
+    p {
+      font-size: 16px;
+      font-weight: 500;
+      color: #ffffff;
+    }
 
-  .icon {
-    position: absolute;
-    right: 0;
-    top: 0;
-    font-size: 14px;
-    padding: 0 20px;
+    .icon {
+      position: absolute;
+      right: 0;
+      top: 0;
+      font-size: 14px;
+      padding: 0 20px;
+    }
   }
-}
 
-.content {
-  flex: 1;
-  overflow-y: auto;
-  padding: 11px;
+  .content {
+    flex: 1;
+    overflow-y: auto;
+    padding: 11px;
 
-  .sign {
-    height: 60px;
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    margin-bottom: 18px;
-
-    .info {
-      flex: 1;
+    .sign {
+      height: 60px;
       display: flex;
+      justify-content: space-between;
       align-items: center;
+      margin-bottom: 18px;
 
-      img {
-        flex: none;
-        width: 60px;
-        height: 60px;
-        border-radius: 4px;
-      }
+      .info {
+        flex: 1;
+        display: flex;
+        align-items: center;
 
-      p {
-        font-size: 14px;
-        font-weight: 400;
-        color: #ffffff;
-        line-height: 20px;
-        margin-left: 10px;
+        img {
+          flex: none;
+          width: 60px;
+          height: 60px;
+          border-radius: 4px;
+        }
+
+        p {
+          font-size: 14px;
+          font-weight: 400;
+          color: #ffffff;
+          line-height: 20px;
+          margin-left: 10px;
+        }
       }
-    }
 
-    &.active .info p {
-      color: #ed6155;
-    }
+      &.active .info p {
+        color: #ed6155;
+      }
 
-    .icon {
-      flex: none;
-      font-size: 10px;
-      margin-left: 20px;
+      .icon {
+        flex: none;
+        font-size: 10px;
+        margin-left: 20px;
+      }
     }
   }
-}
 </style>

+ 136 - 143
src/components/chatRoom/share.vue

@@ -27,166 +27,159 @@
 </template>
 
 <script setup lang="ts">
-import {
-  onMounted,
-  defineProps,
-  defineEmits,
-  ref,
-  unref,
-  watchEffect,
-} from "vue";
-import ClipboardJS from "clipboard";
-import Dialog from "/@/components/basic/dialog";
+  import { onMounted, defineProps, defineEmits, ref, unref, watchEffect } from 'vue';
+  import ClipboardJS from 'clipboard';
+  import Dialog from '/@/components/basic/dialog';
 
-const emit = defineEmits(["close"]);
+  const emit = defineEmits(['close']);
 
-const props = defineProps({
-  title: {
-    type: String,
-    default: "邀请好友",
-  },
-  shareLink: {
-    type: String,
-    default: "",
-  },
-});
-const copylink$ = ref<Nullable<HTMLElement>>(null);
-const show = ref(false);
-const closeCreated = () => {
-  show.value = false;
-  emit("close");
-};
-
-const createdConfirm = () => {
-  if (unref(copylink$)) {
-    const ele = unref(copylink$) as any as HTMLElement;
-    new ClipboardJS(ele).on("success", function (e) {
-      e.clearSelection();
-      Dialog.toast({ content: "链接复制成功", type: "success" });
-      setTimeout(() => {
-        show.value = false;
-        emit("close");
-      }, 300);
-    });
-  }
-};
+  const props = defineProps({
+    title: {
+      type: String,
+      default: '邀请好友',
+    },
+    shareLink: {
+      type: String,
+      default: '',
+    },
+  });
+  const copylink$ = ref<Nullable<HTMLElement>>(null);
+  const show = ref(false);
+  const closeCreated = () => {
+    show.value = false;
+    emit('close');
+  };
 
-onMounted(() => {
-  watchEffect(() => {
-    if (props.shareLink?.length) {
-      show.value = true;
+  const createdConfirm = () => {
+    if (unref(copylink$)) {
+      const ele = unref(copylink$) as any as HTMLElement;
+      new ClipboardJS(ele).on('success', function (e) {
+        e.clearSelection();
+        Dialog.toast({ content: '链接复制成功', type: 'success' });
+        setTimeout(() => {
+          show.value = false;
+          emit('close');
+        }, 300);
+      });
     }
+  };
+
+  onMounted(() => {
+    watchEffect(() => {
+      if (props.shareLink?.length) {
+        show.value = true;
+      }
+    });
   });
-});
 </script>
 
 <style scoped lang="scss">
-#dialog_index {
-  width: 100vw;
-  height: 100%;
-  // background: rgba(0, 0, 0, 0.5);
-  position: fixed;
-  left: 0;
-  top: 0;
-  z-index: 100000;
-  pointer-events: none;
-  .created_dialog {
-    width: 8.64rem;
-    // min-height: 5rem;
-    // background: #ffffff;
-    border-radius: 8px;
-    position: absolute;
-    left: 50%;
-    top: 50%;
-    transform: translate(-50%, -50%);
-    pointer-events: auto;
-    border: 1px solid rgba(255, 255, 255, 0.1);
-    border-radius: 4px;
-    .blurBox {
+  #dialog_index {
+    width: 100vw;
+    height: 100%;
+    // background: rgba(0, 0, 0, 0.5);
+    position: fixed;
+    left: 0;
+    top: 0;
+    z-index: 100000;
+    pointer-events: none;
+    .created_dialog {
+      width: 8.64rem;
+      // min-height: 5rem;
+      // background: #ffffff;
+      border-radius: 8px;
       position: absolute;
-      z-index: 1;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-      background: rgba(0, 0, 0, 0.7);
-      filter: blur(1px);
-    }
-    .content {
-      position: relative;
-      z-index: 2;
-      top: 0;
-      left: 0;
-      width: 100%;
-      height: 100%;
-    }
-    .dialog_title {
-      width: 100%;
-      height: 1.39rem;
-      padding: 0 0.56rem;
-      box-sizing: border-box;
-      font-size: 0.39rem;
-      color: #fff;
-      line-height: 1.39rem;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-      border-bottom-style: solid;
-      border-bottom-width: 1px;
-      border-bottom-color: rgba(255, 255, 255, 0.1);
-    }
-    .dialog_link {
-      width: 100%;
-      font-size: 0.39rem;
-      color: rgba(255, 255, 255, 0.5);
-      padding: 0.53rem 0.56rem;
-      box-sizing: border-box;
-      text-align: justify;
-      text-align: left;
-      > p {
-        background: rgba(0, 0, 0, 0.5);
-        padding: 0.15rem 0.28rem;
-        word-break: break-all;
-        word-wrap: break-word;
-        text-overflow: -o-ellipsis-lastline;
+      left: 50%;
+      top: 50%;
+      transform: translate(-50%, -50%);
+      pointer-events: auto;
+      border: 1px solid rgba(255, 255, 255, 0.1);
+      border-radius: 4px;
+      .blurBox {
+        position: absolute;
+        z-index: 1;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background: rgba(0, 0, 0, 0.7);
+        filter: blur(1px);
+      }
+      .content {
+        position: relative;
+        z-index: 2;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+      }
+      .dialog_title {
+        width: 100%;
+        height: 1.39rem;
+        padding: 0 0.56rem;
+        box-sizing: border-box;
+        font-size: 0.39rem;
+        color: #fff;
+        line-height: 1.39rem;
         overflow: hidden;
         text-overflow: ellipsis;
-        display: -webkit-box;
-        -webkit-line-clamp: 2;
-        line-clamp: 2;
-        -webkit-box-orient: vertical;
-        line-height: 0.72rem;
+        white-space: nowrap;
+        border-bottom-style: solid;
+        border-bottom-width: 1px;
+        border-bottom-color: rgba(255, 255, 255, 0.1);
       }
-    }
-
-    .created_btn {
-      width: 100%;
-      height: 1.36rem;
-      border-top-style: solid;
-      border-top-width: 1px;
-      border-top-color: rgba(255, 255, 255, 0.1);
-      box-sizing: border-box;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      > div {
-        width: 50%;
-        height: 1.36rem;
-        text-align: center;
-        line-height: 1.36rem;
+      .dialog_link {
+        width: 100%;
         font-size: 0.39rem;
+        color: rgba(255, 255, 255, 0.5);
+        padding: 0.53rem 0.56rem;
         box-sizing: border-box;
-        &.created_cancel {
-          color: #fff;
-          border-right-style: solid;
-          border-right-width: 1px;
-          border-right-color: rgba(0, 0, 0, 0.05);
+        text-align: justify;
+        text-align: left;
+        > p {
+          background: rgba(0, 0, 0, 0.5);
+          padding: 0.15rem 0.28rem;
+          word-break: break-all;
+          word-wrap: break-word;
+          text-overflow: -o-ellipsis-lastline;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          display: -webkit-box;
+          -webkit-line-clamp: 2;
+          line-clamp: 2;
+          -webkit-box-orient: vertical;
+          line-height: 0.72rem;
         }
-        &.created_confirm {
-          color: #ed5d18;
+      }
+
+      .created_btn {
+        width: 100%;
+        height: 1.36rem;
+        border-top-style: solid;
+        border-top-width: 1px;
+        border-top-color: rgba(255, 255, 255, 0.1);
+        box-sizing: border-box;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        > div {
+          width: 50%;
+          height: 1.36rem;
+          text-align: center;
+          line-height: 1.36rem;
+          font-size: 0.39rem;
+          box-sizing: border-box;
+          &.created_cancel {
+            color: #fff;
+            border-right-style: solid;
+            border-right-width: 1px;
+            border-right-color: rgba(0, 0, 0, 0.05);
+          }
+          &.created_confirm {
+            color: #ed5d18;
+          }
         }
       }
     }
   }
-}
 </style>

+ 55 - 59
src/components/custom/panel.vue

@@ -10,84 +10,80 @@
       <Icon type="arrows" />
     </span>
   </div>
-  <SceneList
-    v-if="showScenes"
-    @close="showScenes = false"
-    @changeScene="changeScene"
-  />
+  <SceneList v-if="showScenes" @close="showScenes = false" @changeScene="changeScene" />
 </template>
 
 <script setup lang="ts">
-import SceneList from "/@/components/chatRoom/sceneList.vue";
-//import { useMusicPlayer } from "@/utils/sound";
-// import { changeScene } from "@/store/room";
-import Icon from "/@/components/basic/icon/index.vue";
-import { ref, unref } from "vue";
+  import SceneList from '/@/components/chatRoom/sceneList.vue';
+  //import { useMusicPlayer } from "@/utils/sound";
+  // import { changeScene } from "@/store/room";
+  import Icon from '/@/components/basic/icon/index.vue';
+  import { ref, unref } from 'vue';
 
-import { useTourPlayer } from "/@/hooks/userTourPlayer";
+  import { useTourPlayer } from '/@/hooks/userTourPlayer';
 
-const show = ref(false);
+  const show = ref(false);
 
-const showScenes = ref(false);
-const { hasTours } = useTourPlayer();
+  const showScenes = ref(false);
+  const { hasTours } = useTourPlayer();
 
-function handlePlayTours() {
-  const { player, playing } = useTourPlayer();
-  if (!unref(playing)) {
-    player.play();
-  } else {
-    player.pause();
+  function handlePlayTours() {
+    const { player, playing } = useTourPlayer();
+    if (!unref(playing)) {
+      player.play();
+    } else {
+      player.pause();
+    }
   }
-}
 
-const changeScene = () => {};
+  const changeScene = () => {};
 </script>
 
 <style lang="scss" scoped>
-.panel {
-  position: fixed;
-  top: calc(100% - 90px);
-  left: 0;
-  z-index: 22;
-  height: 44px;
-  background: rgba(0, 0, 0, 0.5);
-  border-radius: 0px 24px 24px 0px;
-  border: 1px solid rgba(255, 255, 255, 0.1);
-  padding-right: 30px;
-  display: flex;
-  align-items: center;
-  justify-content: space-evenly;
-  // width: 110px;
-  transform: translateX(calc(-100% + 30px));
+  .panel {
+    position: fixed;
+    top: calc(100% - 90px);
+    left: 0;
+    z-index: 22;
+    height: 44px;
+    background: rgba(0, 0, 0, 0.5);
+    border-radius: 0px 24px 24px 0px;
+    border: 1px solid rgba(255, 255, 255, 0.1);
+    padding-right: 30px;
+    display: flex;
+    align-items: center;
+    justify-content: space-evenly;
+    // width: 110px;
+    transform: translateX(calc(-100% + 30px));
 
-  &.show {
-    transform: translateX(0);
-  }
+    &.show {
+      transform: translateX(0);
+    }
 
-  > .icon {
-    margin: 0 10px;
+    > .icon {
+      margin: 0 10px;
+    }
   }
-}
 
-.icon {
-  font-size: 24px;
-  height: 1em;
-  color: #fff;
+  .icon {
+    font-size: 24px;
+    height: 1em;
+    color: #fff;
 
-  &.active {
-    color: #ed5d18;
+    &.active {
+      color: #ed5d18;
+    }
   }
-}
 
-.ctrl {
-  position: absolute;
-  right: 10px;
-  top: 50%;
-  transform: translateY(-50%) rotateZ(180deg);
-  font-size: 12px;
+  .ctrl {
+    position: absolute;
+    right: 10px;
+    top: 50%;
+    transform: translateY(-50%) rotateZ(180deg);
+    font-size: 12px;
 
-  &.show {
-    transform: translateY(-50%);
+    &.show {
+      transform: translateY(-50%);
+    }
   }
-}
 </style>

+ 11 - 13
src/components/custom/tagView.vue

@@ -1,17 +1,17 @@
 <script setup lang="ts">
-import { computed } from "vue";
+  import { computed } from 'vue';
 
-const props = defineProps({
-  sid: { type: String },
-  url: { type: String },
-  title: { type: String, default: "" },
-  content: { type: String, default: "" },
-  icon: { type: String, default: "" },
-});
+  const props = defineProps({
+    sid: { type: String },
+    url: { type: String },
+    title: { type: String, default: '' },
+    content: { type: String, default: '' },
+    icon: { type: String, default: '' },
+  });
 
-const backgroundURL = computed(
-  () => props.url && props.url + "&x-oss-process=image/resize,m_fill,w_80,h_80"
-);
+  const backgroundURL = computed(
+    () => props.url && props.url + '&x-oss-process=image/resize,m_fill,w_80,h_80',
+  );
 </script>
 
 <template>
@@ -36,5 +36,3 @@ const backgroundURL = computed(
     </div>
   </div>
 </template>
-
-

+ 17 - 19
src/components/registerComponent.ts

@@ -1,26 +1,24 @@
-
 // import Dialog, { Toast, Alert } from '/@/components/basic/dialog'
-import Dialog, { Window, Toast, Alert, DialogContent } from '/@/components/basic/dialog'
-import Button from '/@/components/basic/button/index.vue'
-import type { App } from 'vue'
+import Dialog, { Window, Toast, Alert, DialogContent } from '/@/components/basic/dialog';
+import Button from '/@/components/basic/button/index.vue';
+import type { App } from 'vue';
 
 function setup(...Components) {
-    Components.forEach(Component => {
-        Component.install = function (app: App) {
-            Component.use && Component.use(app)
-            app.component(Component.name, Component)
-        }
-    })
-    return Components
+  Components.forEach((Component) => {
+    Component.install = function (app: App) {
+      Component.use && Component.use(app);
+      app.component(Component.name, Component);
+    };
+  });
+  return Components;
 }
 // 注册带install与use hook
-const registerComponent = setup(Dialog, Window, Toast, Alert, DialogContent, Button)
+const registerComponent = setup(Dialog, Window, Toast, Alert, DialogContent, Button);
 // console.log('registerComponent', registerComponent)
 export default {
-    install: (app: App) => {
-        registerComponent.forEach(component => {
-            component.install(app)
-        })
-    }
-}
-
+  install: (app: App) => {
+    registerComponent.forEach((component) => {
+      component.install(app);
+    });
+  },
+};

+ 10 - 10
src/hooks/useDraw.ts

@@ -1,19 +1,19 @@
-import { ref, unref } from 'vue'
+import { ref } from 'vue';
 
-const isDrawing = ref(false)
+const isDrawing = ref(false);
 
 function setDraw() {
-    isDrawing.value = true
+  isDrawing.value = true;
 }
 
 function setCloseDraw() {
-    isDrawing.value = false
+  isDrawing.value = false;
 }
 
 export function useDraw() {
-    return {
-        isDrawing,
-        setDraw,
-        setCloseDraw
-    }
-}
+  return {
+    isDrawing,
+    setDraw,
+    setCloseDraw,
+  };
+}

+ 56 - 56
src/hooks/useRoom.ts

@@ -1,77 +1,77 @@
-import browser from "/@/utils/browser";
-import axios from "axios";
-import { ref, computed, unref } from 'vue'
+import browser from '/@/utils/browser';
+import axios from 'axios';
+import { ref, computed, unref } from 'vue';
 
-const roomParam = browser.getURLParam("roomId")
+const roomParam = browser.getURLParam('roomId');
 
 interface roomDataType {
-    sceneData: any[]
+  sceneData: any[];
 }
 
-export const room = ref<Nullable<roomDataType>>(null)
-export const roomId = roomParam && roomParam.substr(7)
-export const sceneList = computed(() => unref(room)?.sceneData || [])
-export const isLeader = browser.getURLParam("role") === 'leader'
-
+export const room = ref<Nullable<roomDataType>>(null);
+export const roomId = roomParam && roomParam.substr(7);
+export const sceneList = computed(() => unref(room)?.sceneData || []);
+export const isLeader = browser.getURLParam('role') === 'leader';
 
 export function useRoom() {
-    return {
-        sceneList,
-        currentScene,
-        changeScene,
-        initialRoom,
-        enterRoom,
-        leaveRoom
-    }
+  return {
+    sceneList,
+    currentScene,
+    changeScene,
+    initialRoom,
+    enterRoom,
+    leaveRoom,
+  };
 }
 
 export const currentScene = computed(() => {
-    const num = browser.getURLParam("m")
-    return sceneList.value.find(scene => scene.num === num)
-})
+  const num = browser.getURLParam('m');
+  return sceneList.value.find((scene) => scene.num === num);
+});
 
 export const changeScene = (scene) => {
-    if (currentScene.value?.num !== scene.num) {
-        console.log(scene, currentScene.value)
-        const params = new URLSearchParams(location.search)
-        params.set('m', scene.num)
-        const url = new URL(location.href)
-        url.search = `?` + params.toString()
-        location.replace(url)
-    }
-}
+  if (currentScene.value?.num !== scene.num) {
+    console.log(scene, currentScene.value);
+    const params = new URLSearchParams(location.search);
+    params.set('m', scene.num);
+    const url = new URL(location.href);
+    url.search = `?` + params.toString();
+    location.replace(url);
+  }
+};
 
-
-const shopAxios = axios.create({ baseURL: !import.meta.env.DEV ? 'https://v4-test.4dkankan.com' : '' })
+const shopAxios = axios.create({
+  baseURL: !import.meta.env.DEV ? 'https://v4-test.4dkankan.com' : '',
+});
 
 export const initialRoom = async () => {
-    const res = await shopAxios.get('/takelook/roomInfo', { params: { roomId } })
-    room.value = res.data.data
-    console.log(room.value)
-}
+  const res = await shopAxios.get('/takelook/roomInfo', { params: { roomId } });
+  room.value = res.data.data;
+  console.log(room.value);
+};
 
 export const enterRoom = async () => {
-    if (!isLeader) return;
-    await shopAxios.get('/takelook/inOrOutRoom', {
-        params: {
-            type: 0,
-            role: 'leader',
-            roomId
-        }
-    })
-}
+  if (!isLeader) return;
+  await shopAxios.get('/takelook/inOrOutRoom', {
+    params: {
+      type: 0,
+      role: 'leader',
+      roomId,
+    },
+  });
+};
 
 export const leaveRoom = async () => {
-    if (!isLeader) return;
-    await shopAxios.get('/takelook/inOrOutRoom', {
-        params: {
-            type: 1,
-            role: 'leader',
-            roomId
-        }
-    })
-}
+  if (!isLeader) return;
+  await shopAxios.get('/takelook/inOrOutRoom', {
+    params: {
+      type: 1,
+      role: 'leader',
+      roomId,
+    },
+  });
+};
 
 if (roomId) {
-    shopAxios.get('/takelook/roomAddView', { params: { roomId } })
-}
+  shopAxios.get('/takelook/roomAddView', { params: { roomId } });
+}

+ 337 - 355
src/hooks/useTRTC.ts

@@ -1,10 +1,9 @@
-
-import consola from "consola";
-import { watch, nextTick, onMounted, onUnmounted, ref } from 'vue'
-import TRTC from "trtc-js-sdk";
-import type { LocalStream, Client, RemoteStream } from "trtc-js-sdk";
-import { useRtcStore } from "/@/store/modules/rtc";
-import Dialog from '/@/components/basic/dialog'
+import consola from 'consola';
+import { nextTick, ref } from 'vue';
+import TRTC from 'trtc-js-sdk';
+import type { LocalStream, Client, RemoteStream } from 'trtc-js-sdk';
+import { useRtcStore } from '/@/store/modules/rtc';
+import Dialog from '/@/components/basic/dialog';
 
 let localClient: Client;
 let localStream: LocalStream;
@@ -12,152 +11,145 @@ const invitedRemoteStreams = ref<RemoteStream[]>([]);
 const muteAudioLeader = ref(false);
 const muteVideoLeader = ref(false);
 
-
 export const updateDevice = async () => {
-    try {
-        console.log("updateDevice");
-        const rtcStore = useRtcStore()
-        const microphoneItems = await TRTC.getMicrophones();
-        microphoneItems.forEach((item) => {
-            item['value'] = item.deviceId;
-        });
-        if (microphoneItems?.length) {
-            rtcStore.setAudioDeviceId(microphoneItems[0].deviceId)
-        } else {
-            rtcStore.setAudioDeviceId('')
-        }
-    } catch (error) {
-
+  try {
+    console.log('updateDevice');
+    const rtcStore = useRtcStore();
+    const microphoneItems = await TRTC.getMicrophones();
+    microphoneItems.forEach((item) => {
+      item['value'] = item.deviceId;
+    });
+    if (microphoneItems?.length) {
+      rtcStore.setAudioDeviceId(microphoneItems[0].deviceId);
+    } else {
+      rtcStore.setAudioDeviceId('');
     }
-
-
-}
-
+  } catch (error) {}
+};
 
 const checkoutIsExistAudioInput = async () => {
-    const result = await TRTC.checkSystemRequirements()
-    console.log('result', result)
-}
+  const result = await TRTC.checkSystemRequirements();
+  console.log('result', result);
+};
 
 // interface UseRtcSdkType {
 //     createRTCSocket: () => Promise<void>
 // }
 
 async function createLocalStream() {
-    try {
-        const rtcStore = useRtcStore()
-        localStream = TRTC.createStream({
-            userId: rtcStore.userId,
-            audio: true,
-            video: false,
-            microphoneId: rtcStore.audioDeviceId,
-        });
-
-        await localStream.initialize();
-
-        if (rtcStore.audioMuted) {
-            localStream.muteAudio();
-        }
-    } catch (error) {
-        console.log(error, "createStream");
+  try {
+    const rtcStore = useRtcStore();
+    localStream = TRTC.createStream({
+      userId: rtcStore.userId,
+      audio: true,
+      video: false,
+      microphoneId: rtcStore.audioDeviceId,
+    });
+
+    await localStream.initialize();
+
+    if (rtcStore.audioMuted) {
+      localStream.muteAudio();
     }
+  } catch (error) {
+    console.log(error, 'createStream');
+  }
 }
 
 async function createRTCSocket(): Promise<void> {
-    try {
-        const rtcStore = useRtcStore()
-        await checkoutIsExistAudioInput();
-        await updateDevice()
-        // const microphoneItems = await TRTC.getMicrophones();
+  try {
+    const rtcStore = useRtcStore();
+    await checkoutIsExistAudioInput();
+    await updateDevice();
+    // const microphoneItems = await TRTC.getMicrophones();
 
-        // if (microphoneItems?.length) {
+    // if (microphoneItems?.length) {
 
-        // }
-        await handleJoin();
-
-    } catch (error) {
-        consola.error({
-            tag: 'createRTCSocket',
-            message: error
-        })
-    }
+    // }
+    await handleJoin();
+  } catch (error) {
+    consola.error({
+      tag: 'createRTCSocket',
+      message: error,
+    });
+  }
 }
 async function handleJoin() {
-    try {
-        // let res = await apis.getSign({ userId: store.getters["rtc/userId"] });
-        const rtcStore = useRtcStore()
-        localClient = TRTC.createClient({
-            mode: "rtc",
-            sdkAppId: parseInt(rtcStore.sdkAppId, 10),
-            userId: rtcStore.userId,
-            userSig: rtcStore.genUserSig,
-            useStringRoomId: true,
-            enableAutoPlayDialog: false,
-        });
-        installEventHandlers();
-
-        await localClient.join({ roomId: rtcStore.roomId });
-        // store.commit("rtc/setIsJoined", true);
-        rtcStore.setIsJoined(true)
-        // inviteLink.value = store.commit("rtc/createShareLink");
-    } catch (error) {
-        console.error(error, "error-----------");
-    }
-
-    await createLocalStream();
-    await handlePublish();
-    localStream
-        .play("local")
-        .then(() => {
-            consola.info({
-                message: "音采源",
-                tag: 'rtc:audio'
-            })
-        })
-        .catch((e) => {
-            console.log(localStream);
-        });
-
-    localStream.on("error", (error) => {
-        if (error.getCode() === 0x4043) {
-            // 自动播放受限导致播放失败,此时引导用户点击页面。
-            // 在点击事件的回调函数中,执行 stream.resume();
-            Dialog.confirm({
-                showCloseIcon: false,
-                okText: "确定",
-                content:
-                    "<span style='font-size: 16px; line-height: 1.5;'>在用户与网页产生交互(例如点击、触摸页面等)之前,网页将被禁止播放带有声音的媒体。点击恢复播放<span/>",
-                title: "隐私条款:",
-                single: true,
-                func: (state) => {
-                    if (state == "ok") {
-                        localStream.resume();
-                    }
-                },
-            });
-        }
+  try {
+    // let res = await apis.getSign({ userId: store.getters["rtc/userId"] });
+    const rtcStore = useRtcStore();
+    localClient = TRTC.createClient({
+      mode: 'rtc',
+      sdkAppId: parseInt(rtcStore.sdkAppId, 10),
+      userId: rtcStore.userId,
+      userSig: rtcStore.genUserSig,
+      useStringRoomId: true,
+      enableAutoPlayDialog: false,
+    });
+    installEventHandlers();
+
+    await localClient.join({ roomId: rtcStore.roomId });
+    // store.commit("rtc/setIsJoined", true);
+    rtcStore.setIsJoined(true);
+    // inviteLink.value = store.commit("rtc/createShareLink");
+  } catch (error) {
+    console.error(error, 'error-----------');
+  }
+
+  await createLocalStream();
+  await handlePublish();
+  localStream
+    .play('local')
+    .then(() => {
+      consola.info({
+        message: '音采源',
+        tag: 'rtc:audio',
+      });
+    })
+    .catch((e) => {
+      console.log(localStream);
     });
+
+  localStream.on('error', (error) => {
+    if (error.getCode() === 0x4043) {
+      // 自动播放受限导致播放失败,此时引导用户点击页面。
+      // 在点击事件的回调函数中,执行 stream.resume();
+      Dialog.confirm({
+        showCloseIcon: false,
+        okText: '确定',
+        content:
+          "<span style='font-size: 16px; line-height: 1.5;'>在用户与网页产生交互(例如点击、触摸页面等)之前,网页将被禁止播放带有声音的媒体。点击恢复播放<span/>",
+        title: '隐私条款:',
+        single: true,
+        func: (state) => {
+          if (state == 'ok') {
+            localStream.resume();
+          }
+        },
+      });
+    }
+  });
 }
 
 async function handlePublish() {
-    const rtcStore = useRtcStore()
-
-    if (!rtcStore.isJoined) {
-        return;
-    }
-    if (rtcStore.isPublished) {
-        return;
-    }
-    if (!rtcStore.isLeader) {
-        return;
-    }
-    try {
-        await localClient.publish(localStream);
-        // store.commit("rtc/setIsPublished", true);
-        rtcStore.setIsPublished(true)
-    } catch (error) {
-        console.error(error, "---------------handlePublish--------------------");
-    }
+  const rtcStore = useRtcStore();
+
+  if (!rtcStore.isJoined) {
+    return;
+  }
+  if (rtcStore.isPublished) {
+    return;
+  }
+  if (!rtcStore.isLeader) {
+    return;
+  }
+  try {
+    await localClient.publish(localStream);
+    // store.commit("rtc/setIsPublished", true);
+    rtcStore.setIsPublished(true);
+  } catch (error) {
+    console.error(error, '---------------handlePublish--------------------');
+  }
 }
 
 // async function handleStartShare() {
@@ -179,279 +171,269 @@ async function handlePublish() {
 // }
 
 async function handleUnpublish() {
-    const rtcStore = useRtcStore()
-    if (!rtcStore.isJoined) {
-        return;
-    }
-    if (!rtcStore.isPublished) {
-        return;
-    }
-    try {
-        await localClient.unpublish(localStream);
-        // store.commit("rtc/setIsPublished", false);
-        rtcStore.setIsPublished(false)
-    } catch (error) {
-        console.error(error, "-----------handleUnpublish--------------");
-    }
+  const rtcStore = useRtcStore();
+  if (!rtcStore.isJoined) {
+    return;
+  }
+  if (!rtcStore.isPublished) {
+    return;
+  }
+  try {
+    await localClient.unpublish(localStream);
+    // store.commit("rtc/setIsPublished", false);
+    rtcStore.setIsPublished(false);
+  } catch (error) {
+    console.error(error, '-----------handleUnpublish--------------');
+  }
 }
 
 async function handleLeave() {
-    const rtcStore = useRtcStore()
-    if (rtcStore.isPublished) {
-        await handleUnpublish();
-    }
-    try {
-        uninstallEventHandlers();
-        await localClient.leave();
-        localClient.destroy();
-        // localClient = null;
-        invitedRemoteStreams.value.forEach((item) => {
-            item.stop();
-        });
-        invitedRemoteStreams.value = [];
-        rtcStore.setVideoDeviceId('')
-        rtcStore.setAudioDeviceId('')
-        // store.commit("rtc/setVideoDeviceId", "");
-        // store.commit("rtc/setAudioDeviceId", "");
-
-        if (localStream) {
-            localStream.stop();
-            localStream.close();
-            // localStream = null;
-            console.log("有执行到这里-------------");
-        }
-    } catch (error) {
-        console.error(error, "-----------handleLeave--------------");
+  const rtcStore = useRtcStore();
+  if (rtcStore.isPublished) {
+    await handleUnpublish();
+  }
+  try {
+    uninstallEventHandlers();
+    await localClient.leave();
+    localClient.destroy();
+    // localClient = null;
+    invitedRemoteStreams.value.forEach((item) => {
+      item.stop();
+    });
+    invitedRemoteStreams.value = [];
+    rtcStore.setVideoDeviceId('');
+    rtcStore.setAudioDeviceId('');
+    // store.commit("rtc/setVideoDeviceId", "");
+    // store.commit("rtc/setAudioDeviceId", "");
+
+    if (localStream) {
+      localStream.stop();
+      localStream.close();
+      // localStream = null;
+      console.log('有执行到这里-------------');
     }
+  } catch (error) {
+    console.error(error, '-----------handleLeave--------------');
+  }
 }
 
 function installEventHandlers() {
-    if (!localClient) {
-        return;
-    }
-    localClient.on("error", handleError);
-    localClient.on("client-banned", handleBanned);
-    localClient.on("peer-join", handlePeerJoin);
-    localClient.on("peer-leave", handlePeerLeave);
-    localClient.on("stream-added", handleStreamAdded);
-    localClient.on("stream-subscribed", handleStreamSubscribed);
-    localClient.on("stream-removed", handleStreamRemoved);
-    localClient.on("stream-updated", handleStreamUpdated);
-    localClient.on("mute-video", handleMuteVideo);
-    localClient.on("mute-audio", handleMuteAudio);
-    localClient.on("unmute-video", handleUnmuteVideo);
-    localClient.on("unmute-audio", handleUnmuteAudio);
+  if (!localClient) {
+    return;
+  }
+  localClient.on('error', handleError);
+  localClient.on('client-banned', handleBanned);
+  localClient.on('peer-join', handlePeerJoin);
+  localClient.on('peer-leave', handlePeerLeave);
+  localClient.on('stream-added', handleStreamAdded);
+  localClient.on('stream-subscribed', handleStreamSubscribed);
+  localClient.on('stream-removed', handleStreamRemoved);
+  localClient.on('stream-updated', handleStreamUpdated);
+  localClient.on('mute-video', handleMuteVideo);
+  localClient.on('mute-audio', handleMuteAudio);
+  localClient.on('unmute-video', handleUnmuteVideo);
+  localClient.on('unmute-audio', handleUnmuteAudio);
 }
 
 function uninstallEventHandlers() {
-    if (!localClient) {
-        return;
-    }
-    localClient.off("error", handleError);
-    localClient.off("error", handleError);
-    localClient.off("client-banned", handleBanned);
-    localClient.off("peer-join", handlePeerJoin);
-    localClient.off("peer-leave", handlePeerLeave);
-    localClient.off("stream-added", handleStreamAdded);
-    localClient.off("stream-subscribed", handleStreamSubscribed);
-    localClient.off("stream-removed", handleStreamRemoved);
-    localClient.off("stream-updated", handleStreamUpdated);
-    localClient.off("mute-video", handleMuteVideo);
-    localClient.off("mute-audio", handleMuteAudio);
-    localClient.off("unmute-video", handleUnmuteVideo);
-    localClient.off("unmute-audio", handleUnmuteAudio);
+  if (!localClient) {
+    return;
+  }
+  localClient.off('error', handleError);
+  localClient.off('error', handleError);
+  localClient.off('client-banned', handleBanned);
+  localClient.off('peer-join', handlePeerJoin);
+  localClient.off('peer-leave', handlePeerLeave);
+  localClient.off('stream-added', handleStreamAdded);
+  localClient.off('stream-subscribed', handleStreamSubscribed);
+  localClient.off('stream-removed', handleStreamRemoved);
+  localClient.off('stream-updated', handleStreamUpdated);
+  localClient.off('mute-video', handleMuteVideo);
+  localClient.off('mute-audio', handleMuteAudio);
+  localClient.off('unmute-video', handleUnmuteVideo);
+  localClient.off('unmute-audio', handleUnmuteAudio);
 }
 
 function handleMuteVideo(event) {
-    console.log(`[${event.userId}] mute video`);
-    if (event.userId.indexOf("leader") > -1) {
-        muteVideoLeader.value = true;
-    }
+  console.log(`[${event.userId}] mute video`);
+  if (event.userId.indexOf('leader') > -1) {
+    muteVideoLeader.value = true;
+  }
 }
 
 function handleMuteAudio(event) {
-    if (event.userId.indexOf("leader") > -1) {
-        muteAudioLeader.value = true;
-    }
-    console.log(event, `[] mute audio`);
+  if (event.userId.indexOf('leader') > -1) {
+    muteAudioLeader.value = true;
+  }
+  console.log(event, `[] mute audio`);
 }
 
 function handleUnmuteVideo(event) {
-    console.log(`[${event.userId}] unmute video`);
-    if (event.userId.indexOf("leader") > -1) {
-        muteVideoLeader.value = false;
-    }
+  console.log(`[${event.userId}] unmute video`);
+  if (event.userId.indexOf('leader') > -1) {
+    muteVideoLeader.value = false;
+  }
 }
 
 function handleUnmuteAudio(event) {
-    console.log(`[${event.userId}] unmute audio`);
-    if (event.userId.indexOf("leader") > -1) {
-        muteAudioLeader.value = false;
-    }
+  console.log(`[${event.userId}] unmute audio`);
+  if (event.userId.indexOf('leader') > -1) {
+    muteAudioLeader.value = false;
+  }
 }
 
 function handleError(error) {
-    console.log(`LocalClient error: ${error.message_}`);
+  console.log(`LocalClient error: ${error.message_}`);
 }
 
 function handleBanned(error) {
-    console.log(`Client has been banned for ${error.message_}`);
+  console.log(`Client has been banned for ${error.message_}`);
 }
 
 function handlePeerJoin(event) {
-    const { userId } = event;
-    if (userId !== "local-screen") {
-        console.log(`Peer Client [${userId}] joined`);
-    }
+  const { userId } = event;
+  if (userId !== 'local-screen') {
+    console.log(`Peer Client [${userId}] joined`);
+  }
 }
 
 function handlePeerLeave(event) {
-    const { userId } = event;
-    if (userId !== "local-screen") {
-        console.log(`[${userId}] leave`);
-    }
+  const { userId } = event;
+  if (userId !== 'local-screen') {
+    console.log(`[${userId}] leave`);
+  }
 }
 
 function handleStreamAdded(event) {
-    const remoteStream = event.stream;
-    const id = remoteStream.getId();
-    const userId = remoteStream.getUserId();
-    const rtcStore = useRtcStore()
-
-    console.log(remoteStream, "-------------remoteStream");
-
-    if (remoteStream.getUserId() === rtcStore.userId) {
-        // don't need to screen shared by us
-        localClient.unsubscribe(remoteStream).catch((error) => {
-            console.info(`unsubscribe failed: ${error.message_}`);
-        });
-    } else {
-        console.log(
-            `remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`
-        );
-        localClient.subscribe(remoteStream).catch((error) => {
-            console.info(`subscribe failed: ${error.message_}`);
-        });
-    }
+  const remoteStream = event.stream;
+  const id = remoteStream.getId();
+  const userId = remoteStream.getUserId();
+  const rtcStore = useRtcStore();
+
+  console.log(remoteStream, '-------------remoteStream');
+
+  if (remoteStream.getUserId() === rtcStore.userId) {
+    // don't need to screen shared by us
+    localClient.unsubscribe(remoteStream).catch((error) => {
+      console.info(`unsubscribe failed: ${error.message_}`);
+    });
+  } else {
+    console.log(`remote stream added: [${userId}] ID: ${id} type: ${remoteStream.getType()}`);
+    localClient.subscribe(remoteStream).catch((error) => {
+      console.info(`subscribe failed: ${error.message_}`);
+    });
+  }
 }
 
 async function handleStreamSubscribed(event) {
-    const remoteStream = event.stream;
-    const rtcStore = useRtcStore()
-    const remoteUserId = remoteStream.getUserId()
-    const remoteId = remoteStream.getId()
-    if (remoteUserId == rtcStore.userId) {
-        return;
-    }
-
-    if (!rtcStore.isUserInRemoteStream(remoteUserId)) {
-        rtcStore.pushRemoteStreams(remoteStream)
-        // debugger
+  const remoteStream = event.stream;
+  const rtcStore = useRtcStore();
+  const remoteUserId = remoteStream.getUserId();
+  const remoteId = remoteStream.getId();
+  if (remoteUserId == rtcStore.userId) {
+    return;
+  }
+
+  if (!rtcStore.isUserInRemoteStream(remoteUserId)) {
+    rtcStore.pushRemoteStreams(remoteStream);
+    // debugger
+  }
+  await nextTick();
+  setTimeout(async () => {
+    try {
+      await remoteStream.play(remoteId);
+      consola.info({
+        message: '客音源',
+        tag: 'rtc:audio',
+      });
+    } catch (error) {
+      Dialog.confirm({
+        showCloseIcon: false,
+        okText: '确定',
+        content:
+          "<span style='font-size: 16px; line-height: 1.5;'>在用户与网页产生交互(例如点击、触摸页面等)之前,网页将被禁止播放带有声音的媒体。点击恢复播放<span/>",
+        title: '隐私条款:',
+        single: true,
+        func: (state) => {
+          if (state == 'ok') {
+            remoteStream.resume();
+          }
+        },
+      });
     }
-    await nextTick();
-    setTimeout(async () => {
-        try {
-            await remoteStream
-                .play(remoteId)
-            consola.info({
-                message: "客音源",
-                tag: 'rtc:audio'
-            })
-
-        } catch (error) {
-
-            Dialog.confirm({
-                showCloseIcon: false,
-                okText: "确定",
-                content:
-                    "<span style='font-size: 16px; line-height: 1.5;'>在用户与网页产生交互(例如点击、触摸页面等)之前,网页将被禁止播放带有声音的媒体。点击恢复播放<span/>",
-                title: "隐私条款:",
-                single: true,
-                func: (state) => {
-                    if (state == "ok") {
-                        remoteStream.resume();
-                    }
-                },
-            });
-        }
-
-    }, 200);
-    // console.info(
-    //     remoteStream.userId_,
-    //     rtcStore,
-    //     "handleStreamSubscribedhandleStreamSubscribed.value"
-    // );
-
-    // if (
-    //     !invitedRemoteStreams.value.some(
-    //         (item) => item.userId_ == remoteStream.userId_
-    //     )
-    // ) {
-    //     debugger
-    //     invitedRemoteStreams.value.push(remoteStream);
-    // }
-
-    // console.log(invitedRemoteStreams.value, "invitedRemoteStreams.value");
-
-    // await nextTick();
-    // setTimeout(() => {
-    //     console.log(remoteStream.userId_, "remoteStream.getId()");
-    //     remoteStream
-    //         .play(remoteStream.userId_)
-    //         .then(() => {
-    //             console.log(`RemoteStream play success`, 88888888888888888888);
-    //         })
-    //         .catch((error) => {
-    //             console.log(`RemoteStream play failed:  error: ${error.message_}`);
-    //         });
-    // }, 100);
-
-    // const remoteStream = event.stream;
-    // const userId = remoteStream.getUserId();
-    // console.log(`RemoteStream subscribed: [${userId}]`);
+  }, 200);
+  // console.info(
+  //     remoteStream.userId_,
+  //     rtcStore,
+  //     "handleStreamSubscribedhandleStreamSubscribed.value"
+  // );
+
+  // if (
+  //     !invitedRemoteStreams.value.some(
+  //         (item) => item.userId_ == remoteStream.userId_
+  //     )
+  // ) {
+  //     debugger
+  //     invitedRemoteStreams.value.push(remoteStream);
+  // }
+
+  // console.log(invitedRemoteStreams.value, "invitedRemoteStreams.value");
+
+  // await nextTick();
+  // setTimeout(() => {
+  //     console.log(remoteStream.userId_, "remoteStream.getId()");
+  //     remoteStream
+  //         .play(remoteStream.userId_)
+  //         .then(() => {
+  //             console.log(`RemoteStream play success`, 88888888888888888888);
+  //         })
+  //         .catch((error) => {
+  //             console.log(`RemoteStream play failed:  error: ${error.message_}`);
+  //         });
+  // }, 100);
+
+  // const remoteStream = event.stream;
+  // const userId = remoteStream.getUserId();
+  // console.log(`RemoteStream subscribed: [${userId}]`);
 }
 
 function handleStreamRemoved(event) {
-    const remoteStream = event.stream;
-    const userId = remoteStream.getUserId();
-    console.log(`RemoteStream removed: [${userId}]`);
+  const remoteStream = event.stream;
+  const userId = remoteStream.getUserId();
+  console.log(`RemoteStream removed: [${userId}]`);
 }
 
 function handleStreamUpdated(event) {
-    const remoteStream = event.stream;
-    const userId = remoteStream.getUserId();
-    console.log(
-        `RemoteStream updated: [${userId}] audio:${remoteStream.hasAudio()} video:${remoteStream.hasVideo()}`
-    );
+  const remoteStream = event.stream;
+  const userId = remoteStream.getUserId();
+  console.log(
+    `RemoteStream updated: [${userId}] audio:${remoteStream.hasAudio()} video:${remoteStream.hasVideo()}`,
+  );
 }
 
-let switchDevice = async ({ videoId, audioId }) => {
-    const rtcStore = useRtcStore()
-    if (!rtcStore.isJoined) {
-        return;
-    }
-    if (videoId) {
-        try {
-            await localStream.switchDevice("video", videoId);
-        } catch (error) { }
-    }
-    if (audioId) {
-        try {
-            await localStream.switchDevice("audio", audioId);
-        } catch (error) { }
-    }
-};
-
-
+// const switchDevice = async ({ videoId, audioId }) => {
+//   const rtcStore = useRtcStore();
+//   if (!rtcStore.isJoined) {
+//     return;
+//   }
+//   if (videoId) {
+//     try {
+//       await localStream.switchDevice('video', videoId);
+//     } catch (error) {}
+//   }
+//   if (audioId) {
+//     try {
+//       await localStream.switchDevice('audio', audioId);
+//     } catch (error) {}
+//   }
+// };
 
 export function useRtcSdk() {
-    return {
-        createRTCSocket,
-        handleJoin,
-        handleLeave,
-        localStream,
-        client: localClient
-    }
+  return {
+    createRTCSocket,
+    handleJoin,
+    handleLeave,
+    localStream,
+    client: localClient,
+  };
 }
-
-

+ 38 - 38
src/hooks/userApp.ts

@@ -1,19 +1,19 @@
-
 // import { onMounted, ref, unref } from 'vue'
 
-import consola from 'consola'
+import consola from 'consola';
+import { KanKanInstance } from '/#/sdk';
 
-const instance = (window as any).KanKan
+const instance = (window as any).KanKan;
 let app: KanKanInstance;
 let _num: string;
-const deferred = instance.Deferred()
+const deferred = instance.Deferred();
 interface appOptions {
-    region?: string
-    resource?: string
-    server?: string
-    dom: HTMLElement
-    mobile?: boolean
-    num: string
+  region?: string;
+  resource?: string;
+  server?: string;
+  dom: HTMLElement;
+  mobile?: boolean;
+  num: string;
 }
 // onMounted(() => {
 
@@ -21,40 +21,40 @@ interface appOptions {
 
 // let deferred = KanKan.Deferred()
 export function createApp(options: appOptions): Promise<KanKanInstance> {
-    if (!options?.region) {
-        options.region = import.meta.env.VUE_APP_REGION_URL
-    }
-    if (!options?.resource) {
-        options.region = import.meta.env.VUE_APP_RESOURCE_URL
-    }
-    if (!options?.resource) {
-        options.server = '/'
-    }
-    console.log('options', options)
-
-    _num = options.num
-
-    if (!instance) {
-        consola.error('kankan SDK 没有引入!')
-    }
-    const _app = new instance(options)
-    deferred.resolve(_app);
-    (window as any).__sdk = _app
-    document.body.setAttribute('is-mobile', 'true')
-    app = _app
-    return Promise.resolve(app)
+  if (!options?.region) {
+    options.region = import.meta.env.VUE_APP_REGION_URL;
+  }
+  if (!options?.resource) {
+    options.region = import.meta.env.VUE_APP_RESOURCE_URL;
+  }
+  if (!options?.resource) {
+    options.server = '/';
+  }
+  console.log('options', options);
+
+  _num = options.num;
+
+  if (!instance) {
+    consola.error('kankan SDK 没有引入!');
+  }
+  const _app = new instance(options);
+  deferred.resolve(_app);
+  (window as any).__sdk = _app;
+  document.body.setAttribute('is-mobile', 'true');
+  app = _app;
+  return Promise.resolve(app);
 }
 
 export function useApp(): Promise<KanKanInstance> {
-    if (app) {
-        return Promise.resolve(app)
-    }
-    return deferred
+  if (app) {
+    return Promise.resolve(app);
+  }
+  return deferred;
 }
 export function getApp(): KanKanInstance {
-    return app
+  return app;
 }
 
 export function getNum(): string {
-    return _num
+  return _num;
 }

+ 30 - 34
src/hooks/userSocket.ts

@@ -1,47 +1,43 @@
-import { getApp } from "./userApp";
-import { useRoom } from "./useRoom";
-import { useRtcStore } from "/@/store/modules/rtc";
+import { getApp } from './userApp';
+import { useRoom } from './useRoom';
+import { useRtcStore } from '/@/store/modules/rtc';
 
-
-const io = (window as any).io as SocketIOClientStatic
-let socket: SocketIOClient.Socket
+const io = (window as any).io as SocketIOClientStatic;
+let socket: SocketIOClient.Socket;
 
 interface ReturnUseSocketType {
-    createSocket: Fn,
-    closeSocket: Fn,
-    socket: SocketIOClient.Socket
-
+  createSocket: Fn;
+  closeSocket: Fn;
+  socket: SocketIOClient.Socket;
 }
 
 export function createSocket() {
-    const rtcStore = useRtcStore()
-    // console.log('rtcStore', rtcStore)
-    const address = import.meta.env.VITE_APP_SOCKET_URL
-    socket = io(address, {
-        path: "/ws-sync",
-        transports: ["websocket"],
-    });
-    rtcStore.setSocket(socket)
-    return socket
+  const rtcStore = useRtcStore();
+  // console.log('rtcStore', rtcStore)
+  const address = import.meta.env.VITE_APP_SOCKET_URL;
+  socket = io(address, {
+    path: '/ws-sync',
+    transports: ['websocket'],
+  });
+  rtcStore.setSocket(socket);
+  return socket;
 }
 
 async function closeSocket() {
-    const { leaveRoom } = useRoom()
-    const rtcStore = useRtcStore()
-    await getApp().Connect.follow.exit();
-    await leaveRoom()
-    if (rtcStore.isLeader) {
-        socket.emit('action', { type: 'leader-dismiss' });
-    }
-    setTimeout(() => {
-
-    })
+  const { leaveRoom } = useRoom();
+  const rtcStore = useRtcStore();
+  await getApp().Connect.follow.exit();
+  await leaveRoom();
+  if (rtcStore.isLeader) {
+    socket.emit('action', { type: 'leader-dismiss' });
+  }
+  setTimeout(() => {});
 }
 
 export function useSocket(): ReturnUseSocketType {
-    return {
-        socket,
-        closeSocket,
-        createSocket
-    }
+  return {
+    socket,
+    closeSocket,
+    createSocket,
+  };
 }

+ 44 - 46
src/hooks/userTourPlayer.ts

@@ -1,56 +1,54 @@
-
-import consola from 'consola'
+// import consola from 'consola';
 import { ref } from 'vue';
-import { useTourStore } from '../store/modules/tour'
-import { useApp } from './userApp'
+import { useTourStore } from '../store/modules/tour';
+import { useApp } from './userApp';
 
 const playing = ref(false);
 const hasTours = ref(false);
-let player
+let player;
 
 async function createTourPlayer() {
-    const app = await useApp()
-    player = await app.use('TourPlayer')
-    const tourStore = useTourStore()
-    app.TourManager.on('loaded', tours => {
-        // existsGuide.value = !!tours.length
-        if (tours?.length)
-            hasTours.value = true
-        tourStore.setData(tours)
-    })
-    // { partId, frameId }
-    console.log('player', player)
-    player.on('play', () => {
-        playing.value = true
-    })
-    player.on('pause', () => {
-        playing.value = false
-    })
-    player.on('progress', ({ partId, frameId, progress }) => {
-        // 画面进度
-        // this.partId = partId
-        // this.frameId = frameId
-        // this.progress = Number(progress * 100).toFixed(5)
-
-        // // 片段进度
-        // if (this.tours.length == 1) {
-        //     this.progressPart = this.progress
-        // } else {
-        //     if (currPartId != partId) {
-        //         currPartId = partId
-        //         currFrames = this.tours[partId].list.length
-        //         this.progressPart = 0
-        //     }
-        //     this.progressPart += progress / currFrames
-        // }
-    })
+  const app = await useApp();
+  player = await app.use('TourPlayer');
+  const tourStore = useTourStore();
+  app.TourManager.on('loaded', (tours) => {
+    // existsGuide.value = !!tours.length
+    if (tours?.length) hasTours.value = true;
+    tourStore.setData(tours);
+  });
+  // { partId, frameId }
+  console.log('player', player);
+  player.on('play', () => {
+    playing.value = true;
+  });
+  player.on('pause', () => {
+    playing.value = false;
+  });
+  // { partId, frameId, progress }
+  player.on('progress', () => {
+    // 画面进度
+    // this.partId = partId
+    // this.frameId = frameId
+    // this.progress = Number(progress * 100).toFixed(5)
+    // // 片段进度
+    // if (this.tours.length == 1) {
+    //     this.progressPart = this.progress
+    // } else {
+    //     if (currPartId != partId) {
+    //         currPartId = partId
+    //         currFrames = this.tours[partId].list.length
+    //         this.progressPart = 0
+    //     }
+    //     this.progressPart += progress / currFrames
+    // }
+  });
 }
 
 export function useTourPlayer() {
-    return {
-        createTourPlayer,
-        playing,
-        hasTours,
-        player
-    }
+  return {
+    createTourPlayer,
+    playing,
+    hasTours,
+    player,
+  };
 }

+ 9 - 9
src/main.ts

@@ -1,23 +1,23 @@
-import { createApp } from 'vue'
+import { createApp } from 'vue';
 import 'virtual:windi-base.css';
 import 'virtual:windi-components.css';
-import './style.css'
+import './style.css';
 import 'virtual:windi-utilities.css';
 // import "/@/assets/theme.editor.scss";
 import { setupStore } from '/@/store';
-import App from './App.vue'
-import registerComponent from '/@/components/registerComponent'
+import App from './App.vue';
+import registerComponent from '/@/components/registerComponent';
 
 // import Components from "./global_components";
 
 async function bootstrap() {
-    const app = createApp(App);
+  const app = createApp(App);
 
-    // Configure store
-    setupStore(app);
-    app.use(registerComponent)
+  // Configure store
+  setupStore(app);
+  app.use(registerComponent);
 
-    app.mount('#app');
+  app.mount('#app');
 }
 
 bootstrap();

+ 2 - 2
src/store/index.ts

@@ -1,8 +1,8 @@
 import type { App } from 'vue';
 import { createPinia } from 'pinia';
-import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
+import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
 const store = createPinia();
-store.use(piniaPluginPersistedstate)
+store.use(piniaPluginPersistedstate);
 
 export function setupStore(app: App<Element>) {
   app.use(store);

+ 110 - 116
src/store/modules/app.ts

@@ -2,126 +2,120 @@ import { defineStore } from 'pinia';
 import { useTourStore } from './tour';
 import { getApp, useApp } from '/@/hooks/userApp';
 
-
 interface AppState {
-    panoId: Nullable<string>,
-    isLoaded: boolean,
-    mode: string,
-    flying: boolean,
-    floorId: Nullable<string>,
-    player: {
-        lang: string,
-        showVR: boolean,
-        showMore: boolean,
-        showDescription: boolean,
-        showToolbar: boolean,
-        showMap: boolean,
-        showShare: boolean,
-        showUserGuide: boolean,
-        showWidgets: boolean,
-    },
-    router: any,
-    controlsBottom: string,
-    isTourMode: boolean // 自由观看模式
+  panoId: Nullable<string>;
+  isLoaded: boolean;
+  mode: string;
+  flying: boolean;
+  floorId: Nullable<string>;
+  player: {
+    lang: string;
+    showVR: boolean;
+    showMore: boolean;
+    showDescription: boolean;
+    showToolbar: boolean;
+    showMap: boolean;
+    showShare: boolean;
+    showUserGuide: boolean;
+    showWidgets: boolean;
+  };
+  router: any;
+  controlsBottom: string;
+  isTourMode: boolean; // 自由观看模式
 }
 
 export const useAppStore = defineStore({
-    id: 'app',
-    state: (): AppState => ({
-        isLoaded: false,
-        panoId: null,
-        mode: 'panorama',
-        flying: false,
-        floorId: null,
-        player: {
-            lang: 'zh',
-            showVR: false,
-            showMore: false,
-            showDescription: false,
-            showToolbar: true,
-            showMap: true,
-            showShare: false,
-            showUserGuide: false,
-            showWidgets: true,
-        },
-        router: {},
-        controlsBottom: '20px',
-        isTourMode: true
-
-    }),
-    getters: {
-
-
+  id: 'app',
+  state: (): AppState => ({
+    isLoaded: false,
+    panoId: null,
+    mode: 'panorama',
+    flying: false,
+    floorId: null,
+    player: {
+      lang: 'zh',
+      showVR: false,
+      showMore: false,
+      showDescription: false,
+      showToolbar: true,
+      showMap: true,
+      showShare: false,
+      showUserGuide: false,
+      showWidgets: true,
+    },
+    router: {},
+    controlsBottom: '20px',
+    isTourMode: true,
+  }),
+  getters: {},
+  actions: {
+    setIsTourMode(payload: boolean): void {
+      this.isTourMode = payload;
     },
-    actions: {
-        setIsTourMode(payload: boolean): void {
-            this.isTourMode = payload
-        },
-        setMode(payload: string): void {
-            console.log('setMode', payload)
-            if (payload == this.mode) {
-                return
-            }
-            this.flying = true
-            useApp().then(sdk => {
-                sdk.Camera[payload]()
-                    .then(() => {
-                        this.flying = false
-                    })
-                    .catch(() => {
-                        this.flying = false
-                    })
-            })
+    setMode(payload: string): void {
+      console.log('setMode', payload);
+      if (payload == this.mode) {
+        return;
+      }
+      this.flying = true;
+      useApp().then((sdk) => {
+        sdk.Camera[payload]()
+          .then(() => {
+            this.flying = false;
+          })
+          .catch(() => {
+            this.flying = false;
+          });
+      });
 
-            if (payload == 'dollhouse') {
-                this.setFloor('all');
-            }
-            this.mode = payload
-        },
-        setFloorId(id: string): void {
-            this.floorId = id
-        },
-        setFlying(payload: boolean): void {
-            this.flying = payload
-        },
-        setFloor(id: string): void {
-            this.floorId = id
-            getApp().Scene.gotoFloor(id)
-        },
-        showVR(): void {
-            this.player.showVR = !this.player.showVR
-            this.player.showWidgets = !this.player.showWidgets
-            getApp().Camera.vr()
-        },
-        showUserGuide(payload: boolean): void {
-            this.player.showUserGuide = payload
-        },
-        setControlsBottom(payload: string): void {
-            this.controlsBottom = payload
-        },
-        setPanoId(id: string) {
-            this.panoId = id
-        },
-        setPlayerOptions(payload) {
-            for (let key in payload) {
-                this.player[key] = payload[key]
-                if (key == 'showSplit') {
-                    this.player.showWidgets = !payload[key]
-                }
-            }
-            if (!this.player.showToolbar || this.player.showVR) {
-                const tourStore = useTourStore()
-                // debugger
-                // this.commit('tour/setData', { showTours: false })
-                // tourStore.setData({ showTours: false })
-            }
-        },
-        isLoad() {
-            this.isLoaded = true
-        },
-        unLoad() {
-            this.isLoaded = true
+      if (payload == 'dollhouse') {
+        this.setFloor('all');
+      }
+      this.mode = payload;
+    },
+    setFloorId(id: string): void {
+      this.floorId = id;
+    },
+    setFlying(payload: boolean): void {
+      this.flying = payload;
+    },
+    setFloor(id: string): void {
+      this.floorId = id;
+      getApp().Scene.gotoFloor(id);
+    },
+    showVR(): void {
+      this.player.showVR = !this.player.showVR;
+      this.player.showWidgets = !this.player.showWidgets;
+      getApp().Camera.vr();
+    },
+    showUserGuide(payload: boolean): void {
+      this.player.showUserGuide = payload;
+    },
+    setControlsBottom(payload: string): void {
+      this.controlsBottom = payload;
+    },
+    setPanoId(id: string) {
+      this.panoId = id;
+    },
+    setPlayerOptions(payload) {
+      for (const key in payload) {
+        this.player[key] = payload[key];
+        if (key == 'showSplit') {
+          this.player.showWidgets = !payload[key];
         }
-    }
-
-})
+      }
+      if (!this.player.showToolbar || this.player.showVR) {
+        const tourStore = useTourStore();
+        // debugger
+        // this.commit('tour/setData', { showTours: false })
+        // tourStore.setData({ showTours: false })
+      }
+    },
+    isLoad() {
+      this.isLoaded = true;
+    },
+    unLoad() {
+      this.isLoaded = true;
+    },
+  },
+});

+ 226 - 230
src/store/modules/rtc.ts

@@ -1,262 +1,258 @@
 import { defineStore } from 'pinia';
-import consola from 'consola'
-import { genTestUserSig } from '/@/utils/generateTestUserSig'
-import type { RemoteStream } from "trtc-js-sdk";
-import sortBy from 'lodash-es/sortBy'
+import consola from 'consola';
+import { genTestUserSig } from '/@/utils/generateTestUserSig';
+import type { RemoteStream } from 'trtc-js-sdk';
+import sortBy from 'lodash-es/sortBy';
 
 interface RtcState {
-    socket: Nullable<SocketIOClient.Socket>,
-    socketId: string,
-    showDaoGou: boolean,
-    sdkAppId: string,
-    userId: string,
-    roomId: string,
-    role: 'leader' | 'customer'
-    secretKey: string
-    userSig: string
-    audioDeviceId: string,
-    videoDeviceId: string,
-    cameraList: MediaDeviceInfo[],
-    microphoneList: MediaDeviceInfo[],
-    logs: any[],
-    isJoined: boolean,
-    isPublished: boolean,
-    isShared: boolean,
-    remoteStreams: RemoteStream[],
-    // invitedRemoteStreams: any[],
-    avatar: Nullable<string>,
-    nickname: Nullable<string>,
-    mode: string,
-    chatList: ChatContentType[],
-    memberList: UserInfoType[],
-    audioMuted: boolean,
-    inputStatus: boolean,
-    currentSession: Nullable<UserInfoType>
+  socket: Nullable<SocketIOClient.Socket>;
+  socketId: string;
+  showDaoGou: boolean;
+  sdkAppId: string;
+  userId: string;
+  roomId: string;
+  role: 'leader' | 'customer';
+  secretKey: string;
+  userSig: string;
+  audioDeviceId: string;
+  videoDeviceId: string;
+  cameraList: MediaDeviceInfo[];
+  microphoneList: MediaDeviceInfo[];
+  logs: any[];
+  isJoined: boolean;
+  isPublished: boolean;
+  isShared: boolean;
+  remoteStreams: RemoteStream[];
+  // invitedRemoteStreams: any[],
+  avatar: Nullable<string>;
+  nickname: Nullable<string>;
+  mode: string;
+  chatList: ChatContentType[];
+  memberList: UserInfoType[];
+  audioMuted: boolean;
+  inputStatus: boolean;
+  currentSession: Nullable<UserInfoType>;
 }
 
 interface DeviceListParams {
-    cameraItems: MediaDeviceInfo[],
-    microphoneItems: MediaDeviceInfo[],
+  cameraItems: MediaDeviceInfo[];
+  microphoneItems: MediaDeviceInfo[];
 }
 
 export interface ChatContentType {
-    role: RoleType,
-    mode: string,
-    Nickname: Nullable<string>,
-    UserId: string,
-    text: string,
+  role: RoleType;
+  mode: string;
+  Nickname: Nullable<string>;
+  UserId: string;
+  text: string;
 }
 
 export interface UserInfoType {
-    Avatar: string
-    Id: string
-    InTime: string
-    IsClient: boolean
-    IsMuted: boolean
-    IsWords: boolean
-    JoinTime: string
-    Nickname: string
-    Role: RoleType
-    RoomId: string
-    UserId: string
-    text?: string
-    order: number
+  Avatar: string;
+  Id: string;
+  InTime: string;
+  IsClient: boolean;
+  IsMuted: boolean;
+  IsWords: boolean;
+  JoinTime: string;
+  Nickname: string;
+  Role: RoleType;
+  RoomId: string;
+  UserId: string;
+  text?: string;
+  order: number;
 }
-export type RoleType = 'leader' | 'customer'
+export type RoleType = 'leader' | 'customer';
 export interface SocketParams {
-    userId: string
-    roomId: string
-    role: RoleType
-    avatar: string
-    nickname: string
-    mode: string
+  userId: string;
+  roomId: string;
+  role: RoleType;
+  avatar: string;
+  nickname: string;
+  mode: string;
 }
 
-
-
 export const useRtcStore = defineStore({
-    id: 'rtc',
-    state: (): RtcState => ({
-        socket: null,
-        socketId: '',
-        showDaoGou: false,
-        sdkAppId: "1400685498",
-        nickname: '',
-        userId: '',
-        roomId: '',
-        role: 'customer',
-        secretKey: '7500f8938c46c5d3c64621ae7826905eec9723bf218fbcf121242e056a4ee14f',
-        userSig: 'eJwtzcsOgjAQBdB-6RaDU2jLI3EhsrHRBdGNK2Po0IyvNAWJxvjvEmA5597c*bLj7hD26FnOohDYYrzJ4LOjhkZ*tejPd7wY9EJwnsV8brXmdnGODMu5AEggExBNSUcPHFQpnkopIJkU34784ApECjBvkB1e8MLJfWyLOAis06Wut4b0tVdL77RVTb35dGXby6o6rVfs9wdhLDRy',
-        audioDeviceId: '',
-        videoDeviceId: '',
-        cameraList: [],
-        microphoneList: [],
-        logs: [],
-        isJoined: false,
-        isPublished: false,
-        isShared: false,
-        remoteStreams: [],
-        // invitedRemoteStreams: [],
-        avatar: null,
-        mode: '',
-        chatList: [],
-        memberList: [],
-        audioMuted: true,
-        inputStatus: true,
-        currentSession: null
-    }),
-    persist: {
-        storage: localStorage,
-        paths: ['memberList'],
+  id: 'rtc',
+  state: (): RtcState => ({
+    socket: null,
+    socketId: '',
+    showDaoGou: false,
+    sdkAppId: '1400685498',
+    nickname: '',
+    userId: '',
+    roomId: '',
+    role: 'customer',
+    secretKey: '7500f8938c46c5d3c64621ae7826905eec9723bf218fbcf121242e056a4ee14f',
+    userSig:
+      'eJwtzcsOgjAQBdB-6RaDU2jLI3EhsrHRBdGNK2Po0IyvNAWJxvjvEmA5597c*bLj7hD26FnOohDYYrzJ4LOjhkZ*tejPd7wY9EJwnsV8brXmdnGODMu5AEggExBNSUcPHFQpnkopIJkU34784ApECjBvkB1e8MLJfWyLOAis06Wut4b0tVdL77RVTb35dGXby6o6rVfs9wdhLDRy',
+    audioDeviceId: '',
+    videoDeviceId: '',
+    cameraList: [],
+    microphoneList: [],
+    logs: [],
+    isJoined: false,
+    isPublished: false,
+    isShared: false,
+    remoteStreams: [],
+    // invitedRemoteStreams: [],
+    avatar: null,
+    mode: '',
+    chatList: [],
+    memberList: [],
+    audioMuted: true,
+    inputStatus: true,
+    currentSession: null,
+  }),
+  persist: {
+    storage: localStorage,
+    paths: ['memberList'],
+  },
+  getters: {
+    checkUserInMemberList() {
+      return (userId: string) => this.memberList.find((item) => item.UserId === userId);
     },
-    getters: {
-        checkUserInMemberList() {
-            return (userId: string) => this.memberList.find(item => item.UserId === userId)
-        },
-        isLeader(): boolean {
-            return this.role === 'leader'
-        },
-        isMe() {
-            return (userId: string) => this.userId === userId
-        },
-        genUserSig() {
-            const { userSig } = genTestUserSig({
-                sdkAppId: parseInt(this.sdkAppId, 10),
-                userId: this.userId,
-                secretKey: this.secretKey,
-            });
-            return userSig
-        },
-        isUserInRemoteStream() {
-            return (userId: string) => {
-                return this.remoteStreams.some(item => item.getUserId() === userId)
-            }
-        }
+    isLeader(): boolean {
+      return this.role === 'leader';
+    },
+    isMe() {
+      return (userId: string) => this.userId === userId;
+    },
+    genUserSig() {
+      const { userSig } = genTestUserSig({
+        sdkAppId: parseInt(this.sdkAppId, 10),
+        userId: this.userId,
+        secretKey: this.secretKey,
+      });
+      return userSig;
+    },
+    isUserInRemoteStream() {
+      return (userId: string) => {
+        return this.remoteStreams.some((item) => item.getUserId() === userId);
+      };
+    },
+  },
+  actions: {
+    setSocketParams(params: SocketParams): void {
+      this.avatar = params.avatar;
+      this.roomId = params.roomId;
+      this.userId = params.userId;
+      this.nickname = params.nickname;
+      this.role = params.role;
+      if (!['leader', 'customer'].includes(params.role)) {
+        consola.info({
+          message: '角色参数有误',
+          level: 0,
+          tag: 'role',
+        });
+        this.role = 'customer';
+      }
+    },
+    setAvatar(payload: string) {
+      this.avatar = payload;
+      localStorage.setItem('leaderAvatar', payload || '');
+    },
+    setSocket(payload: SocketIOClient.Socket) {
+      this.socket = payload;
+    },
+    setShowDaoGou(payload: boolean) {
+      this.showDaoGou = payload;
     },
-    actions: {
-        setSocketParams(params: SocketParams): void {
-            this.avatar = params.avatar
-            this.roomId = params.roomId
-            this.userId = params.userId
-            this.nickname = params.nickname
-            this.role = params.role
-            if (!['leader', 'customer'].includes(params.role)) {
-                consola.info({
-                    message: '角色参数有误',
-                    level: 0,
-                    tag: 'role'
-                })
-                this.role = 'customer'
-
-            }
-        },
-        setAvatar(payload: string) {
-            this.avatar = payload
-            localStorage.setItem('leaderAvatar', payload || '')
-        },
-        setSocket(payload: SocketIOClient.Socket) {
-            this.socket = payload
-        },
-        setShowDaoGou(payload: boolean) {
-            this.showDaoGou = payload
-        },
-
-        setUserId(payload: string) {
-            this.userId = payload
-        },
-
-        setRoomId(payload: string) {
-            this.roomId = payload
-        },
-        setRole(payload: RoleType) {
-            this.role = payload
-        },
 
-        setDeviceList(payload: DeviceListParams) {
-            this.cameraList = payload.cameraItems
-            this.microphoneList = payload.microphoneItems
-        },
+    setUserId(payload: string) {
+      this.userId = payload;
+    },
 
-        setVideoDeviceId(payload: string) {
-            this.videoDeviceId = payload
-        },
+    setRoomId(payload: string) {
+      this.roomId = payload;
+    },
+    setRole(payload: RoleType) {
+      this.role = payload;
+    },
 
-        setAudioDeviceId(payload: string) {
-            this.audioDeviceId = payload
-        },
+    setDeviceList(payload: DeviceListParams) {
+      this.cameraList = payload.cameraItems;
+      this.microphoneList = payload.microphoneItems;
+    },
 
-        setIsJoined(payload: boolean) {
-            this.isJoined = payload
-        },
-        setIsPublished(payload: boolean) {
-            this.isPublished = payload
-        },
+    setVideoDeviceId(payload: string) {
+      this.videoDeviceId = payload;
+    },
 
-        addToChatList(content: ChatContentType) {
-            this.chatList.push(content)
-        },
-        setMemberList(members: UserInfoType[]) {
-            const memberList = members.reduce((prev: UserInfoType[], current: UserInfoType, index) => {
-                if (prev.findIndex((ele: UserInfoType) => ele.UserId === current.UserId) === -1) {
-                    // console.log(current);
-                    current.order = index > 1 ? index : 2
-                    if (current.Role === 'leader') {
-                        current.order = 0
-                    }
-                    if (current.UserId === this.userId) {
-                        current.order = 1
-                        this.currentSession = current
-                    }
+    setAudioDeviceId(payload: string) {
+      this.audioDeviceId = payload;
+    },
 
-                    prev.push(current);
-                }
-                return prev;
-            }, []);
-            const sortList = sortBy(memberList, ['order', 'UserId'], ['asc', 'asc'])
-            console.log('sortList', sortList)
-            this.memberList = sortList
-        },
+    setIsJoined(payload: boolean) {
+      this.isJoined = payload;
+    },
+    setIsPublished(payload: boolean) {
+      this.isPublished = payload;
+    },
 
-        clearMemberList(): void {
-            this.memberList = []
-        },
-        updateMemberDatabyId(UserId: string, data: Partial<UserInfoType>) {
-            const updateIndex = this.memberList.findIndex(member => member.UserId === UserId)
-            if (updateIndex > -1) {
-                this.memberList[updateIndex] = Object.assign({}, this.memberList[updateIndex], data)
-                //单点更新并是当事人也更一份数据
-                if (UserId === this.userId) {
-                    this.currentSession = this.memberList[updateIndex]
-                }
-            }
-        },
-        mute() {
-            this.setMute(false)
-        },
-        unmute() {
-            this.setMute(true)
-        },
-        setMute(mute: boolean) {
-            this.audioMuted = mute
-            this.updateMemberDatabyId(this.userId, {
-                IsMuted: mute,
-              });
-        },
+    addToChatList(content: ChatContentType) {
+      this.chatList.push(content);
+    },
+    setMemberList(members: UserInfoType[]) {
+      const memberList = members.reduce((prev: UserInfoType[], current: UserInfoType, index) => {
+        if (prev.findIndex((ele: UserInfoType) => ele.UserId === current.UserId) === -1) {
+          // console.log(current);
+          current.order = index > 1 ? index : 2;
+          if (current.Role === 'leader') {
+            current.order = 0;
+          }
+          if (current.UserId === this.userId) {
+            current.order = 1;
+            this.currentSession = current;
+          }
 
-        setinputStatus(status: boolean) {
-            this.inputStatus = status
-        },
+          prev.push(current);
+        }
+        return prev;
+      }, []);
+      const sortList = sortBy(memberList, ['order', 'UserId'], ['asc', 'asc']);
+      console.log('sortList', sortList);
+      this.memberList = sortList;
+    },
 
-        pushRemoteStreams(stream: RemoteStream) {
-            this.remoteStreams.push(stream)
-        },
-        removeRemoteStreams(id: string) {
-            const existStreamIndex = this.remoteStreams.findIndex(stream => stream.getId() === id)
-            if (existStreamIndex > -1) {
-                this.remoteStreams.splice(existStreamIndex, 1)
-            }
+    clearMemberList(): void {
+      this.memberList = [];
+    },
+    updateMemberDatabyId(UserId: string, data: Partial<UserInfoType>) {
+      const updateIndex = this.memberList.findIndex((member) => member.UserId === UserId);
+      if (updateIndex > -1) {
+        this.memberList[updateIndex] = Object.assign({}, this.memberList[updateIndex], data);
+        //单点更新并是当事人也更一份数据
+        if (UserId === this.userId) {
+          this.currentSession = this.memberList[updateIndex];
         }
+      }
+    },
+    mute() {
+      this.setMute(false);
+    },
+    unmute() {
+      this.setMute(true);
+    },
+    setMute(mute: boolean) {
+      this.audioMuted = mute;
+      this.updateMemberDatabyId(this.userId, {
+        IsMuted: mute,
+      });
     },
 
+    setinputStatus(status: boolean) {
+      this.inputStatus = status;
+    },
 
-})
+    pushRemoteStreams(stream: RemoteStream) {
+      this.remoteStreams.push(stream);
+    },
+    removeRemoteStreams(id: string) {
+      const existStreamIndex = this.remoteStreams.findIndex((stream) => stream.getId() === id);
+      if (existStreamIndex > -1) {
+        this.remoteStreams.splice(existStreamIndex, 1);
+      }
+    },
+  },
+});

+ 51 - 51
src/store/modules/scene.ts

@@ -1,62 +1,62 @@
 import { defineStore } from 'pinia';
+import { KankanMetaDataType } from '/#/sdk';
 import { getApp } from '/@/hooks/userApp';
 
 export interface FloorsType {
-    id: string,
-    subgroup?: string,
-    name: string
-    segment?: any[]
-    tagging?: any[]
-    ['vertex-xy']?: any[]
+  id: string;
+  subgroup?: string;
+  name: string;
+  segment?: any[];
+  tagging?: any[];
+  ['vertex-xy']?: any[];
 }
 interface SceneState {
-    tags: any[],
-    floors: FloorsType[],
-    metadata: KankanMetaDataType
+  tags: any[];
+  floors: FloorsType[];
+  metadata: KankanMetaDataType;
 }
 
 export const useSceneStore = defineStore({
-    id: 'scene',
-    state: (): SceneState => ({
-        tags: [],
-        floors: [],
-        metadata: {} as KankanMetaDataType
-    }),
-    getters: {
-        musicURL(): Nullable<string> {
-            const musicURl = this.metadata.music
-            if (musicURl) {
-                if (/^0\d$/.test(musicURl)) {
-                    return (window as any).resource.getStaticURL(`static/music/${musicURl}.mp3`)
-                } else {
-                    const app = getApp();
-                    return app.resource.getUserResourceURL(this.metadata.musicFile.replace(/(.+)\.(.+)/, 'music-user.$2'))
-                }
-            }
-            return null
-        },
-        loadingLogoFile(): Nullable<string> {
-            if (this.metadata.loadingLogo == 'user') {
-                const app = getApp();
-                return app.resource.getUserResourceURL(this.metadata.loadingLogoFile)
-            }
-            return null
+  id: 'scene',
+  state: (): SceneState => ({
+    tags: [],
+    floors: [],
+    metadata: {} as KankanMetaDataType,
+  }),
+  getters: {
+    musicURL(): Nullable<string> {
+      const musicURl = this.metadata.music;
+      if (musicURl) {
+        if (/^0\d$/.test(musicURl)) {
+          return (window as any).resource.getStaticURL(`static/music/${musicURl}.mp3`);
+        } else {
+          const app = getApp();
+          return app.resource.getUserResourceURL(
+            this.metadata.musicFile.replace(/(.+)\.(.+)/, 'music-user.$2'),
+          );
         }
-
+      }
+      return null;
     },
-    actions: {
-        load(metadata: KankanMetaDataType): void {
-            this.metadata = metadata
-            document.title = metadata.title
-        },
-        loadFloorData(floors: FloorsType[]) {
-            if (floors?.length) {
-                this.floors = floors.map(item => {
-                    return { id: item.subgroup, name: item.name }
-                }) as FloorsType[]
-            }
-
-        },
-    }
-
-})
+    loadingLogoFile(): Nullable<string> {
+      if (this.metadata.loadingLogo == 'user') {
+        const app = getApp();
+        return app.resource.getUserResourceURL(this.metadata.loadingLogoFile);
+      }
+      return null;
+    },
+  },
+  actions: {
+    load(metadata: KankanMetaDataType): void {
+      this.metadata = metadata;
+      document.title = metadata.title;
+    },
+    loadFloorData(floors: FloorsType[]) {
+      if (floors?.length) {
+        this.floors = floors.map((item) => {
+          return { id: item.subgroup, name: item.name };
+        }) as FloorsType[];
+      }
+    },
+  },
+});

+ 33 - 38
src/store/modules/tour.ts

@@ -1,46 +1,41 @@
 import { defineStore } from 'pinia';
 import { getApp, getNum } from '/@/hooks/userApp';
 
-
 export interface TourState {
-    toursList: any[]
-    sourceList: Nullable<any[]>
-    frameId: number
-    partId: number
-    tours: any[],
-    musicList: any[],
-    delList: any[]
-    isPlay: boolean,
-    showTours: boolean,
+  toursList: any[];
+  sourceList: Nullable<any[]>;
+  frameId: number;
+  partId: number;
+  tours: any[];
+  musicList: any[];
+  delList: any[];
+  isPlay: boolean;
+  showTours: boolean;
 }
 
 export const useTourStore = defineStore({
-    id: 'tour',
-    state: (): TourState => ({
-        toursList: [],
-        sourceList: null,
-        frameId: 0,
-        partId: 0,
-        tours: [],
-        musicList: [],
-        delList: [],
-        isPlay: false,
-        showTours: false,
-    }),
-    getters: {
+  id: 'tour',
+  state: (): TourState => ({
+    toursList: [],
+    sourceList: null,
+    frameId: 0,
+    partId: 0,
+    tours: [],
+    musicList: [],
+    delList: [],
+    isPlay: false,
+    showTours: false,
+  }),
+  getters: {},
+  actions: {
+    async delTours(): Promise<void> {
+      const app = getApp();
+      const res = await app.remote_editor.tour_delete({ num: getNum() });
+      console.log('res', res);
     },
-    actions: {
-        async delTours(): Promise<void> {
-            const app = getApp();
-            const res = await app.remote_editor.tour_delete({ num: getNum() })
-            console.log('res', res)
-        },
-        async delFile(): Promise<void> {
-
-        },
-        setData(toursList): void {
-            this.toursList = toursList
-        }
-    }
-
-})
+    async delFile(): Promise<void> {},
+    setData(toursList): void {
+      this.toursList = toursList;
+    },
+  },
+});

Plik diff jest za duży
+ 128 - 104
src/utils/browser.ts


+ 20 - 23
src/utils/install.ts

@@ -1,32 +1,29 @@
-import type { App } from 'vue'
-import type { SFCWithInstall, SFCInstallWithContext } from './typescript'
+import type { App } from 'vue';
+import type { SFCWithInstall, SFCInstallWithContext } from './typescript';
 
 // 组件
-export const withInstall = <T, E extends Record<string, any>>(
-    main: T,
-    extra?: E
-) => {
-    // 定义 install 属性
-    ; (main as SFCWithInstall<T>).install = (app): void => {
-        for (const comp of [main, ...Object.values(extra ?? {})]) {
-            app.component(comp.name, comp)
-        }
+export const withInstall = <T, E extends Record<string, any>>(main: T, extra?: E) => {
+  // 定义 install 属性
+  (main as SFCWithInstall<T>).install = (app): void => {
+    for (const comp of [main, ...Object.values(extra ?? {})]) {
+      app.component(comp.name, comp);
     }
+  };
 
-    if (extra) {
-        for (const [key, comp] of Object.entries(extra)) {
-            ; (main as any)[key] = comp
-        }
+  if (extra) {
+    for (const [key, comp] of Object.entries(extra)) {
+      (main as any)[key] = comp;
     }
-    return main as SFCWithInstall<T> & E
-}
+  }
+  return main as SFCWithInstall<T> & E;
+};
 
 // 函数
 export const withInstallFunction = <T>(fn: T, name: string) => {
-    ; (fn as SFCWithInstall<T>).install = (app: App) => {
-        ; (fn as SFCInstallWithContext<T>)._context = app._context
-        app.config.globalProperties[name] = fn
-    }
+  (fn as SFCWithInstall<T>).install = (app: App) => {
+    (fn as SFCInstallWithContext<T>)._context = app._context;
+    app.config.globalProperties[name] = fn;
+  };
 
-    return fn as SFCInstallWithContext<T>
-}
+  return fn as SFCInstallWithContext<T>;
+};

+ 119 - 118
src/utils/request.ts

@@ -6,139 +6,140 @@
  * @Description: 注释
  */
 // @ts-nocheck
-import axios from 'axios'
+import axios from 'axios';
 
 // TextDecoder polyfills for lower browser
 if (undefined === window.TextEncoder) {
-    window.TextEncoder = class _TextEncoder {
-        encode(s) {
-            return unescape(encodeURIComponent(s))
-                .split('')
-                .map(function (val) {
-                    return val.charCodeAt()
-                })
-        }
+  window.TextEncoder = class _TextEncoder {
+    encode(s) {
+      return unescape(encodeURIComponent(s))
+        .split('')
+        .map(function (val) {
+          return val.charCodeAt();
+        });
     }
-    window.TextDecoder = class _TextDecoder {
-        decode(code_arr) {
-            return decodeURIComponent(escape(String.fromCharCode.apply(null, code_arr)))
-        }
+  };
+  window.TextDecoder = class _TextDecoder {
+    decode(code_arr) {
+      return decodeURIComponent(escape(String.fromCharCode.apply(null, code_arr)));
     }
+  };
 }
 
-const fetch = axios.create()
+const fetch = axios.create();
 
 fetch.interceptors.request.use(
-    config => {
-        config.headers['token'] = 123
+  (config) => {
+    config.headers['token'] = 123;
 
-        return config
-    },
-    error => {
-        return Promise.reject(error)
-    }
-)
+    return config;
+  },
+  (error) => {
+    return Promise.reject(error);
+  },
+);
 fetch.interceptors.response.use(
-    response => {
-        // 正常的文件流
-        if (!/json/gi.test(response.headers['content-type'])) {
-            return response.data
-        }
-
-        // 以文件流方式请求但是返回json,需要解析为JSON对象
-        if (response.request.responseType === 'arraybuffer') {
-            let enc = new TextDecoder('utf-8')
-            let res = JSON.parse(enc.decode(new Uint8Array(response.data)))
-            return res
-        }
+  (response) => {
+    // 正常的文件流
+    if (!/json/gi.test(response.headers['content-type'])) {
+      return response.data;
+    }
 
-        return response.data
-    },
-    error => {
-        console.error(error)
+    // 以文件流方式请求但是返回json,需要解析为JSON对象
+    if (response.request.responseType === 'arraybuffer') {
+      const enc = new TextDecoder('utf-8');
+      const res = JSON.parse(enc.decode(new Uint8Array(response.data)));
+      return res;
     }
-)
+
+    return response.data;
+  },
+  (error) => {
+    console.error(error);
+  },
+);
 
 const http = {
-    retry(func, retries = 0, delay = 1000) {
-        return new Promise((resolve, reject) => {
-            func()
+  retry(func, retries = 0, delay = 1000) {
+    return new Promise((resolve, reject) => {
+      func()
+        .then(resolve)
+        .catch((error) => {
+          if (retries <= 1) {
+            reject(error);
+          } else {
+            setTimeout(() => {
+              http
+                .retry(func, retries - 1, delay)
                 .then(resolve)
-                .catch(error => {
-                    if (retries <= 1) {
-                        reject(error)
-                    } else {
-                        setTimeout(() => {
-                            http.retry(func, retries - 1, delay)
-                                .then(resolve)
-                                .catch(reject)
-                        }, delay)
-                    }
-                })
-        })
-    },
-    get(url,data) {
-        return fetch({
-            method: 'get',
-            url: url,
-            params:data
-        })
-    },
-    getImage(url, retries = 3) {
-        return http.retry(
-            () =>
-                new Promise((resolve, reject) => {
-                    let img = new Image()
-                    img.src = url
-                    img.crossOrigin = 'anonymous'
-                    img.onload = function () {
-                        resolve(img)
-                    }
-                    img.onerror = function () {
-                        reject(`[${url}] load fail`)
-                    }
-                }),
-            retries
-        )
-    },
-    getBueffer(url) {
-        return fetch.get(url, {
-            responseType: 'arraybuffer',
-        })
-    },
-    getBlob(url) {
-        return fetch.get(url, {
-            responseType: 'blob',
-        })
-    },
-    post(url, data) {
-        return fetch.post(url, data)
-    },
-    postFile(url, data) {
-        const form = new FormData()
-        let cb = null
-        if (data.onUploadProgress) {
-            cb = data.onUploadProgress
-            delete data.onUploadProgress
-        }
-        for (let key in data) {
-            // if (key === 'files' && data[key].length > 0) {
-            //     for (let i = 0; i < data[key].length; i++) {
-            //         form.append(key, data[key][i])
-            //     }
-            // } else {
-            //     form.append(key, data[key])
-            // }
-            form.append(key, data[key])
-        }
+                .catch(reject);
+            }, delay);
+          }
+        });
+    });
+  },
+  get(url, data) {
+    return fetch({
+      method: 'get',
+      url: url,
+      params: data,
+    });
+  },
+  getImage(url, retries = 3) {
+    return http.retry(
+      () =>
+        new Promise((resolve, reject) => {
+          const img = new Image();
+          img.src = url;
+          img.crossOrigin = 'anonymous';
+          img.onload = function () {
+            resolve(img);
+          };
+          img.onerror = function () {
+            reject(`[${url}] load fail`);
+          };
+        }),
+      retries,
+    );
+  },
+  getBueffer(url) {
+    return fetch.get(url, {
+      responseType: 'arraybuffer',
+    });
+  },
+  getBlob(url) {
+    return fetch.get(url, {
+      responseType: 'blob',
+    });
+  },
+  post(url, data) {
+    return fetch.post(url, data);
+  },
+  postFile(url, data) {
+    const form = new FormData();
+    let cb = null;
+    if (data.onUploadProgress) {
+      cb = data.onUploadProgress;
+      delete data.onUploadProgress;
+    }
+    for (const key in data) {
+      // if (key === 'files' && data[key].length > 0) {
+      //     for (let i = 0; i < data[key].length; i++) {
+      //         form.append(key, data[key][i])
+      //     }
+      // } else {
+      //     form.append(key, data[key])
+      // }
+      form.append(key, data[key]);
+    }
 
-        return fetch.post(url, form, {
-            headers: {
-                'Content-Type': 'multipart/form-data',
-            },
-            onUploadProgress: cb,
-        })
-    },
-}
+    return fetch.post(url, form, {
+      headers: {
+        'Content-Type': 'multipart/form-data',
+      },
+      onUploadProgress: cb,
+    });
+  },
+};
 
-export { http, fetch }
+export { http, fetch };

+ 4 - 4
src/utils/typescript.ts

@@ -1,7 +1,7 @@
-import type { AppContext, Plugin } from 'vue'
+import type { AppContext, Plugin } from 'vue';
 
-export type SFCWithInstall<T> = T & Plugin
+export type SFCWithInstall<T> = T & Plugin;
 
 export type SFCInstallWithContext<T> = SFCWithInstall<T> & {
-    _context: AppContext | null
-}
+  _context: AppContext | null;
+};

+ 3 - 3
src/vite-env.d.ts

@@ -1,7 +1,7 @@
 /// <reference types="vite/client" />
 
 declare module '*.vue' {
-  import type { DefineComponent } from 'vue'
-  const component: DefineComponent<{}, {}, any>
-  export default component
+  import type { DefineComponent } from 'vue';
+  const component: DefineComponent<{}, {}, any>;
+  export default component;
 }

+ 4 - 1
vite.config.ts

@@ -5,6 +5,7 @@ import { resolve } from 'path'
 import WindiCSS from "vite-plugin-windicss";
 import consola from 'consola'
 import mkcert from "vite-plugin-mkcert";
+// import eslintPlugin from 'vite-plugin-eslint' 
 // import requireTransform from 'vite-plugin-require-transform'
 
 function pathResolve(dir: string) {
@@ -16,7 +17,9 @@ function pathResolve(dir: string) {
 // https://vitejs.dev/config/
 export default ({ mode }) => defineConfig({
   plugins: [
-
+    // eslintPlugin({
+    //   include: ['src/**/*.ts', 'src/**/*.vue', 'src/*.js', 'src/*.vue']
+    // }),
     mkcert(),
     vue(),
     WindiCSS(),