鱼种类修改,导入修改,新增修改

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
扈兆增 2026-04-28 19:27:42 +08:00
parent 10c3c33ad0
commit 7e383e35fe
14 changed files with 558 additions and 126 deletions

View File

@ -6,4 +6,7 @@ NODE_ENV='development'
VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台' VITE_APP_TITLE = '水电水利建设项目全过程环境管理信息平台'
VITE_APP_PORT = 3000 VITE_APP_PORT = 3000
VITE_APP_BASE_API = '/dev-api' VITE_APP_BASE_API = '/dev-api'
## 开发环境API地址
VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
## 开发环境预览 图片视频地址
VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125' VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125'

View File

@ -4,4 +4,7 @@ NODE_ENV='production'
VITE_APP_TITLE = 'qgc-buji-web' VITE_APP_TITLE = 'qgc-buji-web'
VITE_APP_PORT = 3000 VITE_APP_PORT = 3000
VITE_APP_BASE_API = '/prod-api' VITE_APP_BASE_API = '/prod-api'
## 生产环境API地址
VITE_APP_BASE_URL = 'http://localhost:8093'
## 生产环境预览 图片视频地址
VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125' VITE_APP_PREVIEW_URL = 'https://211.99.26.225:12125'

BIN
frontend/dist.rar Normal file

Binary file not shown.

View File

@ -81,7 +81,7 @@ export function checkImportStatus() {
}); });
} }
// 查询用户导入导入结果 // 查询用户导入结果
export function getLastImportResult() { export function getLastImportResult() {
return request({ return request({
url: '/data/fishDraft/getLastImportResult', url: '/data/fishDraft/getLastImportResult',

View File

@ -9,11 +9,11 @@ export function getBaseDropdown(data:any) {
}); });
} }
//电站下拉列表 //电站下拉列表
export function getEngInfoDropdown(params:any) { export function getEngInfoDropdown(data:any) {
return request({ return request({
url: '/env/engInfo/dropdown', url: '/env/engInfo/dropdown',
method: 'get', method: 'post',
params data
}); });
} }
//过鱼设施下拉列表 //过鱼设施下拉列表
@ -31,3 +31,12 @@ export function getFishDictoryDropdown() {
method: 'get' method: 'get'
}); });
} }
// 上传文件
export function uploadFile(data:any) {
return request({
url: import.meta.env.VITE_APP_PREVIEW_URL + '/upload',
method: 'post',
data,
headers: { 'Content-Type': 'multipart/form-data' },
});
}

View File

