| | |
| | | <Button @click="toPrint" type="primary" ghost |
| | | v-if="allowOperation.ship && logisticsType != 'SHUNFENG'">打印电子面单</Button> |
| | | <Button @click="modifyRemark" type="primary">添加备注</Button> |
| | | <!-- 将编辑模板按钮移到这里 --> |
| | | <Button v-if="orderInfo.userCheckTemplates && orderInfo.userCheckTemplates.length > 0" |
| | | @click="editTemplateInfo(orderInfo.userCheckTemplates[0].templateId, sn)" |
| | | type="primary">编辑模板</Button> |
| | | </div> |
| | | </Card> |
| | | |
| | |
| | | }} |
| | | </div> |
| | | </div> |
| | | <div class="div-item" > |
| | | <div class="div-item-left">商品模板:</div> |
| | | <div class="div-item-right"> |
| | | <template v-if="orderInfo.orderItems[0] && orderInfo.orderItems[0].goodsCustomizeTemplateVO"> |
| | | {{ |
| | | orderInfo.orderItems[0].goodsCustomizeTemplateVO.templateName |
| | | }} |
| | | </template> |
| | | <template v-else> |
| | | 暂无 |
| | | </template> |
| | | </div> |
| | | </div> |
| | | <div class="div-item" > |
| | | <div class="div-item-left">模板标题:</div> |
| | | <div class="div-item-right"> |
| | | <!-- 先逐层判断是否存在,避免报错 --> |
| | | <template v-if="orderInfo.orderItems[0] && orderInfo.orderItems[0].goodsCustomizeTemplateVO && orderInfo.orderItems[0].goodsCustomizeTemplateVO.titles && orderInfo.orderItems[0].goodsCustomizeTemplateVO.titles.length"> |
| | | <span |
| | | v-for="(item, index) in orderInfo.orderItems[0].goodsCustomizeTemplateVO.titles" |
| | | :key="index" |
| | | >{{ item.templateTitle }} |
| | | <span v-if="index !== orderInfo.orderItems[0].goodsCustomizeTemplateVO.titles.length - 1">、</span> |
| | | </span> |
| | | </template> |
| | | <template v-else> |
| | | 暂无 |
| | | </template> |
| | | </div> |
| | | </div> |
| | | <div class="div-item"> |
| | | <div class="div-item-left">模板图片:</div> |
| | | <div class="div-item-right"> |
| | | <!-- 图片列表容器 --> |
| | | <div v-if="hasImages" class="image-list"> |
| | | <div |
| | | class="image-item" |
| | | v-for="(image, index) in imageList" |
| | | :key="index" |
| | | @click="previewImage(index)" |
| | | > |
| | | <img |
| | | :src="image.imgUrl" |
| | | :alt="'模板图片' + (index + 1)" |
| | | class="small-image" |
| | | loading="lazy" |
| | | > |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 无图片时显示 --> |
| | | <div v-else >暂无图片</div> |
| | | |
| | | <!-- 图片预览弹窗 --> |
| | | <div v-if="isPreviewVisible" class="preview-modal" @click="closePreview"> |
| | | <div class="preview-content" @click.stop> |
| | | <img |
| | | :src="currentPreviewImage" |
| | | :alt="`预览图片 ${currentPreviewIndex + 1}`" |
| | | class="preview-image" |
| | | > |
| | | <div class="preview-nav"> |
| | | <button class="close-btn" @click="closePreview">×</button> |
| | | </Col> |
| | | <Col span="24"> |
| | | <!-- 外层容器:循环遍历 userCheckTemplates 集合 --> |
| | | <div class="check-template-list"> |
| | | <div class="template-item" v-for="(item, index) in orderInfo.userCheckTemplates" :key="item.id"> |
| | | <!-- 2. 模板标题:仅第一个循环项显示 templateName(index===0 控制) --> |
| | | <div class="div-item" > <!-- 关键:仅首项渲染 --> |
| | | <div class="div-item-left">商品模板:</div> |
| | | <div class="div-item-right"> |
| | | {{ item.templateName || '无模板标题' }} <!-- 处理空值默认显示 --> |
| | | </div> |
| | | </div> |
| | | <!-- 4. 选择图片:渲染 chooseImg 字段(处理 null/空值) --> |
| | | <div class="div-item"> |
| | | <div class="div-item-left">模板图片:</div> |
| | | <div class="div-item-right"> |
| | | <img |
| | | v-if="item.chooseImg" |
| | | :src="getImageUrl(item.chooseImg)" |
| | | alt="选择的图片" |
| | | class="selected-img" |
| | | style="max-width: 200px; max-height: 150px;" |
| | | > |
| | | <span v-else>无选择图片</span> <!-- 无图片时默认文本 --> |
| | | </div> |
| | | </div> |
| | | <!-- 1. 商品模板:每个循环项都显示 subName --> |
| | | <div class="div-item"> |
| | | <div class="div-item-left">模板标题:</div> |
| | | <div class="div-item-right"> |
| | | {{ item.subName || '无商品模板名称' }} <!-- 处理空值默认显示 --> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 3. 文本内容:判断 content 是「图片URL」还是「纯文本」 --> |
| | | <div class="div-item"> |
| | | <div class="div-item-left">{{isUrl(item.content)? '图片:':'文本内容'}}</div> |
| | | <div class="div-item-right"> |
| | | <!-- 正则判断:content 以 http/https 开头 → 渲染图片;否则渲染文本 --> |
| | | <img |
| | | v-if="isUrl(item.content)" |
| | | :src="getImageUrl(item.content)" |
| | | alt="内容图片" |
| | | class="content-img" |
| | | style="max-width: 200px; max-height: 150px;" |
| | | > |
| | | <span v-else>{{ item.content || '无文本内容' }}</span> <!-- 纯文本/空值处理 --> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 可选:循环项分隔线,优化视觉 --> |
| | | <hr v-if="index !== orderInfo.userCheckTemplates.length - 1" style="margin: 15px 0; border: none; border-top: 1px solid #eee;"> |
| | | </div> |
| | | </div> |
| | | </Col> |
| | | |
| | |
| | | <div v-if="packageTraceList.length > 0" v-for="(packageItem, packageIndex) in packageTraceList" :key="packageIndex"> |
| | | <div class="layui-layer-wrap"> |
| | | <dl> |
| | | <dt>包裹编号:</dt> |
| | | <dd><div class="text-box">{{ packageItem.packageNo }}</div></dd> |
| | | </dl> |
| | | <dl> |
| | | <dt>物流公司:</dt> |
| | | <dd><div class="text-box">{{ packageItem.logisticsName }}</div></dd> |
| | | </dl> |
| | |
| | | </ul> |
| | | <ul class="express-log" v-else><li>暂无物流信息</li></ul> |
| | | </div> |
| | | <!-- 添加修改物流单号按钮 --> |
| | | <div style="text-align: center; margin-top: 10px;"> |
| | | <Button type="primary" @click="modifyPackageLogistics(packageItem)">修改物流单号</Button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div v-if = "packageTraceList.length == 0 && logisticsInfo"> |
| | |
| | | </ul> |
| | | <ul class="express-log" v-else><li>暂无物流信息</li></ul> |
| | | </div> |
| | | <!-- 添加修改物流单号按钮 --> |
| | | <div style="text-align: center; margin-top: 10px;"> |
| | | <Button type="primary" @click="modifySingleLogistics">修改物流单号</Button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div slot="footer" style="text-align: right"> |
| | |
| | | </div> |
| | | </Modal> |
| | | |
| | | |
| | | <!-- 修改物流单号弹窗 --> |
| | | <Modal v-model="modifyLogisticsModal" width="530"> |
| | | <p slot="header"> |
| | | <Icon type="edit"></Icon> |
| | | <span>修改物流单号</span> |
| | | </p> |
| | | <div> |
| | | <Form ref="modifyLogisticsForm" :model="modifyLogisticsForm" label-position="left" :label-width="100" :rules="modifyLogisticsValidate"> |
| | | <FormItem label="包裹编号" prop="packageNo"> |
| | | <Input v-model="modifyLogisticsForm.packageNo" size="large" disabled></Input> |
| | | </FormItem> |
| | | <FormItem label="订单编号" prop="orderSn"> |
| | | <Input v-model="modifyLogisticsForm.orderSn" size="large" disabled></Input> |
| | | </FormItem> |
| | | <FormItem label="快递公司" prop="logisticsId"> |
| | | <Select v-model="modifyLogisticsForm.logisticsId" placeholder="请选择快递公司" style="width: 100%"> |
| | | <Option v-for="(item, i) in checkedLogistics" :key="i" :value="item.logisticsId">{{ item.name }}</Option> |
| | | </Select> |
| | | </FormItem> |
| | | <FormItem label="快递单号" prop="logisticsNo"> |
| | | <Input v-model="modifyLogisticsForm.logisticsNo" size="large"></Input> |
| | | </FormItem> |
| | | <!-- <FormItem label="快递编码" prop="logisticsCode">--> |
| | | <!-- <Input v-model="modifyLogisticsForm.logisticsCode" size="large"></Input>--> |
| | | <!-- </FormItem>--> |
| | | </Form> |
| | | </div> |
| | | <div slot="footer" style="text-align: right"> |
| | | <Button @click="modifyLogisticsModal = false">关闭</Button> |
| | | <Button type="primary" @click="modifyLogisticsSubmit">确认修改</Button> |
| | | </div> |
| | | </Modal> |
| | | <!-- 订单发货 --> |
| | | <Modal v-model="orderDeliverModal" width="500px"> |
| | | <p slot="header"> |
| | |
| | | </Modal> |
| | | |
| | | <multipleMap ref="map" @callback="getAddress"></multipleMap> |
| | | |
| | | <!-- 添加模板编辑弹窗 --> |
| | | <EditTemplateModal |
| | | v-model="editTemplateModalVisible" |
| | | :template-id="currentTemplateId" |
| | | :order-sn="sn" |
| | | :user-check-templates="orderInfo.userCheckTemplates" |
| | | @success="handleTemplateEditSuccess" |
| | | @cancel="editTemplateModalVisible = false" |
| | | /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import * as API_Order from "@/api/order"; |
| | | import * as API_Logistics from "@/api/logistics"; |
| | | import * as RegExp from "@/libs/RegExp.js"; |
| | | import { getSts } from "@/api/file"; |
| | | |
| | | import multipleMap from "@/views/my-components/map/multiple-map"; |
| | | |
| | | import EditTemplateModal from "./editTemplateModal.vue"; |
| | | |
| | | export default { |
| | | name: "orderDetail", |
| | | components: { |
| | | multipleMap, |
| | | EditTemplateModal |
| | | }, |
| | | data () { |
| | | return { |
| | | isPreviewVisible: false, |
| | | currentPreviewImage: '', |
| | | currentPreviewIndex: 0, |
| | | // isPreviewVisible: false, |
| | | // currentPreviewImage: '', |
| | | // currentPreviewIndex: 0, |
| | | |
| | | loading:false, |
| | | typeList: [], |
| | |
| | | }, |
| | | submitLoading: false, // 添加或编辑提交状态 |
| | | logisticsType: 'KUAIDINIAO', //物流类型 |
| | | endpoint: '', // 添加endpoint变量用于存储STS endpoint |
| | | |
| | | someJSONdata: '', |
| | | faceSheetForm: { |
| | |
| | | }, |
| | | ], |
| | | orderPackage: [], |
| | | packageTraceList: [] |
| | | packageTraceList: [], |
| | | // 添加模板编辑弹窗相关数据 |
| | | editTemplateModalVisible: false, |
| | | currentTemplateId: "", |
| | | // 用于传递userCheckTemplates数据给子组件 |
| | | userCheckTemplates: [], |
| | | |
| | | // 添加修改物流单号相关数据 |
| | | modifyLogisticsModal: false, // 弹出修改物流单号框 |
| | | modifyLogisticsForm: { |
| | | packageNo: "", |
| | | orderSn: "", |
| | | logisticsId: "", |
| | | logisticsNo: "", |
| | | logisticsCode: "" |
| | | }, |
| | | modifyLogisticsValidate: { |
| | | logisticsId: [ |
| | | { required: true, message: "请选择快递公司", trigger: "change" } |
| | | ], |
| | | logisticsNo: [ |
| | | { required: true, message: "请输入快递单号", trigger: "blur" } |
| | | ] |
| | | }, |
| | | |
| | | }; |
| | | }, |
| | | computed: { |
| | | // 获取图片列表(处理空值情况) |
| | | imageList() { |
| | | console.log(this.orderInfo.orderItems[0].goodsCustomizeTemplateVO) |
| | | if (this.orderInfo && |
| | | this.orderInfo.orderItems && |
| | | this.orderInfo.orderItems[0] && |
| | | this.orderInfo.orderItems[0].goodsCustomizeTemplateVO && |
| | | this.orderInfo.orderItems[0].goodsCustomizeTemplateVO.listImages && |
| | | Array.isArray(this.orderInfo.orderItems[0].goodsCustomizeTemplateVO.listImages)) { |
| | | return this.orderInfo.orderItems[0].goodsCustomizeTemplateVO.listImages; |
| | | } |
| | | return []; |
| | | }, |
| | | // 判断是否有图片 |
| | | hasImages() { |
| | | return this.imageList.length > 0; |
| | | } |
| | | }, |
| | | methods: { |
| | | previewImage(index) { |
| | | if (this.imageList[index]) { |
| | | this.currentPreviewIndex = index; |
| | | this.currentPreviewImage = this.imageList[index].imgUrl; |
| | | this.isPreviewVisible = true; |
| | | // 阻止页面滚动 |
| | | document.body.style.overflow = 'hidden'; |
| | | } |
| | | isUrl(str) { |
| | | if (!str) return false; // 空值直接返回false |
| | | // 正则说明: |
| | | // 1. https?:// :支持http/https协议 |
| | | // 2. ([\w-]+\.)+ :允许子域名包含短横线(如lmk-1356772813) |
| | | // 3. [a-zA-Z]{2,} :顶级域名(如com、cn,至少2个字母) |
| | | // 4. (\w-./?%&=)* :URL路径/参数部分,支持常见字符 |
| | | // 5. \.(jpg|jpeg|png|gif|bmp|webp)$ :仅匹配常见图片后缀,忽略大小写(i标志) |
| | | const imgReg = /^https?:\/\/([\w-]+\.)+[a-zA-Z]{2,}(\/[\w-./?%&=]*)*\.(jpg|jpeg|png|gif|bmp|webp)$/i; |
| | | return imgReg.test(str); |
| | | }, |
| | | // 关闭预览 |
| | | closePreview() { |
| | | this.isPreviewVisible = false; |
| | | // 恢复页面滚动 |
| | | document.body.style.overflow = ''; |
| | | // 获取图片URL(使用STS获取的endpoint) |
| | | getImageUrl(fileKey) { |
| | | // 确保fileKey是字符串类型 |
| | | if (!fileKey || typeof fileKey !== 'string') { |
| | | console.warn('fileKey is not a valid string:', fileKey); |
| | | return ''; // 返回空字符串或默认图片 |
| | | } |
| | | |
| | | // 安全检查startsWith方法是否存在 |
| | | if (fileKey.startsWith && typeof fileKey.startsWith === 'function' && |
| | | (fileKey.startsWith("http://") || fileKey.startsWith("https://"))) { |
| | | return fileKey; |
| | | } |
| | | |
| | | // 如果有endpoint配置,使用endpoint拼接URL |
| | | if (this.endpoint) { |
| | | // 确保fileKey不以/开头,endpoint不以/结尾 |
| | | const cleanEndpoint = this.endpoint.replace(/\/$/, ''); |
| | | const cleanFileKey = fileKey.replace(/^\//, ''); |
| | | return `${cleanEndpoint}/${cleanFileKey}`; |
| | | } |
| | | |
| | | // 否则返回fileKey,让组件自己处理 |
| | | return fileKey; |
| | | }, |
| | | // 选中 |
| | | selectGroupShipGoodsMethods (selected) { |
| | |
| | | }) |
| | | }, |
| | | |
| | | // 获取STS信息 |
| | | // async getStsInfo() { |
| | | // try { |
| | | // const stsRes = await getSts(); |
| | | // if (stsRes.success) { |
| | | // this.endpoint = stsRes.data.endpoint; |
| | | // } |
| | | // } catch (error) { |
| | | // console.error('获取STS信息失败:', error); |
| | | // } |
| | | // }, |
| | | |
| | | // 编辑模板信息 |
| | | editTemplateInfo(templateId, orderSn) { |
| | | console.log("调用editTemplateInfo,参数:", { |
| | | templateId: templateId, |
| | | orderSn: orderSn |
| | | }); |
| | | this.currentTemplateId = templateId; |
| | | // 更新userCheckTemplates数据 |
| | | this.userCheckTemplates = this.orderInfo.userCheckTemplates || []; |
| | | this.editTemplateModalVisible = true; |
| | | }, |
| | | |
| | | // 模板编辑成功回调 |
| | | handleTemplateEditSuccess() { |
| | | this.editTemplateModalVisible = false; |
| | | // 可以在这里刷新数据或提示用户 |
| | | this.$Message.success("模板信息已更新"); |
| | | // 刷新订单详情页面数据 |
| | | this.getDataDetail(); |
| | | }, |
| | | |
| | | getStsInfo() { |
| | | getSts().then(res => { |
| | | if (res.code==200) { |
| | | this.endpoint = res.data.endpoint; |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // 添加修改物流单号方法 |
| | | modifyLogisticsNo() { |
| | | // 获取物流公司列表 |
| | | this.getLogisticsList(); |
| | | |
| | | // 初始化表单数据 |
| | | this.modifyLogisticsForm.orderSn = this.sn; |
| | | |
| | | // 如果有包裹信息,初始化第一个包裹的信息 |
| | | if (this.orderPackage && this.orderPackage.length > 0) { |
| | | const firstPackage = this.orderPackage[0]; |
| | | this.modifyLogisticsForm.packageNo = firstPackage.packageNo || ""; |
| | | this.modifyLogisticsForm.logisticsId = firstPackage.logisticsId || ""; |
| | | this.modifyLogisticsForm.logisticsNo = firstPackage.logisticsNo || ""; |
| | | this.modifyLogisticsForm.logisticsCode = firstPackage.logisticsCode || ""; |
| | | } |
| | | |
| | | this.modifyLogisticsModal = true; |
| | | }, |
| | | |
| | | // 修改指定包裹的物流单号 |
| | | modifyPackageLogistics(packageItem) { |
| | | // 获取物流公司列表 |
| | | this.getLogisticsList(); |
| | | |
| | | // 初始化表单数据 |
| | | this.modifyLogisticsForm.packageNo = packageItem.packageNo || ""; |
| | | this.modifyLogisticsForm.orderSn = this.sn; |
| | | this.modifyLogisticsForm.logisticsId = packageItem.logisticsId || ""; |
| | | this.modifyLogisticsForm.logisticsNo = packageItem.logisticsNo || ""; |
| | | this.modifyLogisticsForm.logisticsCode = packageItem.logisticsCode || ""; |
| | | |
| | | // 关闭查看物流弹窗,打开修改物流弹窗 |
| | | this.logisticsModal = false; |
| | | this.modifyLogisticsModal = true; |
| | | }, |
| | | |
| | | // 修改单个物流单号(非分包裹情况) |
| | | modifySingleLogistics() { |
| | | // 获取物流公司列表 |
| | | this.getLogisticsList(); |
| | | |
| | | // 初始化表单数据 |
| | | this.modifyLogisticsForm.orderSn = this.sn; |
| | | this.modifyLogisticsForm.logisticsId = ""; |
| | | this.modifyLogisticsForm.logisticsNo = this.logisticsInfo.logisticCode || ""; |
| | | this.modifyLogisticsForm.logisticsCode = ""; |
| | | |
| | | // 关闭查看物流弹窗,打开修改物流弹窗 |
| | | this.logisticsModal = false; |
| | | this.modifyLogisticsModal = true; |
| | | }, |
| | | |
| | | // 修改物流单号提交 |
| | | modifyLogisticsSubmit() { |
| | | this.$refs.modifyLogisticsForm.validate((valid) => { |
| | | if (valid) { |
| | | API_Order.updateTraces(this.modifyLogisticsForm).then((res) => { |
| | | if (res.success) { |
| | | this.$Message.success("修改物流单号成功"); |
| | | this.modifyLogisticsModal = false; |
| | | // 重新获取订单详情和包裹信息 |
| | | this.getDataDetail(); |
| | | this.getOrderPackage(); |
| | | // 重新加载物流信息 |
| | | this.checkLogistics(); |
| | | } else { |
| | | this.$Message.error(res.message || "修改物流单号失败"); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | }, |
| | | mounted () { |
| | | this.sn = this.$route.query.sn; |
| | | this.getDataDetail(); |
| | | this.getLogisticsSetting(); |
| | | this.getOrderPackage(); |
| | | this.getStsInfo(); // 添加这行来获取STS信息 |
| | | }, |
| | | // 如果是从详情页返回列表页,修改列表页keepAlive为true,确保不刷新页面 |
| | | beforeRouteLeave (to, from, next) { |
| | |
| | | }; |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .image-list { |
| | | display: flex; |
| | | gap: 8px; |
| | | flex-wrap: wrap; |
| | | max-width: 600px; |
| | | } |
| | | |
| | | .image-item { |
| | | cursor: pointer; |
| | | border: 1px solid #eee; |
| | | border-radius: 4px; |
| | | overflow: hidden; |
| | | transition: transform 0.2s; |
| | | } |
| | | |
| | | .image-item:hover { |
| | | transform: scale(1.02); |
| | | } |
| | | |
| | | .small-image { |
| | | width: 80px; |
| | | height: 80px; |
| | | object-fit: cover; |
| | | } |
| | | |
| | | .no-image { |
| | | color: #999; |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | /* 预览弹窗样式 */ |
| | | .preview-modal { |
| | | position: fixed; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: rgba(0, 0, 0, 0.8); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 1000; |
| | | } |
| | | |
| | | .preview-content { |
| | | position: relative; |
| | | max-width: 90%; |
| | | max-height: 90%; |
| | | } |
| | | |
| | | .preview-image { |
| | | max-width: 100%; |
| | | object-fit: contain; |
| | | } |
| | | |
| | | .preview-nav { |
| | | position: absolute; |
| | | top: -30px; |
| | | right: 0; |
| | | color: white; |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 15px; |
| | | } |
| | | |
| | | .preview-count { |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .close-btn { |
| | | background: none; |
| | | border: none; |
| | | color: white; |
| | | font-size: 20px; |
| | | cursor: pointer; |
| | | width: 24px; |
| | | height: 24px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding: 0; |
| | | } |
| | | |
| | | // 建议引入通用样式 可删除下面样式代码 |
| | | // @import "@/styles/table-common.scss"; |
| | | .lineH30 { |
| | |
| | | height: inherit; |
| | | } |
| | | } |
| | | .check-template-list { |
| | | display: flex; |
| | | flex-wrap: wrap; // 关键:多余子项自动换行 |
| | | gap: 15px; // 子项之间的间距(水平+垂直) |
| | | padding: 10px 0; // 上下内边距,避免贴边 |
| | | width: 100%; // 占满父容器(Col span="12") |
| | | } |
| | | |
| | | // 2. 每个模板项:控制宽度和卡片样式 |
| | | .template-item { |
| | | min-width: 280px; // 最小宽度,避免过窄 |
| | | max-width: 350px; // 最大宽度,防止过宽 |
| | | flex: 1; // 同一行子项均匀分配宽度 |
| | | padding: 12px; |
| | | border: 1px solid #eee; |
| | | border-radius: 6px; |
| | | background-color: #fafafa; |
| | | box-sizing: border-box; // 防止padding撑大宽度 |
| | | } |
| | | .content-img, |
| | | .selected-img { |
| | | max-width: 100%; // 适应子项宽度 |
| | | max-height: 150px; // 限制最大高度 |
| | | border-radius: 4px; |
| | | object-fit: cover; // 保持图片比例,不拉伸 |
| | | } |
| | | </style> |