index.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <div class="photo">
  3. <div class="left">
  4. <div class="upload">
  5. <el-button type="primary" @click="addCaseFileHandler">
  6. 上传照片
  7. </el-button>
  8. <el-button
  9. type="primary"
  10. @click="sortType = !sortType"
  11. :icon="sortType ? FullScreen : Menu"
  12. >{{ sortType ? "横排" : "竖排" }}</el-button
  13. >
  14. </div>
  15. <draggable
  16. ref="childRef"
  17. :caseId="caseId"
  18. :sortType="sortType"
  19. @changeList="changeList"
  20. @handleItem="handleItem"
  21. />
  22. </div>
  23. <div class="right">
  24. <div class="tools">
  25. <el-button @click="handleMark">标注方向</el-button>
  26. <el-button @click="handleLine">标注连线</el-button>
  27. <el-button @click="handleSave">保存</el-button>
  28. <el-button @click="handleFree" v-if="isShowExitEdit">退出</el-button>
  29. </div>
  30. <swiper
  31. class="swiper"
  32. v-if="false"
  33. slides-per-view="auto"
  34. :space-between="24"
  35. :centeredSlides="true"
  36. @swiper="onSwiper"
  37. style="height: 100%"
  38. @slideChange="onSlideChange"
  39. >
  40. <swiper-slide
  41. class="swiperItem"
  42. v-for="(item, index) in newlist"
  43. :key="index"
  44. >
  45. <div class="swiperList">
  46. <div
  47. class="itemper"
  48. :class="{ oneItemper: sortType }"
  49. v-for="eleItem in item"
  50. :key="eleItem"
  51. >
  52. <img class="itemImg" :src="eleItem.imgUrl" alt="" />
  53. <div class="text">{{ eleItem.imgInfo }}</div>
  54. </div>
  55. <div class="page">
  56. <span style="margin-right: 16px">第 {{ index + 1 }} 页</span>
  57. <span>共 {{ newlist.length }} 页</span>
  58. </div>
  59. </div>
  60. </swiper-slide>
  61. </swiper>
  62. <canvas id="canvas" v-show="true"></canvas>
  63. </div>
  64. </div>
  65. </template>
  66. <script setup>
  67. import { onMounted, ref, computed } from "vue";
  68. import { Menu, FullScreen } from "@element-plus/icons-vue";
  69. import { Swiper, SwiperSlide } from "swiper/vue";
  70. import "swiper/css";
  71. // import { addCaseFile } from "@/store/caseFile";
  72. import { addCaseImgFile } from "../quisk";
  73. import { saveCaseImgTagData } from "@/store/case";
  74. import Scene from "@/core/Scene.js";
  75. import draggable from "./draggable.vue";
  76. const props = defineProps({ caseId: Number });
  77. const newlist = ref([]);
  78. const swiperRef = ref(null);
  79. const childRef = ref(null);
  80. const caseId = ref(props.caseId);
  81. const sortType = ref(false);
  82. const drawMode = ref(0);
  83. const isShowExitEdit = computed(() => drawMode.value > 0);
  84. let scene = null;
  85. const addCaseFileHandler = async () => {
  86. await addCaseImgFile({
  87. caseId: caseId.value,
  88. data: {
  89. imgUrl: "",
  90. imgInfo: "",
  91. id: "",
  92. sort: "",
  93. },
  94. });
  95. refresh();
  96. };
  97. function refresh() {
  98. console.log("changeList", childRef.value);
  99. if (childRef.value) {
  100. childRef.value.getList();
  101. }
  102. }
  103. const changeList = (list) => {
  104. let newList = [];
  105. list.map((item, index) => {
  106. if (sortType.value) {
  107. newList.push([item]);
  108. } else {
  109. if (index % 2 == 0) {
  110. let newItem = list[index + 1] ? [item, list[index + 1]] : [item];
  111. newList.push(newItem);
  112. }
  113. }
  114. });
  115. newlist.value = newList;
  116. const arr = [];
  117. newList.map((i) => arr.push(JSON.parse(JSON.stringify(i))));
  118. const type = sortType.value ? 2 : 1;
  119. if (scene) {
  120. scene.load(arr, type);
  121. console.log("changeList", arr, type);
  122. }
  123. };
  124. const renderCanvas = () => {
  125. const canvas = document.getElementById("canvas");
  126. // console.log(canvas)
  127. scene = new Scene(canvas);
  128. scene.init();
  129. window.scene = scene;
  130. scene.on("mode", (mode) => {
  131. console.warn("mode", mode);
  132. drawMode.value = mode;
  133. });
  134. };
  135. const onSwiper = (swiper) => {
  136. console.log("onSwiper");
  137. swiperRef.value = swiper;
  138. };
  139. const onSlideChange = (swiper) => {
  140. console.log(swiper);
  141. };
  142. const handleItem = (item) => {
  143. let active = sortType.value ? item : Math.floor(item / 2);
  144. swiperRef.value.slideTo(active);
  145. console.log("handleItem", item, active);
  146. };
  147. const handleDetele = async (item) => {
  148. if (
  149. await confirm("删除该场景,将同时从案件和融合模型中移除,确定要删除吗?")
  150. ) {
  151. const scenes = getCaseScenes(list.value.filter((item) => item !== scene));
  152. await replaceCaseScenes(props.caseId, scenes);
  153. refresh();
  154. }
  155. };
  156. const handleMark = () => {
  157. if (window.scene) {
  158. window.scene.player.setMode(2);
  159. }
  160. };
  161. const handleLine = () => {
  162. if (window.scene) {
  163. window.scene.player.setMode(1);
  164. }
  165. };
  166. const handleSave = () => {
  167. if (window.scene) {
  168. }
  169. };
  170. const handleFree = () => {
  171. if (window.scene) {
  172. window.scene.player.setMode(0);
  173. }
  174. };
  175. onMounted(() => {
  176. renderCanvas();
  177. });
  178. </script>
  179. <style lang="scss" scoped>
  180. #canvas {
  181. width: 100%;
  182. height: 100%;
  183. }
  184. .photo {
  185. display: flex;
  186. height: 100%;
  187. .left {
  188. width: 260px;
  189. padding: 16px 24px 30px 0;
  190. height: calc(100% - 46.16px);
  191. overflow-y: auto;
  192. background: #ffffff;
  193. box-shadow: 10px 0 10px -10px rgba(0, 0, 0, 0.15);
  194. // box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.15);
  195. }
  196. .right {
  197. width: calc(100% - 260px);
  198. background-color: var(--bgColor);
  199. padding-left: 24px;
  200. height: calc(100% - 0px);
  201. position: relative;
  202. .tools {
  203. position: absolute;
  204. top: 15px;
  205. left: 30px;
  206. }
  207. .swiperItem {
  208. height: calc(100vh - 155.16px);
  209. width: calc((100vh - 156.16px) * 0.707);
  210. background: #ffffff;
  211. .swiperList {
  212. padding: 0 60px;
  213. height: 100%;
  214. .page {
  215. font-weight: 400;
  216. font-size: 12px;
  217. color: rgba(0, 0, 0, 0.85);
  218. line-height: 22px;
  219. text-align: right;
  220. margin-top: 30px;
  221. }
  222. .itemper {
  223. height: calc(50% - 100px);
  224. padding: 60px 0 0 0;
  225. .text {
  226. margin-top: 16px;
  227. border-radius: 0px 0px 0px 0px;
  228. border: 1px dotted #cccccc;
  229. text-align: center;
  230. font-family: Microsoft YaHei, Microsoft YaHei;
  231. font-weight: 400;
  232. font-size: 14px;
  233. line-height: 30px;
  234. color: rgba(0, 0, 0, 0.85);
  235. }
  236. .itemImg {
  237. width: 100%;
  238. height: calc(100% - 48px);
  239. display: block;
  240. object-fit: cover;
  241. }
  242. }
  243. .oneItemper {
  244. height: calc(100% - 120px);
  245. .itemImg {
  246. }
  247. }
  248. }
  249. }
  250. }
  251. }
  252. </style>