a220646bb7a294c61da6d2be8bdf8f9f.json 17 KB

1
  1. {"remainingRequest":"D:\\front\\item\\zyAdmin\\node_modules\\vue-loader\\lib\\index.js??vue-loader-options!D:\\front\\item\\zyAdmin\\src\\components\\hotpotModal\\index.vue?vue&type=style&index=0&id=7ca5a708&lang=scss&scoped=true","dependencies":[{"path":"D:\\front\\item\\zyAdmin\\src\\components\\hotpotModal\\index.vue","mtime":1761614938956},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\css-loader\\index.js","mtime":1761614929364},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\vue-loader\\lib\\loaders\\stylePostLoader.js","mtime":1761614937403},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\postcss-loader\\src\\index.js","mtime":1761614935133},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\sass-loader\\dist\\cjs.js","mtime":1761614936391},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\cache-loader\\dist\\cjs.js","mtime":1761614927801},{"path":"D:\\front\\item\\zyAdmin\\node_modules\\vue-loader\\lib\\index.js","mtime":1761614937402}],"contextDependencies":[],"result":[{"type":"Buffer","data":"base64:DQo6OnYtZGVlcCAuZWwtZGlhbG9nIHsNCiAgYm9yZGVyLXJhZGl1czogMHB4ICFpbXBvcnRhbnQ7DQogIC5lbC1hbGVydF9faWNvbi5pcy1iaWcgew0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgICB3aWR0aDogMTZweDsNCiAgfQ0KICAuZWwtYWxlcnQgLmVsLWFsZXJ0X19kZXNjcmlwdGlvbiB7DQogICAgbWFyZ2luOiAwOw0KICB9DQp9DQouYnRuIHsNCiAgZGlzcGxheTogZmxleDsNCiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogIHBhZGRpbmc6IDE2cHggMDsNCn0NCi5kaWFsb2ctZm9vdGVyIHsNCiAgdGV4dC1hbGlnbjogcmlnaHQ7DQogIG1hcmdpbi10b3A6IDIwcHg7DQogIG1hcmdpbi1yaWdodDogMjBweDsNCn0NCi5vcGVyYXRpb25GbG9vciB7DQogIGRpc3BsYXk6IGZsZXg7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgbWF4LWhlaWdodDogODB2aDsNCiAgLmhlYWRlciB7DQogICAgLnRpdGxlQm94IHsNCiAgICAgIGRpc3BsYXk6IGZsZXg7DQogICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47DQogICAgICBhbGlnbi1pdGVtczogY2VudGVyOw0KICAgICAgaGVpZ2h0OiAxMDBweDsNCiAgICAgIC5uYW1lIHsNCiAgICAgICAgZm9udC1zaXplOiAxM3B4Ow0KICAgICAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICAgIH0NCiAgICB9DQogICAgLnRleHRCb3ggew0KICAgICAgZm9udC1zaXplOiAxMnB4Ow0KICAgICAgY29sb3I6ICM3Nzc7DQogICAgICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KICAgIH0NCiAgfQ0KICAuaW1nQm94Ojotd2Via2l0LXNjcm9sbGJhciB7DQogICAgZGlzcGxheTogbm9uZTsgLyogQ2hyb21lIFNhZmFyaSAqLw0KICB9DQogIC5pbWdCb3ggew0KICAgIGRpc3BsYXk6IGZsZXg7DQogICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogICAgd2lkdGg6IDY1JTsNCiAgICBvdmVyZmxvdy15OiBzY3JvbGw7DQogICAgbWF4LWhlaWdodDogODAwcHg7DQogICAgLmNvbnRhaW5lciB7DQogICAgICBwb3NpdGlvbjogcmVsYXRpdmU7DQogICAgICBib3JkZXI6IDFweCBzb2xpZCAjZjVmNWY1Ow0KICAgIH0NCg0KICAgIGltZyB7DQogICAgICBjdXJzb3I6IGNyb3NzaGFpcjsNCiAgICAgIGRpc3BsYXk6IGJsb2NrOw0KICAgICAgd2lkdGg6IDc1MHB4Ow0KICAgIH0NCiAgICAuYXJlYSB7DQogICAgICBwb3NpdGlvbjogYWJzb2x1dGU7DQogICAgICB3aWR0aDogMjAwcHg7DQogICAgICBoZWlnaHQ6IDIwMHB4Ow0KICAgICAgbGVmdDogMjAwcHg7DQogICAgICB0b3A6IDMwMHB4Ow0KICAgICAgYmFja2dyb3VuZDogcmdiYSgjMjk4MGI5LCAwLjMpOw0KICAgICAgYm9yZGVyOiAxcHggZGFzaGVkICMzNDQ5NWU7DQogICAgfQ0KICB9DQp9DQouZm9ybSB7DQogIGZvbnQtc2l6ZTogMTJweDsNCiAgd2lkdGg6IDMwJTsNCiAgbWF4LWhlaWdodDogODAwcHg7DQogIG92ZXJmbG93LXk6IHNjcm9sbDsNCiAgLmZvcm0tcm93IHsNCiAgICBkaXNwbGF5OiBmbGV4Ow0KICAgIG1hcmdpbjogMTJweCAwOw0KICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7DQogICAgLmZvcm0taXRlbSB7DQogICAgICBkaXNwbGF5OiBmbGV4Ow0KICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOw0KICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7DQogICAgICBtYXJnaW46IDAgNXB4Ow0KICAgICAgZm9udC1zaXplOiAxMnB4Ow0KICAgICAgLm51bSB7DQogICAgICAgIHdpZHRoOiA2OXB4Ow0KICAgICAgICBjb2xvcjogIzk5OTsNCiAgICAgICAgZm9udC1zaXplOiAxMnB4Ow0KICAgICAgfQ0KICAgICAgLmxhYmVsIHsNCiAgICAgICAgY29sb3I6ICNjN2M3Yzc7DQogICAgICB9DQogICAgfQ0KICB9DQogIC5lbC1pY29uLWRlbGV0ZSB7DQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGN1cnNvcjogcG9pbnRlcjsNCiAgfQ0KfQ0K"},{"version":3,"sources":["index.vue"],"names":[],"mappings":";AAsVA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.vue","sourceRoot":"src/components/hotpotModal","sourcesContent":["<template>\r\n <div>\r\n <el-dialog title=\"编辑热区\" :visible.sync=\"dialogVisible\" @opened=\"openModal\" fullscreen>\r\n <div class=\"operationFloor\">\r\n <div class=\"imgBox\" @mouseup.left.stop=\"changeStop()\">\r\n <div ref=\"container\" id=\"img-box-container\" class=\"container\">\r\n <img\r\n ref=\"backgroundImg\"\r\n :src=\"imgs\"\r\n ondragstart=\"return false;\"\r\n oncontextmenu=\"return false;\"\r\n onselect=\"document.selection.empty();\"\r\n alt=\"img\"\r\n @mousedown.left.stop=\"mouseDown($event)\"\r\n />\r\n <!--draw hotpot-->\r\n <div\r\n v-show=\"caseShow\"\r\n :style=\"{\r\n width: areaWidth + 'px',\r\n height: areaHeight + 'px',\r\n left: starX + 'px',\r\n top: starY + 'px',\r\n }\"\r\n class=\"area\"\r\n />\r\n <!--be hotpot-->\r\n <AreaBox\r\n v-for=\"(item, index) in areaData\"\r\n :area-data-index=\"index\"\r\n :key=\"'area' + index\"\r\n :link=\"item.link\"\r\n :title=\"item.title\"\r\n :type=\"parseInt(item.type)\"\r\n :area-init.sync=\"item\"\r\n :parent-width=\"parentWidth\"\r\n :parent-height=\"parentHeight\"\r\n @delAreaBox=\"delAreaBox\"\r\n @addURL=\"addURL\"\r\n />\r\n </div>\r\n </div>\r\n <!-- 热区链接配置 -->\r\n <div class=\"form\">\r\n <h2 class=\"mb20\">图片热区</h2>\r\n <el-alert type=\"warning\" :closable=\"false\" show-icon>框选热区范围,双击设置热区信息</el-alert>\r\n\r\n <div v-for=\"(item, index) in areaData\" :key=\"index\" class=\"form-row\">\r\n <div class=\"form-item\">\r\n <span class=\"num\">热区{{ item.number }}</span>\r\n </div>\r\n <div class=\"form-item label\">\r\n <div>\r\n <el-input\r\n icon=\"ios-arrow-forward\"\r\n v-model=\"item.link\"\r\n :style=\"linkInputStyle\"\r\n placeholder=\"选择跳转链接\"\r\n >\r\n <i class=\"el-icon-link\" slot=\"suffix\" @click=\"getLink(index)\" />\r\n </el-input>\r\n </div>\r\n </div>\r\n <i class=\"el-icon-delete\" @click=\"delAreaBox(index)\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div slot=\"footer\">\r\n <el-button class=\"mr20\" type=\"primary\" @click=\"saveAreaData\"> 完成 </el-button>\r\n </div>\r\n </el-dialog>\r\n <linkaddress ref=\"linkaddres\" @linkUrl=\"linkUrl\"></linkaddress>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport AreaBox from './AreaBox';\r\nimport linkaddress from '@/components/linkaddress';\r\n\r\nexport default {\r\n name: 'OperationFloor',\r\n components: {\r\n AreaBox,\r\n linkaddress,\r\n },\r\n props: {\r\n /**\r\n * @description 图片数据对象\r\n * @type {ImgData}\r\n */\r\n imgs: {\r\n type: String, // 图片类型\r\n default: () => '', // 默认值为空字符串\r\n },\r\n /**\r\n * @description 是否为热门汤品\r\n * @type {boolean}\r\n */\r\n isHotPot: {\r\n type: Boolean, // 布尔类型\r\n default: () => false, // 默认值为false\r\n },\r\n /**\r\n * @description 图片区域数据对象\r\n * @type {AreaData[]}\r\n */\r\n imgAreaData: {\r\n type: Array, // 数组类型\r\n default: () => [], // 默认值为空数组\r\n },\r\n /**\r\n * @description 链接输入框样式对象\r\n * @type {LinkInputStyle}\r\n */\r\n linkInputStyle: {\r\n type: Object, // 对象类型\r\n default: () => ({\r\n // 默认值为一个包含width属性的对象\r\n width: '300px',\r\n }),\r\n },\r\n },\r\n data() {\r\n return {\r\n /**\r\n * @description 对话框是否可见\r\n * @type {boolean}\r\n */\r\n dialogVisible: false,\r\n /**\r\n * @description 开始的x坐标\r\n * @type {number}\r\n */\r\n starX: 0,\r\n /**\r\n * @description 开始的y坐标\r\n * @type {number}\r\n */\r\n starY: 0,\r\n /**\r\n * @description 区域宽度\r\n * @type {number}\r\n */\r\n areaWidth: 0,\r\n /**\r\n * @description 区域高度\r\n * @type {number}\r\n */\r\n areaHeight: 0,\r\n /**\r\n * @description 当前显示的图片索引\r\n * @type {boolean}\r\n */\r\n caseShow: false,\r\n /**\r\n * @description 当前图片的宽度\r\n * @type {null}\r\n */\r\n nowImgWidth: null,\r\n /**\r\n * @description 区域数据\r\n * @type {Array}\r\n */\r\n areaData: [],\r\n /**\r\n * @description 当前显示的图片编号\r\n * @type {number}\r\n */\r\n imgNum: 1,\r\n /**\r\n * @description 父元素宽度\r\n * @type {number}\r\n */\r\n parentWidth: 0,\r\n /**\r\n * @description 父元素高度\r\n * @type {number}\r\n */\r\n parentHeight: 0,\r\n /**\r\n * @description 默认宽度\r\n * @type {number}\r\n */\r\n defaultWidth: 750,\r\n /**\r\n * @description 当前显示的图片索引\r\n * @type {number}\r\n */\r\n itemIndex: 0,\r\n };\r\n },\r\n computed: {},\r\n watch: {\r\n imgAreaData(val) {\r\n this.areaData = [...val];\r\n },\r\n },\r\n mounted() {\r\n this.areaData = [...this.imgAreaData];\r\n },\r\n methods: {\r\n openModal() {\r\n this.$nextTick(() => {\r\n const parentDiv = document.querySelector('#img-box-container');\r\n //获取元素的宽高\r\n this.parentWidth = this.defaultWidth;\r\n // this.parentWidth = parentDiv.clientWidth;\r\n this.parentHeight = parentDiv.clientHeight;\r\n // console.log(\"this.parentWidth\", this.parentWidth, this.parentHeight)\r\n });\r\n },\r\n closeModal() {\r\n this.$confirm('未保存内容,是否在离开前放弃保存?', '提示信息', {\r\n confirmButtonText: '确定',\r\n cancelButtonText: '取消',\r\n type: 'warning',\r\n })\r\n .then(() => {\r\n this.dialogVisible = false;\r\n })\r\n .catch(() => {\r\n this.$message({\r\n type: 'info',\r\n message: '已取消',\r\n });\r\n });\r\n },\r\n // 绘画热区开始\r\n mouseDown(e) {\r\n e.preventDefault();\r\n this.caseShow = true;\r\n // 记录滑动的初始值\r\n this.starX = e.layerX -5;\r\n this.starY = e.layerY -5;\r\n // 鼠标滑动的过程\r\n if (!document.onmousemove) {\r\n let maxWidth = this.defaultWidth - e.layerX;\r\n document.onmousemove = (ev) => {\r\n if (ev.layerX - this.starX < maxWidth) {\r\n this.areaWidth = ev.layerX - this.starX - 5;\r\n } else {\r\n this.areaWidth = maxWidth;\r\n }\r\n this.areaHeight = ev.layerY - this.starY -5;\r\n };\r\n }\r\n },\r\n // 绘画热区结束\r\n changeStop() {\r\n document.onmousemove = null;\r\n this.imgNum = this.areaData.length + 1;\r\n if (this.caseShow && this.areaWidth > 10 && this.areaHeight > 10) {\r\n const data = {\r\n number: this.imgNum,\r\n starX: this.starX,\r\n starY: this.starY,\r\n areaWidth: this.areaWidth,\r\n areaHeight: this.areaHeight,\r\n nowImgWidth: this.defaultWidth,\r\n link: '',\r\n };\r\n this.areaData.push(data);\r\n }\r\n // 初始化绘图\r\n this.caseShow = false;\r\n this.starX = 0;\r\n this.starY = 0;\r\n this.areaWidth = 0;\r\n this.areaHeight = 0;\r\n },\r\n // 删除指定热区\r\n delAreaBox(index) {\r\n /* 删除某个热区 */\r\n this.areaData.splice(index, 1);\r\n this.$emit('delAreaData', this.areaData);\r\n /* 删除后 每个热区按顺序重新编号 */\r\n if (this.areaData) {\r\n const arr = this.areaData.filter((i) => i.number > index);\r\n if (!arr) return;\r\n arr.forEach((i) => i.number--);\r\n if (this.areaData[this.areaData.length - 1]) {\r\n this.imgNum = this.areaData[this.areaData.length - 1].number + 1;\r\n } else {\r\n this.imgNum = 1;\r\n }\r\n }\r\n },\r\n // 添加网址\r\n addURL(index, url) {\r\n let obj = {\r\n ...this.areaData[index],\r\n link: url,\r\n };\r\n this.$set(this.areaData, index, obj);\r\n },\r\n // 保存热区信息\r\n saveAreaData() {\r\n if ((this.areaData && !this.areaData.length) || !this.checkData(this.areaData)) {\r\n this.$message.error('热区是否配置链接、是否至少添加一个热区?');\r\n return;\r\n }\r\n this.$emit('saveAreaData', this.areaData);\r\n this.dialogVisible = false;\r\n this.$message.success('编辑成功!');\r\n },\r\n /**\r\n * 检查列表中每个元素是否都有 link 属性\r\n * @param {Array} list - 待检查的列表\r\n * @returns {Boolean} - 是否所有元素都有 link 属性\r\n */\r\n checkData(list) {\r\n let isCheck = true;\r\n list.some((val) => {\r\n if (!val.link) {\r\n isCheck = false;\r\n }\r\n });\r\n return isCheck;\r\n },\r\n /**\r\n * @description 获取链接地址并打开添加链接的模态框\r\n * @param {number} index - 当前项的索引值\r\n */\r\n getLink(index) {\r\n // 设置当前项的索引值\r\n this.itemIndex = index;\r\n // 打开添加链接的模态框\r\n this.$refs.linkaddres.modals = true;\r\n },\r\n /**\r\n * @description 处理链接地址的输入事件\r\n * @param {string} e - 链接地址\r\n */\r\n linkUrl(e) {\r\n // 将链接地址存储到对应的数据项中\r\n this.areaData[this.itemIndex].link = e;\r\n },\r\n },\r\n};\r\n</script>\r\n\r\n<style lang=\"scss\" scoped>\r\n::v-deep .el-dialog {\r\n border-radius: 0px !important;\r\n .el-alert__icon.is-big {\r\n font-size: 14px;\r\n width: 16px;\r\n }\r\n .el-alert .el-alert__description {\r\n margin: 0;\r\n }\r\n}\r\n.btn {\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n padding: 16px 0;\r\n}\r\n.dialog-footer {\r\n text-align: right;\r\n margin-top: 20px;\r\n margin-right: 20px;\r\n}\r\n.operationFloor {\r\n display: flex;\r\n position: relative;\r\n max-height: 80vh;\r\n .header {\r\n .titleBox {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n height: 100px;\r\n .name {\r\n font-size: 13px;\r\n font-weight: bold;\r\n }\r\n }\r\n .textBox {\r\n font-size: 12px;\r\n color: #777;\r\n margin-bottom: 10px;\r\n }\r\n }\r\n .imgBox::-webkit-scrollbar {\r\n display: none; /* Chrome Safari */\r\n }\r\n .imgBox {\r\n display: flex;\r\n justify-content: center;\r\n width: 65%;\r\n overflow-y: scroll;\r\n max-height: 800px;\r\n .container {\r\n position: relative;\r\n border: 1px solid #f5f5f5;\r\n }\r\n\r\n img {\r\n cursor: crosshair;\r\n display: block;\r\n width: 750px;\r\n }\r\n .area {\r\n position: absolute;\r\n width: 200px;\r\n height: 200px;\r\n left: 200px;\r\n top: 300px;\r\n background: rgba(#2980b9, 0.3);\r\n border: 1px dashed #34495e;\r\n }\r\n }\r\n}\r\n.form {\r\n font-size: 12px;\r\n width: 30%;\r\n max-height: 800px;\r\n overflow-y: scroll;\r\n .form-row {\r\n display: flex;\r\n margin: 12px 0;\r\n align-items: center;\r\n .form-item {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n white-space: nowrap;\r\n margin: 0 5px;\r\n font-size: 12px;\r\n .num {\r\n width: 69px;\r\n color: #999;\r\n font-size: 12px;\r\n }\r\n .label {\r\n color: #c7c7c7;\r\n }\r\n }\r\n }\r\n .el-icon-delete {\r\n font-size: 16px;\r\n cursor: pointer;\r\n }\r\n}\r\n</style>\r\n"]}]}