gemercheung 2 år sedan
förälder
incheckning
98c7c08c05

+ 4 - 1
package.json

@@ -13,6 +13,7 @@
     "clipboard": "^2.0.11",
     "consola": "^2.15.3",
     "pinia": "^2.0.23",
+    "trtc-js-sdk": "^4.14.6",
     "uuid": "^9.0.0",
     "vue": "^3.2.41",
     "vue-types": "^4.2.1"
@@ -25,6 +26,8 @@
     "typescript": "^4.8.4",
     "vite": "^3.2.0",
     "vite-plugin-html-env": "^1.2.7",
-    "vue-tsc": "^1.0.9"
+    "vite-plugin-windicss": "^1.8.8",
+    "vue-tsc": "^1.0.9",
+    "windicss": "^3.5.6"
   }
 }

+ 156 - 0
pnpm-lock.yaml

@@ -9,19 +9,23 @@ specifiers:
   consola: ^2.15.3
   pinia: ^2.0.23
   sass: ^1.55.0
+  trtc-js-sdk: ^4.14.6
   typescript: ^4.8.4
   uuid: ^9.0.0
   vite: ^3.2.0
   vite-plugin-html-env: ^1.2.7
+  vite-plugin-windicss: ^1.8.8
   vue: ^3.2.41
   vue-tsc: ^1.0.9
   vue-types: ^4.2.1
+  windicss: ^3.5.6
 
 dependencies:
   axios: 1.1.3
   clipboard: 2.0.11
   consola: 2.15.3
   pinia: 2.0.23_l7r24p6nevbtlimqmqcwa3ouhu
+  trtc-js-sdk: 4.14.6
   uuid: 9.0.0
   vue: 3.2.41
   vue-types: 4.2.1_vue@3.2.41
@@ -34,10 +38,16 @@ devDependencies:
   typescript: 4.8.4
   vite: 3.2.0_sass@1.55.0
   vite-plugin-html-env: 1.2.7_vite@3.2.0
+  vite-plugin-windicss: 1.8.8_vite@3.2.0
   vue-tsc: 1.0.9_typescript@4.8.4
+  windicss: 3.5.6
 
 packages:
 
+  /@antfu/utils/0.5.2:
+    resolution: {integrity: sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==}
+    dev: true
+
   /@babel/helper-string-parser/7.19.4:
     resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==}
     engines: {node: '>=6.9.0'}
@@ -79,6 +89,27 @@ packages:
     dev: true
     optional: true
 
+  /@nodelib/fs.scandir/2.1.5:
+    resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+    engines: {node: '>= 8'}
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      run-parallel: 1.2.0
+    dev: true
+
+  /@nodelib/fs.stat/2.0.5:
+    resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+    engines: {node: '>= 8'}
+    dev: true
+
+  /@nodelib/fs.walk/1.2.8:
+    resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+    engines: {node: '>= 8'}
+    dependencies:
+      '@nodelib/fs.scandir': 2.1.5
+      fastq: 1.13.0
+    dev: true
+
   /@types/node/18.11.7:
     resolution: {integrity: sha512-LhFTglglr63mNXUSRYD8A+ZAIu5sFqNJ4Y2fPuY7UlrySJH87rRRlhtVmMHplmfk5WkoJGmDjE9oiTfyX94CpQ==}
     dev: true
@@ -215,6 +246,30 @@ packages:
   /@vue/shared/3.2.41:
     resolution: {integrity: sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==}
 
+  /@windicss/config/1.8.8:
+    resolution: {integrity: sha512-kNas/zMkwsDFMcJPmHoPDJlQi1MHvYwx8BSxo9JKcbCW7Gaj8Rg2CnEImX5YdT+ZcFQqQ+kUn0Vi/ScsAxhGEw==}
+    dependencies:
+      debug: 4.3.4
+      jiti: 1.16.0
+      windicss: 3.5.6
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@windicss/plugin-utils/1.8.8:
+    resolution: {integrity: sha512-a+npbTKmdrAvnMqzVJvyPa29xyNcPaSkt6qQpgWY9m0WyVlYd9BM8V0+cbqt279fTlvlaZpUs9dqmilB1PUH6g==}
+    dependencies:
+      '@antfu/utils': 0.5.2
+      '@windicss/config': 1.8.8
+      debug: 4.3.4
+      fast-glob: 3.2.12
+      magic-string: 0.26.7
+      micromatch: 4.0.5
+      windicss: 3.5.6
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /anymatch/3.1.2:
     resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
     engines: {node: '>= 8'}
@@ -300,6 +355,18 @@ packages:
     resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
     dev: true
 
+  /debug/4.3.4:
+    resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.1.2
+    dev: true
+
   /delayed-stream/1.0.0:
     resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
     engines: {node: '>=0.4.0'}
@@ -522,6 +589,23 @@ packages:
   /estree-walker/2.0.2:
     resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
 
+  /fast-glob/3.2.12:
+    resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
+    engines: {node: '>=8.6.0'}
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      '@nodelib/fs.walk': 1.2.8
+      glob-parent: 5.1.2
+      merge2: 1.4.1
+      micromatch: 4.0.5
+    dev: true
+
+  /fastq/1.13.0:
+    resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
+    dependencies:
+      reusify: 1.0.4
+    dev: true
+
   /fill-range/7.0.1:
     resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
     engines: {node: '>=8'}
