Files
cattleTransportation/pc-cattle-transportation/src/views/warehouse/warehouseInDialog.vue
2025-12-08 15:24:43 +08:00

976 lines
34 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
v-model="data.dialogVisible"
:title="data.isDetail ? '进仓详情' : (data.editId ? '编辑进仓记录' : '新增进仓记录')"
:before-close="handleClose"
width="900px"
:close-on-click-modal="false"
>
<el-form ref="formDataRef" :model="ruleForm" :rules="rules" label-width="120px" :disabled="data.isDetail">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="中转仓" prop="warehouseId">
<el-select
v-model="ruleForm.warehouseId"
placeholder="请选择中转仓"
clearable
filterable
style="width: 100%"
@change="handleWarehouseChange"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.warehouseName"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="运送清单" prop="deliveryId">
<el-select
v-model="ruleForm.deliveryId"
placeholder="请选择运送清单"
clearable
filterable
style="width: 100%"
@change="handleDeliveryChange"
>
<el-option
v-for="item in deliveryList"
:key="item.id"
:label="`${item.deliveryNumber || '--'} - ${item.licensePlate || '--'}`"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="订单" prop="orderId">
<el-select
v-model="ruleForm.orderId"
placeholder="请选择订单(可多选)"
multiple
clearable
filterable
style="width: 100%"
>
<el-option
v-for="item in orderList"
:key="item.id"
:label="`订单${item.id} - 单价: ${item.firmPrice || '--'}元/斤`"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="进仓时间" prop="inTime">
<el-date-picker
v-model="ruleForm.inTime"
type="datetime"
placeholder="请选择进仓时间"
style="width: 100%"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="来源地" prop="sourceLocation">
<el-input
v-model="ruleForm.sourceLocation"
placeholder="请输入来源地"
maxlength="255"
style="width: calc(100% - 100px); margin-right: 10px;"
/>
<el-button type="primary" @click="openSourceLocationMap">选择位置</el-button>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="来源地经度">
<el-input v-model="ruleForm.sourceLon" placeholder="经度" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="来源地纬度">
<el-input v-model="ruleForm.sourceLat" placeholder="纬度" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="牛只数量(头)" prop="cattleCount">
<el-input-number
v-model="ruleForm.cattleCount"
:min="1"
:max="9999"
placeholder="请输入牛只数量"
style="width: 100%"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="重量(公斤)" prop="weight">
<el-input-number
v-model="ruleForm.weight"
:min="0"
:precision="2"
placeholder="请输入重量"
style="width: 100%"
>
<template #append>kg</template>
</el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-select v-model="ruleForm.status" placeholder="请选择状态" style="width: 100%">
<el-option label="待进仓" :value="1" />
<el-option label="已进仓" :value="2" />
<el-option label="已出仓" :value="3" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="照片">
<div style="display: flex; flex-direction: column; gap: 10px;">
<!-- 拖拽上传区域 -->
<el-upload
drag
action="#"
:auto-upload="false"
:before-upload="beforePhotoUpload"
:limit="9"
accept="image/*"
:on-change="handlePhotoChange"
:show-file-list="false"
style="width: 100%"
>
<el-icon class="el-icon--upload"><UploadFilled /></el-icon>
<div class="el-upload__text">将图片文件拖到此处<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip">支持 jpg/png/gif 格式单个文件不超过 10MB最多上传 9 </div>
</template>
</el-upload>
<!-- 图片预览列表 -->
<div v-if="photoFileList.length > 0" class="photo-preview-list">
<div
v-for="(file, index) in photoFileList"
:key="index"
class="photo-preview-item"
>
<el-image
:src="file.url || file.response?.data?.url || ''"
fit="cover"
class="photo-preview-image"
:preview-src-list="photoFileList.map(f => f.url || f.response?.data?.url || '').filter(Boolean)"
:initial-index="index"
/>
<el-button
type="danger"
:icon="Delete"
circle
size="small"
class="photo-delete-btn"
@click="handlePhotoRemove(file)"
/>
</div>
</div>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="视频">
<el-upload
drag
action="#"
:auto-upload="false"
:on-change="handleVideoChange"
:on-remove="handleVideoRemove"
:before-upload="beforeVideoUpload"
:limit="3"
accept="video/*"
:show-file-list="false"
style="width: 100%"
>
<el-icon class="el-icon--upload"><UploadFilled /></el-icon>
<div class="el-upload__text">将视频文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip">支持 mp4/avi/rmvb/mkv 格式,单个文件不超过 100MB最多上传 3 个</div>
</template>
</el-upload>
<!-- 视频预览列表 -->
<div v-if="videoFileList.length > 0" class="video-preview-list">
<div
v-for="(file, index) in videoFileList"
:key="index"
class="video-preview-item"
>
<video
:src="file.url || file.response?.data?.url || ''"
controls
class="video-preview-player"
></video>
<div class="video-name">{{ file.name || '视频' }}</div>
<el-button
type="danger"
:icon="Delete"
circle
size="small"
class="video-delete-btn"
@click="handleVideoRemove(file)"
/>
</div>
</div>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="备注">
<el-input
v-model="ruleForm.remark"
type="textarea"
:rows="3"
placeholder="请输入备注"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button v-if="!data.isDetail" :loading="data.saveLoading" type="primary" @click="onClickSave">
保存
</el-button>
<el-button @click="handleClose">{{ data.isDetail ? '关闭' : '取消' }}</el-button>
</span>
</template>
</el-dialog>
<!-- 来源地地址选择地图 -->
<el-dialog v-model="showSourceLocationMap" title="选择来源地地址" width="900px">
<baidu-map
class="map"
:center="ruleForm.sourceLon && ruleForm.sourceLat ? {lng: parseFloat(ruleForm.sourceLon), lat: parseFloat(ruleForm.sourceLat)} : {lng: 116.404, lat: 39.915}"
:zoom="15"
:scroll-wheel-zoom="true"
@click="handleSourceLocationClick"
style="height: 500px"
>
<bm-marker
v-if="ruleForm.sourceLon && ruleForm.sourceLat"
:position="{lng: parseFloat(ruleForm.sourceLon), lat: parseFloat(ruleForm.sourceLat)}"
:dragging="true"
@dragging="handleSourceMarkerDrag"
/>
<bm-map-type :map-types="['BMAP_NORMAL_MAP', 'BMAP_HYBRID_MAP']"></bm-map-type>
</baidu-map>
<template #footer>
<span class="dialog-footer">
<el-button @click="showSourceLocationMap = false">取消</el-button>
<el-button type="primary" @click="showSourceLocationMap = false">确定</el-button>
</span>
</template>
</el-dialog>
<!-- 图片预览 -->
<el-dialog v-model="showImageViewer" title="图片预览" width="800px">
<el-image :src="imageViewerUrl" style="width: 100%" fit="contain" />
</el-dialog>
</template>
<script setup>
import { ref, reactive, watch } from 'vue';
import { ElMessage } from 'element-plus';
import { Plus, UploadFilled, Delete } from '@element-plus/icons-vue';
import { BaiduMap, BmMapType, BmMarker } from 'vue-baidu-map-3x';
import { warehouseInAdd, warehouseInEdit, warehouseInDetail } from '@/api/warehouseIn.js';
import { warehouseAll } from '@/api/warehouse.js';
import { orderPageQuery, shippingList } from '@/api/shipping.js';
const emits = defineEmits(['success']);
const formDataRef = ref(null);
const showSourceLocationMap = ref(false);
const showImageViewer = ref(false);
const imageViewerUrl = ref('');
const photoFileList = ref([]);
const videoFileList = ref([]);
const warehouseList = ref([]);
const orderList = ref([]);
const deliveryList = ref([]);
const data = reactive({
dialogVisible: false,
saveLoading: false,
editId: null,
isDetail: false,
});
const ruleForm = reactive({
id: null,
warehouseId: null,
orderId: [],
deliveryId: null,
sourceLocation: '',
sourceLon: '',
sourceLat: '',
cattleCount: null,
weight: null,
inTime: '',
photos: '',
videos: '',
remark: '',
status: 1,
});
const rules = reactive({
warehouseId: [
{ required: true, message: '请选择中转仓', trigger: 'change' },
],
deliveryId: [
{ required: true, message: '请选择运送清单', trigger: 'change' },
],
cattleCount: [
{ required: true, message: '请输入牛只数量', trigger: 'blur' },
{ type: 'number', min: 1, message: '牛只数量必须大于0', trigger: 'blur' },
],
inTime: [
{ required: true, message: '请选择进仓时间', trigger: 'change' },
],
});
// 加载中转仓列表
const loadWarehouseList = async () => {
try {
const res = await warehouseAll();
if (res.code === 200) {
warehouseList.value = res.data || [];
}
} catch (error) {
console.error('加载中转仓列表失败', error);
}
};
// 加载订单列表
const loadOrderList = async () => {
try {
const res = await orderPageQuery({ pageNum: 1, pageSize: 1000 });
if (res.code === 200) {
const responseData = res.data || res;
if (responseData && typeof responseData === 'object' && 'rows' in responseData) {
orderList.value = responseData.rows || [];
} else if (responseData && responseData.data && 'rows' in responseData.data) {
orderList.value = responseData.data.rows || [];
} else {
orderList.value = [];
}
}
} catch (error) {
console.error('加载订单列表失败', error);
}
};
// 加载运送清单列表
const loadDeliveryList = async () => {
try {
const res = await shippingList({ pageNum: 1, pageSize: 1000 });
if (res.code === 200) {
const responseData = res.data || res;
if (responseData && typeof responseData === 'object' && 'rows' in responseData) {
deliveryList.value = responseData.rows || [];
} else if (responseData && responseData.data && 'rows' in responseData.data) {
deliveryList.value = responseData.data.rows || [];
} else {
deliveryList.value = [];
}
}
} catch (error) {
console.error('加载运送清单列表失败', error);
}
};
const handleClose = () => {
if (formDataRef.value) {
formDataRef.value.resetFields();
}
Object.assign(ruleForm, {
id: null,
warehouseId: null,
orderId: [],
deliveryId: null,
sourceLocation: '',
sourceLon: '',
sourceLat: '',
cattleCount: null,
weight: null,
inTime: '',
photos: '',
videos: '',
remark: '',
status: 1,
});
photoFileList.value = [];
videoFileList.value = [];
data.editId = null;
data.isDetail = false;
data.dialogVisible = false;
};
const onClickSave = () => {
if (!formDataRef.value) {
return;
}
formDataRef.value.validate((valid) => {
if (!valid) {
return false;
}
data.saveLoading = true;
// 处理订单ID多个订单用逗号分隔
const orderIdStr = ruleForm.orderId && ruleForm.orderId.length > 0
? ruleForm.orderId.join(',')
: null;
// 处理照片和视频URL多个用逗号分隔
const photosStr = photoFileList.value.map(file => file.url || file.response?.data?.url || '').filter(url => url).join(',');
const videosStr = videoFileList.value.map(file => file.url || file.response?.data?.url || '').filter(url => url).join(',');
const params = {
warehouseId: ruleForm.warehouseId,
orderId: orderIdStr,
deliveryId: ruleForm.deliveryId,
sourceLocation: ruleForm.sourceLocation,
sourceLon: ruleForm.sourceLon,
sourceLat: ruleForm.sourceLat,
cattleCount: ruleForm.cattleCount,
weight: ruleForm.weight,
inTime: ruleForm.inTime,
photos: photosStr,
videos: videosStr,
remark: ruleForm.remark,
};
if (data.editId) {
// 编辑
params.id = data.editId;
params.status = ruleForm.status;
warehouseInEdit(params)
.then((res) => {
if (res.code === 200) {
ElMessage.success('编辑成功');
handleClose();
emits('success');
} else {
ElMessage.error(res.msg || '编辑失败');
}
})
.catch((error) => {
ElMessage.error('编辑失败:' + (error.message || '未知错误'));
})
.finally(() => {
data.saveLoading = false;
});
} else {
// 新增
warehouseInAdd(params)
.then((res) => {
if (res.code === 200) {
ElMessage.success('新增成功');
handleClose();
emits('success');
} else {
ElMessage.error(res.msg || '新增失败');
}
})
.catch((error) => {
ElMessage.error('新增失败:' + (error.message || '未知错误'));
})
.finally(() => {
data.saveLoading = false;
});
}
});
};
const onShowDialog = (row, isDetail = false) => {
data.isDetail = isDetail || false;
data.editId = null;
if (row) {
data.editId = row.id;
// 如果是详情模式,先获取详情数据
if (isDetail) {
warehouseInDetail(row.id)
.then((res) => {
if (res.code === 200 && res.data) {
const detailData = res.data;
Object.assign(ruleForm, {
id: detailData.id,
warehouseId: detailData.warehouseId,
orderId: detailData.orderId ? detailData.orderId.split(',').map(id => parseInt(id)) : [],
deliveryId: detailData.deliveryId,
sourceLocation: detailData.sourceLocation || '',
sourceLon: detailData.sourceLon || '',
sourceLat: detailData.sourceLat || '',
cattleCount: detailData.cattleCount,
weight: detailData.weight,
inTime: detailData.inTime || '',
photos: detailData.photos || '',
videos: detailData.videos || '',
remark: detailData.remark || '',
status: detailData.status !== undefined ? detailData.status : 1,
});
// 处理照片和视频文件列表
if (detailData.photos) {
photoFileList.value = detailData.photos.split(',').map(url => ({ url, name: 'photo' }));
}
if (detailData.videos) {
videoFileList.value = detailData.videos.split(',').map(url => ({ url, name: 'video' }));
}
}
})
.catch((error) => {
ElMessage.error('获取详情失败:' + (error.message || '未知错误'));
});
} else {
// 编辑模式,直接使用传入的数据
Object.assign(ruleForm, {
id: row.id,
warehouseId: row.warehouseId,
orderId: row.orderId ? row.orderId.split(',').map(id => parseInt(id)) : [],
deliveryId: row.deliveryId,
sourceLocation: row.sourceLocation || '',
sourceLon: row.sourceLon || '',
sourceLat: row.sourceLat || '',
cattleCount: row.cattleCount,
weight: row.weight,
inTime: row.inTime || '',
photos: row.photos || '',
videos: row.videos || '',
remark: row.remark || '',
status: row.status !== undefined ? row.status : 1,
});
// 处理照片和视频文件列表
if (row.photos) {
photoFileList.value = row.photos.split(',').map(url => ({ url, name: 'photo' }));
}
if (row.videos) {
videoFileList.value = row.videos.split(',').map(url => ({ url, name: 'video' }));
}
}
} else {
// 新增模式,重置表单
Object.assign(ruleForm, {
id: null,
warehouseId: null,
orderId: [],
deliveryId: null,
sourceLocation: '',
sourceLon: '',
sourceLat: '',
cattleCount: null,
weight: null,
inTime: '',
photos: '',
videos: '',
remark: '',
status: 1,
});
photoFileList.value = [];
videoFileList.value = [];
}
data.dialogVisible = true;
};
// 中转仓选择变化
const handleWarehouseChange = (warehouseId) => {
// 可以在这里添加逻辑
};
// 运送清单选择变化
const handleDeliveryChange = (deliveryId) => {
if (!deliveryId) {
// 清空相关字段
ruleForm.sourceLocation = '';
ruleForm.sourceLon = '';
ruleForm.sourceLat = '';
ruleForm.cattleCount = null;
ruleForm.weight = null;
return;
}
// 从 deliveryList 中找到对应的运送清单
const selectedDelivery = deliveryList.value.find(item => item.id === deliveryId);
if (selectedDelivery) {
// 自动填充来源地信息
if (selectedDelivery.startLocation) {
ruleForm.sourceLocation = selectedDelivery.startLocation;
}
if (selectedDelivery.startLon) {
ruleForm.sourceLon = selectedDelivery.startLon;
}
if (selectedDelivery.startLat) {
ruleForm.sourceLat = selectedDelivery.startLat;
}
// 自动填充牛只数量
if (selectedDelivery.ratedQuantity) {
ruleForm.cattleCount = selectedDelivery.ratedQuantity;
}
// 自动计算重量entruckWeight - emptyWeight
if (selectedDelivery.entruckWeight && selectedDelivery.emptyWeight) {
const entruckWeight = parseFloat(selectedDelivery.entruckWeight) || 0;
const emptyWeight = parseFloat(selectedDelivery.emptyWeight) || 0;
const calculatedWeight = entruckWeight - emptyWeight;
if (calculatedWeight > 0) {
ruleForm.weight = parseFloat(calculatedWeight.toFixed(2));
}
} else if (selectedDelivery.entruckWeight) {
// 如果只有装车重量,也可以填充
ruleForm.weight = parseFloat(selectedDelivery.entruckWeight) || null;
}
}
};
// 打开来源地地图选择地址
const openSourceLocationMap = () => {
if (ruleForm.sourceLocation && ruleForm.sourceLocation.trim()) {
showSourceLocationMap.value = true;
setTimeout(() => {
if (window.BMap && window.BMap.Geocoder) {
const geocoder = new window.BMap.Geocoder();
geocoder.getPoint(ruleForm.sourceLocation, (point) => {
if (point) {
ruleForm.sourceLon = point.lng;
ruleForm.sourceLat = point.lat;
ElMessage.success('已定位到该地址');
} else {
ElMessage.warning('未找到该地址,请在地图上手动选择');
}
});
}
}, 500);
} else {
showSourceLocationMap.value = true;
}
};
// 地图点击事件
const handleSourceLocationClick = (e) => {
ruleForm.sourceLon = e.point.lng;
ruleForm.sourceLat = e.point.lat;
if (window.BMap && window.BMap.Geocoder) {
const geocoder = new window.BMap.Geocoder();
geocoder.getLocation(e.point, (res) => {
if (res) {
ruleForm.sourceLocation = res.address;
ElMessage.success('已设置来源地地址');
}
});
}
};
// 标记拖拽事件
const handleSourceMarkerDrag = (e) => {
ruleForm.sourceLon = e.point.lng;
ruleForm.sourceLat = e.point.lat;
if (window.BMap && window.BMap.Geocoder) {
const geocoder = new window.BMap.Geocoder();
geocoder.getLocation(e.point, (res) => {
if (res) {
ruleForm.sourceLocation = res.address;
}
});
}
};
// 图片预览(保留用于兼容)
const handlePictureCardPreview = (file) => {
imageViewerUrl.value = file.url || file.response?.data?.url || '';
showImageViewer.value = true;
};
// 照片文件变化处理(拖拽上传时触发)
const handlePhotoChange = (file, fileList) => {
// 验证文件
if (!beforePhotoUpload(file)) {
return;
}
// 手动上传文件
uploadPhotoFile(file);
};
// 手动上传照片文件
const uploadPhotoFile = async (file) => {
const formData = new FormData();
formData.append('file', file.raw || file);
try {
// 获取 token
let token = '';
const userStore = localStorage.getItem('userStore');
if (userStore) {
const us = JSON.parse(userStore);
token = us.token || '';
}
const response = await fetch('/api/common/upload', {
method: 'POST',
headers: {
'Authorization': token,
},
body: formData,
});
const result = await response.json();
if (result.code === 200) {
const photoUrl = result.data?.url || result.data;
photoFileList.value.push({
url: photoUrl,
name: file.name,
uid: file.uid || Date.now(),
});
ElMessage.success('照片上传成功');
} else {
ElMessage.error(result.msg || '照片上传失败');
}
} catch (error) {
console.error('照片上传失败:', error);
ElMessage.error('照片上传失败');
}
};
// 删除照片
const handlePhotoRemove = (file) => {
const index = photoFileList.value.findIndex(item => item.uid === file.uid || item.url === file.url);
if (index > -1) {
photoFileList.value.splice(index, 1);
}
};
// 视频文件变化处理(拖拽上传时触发)
const handleVideoChange = (file, fileList) => {
// 验证文件
if (!beforeVideoUpload(file)) {
return;
}
// 手动上传文件
uploadVideoFile(file);
};
// 手动上传视频文件
const uploadVideoFile = async (file) => {
const formData = new FormData();
formData.append('file', file.raw || file);
try {
// 获取 token
let token = '';
const userStore = localStorage.getItem('userStore');
if (userStore) {
const us = JSON.parse(userStore);
token = us.token || '';
}
const response = await fetch('/api/common/upload', {
method: 'POST',
headers: {
'Authorization': token,
},
body: formData,
});
const result = await response.json();
if (result.code === 200) {
const videoUrl = result.data?.url || result.data;
videoFileList.value.push({
url: videoUrl,
name: file.name,
uid: file.uid || Date.now(),
});
ElMessage.success('视频上传成功');
} else {
ElMessage.error(result.msg || '视频上传失败');
}
} catch (error) {
console.error('视频上传失败:', error);
ElMessage.error('视频上传失败');
}
};
// 删除视频
const handleVideoRemove = (file) => {
const index = videoFileList.value.findIndex(item => item.uid === file.uid || item.url === file.url);
if (index > -1) {
videoFileList.value.splice(index, 1);
}
};
// 上传前验证照片
const beforePhotoUpload = (file) => {
const isImage = file.type.startsWith('image/');
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isImage) {
ElMessage.error('只能上传图片文件!');
return false;
}
if (!isLt10M) {
ElMessage.error('图片大小不能超过 10MB!');
return false;
}
// 检查数量限制
if (photoFileList.value.length >= 9) {
ElMessage.error('最多只能上传 9 张照片!');
return false;
}
return true; // 允许继续处理
};
// 上传前验证视频
const beforeVideoUpload = (file) => {
const isVideo = file.type.startsWith('video/');
const isLt100M = file.size / 1024 / 1024 < 100;
if (!isVideo) {
ElMessage.error('只能上传视频文件!');
return false;
}
if (!isLt100M) {
ElMessage.error('视频大小不能超过 100MB!');
return false;
}
// 检查数量限制
if (videoFileList.value.length >= 3) {
ElMessage.error('最多只能上传 3 个视频!');
return false;
}
return true; // 允许继续处理
};
// 监听对话框打开,加载数据
watch(() => data.dialogVisible, (newVal) => {
if (newVal) {
loadWarehouseList();
loadOrderList();
loadDeliveryList();
}
});
// 暴露方法给父组件调用
defineExpose({
onShowDialog,
});
</script>
<style scoped lang="scss">
.map {
width: 100%;
height: 500px;
}
/* 照片预览列表样式 */
.photo-preview-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 10px;
}
.photo-preview-item {
position: relative;
width: 120px;
height: 120px;
border: 1px solid #dcdfe6;
border-radius: 6px;
overflow: hidden;
}
.photo-preview-image {
width: 100%;
height: 100%;
}
.photo-delete-btn {
position: absolute;
top: 5px;
right: 5px;
z-index: 10;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
/* 视频预览列表样式 */
.video-preview-list {
display: flex;
flex-direction: column;
gap: 15px;
margin-top: 15px;
}
.video-preview-item {
position: relative;
border: 1px solid #dcdfe6;
border-radius: 6px;
padding: 10px;
background-color: #f5f7fa;
}
.video-preview-player {
width: 100%;
max-height: 300px;
border-radius: 4px;
}
.video-name {
margin-top: 8px;
font-size: 12px;
color: #606266;
text-align: center;
}
.video-delete-btn {
position: absolute;
top: 15px;
right: 15px;
z-index: 10;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
</style>