Grid.vue 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  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.mindInfo2(
  337. this.dragging,
  338. "move",
  339. dst,
  340. "us.mindNetwork",
  341. this.userinfo ? this.userinfo.userid : this.userid,
  342. this.RoomInfo.id,
  343. this.draggingE,
  344. src
  345. );
  346. this.updateSocket(mindinfo);
  347. this.updateRoomData();
  348. this.dragging = null; //拖动结束后,清除数据
  349. this.draggingE = null;
  350. },
  351. handleDragOver(e) {
  352. e.dataTransfer.dropEffect = "move"; //在dragenter中针对放置目标来设置!
  353. },
  354. handleDragEnter(e, items) {
  355. this.draggingE = items;
  356. e.dataTransfer.effectAllowed = "move"; //为需要移动的元素设置dragstart事件
  357. // if (items == this.dragging) return;
  358. // var newItems = [...JSON.parse(JSON.stringify(this.data))]; //拷贝一份数据进行交换操作。
  359. // var src = this.dragging; //获取数组下标
  360. // var dst = items;
  361. // newItems.splice(dst, 0, ...newItems.splice(src, 1)); //交换位置
  362. // this.data = newItems;
  363. // this.updateRoomData();
  364. },
  365. handleDraggableFormItemChange(val) {
  366. // console.log(val);
  367. // console.log(this.data[val.moved.newIndex]);
  368. // console.log(this.data[val.moved.oldIndex]);
  369. },
  370. dragEnd(val) {
  371. // if (this.data[val.newIndex].userid != this.userinfo.userid) {
  372. // this.$message.error("不是您上传的作品不能拖动哦");
  373. // return;
  374. // }
  375. // this.updateRoomData();
  376. },
  377. checkMove(evt) {
  378. // console.log(evt);
  379. // if (evt.draggedContext.element.userid != this.userinfo.userid) {
  380. // return false;
  381. // } else {
  382. // return true;
  383. // }
  384. return false;
  385. },
  386. copy() {
  387. this.copyText =
  388. this.$refs.inviteT.innerHTML +
  389. "\n" +
  390. this.$refs.invite1.innerHTML +
  391. "\n" +
  392. this.$refs.invite2.innerHTML +
  393. "\n" +
  394. this.$refs.invite3.innerText +
  395. "\n" +
  396. this.$refs.invite4.innerHTML;
  397. var clipboard = new Clipboard(".tag-read");
  398. clipboard.on("success", (e) => {
  399. this.$message.success("复制成功");
  400. console.log("复制成功");
  401. clipboard.destroy(); // 释放内存
  402. });
  403. clipboard.on("error", (e) => {
  404. console.log("不支持复制,该浏览器不支持自动复制");
  405. clipboard.destroy(); // 释放内存
  406. });
  407. },
  408. handleClose(done) {
  409. this.restart();
  410. done();
  411. },
  412. handleClose2(done) {
  413. // done();
  414. },
  415. restart() {
  416. this.file = {};
  417. this.gIndex = "";
  418. this.remarks = "";
  419. if (this.$refs.pathClear1) {
  420. this.$refs.pathClear1.value = "";
  421. this.$refs.pathClear2.value = "";
  422. }
  423. },
  424. deleteGrid(index) {
  425. if (this.data[index].userid != this.userid) {
  426. this.$message.error("你不是上传人无权限删除");
  427. return;
  428. }
  429. this.$confirm("确定删除吗?", "提示", {
  430. confirmButtonText: "确定",
  431. cancelButtonText: "取消",
  432. type: "warning",
  433. })
  434. .then(() => {
  435. this.data[index] = "";
  436. let mindinfo = this.mindInfo(
  437. index,
  438. "delete",
  439. this.data[index],
  440. "us.mindNetwork",
  441. this.userinfo ? this.userinfo.userid : this.userid,
  442. this.RoomInfo.id,
  443. ""
  444. );
  445. this.updateSocket(mindinfo);
  446. this.updateRoomData();
  447. this.$forceUpdate();
  448. })
  449. .catch(() => {});
  450. },
  451. updateRoomData() {
  452. let params = [
  453. {
  454. data: JSON.stringify(this.data),
  455. idL: this.RoomInfo.id,
  456. },
  457. ];
  458. this.ajax
  459. .post(this.$store.state.api + "updateRoomData", params)
  460. .then((res) => {})
  461. .catch((err) => {});
  462. },
  463. check(index, type) {
  464. this.gIndex = index;
  465. if (this.data[index].userid != this.userid && type != 2 && type != 3) {
  466. this.$message.error("你不是上传人无权限修改");
  467. return;
  468. }
  469. if (this.data[index] && this.data[index].userid == this.userid) {
  470. if (this.data[index].userid != this.userid) {
  471. this.$message.error("你不是上传人无权限修改");
  472. return;
  473. }
  474. this.file = {
  475. photo: this.data[index].photo,
  476. userid: this.data[index].userid,
  477. video:
  478. this.data[index].video &&
  479. this.data[index].video.sources &&
  480. this.data[index].video.sources[0].src,
  481. };
  482. this.remarks = this.data[index].remarks[0].remarks;
  483. } else if (this.data[index] && type == 2) {
  484. this.file = {
  485. userid: this.data[index].userid,
  486. };
  487. for (var i = 0; i < this.data[index].remarks.length; i++) {
  488. if (this.data[index].remarks[i].userid == this.userid) {
  489. this.remarks = this.data[index].remarks[i].remarks;
  490. break;
  491. }
  492. }
  493. this.remarks = this.remarks ? this.remarks : "";
  494. }
  495. this.dialogVisible = true;
  496. },
  497. addEvent(e) {
  498. var el = e.currentTarget;
  499. el.getElementsByTagName("input")[0].click();
  500. },
  501. deleteFile(type) {
  502. if (type == 1) {
  503. this.file.photo = "";
  504. this.deleteVisible1 = false;
  505. this.$refs.pathClear1.value = "";
  506. } else {
  507. this.file.video = "";
  508. this.deleteVisible2 = false;
  509. this.$refs.pathClear2.value = "";
  510. }
  511. this.$forceUpdate();
  512. },
  513. addGrid() {
  514. if (!this.file.userid || this.file.userid == this.userid) {
  515. if (!this.file.video && !this.file.photo) {
  516. this.$message.error("至少上传一个视频或者一张图片");
  517. return;
  518. }
  519. if (!this.data[this.gIndex]) {
  520. this.data[this.gIndex] = {};
  521. }
  522. if (this.file.photo) {
  523. this.data[this.gIndex].photo = this.file.photo;
  524. } else {
  525. // this.playerOptions.sources[0].src = ""
  526. var video = JSON.parse(JSON.stringify(this.playerOptions));
  527. video.sources[0].src = this.file.video;
  528. this.data[this.gIndex].video = video;
  529. }
  530. if (this.data[this.gIndex].remarks) {
  531. this.data[this.gIndex].remarks[0] = {
  532. remarks: this.remarks,
  533. userid: this.userinfo ? this.userinfo.userid : this.userid,
  534. username: this.userinfo ? this.userinfo.name : "用户",
  535. };
  536. } else {
  537. this.data[this.gIndex].remarks = [
  538. {
  539. remarks: this.remarks,
  540. userid: this.userinfo ? this.userinfo.userid : this.userid,
  541. username: this.userinfo ? this.userinfo.name : "用户",
  542. },
  543. ];
  544. }
  545. this.data[this.gIndex].userid = this.userinfo
  546. ? this.userinfo.userid
  547. : this.userid;
  548. } else {
  549. if (!this.remarks) {
  550. this.$message.error("备注不能为空");
  551. return;
  552. }
  553. var a = 0;
  554. for (var i = 0; i < this.data[this.gIndex].remarks.length; i++) {
  555. if (this.data[this.gIndex].remarks[i].userid == this.userid) {
  556. a++;
  557. this.data[this.gIndex].remarks[i] = {
  558. remarks: this.remarks,
  559. userid: this.userinfo ? this.userinfo.userid : this.userid,
  560. username: this.userinfo ? this.userinfo.name : "用户",
  561. };
  562. break;
  563. }
  564. }
  565. if (a < 1) {
  566. this.data[this.gIndex].remarks.push({
  567. remarks: this.remarks,
  568. userid: this.userinfo ? this.userinfo.userid : this.userid,
  569. username: this.userinfo ? this.userinfo.name : "用户",
  570. });
  571. }
  572. }
  573. let mindinfo = this.mindInfo(
  574. this.gIndex,
  575. "update",
  576. this.data[this.gIndex],
  577. "us.mindNetwork",
  578. this.userinfo ? this.userinfo.userid : this.userid,
  579. this.RoomInfo.id,
  580. ""
  581. );
  582. this.updateSocket(mindinfo);
  583. this.updateRoomData();
  584. this.dialogVisible = false;
  585. this.$forceUpdate();
  586. this.restart();
  587. },
  588. beforeUpload(event, type) {
  589. // debugger;
  590. if (this.file.photo && type != 1) {
  591. this.$message.error("只能上传一个视频或者一张图片");
  592. this.$refs.pathClear2.value = "";
  593. return;
  594. } else if (this.file.video && type != 2) {
  595. this.$message.error("只能上传一个视频或者一张图片");
  596. this.$refs.pathClear1.value = "";
  597. return;
  598. }
  599. var file = event.target.files[0];
  600. var credentials = {
  601. accessKeyId: "AKIATLPEDU37QV5CHLMH",
  602. secretAccessKey: "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",
  603. }; //秘钥形式的登录上传
  604. window.AWS.config.update(credentials);
  605. window.AWS.config.region = "cn-northwest-1"; //设置区域
  606. var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
  607. var _this = this;
  608. if (type == 1) {
  609. var mediaFormatList = ["png", "jpg", "jpeg"];
  610. if (
  611. mediaFormatList.indexOf(
  612. file.name
  613. .split(".")
  614. [file.name.split(".").length - 1].toLocaleLowerCase()
  615. ) == "-1"
  616. ) {
  617. _this.$message.error("请上传jpg或者png的图片格式文件");
  618. return;
  619. }
  620. } else {
  621. var mediaFormatList = ["mp4"];
  622. if (
  623. mediaFormatList.indexOf(
  624. file.name
  625. .split(".")
  626. [file.name.split(".").length - 1].toLocaleLowerCase()
  627. ) == "-1"
  628. ) {
  629. _this.$message.error("请上传mp4视频格式文件");
  630. return;
  631. }
  632. }
  633. _this.progress = 0;
  634. _this.proVisible = true;
  635. if (file) {
  636. var params = {
  637. Key:
  638. file.name.split(".")[0] +
  639. new Date().getTime() +
  640. "." +
  641. file.name.split(".")[1],
  642. ContentType: file.type,
  643. Body: file,
  644. "Access-Control-Allow-Credentials": "*",
  645. ACL: "public-read",
  646. }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
  647. var options = {
  648. partSize: 2048 * 1024 * 1024,
  649. queueSize: 2,
  650. leavePartsOnError: true,
  651. };
  652. bucket
  653. .upload(params, options)
  654. .on("httpUploadProgress", function (evt) {
  655. //这里可以写进度条
  656. // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
  657. _this.progress = parseInt((evt.loaded * 80) / evt.total);
  658. })
  659. .send(function (err, data) {
  660. this.progress = 100;
  661. setTimeout(() => {
  662. _this.proVisible = false;
  663. }, 1000);
  664. if (err) {
  665. _this.$message.error("上传失败");
  666. } else {
  667. if (type == 1) {
  668. _this.file.photo = data.Location;
  669. } else {
  670. _this.file.video = data.Location;
  671. }
  672. _this.$forceUpdate();
  673. console.log(data.Location);
  674. }
  675. });
  676. }
  677. },
  678. getUser() {
  679. let params = { uid: this.userid };
  680. this.ajax
  681. .get(this.$store.state.api + "getUser", params)
  682. .then((res) => {
  683. this.userinfo = res.data[0][0];
  684. console.log(res.data[0][0]);
  685. })
  686. .catch((err) => {
  687. console.error(err);
  688. });
  689. },
  690. MathRand() {
  691. var Num = "";
  692. for (var i = 0; i < 6; i++) {
  693. Num += Math.floor(Math.random() * 10);
  694. }
  695. return Num;
  696. },
  697. checkNum() {
  698. this.numNum = this.MathRand();
  699. let params = {
  700. num: this.numNum,
  701. };
  702. this.ajax
  703. .get(this.$store.state.api + "checkRoomNum", params)
  704. .then((res) => {
  705. console.log(res.data[0].length);
  706. if (res.data[0].length) {
  707. this.checkNum();
  708. } else {
  709. this.addRoom();
  710. }
  711. })
  712. .catch((err) => {
  713. console.error(err);
  714. });
  715. },
  716. addRoom() {
  717. let params = [
  718. {
  719. uid: this.userid,
  720. n: this.numNum,
  721. d: JSON.stringify(this.data),
  722. },
  723. ];
  724. this.ajax
  725. .post(this.$store.state.api + "insertRoom", params)
  726. .then((res) => {
  727. this.$message.success("创建成功");
  728. this.getRoom(res.data[0][0].fid);
  729. })
  730. .catch((err) => {
  731. this.$message.error("创建失败");
  732. console.error(err);
  733. });
  734. },
  735. getRoom(fid) {
  736. let params = {
  737. fid: fid,
  738. };
  739. this.ajax
  740. .get(this.$store.state.api + "getRoom", params)
  741. .then((res) => {
  742. if (res.data[0].length) {
  743. // this.RoomInfo = res.data[0][0];
  744. // this.data = JSON.parse(res.data[0][0].data);
  745. // this.dialogVisible3 = false;
  746. // this.dialogVisible2 = true;
  747. debugger
  748. this.getMindNetwork(res.data[0][0].id, this.userinfo.userid);
  749. // this.data.splice(0,1)
  750. // this.updateRoomData()
  751. // this.timer = setInterval(() => {
  752. // this.selectRoom2(uid);
  753. // }, 5000);
  754. } else {
  755. // this.$message.error("此房间不存在或已被解散");
  756. }
  757. })
  758. .catch((err) => {
  759. console.error(err);
  760. });
  761. },
  762. selectRoom(uid) {
  763. let params = {
  764. uid: uid,
  765. };
  766. this.ajax
  767. .get(this.$store.state.api + "selectRoom", params)
  768. .then((res) => {
  769. if (res.data[0].length) {
  770. // this.RoomInfo = res.data[0][0];
  771. // this.data = JSON.parse(res.data[0][0].data);
  772. // this.dialogVisible3 = false;
  773. // this.dialogVisible2 = true;
  774. this.getMindNetwork(res.data[0][0].id, this.userinfo.userid);
  775. // this.data.splice(0,1)
  776. // this.updateRoomData()
  777. // this.timer = setInterval(() => {
  778. // this.selectRoom2(uid);
  779. // }, 5000);
  780. } else {
  781. // this.$message.error("此房间不存在或已被解散");
  782. }
  783. })
  784. .catch((err) => {
  785. console.error(err);
  786. });
  787. },
  788. goRoom(uid) {
  789. let params = {
  790. uid: uid,
  791. };
  792. this.ajax
  793. .get(this.$store.state.api + "selectRoom", params)
  794. .then((res) => {
  795. if (res.data[0].length) {
  796. this.$message.success("加入成功");
  797. // this.RoomInfo = res.data[0][0];
  798. // this.data = JSON.parse(res.data[0][0].data);
  799. // this.dialogVisible3 = false;
  800. // this.dialogVisible2 = true;
  801. this.getMindNetwork(res.data[0][0].id, this.userinfo.userid);
  802. // this.timer = setInterval(() => {
  803. // this.selectRoom2(uid);
  804. // }, 5000);
  805. } else {
  806. this.$message.error("此房间不存在或已被解散");
  807. }
  808. })
  809. .catch((err) => {
  810. console.error(err);
  811. });
  812. },
  813. selectRoom2(uid) {
  814. let params = {
  815. uid: uid,
  816. };
  817. this.ajax
  818. .get(this.$store.state.api + "selectRoom", params)
  819. .then((res) => {
  820. this.RoomInfo = res.data[0][0];
  821. this.data = JSON.parse(res.data[0][0].data);
  822. })
  823. .catch((err) => {
  824. console.error(err);
  825. });
  826. },
  827. dismiss() {
  828. this.$confirm("确定解散房间吗?", "提示", {
  829. confirmButtonText: "确定",
  830. cancelButtonText: "取消",
  831. type: "warning",
  832. })
  833. .then(() => {
  834. let params = [
  835. {
  836. id: this.RoomInfo.id,
  837. },
  838. ];
  839. this.ajax
  840. .post(this.$store.state.api + "dismiss", params)
  841. .then((res) => {
  842. this.$message.success("解散成功");
  843. this.$router.go(0);
  844. })
  845. .catch((err) => {
  846. console.error(err);
  847. });
  848. })
  849. .catch(() => {});
  850. },
  851. /*
  852. * mind 消息类
  853. * 参数一 : 第几个网格
  854. * 参数二 : type 操作类型
  855. * 参数三 : content 行内容
  856. * 参数四 : next 下一行
  857. */
  858. // messageInfo: {
  859. // sendId: userid,
  860. // moveIndex1: id, //第几个网格
  861. // moveIndex2: moveIndex, //移动到的网格
  862. // type: type, //类型
  863. // data: content, //内容
  864. // docId: roomid, //文档id
  865. // // pageId: US.pageId, //当前页面id
  866. // },
  867. mindInfo(id, type, content, navid, userid, roomid, moveIndex) {
  868. var _data = {
  869. "us.mindNetwork": [
  870. {
  871. sendId: userid, //发送人id
  872. receiveId: roomid, //文件id
  873. type: navid, //消息类型
  874. messageInfo: {
  875. id: id, //操作ID
  876. type: type, //类型
  877. content: content, //内容
  878. docId: roomid, //文档id
  879. pageId: top.US.pageId, //当前页面id
  880. },
  881. },
  882. ],
  883. };
  884. return _data;
  885. },
  886. mindInfo2(id, type, content, navid, userid, roomid, moveIndex,moveData) {
  887. var _data = {
  888. "us.mindNetwork": [
  889. {
  890. sendId: userid, //发送人id
  891. receiveId: roomid, //文件id
  892. type: navid, //消息类型
  893. messageInfo: {
  894. id: id, //操作ID
  895. type: type, //类型
  896. content: content, //内容
  897. docId: roomid, //文档id
  898. pageId: top.US.pageId, //当前页面id
  899. },
  900. },
  901. {
  902. sendId: userid, //发送人id
  903. receiveId: roomid, //文件id
  904. type: navid, //消息类型
  905. messageInfo: {
  906. id: moveIndex, //操作ID
  907. type: type, //类型
  908. content: moveData, //内容
  909. docId: roomid, //文档id
  910. pageId: top.US.pageId, //当前页面id
  911. },
  912. },
  913. ],
  914. };
  915. return _data;
  916. },
  917. updateSocket(mindinfo) {
  918. let params = [
  919. {
  920. type: "send",
  921. mindinfo: encodeURIComponent(
  922. encodeURIComponent(JSON.stringify(mindinfo))
  923. ),
  924. post: 1,
  925. },
  926. ];
  927. this.ajax
  928. .post(this.$store.state.socket, params)
  929. .then((res) => {
  930. console.log(res);
  931. })
  932. .catch((err) => {
  933. console.error(err);
  934. });
  935. },
  936. getMindNetwork(id, uid) {
  937. let params = [
  938. {
  939. type: "getMindNetwork",
  940. docid: id,
  941. pageid: window.parent.US.pageId,
  942. userid: uid,
  943. post: "1",
  944. },
  945. ];
  946. this.ajax
  947. .post(this.$store.state.socket, params)
  948. .then((res) => {
  949. if (res.data[0].length) {
  950. this.RoomInfo = res.data[0][0];
  951. try {
  952. this.data = JSON.parse(res.data[0][0].data);
  953. } catch (error) {
  954. this.data = res.data[0][0].data;
  955. }
  956. this.dialogVisible3 = false;
  957. this.dialogVisible2 = true;
  958. }
  959. console.log(res);
  960. })
  961. .catch((err) => {
  962. console.error(err);
  963. });
  964. },
  965. },
  966. beforeDestroy() {
  967. // clearInterval(this.timer);
  968. window.removeEventListener("message");
  969. },
  970. created() {
  971. document.domain = "cocorobo.cn";
  972. // window.parent.postMessage({ cid: cid, type: "U.MD.O.P.pollingAsyn" }, "*");
  973. for (var i = 0; i < 16; i++) {
  974. this.data.push("");
  975. }
  976. this.getUser();
  977. let _this = this;
  978. window.addEventListener("message", function (e) {
  979. // 监听 message 事件
  980. if (
  981. e.data.type &&
  982. e.data.type == "mindNetwork_update" &&
  983. e.data.info.docId == _this.RoomInfo.id &&
  984. !(e.data.sendId == _this.userinfo.userid)
  985. ) {
  986. _this.data[e.data.info.id] = e.data.info.content;
  987. } else if (
  988. e.data.type &&
  989. e.data.type == "mindNetwork_delete" &&
  990. e.data.info.docId == _this.RoomInfo.id &&
  991. !(e.data.sendId == _this.userinfo.userid)
  992. ) {
  993. _this.data[e.data.info.id] = "";
  994. } else if (
  995. e.data.type &&
  996. e.data.type == "mindNetwork_move" &&
  997. e.data.info.docId == _this.RoomInfo.id &&
  998. !(e.data.sendId == _this.userinfo.userid)
  999. ) {
  1000. _this.data[e.data.info.id] = e.data.info.content;
  1001. // var newItems = [...JSON.parse(JSON.stringify(_this.data))]; //拷贝一份数据进行交换操作。
  1002. // _this.data[e.data.info.id] = newItems[e.data.info.moveIndex2];
  1003. // _this.data[e.data.info.moveIndex2] = newItems[e.data.info.moveIndex1];
  1004. }
  1005. _this.$forceUpdate();
  1006. });
  1007. },
  1008. };
  1009. </script>
  1010. <style scoped>
  1011. .g_body {
  1012. width: 100%;
  1013. height: 100%;
  1014. background: #fff;
  1015. border-radius: 5px;
  1016. display: flex;
  1017. align-items: center;
  1018. justify-content: center;
  1019. flex-wrap: wrap;
  1020. position: relative;
  1021. min-height: 750px;
  1022. }
  1023. .coin {
  1024. position: absolute;
  1025. width: 50px;
  1026. z-index: 1;
  1027. user-select: none;
  1028. }
  1029. .coin1 {
  1030. top: 10px;
  1031. left: 20px;
  1032. }
  1033. .coin2 {
  1034. top: 10px;
  1035. right: 20px;
  1036. }
  1037. .coin3 {
  1038. bottom: 10px;
  1039. left: 20px;
  1040. }
  1041. .coin4 {
  1042. bottom: 10px;
  1043. right: 20px;
  1044. }
  1045. .g_box {
  1046. background: rgb(227 228 232);
  1047. width: calc(100% / 4 - 15px);
  1048. height: calc(100% / 4 - 15px);
  1049. margin: 5px;
  1050. border-radius: 5px;
  1051. cursor: pointer;
  1052. display: flex;
  1053. align-items: center;
  1054. justify-content: center;
  1055. /* overflow: hidden; */
  1056. position: relative;
  1057. user-select: none;
  1058. }
  1059. .photo_img {
  1060. width: 100%;
  1061. height: 100%;
  1062. border-radius: 5px;
  1063. }
  1064. .g_box .add_img {
  1065. width: 100px;
  1066. display: none;
  1067. }
  1068. .g_box:hover .add_img {
  1069. display: block;
  1070. }
  1071. .look_notice >>> .el-dialog__header {
  1072. padding: 10px 20px;
  1073. text-align: center;
  1074. background: #32455b;
  1075. }
  1076. .look_notice >>> .el-dialog__title {
  1077. font-size: 14px !important;
  1078. color: #fff !important;
  1079. }
  1080. .look_notice >>> .el-dialog__headerbtn {
  1081. font-size: 20px !important;
  1082. top: 10px;
  1083. }
  1084. .look_notice >>> .el-form-item__label {
  1085. margin-left: 65px;
  1086. }
  1087. .look_notice >>> .el-form-item {
  1088. display: flex;
  1089. }
  1090. .look_notice >>> .el-form-item__content {
  1091. margin: 0 !important;
  1092. }
  1093. .look_notice >>> .el-dialog__footer {
  1094. text-align: center !important;
  1095. }
  1096. .look_notice >>> .el-dialog {
  1097. min-width: 450px;
  1098. background: #f3f3f3;
  1099. }
  1100. .notice_content {
  1101. width: 100%;
  1102. word-wrap: break-word;
  1103. word-break: break-all;
  1104. overflow: hidden;
  1105. font-size: 18px;
  1106. line-height: 35px;
  1107. text-indent: 35px;
  1108. min-width: 385px;
  1109. }
  1110. .roomBtn {
  1111. background: rgb(112 183 79);
  1112. /* padding: 0 !important; */
  1113. border: none;
  1114. }
  1115. .close {
  1116. width: 150px;
  1117. height: 40px;
  1118. border-radius: 30px;
  1119. line-height: 30px;
  1120. font-size: 14px;
  1121. background: rgb(112 183 79);
  1122. padding: 0 !important;
  1123. border: none;
  1124. }
  1125. .header-title {
  1126. display: flex;
  1127. }
  1128. .logoImg {
  1129. width: 30px;
  1130. }
  1131. .logoImg > img {
  1132. width: 100%;
  1133. height: 100%;
  1134. }
  1135. .title_add_student {
  1136. /* margin: 0 auto; */
  1137. color: #fff;
  1138. }
  1139. .grid_member {
  1140. position: absolute;
  1141. background: #fff;
  1142. right: 70px;
  1143. top: 18px;
  1144. /* min-width: 320px; */
  1145. height: 50px;
  1146. border-radius: 5px;
  1147. padding: 0 10px;
  1148. display: flex;
  1149. align-items: center;
  1150. z-index: 1;
  1151. user-select: none;
  1152. }
  1153. .member_imgbox {
  1154. display: flex;
  1155. align-items: center;
  1156. margin: 0 10px;
  1157. width: 185px;
  1158. }
  1159. .member_img {
  1160. height: 40px;
  1161. width: 40px;
  1162. border-radius: 50px;
  1163. overflow: hidden;
  1164. display: block;
  1165. background: aliceblue;
  1166. }
  1167. .member_img + .member_img {
  1168. margin-left: 8px;
  1169. }
  1170. .upload_box {
  1171. border-radius: 5px;
  1172. background: #fff;
  1173. position: relative;
  1174. }
  1175. .upload_box .list_img {
  1176. position: absolute;
  1177. top: 10px;
  1178. left: 10px;
  1179. }
  1180. .upload_box .upload_content {
  1181. display: flex;
  1182. align-items: center;
  1183. justify-content: center;
  1184. padding: 50px 0 20px;
  1185. }
  1186. .upload_box .upload_content div {
  1187. display: flex;
  1188. align-items: center;
  1189. justify-content: center;
  1190. cursor: pointer;
  1191. position: relative;
  1192. }
  1193. .delete_img {
  1194. position: absolute !important;
  1195. width: 25px;
  1196. transform: translate(50%, -50%);
  1197. top: 0;
  1198. z-index: 1;
  1199. right: 0;
  1200. }
  1201. .upload_img {
  1202. width: 306px;
  1203. height: 206px;
  1204. }
  1205. .textarea_box {
  1206. background: #fff;
  1207. margin-top: 20px;
  1208. display: flex;
  1209. flex-direction: column;
  1210. align-items: center;
  1211. padding: 20px 0;
  1212. }
  1213. .textarea_title {
  1214. width: 95%;
  1215. margin: 0 auto;
  1216. font-size: 16px;
  1217. }
  1218. .textarea_content {
  1219. width: 95%;
  1220. margin: 10px auto 0;
  1221. border-radius: 10px;
  1222. }
  1223. .textarea_content >>> .el-textarea__inner {
  1224. background: rgb(243, 243, 243);
  1225. border: none;
  1226. }
  1227. .invite_dialog >>> .el-dialog__body {
  1228. padding: 15px 20px;
  1229. }
  1230. .room_dialog >>> .el-dialog {
  1231. margin-top: 50vh !important;
  1232. transform: translateY(-50%);
  1233. min-width: unset;
  1234. }
  1235. .invite_box {
  1236. font-size: 16px;
  1237. background: #fff;
  1238. border-radius: 5px;
  1239. padding: 30px 0 150px;
  1240. }
  1241. .invite_title {
  1242. width: 90%;
  1243. margin: 0 auto 20px;
  1244. }
  1245. .line {
  1246. width: 95%;
  1247. border-top: 1px solid rgb(230, 230, 230);
  1248. margin: 0 auto;
  1249. }
  1250. .invite_link {
  1251. width: 90%;
  1252. margin: 20px auto 30px;
  1253. }
  1254. .invite_link div + div {
  1255. margin-top: 15px;
  1256. }
  1257. .invite_num {
  1258. width: 90%;
  1259. margin: 0 auto 50px;
  1260. }
  1261. .invite_num span {
  1262. color: rgb(112 183 79);
  1263. font-size: 28px;
  1264. }
  1265. .addRoom_box {
  1266. background: #fff;
  1267. padding: 30px 20px;
  1268. border-radius: 5px;
  1269. }
  1270. .room_b {
  1271. margin: 5px 0 30px;
  1272. /* width:300px; */
  1273. }
  1274. .room_btn {
  1275. display: flex;
  1276. justify-content: space-around;
  1277. }
  1278. .mask {
  1279. background-color: rgba(0, 0, 0, 0);
  1280. position: fixed;
  1281. top: 0;
  1282. left: 0;
  1283. width: 100%;
  1284. height: 100%;
  1285. z-index: 20000;
  1286. display: flex;
  1287. align-items: center;
  1288. justify-content: center;
  1289. }
  1290. .progressBox {
  1291. width: 500px;
  1292. height: 180px;
  1293. background: #fff;
  1294. border-radius: 10px;
  1295. box-shadow: 0 0 6px 1px #bfbfbf;
  1296. display: flex;
  1297. align-items: center;
  1298. justify-content: center;
  1299. flex-direction: column;
  1300. }
  1301. .progressBox .lbox {
  1302. height: 100px;
  1303. font-size: 19px;
  1304. display: flex;
  1305. align-items: center;
  1306. }
  1307. .progressBox .lbox img {
  1308. width: 40px;
  1309. margin-right: 20px;
  1310. }
  1311. .progressBox >>> .el-progress-bar__outer {
  1312. background-color: #d1dfff !important;
  1313. }
  1314. .top-popover {
  1315. position: absolute;
  1316. top: -50px;
  1317. left: 0;
  1318. background: #fff;
  1319. display: flex;
  1320. height: 45px;
  1321. align-items: center;
  1322. padding: 0px 10px 0 20px;
  1323. border-radius: 5px;
  1324. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1325. z-index: 10;
  1326. transition: 0.5s all;
  1327. opacity: 0;
  1328. visibility: hidden;
  1329. }
  1330. .top-popover .pChild {
  1331. display: flex;
  1332. align-items: center;
  1333. }
  1334. .top-popover .pChild + .pChild {
  1335. margin-left: 10px;
  1336. }
  1337. .left-popover {
  1338. position: absolute;
  1339. top: 0px;
  1340. right: -65px;
  1341. background: #fff;
  1342. display: flex;
  1343. width: 45px;
  1344. align-items: center;
  1345. padding: 10px 5px 20px;
  1346. border-radius: 5px;
  1347. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1348. z-index: 10;
  1349. flex-direction: column;
  1350. justify-content: center;
  1351. transition: 0.5s all;
  1352. opacity: 0;
  1353. visibility: hidden;
  1354. }
  1355. .left-popover .pChild {
  1356. display: flex;
  1357. align-items: center;
  1358. flex-direction: column;
  1359. }
  1360. .left-popover .pChild span {
  1361. display: flex;
  1362. align-items: center;
  1363. flex-direction: column;
  1364. text-align: center;
  1365. }
  1366. .left-popover .pChild + .pChild {
  1367. margin-top: 10px;
  1368. }
  1369. .right-popover {
  1370. position: absolute;
  1371. top: 0px;
  1372. left: -65px;
  1373. background: #fff;
  1374. display: flex;
  1375. width: 45px;
  1376. align-items: center;
  1377. padding: 10px 5px 20px;
  1378. border-radius: 5px;
  1379. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1380. z-index: 10;
  1381. flex-direction: column;
  1382. justify-content: center;
  1383. transition: 0.5s all;
  1384. opacity: 0;
  1385. visibility: hidden;
  1386. }
  1387. .right-popover .pChild {
  1388. display: flex;
  1389. align-items: center;
  1390. flex-direction: column;
  1391. }
  1392. .right-popover .pChild span {
  1393. display: flex;
  1394. align-items: center;
  1395. flex-direction: column;
  1396. text-align: center;
  1397. }
  1398. .right-popover .pChild + .pChild {
  1399. margin-top: 10px;
  1400. }
  1401. .visibleO {
  1402. opacity: 1 !important;
  1403. visibility: visible !important;
  1404. }
  1405. .remark-bottom-popover {
  1406. position: absolute;
  1407. bottom: 0px;
  1408. left: 0;
  1409. background: #fff;
  1410. max-height: 150px;
  1411. width: 100%;
  1412. padding: 10px 20px;
  1413. border-radius: 5px;
  1414. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1415. z-index: 10;
  1416. transition: 0.5s all;
  1417. box-sizing: border-box;
  1418. transform: translateY(calc(100% + 5px));
  1419. overflow: auto;
  1420. opacity: 0;
  1421. visibility: hidden;
  1422. }
  1423. .Rbox {
  1424. display: flex;
  1425. word-break: break-all;
  1426. }
  1427. .Rbox + .Rbox {
  1428. border-top: 1px solid rgb(233, 233, 233);
  1429. margin-top: 10px;
  1430. padding-top: 10px;
  1431. }
  1432. .Rportal {
  1433. height: 45px;
  1434. min-width: 45px;
  1435. border-radius: 50px;
  1436. overflow: hidden;
  1437. display: block;
  1438. background: aliceblue;
  1439. user-select: none;
  1440. }
  1441. .RContent {
  1442. margin-left: 10px;
  1443. }
  1444. .RContent div:nth-child(1) {
  1445. user-select: none;
  1446. color: rgb(80, 80, 80);
  1447. margin-bottom: 5px;
  1448. font-size: 14px;
  1449. }
  1450. .RContent div:nth-child(2) {
  1451. font-family: "微软雅黑";
  1452. font-size: 15px;
  1453. }
  1454. .remark-right-popover {
  1455. position: absolute;
  1456. top: 0;
  1457. right: 0;
  1458. background: #fff;
  1459. max-height: 100%;
  1460. width: 300px;
  1461. padding: 10px 20px;
  1462. border-radius: 5px;
  1463. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1464. z-index: 10;
  1465. transition: 0.5s all;
  1466. box-sizing: border-box;
  1467. transform: translateX(calc(100% + 5px));
  1468. overflow: auto;
  1469. opacity: 0;
  1470. visibility: hidden;
  1471. }
  1472. .remark-left-popover {
  1473. position: absolute;
  1474. top: 0;
  1475. left: 0;
  1476. background: #fff;
  1477. max-height: 100%;
  1478. width: 300px;
  1479. padding: 10px 20px;
  1480. border-radius: 5px;
  1481. box-shadow: 0 1px 3px 1px rgb(202, 202, 202);
  1482. z-index: 10;
  1483. transition: 0.5s all;
  1484. box-sizing: border-box;
  1485. transform: translateX(calc(-100% - 5px));
  1486. overflow: auto;
  1487. opacity: 0;
  1488. visibility: hidden;
  1489. }
  1490. </style>