| | |
| | | <template> |
| | | <FYImageSelectDialog |
| | | v-bind="$attrs" |
| | | v-loading="loading" |
| | | title="场景图片" |
| | | :typeList="typesList" |
| | | :typeImgMap="typesMap" |
| | | :onContextMenu="showContextMenu" |
| | | contextMenuStr="右键点击图片修改分类" |
| | | ></FYImageSelectDialog> |
| | | <!-- <div |
| | | |
| | | @click="closeContextMenu" |
| | | @contextmenu="closeContextMenu" |
| | | class="container" |
| | | > --> |
| | | <div |
| | | v-if="showMenu && !menuLoading" |
| | | ref="menu" |
| | | :style="menuStyle" |
| | | class="context-menu" |
| | | > |
| | | <template v-for="(item, index) in menuItems" :key="index"> |
| | | <el-popover v-if="item.children" placement="right-start" trigger="hover"> |
| | | <template #reference> |
| | | <el-row justify="space-between" class="menu-item"> |
| | | <span>{{ item.label }}</span> |
| | | <el-icon><ArrowRight /></el-icon> |
| | | </el-row> |
| | | </template> |
| | | <div |
| | | v-for="(item1, index1) in item.children" |
| | | :key="index1" |
| | | class="menu-item" |
| | | @click.stop="handleMenuItem(item1)" |
| | | > |
| | | {{ item1.label }} |
| | | </div> |
| | | </el-popover> |
| | | |
| | | <div class="menu-item" @click.stop="handleMenuItem(item)" v-else> |
| | | {{ item.label }} |
| | | </div> |
| | | </template> |
| | | </div> |
| | | <!-- </div> --> |
| | | </template> |
| | | <script> |
| | | import mediafileApi from '@/api/fysp/mediafileApi.js'; |
| | | import { $fysp } from '@/api/index.js'; |
| | | import { enumMediaFile } from '@/enum/mediaFile.js'; |
| | | |
| | | export default { |
| | | props: { |
| | | subtask: { |
| | | type: Object, |
| | | efault: {} |
| | | type: Object |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | // 无数据 |
| | | typesList: [], |
| | | typesMap: new Map() |
| | | typesMap: new Map(), |
| | | loading: true, |
| | | // 右键图片弹出菜单控制 |
| | | showMenu: false, |
| | | menuLoading: true, |
| | | menuStyle: undefined, |
| | | allMoveActions: [], |
| | | closeContextMenuListenr: undefined, |
| | | // 右键选中的图片 |
| | | selectedFileElement: undefined, |
| | | selectedFile: undefined, |
| | | selectedIndex: undefined, |
| | | selectedTypeId: undefined |
| | | }; |
| | | }, |
| | | computed: { |
| | | menuItems() { |
| | | return [ |
| | | // { label: '复制到剪贴板', action: 'copy' }, |
| | | { |
| | | label: '移动到', |
| | | children: this.allMoveActions.filter((v) => { |
| | | return v.value != this.selectedTypeId; |
| | | }) |
| | | } |
| | | ]; |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.getGroupImgs(); |
| | | this.closeContextMenuListenr = (event) => { |
| | | if ( |
| | | this.$refs.menu && |
| | | !this.$refs.menu.contains(event.target) && |
| | | this.showMenu |
| | | ) { |
| | | // 如果点击不是在菜单内部且菜单是可见的 |
| | | this.showMenu = false; // 隐藏菜单 |
| | | } |
| | | }; |
| | | document.addEventListener('click', this.closeContextMenuListenr); |
| | | |
| | | this.initMenuItems(); |
| | | }, |
| | | unmounted() { |
| | | document.removeEventListener('click', this.closeContextMenuListenr); |
| | | }, |
| | | methods: { |
| | | // 图片分类 |
| | | getGroupImgs() { |
| | | mediafileApi.getRoutineByStGuid(this.subtask.stGuid).then((res) => { |
| | | let typeList = []; |
| | | let typeMap = new Map(); |
| | | const data = res.data; |
| | | for (const e of data) { |
| | | let img = { |
| | | url: $fysp.imgUrl + e.extension1 + e.guid + '.jpg' |
| | | }; |
| | | const businesstype = e.businesstype; |
| | | const businesstypeid = e.businesstypeid; |
| | | if ( |
| | | typeList.find((item) => item.typeName == businesstype) != undefined |
| | | ) { |
| | | typeMap.get(businesstypeid).push(img); |
| | | } else { |
| | | typeList.push({ |
| | | typeId: businesstypeid, |
| | | typeName: businesstype |
| | | }); |
| | | typeMap.set(businesstypeid, [img]); |
| | | mediafileApi |
| | | .getRoutineByStGuid(this.subtask.stGuid) |
| | | .then((res) => { |
| | | this.loading = true; |
| | | let typeList = []; |
| | | let typeMap = new Map(); |
| | | const data = res.data; |
| | | for (const e of data) { |
| | | let img = { |
| | | url: $fysp.imgUrl + e.extension1 + e.guid + '.jpg', |
| | | data: e |
| | | }; |
| | | const businesstype = e.businesstype; |
| | | const businesstypeid = e.businesstypeid; |
| | | if ( |
| | | typeList.find((item) => item.typeId == businesstypeid) != |
| | | undefined |
| | | ) { |
| | | typeMap.get(businesstypeid).push(img); |
| | | } else { |
| | | typeList.push({ |
| | | typeId: businesstypeid, |
| | | typeName: businesstype |
| | | }); |
| | | typeMap.set(businesstypeid, [img]); |
| | | } |
| | | } |
| | | } |
| | | this.typesList = typeList; |
| | | this.typesMap = typeMap; |
| | | }); |
| | | this.typesList = typeList; |
| | | this.typesMap = typeMap; |
| | | }) |
| | | .finally(() => (this.loading = false)); |
| | | }, |
| | | // 图片右键点击事件 |
| | | showContextMenu(event, typeId, index) { |
| | | this.showMenu = true; |
| | | this.menuStyle = { |
| | | left: `${event.clientX}px`, |
| | | top: `${event.clientY}px` |
| | | }; |
| | | this.selectedFileElement = event.target; |
| | | this.selectedTypeId = typeId; |
| | | this.selectedIndex = index; |
| | | this.selectedFile = this.typesMap.get(typeId)[index]; |
| | | }, |
| | | closeContextMenu() { |
| | | this.showMenu = false; |
| | | }, |
| | | handleMenuItem(item) { |
| | | switch (item.action) { |
| | | case 'copy': |
| | | this.drawImageToCanvas(); |
| | | break; |
| | | case 'move': |
| | | this.selectedFile.data.businesstypeid = item.value; |
| | | this.selectedFile.data.businesstype = item.label; |
| | | this.changeMediaFileType(this.selectedFile); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | this.closeContextMenu(); |
| | | }, |
| | | changeMediaFileType() { |
| | | this.selectedFile.loading = true; |
| | | const file = this.selectedFile.data; |
| | | return mediafileApi |
| | | .updateMediaFile(file) |
| | | .then((res) => { |
| | | if (res == 1) { |
| | | const m = this.typesMap |
| | | .get(this.selectedTypeId) |
| | | .splice(this.selectedIndex, 1); |
| | | if (!this.typesMap.has(file.businesstypeid)) { |
| | | this.typesList.push({ |
| | | typeId: file.businesstypeid, |
| | | typeName: file.businesstype |
| | | }); |
| | | this.typesMap.set(file.businesstypeid, m); |
| | | } else { |
| | | this.typesMap.get(file.businesstypeid).push(m[0]); |
| | | } |
| | | } |
| | | }) |
| | | .finally(() => (this.selectedFile.loading = false)); |
| | | |
| | | // setTimeout(() => { |
| | | // const m = this.typesMap |
| | | // .get(this.selectedTypeId) |
| | | // .splice(this.selectedIndex, 1); |
| | | // if (!this.typesMap.has(file.businesstypeid)) { |
| | | // this.typesList.push({ |
| | | // typeId: file.businesstypeid, |
| | | // typeName: file.businesstype |
| | | // }); |
| | | // this.typesMap.set(file.businesstypeid, m); |
| | | // } else { |
| | | // this.typesMap.get(file.businesstypeid).push(m[0]); |
| | | // } |
| | | // this.selectedFile.loading = false; |
| | | // }, 2000); |
| | | }, |
| | | drawImageToCanvas() { |
| | | const canvas = document.createElement('canvas'); |
| | | const ctx = canvas.getContext('2d'); |
| | | const img = this.selectedFileElement; // 获取DOM引用 |
| | | // img.crossOrigin = 'Anonymous'; |
| | | canvas.width = img.naturalWidth; |
| | | canvas.height = img.naturalHeight; |
| | | ctx.drawImage(img, 0, 0, canvas.width, canvas.height); |
| | | // this.copyCanvasToClipboard(canvas); |
| | | const dataUrl = canvas.toDataURL('image/png'); // 可以选择其他格式如'image/jpeg' |
| | | // 创建一个临时的textarea元素来复制文本 |
| | | const tempTextArea = document.createElement('textarea'); |
| | | document.body.appendChild(tempTextArea); |
| | | tempTextArea.value = dataUrl; |
| | | tempTextArea.select(); |
| | | document.execCommand('copy'); |
| | | document.body.removeChild(tempTextArea); |
| | | }, |
| | | copyCanvasToClipboard(canvas) { |
| | | canvas.toBlob((blob) => { |
| | | const item = new ClipboardItem({ 'image/png': blob }); // 你可以根据需要改变格式,如 "image/jpeg" |
| | | navigator.clipboard.write([item]).then( |
| | | () => { |
| | | console.log('Image copied to clipboard'); |
| | | }, |
| | | (err) => { |
| | | console.error('Could not copy image: ', err); |
| | | } |
| | | ); |
| | | }, 'image/png'); // 同样,这里也可以指定其他格式,如 'image/jpeg' |
| | | }, |
| | | // 初始化场景图片的类型菜单 |
| | | initMenuItems() { |
| | | this.menuLoading = true; |
| | | const sceneTypeId = this.subtask.sceneTypeId; |
| | | enumMediaFile(sceneTypeId, false) |
| | | .then((res) => { |
| | | this.allMoveActions = res.map((v) => { |
| | | return { |
| | | action: 'move', |
| | | label: v.label, |
| | | value: v.value |
| | | }; |
| | | }); |
| | | }) |
| | | .finally(() => (this.menuLoading = false)); |
| | | } |
| | | } |
| | | }; |
| | | </script> |
| | | <style scoped></style> |
| | | <style scoped> |
| | | .container { |
| | | /* background-color: rgba(19, 211, 67, 0.514); */ |
| | | position: fixed; |
| | | left: 0; |
| | | top: 0; |
| | | height: 100vh; |
| | | width: 100vw; |
| | | z-index: 10000; |
| | | } |
| | | .context-menu { |
| | | position: fixed; |
| | | background: white; |
| | | border-radius: 4px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| | | min-width: 200px; |
| | | z-index: 10001; |
| | | } |
| | | |
| | | .menu-item { |
| | | padding: 8px 16px; |
| | | cursor: pointer; |
| | | transition: background 0.2s; |
| | | } |
| | | |
| | | .menu-item:hover { |
| | | background-color: #f0f0f0; |
| | | } |
| | | </style> |