From 4f9a8b45f77974a5f59fc3e9f5820f03828d8be9 Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期三, 18 六月 2025 17:58:26 +0800 Subject: [PATCH] 视频编辑、下架、删除功能 --- pages/video/video-edit.vue | 497 +++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 337 insertions(+), 160 deletions(-) diff --git a/pages/video/video-edit.vue b/pages/video/video-edit.vue index f8a3ec2..1b51fe7 100644 --- a/pages/video/video-edit.vue +++ b/pages/video/video-edit.vue @@ -1,49 +1,73 @@ <template> <view class="publish-container"> + <u-popup v-model="fileTypeShow" mode="bottom" round="20" height="35%"> + <view style="width: 100%;height:100%;display: flex;flex-direction: column;justify-content: center;align-items: center;"> + <view>璇烽�夋嫨瑕佸彂甯冪殑绫诲瀷</view> + <u-button style="width: 50%;margin-bottom: 30rpx;margin-top: 20rpx;" type="success" @click="chooseVideo">瑙嗛</u-button> + <u-button style="width: 50%;" type="success" @click="chooseImgs">鍥剧墖</u-button> + </view> + </u-popup> <!-- 瑙嗛涓婁紶鍖哄煙 --> <view class="upload-section"> - <view class="upload-btn" @click="chooseVideo" v-if="!videoInfo.url"> + <view class="upload-btn" @click="this.fileTypeShow = true" v-if="!formData.videoFileKey && formData.videoImgs.length < 1"> <u-icon name="plus" size="40" color="#999"></u-icon> - <text class="upload-text">鐐瑰嚮涓婁紶瑙嗛</text> - <text class="upload-tips">鏀寔MP4鏍煎紡锛屾渶闀�60绉�</text> + <text class="upload-text">鐐瑰嚮涓婁紶</text> </view> - - <view class="video-preview" v-else> - <video - :src="videoInfo.url" + + <view class="video-preview" v-else-if="formData.videoContentType === 'video'"> + <video + :src="videoInfo.url" :object-fit="formData.videoFit" class="video-player" :poster="videoInfo.cover || ''" ></video> - <view class="progress-box"> + <view class="progress-box" v-if="showUploadProgress"> <progress style="width: 100%;" :percent="videoUploadProgress" active-mode="forwards" show-info stroke-width="6" :active="true" active-color="#ff573e" /> </view> <view class="video-actions"> <u-button type="error" size="mini" @click="reUpload">閲嶆柊涓婁紶</u-button> - <u-button type="primary" size="mini" @click="chooseCover" v-if="videoInfo.url">{{formData.cover ? '鏇存崲灏侀潰' : '璇烽�夋嫨灏侀潰'}}</u-button> + <u-button type="primary" size="mini" @click="chooseCover" v-if="formData.videoFileKey">{{formData.cover ? '鏇存崲灏侀潰' : '璇烽�夋嫨灏侀潰'}}</u-button> </view> </view> + + <view class="image-list" v-else-if="formData.videoContentType === 'img'"> + <view + v-for="item in videoPreviewImgs" + :key="item" + class="image-item" + :style="{width: itemWidth + 'px', height: itemWidth + 'px'}" + > + <image + :src="item" + mode="aspectFill" + class="image" + /> + </view> + <view class="video-actions"> + <u-button type="error" size="mini" @click="reUpload">閲嶆柊涓婁紶</u-button> + </view> + </view> </view> - + <!-- 瑙嗛淇℃伅琛ㄥ崟 --> <view class="form-section"> <u-form :model="formData" ref="formRef" labelWidth="80"> <!-- 鏍囬杈撳叆 --> <u-form-item label="鏍囬" prop="title" borderBottom> - <u-input - v-model="formData.title" + <u-input + v-model="formData.title" placeholder="璇疯緭鍏ヨ棰戞爣棰�,20瀛椾互鍐�" maxlength="20" show-word-limit clearable /> </u-form-item> - + <!-- 璇濋杈撳叆 --> <u-form-item label="璇濋" prop="tags" borderBottom> <view class="tags-input-container"> - <u-input - v-model="tagInput" + <u-input + v-model="tagInput" placeholder="杈撳叆璇濋锛屽洖杞︾‘璁�" clearable @confirm="addTag" @@ -52,7 +76,7 @@ ></u-input> <!-- 宸查�夎瘽棰樺睍绀� --> <view class="tags-display" v-if="formData.tags.length > 0"> - <my-tag + <my-tag v-for="(tag, index) in formData.tags" :key="index" :text="tag.tagName" @@ -69,7 +93,7 @@ <view class="hot-topics" v-if="showTopicRecommendations"> <text class="section-title">{{ tagInput ? '鎺ㄨ崘璇濋' : '鐑棬璇濋' }}</text> <view class="topic-list"> - <my-tag + <my-tag v-for="(tag, index) in recommendedTags" :key="index" :text="tag.tagName" @@ -81,47 +105,54 @@ </view> </view> </u-form-item> - - + + <!-- 鍟嗗搧閾炬帴 --> <u-form-item label="鍟嗗搧" prop="goodsId" borderBottom> <view class="goods-link-container"> - <u-input + <u-input placeholder="鍙�夋嫨鎺ㄨ崘鍟嗗搧" clearable v-if="!selectedGoods" @click="chooseGoods" disabled > - <u-icon - slot="right" - name="search" - size="24" + <u-icon + slot="right" + name="search" + size="24" @click="chooseGoods" ></u-icon> </u-input> - <view class="goods-preview" v-if="selectedGoods"> - <image :src="selectedGoods.image" class="goods-image"></image> + <view class="goods-preview" @click="chooseGoods" v-for="goods in selectedGoodsList" :key="goods.id"> + <image :src="goods.thumbnail" class="goods-image"></image> <view class="goods-info"> - <text class="goods-name">{{ selectedGoods.name }}</text> - <text class="goods-price">楼{{ selectedGoods.price }}</text> + <text class="goods-name">{{ goods.goodsName }}</text> + <view style="display: flex;"> + <view class="goods-price" style="flex: 1;">楼{{ goods.price }}</view> + <view @click.stop="() => {}" style="flex: 1;display: flex;justify-content: center;align-items: center;"> + <view style="width: 90rpx">鏁伴噺锛�</view> + <uni-number-box v-model="goods.goodsNum" :min="0"/> + </view> + </view> </view> - <u-icon - name="close" - size="20" - @click="clearGoods" + <u-icon + style="position: absolute;right: 8rpx;top: 8rpx" + name="close" + size="24" + @click.stop="clearGoods(goods)" ></u-icon> </view> </view> </u-form-item> </u-form> </view> - + <!-- 鍙戝竷鎸夐挳 --> <view class="publish-btn"> - <u-button - type="primary" - shape="circle" + <u-button + type="success" + shape="circle" :loading="loading" @click="handlePublish" :disabled="!canPublish" @@ -129,7 +160,7 @@ {{ loading ? '鍙戝竷涓�...' : '绔嬪嵆鍙戝竷' }} </u-button> </view> - + <!-- 鍟嗗搧閫夋嫨寮圭獥 --> <u-popup v-model="showGoodsPicker" mode="bottom" round="20" height="70%"> <view class="goods-picker"> @@ -138,34 +169,37 @@ <u-icon name="close" size="24" @click="showGoodsPicker = false"></u-icon> </view> <view class="search-bar"> - <u-search - v-model="goodsSearch" - placeholder="鎼滅储鍟嗗搧鍚嶇О" + <u-search + v-model="goodsQuery.keyword" + placeholder="鎼滅储鍟嗗搧" :showAction="false" + @change="handlerGoodsSearch" ></u-search> </view> - <scroll-view class="goods-list" scroll-y> - <view - class="goods-item" - v-for="goods in filteredGoods" + <scroll-view class="goods-list" @scrolltolower="loadMoreGoods" scroll-y :show-scrollbar="false"> + <view + class="goods-item" + v-for="(goods, index) in goodsList" :key="goods.id" - @click="selectGoods(goods)" + @click="selectGoods(goods, index)" > - <image :src="goods.image" class="goods-image"></image> + <image :src="goods.thumbnail" class="goods-image"></image> <view class="goods-info"> - <text class="goods-name">{{ goods.name }}</text> + <text class="goods-name">{{ goods.goodsName }}</text> <text class="goods-price">楼{{ goods.price }}</text> +<!-- <view>{{ goods.sellingPoint }}</view> --> </view> - <u-icon - name="checkmark" - size="24" - :color="selectedGoods && selectedGoods.id === goods.id ? '#2979ff' : '#ccc'" + <u-icon + v-if="goods.selected" + name="checkmark" + size="36" + :color="'#2979ff'" ></u-icon> </view> </scroll-view> </view> </u-popup> - + <custom-tabbar bgColor="#ffffff" selected="video"></custom-tabbar> </view> </template> @@ -175,21 +209,26 @@ import MyTag from '@/components/my-tag.vue' import { getSTSToken, getFilePreviewUrl } from "@/api/common.js"; -import { publish, getVideoDetail } from "@/api/video.js"; +import { updateVideo, getVideoDetail } from "@/api/video.js"; import { getRecommendTag3 } from "@/api/video-tag.js"; import { getFileKey } from "@/utils/file.js"; +import { getVideoGoodsList } from "@/api/goods.js"; + export default { components: {MyTag}, data() { return { + showUploadProgress: false, + fileTypeShow: false, cosClient: null, bucket: '', region: '', + endpoint: '', videoUploadProgress: 0, loading: false, showGoodsPicker: false, - goodsSearch: '', tagInput: '', + videoPreviewImgs: [], // 棰勮鍥剧墖鍦板潃 videoInfo: { url: '', fileKey: '', @@ -197,6 +236,12 @@ fileSize: 0, originalFileName: '', cover: '' + }, + goodsQuery: { + keyword: '', + searchFromSelfStore: false, // 鏄惁鏄煡璇㈣嚜瀹跺簵閾哄晢鍝� + pageNumber: 1, + pageSize: 5 }, formData: { id: '', @@ -206,49 +251,50 @@ videoDuration: 0, videoFit: 'cover', goodsId: '', + videoContentType: 'video', + videoImgs: [], tags: [], fileInfo: {} }, - selectedGoods: null, - goodsList: [ - { - id: '1', - name: '鏂版鏃犵嚎钃濈墮鑰虫満', - price: '199.00', - image: 'https://via.placeholder.com/100' - }, - { - id: '2', - name: '鏅鸿兘鎵嬬幆杩愬姩鎵嬭〃', - price: '299.00', - image: 'https://via.placeholder.com/100' - } - ], + selectedGoodsList: [], + goodsList: [], + noMoreGoods: false, // 娌℃湁鏇村鍟嗗搧浜� recommendedTags: [], rules: { title: [ { required: true, message: '璇疯緭鍏ヨ棰戞爣棰�', trigger: 'blur' }, { min: 1, max: 20, message: '鏍囬闀垮害鍦�1鍒�20涓瓧绗�', trigger: 'blur' } ] - } + }, + screenWidth: 375, + gap: 10 // 鍥剧墖闂磋窛 }; }, computed: { canPublish() { - return this.formData.videoFileKey && this.formData.title && this.formData.cover; - }, - filteredGoods() { - if (!this.goodsSearch) return this.goodsList; - return this.goodsList.filter(goods => - goods.name.toLowerCase().includes(this.goodsSearch.toLowerCase()) - ); + if(this.formData.videoContentType === 'video') { + return this.formData.videoFileKey && this.formData.title && this.formData.cover; + } else if(this.formData.videoContentType === 'img') { + return this.formData.videoImgs.length > 0 && this.formData.title; + } }, showTopicRecommendations() { return (this.tagInput === '' || this.recommendedTags.length > 0) && this.formData.tags.length < 5; - } + }, + // 璁$畻姣忎釜鍥剧墖椤圭殑瀹藉害锛堣�冭檻闂磋窛锛� + itemWidth() { + return (this.screenWidth - (this.gap * 4) - 20) / 3 + } }, onLoad(option) { - this.getVideoDetail(option.id) + this.getVDetail(option.id) + // 鑾峰彇灞忓箷瀹藉害 + const systemInfo = uni.getSystemInfoSync() + this.screenWidth = systemInfo.windowWidth + this.goodsQuery.pageNumber = 1 + this.goodsQuery.pageSize = 10 + this.getVideoGoodsByEs() + }, onShow() { this.initCOS() @@ -256,23 +302,57 @@ this.getRecommendTags() }, methods: { - getVideoDetail(id) { - getVideoDetail(id).then(res => { - this.fileInfo.cover = res.data.data.coverUrl - this.fileInfo.url = res.data.data.videoUrl - this.formData.cover = res.data.data.coverFileKey - this.formData.id = res.data.data.id - this.formData.title = res.data.data.title - this.formData.videoFileKey = res.data.data.videoFileKey - this.formData.videoFit = res.data.data.videoFit - this.formData.videoDuration = res.data.data.videoDuration - this.formData.goodsId = res.data.data.goodsId - this.formData.tags = res.data.data.tags - }).catch(() => { - uni.navigateBack({ - delta: 1 - }); - }) + getVDetail(id) { + getVideoDetail(id).then(res => { + this.videoInfo.cover = res.data.data.coverUrl + this.videoInfo.url = res.data.data.videoUrl + this.formData.videoImgs = res.data.data.imgs + this.formData.videoContentType = res.data.data.videoContentType + this.formData.cover = res.data.data.coverFileKey + this.formData.id = res.data.data.id + this.formData.title = res.data.data.title + this.formData.videoFileKey = res.data.data.videoFileKey + this.formData.videoFit = res.data.data.videoFit + this.formData.videoDuration = res.data.data.videoDuration + this.selectedGoodsList = res.data.data.goodsList + this.formData.tags = res.data.data.tags + this.showUploadProgress = false + console.log("瑙嗛璇︽儏", this.formData); + }) + }, + // 鍔犺浇鏇村鍟嗗搧 + loadMoreGoods() { + if(this.noMoreGoods) { + return + } + this.goodsQuery.pageNumber += 1; + this.goodsQuery.pageSize = 5; + this.getVideoGoodsByEs() + }, + // 澶勭悊鍟嗗搧鎼滅储鍊� + handlerGoodsSearch() { + this.goodsQuery.pageNumber = 1 + this.goodsQuery.pageSize = 10 + this.getVideoGoodsByEs() + }, + // 鑾峰彇鍟嗗搧鍒嗛〉 + async getVideoGoodsByEs() { + getVideoGoodsList(this.goodsQuery).then(res => { + + if(this.goodsQuery.pageNumber === 1) { + this.goodsList = res.data.data + } else { + this.goodsList = [ + ...this.goodsList, + ...res.data.data.filter( + (newItem) => !this.goodsList.some((oldItem) => oldItem.id === newItem.id) + ), + ]; + } + if(res.data.data.length < this.goodsQuery.pageSize) { + this.noMoreGoods = true; + } + }) }, // 鑾峰彇鎺ㄨ崘鏍囩 async getRecommendTags(type) { @@ -290,7 +370,7 @@ getSTSToken().then(res => { const COS = require('@/lib/cos-wx-sdk-v5.js'); // 寮�鍙戞椂浣跨敤 // const COS = require('./lib/cos-wx-sdk-v5.min.js'); // 涓婄嚎鏃朵娇鐢ㄥ帇缂╁寘 - + // console.log(COS.version); sdk 鐗堟湰闇�瑕佷笉浣庝簬 1.7.2 this.cosClient = new COS({ SecretId: res.data.data.tmpSecretId, // sts 鏈嶅姟涓嬪彂鐨勪复鏃� secretId @@ -302,21 +382,28 @@ }); this.bucket = res.data.data.bucket this.region = res.data.data.region + this.endpoint = res.data.data.endpoint }) - + }, // 閫夋嫨瑙嗛 chooseVideo() { + this.fileTypeShow = false; + // 娓呯┖閫夋嫨鐨勫浘鐗� + this.videoPreviewImgs = []; + this.formData.videoImgs = []; + this.formData.videoContentType = 'video' uni.chooseVideo({ sourceType: ['album', 'camera'], maxDuration: 60, camera: 'back', success: (res) => { this.videoUploadProgress = 0 + // 鑾峰彇鏂囦欢鍚� const tempPath = res.tempFilePath; let fileName = tempPath.substring(tempPath.lastIndexOf('/') + 1); - + // 澶勭悊瀹夊崜鍙兘鐨刄RI缂栫爜 if(fileName.indexOf('%') > -1) { fileName = decodeURIComponent(fileName); @@ -334,12 +421,12 @@ this.formData.videoDuration = res.duration; // 鍒ゆ柇瑙嗛鐨勫~鍏呮ā寮� this.formData.videoFit = this.calculateVideoFit(res.width, res.height) - + this.showUploadProgress = true this.cosClient.uploadFile({ Bucket: this.bucket, Region: this.region, Key: fileKey, - FilePath: res.tempFilePath, + FilePath: res.tempFilePath, SliceSize: 1024 * 1024 * 5, /* 瑙﹀彂鍒嗗潡涓婁紶鐨勯槇鍊�,5M */ onProgress: (progressData) => { console.log(progressData.percent); @@ -357,7 +444,7 @@ cover: '' } } else { - console.log(this.videoInfo); + } }); }, @@ -374,27 +461,75 @@ calculateVideoFit(width, height) { const viewportRatio = uni.getSystemInfoSync().windowWidth / uni.getSystemInfoSync().windowHeight; const videoRatio = width / height; - + // 瑙勫垯1锛氳秴瀹借棰戯紙濡傜數褰�21:9锛� if (videoRatio > 2) return 'contain'; - + // 瑙勫垯2锛氱珫灞忚棰戯紙濡�9:16锛� if (videoRatio < 0.8) return 'cover'; - + // 瑙勫垯3锛氭帴杩戝睆骞曟瘮渚嬬殑妯睆瑙嗛 return Math.abs(videoRatio - viewportRatio) > 0.3 ? 'contain' : 'cover'; }, // 閲嶆柊涓婁紶 reUpload() { this.videoInfo = { - url: '', - cover: '', - duration: 0, - size: 0 + url: '', + fileKey: '', + fileType: '', + fileSize: 0, + originalFileName: '', + cover: '' }; - this.chooseVideo(); + this.formData.videoFileKey = '' + this.formData.cover = '' + this.formData.videoFit = 'cover' + this.formData.videoDuration = 0 + this.formData.videoImgs = [] + this.formData.fileInfo = {} + this.formData.videoContentType = 'video' + this.videoPreviewImgs = [] + this.fileTypeShow = true }, - + // 閫夋嫨瑙嗛鍥鹃泦 + chooseImgs() { + this.fileTypeShow = false + // 娓呯┖閫夋嫨鐨勮棰� + this.formData.videoFileKey = ''; + this.formData.cover = ''; + this.formData.videoContentType = 'img' + uni.chooseImage({ + count: 9, + sizeType: ['compressed'], + sourceType: ['album'], + success: (res) => { + res.tempFilePaths.forEach(tmpImg => { + let fileName = tmpImg.substring(tmpImg.lastIndexOf('/') + 1); + // 澶勭悊瀹夊崜鍙兘鐨刄RI缂栫爜 + if(fileName.indexOf('%') > -1) { + fileName = decodeURIComponent(fileName); + } + const fileKey = getFileKey(fileName); + this.cosClient.uploadFile({ + Bucket: this.bucket, + Region: this.region, + Key: fileKey, + FilePath: tmpImg, + SliceSize: 1024 * 1024 * 5 /* 瑙﹀彂鍒嗗潡涓婁紶鐨勯槇鍊�,5M */ + }, (err, data) => { + if (err) { + console.log('涓婁紶澶辫触', err); + } else { + // 鑾峰彇灏侀潰鐨勮闂湴鍧� + this.videoPreviewImgs.push(this.endpoint + '/' + fileKey); + this.formData.videoImgs.push(fileKey); + } + }); + }) + + } + }); + }, // 閫夋嫨灏侀潰 chooseCover() { uni.chooseImage({ @@ -413,41 +548,54 @@ Bucket: this.bucket, Region: this.region, Key: fileKey, - FilePath: res.tempFilePaths[0], + FilePath: res.tempFilePaths[0], SliceSize: 1024 * 1024 * 5 /* 瑙﹀彂鍒嗗潡涓婁紶鐨勯槇鍊�,5M */ }, (err, data) => { if (err) { console.log('涓婁紶澶辫触', err); } else { - // 鑾峰彇灏侀潰鐨勮闂湴鍧� - getFilePreviewUrl(fileKey).then(res => { - this.videoInfo.cover = res.data.data - this.formData.cover = fileKey - }) + this.videoInfo.cover = this.endpoint + '/' + fileKey + this.formData.cover = fileKey } }); } }); }, - + // 閫夋嫨鍟嗗搧 chooseGoods() { + if(this.selectedGoodsList.length > 0) { + const selectedGoodsIds = new Set(this.selectedGoodsList.map(i => i.goodsId)); + console.log(selectedGoodsIds, "mimade"); + this.goodsList?.forEach(goods => { + this.$set(goods, 'selected', selectedGoodsIds.has(goods.goodsId)); + }); + } this.showGoodsPicker = true; }, - + // 閫夋嫨鍏蜂綋鍟嗗搧 - selectGoods(goods) { - this.selectedGoods = goods; - this.formData.goodsId = goods.id; - this.showGoodsPicker = false; + selectGoods(goods, index) { + if(! this.selectedGoodsList.some(item => item.id === goods.id)) { + goods["goodsNum"] = 1 + this.selectedGoodsList.push(goods) + this.goodsList[index].selected = true + } else { + this.goodsList[index].selected = false + this.selectedGoodsList = this.selectedGoodsList.filter(item => item.id !== goods.id); + } }, - + // 娓呴櫎鍟嗗搧 - clearGoods() { - this.selectedGoods = null; - this.formData.goodsId = ''; + clearGoods(goods) { + this.selectedGoodsList = this.selectedGoodsList.filter(item => item.id !== goods.id); + this.goodsList.forEach(item => { + if(item.id === goods.id) { + item.selected = false + } + }) }, - + // 鎼滅储鐑棬璇濋 searchTags() { if (this.tagInput.trim() !== '') { @@ -478,7 +626,7 @@ }); } }, - + // 閫夋嫨鎺ㄨ崘璇濋 selectTopic(index) { const tag = this.recommendedTags[index] @@ -489,7 +637,7 @@ }); return; } - + if (this.formData.tags.filter(item => item.tagName === tag.tagName).length < 1) { this.formData.tags.push(tag); this.tagInput = ''; @@ -500,49 +648,31 @@ }); } }, - + // 绉婚櫎鏍囩 removeTag(index) { this.formData.tags.splice(index, 1); }, - + // 澶勭悊鍙戝竷 handlePublish() { this.$refs.formRef.validate(valid => { if (valid && this.canPublish) { this.loading = true; this.formData.fileInfo = this.videoInfo; - console.log(this.formData); - publish(this.formData).then(res => { + this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsNum: item.goodsNum}}); + updateVideo(this.formData).then(res => { uni.showToast({ title: '瑙嗛宸叉彁浜ゅ鏍竳', icon: 'success' }); this.loading = false // 閲嶇疆琛ㄥ崟 - this.videoInfo = { - url: '', - fileKey: '', - fileType: '', - fileSize: 0, - originalFileName: '', - cover: '' - }; - this.formData = { - id: '', - title: '', - videoFileKey: '', - cover: '', - videoFit: 'cover', - videoDuration: 0, - goodsId: '', - tags: [], - fileInfo: {} - }; + this.resetData(); this.selectedGoods = null; this.tagInput = ''; this.recommendedTags = []; - + // TODO 鍏堣烦棣栭〉,鍚庨潰璺虫垜鐨勮棰戦〉闈� setTimeout(() => { uni.switchTab({ @@ -557,21 +687,46 @@ }); } }); - } + }, + resetData() { + // 閲嶇疆琛ㄥ崟 + this.videoInfo = { + url: '', + fileKey: '', + fileType: '', + fileSize: 0, + originalFileName: '', + cover: '' + }; + this.formData = { + id: '', + title: '', + videoFileKey: '', + cover: '', + videoFit: 'cover', + videoDuration: 0, + goodsId: '', + videoContentType: 'video', + videoImgs: [], + tags: [], + fileInfo: {} + }; + this.videoPreviewImgs = [] + this.selectedGoodsList = [] + } } }; </script> <style scoped> .publish-container { - padding: 20rpx; + padding: 10px; padding-bottom: 120rpx; } .upload-section { background-color: #f8f8f8; border-radius: 16rpx; - padding: 40rpx; margin-bottom: 30rpx; display: flex; justify-content: center; @@ -611,9 +766,11 @@ } .video-actions { + width: 100%; margin-top: 20rpx; display: flex; justify-content: center; + align-items: center; gap: 20rpx; } @@ -634,6 +791,7 @@ background-color: #f9f9f9; border-radius: 8rpx; margin-top: 15rpx; + position: relative; } .goods-preview .goods-image { @@ -705,10 +863,11 @@ } .publish-btn { - position: fixed; + /* position: fixed; bottom: 100rpx; left: 20rpx; - right: 20rpx; + right: 20rpx; */ + margin-top: 40rpx; } .goods-picker { @@ -779,4 +938,22 @@ height: 25px; margin-top: 10px; } -</style> \ No newline at end of file + +.image-list { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; +} + +.image-item { + margin: 5px; + overflow: hidden; + border-radius: 8px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); +} + +.image { + width: 100%; + height: 100%; +} +</style> -- Gitblit v1.8.0