From c40f4c1267dae4fcf27dbbd75ea83014fba87783 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期二, 15 七月 2025 15:28:21 +0800 Subject: [PATCH] 新增联合执法清单 --- src/views/fysp/check/components/ArbitraryPhoto.vue | 561 ++++++++++++++++++++++++------------------------------- 1 files changed, 248 insertions(+), 313 deletions(-) diff --git a/src/views/fysp/check/components/ArbitraryPhoto.vue b/src/views/fysp/check/components/ArbitraryPhoto.vue index 854296c..012ae5c 100644 --- a/src/views/fysp/check/components/ArbitraryPhoto.vue +++ b/src/views/fysp/check/components/ArbitraryPhoto.vue @@ -1,356 +1,291 @@ <template> - <div class="main"> - <div class="filters" v-if="false"> - <el-select - v-for="(key_select, index_select) of filters.keys()" - :placeholder="key_select.text" - > - <el-option - v-for="(key_option) in filters.get(key_select.key)" - :key="key_option.key" - :value="key_option.value" - :label="key_option.label" + <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)" > - </el-option> - </el-select> - </div> - <div class="btns" v-if="!readonly"> - <el-button size="small" type="primary" @click="sendSelectedImg(true)">纭畾</el-button> - <el-button size="small" type="primary" @click="sendSelectedImg(false)">鍙栨秷</el-button> - </div> + {{ item1.label }} + </div> + </el-popover> - <div class="center"> - <el-descriptions> - <el-descriptions-item label="鎬绘暟"> - <span>{{ this.imgUrlList.length }}</span> - </el-descriptions-item> - </el-descriptions> - <el-tabs v-model="activeId" type="card"> - <el-tab-pane - v-for="item in typeList" - :label="item.businesstype" - :name="item.businesstypeid" - > - </el-tab-pane> - </el-tabs> - <el-empty v-if="isEmpty" description="鏆傛棤璁板綍" /> - <div class="imgs"> - <el-image - v-for="(img, i) in typeImgMap.get(activeId)" - :class="[Boolean(img.isSelect) ? 'selected' : 'noActive', 'image']" - fit="cover" - :src="img.url" - lazy - @click="onSelect(img, i)" - /> + <div class="menu-item" @click.stop="handleMenuItem(item)" v-else> + {{ item.label }} </div> - </div> + </template> </div> + <!-- </div> --> </template> <script> -import problemApi from '@/api/fysp/problemApi.js'; import mediafileApi from '@/api/fysp/mediafileApi.js'; import { $fysp } from '@/api/index.js'; +import { enumMediaFile } from '@/enum/mediaFile.js'; + export default { props: { - filters: Map, - // 鏄惁浠ュ彧璇荤殑褰㈠紡鏌ョ湅褰撳墠椤甸潰 - readonly: { - type: Boolean, - default: false - }, subtask: { - type: Object, - efault: {} - }, - inspectionGuid: { - type: String, - default: '' - }, - defaultFile: { - type: Array, - default: () => [] + type: Object } }, data() { return { - // 鏃犳暟鎹� - isEmpty: false, - isClose: false, - isAll: false, - activeId: '', - typeList: [ - // { businesstypeid: 5, businesstype: '甯歌璁板綍' }, - // { businesstypeid: 3, businesstype: '鐩戞祴璁惧' }, - // { businesstypeid: 7, businesstype: '閾墝' }, - // { businesstypeid: 51, businesstype: '鎵╁睍绫讳竴' }, - // { businesstypeid: 52, businesstype: '鎵╁睍绫讳簩' }, - // { businesstypeid: 53, businesstype: '鎵╁睍绫讳笁' }, - // { businesstypeid: 54, businesstype: '鎵╁睍绫诲洓' }, - // { businesstypeid: 55, businesstype: '鎵╁睍绫讳簲' }, - // { businesstypeid: 56, businesstype: '鎵╁睍绫诲叚' }, - // { businesstypeid: 57, businesstype: '鎵╁睍绫讳竷' }, - // { businesstypeid: 58, businesstype: '鎵╁睍绫诲叓' }, - // { businesstypeid: 59, businesstype: '鎵╁睍绫讳節' }, - // { businesstypeid: 60, businesstype: '鎵╁睍绫诲崄' } - ], - typeImgMap: new Map(), - imgUrlList: [] + typesList: [], + typesMap: new Map(), + loading: true, + // 鍙抽敭鍥剧墖寮瑰嚭鑿滃崟鎺у埗 + showMenu: false, + menuLoading: true, + menuStyle: undefined, + allMoveActions: [], + closeContextMenuListenr: undefined, + // 鍙抽敭閫変腑鐨勫浘鐗� + selectedFileElement: undefined, + selectedFile: undefined, + selectedIndex: undefined, + selectedTypeId: undefined }; }, - watch: { - defaultFile: { - handler(newFileList, oldFileList) { - if (this.isClose) { - return; + computed: { + menuItems() { + return [ + // { label: '澶嶅埗鍒板壀璐存澘', action: 'copy' }, + { + label: '绉诲姩鍒�', + children: this.allMoveActions.filter((v) => { + return v.value != this.selectedTypeId; + }) } - }, - deep: true - }, - typeImgMap: { - handler(newMap, oldMap) { - if (this.isClose || newMap.get(this.activeId) == undefined) { - return; - } - newMap.get(this.activeId).forEach((i) => { - if (i.isSelect == true) { - return; - } - this.defaultFile.forEach((imgItem) => { - if (imgItem.url == i.url) { - i.isSelect = true; - } - }); - }); - }, - - deep: true + ]; } }, mounted() { - if (this.subtask) { - this.getAllImgList(); - } + 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: { - // 鍒濆鍖栧垰寮�濮嬮�変腑鐨勬爣绛� - initSelectedTab() { - if (this.typeList.length > 0) { - this.activeId = this.typeList[0].businesstypeid; + // 鍥剧墖鍒嗙被 + getGroupImgs() { + 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; + }) + .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(); }, - async getAllImgList() { - // for(var k of this.typeImgMap.keys()) { - // this.typeImgMap.set(k, []) - // } - await mediafileApi.getRoutineByStGuid(this.subtask.stGuid).then((res) => { - this.isEmpty = false; - let data = res.data; - if (data.length == 0) { - this.isEmpty = true; - } - for (const e of data) { - let list; - let businesstypeid = e.businesstypeid; - let businesstype = e.businesstype; - let hasThisType = false; - this.typeImgMap.forEach((v, k, m) => { - if (k == businesstypeid) { - hasThisType = true; - var isAlreadyHas = false; - if (v != undefined && v != null) { - for (let index = 0; index < v.length; index++) { - const element = v[index]; - if (element.guid == e.guid) { - isAlreadyHas = true; - break; - } - } - } - if (!isAlreadyHas) { - v.push(e); - } + 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]); } - }); - if (!hasThisType) { - this.typeImgMap.set(businesstypeid, Array.of(e)); - this.typeList.push(e); } - this.imgUrlList.push(e); - // TODO imgUrl鍏ㄥ眬閰嶇疆 - e.url = $fysp.imgUrl + e.extension1 + e.guid + '.jpg'; - // e.url = "http://47.100.191.150:9005/images/" + e.extension1 + e.guid + '.jpg' - e.isSelect = false; - } - this.initSelectedTab(); - }); - }, - getInitImgList() { - mediafileApi.getRoutineByStGuid(this.subtask.stGuid).then((res) => { - let data = res.data; - for (const e of data) { - let list; - let businesstypeid = e.businesstypeid; - let businesstype = e.businesstype; - let hasThisType = false; - this.typeImgMap.forEach((v, k, m) => { - if (k == businesstypeid) { - hasThisType = true; - if (v.length < 3) { - v.push(e); - } - } - }); - if (!hasThisType) { - this.typeImgMap.set(businesstypeid, Array.of(e)); - this.typeList.push(e); - } - this.imgUrlList.push(e); - // TODO imgUrl鍏ㄥ眬閰嶇疆 - e.url = $fysp.imgUrl + e.extension1 + e.guid + '.jpg'; - // e.url = "http://47.100.191.150:9005/images/" + e.extension1 + e.guid + '.jpg' - e.isSelect = false; - } - if (this.typeList.length > 0) { - this.activeId = this.typeList[0].businesstypeid; - } - }); - }, - onSelect(img, i) { - // if (i == 2 && !this.isAll) { - // this.getAllImgList(); - // this.isAll = true; - // } else { - // if (this.readonly) { - // return; - // } - // img.isSelect = !Boolean(img.isSelect); - // } + }) + .finally(() => (this.selectedFile.loading = false)); - if (this.readonly) { - return; - } - img.isSelect = !img.isSelect; + // 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); }, - sendSelectedImg(isOk) { - let result = []; - if (!isOk) { - this.$emit('selectByAnyPhonoEvent', result); - } - for (const item of this.imgUrlList) { - if (item.isSelect == true) { - result.push(item); - } - } - this.isClose = true; - this.$emit('selectByAnyPhonoEvent', result); + 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> -.center { - display: flex; - flex-direction: column; - align-items: center; +.container { + /* background-color: rgba(19, 211, 67, 0.514); */ + position: fixed; + left: 0; + top: 0; + height: 100vh; + width: 100vw; + z-index: 10000; } -.text { - padding: 20px; -} - -.main { - margin: 0 auto; /* 浣跨埗鍏冪礌灞呬腑 */ - height: 100%; - width: 100%; -} - -.btns { - /* height: 10%; */ -} -/* -.img_types { - margin: 0 auto; - height: 440px; - width: 900px; - flex-grow: 1; - overflow-y: hidden ; - padding: 3%; - flex-wrap: wrap; - overflow: hidden; -} */ - -.imgs { - height: 650px; - width: 90%; - min-height: 100px !important; - /* border-style:solid; - border-radius: 1px; */ - /* height: 100%; */ - flex-grow: 1 !important; - overflow-y: auto !important; - /* 鍐呭鐨勫唴杈硅窛 */ - display: flex !important; - flex-wrap: wrap !important; - /* overflow: hidden; */ -} - -.image { - height: 210px; - width: 200px; +.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; } -.active { - padding: 5px; - width: 20%; - height: 200px; - border: 0.5rem outset rgb(52, 155, 4); +.menu-item { + padding: 8px 16px; + cursor: pointer; + transition: background 0.2s; } -.selected { - padding: 5px; - color: #4abe84; - box-shadow: 0 2px 7px 0 rgba(85, 110, 97, 0.35); - border: 1px solid rgba(74, 190, 132, 1); -} - -.selected:before { - content: ''; - position: absolute; - right: 0; - bottom: 0; - border: 17px solid #4abe84; - border-top-color: transparent; - border-left-color: transparent; -} - -.selected:after { - content: ''; - width: 5px; - height: 12px; - position: absolute; - right: 6px; - bottom: 6px; - border: 2px solid #fff; - border-top-color: transparent; - border-left-color: transparent; - transform: rotate(45deg); -} - -.noActive { - padding: 5px; -} - -.blurry { - filter: blur(3px); -} -.filters { - display: flex; - padding: 5px; -} - -::v-deep .el-dialog__body { - height: 60vh; - padding: 10px calc(var(--el-dialog-padding-primary) + 10px) !important; +.menu-item:hover { + background-color: #f0f0f0; } </style> -- Gitblit v1.9.3