补充工具管理界面

This commit is contained in:
wangchengming 2025-09-02 22:55:31 +08:00
parent 3f52daa131
commit 139a23ddfa
7 changed files with 961 additions and 68 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

View File

@ -432,7 +432,7 @@ h6 {
}
.my-confirm-btn {
width: 100px;
min-width: 100px;
height: 34px;
border-radius: 4px 4px 4px 4px;
background: #1a75e6;
@ -1058,7 +1058,7 @@ h6 {
font-weight: 700;
font-size: 18px;
color: #000000;
line-height: 30px !important;
line-height: 30px !important;
}
.my_dialog .el-dialog__headerbtn {

View File

@ -1,67 +1,70 @@
<template>
<div class="flex-container">
<!-- 左侧内容 - 自动宽度 -->
<div class="left-content">
<div class="dashboard-4grid">
<div class="grid-item4" @click="handleGoMediaMap">
<img :src="mediaMap" class="custom-icon" />
<div class="grid-title grid-item4-margin">媒体地图</div>
<div class="grid-line"></div>
<div>
<div v-if="!showTool" class="flex-container">
<!-- 左侧内容 - 自动宽度 -->
<div class="left-content">
<div class="dashboard-4grid">
<div class="grid-item4" @click="handleGoMediaMap">
<img :src="mediaMap" class="custom-icon" />
<div class="grid-title grid-item4-margin">媒体地图</div>
<div class="grid-line"></div>
</div>
<div class="grid-item4" @click="handleGoSupplierManage">
<img :src="supplierManage" class="custom-icon" />
<div class="grid-title grid-item4-margin">供应商管理</div>
<div class="grid-line"></div>
</div>
<div class="grid-item4" @click="handleGoMediaLibary">
<img :src="mediaLibary" class="custom-icon" />
<div class="grid-title grid-item4-margin">媒体库管理</div>
<div class="grid-line"></div>
</div>
<div class="grid-item4" @click="handleGoOutdoorMediaMap">
<img :src="outdoorMediaMap" class="custom-icon" />
<div class="grid-title grid-item4-margin">户外媒介数据</div>
<div class="grid-line"></div>
</div>
</div>
<div class="grid-item4" @click="handleGoSupplierManage">
<img :src="supplierManage" class="custom-icon" />
<div class="grid-title grid-item4-margin">供应商管理</div>
<div class="grid-line"></div>
</div>
<div class="grid-item4" @click="handleGoMediaLibary">
<img :src="mediaLibary" class="custom-icon" />
<div class="grid-title grid-item4-margin">媒体库管理</div>
<div class="grid-line"></div>
</div>
<div class="grid-item4" @click="handleGoOutdoorMediaMap">
<img :src="outdoorMediaMap" class="custom-icon" />
<div class="grid-title grid-item4-margin">户外媒介数据</div>
<div class="grid-line"></div>
<div class="dashboard-3grid">
<div class="grid-item3 calibrationPlatform" @click="handleGoCalibrationPlatform">
<div class="grid-title">校准平台</div>
<div class="grid-sub-title"><span>去使用</span>></div>
</div>
<div class="grid-item3 PPTAnalysisTool" @click="handleGoPPTAnalysisTool">
<div class="grid-title">PPT分析工具</div>
<div class="grid-sub-title"><span>去使用</span>></div>
</div>
<div class="grid-item3 longitudeConversion" @click="handleGoLongitudeConversion">
<div class="grid-title">经纬度转换</div>
<div class="grid-sub-title"><span>去使用</span>></div>
</div>
</div>
</div>
<div class="dashboard-3grid">
<div class="grid-item3 calibrationPlatform" @click="handleGoCalibrationPlatform">
<div class="grid-title">校准平台</div>
<div class="grid-sub-title"><span>去使用</span>></div>
</div>
<div class="grid-item3 PPTAnalysisTool" @click="handleGoPPTAnalysisTool">
<div class="grid-title">PPT分析工具</div>
<div class="grid-sub-title"><span>去使用</span>></div>
</div>
<div class="grid-item3 longitudeConversion" @click="handleGoLongitudeConversion">
<div class="grid-title">经纬度转换</div>
<div class="grid-sub-title"><span>去使用</span>></div>
</div>
</div>
</div>
<!-- 右侧内容 - 固定宽度360px -->
<div class="right-content">
<div class="title-container">
<div class="title-label">
<img :src="notic_icon" class="custom-icon" /><span>系统通知</span>
<!-- 右侧内容 - 固定宽度360px -->
<div class="right-content">
<div class="title-container">
<div class="title-label">
<img :src="notic_icon" class="custom-icon" /><span>系统通知</span>
</div>
</div>
<ul class="resource-list" v-if="notices.length > 0">
<li v-for="(notice, index) in notices" :key="index" class="resource-link" @click="handleGoSupplierManage">
{{ notice.content }}
</li>
</ul>
<div class="no_result" v-else>
<img :src="no_notice" />
<div class="no_notice_title">暂无通知</div>
</div>
</div>
<ul class="resource-list" v-if="notices.length > 0">
<li v-for="(notice, index) in notices" :key="index" class="resource-link" @click="handleGoSupplierManage">
{{ notice.content }}
</li>
</ul>
<div class="no_result" v-else>
<img :src="no_notice" />
<div class="no_notice_title">暂无通知</div>
</div>
</div>
<mediaTool ref="mediaToolRef" v-if="showTool" @handleGoBack="handleGoBack" />
</div>
</template>
<script setup name="Index">
import { onMounted, ref } from 'vue';
import { nextTick, onMounted, ref } from 'vue';
import mediaMap from '@/assets/images/mediaMap.png'
import supplierManage from '@/assets/images/supplierManage.png'
import mediaLibary from '@/assets/images/mediaLibary.png'
@ -73,6 +76,11 @@ import { useBackgroundStore } from '@/store/modules/background'
import bigBackgroud from '@/assets/images/bigBackgroud.png'
const bgStore = useBackgroundStore()
import mediaTool from './mediaTool/index.vue'
const showTool = ref(false)
const mediaToolRef = ref(null)
const router = useRouter()
//
onMounted(() => {
@ -107,39 +115,51 @@ const notices = ref([
]);
//
const handleGoMediaMap = () => {
// router.push('/pitchPrice')
router.push('/mediaMap')
}
//
const handleGoSupplierManage = () => {
router.push('/supplier')
router.push('/supplier')
}
//
const handleGoMediaLibary = () => {
router.push('/mediaLibrary')
router.push('/mediaLibrary')
}
//
const handleGoOutdoorMediaMap = () => {
router.push('/outdoorMedia')
router.push('/outdoorMedia')
}
//
const handleGoCalibrationPlatform = () => {
// router.push('/pitchPrice')
showTool.value = true
nextTick(() => {
mediaToolRef.value.initTool(1)
})
}
// PPT
const handleGoPPTAnalysisTool = () => {
// router.push('/pitchPrice')
showTool.value = true
nextTick(() => {
mediaToolRef.value.initTool(2)
})
}
//
const handleGoLongitudeConversion = () => {
// router.push('/pitchPrice')
showTool.value = true
nextTick(() => {
mediaToolRef.value.initTool(3)
})
}
//
const handleGoBack = () => {
showTool.value = false
}
</script>
<style scoped lang="scss">
.flex-container {

View File

@ -39,7 +39,7 @@
<el-option v-for="dict in business" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
</el-form-item>
<el-form-item label="状态:">
<el-select v-model="queryParams.media_status" placeholder="请选择" style="min-width: 30px;"
clearable>
@ -147,13 +147,13 @@
</template>
</el-dropdown>
<el-button type="primary" class="primaryBtn" @click="handleExportExcel">导出excel</el-button>
<el-button type="primary" class="primaryBtn">媒体可视化地图</el-button>
<el-button type="primary" class="primaryBtn" @click="handleGoMediaMap">媒体可视化地图</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="mediaList" @selection-change="handleSelectionChange"
:height="unfoldFlag ? 'calc(100vh - 382px)' : 'calc(100vh - 338px)'">
:height="unfoldFlag ? 'calc(100vh - 372px)' : 'calc(100vh - 338px)'">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="媒体名称" align="left" prop="mediaName" width="320">
<template #default="scope">
@ -323,6 +323,7 @@
</template>
<script setup name="Post">
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router'
import { Search } from '@element-plus/icons-vue'
import { sysRegionListByPid } from "@/api/system/administrativeRegion"
import { sysMediaTypeListByPid } from "@/api/system/mediaType"
@ -341,6 +342,7 @@ import downFiles from './downFiles.vue';
import viewFileDialog from '@/components/ViewFile/index.vue'
import exportDialog from './exportDialog.vue';
const router = useRouter()
const bgStore = useBackgroundStore()
const { proxy } = getCurrentInstance()
const { media_form, display_form, key_words, media_schedule, media_format, sales_method, business, media_status, approval_document_status } = proxy.useDict("media_form", "display_form", "key_words", "media_schedule", "media_format", "sales_method", "business", "media_status", "approval_document_status")
@ -622,7 +624,7 @@ const handleExportExcel = () => {
const handleExportPPT = (key) => {
exportPPT.title = '导出PPT'
exportPPT.open = true
}
}
//
const handleCheckAllChange = (val) => {
checkedCities.value = []
@ -701,6 +703,10 @@ const importTemplate = () => {
// document.body.removeChild(a)
// })
}
//
const handleGoMediaMap = () => {
router.push('/mediaMap')
}
//
onMounted(() => {
bgStore.setBgImage(otherbg)

View File

@ -0,0 +1,549 @@
<template>
<div class="app-container">
<el-card class="mediaCard">
<el-row :gutter="10" class="my_row" style="padding: 0 20px;">
<el-col :span="12">
<el-form :model="queryParams" ref="queryRef" :inline="true" class="searchInputForm">
<el-form-item label="" prop="templateName">
<el-input v-model="queryParams.keyword" placeholder="请输入媒体名称/媒体编号/关键字"
:prefix-icon="Search" style="width: 400px;" />
</el-form-item>
</el-form>
</el-col>
<el-col :span="12" style="text-align: right;">
<el-dropdown placement="bottom-start">
<el-button type="primary" class="mediaMapBtn">距离{{ distanceLable }}</el-button>
<template #dropdown>
<el-dropdown-menu style="min-width: 122px;">
<template v-for="item in distanceLableArray" :key="item.value">
<el-dropdown-item
:class="activeLableIndex === item.value ? 'distanceItemActive' : 'distanceItem'"
@click="handleChangeDistance(item)">{{ item.label }}</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<div class="clearBtn">清除条件</div>
</el-col>
</el-row>
<div id="mapContainer" class="mediaMapContainer"></div>
</el-card>
</div>
</template>
<script setup name="Post">
import { onMounted, ref } from 'vue';
import { Search } from '@element-plus/icons-vue'
import AMapLoader from "@amap/amap-jsapi-loader"; //
import { useBackgroundStore } from '@/store/modules/background'
import otherbg from '@/assets/images/otherbg.png'
const bgStore = useBackgroundStore()
const { proxy } = getCurrentInstance()
//
const distanceLable = ref('请选择')
const distanceLableArray = ref([
{ label: '1公里内', value: 1 },
{ label: '2公里内', value: 2 },
{ label: '3公里内', value: 3 },
{ label: '5公里内', value: 5 }
])
const activeLableIndex = ref(null)
const data = reactive({
queryParams: {
keyword: undefined,
distance: undefined,
}
})
const { queryParams } = toRefs(data)
/** 清除条件操作 */
const resetQuery = () => {
proxy.resetForm("queryRef")
handleQuery()
}
//
const handleChangeDistance = (itemDistance) => {
queryParams.value.distance = itemDistance.value
activeLableIndex.value = itemDistance.value
distanceLable = itemDistance.label
}
// map
const mapInstance = ref(null)
const massMarks = ref(null)
// 2D/3D
const mapMode = ref('2D')
//
const isFullscreen = ref(false)
//
const loadMap = () => {
return new Promise((resolve, reject) => {
//
window._AMapSecurityConfig = {
securityJsCode: 'a157b9d8963b598f40023f5469d3e73c'
};
AMapLoader.load({
key: "f5b170e2332903225896a7290b90793a",
plugins: [],
AMapUI: {
version: "1.1",
plugins: []
}
}).then(AMap => {
//
const initialPitch = mapMode.value === '3D' ? 65 : 0;
const initialRotation = mapMode.value === '3D' ? -15 : 0;
mapInstance.value = new AMap.Map("mapContainer", {
resizeEnable: true,
zoom: 14,
center: [116.397428, 39.90923],
pitch: initialPitch, // 2D/3D
rotation: initialRotation, //
buildingAnimation: true,
expandZoomRange: true,
zooms: [3, 20],
viewMode: mapMode.value // 3D
});
//
mapInstance.value.setZoom(14);
//
addCustomControls(AMap);
// Logo
setTimeout(() => {
hideAmapLogo();
}, 1000);
//
mapInstance.value.on('render', hideAmapLogo);
//
renderMassMarks();
resolve();
}).catch(e => {
console.log(e, "高德地图加载失败");
reject(e);
});
});
}
//
const addCustomControls = (AMap) => {
//
const controlContainer = document.createElement('div');
controlContainer.className = 'custom-map-controls';
// 2D/3D
const toggle2D3DBtn = document.createElement('div');
toggle2D3DBtn.className = mapMode.value === '2D' ? 'map-control-btn map-control-3dbtn' : 'map-control-btn map-control-2dbtn';
toggle2D3DBtn.onclick = toggle2D3DMode;
//
const fullscreenBtn = document.createElement('div');
fullscreenBtn.className = isFullscreen.value === true ? 'map-control-btn map-full-screen' : 'map-control-btn map-nofull-screen';
fullscreenBtn.onclick = toggleFullscreen;
controlContainer.appendChild(toggle2D3DBtn);
controlContainer.appendChild(fullscreenBtn);
//
document.getElementById('mapContainer').appendChild(controlContainer);
}
// 2D/3D
const toggle2D3DMode = () => {
if (!mapInstance.value) return;
const currentPitch = mapInstance.value.getPitch();
if (currentPitch === 0) {
// 3D
mapInstance.value.setPitch(65);
mapInstance.value.setRotation(-15);
mapMode.value = '3D';
loadMap()
} else {
// 2D
mapInstance.value.setPitch(0);
mapInstance.value.setRotation(0);
mapMode.value = '2D';
loadMap()
}
}
//
const toggleFullscreen = () => {
const mapContainer = document.getElementById('mapContainer');
if (!document.fullscreenElement) {
//
if (mapContainer.requestFullscreen) {
mapContainer.requestFullscreen().then(() => {
isFullscreen.value = true;
const buttons = document.querySelectorAll('.map-control-btn');
buttons[1].className = 'map-control-btn map-full-screen';
}).catch(err => {
console.error('全屏模式错误:', err);
});
}
} else {
// 退
if (document.exitFullscreen) {
document.exitFullscreen().then(() => {
isFullscreen.value = false;
const buttons = document.querySelectorAll('.map-control-btn');
buttons[1].className = 'map-control-btn map-nofull-screen';
});
}
}
}
//
document.addEventListener('fullscreenchange', () => {
if (!document.fullscreenElement) {
isFullscreen.value = false;
}
});
//
const createPointStyle = (color, size, styleType) => {
const canvas = document.createElement('canvas');
canvas.width = size * 2;
canvas.height = size * 2;
const ctx = canvas.getContext('2d');
//
switch (styleType) {
case 'circle':
ctx.beginPath();
ctx.arc(size, size, size, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
break;
case 'ring':
ctx.beginPath();
ctx.arc(size, size, size, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.fill();
ctx.beginPath();
ctx.arc(size, size, size * 0.7, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
break;
case 'square':
ctx.fillStyle = color;
ctx.fillRect(0, 0, size * 2, size * 2);
break;
case 'star':
ctx.fillStyle = color;
ctx.beginPath();
for (let i = 0; i < 5; i++) {
const angle = (i * 2 * Math.PI / 5) - Math.PI / 2;
const x = size + size * Math.cos(angle);
const y = size + size * Math.sin(angle);
if (i === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
const innerAngle = angle + Math.PI / 5;
const innerX = size + size * 0.4 * Math.cos(innerAngle);
const innerY = size + size * 0.4 * Math.sin(innerAngle);
ctx.lineTo(innerX, innerY);
}
ctx.closePath();
ctx.fill();
break;
}
return canvas;
}
//
const renderMassMarks = () => {
//
if (massMarks.value) {
massMarks.value.clear();
}
//
const styles = [
// -
{
url: createPointStyle('#EC1B60', 18, 'circle').toDataURL(),
anchor: new AMap.Pixel(18, 18),
size: new AMap.Size(18, 18)
},
// -
{
url: createPointStyle('#058DED', 18, 'circle').toDataURL(),
anchor: new AMap.Pixel(18, 18),
size: new AMap.Size(18, 18)
},
// {
// url: createPointStyle('#FFA200', 18, 'circle').toDataURL(),
// anchor: new AMap.Pixel(18, 18),
// size: new AMap.Size(18, 18)
// },
// {
// url: createPointStyle('#00C272', 18, 'circle').toDataURL(),
// anchor: new AMap.Pixel(18, 18),
// size: new AMap.Size(18, 18)
// }
];
//
const points = [
{ "lnglat": [116.258446, 37.686622], "name": "景县", "style": 1 },
{ "lnglat": [113.559954, 22.124049], "name": "圣方济各堂区", "style": 1 },
{ "lnglat": [116.366794, 39.915309], "name": "西城区", "style": 1 },
{ "lnglat": [116.486409, 39.921489], "name": "朝阳区", "style": 1 },
{ "lnglat": [116.286968, 39.863642], "name": "丰台区", "style": 1 },
{ "lnglat": [116.195445, 39.914601], "name": "石景山区", "style": 1 },
{ "lnglat": [116.310316, 39.956074], "name": "海淀区", "style": 1 },
{ "lnglat": [116.105381, 39.937183], "name": "门头沟区", "style": 0 },
{ "lnglat": [116.139157, 39.735535], "name": "房山区", "style": 0 },
{ "lnglat": [116.658603, 39.902486], "name": "通州区", "style": 0 },
{ "lnglat": [116.653525, 40.128936], "name": "顺义区", "style": 0 },
{ "lnglat": [116.235906, 40.218085], "name": "昌平区", "style": 0 },
{ "lnglat": [116.338033, 39.728908], "name": "大兴区", "style": 0 },
{ "lnglat": [116.637122, 40.324272], "name": "怀柔区", "style": 0 },
{ "lnglat": [117.112335, 40.144783], "name": "平谷区", "style": 0 },
{ "lnglat": [116.843352, 40.377362], "name": "密云区", "style": 0 },
{ "lnglat": [115.985006, 40.465325], "name": "延庆区", "style": 1 },
{ "lnglat": [113.56925, 22.136546], "name": "路凼填海区", "style": 1 },
{ "lnglat": [117.195907, 39.118327], "name": "和平区", "style": 1 },
{ "lnglat": [117.226568, 39.122125], "name": "河东区", "style": 1 },
{ "lnglat": [117.217536, 39.101897], "name": "河西区", "style": 1 },
{ "lnglat": [117.164143, 39.120474], "name": "南开区", "style": 1 },
{ "lnglat": [117.201569, 39.156632], "name": "河北区", "style": 0 },
{ "lnglat": [117.163301, 39.175066], "name": "红桥区", "style": 1 },
{ "lnglat": [117.313967, 39.087764], "name": "东丽区", "style": 0 },
{ "lnglat": [117.012247, 39.139446], "name": "西青区", "style": 0 },
{ "lnglat": [117.382549, 38.989577], "name": "津南区", "style": 0 },
{ "lnglat": [117.13482, 39.225555], "name": "北辰区", "style": 0 },
{ "lnglat": [117.057959, 39.376925], "name": "武清区", "style": 0 },
{ "lnglat": [116.405285, 39.904989], "name": "北京市", "style": 0 }
]
// MassMarks
massMarks.value = new AMap.MassMarks(points, {
opacity: 1,
zIndex: 111,
cursor: 'pointer',
style: styles
});
//
massMarks.value.setMap(mapInstance.value);
//
massMarks.value.on('click', function (e) {
console.log('点击了节点', e.data)
});
}
// Logo
const hideAmapLogo = () => {
const logos = document.querySelectorAll('.amap-logo, .amap-copyright');
logos.forEach(logo => {
logo.style.display = 'none';
logo.style.visibility = 'hidden';
logo.style.opacity = '0';
});
}
//
onMounted(() => {
bgStore.setBgImage(otherbg)
loadMap()
});
</script>
<style lang="scss">
.mediaCard .el-card__body {
padding: 0px !important;
}
.mediaMapBtn {
min-width: 122px;
height: 34px;
border-radius: 4px;
background: #1a75e6;
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 16px;
text-align: left;
color: #FFFFFF;
padding: 10px;
}
.mediaMapBtn>span {
align-items: center;
display: inline-flex;
width: 100%;
}
.mediaMapBtn:hover {
background: #1a75e6;
}
.distanceItem {
position: relative;
padding-left: 40px;
padding-right: 30px;
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 16px;
color: #1E1E1E;
}
.distanceItem:hover {
font-weight: 600;
color: #1A75E6;
}
.distanceItemActive {
position: relative;
padding-left: 40px;
padding-right: 30px;
font-family: Microsoft YaHei;
font-weight: 600;
font-size: 16px;
color: #1A75E6;
}
.distanceItem:hover::before,
.distanceItemActive::before {
content: "√";
position: absolute;
left: 17px;
top: 6px;
width: 13px;
height: 10px;
font-family: Microsoft YaHei;
font-weight: 600;
color: #1A75E6;
}
.clearBtn {
display: inline-flex;
margin-left: 20px;
padding-left: 18px;
position: relative;
min-width: 82px;
height: 34px;
line-height: 34px;
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 16px;
color: #87898E;
cursor: pointer;
}
.clearBtn::before {
content: "";
position: absolute;
left: 0px;
top: 10px;
width: 14px;
height: 14px;
background-image: url('../../assets/images/iconClearWhere.png');
background-repeat: no-repeat;
}
.mediaMapContainer {
width: 100%;
height: calc(100vh - 170px);
background: #3f8bff;
}
.custom-map-controls {
position: absolute;
top: 5px;
right: 5px;
z-index: 1000;
display: flex;
flex-direction: column;
gap: 0px;
}
.map-control-btn {
cursor: pointer;
}
.map-control-2dbtn {
width: 40px;
height: 40px;
background: url('../../assets/images/icon-2D-btn.png');
}
.map-control-2dbtn:hover {
background: url('../../assets/images/icon-2D-active-btn.png');
}
.map-control-3dbtn {
width: 40px;
height: 40px;
background: url('../../assets/images/icon-3D-btn.png');
}
.map-control-3dbtn:hover {
background: url('../../assets/images/icon-3D-active-btn.png');
}
.map-nofull-screen {
width: 40px;
height: 40px;
background: url('../../assets/images/icon-full-screen.png');
}
.map-nofull-screen:hover {
background: url('../../assets/images/icon-full-screen-active.png');
}
.map-full-screen {
width: 40px;
height: 40px;
background: url('../../assets/images/icon-map-nofull-screen.png');
}
.map-full-screen:hover {
background: url('../../assets/images/icon-map-nofull-screen-active.png');
}
/* 全屏样式 */
.mapContainer:-webkit-full-screen {
width: 100% !important;
height: 100% !important;
}
.mapContainer:-moz-full-screen {
width: 100% !important;
height: 100% !important;
}
.mapContainer:-ms-fullscreen {
width: 100% !important;
height: 100% !important;
}
.mapContainer:fullscreen {
width: 100% !important;
height: 100% !important;
}
</style>

View File

@ -0,0 +1,318 @@
<template>
<div class="app-container">
<el-card>
<template #header>
<div class="card-header">
<span>{{ formTitle }}</span>
<el-icon style="float: right;cursor: pointer;" @click="handleClose">
<Close />
</el-icon>
</div>
</template>
<div class="tool-content">
<el-row :gutter="20" style="margin: 0 -10px 30px -10px;">
<el-col :span="toolType == 2 ? 12 : 24">
<div class="toolItemTitle mb20">上传文件</div>
<el-upload class="my-upload-demo" drag action="#" :http-request="requestDocUpload"
:file-list="docUploadList" :before-upload="beforeDocUpload" :on-remove="removeDocUpload">
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">
<span class="upload_tip">将文件拖曳至此区域</span> <em>点击上传</em>
</div>
<div class="el-upload__text">
支持扩展名.xlsx
</div>
</el-upload>
</el-col>
<el-col v-if="toolType == 2" :span="12">
<div class="toolItemTitle mb20">使用统计</div>
</el-col>
</el-row>
<div class="toolItemTitle mb20">任务记录</div>
<el-table v-loading="loading" :data="taskList" height="calc(100% - 422px)">
<el-table-column label="序号" align="center" width="80">
<template #default="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="文件名称" align="left" prop="fileName" min-width="180"
:show-overflow-tooltip="true" />
<el-table-column label="任务进度" align="center" prop="process" min-width="150">
<template #default="scope">
<el-progress class="myprogress" type="circle" :percentage="scope.row.process" width="40"
stroke-width="2" :color="colors" />
</template>
</el-table-column>
<el-table-column label="操作时间" align="center" prop="optionTime" width="210" />
<el-table-column label="操作" :width="160" align="center">
<template #default="scope">
<el-button v-if="scope.row.process == 0" link type="primary"
v-hasPermi="['system:pptTemplate:edit']">
<span v-if="toolType == 1">开始比对</span>
<span v-if="toolType == 2">开始分析</span>
<span v-if="toolType == 3">开始执行</span>
</el-button>
<el-button v-if="scope.row.process != 0" link type="primary"
@click="handleResultOption(scope.row)" v-hasPermi="['system:pptTemplate:remove']">
<span v-if="toolType == 1">比对结果</span>
<span v-else>导出结果</span>
</el-button>
<el-button link type="primary" v-hasPermi="['system:pptTemplate:remove']">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="queryParams.pageIndex" v-model:limit="queryParams.pageSize"
@pagination="getTaskRecordPageList" />
</div>
</el-card>
<!-- 比对结果查看对话框 -->
<el-dialog title="比对结果" v-model="open" width="1450px" class="my_dialog" align-center :destroy-on-close="true"
:close-on-click-modal="false">
<el-table v-loading="loading" :data="taskList" height="calc(100% - 422px)">
<el-table-column label="序号" align="center" width="80">
<template #default="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="类型" align="center" prop="optionTime" width="100" />
<el-table-column label="供应商" align="left" prop="fileName" min-width="180"
:show-overflow-tooltip="true" />
<el-table-column label="城市" align="center" prop="optionTime" width="100" />
<el-table-column label="媒体名称" align="center" prop="optionTime" width="100" />
<el-table-column label="购买周期" align="center" prop="optionTime" width="100" />
<el-table-column label="刊例价" align="center" prop="optionTime" width="100" />
<el-table-column label="折扣" align="center" prop="optionTime" width="100" />
<el-table-column label="单日覆盖人流量/人次" align="center" prop="optionTime" width="100" />
<el-table-column label="SOV" align="center" prop="optionTime" width="100" />
<el-table-column label="比对结果" align="center" prop="optionTime" width="100">
<template #default="scope">
<el-badge is-dot class="mybadge1"></el-badge>
<el-text class="myMedioStatus1">新增</el-text>
</template>
</el-table-column>
<el-table-column label="操作" :width="160" align="center">
<template #default="scope">
<el-button link type="primary" v-hasPermi="['system:pptTemplate:remove']">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button class="my-cancel-btn" @click="open = false"> </el-button>
<el-button class="my-confirm-btn" type="primary">存为历史报价</el-button>
<el-button class="my-confirm-btn" type="primary">导出Excel</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { onMounted, nextTick, defineEmits, ref } from 'vue'
import { Close } from '@element-plus/icons-vue'
const { proxy } = getCurrentInstance()
const emit = defineEmits(['handleGoBack']);
const formTitle = ref('')
// 1-2-PPT3-
const toolType = ref(null)
const docUploadList = ref([])
const colors = [
{ color: '#EDEDED', percentage: 0 },
{ color: '#FFC63D', percentage: 99 },
{ color: '#ADE8BD', percentage: 100 },
]
const taskList = ref([
{ fileName: 'XXXXXXXXXXXXXXXXXXXXXXXXXXX文件', process: 0, optionTime: '2024-09-23 14:36:28' },
{ fileName: 'XXXXXXXXXXXXXXXXXXXXXXXXXXX文件', process: 30, optionTime: '2024-09-23 14:36:28' },
{ fileName: 'XXXXXXXXXXXXXXXXXXXXXXXXXXX文件', process: 100, optionTime: '2024-09-23 14:36:28' },
])
const total = ref(0)
const loading = ref(false)
const data = reactive({
queryParams: {
pageIndex: 1,
pageSize: 10
}
})
const { queryParams } = toRefs(data)
const open = ref(false)
//
const getTaskRecordPageList = () => {
}
//
const requestDocUpload = (options) => {
const { file } = options
var formData = new FormData();
formData.append('file', file);
// importVehicleModelTraining(formData).then(res => {
// if (res.code == 200) {
// proxy.$modal.msgSuccess("")
// } else {
// proxy.$modal.msgError(res.msg);
// }
// })
}
//
const beforeDocUpload = (file) => {
const type = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
];
const isXlsx = type.includes(file.type);
//
if (!isXlsx) {
proxy.$modal.msgError("文件格式错误,请上传.xlsx后缀的文件。");
return false;
}
}
//
const removeDocUpload = (file, fileList) => {
docUploadList.value = docUploadList.value.filter(
item => item.name != file.name
);
}
//
const handleResultOption = (row) => {
if (toolType.value == 1) open.value = true
}
//
const handleClose = () => {
emit('handleGoBack')
}
//
const initTool = (_toolType) => {
toolType.value = _toolType
switch (_toolType) {
case 1:
formTitle.value = '校准平台'
break;
case 2:
formTitle.value = 'PPT分析工具'
break;
case 3:
formTitle.value = '经纬度转换'
break;
}
nextTick(() => {
});
}
// \
defineExpose({
initTool
});
</script>
<style lang="scss">
.tool-content {
width: 100%;
padding: 30px 420px 10px;
height: calc(100vh - 180px);
overflow-y: auto;
}
.toolItemTitle {
position: relative;
width: 100%;
height: 40px;
line-height: 40px;
font-family: Microsoft YaHei;
font-weight: 600;
font-size: 22px;
text-align: left;
color: #1E1E1E;
padding-left: 20px;
}
.toolItemTitle::before {
content: "■";
position: absolute;
left: 0px;
top: -4px;
width: 8px;
height: 8px;
border-radius: 2px;
color: #ffc63d;
}
.my-upload-demo .el-upload-dragger {
background: #0090ff05;
border: 1px dashed #1A75E6;
border-radius: 6px;
}
.my-upload-demo .upload_tip {
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 18px;
color: #000000;
}
.my-upload-demo em {
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 18px;
color: #1A75E6;
}
.my-upload-demo .el-upload__text {
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 16px;
color: #8C8C8C;
}
.myprogress .el-progress__text {
min-width: 40px !important;
}
.myprogress .el-progress__text span {
font-family: Arial;
font-weight: 700;
font-size: 14px;
color: #8F8F8F;
}
.mybadge1 .el-badge__content.is-dot {
width: 6px;
height: 6px;
background-color: #126601;
margin-right: 10px;
}
.myMedioStatus1 {
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 16px;
color: #126601;
}
.mybadge2 .el-badge__content.is-dot {
width: 6px;
height: 6px;
background-color: #E12500;
margin-right: 10px;
}
.myMedioStatus2 {
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 16px;
color: #E12500;
}
</style>

View File

@ -102,10 +102,10 @@
<el-button type="primary" class="primaryBtn">清空所选媒体</el-button>
</el-col>
</el-row>
<el-row :gutter="10" class="my_row">
<el-row :gutter="10" class="my_row" style="margin-bottom: 0;">
<el-col :span="12">
<el-table v-loading="loading" :data="outdoorMediaList" @selection-change="handleSelectionChange"
:height="unfoldFlag ? 'calc(100vh - 388px)' : 'calc(100vh - 354px)'">
:height="unfoldFlag ? 'calc(100vh - 372px)' : 'calc(100vh - 338px)'">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="实景图片" align="left" prop="mediaName" width="170">
<template #default="scope">