江夏区图书馆自助查询机
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
13 KiB

6 months ago
5 months ago
6 months ago
5 months ago
6 months ago
  1. <template>
  2. <div class="venue-preview">
  3. <!-- v-show="currentMarkData && currentMarkData.signPoint" -->
  4. <div v-show="currentMarkData && currentMarkData.signPoint">
  5. <canvas :id="`canvasPreview${currentMarkData && currentMarkData.id}`" :width="width" :height="height" />
  6. </div>
  7. <img v-if="currentMarkData &&!currentMarkData.signPoint" :src="imageUrl" :onerror="defaultImg" alt="">
  8. <div id="tooltip" class="tooltip-style">
  9. <!-- <div class="tooltip-top">
  10. <h4>区域名称</h4>
  11. <span class="update-time">2024-11-28 09:46</span>
  12. </div>
  13. <ul>
  14. <li><p>在架</p><span><i>15000</i></span></li>
  15. <li><p>错架</p><span><i>300</i></span> <span class="percentage">2.00%</span></li>
  16. <li><p>错序</p><span><i>0</i></span><span class="percentage">0.00%</span></li>
  17. </ul> -->
  18. </div>
  19. </div>
  20. </template>
  21. <script>
  22. // import { dataScreeningCrud } from '@/views/visualCheck/mixins/index'
  23. import defaultImg from '@/assets/images/default-img-bg.jpg'
  24. import { fabric } from 'fabric'
  25. import { mapGetters } from 'vuex'
  26. export default {
  27. name: 'Mark',
  28. mixins: [],
  29. props: {
  30. currentMarkData: {
  31. type: Object,
  32. require: true,
  33. default: function() {
  34. return {}
  35. }
  36. },
  37. imageUrl: {
  38. type: String,
  39. default: ''
  40. },
  41. pagePreview: {
  42. type: String,
  43. default: ''
  44. }
  45. },
  46. data() {
  47. return {
  48. defaultImg: defaultImg,
  49. canvasPreview: {},
  50. width: 1200,
  51. height: 600,
  52. drawWidth: 2,
  53. tooltipInfo: null,
  54. initialDistance: 0,
  55. initialZoom: 0
  56. }
  57. },
  58. computed: {
  59. ...mapGetters([
  60. 'user',
  61. 'baseApi'
  62. ])
  63. },
  64. watch: {
  65. width() {
  66. this.canvasPreview.setWidth(this.width)
  67. },
  68. height() {
  69. this.canvasPreview.setHeight(this.height)
  70. },
  71. currentMarkData: {
  72. handler(newVal, oldVal) {
  73. // 检查 newVal 是否为 null 或 undefined
  74. if (!newVal) {
  75. console.log('newVal - null')
  76. return
  77. }
  78. },
  79. deep: true
  80. },
  81. imageUrl(newVal, oldVal) {
  82. if (newVal !== oldVal) {
  83. console.log('imageUrl', newVal)
  84. }
  85. }
  86. },
  87. mounted() {
  88. // if (this.canvasPreview.lowerCanvasEl) {
  89. // this.canvasPreview.getCanvas().el.addEventListener('touchstart', this.handleTouchStart.bind(this))
  90. // this.canvasPreview.getCanvas().el.addEventListener('touchmove', this.handleTouchMove.bind(this))
  91. // this.canvasPreview.getCanvas().el.addEventListener('touchend', this.handleTouchEnd.bind(this))
  92. // }
  93. },
  94. beforeDestroy() {
  95. // if (this.canvasPreview) {
  96. // this.canvasPreview.clear()
  97. // this.canvasPreview.dispose()
  98. // }
  99. },
  100. methods: {
  101. initCanvasPreview(drawinfo, tabIndex) {
  102. if (!this.currentMarkData) {
  103. console.error('currentMarkData - null')
  104. return
  105. }
  106. const canvasId = `canvasPreview${this.currentMarkData.id}`
  107. this.canvasPreview = new fabric.Canvas(canvasId, {
  108. skipTargetFind: false,
  109. selectable: false,
  110. selection: false
  111. })
  112. this.$nextTick(() => {
  113. this.canvasPreview.selectionColor = 'rgba(0,0,0,0.05)'
  114. this.loadDrawPreview(drawinfo, tabIndex)
  115. // this.canvasPreview.on('mouse:wheel', this.mouse)
  116. })
  117. },
  118. // 触摸事件处理函数
  119. handleTouchStart(e) {
  120. if (e.touches.length === 2) {
  121. const touch1 = e.touches[0]
  122. const touch2 = e.touches[1]
  123. this.initialDistance = Math.sqrt((touch2.clientX - touch1.clientX) * (touch2.clientX - touch1.clientX) + (touch2.clientY - touch1.clientY) * (touch2.clientY - touch1.clientY))
  124. this.initialZoom = this.canvasPreview.getZoom()
  125. }
  126. },
  127. handleTouchMove(e) {
  128. if (e.touches.length === 2) {
  129. const touch1 = e.touches[0]
  130. const touch2 = e.touches[1]
  131. const currentDistance = Math.sqrt((touch2.clientX - touch1.clientX) * (touch2.clientX - touch1.clientX) + (touch2.clientY - touch1.clientY) * (touch2.clientY - touch1.clientY))
  132. let newZoom = this.initialZoom * (currentDistance / this.initialDistance)
  133. newZoom = Math.max(0.8, newZoom)
  134. newZoom = Math.min(3, newZoom)
  135. const centerX = (touch1.clientX + touch2.clientX) / 2
  136. const centerY = (touch1.clientY + touch2.clientY) / 2
  137. const zoomPoint = new fabric.Point(centerX, centerY)
  138. this.canvasPreview.zoomToPoint(zoomPoint, newZoom)
  139. }
  140. },
  141. handleTouchEnd() {
  142. // 触摸结束时可以做一些清理操作,这里暂未用到
  143. },
  144. // 回显详情信息
  145. loadDrawPreview(drawinfo, tabIndex) {
  146. const self = this
  147. const pointGroup = drawinfo.pointInfo
  148. const imgInfo = drawinfo.imgInfo
  149. imgInfo.src = self.imageUrl
  150. // 加载底图
  151. fabric.util.enlivenObjects([imgInfo], objects => {
  152. objects.forEach(o => {
  153. o.selectable = false
  154. o.hasControls = false
  155. o.centeredScaling = false
  156. self.canvasPreview.add(o)
  157. })
  158. // 处理多边形绘制回显操作
  159. pointGroup.forEach(async(item, index) => {
  160. console.log('item', item)
  161. if (item.pointInfo !== '') {
  162. const polygon = new fabric.Polygon(item.pointInfo, {
  163. id: item.id,
  164. name: item.name,
  165. floorId: item.floorId,
  166. regionId: item.regionId,
  167. rowType: item.rowType,
  168. toward: item.toward,
  169. floorName: item.floorName,
  170. regionName: item.regionName,
  171. shelfFloor: item.shelfFloor,
  172. shelfShelf: item.shelfShelf,
  173. errorOrderNum: item.errorOrderNum,
  174. errorOrderProbo: item.errorOrderProbo,
  175. errorShelfNum: item.errorShelfNum,
  176. errorShelfProbo: item.errorShelfProbo,
  177. onShelfNum: item.onShelfNum,
  178. stroke: 'rgba(196,43, 1, 1)',
  179. strokeWidth: self.drawWidth,
  180. fill: 'rgba(196,43, 1, 1)',
  181. opacity: 0.5,
  182. selectable: false,
  183. hasBorders: false,
  184. hasControls: false,
  185. originX: 'left', // 设置原点为左上角
  186. originY: 'top' // 设置原点为左上角
  187. })
  188. self.canvasPreview.add(polygon)
  189. // const lastClickTime = 0
  190. // const doubleClickInterval = 300
  191. polygon.on('mousedown', function(e) {
  192. // const currentTime = new Date().getTime()
  193. // const timeDiff = currentTime - lastClickTime
  194. const toReigonsData = {
  195. id: e.target.id,
  196. name: e.target.name,
  197. floorId: e.target.floorId,
  198. regionId: e.target.regionId,
  199. rowType: e.target.rowType,
  200. toward: e.target.toward,
  201. regionName: e.target.regionName,
  202. floorName: e.target.floorName
  203. }
  204. console.log('toReigonsData', toReigonsData)
  205. if (self.pagePreview === 'floor') {
  206. console.log('toReigonsData', toReigonsData)
  207. self.handleToRegions(toReigonsData, tabIndex)
  208. } else if (self.pagePreview === 'region') {
  209. self.handleToShelfs(toReigonsData, tabIndex)
  210. }
  211. // if (timeDiff <= doubleClickInterval) {
  212. // console.log('双击事件', e)
  213. // lastClickTime = 0
  214. // const toReigonsData = {
  215. // id: e.target.id,
  216. // name: e.target.name,
  217. // floorId: e.target.floorId,
  218. // regionId: e.target.regionId,
  219. // rowType: e.target.rowType,
  220. // toward: e.target.toward,
  221. // regionName: e.target.regionName,
  222. // floorName: e.target.floorName
  223. // }
  224. // console.log('toReigonsData', toReigonsData)
  225. // if (self.pagePreview === 'floor') {
  226. // self.handleToRegions(toReigonsData, tabIndex)
  227. // } else if (self.pagePreview === 'region') {
  228. // self.handleToShelfs(toReigonsData, tabIndex)
  229. // }
  230. // } else {
  231. // lastClickTime = currentTime
  232. // }
  233. })
  234. // polygon.on('mouseover', function(e) {
  235. // this.tooltipInfo = {
  236. // 'id': e.target.id,
  237. // 'name': e.target.name,
  238. // 'rowType': e.target.rowType,
  239. // 'shelfFloor': e.target.shelfFloor,
  240. // 'shelfShelf': e.target.shelfShelf,
  241. // 'floorId': e.target.floorId,
  242. // 'regionId': e.target.regionId,
  243. // 'errorOrderNum': e.target.errorOrderNum,
  244. // 'errorOrderProbo': e.target.errorOrderProbo,
  245. // 'errorShelfNum': e.target.errorShelfNum,
  246. // 'errorShelfProbo': e.target.errorShelfProbo,
  247. // 'onShelfNum': e.target.onShelfNum
  248. // }
  249. // this.set({ opacity: 0.8, hoverCursor: 'pointer' })
  250. // // <span class="update-time">2024-11-28 09:46</span>
  251. // if (self.pagePreview === 'floor') {
  252. // document.getElementById('tooltip').innerHTML =
  253. // `<div class="tooltip-top">
  254. // <h4>${this.tooltipInfo.name}</h4>
  255. // </div>
  256. // <ul>
  257. // <li><p>在架</p><span><i>${this.tooltipInfo.onShelfNum}</i>册</span></li>
  258. // <li><p>错架</p><span><i>${this.tooltipInfo.errorShelfNum}</i>册</span> <span class="percentage">(${this.tooltipInfo.errorShelfProbo})</span></li>
  259. // <li><p>错序</p><span><i>${this.tooltipInfo.errorOrderNum}</i>册</span><span class="percentage">(${this.tooltipInfo.errorOrderProbo})</span></li>
  260. // </ul>`
  261. // } else if (self.pagePreview === 'region') {
  262. // document.getElementById('tooltip').innerHTML =
  263. // `<div class="tooltip-top">
  264. // <h4>书架概况</h4>
  265. // </div>
  266. // <ul>
  267. // <li><p>书架</p><span><i>${this.tooltipInfo.name}</i></span></li>
  268. // <li><p>规则</p><span><i>${this.tooltipInfo.rowType === 1 ? '单面' : '双面'}${this.tooltipInfo.shelfFloor}*${this.tooltipInfo.shelfShelf}</i></span></li>
  269. // <li><p>在架</p><span><i>${this.tooltipInfo.onShelfNum}</i>册</span></li>
  270. // <li><p>错架</p><span><i>${this.tooltipInfo.errorShelfNum}</i>册</span> <span class="percentage">(${this.tooltipInfo.errorShelfProbo})</span></li>
  271. // <li><p>错序</p><span><i>${this.tooltipInfo.errorOrderNum}</i>册</span><span class="percentage">(${this.tooltipInfo.errorOrderProbo})</span></li>
  272. // </ul>`
  273. // }
  274. // // var rectLeft = e.target.left + e.target.width - 100
  275. // var rectLeft = e.target.left + e.target.width
  276. // var rectTop = e.target.top + e.target.height - 40
  277. // document.getElementById('tooltip').style.left = rectLeft + 'px'
  278. // document.getElementById('tooltip').style.top = rectTop + 'px'
  279. // document.getElementById('tooltip').style.display = 'block'
  280. // self.canvasPreview.renderAll()
  281. // })
  282. // polygon.on('mouseout', function() {
  283. // this.set({ opacity: 0.5 })
  284. // document.getElementById('tooltip').style.display = 'none'
  285. // self.canvasPreview.renderAll()
  286. // })
  287. }
  288. })
  289. // 计算画布的中心点
  290. const centerX = self.canvasPreview.width / 2
  291. const centerY = self.canvasPreview.height / 2
  292. const centerPoint = new fabric.Point(centerX, centerY)
  293. // 设置画布的缩放比例为最小值并居中显示
  294. self.canvasPreview.zoomToPoint(centerPoint, 1)
  295. self.canvasPreview.renderAll()
  296. setTimeout(() => {
  297. self.$parent.prewLoading = false
  298. }, 500)
  299. })
  300. },
  301. handleToRegions(data, tabIndex) {
  302. this.$router.push({ path: '/regions' })
  303. localStorage.setItem('dataScreenFloor', JSON.stringify(data))
  304. localStorage.setItem('dataScreenFloorTableIndex', tabIndex)
  305. },
  306. handleToShelfs(data, tabIndex) {
  307. this.$router.push({ path: '/shelf' })
  308. localStorage.setItem('dataScreenRegion', JSON.stringify(data))
  309. localStorage.setItem('dataScreenRegionTableIndex', tabIndex)
  310. }
  311. }
  312. }
  313. </script>
  314. <style lang="scss" scoped>
  315. #expImg{
  316. display: none;
  317. }
  318. .venue-preview{
  319. width: 100%;
  320. background-color: #fff;
  321. overflow: hidden;
  322. // margin-top: -30px;
  323. }
  324. </style>