提交
This commit is contained in:
parent
5a04faae5f
commit
21f87755cd
|
|
@ -87,7 +87,8 @@ export function exportMediaExcel(query) {
|
|||
url: '/media/export/dynamic/excel',
|
||||
method: 'post',
|
||||
data: query,
|
||||
responseType: 'blob'
|
||||
responseType: 'blob',
|
||||
timeout: 3600000, // 3600秒 = 60分钟,根据文件大小调整
|
||||
})
|
||||
}
|
||||
// 获取导出PPT字段
|
||||
|
|
|
|||
|
|
@ -493,8 +493,8 @@ h6 {
|
|||
}
|
||||
|
||||
.myImg_popover {
|
||||
width: 476px !important;
|
||||
height: 284px !important;
|
||||
width: 414px !important;
|
||||
// height: 314px !important;
|
||||
border-radius: 6px !important;
|
||||
padding: 8px !important;
|
||||
background: #d1e3f9cc !important;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const service = axios.create({
|
|||
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
// 超时
|
||||
timeout: 10000
|
||||
timeout: 1800000
|
||||
})
|
||||
|
||||
// request拦截器
|
||||
|
|
|
|||
|
|
@ -1319,6 +1319,8 @@ const exportForm = ref({
|
|||
hasFiles: false
|
||||
})
|
||||
|
||||
const filterPriceFieldArr = ref([])
|
||||
|
||||
// 基础字段是否全选
|
||||
const baseFieldCheckAll = ref(false)
|
||||
const baseFieldIsIndeterminate = ref(false)
|
||||
|
|
@ -1457,11 +1459,55 @@ const handleClick = (tab, event) => {
|
|||
// 执行导出
|
||||
const handleSubmitExport = () => {
|
||||
exportForm.value.exportBaseFields = checkedBaseFields
|
||||
exportForm.value.mediaTypeExport = exportForm.value.mediaTypeExport.filter(item => item.exportPriceFields.length > 0)
|
||||
filterPriceFieldArr.value = []
|
||||
exportForm.value.mediaTypeExport.forEach(item => {
|
||||
// 0'优势报价', 1'门禁', 2'候车厅', 3'道闸', 4'地铁', 5'高铁', 6'写字楼', 7'车库灯箱'
|
||||
if (item.type == 0) {
|
||||
const result = ysPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
if (item.type == 1) {
|
||||
const result = mjPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
if (item.type == 2) {
|
||||
const result = hctPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
if (item.type == 3) {
|
||||
const result = dzPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
if (item.type == 4) {
|
||||
const result = dtPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
if (item.type == 5) {
|
||||
const result = gtPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
if (item.type == 6) {
|
||||
const result = xzlPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
if (item.type == 7) {
|
||||
const result = ckdxPriceFild.value.filter(field => item.exportPriceFields.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
filterPriceFieldArr.value.push({ type: item.type, exportPriceFields: propertyPaths })
|
||||
}
|
||||
})
|
||||
exportForm.value.mediaTypeExport = filterPriceFieldArr.value.filter(item => item.exportPriceFields.length > 0)
|
||||
|
||||
proxy.$modal.loading(`正在执行导出,请耐心等待...`)
|
||||
|
||||
exportMediaExcel(exportForm.value).then(res => {
|
||||
exportMediaExcel(exportForm.value).then(res => {
|
||||
proxy.$modal.closeLoading()
|
||||
const downLoadName = '媒体信息_' + getCurrentTime() + '.xlsx'
|
||||
// 通过a标签打开新页面下载文件
|
||||
|
|
@ -1500,6 +1546,9 @@ const getMediaExcelBaseField = () => {
|
|||
} else {
|
||||
baseFields.value = ysBaseFild.value
|
||||
}
|
||||
} else {
|
||||
// 默认导出全部时的字段
|
||||
baseFields.value = ysBaseFild.value
|
||||
}
|
||||
}
|
||||
// 获取报价信息字段
|
||||
|
|
@ -1522,6 +1571,12 @@ const getMediaExcelPriceField = () => {
|
|||
priceFields.value = ysPriceFild.value
|
||||
handleCheckPriceField(0)
|
||||
}
|
||||
} else {
|
||||
// 默认导出全部时的报价
|
||||
ToolOptions.value = ['优势报价', '门禁', '候车厅', '道闸', '地铁', '高铁', '写字楼', '车库灯箱']
|
||||
activeIndex.value = 0
|
||||
priceFields.value = ysPriceFild.value
|
||||
handleCheckPriceField(0)
|
||||
}
|
||||
}
|
||||
// 判断报价信息是否存在指定类型数据
|
||||
|
|
|
|||
|
|
@ -157,9 +157,7 @@ const pptFields = ref([
|
|||
propertyPath: "invalidReason"
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
|
||||
|
||||
// 已选择的ppt字段
|
||||
const checkedPPTFields = ref([])
|
||||
|
||||
|
|
@ -189,8 +187,10 @@ const handleCheckedPPTFieldChange = (value) => {
|
|||
}
|
||||
|
||||
// 导出ppt实现代码
|
||||
const handleSubmitExportPPT = () => {
|
||||
exportForm.value.exportFields = checkedPPTFields
|
||||
const handleSubmitExportPPT = () => {
|
||||
const result = pptFields.value.filter(field => checkedPPTFields.value.includes(field.propertyPath));
|
||||
const propertyPaths = result.map(res => res.propertyPath);
|
||||
exportForm.value.exportFields = propertyPaths
|
||||
|
||||
proxy.$modal.loading(`正在执行导出,请耐心等待...`)
|
||||
exportMediaPPT(exportForm.value).then(res => {
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ const initHistoryCharLine = () => {
|
|||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
left: '5%',
|
||||
right: '3%', // 右侧留更多空间显示长数值
|
||||
top: '14%',
|
||||
bottom: '10%',
|
||||
|
|
@ -301,9 +301,10 @@ const initHistoryCharLine = () => {
|
|||
}
|
||||
]
|
||||
})
|
||||
// window.addEventListener("resize", () => {
|
||||
// _historyChar.value.resize()
|
||||
// })
|
||||
window.addEventListener("resize", () => {
|
||||
// _historyChar.value.resize()
|
||||
initHistoryCharLine()
|
||||
})
|
||||
}
|
||||
// 柱状图
|
||||
const initHistoryCharBar = () => {
|
||||
|
|
@ -322,7 +323,7 @@ const initHistoryCharBar = () => {
|
|||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
left: '5%',
|
||||
right: '3%', // 右侧留更多空间显示长数值
|
||||
top: '14%',
|
||||
bottom: '10%',
|
||||
|
|
@ -399,9 +400,10 @@ const initHistoryCharBar = () => {
|
|||
}
|
||||
}]
|
||||
})
|
||||
// window.addEventListener("resize", () => {
|
||||
// _historyChar.value.resize()
|
||||
// })
|
||||
window.addEventListener("resize", () => {
|
||||
// _historyChar.value.resize()
|
||||
initHistoryCharBar()
|
||||
})
|
||||
}
|
||||
const handleChangeMediaType = (val) => {
|
||||
getMediaPriceList()
|
||||
|
|
@ -428,18 +430,21 @@ const getMediaPriceList = () => {
|
|||
xData.value = []
|
||||
yData.value = []
|
||||
historyList.value.forEach(item => {
|
||||
xData.value.push(item.supplier)
|
||||
xData.value.push(item.supplier ? item.supplier : '')
|
||||
let itemYDate = null;
|
||||
const convertIntTotalRegularPrice = parseFloat(item.totalRegularPrice.replace(/,/g, ''))
|
||||
if (readonly.value) itemYDate = (convertIntTotalRegularPrice / item.buyCycle).toFixed(2)
|
||||
else {
|
||||
// 判断是否纯数字
|
||||
const convertIntValue = safeParseInt(item.buyCycle)
|
||||
if (typeof convertIntValue === 'number' && Number.isFinite(convertIntValue)) {
|
||||
itemYDate = (convertIntTotalRegularPrice / (item.buyCycle * 7)).toFixed(2)
|
||||
} else {
|
||||
const repliceValue = parseInt(item.buyCycle.replace('个月', '').replace('月', ''))
|
||||
itemYDate = (convertIntTotalRegularPrice / (repliceValue * 31)).toFixed(2)
|
||||
console.log('item.totalRegularPrice', item.totalRegularPrice)
|
||||
if (item.totalRegularPrice) {
|
||||
const convertIntTotalRegularPrice = parseFloat(item.totalRegularPrice.replace(/,/g, ''))
|
||||
if (readonly.value) itemYDate = (convertIntTotalRegularPrice / item.buyCycle).toFixed(2)
|
||||
else {
|
||||
// 判断是否纯数字
|
||||
const convertIntValue = safeParseInt(item.buyCycle)
|
||||
if (typeof convertIntValue === 'number' && Number.isFinite(convertIntValue)) {
|
||||
itemYDate = (convertIntTotalRegularPrice / (item.buyCycle * 7)).toFixed(2)
|
||||
} else {
|
||||
const repliceValue = parseInt(item.buyCycle.replace('个月', '').replace('月', ''))
|
||||
itemYDate = (convertIntTotalRegularPrice / (repliceValue * 31)).toFixed(2)
|
||||
}
|
||||
}
|
||||
}
|
||||
yData.value.push(itemYDate)
|
||||
|
|
|
|||
|
|
@ -180,16 +180,19 @@
|
|||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="媒体名称" align="left" prop="mediaName" width="320">
|
||||
<template #default="scope">
|
||||
<el-popover popper-class="myImg_popover" placement="right-start">
|
||||
<img v-if="scope.row.mediaFileList.length > 0"
|
||||
:src="baseUrl + scope.row.mediaFileList[0].fileName" />
|
||||
<el-popover popper-class="myImg_popover" placement="right-start"
|
||||
:open-delay="300" @show="loadMediaImage(scope.row)" @hide="clearMediaImage(scope.row)">
|
||||
<div v-if="scope.row.imageLoading" class="img-loading">加载中...</div>
|
||||
<img v-else-if="scope.row.imageUrl" :src="scope.row.imageUrl" class="media-preview-img"
|
||||
@error="scope.row.imageUrl = ''" />
|
||||
<div v-else class="img-empty">暂无图片</div>
|
||||
|
||||
<template #reference>
|
||||
<span class="mediaNameLabel" @click="handleOpenDetail(scope.row)">{{
|
||||
scope.row.mediaName
|
||||
}}</span>
|
||||
}}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="媒体编号" align="left" prop="mediaCode" width="180" />
|
||||
|
|
@ -280,7 +283,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script setup name="Post">
|
||||
import { onMounted, nextTick, ref } from 'vue';
|
||||
import { onMounted, nextTick, ref, reactive, toRefs } from 'vue';
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
|
|
@ -315,8 +318,30 @@ const router = useRouter()
|
|||
const bgStore = useBackgroundStore()
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { media_status } = proxy.useDict("media_status")
|
||||
|
||||
const baseUrl = import.meta.env.VITE_APP_BASE_API
|
||||
// #################### 新增:手动实现防抖函数 ####################
|
||||
const debounce = (fn, delay) => {
|
||||
let timer = null;
|
||||
return function (...args) {
|
||||
// 清除之前的定时器
|
||||
if (timer) clearTimeout(timer);
|
||||
// 重新设置定时器
|
||||
timer = setTimeout(() => {
|
||||
fn.apply(this, args);
|
||||
timer = null;
|
||||
}, delay);
|
||||
};
|
||||
};
|
||||
// ################################################################
|
||||
// 新增:控制图片加载的并发和状态
|
||||
const imageLoadingMap = ref(new Map()); // 记录正在加载的图片请求
|
||||
const MAX_CONCURRENT = 1; // 最大并发图片请求数
|
||||
|
||||
// 防抖函数:限制加载频率(300ms内只触发一次)
|
||||
const debouncedLoadImage = debounce((row) => {
|
||||
loadImageAsync(row);
|
||||
}, 300);
|
||||
|
||||
// 省、市、县、镇数据
|
||||
const province = ref([])
|
||||
const city = ref([])
|
||||
|
|
@ -391,6 +416,57 @@ const tableRef = ref(null)
|
|||
// 添加一个标志位来区分是用户操作还是程序设置
|
||||
const isSettingSelection = ref(false)
|
||||
|
||||
// 加载图片(异步+并发控制)
|
||||
const loadMediaImage = (row) => {
|
||||
// 已加载/正在加载,直接返回
|
||||
if (row.imageUrl || imageLoadingMap.value.has(row.id)) return;
|
||||
|
||||
// 控制并发数
|
||||
if (imageLoadingMap.value.size >= MAX_CONCURRENT) {
|
||||
// 等待当前请求完成后再加载
|
||||
setTimeout(() => loadMediaImage(row), 100);
|
||||
return;
|
||||
}
|
||||
|
||||
row.imageLoading = true;
|
||||
debouncedLoadImage(row);
|
||||
};
|
||||
|
||||
// 异步加载图片(核心逻辑)
|
||||
const loadImageAsync = async (row) => {
|
||||
if (!row.mediaFileList || row.mediaFileList.length === 0) {
|
||||
row.imageLoading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const imageUrl = baseUrl + row.mediaFileList[0].fileName;
|
||||
imageLoadingMap.value.set(row.id, true);
|
||||
|
||||
try {
|
||||
// 预加载图片,验证有效性
|
||||
await new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.src = imageUrl;
|
||||
img.onload = resolve;
|
||||
img.onerror = reject;
|
||||
});
|
||||
// 图片加载成功,赋值给row(避免重复请求)
|
||||
row.imageUrl = imageUrl;
|
||||
} catch (error) {
|
||||
row.imageUrl = ''; // 加载失败标记
|
||||
console.error('图片加载失败:', error);
|
||||
} finally {
|
||||
row.imageLoading = false;
|
||||
imageLoadingMap.value.delete(row.id);
|
||||
}
|
||||
};
|
||||
|
||||
// 隐藏时清空图片(释放内存)
|
||||
const clearMediaImage = (row) => {
|
||||
// 可选:保留已加载的图片(下次直接显示),或清空
|
||||
// row.imageUrl = ''; // 若需要每次重新加载,解开注释
|
||||
};
|
||||
|
||||
// 获取PPT模板
|
||||
const getpptTemplatePageList = () => {
|
||||
pptTemplatePage(queryParams.value).then(res => {
|
||||
|
|
@ -491,8 +567,10 @@ const handleFlod = () => {
|
|||
unfoldFlag.value = !unfoldFlag.value
|
||||
}
|
||||
/** 查询媒体信息列表 */
|
||||
|
||||
// 初始化时给每行添加图片相关状态
|
||||
const getMediaPageList = () => {
|
||||
loading.value = true
|
||||
loading.value = true;
|
||||
mediaPageList(queryParams.value).then(res => {
|
||||
res.data.rows.forEach(element => {
|
||||
element.currentImageSrc = defaultImageSrc.value;
|
||||
|
|
@ -500,17 +578,20 @@ const getMediaPageList = () => {
|
|||
element.currentMediaChainSrc = defaultViewFileSrc.value;
|
||||
element.currentQualificationFileSrc = defaultViewFileSrc.value;
|
||||
element.currentStampedPublicationSrc = defaultViewFileSrc.value;
|
||||
// 新增:图片加载相关状态
|
||||
element.imageUrl = ''; // 存储加载后的图片地址
|
||||
element.imageLoading = false; // 加载状态
|
||||
});
|
||||
mediaList.value = res.data.rows
|
||||
total.value = res.data.total
|
||||
loading.value = false
|
||||
|
||||
// 数据加载完成后,设置选中状态
|
||||
nextTick(() => {
|
||||
setTableSelection()
|
||||
})
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1
|
||||
|
|
@ -709,10 +790,10 @@ const handleViewPhoto = (_fileType, row) => {
|
|||
}
|
||||
/** 导出Excel按钮操作 */
|
||||
const handleExportExcel = () => {
|
||||
if (multipleChoseArr.value.length == 0) {
|
||||
proxy.$modal.msgWarning("请选择要导出的媒体!!!")
|
||||
return false
|
||||
}
|
||||
// if (multipleChoseArr.value.length == 0) {
|
||||
// proxy.$modal.msgWarning("请选择要导出的媒体!!!")
|
||||
// return false
|
||||
// }
|
||||
const mediaIds = multipleChoseArr.value.map(item => item.id);
|
||||
const uniqueDeptIds = [...new Set(multipleChoseArr.value.map(item => item.dataScopeDeptId))];
|
||||
exportDialogRef.value.initExportExcel(mediaIds, uniqueDeptIds)
|
||||
|
|
@ -745,6 +826,30 @@ onMounted(() => {
|
|||
});
|
||||
</script>
|
||||
<style lang="scss">
|
||||
// 新增图片预览相关样式
|
||||
.myImg_popover {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.media-preview-img {
|
||||
max-width: 400px;
|
||||
max-height: 300px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.img-loading,
|
||||
.img-empty {
|
||||
width: 400px;
|
||||
height: 300px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mediaNameLabel {
|
||||
font-family: Microsoft YaHei;
|
||||
font-weight: 400;
|
||||
|
|
|
|||
|
|
@ -949,6 +949,10 @@ const getbusinessAreaList = (val) => {
|
|||
busTradingAreaPage(_params).then(res => {
|
||||
if (res.code == 200) {
|
||||
businessAreaList.value = res.data.list
|
||||
if (res.data.list.length == 0) {
|
||||
ruleForm.value.businessDistrictId = null
|
||||
ruleForm.value.businessDistrictName = null
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -1001,7 +1005,7 @@ const handleSubmit = () => {
|
|||
}
|
||||
ruleForm.value.mediaFile = mediaFile.value
|
||||
|
||||
ruleForm.value.displayForm = ruleForm.value.displayForm ? ruleForm.value.displayForm : -1
|
||||
// ruleForm.value.displayForm = ruleForm.value.displayForm ? ruleForm.value.displayForm : -1
|
||||
|
||||
if (ruleForm.value.id != undefined) {
|
||||
updateMedia(ruleForm.value).then(response => {
|
||||
|
|
@ -1031,100 +1035,89 @@ const getSupplierInfo = () => {
|
|||
// 获取媒体详情
|
||||
const getMediaInfo = () => {
|
||||
mediaDetail({ mediaId: ruleForm.value.id }).then(res => {
|
||||
ruleForm.value = res.data
|
||||
mediaFile.value = res.data.mediaFile
|
||||
mediaPrice.value = res.data.mediaPrices
|
||||
ruleForm.value.mediaCity = ruleForm.value.provinceName + '/' + ruleForm.value.cityName + '/' + ruleForm.value.areaName + '/' + ruleForm.value.townName
|
||||
if (ruleForm.value.mapY && ruleForm.value.mapX) latVal.value = ruleForm.value.mapY + ',' + ruleForm.value.mapX
|
||||
if (ruleForm.value.belongSupplierId) getSupplierInfo()
|
||||
handleChangeDept(res.data.dataScopeDeptId)
|
||||
if (ruleForm.value.mediaFile && ruleForm.value.mediaFile.length > 0) {
|
||||
if (approvalDocumentRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 1)
|
||||
approvalDocumentRef.value.setFileInfo(fileList)
|
||||
if (res.data.mediaType) getMediaTypeTwo2(res.data.mediaType)
|
||||
if (res.data.mediaCategory) getMediaTypeThree2(res.data.mediaCategory)
|
||||
|
||||
if (res.data.provinceCode) getCityList2(res.data.provinceCode)
|
||||
if (res.data.cityCode) getCountyList2(res.data.cityCode)
|
||||
if (res.data.areaCode) getTownList2(res.data.areaCode)
|
||||
|
||||
getbusinessAreaList()
|
||||
|
||||
setTimeout(() => {
|
||||
// 延迟500ms后刷新表单
|
||||
ruleForm.value = res.data
|
||||
mediaFile.value = res.data.mediaFile
|
||||
mediaPrice.value = res.data.mediaPrices
|
||||
ruleForm.value.mediaCity = ruleForm.value.provinceName + '/' + ruleForm.value.cityName + '/' + ruleForm.value.areaName + '/' + ruleForm.value.townName
|
||||
if (ruleForm.value.mapY && ruleForm.value.mapX) latVal.value = ruleForm.value.mapY + ',' + ruleForm.value.mapX
|
||||
if (ruleForm.value.belongSupplierId) getSupplierInfo()
|
||||
handleChangeDept(res.data.dataScopeDeptId)
|
||||
}, 500);
|
||||
|
||||
setTimeout(() => {
|
||||
if (ruleForm.value.mediaFile && ruleForm.value.mediaFile.length > 0) {
|
||||
if (approvalDocumentRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 1)
|
||||
approvalDocumentRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (exclusiveLicenseFileRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 2)
|
||||
exclusiveLicenseFileRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaLicenseFileRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 3)
|
||||
mediaLicenseFileRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaOwnershipRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 4)
|
||||
mediaOwnershipRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (onceMediaPhotoRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 5)
|
||||
onceMediaPhotoRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaPicRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 6)
|
||||
mediaPicRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaVideoRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 7)
|
||||
mediaVideoRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (stampedPublicationRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 8)
|
||||
stampedPublicationRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (qualificationFileRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 9)
|
||||
qualificationFileRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaChainRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 10)
|
||||
mediaChainRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (journalCataloguePhotoRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 11)
|
||||
journalCataloguePhotoRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mRProductionRequirementsRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 12)
|
||||
mRProductionRequirementsRef.value.setFileInfo(fileList)
|
||||
}
|
||||
}
|
||||
if (exclusiveLicenseFileRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 2)
|
||||
exclusiveLicenseFileRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaLicenseFileRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 3)
|
||||
mediaLicenseFileRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaOwnershipRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 4)
|
||||
mediaOwnershipRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (onceMediaPhotoRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 5)
|
||||
onceMediaPhotoRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaPicRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 6)
|
||||
mediaPicRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaVideoRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 7)
|
||||
mediaVideoRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (stampedPublicationRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 8)
|
||||
stampedPublicationRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (qualificationFileRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 9)
|
||||
qualificationFileRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mediaChainRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 10)
|
||||
mediaChainRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (journalCataloguePhotoRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 11)
|
||||
journalCataloguePhotoRef.value.setFileInfo(fileList)
|
||||
}
|
||||
if (mRProductionRequirementsRef.value) {
|
||||
const fileList = ruleForm.value.mediaFile.filter(item => item.fileType == 12)
|
||||
mRProductionRequirementsRef.value.setFileInfo(fileList)
|
||||
}
|
||||
}
|
||||
handleResponse(res)
|
||||
}, 500);
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新联动数据
|
||||
async function handleResponse(response) {
|
||||
const promises = [];
|
||||
|
||||
if (response.data.provinceCode) {
|
||||
promises.push(getCityList2(response.data.provinceCode));
|
||||
}
|
||||
if (response.data.cityCode) {
|
||||
promises.push(getCountyList2(response.data.cityCode));
|
||||
}
|
||||
if (response.data.areaCode) {
|
||||
promises.push(getTownList2(response.data.areaCode));
|
||||
}
|
||||
|
||||
if (response.data.mediaType) {
|
||||
promises.push(getMediaTypeTwo2(response.data.mediaType));
|
||||
}
|
||||
if (response.data.mediaCategory) {
|
||||
promises.push(getMediaTypeThree2(response.data.mediaCategory));
|
||||
}
|
||||
|
||||
getbusinessAreaList()
|
||||
|
||||
// 等待所有请求完成
|
||||
await Promise.all(promises);
|
||||
}
|
||||
// 初始化
|
||||
const initForm = (_formTitle, _ruleForm) => {
|
||||
showClose.value = true
|
||||
formTitle.value = _formTitle
|
||||
ruleForm.value = _ruleForm
|
||||
ruleForm.value.mediaCity = ruleForm.value.provinceName + '/' + ruleForm.value.cityName + '/' + ruleForm.value.areaName + '/' + ruleForm.value.townName
|
||||
if (ruleForm.value.mapY && ruleForm.value.mapX) latVal.value = ruleForm.value.mapY + ',' + ruleForm.value.mapX
|
||||
// ruleForm.value = _ruleForm
|
||||
ruleForm.value.id = _ruleForm.id
|
||||
ruleForm.value.mediaCity = _ruleForm.provinceName + '/' + _ruleForm.cityName + '/' + _ruleForm.areaName + '/' + _ruleForm.townName
|
||||
if (_ruleForm.mapY && _ruleForm.mapX) latVal.value = _ruleForm.mapY + ',' + _ruleForm.mapX
|
||||
getDepList()
|
||||
getMediaTypeOne()
|
||||
getProvinceList()
|
||||
|
|
@ -1135,9 +1128,10 @@ const initForm = (_formTitle, _ruleForm) => {
|
|||
const linkInitForm = (_formTitle, _ruleForm) => {
|
||||
showClose.value = false
|
||||
formTitle.value = _formTitle
|
||||
ruleForm.value = _ruleForm
|
||||
ruleForm.value.mediaCity = ruleForm.value.provinceName + '/' + ruleForm.value.cityName + '/' + ruleForm.value.areaName + '/' + ruleForm.value.townName
|
||||
if (ruleForm.value.mapY && ruleForm.value.mapX) latVal.value = ruleForm.value.mapY + ',' + ruleForm.value.mapX
|
||||
// ruleForm.value = _ruleForm
|
||||
ruleForm.value.id = _ruleForm.id
|
||||
ruleForm.value.mediaCity = _ruleForm.provinceName + '/' + _ruleForm.cityName + '/' + _ruleForm.areaName + '/' + _ruleForm.townName
|
||||
if (_ruleForm.mapY && _ruleForm.mapX) latVal.value = _ruleForm.mapY + ',' + _ruleForm.mapX
|
||||
getDepList()
|
||||
getMediaTypeOne()
|
||||
getProvinceList()
|
||||
|
|
|
|||
|
|
@ -113,9 +113,18 @@
|
|||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="实景图片" align="left" prop="mediaFileList" width="170">
|
||||
<template #default="scope">
|
||||
<img v-if="scope.row.mediaFileList.length > 0"
|
||||
:src="baseUrl + scope.row.mediaFileList[0].fileName" fit="fill"
|
||||
style="width: 138px;height: 78px; border-radius: 4px" />
|
||||
<!-- 加载中占位(动画/静态图) -->
|
||||
<div class="img-loading" v-if="!scope.row.imgLoaded && !scope.row.imgError">
|
||||
<span class="loading-text">加载中...</span>
|
||||
</div>
|
||||
<!-- 加载成功显示图片 -->
|
||||
<img v-else-if="scope.row.imgLoaded && !scope.row.imgError" :src="scope.row.imgUrl"
|
||||
style="width: 138px; height: 78px; border-radius: 4px; object-fit: cover; cursor: pointer;"
|
||||
@click="handleViewMedia(scope.row.id)" />
|
||||
<!-- 加载失败占位 -->
|
||||
<div v-else class="img-error" @click="reloadImg(scope.row)">
|
||||
<span class="error-text">加载失败,点击重试</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="媒体名称" align="left" prop="mediaName" width="150" />
|
||||
|
|
@ -277,7 +286,9 @@ const handleExportMore = () => {
|
|||
}
|
||||
// 导出ppt实现代码
|
||||
const handleSubmitExportPPT = () => {
|
||||
proxy.$modal.loading(`正在执行导出,请耐心等待...`)
|
||||
exportMediaPPT(exportForm.value).then(res => {
|
||||
proxy.$modal.closeLoading()
|
||||
const downLoadName = '媒体信息_' + getCurrentTime() + '.pptx'
|
||||
// 通过a标签打开新页面下载文件
|
||||
const a = document.createElement('a')
|
||||
|
|
@ -460,17 +471,68 @@ const getZoomLevel = (province, city, county, town) => {
|
|||
const handleFlod = () => {
|
||||
unfoldFlag.value = !unfoldFlag.value
|
||||
}
|
||||
// 初始化时,为每行数据添加图片加载状态
|
||||
const initImgStatus = (list) => {
|
||||
list.forEach(row => {
|
||||
row.imgLoaded = false; // 加载完成标志
|
||||
row.imgError = false; // 加载失败标志
|
||||
row.imgUrl = ''; // 最终渲染的图片 URL
|
||||
// 触发异步加载
|
||||
if (row.mediaFileList && row.mediaFileList.length > 0) {
|
||||
loadImgAsync(row);
|
||||
} else {
|
||||
row.imgError = true; // 无图片时标记为失败(显示无图占位)
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 异步加载图片核心函数
|
||||
const loadImgAsync = (row) => {
|
||||
// 构建优化后的图片 URL(结合之前的格式/缩略图优化)
|
||||
const imgUrl = baseUrl + row.mediaFileList[0].fileName;
|
||||
|
||||
// 创建新的图片对象(异步加载)
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'anonymous'; // 处理跨域
|
||||
img.src = imgUrl;
|
||||
|
||||
// 加载成功回调
|
||||
img.onload = () => {
|
||||
row.imgUrl = imgUrl;
|
||||
row.imgLoaded = true;
|
||||
row.imgError = false;
|
||||
};
|
||||
|
||||
// 加载失败回调
|
||||
img.onerror = () => {
|
||||
console.warn('图片异步加载失败:', imgUrl);
|
||||
row.imgError = true;
|
||||
row.imgLoaded = false;
|
||||
};
|
||||
};
|
||||
|
||||
// 重试加载图片
|
||||
const reloadImg = (row) => {
|
||||
row.imgError = false;
|
||||
loadImgAsync(row);
|
||||
};
|
||||
// 获取户外媒介列表数据
|
||||
// 优化:在获取表格数据后初始化图片状态
|
||||
const getOutMediaPageList = () => {
|
||||
loading.value = true
|
||||
loading.value = true;
|
||||
outMediaPageList(queryParams.value).then(res => {
|
||||
points.value = []
|
||||
res.data.rows.forEach(itemPoint => {
|
||||
points.value = [];
|
||||
const rows = res.data.rows;
|
||||
// 1. 初始化图片加载状态 + 触发异步加载
|
||||
initImgStatus(rows);
|
||||
|
||||
// 原有逻辑:处理地图点、表格数据
|
||||
rows.forEach(itemPoint => {
|
||||
itemPoint.currentImageSrc = defaultImageSrc.value;
|
||||
if (itemPoint.mapX && itemPoint.mapX !== '' && itemPoint.mapY && itemPoint.mapY !== '') {
|
||||
if (itemPoint.dataScopeDeptId == 220) points.value.push({ "lnglat": [itemPoint.mapX, itemPoint.mapY], "name": itemPoint.mediaName, "mediaId": itemPoint.id, "style": 0 })
|
||||
else if (itemPoint.dataScopeDeptId == 219) points.value.push({ "lnglat": [itemPoint.mapX, itemPoint.mapY], "name": itemPoint.mediaName, "mediaId": itemPoint.id, "style": 1 })
|
||||
// 同时更新极值
|
||||
// 更新经纬度极值
|
||||
const lng = itemPoint.mapX;
|
||||
const lat = itemPoint.mapY;
|
||||
if (lng < minLng) minLng = lng;
|
||||
|
|
@ -479,18 +541,19 @@ const getOutMediaPageList = () => {
|
|||
if (lat > maxLat) maxLat = lat;
|
||||
}
|
||||
});
|
||||
outdoorMediaList.value = res.data.rows
|
||||
total.value = res.data.total
|
||||
loading.value = false
|
||||
|
||||
// 数据加载完成后,设置选中状态
|
||||
outdoorMediaList.value = rows;
|
||||
total.value = res.data.total;
|
||||
loading.value = false;
|
||||
|
||||
// 原有逻辑:设置表格选中状态、渲染地图点
|
||||
nextTick(() => {
|
||||
setTableSelection()
|
||||
// 在地图完全加载后执行点数据处理
|
||||
setTableSelection();
|
||||
renderMassMarks();
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1
|
||||
|
|
@ -522,7 +585,7 @@ const handleSelectionChange = (selection) => {
|
|||
// 如果是程序设置的选中状态,不更新 multipleChoseArr
|
||||
if (isSettingSelection.value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前页所有行的ID
|
||||
const currentPageIds = outdoorMediaList.value.map(item => item.id)
|
||||
|
|
@ -535,7 +598,7 @@ const handleSelectionChange = (selection) => {
|
|||
)
|
||||
|
||||
// 如果当前页有应该选中的数据但selection为空,说明是页面切换,不处理
|
||||
if (shouldHaveSelections) {
|
||||
if (shouldHaveSelections) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -551,7 +614,7 @@ const handleSelectionChange = (selection) => {
|
|||
if (!multipleChoseArr.value.some(item => item.id === newItem.id)) {
|
||||
multipleChoseArr.value.push(newItem)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
// 设置表格选中状态 - 完善版本
|
||||
const setTableSelection = () => {
|
||||
|
|
@ -1051,6 +1114,59 @@ onMounted(() => {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* 加载中占位 */
|
||||
.img-loading {
|
||||
width: 138px;
|
||||
height: 78px;
|
||||
border-radius: 4px;
|
||||
background: #f5f5f5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 加载动画(可选) */
|
||||
.img-loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
animation: imgLoading 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes imgLoading {
|
||||
100% {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 加载失败占位 */
|
||||
.img-error {
|
||||
width: 138px;
|
||||
height: 78px;
|
||||
border-radius: 4px;
|
||||
background: #fef0f0;
|
||||
border: 1px solid #fde2e2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #f56c6c;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.img-error:hover {
|
||||
background: #fcf1f1;
|
||||
}
|
||||
|
||||
.noChoseLabel {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,7 @@ import createVitePlugins from './vite/plugins'
|
|||
import postcsspxtorem from 'postcss-pxtorem'
|
||||
|
||||
const baseUrl = 'http://43.143.229.145:9002/prod-api' // 后端接口
|
||||
const analysisUrl = 'http://43.143.229.145:9002/ppt-analysis-api'
|
||||
// 生产环境
|
||||
// const baseUrl = 'http://8.140.172.21:9002/prod-api' // 后端接口
|
||||
// const analysisUrl = 'http://8.140.172.21:9002/ppt-analysis-api'
|
||||
const analysisUrl = 'http://43.143.229.145:9002/ppt-analysis-api'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ mode, command }) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user