From d3d0b4dbb4f1f8c4784c834e0a39feba8aa5afa5 Mon Sep 17 00:00:00 2001 From: peng <peng.com> Date: 星期三, 02 七月 2025 10:41:08 +0800 Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev --- pages/tabbar/video/video.vue | 942 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 930 insertions(+), 12 deletions(-) diff --git a/pages/tabbar/video/video.vue b/pages/tabbar/video/video.vue index 9c11087..c70a040 100644 --- a/pages/tabbar/video/video.vue +++ b/pages/tabbar/video/video.vue @@ -1,22 +1,940 @@ <template> - <view> - <custom-tabbar bgColor="#ffffff" selected="video"></custom-tabbar> - </view> + <view class="publish-container" :style="{height: windowHeight - marginBottom - 50 + 'px'}"> + <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="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> + </view> + + <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"> + <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="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" + 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" + placeholder="杈撳叆璇濋锛屽洖杞︾‘璁�" + clearable + @confirm="addTag" + @blur="addTag" + @input="searchTags" + ></u-input> + <!-- 宸查�夎瘽棰樺睍绀� --> + <view class="tags-display" v-show="formData.tags.length > 0"> + <my-tag + v-for="(tag, index) in formData.tags" + :key="index" + :text="tag.tagName" + :index="index" + type="success" + @close="removeTag(index)" + /> + </view> + <text class="tags-count" v-show="formData.tags.length > 0"> + 宸查�� {{ formData.tags.length }}/5 + </text> + </view> + <!-- 璇濋鎺ㄨ崘 --> + <view class="hot-topics" v-show="showTopicRecommendations"> + <text class="section-title">{{ tagInput ? '鎺ㄨ崘璇濋' : '鐑棬璇濋' }}</text> + <view class="topic-list"> + <my-tag + v-for="(tag, index) in recommendedTags" + :key="index" + :text="tag.tagName" + :index="index" + type="success" + :closeable="false" + @click="selectTopic(index)" + /> + </view> + </view> + </u-form-item> + + + <!-- 鍟嗗搧閾炬帴 --> + <u-form-item label="鍟嗗搧" prop="goodsId" borderBottom> + <view class="goods-link-container"> + <u-input + placeholder="鍙�夋嫨鎺ㄨ崘鍟嗗搧" + clearable + v-if="!selectedGoods" + @click="chooseGoods" + disabled + > + <u-icon + slot="right" + name="search" + size="24" + @click="chooseGoods" + ></u-icon> + </u-input> + <view class="goods-preview" @click="chooseGoods" v-for="goods in selectedGoodsList" :key="goods.id"> + <image :src="endpoint + '/' + goods.thumbnail" class="goods-image"></image> + <view class="goods-info"> + <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="1"/> + </view> + </view> + </view> + <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="success" + shape="circle" + :loading="loading" + @click="handlePublish" + :disabled="!canPublish" + > + {{ loading ? '鍙戝竷涓�...' : '绔嬪嵆鍙戝竷' }} + </u-button> + </view> + + <!-- 鍟嗗搧閫夋嫨寮圭獥 --> + <u-popup v-model="showGoodsPicker" mode="bottom" round="20" height="70%"> + <view class="goods-picker"> + <view class="picker-header"> + <text class="picker-title">閫夋嫨鍟嗗搧</text> + <u-icon name="close" size="24" @click="showGoodsPicker = false"></u-icon> + </view> + <view class="search-bar"> + <u-search + v-model="goodsQuery.keyword" + placeholder="鎼滅储鍟嗗搧" + :showAction="false" + @change="handlerGoodsSearch" + ></u-search> + </view> + <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, index)" + > + <image :src="endpoint + '/' + goods.thumbnail" class="goods-image"></image> + <view class="goods-info"> + <text class="goods-name">{{ goods.goodsName }}</text> + <text class="goods-price">楼{{ goods.price }}</text> +<!-- <view>{{ goods.sellingPoint }}</view> --> + </view> + <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> <script> - export default { - data() { - return { - - } - }, - methods: { - +import '@/components/uview-components/uview-ui'; +import MyTag from '@/components/my-tag.vue' + +import { getSTSToken, getFilePreviewUrl } from "@/api/common.js"; +import { publish } 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 { + fileTypeShow: false, + cosClient: null, + bucket: '', + region: '', + endpoint: '', + videoUploadProgress: 0, + loading: false, + showGoodsPicker: false, + tagInput: '', + videoPreviewImgs: [], // 棰勮鍥剧墖鍦板潃 + videoInfo: { + url: '', + fileKey: '', + fileType: '', + fileSize: 0, + originalFileName: '', + cover: '' + }, + goodsQuery: { + keyword: '', + searchFromSelfStore: false, // 鏄惁鏄煡璇㈣嚜瀹跺簵閾哄晢鍝� + pageNumber: 0, + pageSize: 5 + }, + formData: { + id: '', + title: '', + cover: '', + videoFileKey: '', + videoDuration: 0, + videoFit: 'cover', + videoContentType: 'video', + videoImgs: [], + tags: [], + fileInfo: {} + }, + 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, // 鍥剧墖闂磋窛 + windowHeight: 0, + marginBottom: 0 + }; + }, + computed: { + canPublish() { + 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() { + // 鑾峰彇灞忓箷瀹藉害 + const systemInfo = uni.getSystemInfoSync() + this.screenWidth = systemInfo.windowWidth + this.windowHeight = systemInfo.windowHeight + this.marginBottom = uni.getSystemInfoSync().safeAreaInsets.bottom + this.goodsQuery.pageNumber = 0 + this.goodsQuery.pageSize = 10 + this.getVideoGoodsByEs() + }, + onShow() { + this.initCOS() + // 鍒濆鍖栨帹鑽愭爣绛� + this.getRecommendTags() + }, + methods: { + // 鍔犺浇鏇村鍟嗗搧 + loadMoreGoods() { + if(this.noMoreGoods) { + return + } + this.goodsQuery.pageNumber += 1; + this.goodsQuery.pageSize = 5; + this.getVideoGoodsByEs() + }, + // 澶勭悊鍟嗗搧鎼滅储鍊� + handlerGoodsSearch() { + this.goodsQuery.pageNumber = 0 + this.goodsQuery.pageSize = 10 + this.getVideoGoodsByEs() + }, + // 鑾峰彇鍟嗗搧鍒嗛〉 + async getVideoGoodsByEs() { + getVideoGoodsList(this.goodsQuery).then(res => { + + if(this.goodsQuery.pageNumber === 0) { + 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) { + const params = { + tagName: this.tagInput.trim(), + searchType: type + } + getRecommendTag3(params).then(res => { + this.recommendedTags = res.data.data + }) + }, + // 鍒濆鍖栬吘璁簯cos瀹㈡埛绔� + initCOS() { + // 璋冪敤鍚庣鑾峰彇sts涓存椂璁块棶鍑瘉 + 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 + SecretKey: res.data.data.tmpSecretKey, // sts 鏈嶅姟涓嬪彂鐨勪复鏃� secretKey + SecurityToken: res.data.data.sessionToken, // sts 鏈嶅姟涓嬪彂鐨勪复鏃� SessionToken + StartTime: res.data.data.stsStartTime, // 寤鸿浼犲叆鏈嶅姟绔椂闂达紝鍙伩鍏嶅鎴风鏃堕棿涓嶅噯瀵艰嚧鐨勭鍚嶉敊璇� + ExpiredTime: res.data.data.stsEndTime, // 涓存椂瀵嗛挜杩囨湡鏃堕棿 + SimpleUploadMethod: 'putObject', // 寮虹儓寤鸿锛岄珮绾т笂浼犮�佹壒閲忎笂浼犲唴閮ㄥ灏忔枃浠跺仛绠�鍗曚笂浼犳椂浣跨敤 putObject,sdk 鐗堟湰鑷冲皯闇�瑕乿1.3.0 + }); + 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); + } + const fileKey = getFileKey(fileName); + this.videoInfo = { + url: res.tempFilePath, + fileKey: fileKey, + fileType: fileKey.split('/')[0], + fileSize: res.size, + originalFileName: fileName, + cover: '' + }; + this.formData.videoFileKey = fileKey; + this.formData.videoDuration = res.duration; + // 鍒ゆ柇瑙嗛鐨勫~鍏呮ā寮� + this.formData.videoFit = this.calculateVideoFit(res.width, res.height) + + this.cosClient.uploadFile({ + Bucket: this.bucket, + Region: this.region, + Key: fileKey, + FilePath: res.tempFilePath, + SliceSize: 1024 * 1024 * 5, /* 瑙﹀彂鍒嗗潡涓婁紶鐨勯槇鍊�,5M */ + onProgress: (progressData) => { + console.log(progressData.percent); + this.videoUploadProgress = progressData.percent * 100 + } + }, (err, data) => { + if (err) { + console.log('涓婁紶澶辫触', err); + this.videoInfo = { + url: '', + fileKey: '', + fileType: '', + fileSize: 0, + originalFileName: '', + cover: '' + } + } else { + console.log(this.videoInfo); + } + }); + }, + fail: (err) => { + uni.showToast({ + title: '鏈�夋嫨瑙嗛', + icon: 'none' + }); + console.error(err); + } + }); + }, + // 鏍规嵁瀹介珮姣旈�夋嫨瑙嗛濉厖妯″紡 + 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: '', + fileKey: '', + fileType: '', + fileSize: 0, + originalFileName: '', + cover: '' + }; + 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({ + count: 1, + sizeType: ['compressed'], + sourceType: ['album'], + success: (res) => { + let fileName = res.tempFilePaths[0].substring(res.tempFilePaths[0].lastIndexOf('/') + 1); + // 澶勭悊瀹夊崜鍙兘鐨刄RI缂栫爜 + if(fileName.indexOf('%') > -1) { + fileName = decodeURIComponent(fileName); + } + const fileKey = getFileKey(fileName); + this.videoInfo.cover = res.tempFilePaths[0]; + this.cosClient.uploadFile({ + Bucket: this.bucket, + Region: this.region, + Key: fileKey, + FilePath: res.tempFilePaths[0], + SliceSize: 1024 * 1024 * 5 /* 瑙﹀彂鍒嗗潡涓婁紶鐨勯槇鍊�,5M */ + }, (err, data) => { + if (err) { + console.log('涓婁紶澶辫触', err); + } else { + this.videoInfo.cover = this.endpoint + '/' + fileKey + this.formData.cover = fileKey + } + }); + } + }); + }, + + // 閫夋嫨鍟嗗搧 + chooseGoods() { + if(this.selectedGoodsList.length > 0) { + const selectedGoodsSkuIds = new Set(this.selectedGoodsList.map(i => i.id)); + this.goodsList?.forEach(goods => { + this.$set(goods, 'selected', selectedGoodsSkuIds.has(goods.id)); + }); + } + this.showGoodsPicker = true; + }, + + // 閫夋嫨鍏蜂綋鍟嗗搧 + 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(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() !== '') { + this.getRecommendTags("SEARCH") + } + }, + // 娣诲姞鏍囩 + addTag() { + if(!this.tagInput.trim()) { + return + } + const newTag = {'id': '', 'tagName': this.tagInput.trim()}; + if (newTag && this.formData.tags.length < 5) { + if (this.formData.tags.filter(item => item.tagName === newTag.tagName).length < 1) { + this.formData.tags.push(newTag); + this.tagInput = ''; + this.getRecommendTags() // 閲嶇疆鎺ㄨ崘 + } else { + uni.showToast({ + title: '璇ヨ瘽棰樺凡娣诲姞杩囦簡~', + icon: 'none' + }); + } + } else if (this.formData.tags.length >= 5) { + uni.showToast({ + title: '鏈�澶氭坊鍔�5涓瘽棰榽', + icon: 'none' + }); + } + }, + + // 閫夋嫨鎺ㄨ崘璇濋 + selectTopic(index) { + const tag = this.recommendedTags[index] + if (this.formData.tags.length >= 5) { + uni.showToast({ + title: '鏈�澶氭坊鍔�5涓瘽棰榽', + icon: 'none' + }); + return; + } + + if (this.formData.tags.filter(item => item.tagName === tag.tagName).length < 1) { + this.formData.tags.push(tag); + this.tagInput = ''; + } else { + uni.showToast({ + title: '璇ヨ瘽棰樺凡娣诲姞杩囦簡~', + icon: 'none' + }); + } + }, + + // 绉婚櫎鏍囩 + 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; + this.formData["goodsList"] = this.selectedGoodsList.map(item => {return {goodsId: item.goodsId, goodsSkuId: item.id, goodsNum: item.goodsNum}}); + publish(this.formData).then(res => { + uni.showToast({ + title: '瑙嗛宸叉彁浜ゅ鏍竳', + icon: 'success' + }); + this.loading = false + // 閲嶇疆琛ㄥ崟 + this.resetData(); + this.selectedGoods = null; + this.tagInput = ''; + this.recommendedTags = []; + + // TODO 鍏堣烦棣栭〉,鍚庨潰璺虫垜鐨勮棰戦〉闈� + setTimeout(() => { + uni.switchTab({ + url: '/pages/tabbar/index/home' + }); + }, 1500); + }) + } else { + uni.showToast({ + title: '璇峰畬鍠勮棰戜俊鎭瘇', + icon: 'none' + }); + } + }); + }, + resetData() { + // 閲嶇疆琛ㄥ崟 + this.videoInfo = { + url: '', + fileKey: '', + fileType: '', + fileSize: 0, + originalFileName: '', + cover: '' + }; + this.formData = { + id: '', + title: '', + videoFileKey: '', + cover: '', + videoFit: 'cover', + videoDuration: 0, + videoContentType: 'video', + videoImgs: [], + tags: [], + fileInfo: {} + }; + this.videoPreviewImgs = [] + this.selectedGoodsList = [] + } + } +}; </script> -<style> +<style scoped> +.publish-container { + padding: 10px; + overflow-y: scroll; +} +.upload-section { + background-color: #f8f8f8; + border-radius: 16rpx; + margin-bottom: 30rpx; + display: flex; + justify-content: center; + align-items: center; + min-height: 400rpx; +} + +.upload-btn { + display: flex; + flex-direction: column; + align-items: center; + color: #999; +} + +.upload-text { + font-size: 32rpx; + margin: 20rpx 0 10rpx; +} + +.upload-tips { + font-size: 24rpx; + color: #ccc; +} + +.video-preview { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} + +.video-player { + width: 100%; + height: 400rpx; + border-radius: 12rpx; + background-color: #000; +} + +.video-actions { + width: 100%; + margin-top: 20rpx; + display: flex; + justify-content: center; + align-items: center; + gap: 20rpx; +} + +.form-section { + background-color: #fff; + border-radius: 16rpx; + padding: 0 20rpx; +} + +.goods-link-container { + width: 100%; +} + +.goods-preview { + display: flex; + align-items: center; + padding: 15rpx; + background-color: #f9f9f9; + border-radius: 8rpx; + margin-top: 15rpx; + position: relative; +} + +.goods-preview .goods-image { + width: 80rpx; + height: 80rpx; + border-radius: 8rpx; + margin-right: 15rpx; +} + +.goods-preview .goods-info { + flex: 1; + display: flex; + flex-direction: column; +} + +.goods-preview .goods-info .goods-name { + font-size: 26rpx; + color: #333; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.goods-preview .goods-info .goods-price { + font-size: 28rpx; + color: #f44; + font-weight: bold; +} + +.topic-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; + line-height: 22px; +} + +.tags-input-container { + width: 100%; +} + +.tags-display { + display: flex; + flex-wrap: wrap; + margin-top: 15rpx; + line-height: 22px; + height: 80rpx; +} + +.hot-topics { + display: flex; + flex-direction: column; + margin-top: 15rpx; + margin-bottom: 15rpx; + height: 46rpx; +} + +.section-title { + font-size: 12px; + color: #999; + line-height: 12px; + margin-bottom: 6rpx; +} + +.tags-count { + display: block; + font-size: 12px; + line-height: 12px; + color: #999; + margin-top: 10rpx; + text-align: right; +} + +.publish-btn { + /* position: fixed; + bottom: 100rpx; + left: 20rpx; + right: 20rpx; */ + margin-top: 40rpx; +} + +.goods-picker { + padding: 30rpx; + height: 100%; + display: flex; + flex-direction: column; +} + +.goods-picker .picker-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 30rpx; +} + +.goods-picker .picker-header .picker-title { + font-size: 36rpx; + font-weight: bold; +} + +.goods-picker .search-bar { + margin-bottom: 20rpx; +} + +.goods-picker .goods-list { + flex: 1; + overflow: hidden; +} + +.goods-picker .goods-list .goods-item { + display: flex; + align-items: center; + padding: 20rpx 0; + border-bottom: 1rpx solid #f5f5f5; +} + +.goods-picker .goods-list .goods-item .goods-image { + width: 100rpx; + height: 100rpx; + border-radius: 8rpx; + margin-right: 20rpx; +} + +.goods-picker .goods-list .goods-item .goods-info { + flex: 1; +} + +.goods-picker .goods-list .goods-item .goods-info .goods-name { + font-size: 28rpx; + color: #333; + margin-bottom: 10rpx; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.goods-picker .goods-list .goods-item .goods-info .goods-price { + font-size: 28rpx; + color: #f44; + font-weight: bold; +} + +.progress-box { + width: 100%; + display: flex; + height: 25px; + margin-top: 10px; +} + +.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