@@ -624,11 +708,40 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: false
 
+  /jiti/1.16.0:
+    resolution: {integrity: sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==}
+    hasBin: true
+    dev: true
+
+  /kolorist/1.6.0:
+    resolution: {integrity: sha512-dLkz37Ab97HWMx9KTes3Tbi3D1ln9fCAy2zr2YVExJasDRPGRaKcoE4fycWNtnCAJfjFqe0cnY+f8KT2JePEXQ==}
+    dev: true
+
   /magic-string/0.25.9:
     resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
     dependencies:
       sourcemap-codec: 1.4.8
 
+  /magic-string/0.26.7:
+    resolution: {integrity: sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==}
+    engines: {node: '>=12'}
+    dependencies:
+      sourcemap-codec: 1.4.8
+    dev: true
+
+  /merge2/1.4.1:
+    resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+    engines: {node: '>= 8'}
+    dev: true
+
+  /micromatch/4.0.5:
+    resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+    engines: {node: '>=8.6'}
+    dependencies:
+      braces: 3.0.2
+      picomatch: 2.3.1
+    dev: true
+
   /mime-db/1.52.0:
     resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
     engines: {node: '>= 0.6'}
@@ -648,6 +761,10 @@ packages:
       brace-expansion: 2.0.1
     dev: true
 
+  /ms/2.1.2:
+    resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+    dev: true
+
   /muggle-string/0.1.0:
     resolution: {integrity: sha512-Tr1knR3d2mKvvWthlk7202rywKbiOm4rVFLsfAaSIhJ6dt9o47W4S+JMtWhd/PW9Wrdew2/S2fSvhz3E2gkfEg==}
     dev: true
@@ -704,6 +821,10 @@ packages:
     resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
     dev: false
 
+  /queue-microtask/1.2.3:
+    resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+    dev: true
+
   /readdirp/3.6.0:
     resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
     engines: {node: '>=8.10.0'}
@@ -720,6 +841,11 @@ packages:
       supports-preserve-symlinks-flag: 1.0.0
     dev: true
 
+  /reusify/1.0.4:
+    resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+    engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+    dev: true
+
   /rollup/2.79.1:
     resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==}
     engines: {node: '>=10.0.0'}
@@ -728,6 +854,12 @@ packages:
       fsevents: 2.3.2
     dev: true
 
+  /run-parallel/1.2.0:
+    resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+    dependencies:
+      queue-microtask: 1.2.3
+    dev: true
+
   /sass/1.55.0:
     resolution: {integrity: sha512-Pk+PMy7OGLs9WaxZGJMn7S96dvlyVBwwtToX895WmCpAOr5YiJYEUJfiJidMuKb613z2xNWcXCHEuOvjZbqC6A==}
     engines: {node: '>=12.0.0'}
@@ -773,6 +905,10 @@ packages:
       is-number: 7.0.0
     dev: true
 
+  /trtc-js-sdk/4.14.6:
+    resolution: {integrity: sha512-ERjHQMWY6rmVVAlNTIxaL1PPKjEfewZZDLcEvjDGyGmr0jLYkX3n579A3CfCThTtcBHHpDjsbI2Ac3xnAx1h6g==}
+    dev: false
+
   /typescript/4.8.4:
     resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==}
     engines: {node: '>=4.2.0'}
@@ -792,6 +928,20 @@ packages:
       vite: 3.2.0_sass@1.55.0
     dev: true
 
+  /vite-plugin-windicss/1.8.8_vite@3.2.0:
+    resolution: {integrity: sha512-iyu+ZX0NmhNEUaLPv7xtC+EFRBpWMmw0nhd9a9upayfuNG/thwslKiQKmRB7U/dG0k/2oWLvPDvN/B9i7oRgSA==}
+    peerDependencies:
+      vite: ^2.0.1 || ^3.0.0
+    dependencies:
+      '@windicss/plugin-utils': 1.8.8
+      debug: 4.3.4
+      kolorist: 1.6.0
+      vite: 3.2.0_sass@1.55.0
+      windicss: 3.5.6
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
   /vite/3.2.0_sass@1.55.0:
     resolution: {integrity: sha512-Ovj7+cqIdM1I0LPCk2CWxzgADXMix3NLXpUT6g7P7zg/a9grk/TaC3qn9YMg7w7M0POIVCBOp1aBANJW+RH7oA==}
     engines: {node: ^14.18.0 || >=16.0.0}
@@ -874,3 +1024,9 @@ packages:
       '@vue/runtime-dom': 3.2.41
       '@vue/server-renderer': 3.2.41_vue@3.2.41
       '@vue/shared': 3.2.41
+
+  /windicss/3.5.6:
+    resolution: {integrity: sha512-P1mzPEjgFMZLX0ZqfFht4fhV/FX8DTG7ERG1fBLiWvd34pTLVReS5CVsewKn9PApSgXnVfPWwvq+qUsRwpnwFA==}
+    engines: {node: '>= 12'}
+    hasBin: true
+    dev: true

