Grid.vue 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432
  1. <template>
  2. <div class="pb_content g_body">
  3. <div>
  4. <el-image class="coin coin1" :src="require('../../assets/grid/coin1.png')" fit="cover"></el-image>
  5. <el-image class="coin coin2" :src="require('../../assets/grid/coin2.png')" fit="cover"></el-image>
  6. <el-image class="coin coin3" :src="require('../../assets/grid/coin3.png')" fit="cover"></el-image>
  7. <el-image class="coin coin4" :src="require('../../assets/grid/coin4.png')" fit="cover"></el-image>
  8. </div>
  9. <div class="grid_member">
  10. <!-- <div class="member_imgbox">
  11. <el-image
  12. v-for="item in 4"
  13. :key="item"
  14. class="member_img"
  15. :src="require('../../assets/grid/portal.png')"
  16. fit="cover"
  17. ></el-image>
  18. </div>-->
  19. <el-button type="text" @click="dialogVisible2 = true">邀请成员</el-button>
  20. <!-- <el-button type="text">成员</el-button> -->
  21. <el-button type="text" v-if="RoomInfo.userid == userid" @click="dismiss">解散房间</el-button>
  22. </div>
  23. <draggable
  24. element="div"
  25. v-model="data"
  26. class="g_body"
  27. @change="handleDraggableFormItemChange"
  28. @end="dragEnd"
  29. :move="checkMove"
  30. >
  31. <div
  32. v-for="(item,index) in data"
  33. :key="index"
  34. class="g_box"
  35. @mouseover="pIndex = index"
  36. @mouseleave="pIndex = ''"
  37. @dragstart="handleDragStart($event, index)"
  38. @dragover.prevent="handleDragOver($event, index)"
  39. @dragenter="handleDragEnter($event, index)"
  40. @dragend="handleDragEnd($event, index)"
  41. >
  42. <div
  43. :class="{'left-popover':index<3,'right-popover':index==3,'top-popover':index>3,'visibleO':pIndex === index && item && (item.video || item.photo)}"
  44. >
  45. <div class="pChild" @click="check(index)">
  46. <el-image :src="require('../../assets/grid/upload.png')" fit="cover"></el-image>
  47. <span>修改</span>
  48. </div>
  49. <div class="pChild" @click="deleteGrid(index)">
  50. <el-image :src="require('../../assets/grid/deleteT.png')" fit="cover"></el-image>
  51. <span>删除</span>
  52. </div>
  53. <div class="pChild" @click="check(index,2)">
  54. <el-image :src="require('../../assets/grid/edit.png')" fit="cover"></el-image>
  55. <span>添加备注</span>
  56. </div>
  57. </div>
  58. <div
  59. v-if="item && item.remarks"
  60. :class="{'remark-right-popover':index>11 && index!=15,'remark-left-popover':index==15,'remark-bottom-popover':index<12,'visibleO':pIndex === index && item && item.remarks}"
  61. >
  62. <div class="Rbox" v-for="(x,y) in item.remarks" :key="y">
  63. <div v-if="x.remarks!=''" style="display:flex">
  64. <el-image class="Rportal" :src="require('../../assets/grid/portal.png')" fit="cover"></el-image>
  65. <div class="RContent">
  66. <div>{{x.username}}</div>
  67. <div>{{x.remarks}}</div>
  68. </div>
  69. </div>
  70. <div v-else-if="x.remarks==''&& y==0">{{x.username}}暂无备注</div>
  71. </div>
  72. </div>
  73. <el-image
  74. v-if="item && item.photo"
  75. v-viewer
  76. class="photo_img"
  77. :src="item.photo"
  78. fit="cover"
  79. ></el-image>
  80. <video-player
  81. v-else-if="item && item.video"
  82. class="video-player vjs-custom-skin"
  83. ref="videoPlayer"
  84. :playsinline="true"
  85. :options="item.video"
  86. style="width: 85%;"
  87. ></video-player>
  88. <el-image
  89. v-else
  90. class="add_img"
  91. :src="require('../../assets/grid/add.png')"
  92. fit="cover"
  93. @click="check(index,3)"
  94. ></el-image>
  95. </div>
  96. </draggable>
  97. <el-dialog
  98. title="上传文件"
  99. :visible.sync="dialogVisible"
  100. :append-to-body="true"
  101. width="800px"
  102. :before-close="handleClose"
  103. class="look_notice"
  104. >
  105. <div slot="title" class="header-title">
  106. <div class="title_add_student">上传文件</div>
  107. </div>
  108. <div>
  109. <div class="upload_box" v-show="!file.userid || file.userid == userid">
  110. <el-image class="list_img" :src="require('../../assets/grid/list.png')" fit="cover"></el-image>
  111. <div class="upload_content">
  112. <div
  113. @click="addEvent($event)"
  114. @mouseover="file.photo ? deleteVisible1 = true:''"
  115. @mouseleave="file.photo ? deleteVisible1 = false:''"
  116. >
  117. <el-image
  118. class="delete_img"
  119. :src="require('../../assets/grid/delete.png')"
  120. fit="cover"
  121. v-if="deleteVisible1"
  122. @click.stop="deleteFile(1)"
  123. ></el-image>
  124. <el-image
  125. class="upload_img"
  126. :src="file.photo ? file.photo : require('../../assets/grid/image.png')"
  127. fit="cover"
  128. ></el-image>
  129. <input
  130. type="file"
  131. accept="image/*"
  132. style="display: none"
  133. ref="pathClear1"
  134. @change="beforeUpload($event, 1)"
  135. />
  136. </div>
  137. <div
  138. style="margin-left: 20px;"
  139. @click="addEvent($event)"
  140. @mouseover="file.video ? deleteVisible2 = true:''"
  141. @mouseleave="file.video ? deleteVisible2 = false:''"
  142. >
  143. <el-image
  144. class="delete_img"
  145. :src="require('../../assets/grid/delete.png')"
  146. fit="cover"
  147. v-if="deleteVisible2"
  148. @click.stop="deleteFile(2)"
  149. ></el-image>
  150. <el-image
  151. class="upload_img"
  152. :src="file.video ? require('../../assets/grid/videoH.png') : require('../../assets/grid/video.png')"
  153. fit="cover"
  154. ></el-image>
  155. <input
  156. type="file"
  157. accept="video/mp4, video/quicktime, video/x-msvideo"
  158. style="display: none"
  159. ref="pathClear2"
  160. @change="beforeUpload($event, 2)"
  161. />
  162. </div>
  163. </div>
  164. </div>
  165. <div class="textarea_box">
  166. <div class="textarea_title">添加描述</div>
  167. <el-input
  168. type="textarea"
  169. v-model="remarks"
  170. placeholder="请输入描述..."
  171. class="textarea_content"
  172. :rows="5"
  173. resize="none"
  174. ></el-input>
  175. </div>
  176. </div>
  177. <span slot="footer" class="dialog-footer">
  178. <el-button class="close" @click="addGrid()" type="primary">确定</el-button>
  179. </span>
  180. </el-dialog>
  181. <el-dialog
  182. title="邀请成员"
  183. :visible.sync="dialogVisible2"
  184. :append-to-body="true"
  185. width="400px"
  186. :before-close="handleClose"
  187. class="look_notice invite_dialog"
  188. >
  189. <div slot="title" class="header-title">
  190. <div class="title_add_student">邀请成员</div>
  191. </div>
  192. <div>
  193. <div class="invite_box">
  194. <div class="invite_title" ref="inviteT">{{userinfo ? this.userinfo.name: "用户"}}邀请您参加思维网格</div>
  195. <div class="line"></div>
  196. <div class="invite_link">
  197. <div ref="invite1">复制链接加入房间:</div>
  198. <div ref="invite2">https://baidu.com</div>
  199. </div>
  200. <div class="invite_num" ref="invite3">
  201. 房间号:
  202. <span>{{RoomInfo.num}}</span>
  203. </div>
  204. <div class="invite_num" ref="invite4">复制房间号信息,打开思维网格输入即可加入。</div>
  205. </div>
  206. </div>
  207. <span slot="footer" class="dialog-footer">
  208. <el-button
  209. class="close tag-read"
  210. @click="copy"
  211. type="primary"
  212. :data-clipboard-text="copyText"
  213. >一键复制信息</el-button>
  214. </span>
  215. </el-dialog>
  216. <el-dialog
  217. title="创建/加入房间"
  218. :visible.sync="dialogVisible3"
  219. :append-to-body="true"
  220. width="400px"
  221. :before-close="handleClose2"
  222. class="look_notice invite_dialog room_dialog"
  223. >
  224. <div slot="title" class="header-title">
  225. <div class="title_add_student">创建/加入房间</div>
  226. </div>
  227. <div class="addRoom_box">
  228. <div>
  229. <el-input v-model="goNum" placeholder="请输入要加入的房间号"></el-input>
  230. <div class="room_b">备注:输入房间号点击加入房间或点击创建房间直接创建房间</div>
  231. <div class="room_btn">
  232. <el-button class="roomBtn" type="primary" @click="goRoom(goNum)">加入房间</el-button>
  233. <el-button class="roomBtn" type="primary" @click="checkNum">创建房间</el-button>
  234. </div>
  235. </div>
  236. </div>
  237. </el-dialog>
  238. <div v-if="proVisible" class="mask">
  239. <div class="progressBox">
  240. <div class="lbox">
  241. <img :src="require('../../assets/loading.gif')" />上传中,请稍后
  242. </div>
  243. <el-progress
  244. :text-inside="true"
  245. :stroke-width="20"
  246. :percentage="progress"
  247. style="width:80%"
  248. ></el-progress>
  249. </div>
  250. </div>
  251. </div>
  252. </template>
  253. <script>
  254. import Clipboard from "clipboard";
  255. import draggable from "vuedraggable";
  256. export default {
  257. components: {
  258. //调用组件
  259. draggable,
  260. },
  261. data() {
  262. return {
  263. timer: null,
  264. userinfo: [],
  265. RoomInfo: [],
  266. copyText: "",
  267. userid: this.$route.query.userid,
  268. data: [],
  269. dialogVisible: false,
  270. dialogVisible2: false,
  271. dialogVisible3: true,
  272. deleteVisible1: false,
  273. deleteVisible2: false,
  274. dialogImgVisible: false,
  275. dialogImageUrl: "",
  276. remarks: "",
  277. goNum: "",
  278. numNum: "",
  279. file: {},
  280. gIndex: "",
  281. pIndex: "",
  282. proVisible: false,
  283. progress: 0,
  284. playerOptions: {
  285. playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
  286. autoplay: false, //如果true,浏览器准备好时开始回放。
  287. muted: false, // 默认情况下将会消除任何音频。
  288. loop: false, // 导致视频一结束就重新开始。
  289. preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
  290. language: "zh-CN",
  291. aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
  292. fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
  293. sources: [
  294. {
  295. type: "video/mp4", //这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目 || "video/ogg"|| "video/webm"
  296. src: "", //url地址require("../../assets/media/aaa.mp4")
  297. },
  298. ],
  299. // poster: require("../../assets/tu31.png"), //你的封面地址
  300. // poster: dataRes.imgUrl, //你的封面地址
  301. notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
  302. controlBar: {
  303. timeDivider: true, //当前时间和持续时间的分隔符
  304. durationDisplay: true, //显示持续时间
  305. remainingTimeDisplay: false, //是否显示剩余时间功能
  306. fullscreenToggle: true, //全屏按钮
  307. },
  308. },
  309. playerO: {},
  310. dragging: null,
  311. draggingE: null,
  312. };
  313. },
  314. methods: {
  315. handleDragStart(e, items) {
  316. this.dragging = items; //开始拖动时,暂时保存当前拖动的数据。
  317. if (!this.data[items]) {
  318. return;
  319. }
  320. },
  321. handleDragEnd(e, items) {
  322. if (!this.data[this.dragging]) {
  323. return;
  324. }
  325. e.dataTransfer.effectAllowed = "move"; //为需要移动的元素设置dragstart事件
  326. if (this.draggingE == this.dragging) return;
  327. var newItems = [...JSON.parse(JSON.stringify(this.data))]; //拷贝一份数据进行交换操作。
  328. var src = newItems[this.dragging]; //获取数组下标
  329. var dst = newItems[this.draggingE];
  330. // newItems[this.dragging] = dst;
  331. // newItems[this.draggingE] = src;
  332. // // newItems2.splice(dst, 0, ...newItems.splice(src, 1)); //交换位置
  333. // this.data = newItems;
  334. this.data[this.dragging] = dst;
  335. this.data[this.draggingE] = src;
  336. let mindinfo = this.mindInfo(
  337. this.dragging,
  338. "move",
  339. this.data[this.gIndex],
  340. "us.mindNetwork",
  341. this.userinfo ? this.userinfo.userid : this.userid,
  342. this.RoomInfo.id,
  343. this.draggingE
  344. );
  345. this.updateSocket(mindinfo);
  346. this.updateRoomData();
  347. this.dragging = null; //拖动结束后,清除数据
  348. this.draggingE = null;
  349. },
  350. handleDragOver(e) {
  351. e.dataTransfer.dropEffect = "move"; //在dragenter中针对放置目标来设置!
  352. },
  353. handleDragEnter(e, items) {
  354. this.draggingE = items;
  355. e.dataTransfer.effectAllowed = "move"; //为需要移动的元素设置dragstart事件
  356. // if (items == this.dragging) return;
  357. // var newItems = [...JSON.parse(JSON.stringify(this.data))]; //拷贝一份数据进行交换操作。
  358. // var src = this.dragging; //获取数组下标
  359. // var dst = items;
  360. // newItems.splice(dst, 0, ...newItems.splice(src, 1)); //交换位置
  361. // this.data = newItems;
  362. // this.updateRoomData();
  363. },
  364. handleDraggableFormItemChange(val) {
  365. // console.log(val);
  366. // console.log(this.data[val.moved.newIndex]);
  367. // console.log(this.data[val.moved.oldIndex]);
  368. },
  369. dragEnd(val) {
  370. // if (this.data[val.newIndex].userid != this.userinfo.userid) {
  371. // this.$message.error("不是您上传的作品不能拖动哦");
  372. // return;
  373. // }
  374. // this.updateRoomData();
  375. },
  376. checkMove(evt) {
  377. // console.log(evt);
  378. // if (evt.draggedContext.element.userid != this.userinfo.userid) {
  379. // return false;
  380. // } else {
  381. // return true;
  382. // }
  383. return false;
  384. },
  385. copy() {
  386. this.copyText =
  387. this.$refs.inviteT.innerHTML +
  388. "\n" +
  389. this.$refs.invite1.innerHTML +
  390. "\n" +
  391. this.$refs.invite2.innerHTML +
  392. "\n" +
  393. this.$refs.invite3.innerText +
  394. "\n" +
  395. this.$refs.invite4.innerHTML;
  396. var clipboard = new Clipboard(".tag-read");
  397. clipboard.on("success", (e) => {
  398. this.$message.success("复制成功");
  399. console.log("复制成功");
  400. clipboard.destroy(); // 释放内存
  401. });
  402. clipboard.on("error", (e) => {
  403. console.log("不支持复制,该浏览器不支持自动复制");
  404. clipboard.destroy(); // 释放内存
  405. });
  406. },
  407. handleClose(done) {
  408. this.restart();
  409. done();
  410. },
  411. handleClose2(done) {
  412. // done();
  413. },
  414. restart() {
  415. this.file = {};
  416. this.gIndex = "";
  417. this.remarks = "";
  418. if (this.$refs.pathClear1) {
  419. this.$refs.pathClear1.value = "";
  420. this.$refs.pathClear2.value = "";
  421. }
  422. },
  423. deleteGrid(index) {
  424. if (this.data[index].userid != this.userid) {
  425. this.$message.error("你不是上传人无权限删除");
  426. return;
  427. }
  428. this.$confirm("确定删除吗?", "提示", {
  429. confirmButtonText: "确定",
  430. cancelButtonText: "取消",
  431. type: "warning",
  432. })
  433. .then(() => {
  434. this.data[index] = "";
  435. let mindinfo = this.mindInfo(
  436. this.index,
  437. "delete",
  438. this.data[this.index],
  439. "us.mindNetwork",
  440. this.userinfo ? this.userinfo.userid : this.userid,
  441. this.RoomInfo.id,
  442. ""
  443. );
  444. this.updateSocket(mindinfo);
  445. this.updateRoomData();
  446. this.$forceUpdate();
  447. })
  448. .catch(() => {});
  449. },
  450. updateRoomData() {
  451. let params = [
  452. {
  453. data: JSON.stringify(this.data),
  454. idL: this.RoomInfo.id,
  455. },
  456. ];
  457. this.ajax
  458. .post(this.$store.state.api + "updateRoomData", params)
  459. .then((res) => {})
  460. .catch((err) => {});
  461. },
  462. check(index, type) {
  463. this.gIndex = index;
  464. if (this.data[index].userid != this.userid && type != 2 && type != 3) {
  465. this.$message.error("你不是上传人无权限修改");
  466. return;
  467. }
  468. if (this.data[index] && this.data[index].userid == this.userid) {
  469. if (this.data[index].userid != this.userid) {
  470. this.$message.error("你不是上传人无权限修改");
  471. return;
  472. }
  473. this.file = {
  474. photo: this.data[index].photo,
  475. userid: this.data[index].userid,
  476. video:
  477. this.data[index].video &&
  478. this.data[index].video.sources &&
  479. this.data[index].video.sources[0].src,
  480. };
  481. this.remarks = this.data[index].remarks[0].remarks;
  482. } else if (this.data[index] && type == 2) {
  483. this.file = {
  484. userid: this.data[index].userid,
  485. };
  486. for (var i = 0; i < this.data[index].remarks.length; i++) {
  487. if (this.data[index].remarks[i].userid == this.userid) {
  488. this.remarks = this.data[index].remarks[i].remarks;
  489. break;
  490. }
  491. }
  492. this.remarks = this.remarks ? this.remarks : "";
  493. }
  494. this.dialogVisible = true;
  495. },
  496. addEvent(e) {
  497. var el = e.currentTarget;
  498. el.getElementsByTagName("input")[0].click();
  499. },
  500. deleteFile(type) {
  501. if (type == 1) {
  502. this.file.photo = "";
  503. this.deleteVisible1 = false;
  504. this.$refs.pathClear1.value = "";
  505. } else {
  506. this.file.video = "";
  507. this.deleteVisible2 = false;
  508. this.$refs.pathClear2.value = "";
  509. }
  510. this.$forceUpdate();
  511. },
  512. addGrid() {
  513. if (!this.file.userid || this.file.userid == this.userid) {
  514. if (!this.file.video && !this.file.photo) {
  515. this.$message.error("至少上传一个视频或者一张图片");
  516. return;
  517. }
  518. if (!this.data[this.gIndex]) {
  519. this.data[this.gIndex] = {};
  520. }
  521. if (this.file.photo) {
  522. this.data[this.gIndex].photo = this.file.photo;
  523. } else {
  524. // this.playerOptions.sources[0].src = ""
  525. var video = JSON.parse(JSON.stringify(this.playerOptions));
  526. video.sources[0].src = this.file.video;
  527. this.data[this.gIndex].video = video;
  528. }
  529. if (this.data[this.gIndex].remarks) {
  530. this.data[this.gIndex].remarks[0] = {
  531. remarks: this.remarks,
  532. userid: this.userinfo ? this.userinfo.userid : this.userid,
  533. username: this.userinfo ? this.userinfo.name : "用户",
  534. };
  535. } else {
  536. this.data[this.gIndex].remarks = [
  537. {
  538. remarks: this.remarks,
  539. userid: this.userinfo ? this.userinfo.userid : this.userid,
  540. username: this.userinfo ? this.userinfo.name : "用户",
  541. },
  542. ];
  543. }
  544. this.data[this.gIndex].userid = this.userinfo
  545. ? this.userinfo.userid
  546. : this.userid;
  547. } else {
  548. if (!this.remarks) {
  549. this.$message.error("备注不能为空");
  550. return;
  551. }
  552. var a = 0;
  553. for (var i = 0; i < this.data[this.gIndex].remarks.length; i++) {
  554. if (this.data[this.gIndex].remarks[i].userid == this.userid) {
  555. a++;
  556. this.data[this.gIndex].remarks[i] = {
  557. remarks: this.remarks,
  558. userid: this.userinfo ? this.userinfo.userid : this.userid,
  559. username: this.userinfo ? this.userinfo.name : "用户",
  560. };
  561. break;
  562. }
  563. }
  564. if (a < 1) {
  565. this.data[this.gIndex].remarks.push({
  566. remarks: this.remarks,
  567. userid: this.userinfo ? this.userinfo.userid : this.userid,
  568. username: this.userinfo ? this.userinfo.name : "用户",
  569. });
  570. }
  571. }
  572. let mindinfo = this.mindInfo(
  573. this.gIndex,
  574. "update",
  575. this.data[this.gIndex],
  576. "us.mindNetwork",
  577. this.userinfo ? this.userinfo.userid : this.userid,
  578. this.RoomInfo.id,
  579. ""
  580. );
  581. this.updateSocket(mindinfo);
  582. this.updateRoomData();
  583. this.dialogVisible = false;
  584. this.$forceUpdate();
  585. this.restart();
  586. },
  587. beforeUpload(event, type) {
  588. // debugger;
  589. if (this.file.photo && type != 1) {
  590. this.$message.error("只能上传一个视频或者一张图片");
  591. this.$refs.pathClear2.value = "";
  592. return;
  593. } else if (this.file.video && type != 2) {
  594. this.$message.error("只能上传一个视频或者一张图片");
  595. this.$refs.pathClear1.value = "";
  596. return;
  597. }
  598. var file = event.target.files[0];
  599. var credentials = {
  600. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  601. secretAccessKey: "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",
  602. }; //秘钥形式的登录上传
  603. window.AWS.config.update(credentials);
  604. window.AWS.config.region = "cn-northwest-1"; //设置区域
  605. var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
  606. var _this = this;
  607. if (type == 1) {
  608. var mediaFormatList = ["png", "jpg", "jpeg"];
  609. if (
  610. mediaFormatList.indexOf(
  611. file.name
  612. .split(".")
  613. [file.name.split(".").length - 1].toLocaleLowerCase()
  614. ) == "-1"
  615. ) {
  616. _this.$message.error("请上传jpg或者png的图片格式文件");
  617. return;
  618. }
  619. } else {
  620. var mediaFormatList = ["mp4"];
  621. if (
  622. mediaFormatList.indexOf(
  623. file.name
  624. .split(".")
  625. [file.name.split(".").length - 1].toLocaleLowerCase()
  626. ) == "-1"
  627. ) {
  628. _this.$message.error("请上传mp4视频格式文件");
  629. return;
  630. }
  631. }
  632. _this.progress = 0;
  633. _this.proVisible = true;
  634. if (file) {
  635. var params = {
  636. Key:
  637. file.name.split(".")[0] +
  638. new Date().getTime() +
  639. "." +
  640. file.name.split(".")[1],
  641. ContentType: file.type,
  642. Body: file,
  643. "Access-Control-Allow-Credentials": "*",
  644. ACL: "public-read",
  645. }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
  646. var options = {
  647. partSize: 2048 * 1024 * 1024,
  648. queueSize: 2,
  649. leavePartsOnError: true,
  650. };
  651. bucket
  652. .upload(params, options)
  653. .on("httpUploadProgress", function (evt) {
  654. //这里可以写进度条
  655. // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
  656. _this.progress = parseInt((evt.loaded * 80) / evt.total);
  657. })
  658. .send(function (err, data) {
  659. this.progress = 100;
  660. setTimeout(() => {
  661. _this.proVisible = false;
  662. }, 1000);
  663. if (err) {
  664. _this.$message.error("上传失败");
  665. } else {
  666. if (type == 1) {
  667. _this.file.photo = data.Location;
  668. } else {
  669. _this.file.video = data.Location;
  670. }
  671. _this.$forceUpdate();
  672. console.log(data.Location);
  673. }
  674. });
  675. }
  676. },
  677. getUser() {
  678. let params = { uid: this.userid };
  679. this.ajax
  680. .get(this.$store.state.api + "getUser", params)
  681. .then((res) => {
  682. this.userinfo = res.data[0][0];
  683. console.log(res.data[0][0]);
  684. })
  685. .catch((err) => {
  686. console.error(err);
  687. });
  688. },
  689. MathRand() {
  690. var Num = "";
  691. for (var i = 0; i < 6; i++) {
  692. Num += Math.floor(Math.random() * 10);
  693. }
  694. return Num;
  695. },
  696. checkNum() {
  697. this.numNum = this.MathRand();
  698. let params = {
  699. num: this.numNum,
  700. };
  701. this.ajax
  702. .get(this.$store.state.api + "checkRoomNum", params)
  703. .then((res) => {
  704. console.log(res.data[0].length);
  705. if (res.data[0].length) {
  706. this.checkNum();
  707. } else {
  708. this.addRoom();
  709. }
  710. })
  711. .catch((err) => {
  712. console.error(err);
  713. });
  714. },
  715. addRoom() {
  716. let params = [
  717. {
  718. uid: this.userid,
  719. n: this.numNum,
  720. d: JSON.stringify(this.data),
  721. },
  722. ];
  723. this.ajax
  724. .post(this.$store.state.api + "insertRoom", params)
  725. .then((res) => {
  726. this.$message.success("创建成功");
  727. this.selectRoom(this.userid);
  728. })
  729. .catch((err) => {
  730. this.$message.error("创建失败");
  731. console.error(err);
  732. });
  733. },
  734. selectRoom(uid) {
  735. let params = {
  736. uid: uid,
  737. };
  738. this.ajax
  739. .get(this.$store.state.api + "selectRoom", params)
  740. .then((res) => {
  741. if (res.data[0].length) {
  742. // this.RoomInfo = res.data[0][0];
  743. // this.data = JSON.parse(res.data[0][0].data);
  744. // this.dialogVisible3 = false;
  745. // this.dialogVisible2 = true;
  746. this.getMindNetwork(res.data[0][0].id, this.userinfo.userid);
  747. // this.data.splice(0,1)
  748. // this.updateRoomData()
  749. // this.timer = setInterval(() => {
  750. // this.selectRoom2(uid);
  751. // }, 5000);
  752. } else {
  753. // this.$message.error("此房间不存在或已被解散");
  754. }
  755. })
  756. .catch((err) => {
  757. console.error(err);
  758. });
  759. },
  760. goRoom(uid) {
  761. let params = {
  762. uid: uid,
  763. };
  764. this.ajax
  765. .get(this.$store.state.api + "selectRoom", params)
  766. .then((res) => {
  767. if (res.data[0].length) {
  768. this.$message.success("加入成功");
  769. // this.RoomInfo = res.data[0][0];
  770. // this.data = JSON.parse(res.data[0][0].data);
  771. this.dialogVisible3 = false;
  772. this.dialogVisible2 = true;
  773. this.getMindNetwork(res.data[0][0].id, this.userinfo.userid);
  774. // this.timer = setInterval(() => {
  775. // this.selectRoom2(uid);
  776. // }, 5000);
  777. } else {
  778. this.$message.error("此房间不存在或已被解散");
  779. }
  780. })
  781. .catch((err) => {
  782. console.error(err);
  783. });
  784. },
  785. selectRoom2(uid) {
  786. let params = {
  787. uid: uid,
  788. };
  789. this.ajax
  790. .get(this.$store.state.api + "selectRoom", params)
  791. .then((res) => {
  792. this.RoomInfo = res.data[0][0];
  793. this.data = JSON.parse(res.data[0][0].data);
  794. })
  795. .catch((err) => {
  796. console.error(err);
  797. });
  798. },
  799. dismiss() {
  800. this.$confirm("确定解散房间吗?", "提示", {
  801. confirmButtonText: "确定",
  802. cancelButtonText: "取消",
  803. type: "warning",
  804. })
  805. .then(() => {
  806. let params = [
  807. {
  808. id: this.RoomInfo.id,
  809. },
  810. ];
  811. this.ajax
  812. .post(this.$store.state.api + "dismiss", params)
  813. .then((res) => {
  814. this.$message.success("解散成功");
  815. this.$router.go(0);
  816. })
  817. .catch((err) => {
  818. console.error(err);
  819. });
  820. })
  821. .catch(() => {});
  822. },
  823. /*
  824. * mind 消息类
  825. * 参数一 : 第几个网格
  826. * 参数二 : type 操作类型
  827. * 参数三 : content 行内容
  828. * 参数四 : next 下一行
  829. */
  830. mindInfo(id, type, content, navid, userid, roomid, moveIndex) {
  831. var _data = {
  832. sendId: userid, //发送人id
  833. receiveId: roomid, //文件id
  834. type: navid, //消息类型
  835. messageInfo: {
  836. moveIndex1: id, //第几个网格
  837. moveIndex2: moveIndex, //移动到的网格
  838. type: type, //类型
  839. data: content, //内容
  840. docId: roomid, //文档id
  841. // pageId: US.pageId, //当前页面id
  842. },
  843. };
  844. return _data;
  845. },
  846. updateSocket(mindinfo) {
  847. let params = [
  848. {
  849. type: "send",
  850. mindinfo: JSON.stringify(mindinfo),
  851. post: 1,
  852. },
  853. ];
  854. this.ajax
  855. .post(this.$store.state.socket, params)
  856. .then((res) => {
  857. console.log(res);
  858. })
  859. .catch((err) => {
  860. console.error(err);
  861. });
  862. },
  863. getMindNetwork(id, uid) {
  864. let params = [
  865. {
  866. type: "getMindNetwork",
  867. docid: id,
  868. pageid: window.parent.US.pageId,
  869. userid: uid,
  870. post: "1",
  871. },
  872. ];
  873. this.ajax
  874. .post(this.$store.state.socket, params)
  875. .then((res) => {
  876. if (res.data[0].length) {
  877. this.RoomInfo = res.data[0][0];
  878. this.data = JSON.parse(res.data[0][0].data);
  879. this.dialogVisible3 = false;
  880. this.dialogVisible2 = true;
  881. }
  882. console.log(res);
  883. })
  884. .catch((err) => {
  885. console.error(err);
  886. });
  887. },
  888. },
  889. beforeDestroy() {
  890. // clearInterval(this.timer);
  891. window.removeEventListener("message");
  892. },
  893. created() {
  894. document.domain = "cocorobo.cn";
  895. // window.parent.postMessage({ cid: cid, type: "U.MD.O.P.pollingAsyn" }, "*");
  896. for (var i = 0; i < 16; i++) {
  897. this.data.push("");
  898. }
  899. this.getUser();
  900. window.addEventListener("message", function (e) {
  901. // 监听 message 事件
  902. if (e.data.type && e.data.type == "mindNetwork_update") {
  903. this.data[e.data.moveIndex1] = e.data.data;
  904. this.$forceUpdate();
  905. } else if (e.data.close && e.data.type == "mindNetwork_delete") {
  906. this.data.splice(e.data.moveIndex1, 1);
  907. this.$forceUpdate();
  908. } else if (e.data.close && e.data.type == "mindNetwork_move") {
  909. var newItems = [...JSON.parse(JSON.stringify(this.data))]; //拷贝一份数据进行交换操作。
  910. this.data[e.data.moveIndex1] = newItems[e.data.moveIndex2];
  911. this.data[e.data.moveIndex2] = newItems[e.data.moveIndex1];
  912. this.$forceUpdate();
  913. }
  914. });
  915. },
  916. };
  917. </script>
  918. <style scoped>
  919. .g_body {
  920. width: 100%;
  921. height: 100%;
  922. background: #fff;
  923. border-radius: 5px;
  924. display: flex;
  925. align-items: center;
  926. justify-content: center;
  927. flex-wrap: wrap;
  928. position: relative;
  929. min-height: 750px;
  930. }
  931. .coin {
  932. position: absolute;
  933. width: 50px;
  934. z-index: 1;
  935. user-select: none;
  936. }
  937. .coin1 {
  938. top: 10px;
  939. left: 20px;
  940. }
  941. .coin2 {
  942. top: 10px;
  943. right: 20px;
  944. }
  945. .coin3 {
  946. bottom: 10px;
  947. left: 20px;
  948. }
  949. .coin4 {
  950. bottom: 10px;
  951. right: 20px;
  952. }
  953. .g_box {
  954. background: rgb(227 228 232);
  955. width: calc(100% / 4 - 15px);
  956. height: calc(100% / 4 - 15px);
  957. margin: 5px;
  958. border-radius: 5px;
  959. cursor: pointer;
  960. display: flex;
  961. align-items: center;
  962. justify-content: center;
  963. /* overflow: hidden; */
  964. position: relative;
  965. user-select: none;
  966. }
  967. .photo_img {
  968. width: 100%;
  969. height: 100%;
  970. border-radius: 5px;
  971. }
  972. .g_box .add_img {
  973. width: 100px;
  974. display: none;
  975. }
  976. .g_box:hover .add_img {
  977. display: block;
  978. }
  979. .look_notice >>> .el-dialog__header {
  980. padding: 10px 20px;
  981. text-align: center;
  982. background: #32455b;
  983. }
  984. .look_notice >>> .el-dialog__title {
  985. font-size: 14px !important;
  986. color: #fff !important;
  987. }
  988. .look_notice >>> .el-dialog__headerbtn {
  989. font-size: 20px !important;
  990. top: 10px;
  991. }
  992. .look_notice >>> .el-form-item__label {
  993. margin-left: 65px;
  994. }
  995. .look_notice >>> .el-form-item {
  996. display: flex;
  997. }
  998. .look_notice >>> .el-form-item__content {
  999. margin: 0 !important;
  1000. }
  1001. .look_notice >>> .el-dialog__footer {
  1002. text-align: center !important;
  1003. }
  1004. .look_notice >>> .el-dialog {
  1005. min-width: 450px;
  1006. background: #f3f3f3;
  1007. }
  1008. .notice_content {
  1009. width: 100%;
  1010. word-wrap: break-word;
  1011. word-break: break-all;
  1012. overflow: hidden;
  1013. font-size: 18px;
  1014. line-height: 35px;
  1015. text-indent: 35px;
  1016. min-width: 385px;
  1017. }
  1018. .roomBtn {
  1019. background: rgb(112 183 79);
  1020. /* padding: 0 !important; */
  1021. border: none;
  1022. }
  1023. .close {
  1024. width: 150px;
  1025. height: 40px;
  1026. border-radius: 30px;
  1027. line-height: 30px;
  1028. font-size: 14px;
  1029. background: rgb(112 183 79);
  1030. padding: 0 !important;
  1031. border: none;
  1032. }
  1033. .header-title {
  1034. display: flex;
  1035. }
  1036. .logoImg {
  1037. width: 30px;
  1038. }
  1039. .logoImg > img {
  1040. width: 100%;
  1041. height: 100%;
  1042. }
  1043. .title_add_student {
  1044. /* margin: 0 auto; */
  1045. color: #fff;
  1046. }
  1047. .grid_member {
  1048. position: absolute;
  1049. background: #fff;
  1050. right: 70px;
  1051. top: 18px;
  1052. /* min-width: 320px; */
  1053. height: 50px;
  1054. border-radius: 5px;
  1055. padding: 0 10px;
  1056. display: flex;
  1057. align-items: center;
  1058. z-index: 1;
  1059. user-select: none;
  1060. }
  1061. .member_imgbox {
  1062. display: flex;
  1063. align-items: center;
  1064. margin: 0 10px;
  1065. width: 185px;
  1066. }
  1067. .member_img {
  1068. height: 40px;
  1069. width: 40px;
  1070. border-radius: 50px;
  1071. overflow: hidden;
  1072. display: block;
  1073. background: aliceblue;
  1074. }
  1075. .member_img + .member_img {
  1076. margin-left: 8px;
  1077. }
  1078. .upload_box {
  1079. border-radius: 5px;
  1080. background: #fff;
  1081. position: relative;
  1082. }
  1083. .upload_box .list_img {
  1084. position: absolute;
  1085. top: 10px;
  1086. left: 10px;
  1087. }
  1088. .upload_box .upload_content {
  1089. display: flex;
  1090. align-items: center;
  1091. justify-content: center;
  1092. padding: 50px 0 20px;
  1093. }
  1094. .upload_box .upload_content div {
  1095. display: flex;
  1096. align-items: center;
  1097. justify-content: center;
  1098. cursor: pointer;
  1099. position: relative;
  1100. }
  1101. .delete_img {
  1102. position: absolute !important;
  1103. width: 25px;
  1104. transform: translate(50%, -50%);
  1105. top: 0;
  1106. z-index: 1;
  1107. right: 0;
  1108. }
  1109. .upload_img {
  1110. width: 306px;
  1111. height: 206px;
  1112. }
  1113. .textarea_box {
  1114. background: #fff;
  1115. margin-top: 20px;
  1116. display: flex;
  1117. flex-direction: column;
  1118. align-items: center;
  1119. padding: 20px 0;
  1120. }
  1121. .textarea_title {
  1122. width: 95%;
  1123. margin: 0 auto;
  1124. font-size: 16px;
  1125. }
  1126. .textarea_content {
  1127. width: 95%;
  1128. margin: 10px auto 0;
  1129. border-radius: 10px;
  1130. }
  1131. .textarea_content >>> .el-textarea__inner {
  1132. background: rgb(243, 243, 243);
  1133. border: none;
  1134. }
  1135. .invite_dialog >>> .el-dialog__body {
  1136. padding: 15px 20px;
  1137. }
  1138. .room_dialog >>> .el-dialog {
  1139. margin-top: 50vh !important;
  1140. transform: translateY(-50%);
  1141. min-width: unset;
  1142. }
  1143. .invite_box {
  1144. font-size: 16px;
  1145. background: #fff;
  1146. border-radius: 5px;
  1147. padding: 30px 0 150px;
  1148. }
  1149. .invite_title {
  1150. width: 90%;
  1151. margin: 0 auto 20px;
  1152. }
  1153. .line {
  1154. width: 95%;
  1155. border-top: 1px solid rgb(230, 230, 230);
  1156. margin: 0 auto;
  1157. }
  1158. .invite_link {
  1159. width: 90%;
  1160. margin: 20px auto 30px;
  1161. }
  1162. .invite_link div + div {
  1163. margin-top: 15px;
  1164. }
  1165. .invite_num {
  1166. width: 90%;
  1167. margin: 0 auto 50px;
  1168. }
  1169. .invite_num span {
  1170. color: rgb(112 183 79);
  1171. font-size: 28px;
  1172. }
  1173. .addRoom_box {
  1174. background: #fff;
  1175. padding: 30px 20px;
  1176. border-radius: 5px;
  1177. }
  1178. .room_b {
  1179. margin: 5px 0 30px;
  1180. /* width:300px; */
  1181. }
  1182. .room_btn {
  1183. display: flex;
  1184. justify-content: space-around;
  1185. }
  1186. .mask {
  1187. background-color: rgba(0, 0, 0, 0);
  1188. position: fixed;
  1189. top: 0;
  1190. left: 0;
  1191. width: 100%;
  1192. height: 100%;
  1193. z-index: 20000;
  1194. display: flex;
  1195. align-items: center;
  1196. justify-content: center;
  1197. }
  1198. .progressBox {
  1199. width: 500px;
  1200. height: 180px;
  1201. background: #fff;
  1202. border-radius: 10px;
  1203. box-shadow: 0 0 6px 1px #bfbfbf;
  1204. display: flex;
  1205. align-items: center;
  1206. justify-content: center;
  1207. flex-direction: column;
  1208. }
  1209. .progressBox .lbox {
  1210. height: 100px;
  1211. font-size: 19px;
  1212. display: flex;
  1213. align-items: center;
  1214. }
  1215. .progressBox .lbox img {
  1216. width: 40px;
  1217. margin-right: 20px;
  1218. }
  1219. .progressBox >>> .el-progress-bar__outer {
  1220. background-color: #d1dfff !important;
  1221. }
  1222. .top-popover {
  1223. position: absolute;
  1224. top: -50px;
  1225. left: 0;
  1226. background: #fff;
  1227. display: flex;
  1228. height: 45px;
  1229. align-items: center;
  1230. padding: 0px 10px 0 20px;
  1231. border-radius: 5px;
  1232. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1233. z-index: 10;
  1234. transition: 0.5s all;
  1235. opacity: 0;
  1236. visibility: hidden;
  1237. }
  1238. .top-popover .pChild {
  1239. display: flex;
  1240. align-items: center;
  1241. }
  1242. .top-popover .pChild + .pChild {
  1243. margin-left: 10px;
  1244. }
  1245. .left-popover {
  1246. position: absolute;
  1247. top: 0px;
  1248. right: -65px;
  1249. background: #fff;
  1250. display: flex;
  1251. width: 45px;
  1252. align-items: center;
  1253. padding: 10px 5px 20px;
  1254. border-radius: 5px;
  1255. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1256. z-index: 10;
  1257. flex-direction: column;
  1258. justify-content: center;
  1259. transition: 0.5s all;
  1260. opacity: 0;
  1261. visibility: hidden;
  1262. }
  1263. .left-popover .pChild {
  1264. display: flex;
  1265. align-items: center;
  1266. flex-direction: column;
  1267. }
  1268. .left-popover .pChild span {
  1269. display: flex;
  1270. align-items: center;
  1271. flex-direction: column;
  1272. text-align: center;
  1273. }
  1274. .left-popover .pChild + .pChild {
  1275. margin-top: 10px;
  1276. }
  1277. .right-popover {
  1278. position: absolute;
  1279. top: 0px;
  1280. left: -65px;
  1281. background: #fff;
  1282. display: flex;
  1283. width: 45px;
  1284. align-items: center;
  1285. padding: 10px 5px 20px;
  1286. border-radius: 5px;
  1287. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1288. z-index: 10;
  1289. flex-direction: column;
  1290. justify-content: center;
  1291. transition: 0.5s all;
  1292. opacity: 0;
  1293. visibility: hidden;
  1294. }
  1295. .right-popover .pChild {
  1296. display: flex;
  1297. align-items: center;
  1298. flex-direction: column;
  1299. }
  1300. .right-popover .pChild span {
  1301. display: flex;
  1302. align-items: center;
  1303. flex-direction: column;
  1304. text-align: center;
  1305. }
  1306. .right-popover .pChild + .pChild {
  1307. margin-top: 10px;
  1308. }
  1309. .visibleO {
  1310. opacity: 1 !important;
  1311. visibility: visible !important;
  1312. }
  1313. .remark-bottom-popover {
  1314. position: absolute;
  1315. bottom: 0px;
  1316. left: 0;
  1317. background: #fff;
  1318. max-height: 150px;
  1319. width: 100%;
  1320. padding: 10px 20px;
  1321. border-radius: 5px;
  1322. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1323. z-index: 10;
  1324. transition: 0.5s all;
  1325. box-sizing: border-box;
  1326. transform: translateY(calc(100% + 5px));
  1327. overflow: auto;
  1328. opacity: 0;
  1329. visibility: hidden;
  1330. }
  1331. .Rbox {
  1332. display: flex;
  1333. word-break: break-all;
  1334. }
  1335. .Rbox + .Rbox {
  1336. border-top: 1px solid rgb(233, 233, 233);
  1337. margin-top: 10px;
  1338. padding-top: 10px;
  1339. }
  1340. .Rportal {
  1341. height: 45px;
  1342. min-width: 45px;
  1343. border-radius: 50px;
  1344. overflow: hidden;
  1345. display: block;
  1346. background: aliceblue;
  1347. user-select: none;
  1348. }
  1349. .RContent {
  1350. margin-left: 10px;
  1351. }
  1352. .RContent div:nth-child(1) {
  1353. user-select: none;
  1354. color: rgb(80, 80, 80);
  1355. margin-bottom: 5px;
  1356. font-size: 14px;
  1357. }
  1358. .RContent div:nth-child(2) {
  1359. font-family: "微软雅黑";
  1360. font-size: 15px;
  1361. }
  1362. .remark-right-popover {
  1363. position: absolute;
  1364. top: 0;
  1365. right: 0;
  1366. background: #fff;
  1367. max-height: 100%;
  1368. width: 300px;
  1369. padding: 10px 20px;
  1370. border-radius: 5px;
  1371. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1372. z-index: 10;
  1373. transition: 0.5s all;
  1374. box-sizing: border-box;
  1375. transform: translateX(calc(100% + 5px));
  1376. overflow: auto;
  1377. opacity: 0;
  1378. visibility: hidden;
  1379. }
  1380. .remark-left-popover {
  1381. position: absolute;
  1382. top: 0;
  1383. left: 0;
  1384. background: #fff;
  1385. max-height: 100%;
  1386. width: 300px;
  1387. padding: 10px 20px;
  1388. border-radius: 5px;
  1389. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1390. z-index: 10;
  1391. transition: 0.5s all;
  1392. box-sizing: border-box;
  1393. transform: translateX(calc(-100% - 5px));
  1394. overflow: auto;
  1395. opacity: 0;
  1396. visibility: hidden;
  1397. }
  1398. </style>