@ -7,13 +7,12 @@
:loading="loading" :loading="loading"
@change="handleChange" @change="handleChange"
@search="handleSearch" @search="handleSearch"
placeholder="请选择鱼种类" placeholder="鱼种类支持俗名查询"
:mode="multiple ? 'multiple' : undefined" :mode="multiple ? 'multiple' : undefined"
show-search show-search
:filter-option="false" :filter-option="false"
class="custom-fish-select" class="custom-fish-select"
:dropdownMatchSelectWidth="false" :dropdownMatchSelectWidth="false"
:getPopupContainer="(triggerNode: HTMLElement) => triggerNode.parentNode"
@dropdownVisibleChange="handleDropdownVisibleChange" @dropdownVisibleChange="handleDropdownVisibleChange"
:max-tag-count="multiple ? 1 : undefined" :max-tag-count="multiple ? 1 : undefined"
:open="open" :open="open"
@ -29,6 +28,23 @@
<template #dropdownRender> <template #dropdownRender>
<div class="custom-dropdown-container"> <div class="custom-dropdown-container">
<div class="w-[340px] h-[30px] flex items-center pl-[10px]" @click.stop @mousedown.prevent>
<div>查询方式</div>
<div
class="text-[12px] font-bold mr-2 cursor-pointer"
:class="{ 'text-[#005293]': !isIntelligentQuery }"
@click="IntelligentQueryCLick(false)"
>
相似度
</div>
<div
class="text-[12px] font-bold cursor-pointer"
:class="{ 'text-[#005293]': isIntelligentQuery }"
@click="IntelligentQueryCLick(true)"
>
智能查询
</div>
</div>
<!-- 左侧可滚动的选项列表 --> <!-- 左侧可滚动的选项列表 -->
<div class="dropdown-left-list"> <div class="dropdown-left-list">
<div <div
@ -42,7 +58,7 @@
@click.stop="handleSelectOption(opt)" @click.stop="handleSelectOption(opt)"
@mouseenter="hoveredId = opt.id" @mouseenter="hoveredId = opt.id"
> >
<span class="item-name">{{ opt.name }}</span> <span class="item-name" v-html="highlightText(opt.name)"></span>
<!-- 选中对勾 --> <!-- 选中对勾 -->
<span v-if="isSelected(opt.id)" class="check-icon"></span> <span v-if="isSelected(opt.id)" class="check-icon"></span>
</div> </div>
@ -53,11 +69,14 @@
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<!-- 右侧固定显示的别名/详情 --> <!-- 右侧固定显示的别名/详情 -->
<div class="dropdown-right-detail"> <div class="dropdown-right-detail" @click.stop @mousedown.prevent>
<div v-if="currentDetailData" class="detail-content"> <div v-if="currentDetailData" class="detail-content">
<div class="detail-title">{{ currentDetailData.name }}</div> <div
class="detail-title"
v-html="highlightText(currentDetailData.name)"
></div>
<div class="detail-alias" :title="currentDetailData.alias"> <div class="detail-alias" :title="currentDetailData.alias">
{{ currentDetailData.alias || "暂无别名" }} <div v-html="highlightText(currentDetailData.alias)"></div>
</div> </div>
</div> </div>
<div v-else class="detail-placeholder">请选择或悬停查看</div> <div v-else class="detail-placeholder">请选择或悬停查看</div>
@ -71,6 +90,7 @@
import { ref, onMounted, computed, watch } from "vue"; import { ref, onMounted, computed, watch } from "vue";
import { getFishDictoryDropdown } from "@/api/select"; import { getFishDictoryDropdown } from "@/api/select";
import { useShuJuTianBaoStore } from "@/store/modules/shuJuTianBao"; import { useShuJuTianBaoStore } from "@/store/modules/shuJuTianBao";
import { message } from "ant-design-vue";
const shuJuTianBaoStore = useShuJuTianBaoStore(); const shuJuTianBaoStore = useShuJuTianBaoStore();
// --- Props & Emits --- // --- Props & Emits ---
@ -94,6 +114,7 @@ const options = ref<any[]>([]);
const searchKeyword = ref<string>(""); const searchKeyword = ref<string>("");
const hoveredId = ref<string | null>(null); const hoveredId = ref<string | null>(null);
const open = ref(false); // const open = ref(false); //
const isIntelligentQuery = ref(true); //
// --- Computed --- // --- Computed ---
const filteredOptions = computed(() => { const filteredOptions = computed(() => {
@ -128,6 +149,7 @@ const isSelected = (id: string) => {
const handleSearch = (value: string) => { const handleSearch = (value: string) => {
searchKeyword.value = value; searchKeyword.value = value;
hoveredId.value = null;
}; };
const handleDropdownVisibleChange = (val: boolean) => { const handleDropdownVisibleChange = (val: boolean) => {
@ -139,6 +161,8 @@ const handleDropdownVisibleChange = (val: boolean) => {
}; };
const handleSelectOption = (opt: any) => { const handleSelectOption = (opt: any) => {
console.log(props.modelValue)
console.log(props.modelValue)
if (props.multiple) { if (props.multiple) {
// --- --- // --- ---
let newValues: string[] = Array.isArray(props.modelValue) let newValues: string[] = Array.isArray(props.modelValue)
@ -165,11 +189,19 @@ const handleSelectOption = (opt: any) => {
} }
} }
}; };
const IntelligentQueryCLick = (val: boolean) => {
isIntelligentQuery.value = val;
if (val) {
message.success("智能查询已开启");
} else {
message.success("智能查询已关闭");
}
};
const handleChange = (val: any) => { const handleChange = (val: any) => {
// a-select change Tag // a-select change Tag
// //
emit("update:modelValue", val, ''); emit("update:modelValue", val, "");
}; };
const getFishNameById = (id: string) => { const getFishNameById = (id: string) => {
@ -210,6 +242,14 @@ const init = () => {
} }
}; };
//
const highlightText = (text) => {
if (text == null) {
return "暂无别名";
}
const reg = new RegExp(searchKeyword.value, "g");
return text.replace(reg, `<span style="color: red;">${searchKeyword.value}</span>`);
};
onMounted(() => { onMounted(() => {
init(); init();
}); });
@ -226,7 +266,9 @@ onMounted(() => {
} }
.custom-dropdown-container { .custom-dropdown-container {
width: 401px;
display: flex; display: flex;
flex-wrap: wrap;
background: #fff; background: #fff;
border-radius: 4px; border-radius: 4px;
overflow: hidden; overflow: hidden;
@ -323,6 +365,9 @@ onMounted(() => {
color: #666; color: #666;
line-height: 1.5; line-height: 1.5;
word-break: break-all; word-break: break-all;
span {
color: red;
}
} }
.detail-placeholder { .detail-placeholder {

View File

@ -2,7 +2,7 @@
import { computed } from "vue"; import { computed } from "vue";
import { useTagsViewStore } from "@/store/modules/tagsView"; import { useTagsViewStore } from "@/store/modules/tagsView";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import GisView from "@/components/gis/GisView.vue"; // import GisView from "@/components/gis/GisView.vue";
const tagsViewStore = useTagsViewStore(); const tagsViewStore = useTagsViewStore();
@ -12,7 +12,7 @@ const routeKey = computed(() => router.path + Math.random());
<template> <template>
<section class="app-main"> <section class="app-main">
<GisView /> <!-- <GisView /> -->
<div class="gi-panels"> <div class="gi-panels">
<router-view v-slot="{ Component, route }" :key="routeKey"> <router-view v-slot="{ Component, route }" :key="routeKey">
<transition name="router-fade" mode="out-in"> <transition name="router-fade" mode="out-in">

View File

@ -11,11 +11,9 @@ import Sidebar from "./Sidebar/index.vue";
import { useTagsViewStore } from "@/store/modules/tagsView"; import { useTagsViewStore } from "@/store/modules/tagsView";
import { useUserStore } from "@/store/modules/user"; import { useUserStore } from "@/store/modules/user";
import Cookies from "js-cookie";
import {getPath,removePath } from '@/utils/auth'; import {getPath,removePath } from '@/utils/auth';
// const url = import.meta.env.VITE_APP_BASE_API; // const url = import.meta.env.VITE_APP_BASE_API;
const username = Cookies.get("username");
const tagsViewStore = useTagsViewStore(); const tagsViewStore = useTagsViewStore();
const userStore = useUserStore(); const userStore = useUserStore();
@ -67,7 +65,7 @@ onBeforeUnmount(() => {
<span class="icon"> <span class="icon">
<UserOutlined /> <UserOutlined />
</span> </span>
<span class="text">{{ username }}</span> <span class="text">{{ userStore.username }}</span>
</div> </div>
</a-space> </a-space>
<template #overlay> <template #overlay>

View File

@ -12,6 +12,7 @@ import { UserInfo } from '@/api/user/types';
export const useUserStore = defineStore('user', () => { export const useUserStore = defineStore('user', () => {
// state // state
const Token = ref<string>(getToken() || ''); const Token = ref<string>(getToken() || '');
const username = ref<string>('');
const nickname = ref<string>(''); const nickname = ref<string>('');
const avatar = ref<string>(''); const avatar = ref<string>('');
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限 const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
@ -47,6 +48,7 @@ export const useUserStore = defineStore('user', () => {
if (!data.roles || data.roles.length <= 0) { if (!data.roles || data.roles.length <= 0) {
reject('getUserInfo: roles must be a non-null array!'); reject('getUserInfo: roles must be a non-null array!');
} }
username.value = data.userInfo.username;
nickname.value = data.userInfo.nickname; nickname.value = data.userInfo.nickname;
avatar.value = data.userInfo.avatar; avatar.value = data.userInfo.avatar;
roles.value = data.roles; roles.value = data.roles;
@ -85,6 +87,7 @@ export const useUserStore = defineStore('user', () => {
} }
return { return {
Token, Token,
username,
nickname, nickname,
avatar, avatar,
roles, roles,

View File

@ -46,7 +46,7 @@
v-model:value="formData.rstcd" v-model:value="formData.rstcd"
:loading="engLoading" :loading="engLoading"
placeholder="请选择电站名称" placeholder="请选择电站名称"
:disabled="isView" :disabled="isView || !formData.baseId"
show-search show-search
allowClear allowClear
:filter-option="filterOption" :filter-option="filterOption"
@ -72,7 +72,7 @@
v-model:value="formData.stcd" v-model:value="formData.stcd"
:loading="fpssLoading" :loading="fpssLoading"
placeholder="请选择过鱼设施" placeholder="请选择过鱼设施"
:disabled="isView" :disabled="isView || !formData.rstcd"
show-search show-search
allowClear allowClear
:filter-option="filterOption" :filter-option="filterOption"
@ -218,16 +218,47 @@
/> />
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12" class="imgupload" :class="{'imgupload_hidden': isView}">
<a-form-item label="图片" name="picpth"> <a-form-item label="图片" name="picpth">
<!-- <a-input v-model:value="formData.picpth" placeholder="图片路径" /> --> <a-upload
v-model:file-list="imageFileList"
list-type="picture-card"
:multiple="true"
accept=".png,.jpg,.jpeg"
:before-upload="beforeImageUpload"
@preview="handleImagePreview"
:disabled="isView"
:maxCount="5"
@remove="handleImageRemove"
>
<div v-if="!isView && imageFileList.length < 5">
<plus-outlined />
<div style="margin-top: 8px">上传</div>
</div>
</a-upload>
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="12"> <a-col :span="12">
<a-form-item label="视频" name="vdpth"> <a-form-item label="视频" name="vdpth">
<!-- <a-input v-model:value="formData.vdpth" placeholder="视频路径" /> --> <a-upload
v-if="!isView"
v-model:file-list="videoFileList"
list-type="text"
:multiple="false"
accept=".mp4"
:before-upload="beforeVideoUpload"
:disabled="isView"
:maxCount="5"
@remove="handleVideoRemove"
>
<a-button :disabled="isView && videoFileList.length < 5">
<upload-outlined />
上传视频 (MP4)
</a-button>
</a-upload>
<a-button v-else @click="handleVideoPreview"> 点击预览视频 </a-button>
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>
@ -238,10 +269,17 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, watch, computed } from "vue"; import { ref, reactive, watch, computed } from "vue";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { message } from "ant-design-vue"; import { Upload, message } from "ant-design-vue";
import { UploadOutlined, PlusOutlined } from "@ant-design/icons-vue";
import type { Rule } from "ant-design-vue/es/form"; import type { Rule } from "ant-design-vue/es/form";
import type { UploadProps } from "ant-design-vue";
import fishSearch from "@/components/fishSearch/index.vue"; import fishSearch from "@/components/fishSearch/index.vue";
import { getBaseDropdown, getEngInfoDropdown, getFpssDropdown } from "@/api/select"; import {
getBaseDropdown,
getEngInfoDropdown,
getFpssDropdown,
uploadFile,
} from "@/api/select";
// Props // Props
interface Props { interface Props {
@ -257,6 +295,8 @@ const fpssLoading = ref(false);
const baseOption = ref<any[]>([]); const baseOption = ref<any[]>([]);
const engOption = ref<any[]>([]); const engOption = ref<any[]>([]);
const fpssOption = ref<any[]>([]); const fpssOption = ref<any[]>([]);
const imageFileList = ref<any[]>([]);
const videoFileList = ref<any[]>([]);
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
visible: false, visible: false,
@ -315,6 +355,7 @@ const emit = defineEmits<{
(e: "update:visible", value: boolean): void; (e: "update:visible", value: boolean): void;
(e: "cancel"): void; (e: "cancel"): void;
(e: "ok", values: any): void; (e: "ok", values: any): void;
(e: "preview-click", record: any, type: string, index: number): void;
}>(); }>();
// //
@ -420,7 +461,55 @@ const validateWeight = () => {
return true; return true;
}; };
//
const beforeImageUpload: UploadProps["beforeUpload"] = (file) => {
const isJpgOrPng =
file.type === "image/jpeg" ||
file.type === "image/png" ||
file.name.toLowerCase().endsWith(".jpg") ||
file.name.toLowerCase().endsWith(".jpeg") ||
file.name.toLowerCase().endsWith(".png");
if (!isJpgOrPng) {
message.error("只能上传 JPG/PNG/JPEG 格式的图片!");
return Upload.LIST_IGNORE;
}
const isLt2M = file.size / 1024 / 1024 < 5; // 5M
if (!isLt2M) {
message.error("图片大小不能超过 5MB!");
return Upload.LIST_IGNORE;
}
// false
return false;
};
//
const beforeVideoUpload: UploadProps["beforeUpload"] = (file) => {
const isMp4 = file.type === "video/mp4" || file.name.toLowerCase().endsWith(".mp4");
if (!isMp4) {
message.error("只能上传 MP4 格式的视频!");
return false;
}
const isLt50M = file.size / 1024 / 1024 < 10; // 50M
if (!isLt50M) {
message.error("视频大小不能超过 10MB!");
return false;
}
// false
return false;
};
//
const handleImageRemove = (file: any) => {
const index = imageFileList.value.indexOf(file);
const newFileList = imageFileList.value.slice();
newFileList.splice(index, 1);
imageFileList.value = newFileList;
};
//
const handleVideoRemove = (file: any) => {
videoFileList.value = [];
};
// 1. // 1.
const initForm = () => { const initForm = () => {
if (props.initialValues) { if (props.initialValues) {
@ -453,7 +542,30 @@ const initForm = () => {
formData.bodyLengthMin = undefined; formData.bodyLengthMin = undefined;
formData.bodyLengthMax = undefined; formData.bodyLengthMax = undefined;
} }
if (values.picpth) {
const paths = Array.isArray(values.picpth)
? values.picpth
: values.picpth.split(",");
imageFileList.value = paths.map((path: string, index: number) => ({
uid: `-${index}`,
name: path.split("/").pop() || `image-${index}`,
status: "done",
path: path,
url: import.meta.env.VITE_APP_PREVIEW_URL + "/?" + path, // 访URL
}));
}
//
if (values.vdpth) {
const paths = Array.isArray(values.vdpth) ? values.vdpth : values.vdpth.split(",");
videoFileList.value = paths.map((path: string, index: number) => ({
uid: `-${index}`,
name: path.split("/").pop() || `image-${index}`,
status: "done",
path: path,
url: import.meta.env.VITE_APP_PREVIEW_URL + "/?" + path, // 访URL
}));
}
// //
Object.keys(formData).forEach((key) => { Object.keys(formData).forEach((key) => {
// //
@ -498,6 +610,9 @@ const resetForm = () => {
// //
bodyLengthError.value = ""; bodyLengthError.value = "";
weightError.value = ""; weightError.value = "";
//
imageFileList.value = [];
videoFileList.value = [];
}; };
// //
@ -506,7 +621,21 @@ const handleCancel = () => {
emit("cancel"); emit("cancel");
resetForm(); resetForm();
}; };
const handleVideoPreview = () => {
emit("preview-click", { vdpthList: videoFileList.value }, "formVideo", 0);
};
// ... ...
//
const handleImagePreview = async (file: any) => {
if (!props.isView) {
return "";
}
emit("preview-click", { picpthList: imageFileList.value }, "formImage", 0);
return "";
};
// ... ...
// //
const handleOk = async () => { const handleOk = async () => {
try { try {
@ -520,6 +649,70 @@ const handleOk = async () => {
} }
// //
await formRef.value.validate(); await formRef.value.validate();
// 1.
let uploadedPicPaths: any[] = [];
// url
const newImageFiles = imageFileList.value.filter(
(file) => !file.url && file.originFileObj
);
if (newImageFiles.length > 0) {
// 使 Promise.all
// uploadFile { data: { url: '...' } }
const uploadPromises = newImageFiles.map((file) => {
const formDataUpload = new FormData();
formDataUpload.append("file", file.originFileObj);
return uploadFile(formDataUpload); //
});
const results = await Promise.all(uploadPromises);
uploadedPicPaths = results.map((item: any, index: number) => ({
path: item.message,
uid: `-${index}`,
name: item.fileMD5,
status: "done",
url: item.fullFilePath, // 访URL
}));
}
//
const existingPics = imageFileList.value
.filter((file) => file.path)
.map((file) => file.path);
const uploadedPicPaths1 = uploadedPicPaths
.filter((file) => file.path)
.map((file) => file.path);
const finalPicPaths = [...existingPics, ...uploadedPicPaths1];
// 2.
let uploadedVideoPath = [];
const newVideoFiles = videoFileList.value.filter(
(file) => !file.url && file.originFileObj
);
if (newVideoFiles.length > 0) {
const uploadPromises = newVideoFiles.map((file) => {
const formDataUpload = new FormData();
formDataUpload.append("file", file.originFileObj);
return uploadFile(formDataUpload); //
});
const results = await Promise.all(uploadPromises);
uploadedVideoPath = results.map((item: any, index: number) => ({
path: item.message,
uid: `-${index}`,
name: item.fileMD5,
status: "done",
url: item.fullFilePath, // 访URL
}));
}
const existingVideos = videoFileList.value
.filter((file) => file.path)
.map((file) => file.path);
const uploadedVideoPaths1 = uploadedVideoPath
.filter((file) => file.path)
.map((file) => file.path);
const finalVideoPaths = [...existingVideos, ...uploadedVideoPaths1];
let fwet = ""; let fwet = "";
if ( if (
formData.weightMin == formData.weightMax && formData.weightMin == formData.weightMax &&
@ -528,7 +721,7 @@ const handleOk = async () => {
) { ) {
fwet = formData.weightMin; fwet = formData.weightMin;
} else if (formData.weightMin == undefined && formData.weightMax == undefined) { } else if (formData.weightMin == undefined && formData.weightMax == undefined) {
fwet = "-"; fwet = "";
} else { } else {
fwet = formData.weightMin + "~" + formData.weightMax; fwet = formData.weightMin + "~" + formData.weightMax;
} }
@ -543,7 +736,7 @@ const handleOk = async () => {
formData.bodyLengthMin == undefined && formData.bodyLengthMin == undefined &&
formData.bodyLengthMax == undefined formData.bodyLengthMax == undefined
) { ) {
fsz = "-"; fsz = "";
} else { } else {
fsz = formData.bodyLengthMin + "~" + formData.bodyLengthMax; fsz = formData.bodyLengthMin + "~" + formData.bodyLengthMax;
} }
@ -552,9 +745,12 @@ const handleOk = async () => {
...formData, ...formData,
fwet: fwet, fwet: fwet,
fsz: fsz, fsz: fsz,
picpth: finalPicPaths.join(","), //
vdpth: finalVideoPaths.join(","),
}; };
if (!formData.id) submitValues.tm = dayjs().format("YYYY-MM-DD HH:mm:ss"); if (!formData.id) submitValues.tm = dayjs().format("YYYY-MM-DD HH:mm:ss");
console.log(submitValues); console.log(submitValues);
// return;
emit("ok", submitValues); emit("ok", submitValues);
} catch (error) { } catch (error) {
console.error("Validate Failed:", error); console.error("Validate Failed:", error);
@ -563,5 +759,52 @@ const handleOk = async () => {
}; };
</script> </script>
<style scoped> <style scoped lang="scss">
.imgupload {
/* 1. 控制上传触发按钮(那个加号框)的大小 */
:deep(.ant-upload-select-picture-card) {
width: 78px !important;
height: 78px !important;
margin-right: 8px;
margin-bottom: 8px;
display: flex;
align-items: center;
justify-content: center;
}
/* 2. 控制已上传列表项容器的大小 */
:deep(.ant-upload-list-item-container) {
width: 78px !important;
height: 78px !important;
float: left; /* 确保浮动排列,避免换行问题 */
margin-right: 8px;
margin-bottom: 8px;
}
/* 3. 控制列表项内部的具体内容(图片/缩略图) */
:deep(.ant-upload-list-item) {
width: 100% !important;
height: 100% !important;
padding: 0;
border: 1px solid #d9d9d9;
border-radius: 2px;
/* 删除预览按钮 */
.ant-upload-list-item-actions {
a {
display: none;
}
}
}
}
.imgupload_hidden{
:deep(.ant-upload-list-item) {
/* 删除预览按钮 */
.ant-upload-list-item-actions {
a {
display: block;
}
}
}
}
</style> </style>

View File

@ -78,7 +78,6 @@ import {
import dayjs from "dayjs"; import dayjs from "dayjs";
import BasicSearch from "@/components/BasicSearch/index.vue"; // import BasicSearch from "@/components/BasicSearch/index.vue"; //
import { DateSetting } from "@/utils/enumeration"; import { DateSetting } from "@/utils/enumeration";
import { checkPerm } from "@/directive/permission";
import fishSearch from "@/components/fishSearch/index.vue"; import fishSearch from "@/components/fishSearch/index.vue";
import { useShuJuTianBaoStore } from "@/store/modules/shuJuTianBao"; import { useShuJuTianBaoStore } from "@/store/modules/shuJuTianBao";

View File

@ -6,7 +6,7 @@
:columns="modalColumns" :columns="modalColumns"
:scroll="{ y: 500, x: '100%' }" :scroll="{ y: 500, x: '100%' }"
:pagination="false" :pagination="false"
:row-key="(record, index) => index" :row-key="(_record, index) => index"
> >
<template #bodyCell="{ column, record, index }"> <template #bodyCell="{ column, record, index }">
<!-- 1. 操作列 --> <!-- 1. 操作列 -->
@ -29,28 +29,33 @@
<template <template
v-else-if=" v-else-if="
!isEditing(index) && !isEditing(index) &&
column.dataIndexKey &&
record._warnings && record._warnings &&
record._warnings.includes(column.dataIndexKey) record._warnings.includes(column.dataIndexKey)
" "
> >
<div style="color: red; display: flex; align-items: center"> <div style="color: red; display: flex; align-items: center">
<span>{{ record[column.dataIndex] }}</span> <span v-if="record[column.dataIndex]">{{ record[column.dataIndex] }}</span>
<span v-else> 请添加{{ column.title }}</span>
<exclamation-circle-outlined style="margin-left: 4px" /> <exclamation-circle-outlined style="margin-left: 4px" />
</div> </div>
</template> </template>
<!-- 3. 编辑状态下的单元格 (绑定到 editingData) --> <!-- 3. 编辑状态下的单元格 (绑定到 editingData) -->
<template v-else-if="isEditing(index) && column.dataIndex != 'picpth' && column.dataIndex != 'vdpth'"> <template
v-else-if="
isEditing(index) && column.dataIndex != 'picpth' && column.dataIndex != 'vdpth'
"
>
<template v-if="column.dataIndex === 'baseName'"> <template v-if="column.dataIndex === 'baseName'">
<a-select <a-select
v-model:value="editingData.baseId" v-model:value="editingData.baseId"
placeholder="请选择" placeholder="请选择"
show-search show-search
allowClear
:filter-option="filterOption" :filter-option="filterOption"
:loading="rowStates[index]?.baseLoading" :loading="rowStates[index]?.baseLoading"
style="width: 100%" style="width: 100%"
@change="(val) => handleBaseChange(val, index)" @change="(val) => handleBaseChange(val, index, 'input')"
> >
<a-select-option <a-select-option
v-for="opt in baseOptions" v-for="opt in baseOptions"
@ -69,11 +74,12 @@
v-model:value="editingData.rstcd" v-model:value="editingData.rstcd"
placeholder="请选择" placeholder="请选择"
show-search show-search
allowClear
:filter-option="filterOption" :filter-option="filterOption"
:loading="rowStates[index]?.engLoading" :loading="rowStates[index]?.engLoading"
style="width: 100%" style="width: 100%"
:disabled="!editingData.baseId" :disabled="!editingData.baseId"
@change="(val) => handleEngChange(val, index)" @change="(val) => handleEngChange(val, index, 'input')"
> >
<a-select-option <a-select-option
v-for="opt in rowStates[index]?.engOptions || []" v-for="opt in rowStates[index]?.engOptions || []"
@ -92,6 +98,7 @@
v-model:value="editingData.stcd" v-model:value="editingData.stcd"
placeholder="请选择" placeholder="请选择"
show-search show-search
allowClear
:filter-option="filterOption" :filter-option="filterOption"
:loading="rowStates[index]?.fpssLoading" :loading="rowStates[index]?.fpssLoading"
style="width: 100%" style="width: 100%"
@ -117,6 +124,7 @@
style="width: 100%" style="width: 100%"
format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
@change="(val) => delWarning(val,'strdt')"
/> />
</template> </template>
@ -135,6 +143,7 @@
v-model:value="editingData.direction" v-model:value="editingData.direction"
placeholder="请选择" placeholder="请选择"
style="width: 100%" style="width: 100%"
@change="(val) => delWarning(val,'direction')"
> >
<a-select-option <a-select-option
v-for="item in direction" v-for="item in direction"
@ -147,7 +156,15 @@
</template> </template>
<!-- 数字输入框 --> <!-- 数字输入框 -->
<template v-else-if="['fcnt', 'wt'].includes(column.dataIndex)"> <template v-else-if="['fcnt'].includes(column.dataIndex)">
<a-input-number
v-model:value="editingData[column.dataIndex]"
style="width: 100%"
@change="(val) => delWarning(val, column.dataIndex)"
:min="0"
/>
</template>
<template v-else-if="['wt'].includes(column.dataIndex)">
<a-input-number <a-input-number
v-model:value="editingData[column.dataIndex]" v-model:value="editingData[column.dataIndex]"
style="width: 100%" style="width: 100%"
@ -157,7 +174,8 @@
<!-- 是否鱼苗 --> <!-- 是否鱼苗 -->
<template v-else-if="column.dataIndex === 'isfs'"> <template v-else-if="column.dataIndex === 'isfs'">
<a-radio-group v-model:value="editingData.isfs"> <a-radio-group v-model:value="editingData.isfs"
@change="(val) => delWarning(val,'isfs')">
<a-radio :value="1"></a-radio> <a-radio :value="1"></a-radio>
<a-radio :value="0"></a-radio> <a-radio :value="0"></a-radio>
</a-radio-group> </a-radio-group>
@ -198,21 +216,25 @@
</template> </template>
</template> </template>
<template <template v-else-if="column.dataIndex === 'picpth'">
v-else-if="column.dataIndex === 'picpth'"
>
<div class="preview" v-for="(item, index) in record.picpthList"> <div class="preview" v-for="(item, index) in record.picpthList">
<div class="text" :class="{'text_warning': record.picpthsWarnings.includes(item.name)}" @click="emit('preview-click', record, 'image' ,index)"> <div
class="text"
:class="{ text_warning: record.picpthsWarnings.includes(item.name) }"
@click="emit('preview-click', record, 'image', index)"
>
{{ item.name }} {{ item.name }}
</div> </div>
</div> </div>
<div v-if="record.picpthList.length == 0">暂无图片</div> <div v-if="record.picpthList.length == 0">暂无图片</div>
</template> </template>
<template <template v-else-if="column.dataIndex === 'vdpth'">
v-else-if="column.dataIndex === 'vdpth'"
>
<div class="preview" v-for="(item, index) in record.vdpthList"> <div class="preview" v-for="(item, index) in record.vdpthList">
<div class="text" :class="{'text_warning': record.vdpthsWarnings.includes(item.name)}" @click="emit('preview-click', record, 'vdpth' ,index)"> <div
class="text"
:class="{ text_warning: record.vdpthsWarnings.includes(item.name) }"
@click="emit('preview-click', record, 'video', index)"
>
{{ item.name }} {{ item.name }}
</div> </div>
</div> </div>
@ -228,8 +250,6 @@ import { message, Tag } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue"; import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import fishSearch from "@/components/fishSearch/index.vue"; import fishSearch from "@/components/fishSearch/index.vue";
import { getBaseDropdown, getEngInfoDropdown, getFpssDropdown } from "@/api/select"; import { getBaseDropdown, getEngInfoDropdown, getFpssDropdown } from "@/api/select";
import { CloseCircleOutlined } from "@ant-design/icons-vue";
import { es } from "element-plus/es/locale/index.mjs";
const props: any = defineProps({ const props: any = defineProps({
fileTableData: { type: Array, default: () => [] }, fileTableData: { type: Array, default: () => [] },
@ -269,12 +289,25 @@ const modalColumns = ref([
title: "过鱼设施名称", title: "过鱼设施名称",
width: 150, width: 150,
}, },
{ dataIndex: "strdt", key: "strdt", title: "过鱼时间", width: 190 }, {
{ dataIndex: "ftpName", key: "ftpName", title: "鱼种类", width: 120 }, dataIndex: "strdt",
key: "strdt",
dataIndexKey: "strdt",
title: "过鱼时间",
width: 190,
},
{
dataIndex: "ftpName",
key: "ftpName",
dataIndexKey: "ftp",
title: "鱼种类",
width: 120,
},
{ {
dataIndex: "isfs", dataIndex: "isfs",
key: "isfs", key: "isfs",
title: "是否鱼苗", title: "是否鱼苗",
dataIndexKey: "isfs",
width: 130, width: 130,
customRender: ({ text }: any) => { customRender: ({ text }: any) => {
const isYes = text === 1 || text === "1"; const isYes = text === 1 || text === "1";
@ -285,13 +318,20 @@ const modalColumns = ref([
}, },
{ {
dataIndex: "direction", dataIndex: "direction",
dataIndexKey: "direction",
key: "direction", key: "direction",
title: "游向", title: "游向",
width: 120, width: 120,
customRender: ({ text }: any) => props.direction.find((item: any) => item.itemCode === text)?.dictName || "-" customRender: ({ text }: any) =>
, props.direction.find((item: any) => item.itemCode === text)?.dictName || "-",
},
{
dataIndex: "fcnt",
key: "fcnt",
dataIndexKey: "fcnt",
title: "过鱼数量(尾)",
width: 120,
}, },
{ dataIndex: "fcnt", key: "fcnt", title: "过鱼数量(尾)", width: 120 },
{ dataIndex: "fsz", key: "fsz", title: "体长(cm)", width: 160 }, { dataIndex: "fsz", key: "fsz", title: "体长(cm)", width: 160 },
{ dataIndex: "fwet", key: "fwet", title: "平均体重(g)", width: 160 }, { dataIndex: "fwet", key: "fwet", title: "平均体重(g)", width: 160 },
{ dataIndex: "wt", key: "wt", title: "水温(℃)", width: 80 }, { dataIndex: "wt", key: "wt", title: "水温(℃)", width: 80 },
@ -335,25 +375,23 @@ const ensureRowState = (index: number) => {
}; };
// --- ( editingData) --- // --- ( editingData) ---
const handleBaseChange = async (
const handleBaseChange = async (baseId: string, index: number) => { baseId: string,
console.log(baseId); index: number,
type: string = "start"
) => {
const state = ensureRowState(index);
editingData.value.baseName = baseOptions.value.find( editingData.value.baseName = baseOptions.value.find(
(item: any) => item.baseid == baseId (item: any) => item.baseid == baseId
)?.basename; )?.basename;
if (baseId && editingData.value._warnings) { delWarning(baseId, "baseId");
editingData.value._warnings = editingData.value._warnings.filter(
(w: string) => w !== "baseName"
);
}
const state = ensureRowState(index);
// //
if (type != "start") {
editingData.value.rstcd = undefined; editingData.value.rstcd = undefined;
editingData.value.stcd = undefined; editingData.value.stcd = undefined;
state.engOptions = []; state.engOptions = [];
state.fpssOptions = []; state.fpssOptions = [];
}
if (!baseId) return;
state.engLoading = true; state.engLoading = true;
try { try {
const res = await getEngInfoDropdown({ baseId }); const res = await getEngInfoDropdown({ baseId });
@ -365,20 +403,16 @@ const handleBaseChange = async (baseId: string, index: number) => {
} }
}; };
const handleEngChange = async (rstcd: string, index: number) => { const handleEngChange = async (rstcd: string, index: number, type: string = "start") => {
const state = ensureRowState(index); const state = ensureRowState(index);
if (rstcd && editingData.value._warnings) {
editingData.value._warnings = editingData.value._warnings.filter(
(w: string) => w !== "ennm"
);
}
editingData.value.ennm = state.engOptions.find( editingData.value.ennm = state.engOptions.find(
(item: any) => item.stcd === rstcd (item: any) => item.stcd === rstcd
)?.ennm; )?.ennm;
delWarning(rstcd, "rstcd");
if (type != "start") {
editingData.value.stcd = undefined; editingData.value.stcd = undefined;
state.fpssOptions = []; state.fpssOptions = [];
}
if (!rstcd || !editingData.value.baseId) return;
state.fpssLoading = true; state.fpssLoading = true;
try { try {
const res = await getFpssDropdown({ rstcd, baseId: editingData.value.baseId }); const res = await getFpssDropdown({ rstcd, baseId: editingData.value.baseId });
@ -391,18 +425,35 @@ const handleEngChange = async (rstcd: string, index: number) => {
}; };
const handleFpssChange = (stcd: string, index: number) => { const handleFpssChange = (stcd: string, index: number) => {
const state = ensureRowState(index); const state = ensureRowState(index);
if (stcd && editingData.value._warnings) { delWarning(stcd, "stcd");
editingData.value._warnings = editingData.value._warnings.filter(
(w: string) => w !== "stnm"
);
}
editingData.value.stnm = state.fpssOptions.find( editingData.value.stnm = state.fpssOptions.find(
(item: any) => item.stcd === stcd (item: any) => item.stcd === stcd
)?.stnm; )?.stnm;
}; };
// --- --- // /
const delWarning = (val: any, key: string) => {
// _warnings
if (!editingData.value._warnings) {
editingData.value._warnings = [];
}
const warnings = editingData.value._warnings;
const hasWarning = warnings.includes(key);
if (val !== null && val !== undefined && val !== '') {
// 1.
if (hasWarning) {
editingData.value._warnings = warnings.filter((w: string) => w !== key);
}
} else {
// 2. (null/undefined/'')
if (!hasWarning) {
editingData.value._warnings.push(key);
}
}
};
// --- ---
const isEditing = (index: number) => editingRowIndex.value === index; const isEditing = (index: number) => editingRowIndex.value === index;
const startEdit = (index: number) => { const startEdit = (index: number) => {
const originalRecord = props.fileTableData[index]; const originalRecord = props.fileTableData[index];
@ -416,11 +467,20 @@ const startEdit = (index: number) => {
editingRowIndex.value = index; editingRowIndex.value = index;
// 3. ( editingData ) // 3. ( editingData )
if (editingData.value.baseId && !editingData.value.rstcd) { console.log(editingData.value.baseId);
handleBaseChange(editingData.value.baseId, index); if (editingData.value.baseId == "" || editingData.value.baseId == undefined) {
} else if (editingData.value.baseId && editingData.value.rstcd) { console.log(editingData.value.rstcd);
handleBaseChange(editingData.value.baseId, index).then(() => { if (editingData.value.rstcd) {
handleEngChange(editingData.value.rstcd, index); handleBaseChange("", index, "start").then(() => {
handleEngChange(editingData.value.rstcd, index, "start");
});
} else {
handleEngChange("", index, "start");
}
} else if (editingData.value.baseId != "" && editingData.value.baseId != undefined) {
console.log(2);
handleBaseChange(editingData.value.baseId, index, "start").then(() => {
handleEngChange(editingData.value.rstcd, index, "start");
}); });
} }
}; };
@ -515,9 +575,9 @@ const handlePreviewDelete = (index: number) => {
// //
const handleFtpChange = (val: any, opt: any) => { const handleFtpChange = (val: any, opt: any) => {
editingData.value.ftpName = opt.name; editingData.value.ftpName = opt.name;
delWarning(val, "ftp");
}; };
// --- --- // --- ---
const filterOption = (input: string, option: any) => { const filterOption = (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0; return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;

View File

@ -128,6 +128,7 @@
:loading="submitLoading" :loading="submitLoading"
@cancel="editModalCancel" @cancel="editModalCancel"
@ok="handleEditSubmit" @ok="handleEditSubmit"
@preview-click="handlePreviewClick"
/> />
<!-- 媒体预览 Modal --> <!-- 媒体预览 Modal -->
@ -137,6 +138,7 @@
:footer="null" :footer="null"
width="900px" width="900px"
@cancel="closeMediaPreview" @cancel="closeMediaPreview"
z-index="2000"
> >
<div class="flex h-[60vh] gap-4"> <div class="flex h-[60vh] gap-4">
<!-- 左侧混合列表 (图片+视频) --> <!-- 左侧混合列表 (图片+视频) -->
@ -149,9 +151,12 @@
@click="currentMediaIndex = index" @click="currentMediaIndex = index"
> >
<span class="file-name">{{ item.name }}</span> <span class="file-name">{{ item.name }}</span>
<!-- 删除按钮 --> <!-- 删除按钮 -->
<div class="list-item-delete" @click.stop="handleDeleteMedia(item, index)"> <div
class="list-item-delete"
v-if="item.type != 'formVideo' && item.type != 'formImage'"
@click.stop="handleDeleteMedia(item, index)"
>
<CloseCircleOutlined /> <CloseCircleOutlined />
</div> </div>
</div> </div>
@ -166,17 +171,16 @@
v-if=" v-if="
currentMediaItem && currentMediaItem &&
currentMediaItem.url != '' && currentMediaItem.url != '' &&
currentMediaItem.type === 'image' (currentMediaItem.type === 'image' || currentMediaItem.type === 'formImage')
" "
:src="currentMediaItem.url" :src="currentMediaItem.url"
class="max-w-full max-h-full object-contain" class="max-w-full max-h-full object-contain"
:preview="{ visible: false }"
/> />
<div <div
v-else-if=" v-else-if="
currentMediaItem && currentMediaItem &&
currentMediaItem.url == '' && currentMediaItem.url == '' &&
currentMediaItem.type === 'image' (currentMediaItem.type === 'image' || currentMediaItem.type === 'formImage')
" "
class="text-gray-400" class="text-gray-400"
> >
@ -188,7 +192,7 @@
v-else-if=" v-else-if="
currentMediaItem && currentMediaItem &&
currentMediaItem.url != '' && currentMediaItem.url != '' &&
currentMediaItem.type === 'video' (currentMediaItem.type === 'video' || currentMediaItem.type === 'formVideo')
" "
:src="currentMediaItem.url" :src="currentMediaItem.url"
controls controls
@ -201,7 +205,7 @@
v-else-if=" v-else-if="
currentMediaItem && currentMediaItem &&
currentMediaItem.url == '' && currentMediaItem.url == '' &&
currentMediaItem.type === 'video' (currentMediaItem.type === 'video' || currentMediaItem.type === 'formVideo')
" "
class="text-gray-400" class="text-gray-400"
> >
@ -240,6 +244,7 @@ import BasicTable from "@/components/BasicTable/index.vue";
import GuoYuSheShiShuJuTianBaoSearch from "./guoYuSheShiShuJuTianBaoSearch.vue"; import GuoYuSheShiShuJuTianBaoSearch from "./guoYuSheShiShuJuTianBaoSearch.vue";
import GuoYuSheShiShuJuTianBaoTable from "./guoYuSheShiShuJuTianBaoTable.vue"; import GuoYuSheShiShuJuTianBaoTable from "./guoYuSheShiShuJuTianBaoTable.vue";
import EditModal from "./guoYuSheShiShuJuTianBaoForm.vue"; import EditModal from "./guoYuSheShiShuJuTianBaoForm.vue";
import { checkPerm } from "@/directive/permission";
import { import {
getFishDraftPage, getFishDraftPage,
@ -353,7 +358,7 @@ const submitLoading = ref(false);
const mediaPreviewVisible = ref(false); const mediaPreviewVisible = ref(false);
const videoPreviewTitle = ref("视频预览"); const videoPreviewTitle = ref("视频预览");
interface MediaItem { interface MediaItem {
type: "image" | "video"; type: "image" | "video" | "formVideo" | "formImage";
name: string; name: string;
url: string; url: string;
} }
@ -412,6 +417,7 @@ const columns = computed(() => {
// --- --- // --- ---
const handleAdd = () => { const handleAdd = () => {
isView.value = false;
currentRecord.value = null; currentRecord.value = null;
editModalVisible.value = true; editModalVisible.value = true;
}; };
@ -552,13 +558,14 @@ const handleReject = (id: any) => {
}; };
// //
const getCheckboxProps = (record: any) => { const getCheckboxProps = (record: any) => {
console.log(checkPerm(["sjtb:edit-review"]));
return { return {
disabled: ['SUBMITTED', 'APPROVED'].includes(record.status), disabled: ["SUBMITTED", "APPROVED"].includes(record.status),
}; };
}; };
const handleDataLoaded = (params: any, data: any) => { const handleDataLoaded = (params: any, data: any) => {
console.log(params, data); console.log(params, data);
return return;
}; };
// //
const handleSelectionChange = (keys: any) => { const handleSelectionChange = (keys: any) => {
@ -652,10 +659,40 @@ const handleModalOk = () => {
return; return;
} }
for (let i = 0; i < fileTableData.value.length; i++) { for (let i = 0; i < fileTableData.value.length; i++) {
// if (fileTableData.value[i]._warnings?.length > 0) { if (fileTableData.value[i]._warnings?.length > 0) {
// message.warning(""); if (fileTableData.value[i]._warnings.includes("baseId")) {
// return; message.warning("请检查流域,流域填写有误!");
// } return;
}
if (fileTableData.value[i]._warnings.includes("rstcd")) {
message.warning("请检查电站,电站填写有误!");
return;
}
if (fileTableData.value[i]._warnings.includes("stcd")) {
message.warning("请检查过鱼设施,过鱼设施填写有误!");
return;
}
if (fileTableData.value[i]._warnings.includes("strdt")) {
message.warning("请检查过鱼时间,过鱼时间填写有误!");
return;
}
if (fileTableData.value[i]._warnings.includes("ftp")) {
message.warning("请检查鱼种类,鱼种类填写有误!");
return;
}
if (fileTableData.value[i]._warnings.includes("direction")) {
message.warning("请检查游向,游向填写有误!");
return;
}
if (fileTableData.value[i]._warnings.includes("isfs")) {
message.warning("请检查是否鱼苗,是否鱼苗填写有误!");
return;
}
if (fileTableData.value[i]._warnings.includes("fcnt")) {
message.warning("请检查过鱼数量,过鱼数量填写有误!");
return;
}
}
if (fileTableData.value[i].picpthsWarnings?.length > 0) { if (fileTableData.value[i].picpthsWarnings?.length > 0) {
message.warning("请检查图片,图片路径有误!"); message.warning("请检查图片,图片路径有误!");
return; return;
@ -800,10 +837,16 @@ const fileTableaAnalysis = (res: any, type: string) => {
let data = []; let data = [];
let list = []; let list = [];
if (type == "file") { if (type == "file") {
list = res.data.failedRows; list = res.data.failedRows.concat(res.data.successRows);
} else { } else {
list = res.data.result.failedRowDetails; list = res.data.result.failedRowDetails.concat(res.data.result.successRowDetails);
} }
list.sort((a: any, b: any) => {
const keyA = a.rowIndex !== undefined && a.rowIndex !== null ? Number(a.rowIndex) : -1;
const keyB = b.rowIndex !== undefined && b.rowIndex !== null ? Number(b.rowIndex) : -1;
return keyA - keyB;
});
list.forEach((item) => { list.forEach((item) => {
data.push({ data.push({
...item.data, ...item.data,
@ -827,7 +870,9 @@ const customTransform = (res: any) => {
const modifiedRecords = rawRecords.map((item: any) => { const modifiedRecords = rawRecords.map((item: any) => {
return { return {
...item, ...item,
picpthList: item.picpth ? item.picpth.split(",").map((item: string) => baseUrl + "/?" + item) || [] : [], picpthList: item.picpth
? item.picpth.split(",").map((item: string) => baseUrl + "/?" + item) || []
: [],
}; };
}); });
return { return {
@ -896,9 +941,10 @@ const handleSearchFinish = (values: any) => {
}; };
// () // ()
const handlePreviewClick = (record: any, type: string, index: number) => { const handlePreviewClick = (record: any, type: string, index: number) => {
console.log(record, type);
const mixedList: MediaItem[] = []; const mixedList: MediaItem[] = [];
tablePreviewRecord.value = record;
if (type === "image") { if (type === "image") {
tablePreviewRecord.value = record;
videoPreviewTitle.value = "图片预览"; videoPreviewTitle.value = "图片预览";
const nameList = record.picpthList; const nameList = record.picpthList;
nameList.forEach((item: any) => { nameList.forEach((item: any) => {
@ -908,7 +954,8 @@ const handlePreviewClick = (record: any, type: string, index: number) => {
url: item.value ? `${baseUrl}/?${item.value}` : "", url: item.value ? `${baseUrl}/?${item.value}` : "",
}); });
}); });
} else { } else if (type === "video") {
tablePreviewRecord.value = record;
videoPreviewTitle.value = "视频预览"; videoPreviewTitle.value = "视频预览";
const nameList = record.vdpthList; const nameList = record.vdpthList;
nameList.forEach((item: any) => { nameList.forEach((item: any) => {
@ -918,10 +965,31 @@ const handlePreviewClick = (record: any, type: string, index: number) => {
url: item.value ? `${baseUrl}/?${item.value}` : "", url: item.value ? `${baseUrl}/?${item.value}` : "",
}); });
}); });
} else if (type === "formImage") {
videoPreviewTitle.value = "图片预览";
const nameList = JSON.parse(JSON.stringify(record)).picpthList;
nameList.forEach((item: any) => {
mixedList.push({
type: "formImage",
name: item.name, //
url: item.url,
});
});
} else if (type === "formVideo") {
videoPreviewTitle.value = "视频预览";
const nameList = JSON.parse(JSON.stringify(record)).vdpthList;
nameList.forEach((item: any) => {
mixedList.push({
type: "formVideo",
name: item.name, //
url: item.url,
});
});
} }
mediaPreviewVisible.value = true; mediaPreviewVisible.value = true;
currentMediaIndex.value = index; currentMediaIndex.value = index;
console.log(mixedList);
nextTick(() => { nextTick(() => {
previewList.value = mixedList; previewList.value = mixedList;
}); });
@ -945,6 +1013,7 @@ const handleDeleteMedia = (item: any, index: number) => {
Modal.confirm({ Modal.confirm({
title: "确认删除", title: "确认删除",
content: "确定要从预览列表中移除该项吗?", content: "确定要从预览列表中移除该项吗?",
zIndex: 2002,
onOk: () => { onOk: () => {
previewList.value.splice(index, 1); previewList.value.splice(index, 1);
console.log(previewList.value); console.log(previewList.value);

View File

@ -25,9 +25,9 @@ export default ({ mode }: ConfigEnv): UserConfig => {
proxy: { proxy: {
[env.VITE_APP_BASE_API]: { [env.VITE_APP_BASE_API]: {
// 线上API地址 // 线上API地址
// target: 'http://localhost:8093/', target: env.VITE_APP_BASE_URL,
// 本地API地址 // 本地API地址
target: 'http://10.84.121.21:8093', // target: 'http://10.84.121.21:8093',
changeOrigin: true, changeOrigin: true,
rewrite: path => rewrite: path =>
path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '') path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')