+ 12 - 2
src/App.vue

@@ -5,9 +5,14 @@ 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 { 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 { createSocket } from "./hooks/userRoom";
+
+
 const sceneStore = useSceneStore();
 const appStore = useAppStore();
 const dataLoaded = ref(false);
@@ -39,6 +44,7 @@ onMounted(async () => {
     num: "KK-t-gpAaKxXhE9",
     mobile: true,
   });
+  createSocket();
   // SDK初始化
   app.use("MinMap", { theme: { camera_fillStyle: "#ED5D18" } });
   app.use("Tag");
@@ -121,6 +127,8 @@ const changeMode = (name: string) => {
 
 <template>
   <LoadingLogo :thumb="true" />
+  <!-- 引导页 -->
+  <Guideline />
   <div class="ui-view-layout" :class="{ show: show }">
     <div class="scene" ref="scene$"></div>
     <template v-if="dataLoaded">
@@ -139,6 +147,8 @@ const changeMode = (name: string) => {
         @change-mode="changeMode"
       />
       <!-- 平面图 end -->
+
+      <ChatRoom />
     </template>
   </div>
 </template>

+ 4 - 3
src/components/RTC/PageRtcLive.vue

@@ -216,7 +216,7 @@
   />
 </template>
 
-<script setup>
+<script setup lang="ts">
 import {
   onMounted,
   onUnmounted,
@@ -235,7 +235,8 @@ import {
   currentScene,
   sceneList,
 } from "@/store/room";
-import { useApp, getApp } from "@/app";
+
+import { useApp, getApp } from "/@/hooks/userApp";
 import { useStore } from "vuex";
 import { Dialog } from "@/global_components/";
 import common from "@/utils/common";
@@ -249,7 +250,7 @@ import defaultAvatar from "@/assets/images/avatar_default.png";
 import { isMiniApp } from "@/env";
 import { initialMini } from "./mini-platform";
 import Icon from "@/components/icon/index.vue";
-import { useMusicPlayer } from "@/utils/sound";
+// import { useMusicPlayer } from "@/utils/sound";
 
 const emit = defineEmits(["openDialog", "closeSocket"]);
 

+ 1 - 1
src/components/RTC/dialog/checkBrowser.vue

@@ -14,7 +14,7 @@
   </div>
 </template>
 
-<script>
+<script >
 export default {
   data() {
     return {

+ 4 - 2
src/components/RTC/paint/Draw.vue

@@ -20,11 +20,13 @@
   </div>
 </template>
 <script lang="ts">
-import { getRole, sendToH5 } from "../../../rtc_socket";
+import { getRole, sendToH5 } from "../../../utils/rtc_socket";
 import { objects } from "/@/core/base";
 import math from "/@/core/util/math";
 import convertTool from "/@/core/util/convertTool";
 
+
+
 export default {
   props: {
     showPaint: Boolean,
@@ -162,7 +164,7 @@ export default {
       draw.forEach((item, index) => {
         math.convertScreenPositionToNDC(item.x, item.y, this.mouse);
 
-        var intersect = convertTool.getMouseIntersect(
+        var intersect = .getMouseIntersect(
           objects.player.camera,
           [this.intersectPlane],
           this.mouse

+ 1 - 1
src/components/RTC/trtc/Device.vue

@@ -2,7 +2,7 @@
   <div></div>
 </template>
 
-<script setup>
+<script lang="ts" setup>
 import { defineEmits, computed, ref } from "vue";
 import TRTC from "trtc-js-sdk";
 import { useStore } from "vuex";

+ 11 - 9
src/components/basic/guide.vue

@@ -8,18 +8,20 @@
   </div>
 </template>
 <script lang="ts" setup>
-import { onMounted, watch, computed, ref, nextTick } from "vue";
-import { useApp } from "@/app";
-import browser from "@/utils/browser";
-import { useStore } from "vuex";
+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 show = computed(() => store.getters["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());
+  // store.commit("showUserGuide", false);
+  // localStorage.setItem("user_guide", Date.now());
 };
 const getTips = (tips) => {
   let text = tips.split("<br />");
@@ -28,7 +30,7 @@ const getTips = (tips) => {
 useApp().then((app) => {
   app.Scene.on("loaded", () => {
     if (!localStorage.getItem("user_guide")) {
-      store.commit("showUserGuide", true);
+      // store.commit("showUserGuide", true);
     }
   });
 });

+ 71 - 0
src/components/chatRoom/chat.vue

@@ -0,0 +1,71 @@
+<template>
+  <div id="chat">
+    <div id="contents">
+      <div class="chat-item" v-for="(i, index) in chatList" :key="index">
+        <div class="chat-msg">
+          <!-- {{ user_info }} -->
+          <span :class="{ my: i.UserId == user_info.UserId }" class="chat-name">
+            {{ i.Nickname }} &nbsp;</span
+          >
+          <span class="chat-content"> {{ i.text }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { defineProps, } from "vue";
+
+const props = defineProps({
+  user_info: {
+    type: Object,
+    default: {},
+  },
+  chatList: {
+    type: Array,
+    default: [],
+  },
+});
+</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;
+
+    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;
+    }
+  }
+  &::-webkit-scrollbar {
+    display: none;
+  }
+}
+</style>

+ 558 - 0
src/components/chatRoom/chatroom.scss

@@ -0,0 +1,558 @@
+.avatar-box {
+    width: 1.7067rem;
+    height: 1.7067rem;
+    margin: 0.56rem auto 0;
+    border: 1px #ed5d18 solid;
+    border-radius: 50%;
+    // background-image: url('@/assets/images/avatar_default.jpg');
+    background-size: 100%;
+    background-repeat: no-repeat;
+    position: fixed;
+    top: 0.2667rem;
+    left: 0.2667rem;
+    z-index: 100;
+    overflow: hidden;
+    .tips {
+      width: 100%;
+      height: 0.5rem;
+      position: absolute;
+      background: rgba(0, 0, 0, 0.5);
+      bottom: 0;
+      left: 0;
+      text-align: center;
+      line-height: 0.5rem;
+      font-size: 0.22rem;
+      color: #ed5d18;
+    }
+    input {
+      width: 100%;
+      height: 100%;
+      opacity: 0;
+      position: relative;
+      z-index: 10;
+      cursor: pointer;
+    }
+  }
+  #PageRtcLive {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    // height: 7.31rem;
+    width: 100%;
+    z-index: 999;
+    //   background: rgba(0, 0, 0, 0.1);
+    padding: 0 0.44rem;
+    box-sizing: border-box;
+    // pointer-events: none;
+    .member_number {
+      // width: 1.67rem;
+      height: 0.5rem;
+      background: rgba(0, 0, 0, 0.3);
+      border-radius: 0.25rem;
+      position: fixed;
+      top: 0.56rem;
+      right: 0.44rem;
+      padding: 0.07rem 0.17rem;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      .members {
+        width: 0.42rem;
+        height: 0.42rem;
+        background: url(/@/assets/images/rtcLive/members@2x.png);
+        background-size: 100% 100%;
+        margin-right: 0.07rem;
+      }
+      span {
+        font-size: 0.24rem;
+        color: #fff;
+      }
+    }
+    .controlBar {
+      width: 9.51rem;
+      height: 1.173333rem;
+      background: rgba(0, 0, 0, 0.5);
+      border-radius: 0.67rem;
+      border: 0.03rem solid rgba(255, 255, 255, 0.1);
+      margin: 0.67rem auto 0;
+      // position: absolute;
+      position: fixed;
+      z-index: 9999;
+      left: 50%;
+      transform: translateX(-50%);
+      padding: 0 0.266667rem;
+      box-sizing: border-box;
+      bottom: 0.94rem;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      .saySomething {
+        color: #fff;
+        // font-size: 0.42rem;
+        height: 0.8rem;
+        position: relative;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        background: rgba(0, 0, 0, 0.5);
+        padding: 0 0.2rem 0 0.2rem;
+        border-radius: 0.64rem;
+        width: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        .disSpeakBtn {
+          width: 0.533333rem;
+          height: 0.533333rem;
+          background: url(/@/assets/images/rtcLive/pop-up_screen_on@2x.png)
+            no-repeat;
+          background-size: 100% 100%;
+          cursor: pointer;
+          &.dis {
+            background: url(/@/assets/images/rtcLive/pop-up_screen_off@2x.png)
+              no-repeat;
+            background-size: 100% 100%;
+          }
+        }
+        .speakIcon {
+          width: 0.32rem;
+          height: 0.32rem;
+          background: url(/@/assets/images/rtcLive/Input_norma@2x.png);
+          background-size: 100% 100%;
+          display: block;
+          margin-right: 0.1rem;
+          &.dis {
+            background: url(/@/assets/images/rtcLive/Input_disabled@2x.png);
+            background-size: 100% 100%;
+          }
+        }
+        span {
+          font-size: 0.266667rem;
+        }
+        // &::after {
+        //   content: "";
+        //   position: absolute;
+        //   width: 0.04rem;
+        //   height: 0.44rem;
+        //   background: #ffffff;
+        //   border-radius: 0.03rem;
+        //   top: 50%;
+        //   transform: translateY(-50%);
+        //   right: -0.28rem;
+        // }
+      }
+      .control_btn {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        margin-left: 0.2rem;
+        > div {
+          // width: 0.56rem;
+          // height: 0.56rem;
+          width: 0.65rem;
+          height: 0.65rem;
+          // font-size: 0.56rem;
+          // background: #FD5151;
+          margin-right: 0.33rem;
+          // &.iconexit {
+          //   //   width: 0.56rem;
+          //   //   height: 0.56rem;
+          //   color: #fd5151;
+          //   //   background: #fff;
+          //   //   border-radius: 50%;
+          //   //   overflow: hidden;
+          // }
+          &.brushesBack {
+            background: url(/@/assets/images/rtcLive/revocation@2x.png);
+            background-size: 100% 100%;
+          }
+          &.brushes {
+            // background: url(/@/assets/images/rtcLive/brushes@2x.png);
+            background: url(/@/assets/images/rtcLive/brushes@2x.png);
+            background-size: 100% 100%;
+          }
+          &.brushesed {
+            background: url(/@/assets/images/rtcLive/brushes_selected@2_1.png);
+            background-size: 100% 100%;
+          }
+          &.invitation {
+            background: url(/@/assets/images/rtcLive/invitation@2x.png);
+            background-size: 100% 100%;
+          }
+          &.members {
+            background: url(/@/assets/images/rtcLive/members@2x.png);
+            background-size: 100% 100%;
+          }
+          &.mic_on {
+            background: url(/@/assets/images/rtcLive/mic_on@2x.png);
+            background-size: 100% 100%;
+          }
+          &.mic_no {
+            background: url(/@/assets/images/rtcLive/mic_off_50@2x.png);
+            background-size: 100% 100%;
+          }
+          &.mic_off {
+            background: url(/@/assets/images/rtcLive/mic_off@2x.png);
+            background-size: 100% 100%;
+          }
+          &.video_on {
+            background: url(/@/assets/images/rtcLive/video_on@2x.png);
+            background-size: 100% 100%;
+          }
+          &.video_no {
+            background: url(/@/assets/images/rtcLive/video_off_50@2x.png);
+            background-size: 100% 100%;
+          }
+          &.video_off {
+            background: url(/@/assets/images/rtcLive/video_off@2x.png);
+            background-size: 100% 100%;
+          }
+          &.exit {
+            background: url(/@/assets/images/rtcLive/exit@2x.png);
+            background-size: 100% 100%;
+          }
+          &:last-child {
+            margin-right: 0;
+          }
+        }
+      }
+    }
+    .layer {
+      width: 100vw;
+      height: 100vh;
+      background: rgba(0, 0, 0, 0.1);
+      z-index: 10000;
+  
+      position: fixed;
+      bottom: 0;
+      left: 0;
+      // right: unset;
+      // top: unset;
+      .inputBox {
+        width: 100vw;
+        height: 1.39rem;
+        // background: #f2f2f2;
+        border: 1px solid rgba(255, 255, 255, 0.1);
+        background: rgba(0, 0, 0, 0.5);
+  
+        position: absolute;
+        bottom: 0;
+        left: 0;
+        padding: 0 0.44rem;
+        box-sizing: border-box;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .msgBox {
+          width: 9.53rem;
+          height: 0.94rem;
+          position: absolute;
+          > input {
+            width: 9.53rem;
+            height: 0.94rem;
+            background: rgba(0, 0, 0, 0.5);
+            border-radius: 0.56rem;
+            font-size: 0.42rem;
+            padding: 0 1.6rem 0 0.44rem;
+            box-sizing: border-box;
+            border: none;
+            outline: none;
+            color: #fff;
+            resize: none;
+            line &::placeholder {
+              color: rgba(255, 255, 255, 0.5);
+            }
+          }
+          .iconfont {
+            // width: 0.56rem;
+            // height: 0.56rem;
+            // background: #ed5d18;
+            font-size: 0.56rem;
+            position: absolute;
+            top: 50%;
+            transform: translateY(-50%);
+            right: 0.78rem;
+            color: #fff;
+            &.active {
+              color: #ed5d18;
+            }
+          }
+          .iconsend_icon {
+            position: absolute;
+            top: 50%;
+            transform: translateY(-50%);
+            // right: 0.78rem;
+            right: 0.106667rem;
+            width: 1.28rem;
+            height: 0.693333rem;
+            background: #ed5d18;
+            color: #fff;
+            font-size: 0.32rem;
+            text-align: center;
+            line-height: 0.693333rem;
+            border-radius: 0.533333rem;
+            // width: 0.67rem;
+            // height: 0.67rem;
+            // background-image: url(/@/assets/images/rtcLive/send_selected@2x.png);
+            // background-size: 100% 100%;
+          }
+        }
+      }
+      .memberContent {
+        height: auto;
+        width: 100%;
+        // background: #ffffff;
+        border-radius: 0.28rem 0.28rem 0px 0px;
+        position: absolute;
+        left: 0;
+        bottom: 0;
+        &.animated {
+          animation-duration: 0.3s;
+        }
+        .blurBox {
+          background: rgba(0, 0, 0, 0.9);
+          border-radius: 0.14rem 0.14rem 0px 0px;
+          filter: blur(1px);
+          position: absolute;
+          width: 100%;
+          height: 100%;
+          z-index: 1;
+          top: 0;
+          left: 0;
+        }
+        .content {
+          position: relative;
+          width: 100%;
+          height: 100%;
+          z-index: 2;
+          top: 0;
+          left: 0;
+        }
+        .memberHeader {
+          width: 100%;
+          height: 1.28rem;
+          text-align: center;
+          line-height: 1.28rem;
+          > span {
+            font-size: 0.42rem;
+            color: #fff;
+          }
+        }
+        .memberList {
+          width: 100%;
+          height: 8.33rem;
+          border-top-style: solid;
+          border-top-color: rgba(0, 0, 0, 0.1);
+          border-top-width: 1px;
+          border-bottom-style: solid;
+          border-bottom-color: rgba(0, 0, 0, 0.1);
+          border-bottom-width: 1px;
+          box-sizing: border-box;
+          overflow-y: auto;
+          &::-webkit-scrollbar {
+            display: none;
+          }
+          .memberItem {
+            width: 100%;
+            height: 1.39rem;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            padding: 0.19rem 0.44rem;
+  
+            .userMsg {
+              display: flex;
+              align-items: center;
+              justify-content: center;
+  
+              .avatar {
+                width: 1rem;
+                height: 1rem;
+                border-radius: 50%;
+                // overflow: hidden;
+                margin-right: 0.28rem;
+                > img {
+                  // width: 100%;
+                  // height: 100%;
+                  width: 1rem;
+                  height: 1rem;
+                }
+              }
+              .name {
+                font-size: 0.39rem;
+                color: #fff;
+              }
+            }
+            .button {
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              > div {
+                //   width: 0.56rem;
+                //   height: 0.56rem;
+                //   background: #fc6970;
+                font-size: 0.65rem;
+                color: #fff;
+                &.micBtn {
+                  width: 0.65rem;
+                  height: 0.65rem;
+                  margin-right: 0.3rem;
+                  &.mute_all_mic {
+                    background-image: url(/@/assets/images/rtcLive/mic_all_on@2x.png);
+                    background-size: 100% 100%;
+                  }
+                  &.open_all_mic {
+                    background-image: url(/@/assets/images/rtcLive/mic_all_off@2x.png);
+                    background-size: 100% 100%;
+                  }
+                  &.mute_one_mic_on {
+                    background-image: url(/@/assets/images/rtcLive/mic_on@2x.png);
+                    background-size: 100% 100%;
+                  }
+                  &.mute_one_mic_off {
+                    background-image: url(/@/assets/images/rtcLive/mic_off@2x.png);
+                    background-size: 100% 100%;
+                  }
+                  &.ban_speak_on {
+                    background-image: url(/@/assets/images/rtcLive/chat_on@2x.png);
+                    background-size: 100% 100%;
+                  }
+                  &.ban_speak_off {
+                    background-image: url(/@/assets/images/rtcLive/chat_off@2x.png);
+                    background-size: 100% 100%;
+                  }
+                }
+                &.outBtn {
+                  margin-right: 0.3rem;
+                  width: 0.65rem;
+                  height: 0.65rem;
+                  &.icon_remove {
+                    background-image: url(/@/assets/images/rtcLive/remove@2x.png);
+                    background-size: 100% 100%;
+                  }
+                }
+              }
+            }
+          }
+        }
+        .memberBottom {
+          width: 100%;
+          padding: 0 0.44rem;
+          box-sizing: border-box;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          padding: 0.28rem 0;
+          box-sizing: border-box;
+          > div {
+            width: 4.61rem;
+            height: 1.11rem;
+            color: #ed5d18;
+            border-radius: 0.11rem;
+            border: 0.03rem solid #ed5d18;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            font-size: 0.39rem;
+            &.mute_all {
+              margin-right: 0.31rem;
+            }
+          }
+        }
+      }
+    }
+  
+    .chat__area-layoutBox {
+      display: block;
+      width: 100%;
+      height: auto;
+      position: fixed;
+      bottom: 0;
+      left: 0;
+      right: unset;
+      top: unset;
+      background: #fff;
+      // padding-bottom: 0.821256rem;
+      .chat__area-layoutBox_bg {
+        width: 100vw;
+        height: 100vh;
+        position: fixed;
+        z-index: 1;
+        top: 0;
+        left: 0;
+      }
+      .chat__area-l-content {
+        display: -webkit-box;
+        display: -ms-flexbox;
+        display: flex;
+        -webkit-box-orient: horizontal;
+        -webkit-box-direction: normal;
+        -ms-flex-direction: row;
+        flex-direction: row;
+        -webkit-box-align: center;
+        -ms-flex-align: center;
+        align-items: center;
+        -webkit-box-pack: center;
+        -ms-flex-pack: center;
+        justify-content: center;
+        min-height: 0.821256rem;
+        padding: 0.241546rem 0;
+        width: 100%;
+        position: relative;
+        z-index: 100;
+        textarea {
+          width: calc(100% - 0.96618rem);
+          -ms-flex-preferred-size: calc(100% - 0.96618rem);
+          flex-basis: calc(100% - 0.96618rem);
+          background: none;
+          border: none;
+          border-radius: 0;
+          color: #000;
+          font-size: 0.386473rem;
+          line-height: 0.483092rem;
+          padding: 0 0.241546rem;
+          resize: none;
+          -webkit-user-select: text;
+          caret-color: #ff4500;
+          overflow: hidden !important;
+        }
+      }
+    }
+  
+    @keyframes myAnimation {
+      0% {
+        background-position: 0px 0px;
+        background-size: 13.3344rem auto;
+      }
+  
+      100% {
+        background-position: -13.1104rem 0px;
+        background-size: 13.3344rem auto;
+      }
+    }
+  }
+  .sharetip {
+    position: fixed;
+    z-index: 99999;
+    width: 100%;
+    height: 100%;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    top: 0;
+    background-color: rgba($color: #000000, $alpha: 0.66);
+    > img {
+      position: absolute;
+      right: 16%;
+      top: 0;
+      max-width: 70vw;
+    }
+  }
+  .cropper-box {
+    z-index: 1000;
+  }
+  
+  .disable {
+    opacity: 0.5;
+    pointer-events: none;
+  }

+ 76 - 0
src/components/chatRoom/index.vue

@@ -0,0 +1,76 @@
+<template>
+  <!-- 主区域 start  -->
+  <div id="PageRtcLive">
+    <div class="controlBar" v-if="!showInput">
+      <div class="saySomething" @click="onFocus">
+        <!-- <i class="speakIcon"
+           :class="{'dis':!user_info.IsWords}"></i> -->
+        <span>说点什么~</span>
+        <!-- <span>已被禁言</span> -->
+
+        <div class="disSpeakBtn"></div>
+      </div>
+      <!-- <div style="text-align: right; width: 100%">连接中...</div> -->
+      <div class="control_btn">
+        <div class="brushesBack"></div>
+        <div class="brushes"></div>
+
+        <div class="invitation"></div>
+        <div></div>
+        <template>
+          <div class="mic_on"></div>
+          <div class="mic_no"></div>
+        </template>
+
+        <div style="font-size: 0.65rem">
+          <Icon type="scene" />
+        </div>
+        <div class="exit"></div>
+      </div>
+    </div>
+
+    <!-- 主区域 end  -->
+
+    <div class="layer" v-if="showInput" @click.stop="closeText">
+      <div class="inputBox" @click.stop>
+        <div class="msgBox">
+          <input
+            id="input_msg"
+            type="text"
+            maxlength="50"
+            v-model.trim="text"
+            :placeholder="`说点什么~`"
+          />
+          <span
+            class="iconsend_icon"
+            :class="{ disable: text == '' }"
+            @click.stop="sendText"
+            >发送</span
+          >
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { onMounted, ref } from "vue";
+import { getApp } from "/@/hooks/userApp";
+
+const showInput = ref(false);
+const text = ref<string>("");
+onMounted(() => {
+  const app = getApp();
+});
+
+/* method */
+function closeText() {}
+function sendText() {}
+function onFocus(): void {
+  showInput.value = true;
+}
+</script>
+
+<style scoped lang="scss">
+@import "./chatroom.scss";
+</style>

+ 16 - 0
src/hooks/userRoom.ts

@@ -0,0 +1,16 @@
+import { useRtcStore } from "/@/store/modules/rtc";
+
+const io = (window as any).io as SocketIOClientStatic
+
+export function createSocket() {
+    const rtcStore = useRtcStore()
+    console.log('rtcStore', rtcStore)
+    const address = import.meta.env.VITE_APP_SOCKET_URL
+    const socket = io(address, {
+        path: "/ws-sync",
+        transports: ["websocket"],
+    });
+    console.log('socket', socket)
+    // rtcStore.setSocket(socket)
+    return socket
+}

+ 3 - 0
src/main.ts

@@ -1,5 +1,8 @@
 import { createApp } from 'vue'
+import 'virtual:windi-base.css';
+import 'virtual:windi-components.css';
 import './style.css'
+import 'virtual:windi-utilities.css';
 import "/@/assets/theme.editor.scss";
 import { setupStore } from '/@/store';
 import App from './App.vue'

+ 72 - 9
src/store/modules/rtc.ts

@@ -1,19 +1,38 @@
 import { defineStore } from 'pinia';
+interface RtcState {
+    socket: Nullable<SocketIOClientStatic>,
+    showDaoGou: boolean,
+    sdkAppId: string,
+    userId: string,
+    roomId: string,
+    role: string,
+    secretKey: string
+    userSig: string
+    audioDeviceId: string,
+    videoDeviceId: string,
+    cameraList: MediaDeviceInfo[],
+    microphoneList: MediaDeviceInfo[],
+    logs: any[],
+    isJoined: boolean,
+    isPublished: boolean,
+    isShared: boolean,
+    remoteStreams: any[],
+    invitedRemoteStreams: any[],
+    avatar: Nullable<string>,
 
-interface floorsType {
-    id: string,
-    subgroup: string,
-    name: string
 }
-interface RtcState {
- 
+
+interface DeviceListParams {
+    cameraItems: MediaDeviceInfo[],
+    microphoneItems: MediaDeviceInfo[],
 }
 
+
 export const useRtcStore = defineStore({
     id: 'rtc',
     state: (): RtcState => ({
         socket: null,
-        showdaogou: false,
+        showDaoGou: false,
         sdkAppId: "1400685498",
         userId: '',
         roomId: '',
@@ -34,8 +53,52 @@ export const useRtcStore = defineStore({
 
     }),
     getters: {
-      
-
+        isLeader(): boolean {
+            return this.role === 'leader'
+        }
     },
+    actions: {
+        setAvatar(payload: string) {
+            this.avatar = payload
+            localStorage.setItem('leaderAvatar', payload || '')
+        },
+        setSocket(payload: SocketIOClientStatic) {
+            this.socket = payload
+        },
+        setShowDaoGou(payload: boolean) {
+            this.showDaoGou = payload
+        },
+
+        setUserId(payload: string) {
+            this.userId = payload
+        },
+
+        setRoomId(payload: string) {
+            this.roomId = payload
+        },
+        setRole(payload: string) {
+            this.role = payload
+        },
+
+        setDeviceList(payload: DeviceListParams) {
+            this.cameraList = payload.cameraItems
+            this.microphoneList = payload.microphoneItems
+        },
+
+        setVideoDeviceId(payload: string) {
+            this.videoDeviceId = payload
+        },
+
+        setAudioDeviceId(payload: string) {
+            this.audioDeviceId = payload
+        },
+
+        setIsJoined(payload: boolean) {
+            this.isJoined = payload
+        },
+        setIsPublished(payload: boolean) {
+            this.isPublished = payload
+        },
+    }
 
 })

+ 0 - 0
src/utils/rtc_socket.ts


+ 40 - 0
types/io.d.ts

@@ -0,0 +1,40 @@
+declare var io: SocketIOClientStatic;
+
+declare module 'socket.io-client' {
+    export = io;
+}
+
+interface SocketIOClientStatic {
+    (host: string, details?: any): SocketIOClient.Socket;
+    (details?: any): SocketIOClient.Socket;
+    connect(host: string, details?: any): SocketIOClient.Socket;
+    connect(details?: any): SocketIOClient.Socket;
+    protocol: number;
+    Socket: { new (...args: any[]): SocketIOClient.Socket };
+    Manager: SocketIOClient.ManagerStatic;
+}
+
+declare module SocketIOClient {
+    interface Socket {
+        on(event: string, fn: Function): Socket;
+        once(event: string, fn: Function): Socket;
+        off(event?: string, fn?: Function): Socket;
+        emit(event: string, ...args: any[]): Socket;
+        listeners(event: string): Function[];
+        hasListeners(event: string): boolean;
+        connected: boolean;
+    }
+
+    interface ManagerStatic {
+        (url: string, opts: any): SocketIOClient.Manager;
+        new (url: string, opts: any): SocketIOClient.Manager;
+    }
+
+    interface Manager {
+        reconnection(v: boolean): Manager;
+        reconnectionAttempts(v: boolean): Manager;
+        reconnectionDelay(v: boolean): Manager;
+        reconnectionDelayMax(v: boolean): Manager;
+        timeout(v: boolean): Manager;
+    }
+}

+ 2 - 0
vite.config.ts

@@ -2,6 +2,7 @@ import { defineConfig, loadEnv } from 'vite'
 import vue from '@vitejs/plugin-vue'
 import VitePluginHtmlEnv from 'vite-plugin-html-env'
 import { resolve } from 'path'
+import WindiCSS from "vite-plugin-windicss";  
 import consola from 'consola'
 
 function pathResolve(dir: string) {
@@ -12,6 +13,7 @@ function pathResolve(dir: string) {
 export default ({ mode }) => defineConfig({
   plugins: [
     vue(),
+    WindiCSS(),
     VitePluginHtmlEnv({
       prefix: '<%=',
       suffix: '%>',

+ 73 - 0
windi.config.ts

@@ -0,0 +1,73 @@
+import { defineConfig } from 'vite-plugin-windicss';
+
+export default defineConfig({
+  darkMode: 'class',
+  plugins: [createEnterPlugin()],
+  theme: {
+    extend: {
+      zIndex: {
+        '-1': '-1',
+      },
+      colors: {
+        // primary: primaryColor,
+      },
+      screens: {
+        sm: '576px',
+        md: '768px',
+        lg: '992px',
+        xl: '1200px',
+        '2xl': '1600px',
+      },
+    },
+  },
+});
+
+/**
+ * Used for animation when the element is displayed
+ * @param maxOutput The larger the maxOutput output, the larger the generated css volume
+ */
+function createEnterPlugin(maxOutput = 7) {
+  const createCss = (index: number, d = 'x') => {
+    const upd = d.toUpperCase();
+    return {
+      [`*> .enter-${d}:nth-child(${index})`]: {
+        transform: `translate${upd}(50px)`,
+      },
+      [`*> .-enter-${d}:nth-child(${index})`]: {
+        transform: `translate${upd}(-50px)`,
+      },
+      [`* > .enter-${d}:nth-child(${index}),* > .-enter-${d}:nth-child(${index})`]: {
+        'z-index': `${10 - index}`,
+        opacity: '0',
+        animation: `enter-${d}-animation 0.4s ease-in-out 0.3s`,
+        'animation-fill-mode': 'forwards',
+        'animation-delay': `${(index * 1) / 10}s`,
+      },
+    };
+  };
+  const handler = ({ addBase }) => {
+    const addRawCss = {};
+    for (let index = 1; index < maxOutput; index++) {
+      Object.assign(addRawCss, {
+        ...createCss(index, 'x'),
+        ...createCss(index, 'y'),
+      });
+    }
+    addBase({
+      ...addRawCss,
+      [`@keyframes enter-x-animation`]: {
+        to: {
+          opacity: '1',
+          transform: 'translateX(0)',
+        },
+      },
+      [`@keyframes enter-y-animation`]: {
+        to: {
+          opacity: '1',
+          transform: 'translateY(0)',
+        },
+      },
+    });
+  };
+  return { handler };
+}