From d25f94845ef10169389c980c7ffaa7d6bc461760 Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期四, 15 五月 2025 18:28:37 +0800 Subject: [PATCH] 视频发布静态页面 --- pages/tabbar/video/video.vue | 657 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 642 insertions(+), 15 deletions(-) diff --git a/pages/tabbar/video/video.vue b/pages/tabbar/video/video.vue index 9c11087..d6beb2f 100644 --- a/pages/tabbar/video/video.vue +++ b/pages/tabbar/video/video.vue @@ -1,22 +1,649 @@ <template> - <view> - <custom-tabbar bgColor="#ffffff" selected="video"></custom-tabbar> - </view> + <view class="publish-container"> + <!-- 瑙嗛涓婁紶鍖哄煙 --> + <view class="upload-section"> + <view class="upload-btn" @click="chooseVideo" v-if="!videoInfo.url"> + <u-icon name="plus" size="40" color="#999"></u-icon> + <text class="upload-text">鐐瑰嚮涓婁紶瑙嗛</text> + <text class="upload-tips">鏀寔MP4鏍煎紡锛屾渶闀�60绉�</text> + </view> + + <view class="video-preview" v-else> + <video + :src="videoInfo.url" + controls + class="video-player" + :poster="videoInfo.cover || ''" + ></video> + <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">閫夋嫨灏侀潰</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="璇疯緭鍏ヨ棰戞爣棰�" + maxlength="30" + 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="searchHotTopics" + ></u-input> + <!-- 宸查�夎瘽棰樺睍绀� --> + <view class="tags-display" v-if="formData.tags.length > 0"> + <u-tag + v-for="(tag, index) in formData.tags" + :key="index" + :text="tag" + closable + @close="removeTag(index)" + size="medium" + type="primary" + style="margin-right: 10rpx; margin-bottom: 10rpx;" + /> + </view> + <text class="tags-count" v-if="formData.tags.length > 0"> + 宸查�� {{ formData.tags.length }}/5 + </text> + </view> + </u-form-item> + + + <!-- 璇濋鎺ㄨ崘 --> + <view class="hot-topics" v-if="showTopicRecommendations"> + <text class="section-title">{{ tagInput ? '鎺ㄨ崘璇濋' : '鐑棬璇濋' }}</text> + <view class="topic-list"> + <u-tag + v-for="(topic, index) in recommendedTopics" + :key="index" + :text="topic" + size="medium" + type="info" + @click="selectTopic(topic)" + style="margin-right: 10rpx; margin-bottom: 10rpx;" + /> + </view> + </view> + + <!-- 鍟嗗搧閾炬帴 --> + <u-form-item label="鍟嗗搧" prop="goodsLink" 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" v-if="selectedGoods"> + <image :src="selectedGoods.image" class="goods-image"></image> + <view class="goods-info"> + <text class="goods-name">{{ selectedGoods.name }}</text> + <text class="goods-price">楼{{ selectedGoods.price }}</text> + </view> + <u-icon + name="close" + size="20" + @click="clearGoods" + ></u-icon> + </view> + </view> + </u-form-item> + </u-form> + </view> + + <!-- 鍙戝竷鎸夐挳 --> + <view class="publish-btn"> + <u-button + type="primary" + 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="goodsSearch" + placeholder="鎼滅储鍟嗗搧鍚嶇О" + :showAction="false" + ></u-search> + </view> + <scroll-view class="goods-list" scroll-y> + <view + class="goods-item" + v-for="goods in filteredGoods" + :key="goods.id" + @click="selectGoods(goods)" + > + <image :src="goods.image" class="goods-image"></image> + <view class="goods-info"> + <text class="goods-name">{{ goods.name }}</text> + <text class="goods-price">楼{{ goods.price }}</text> + </view> + <u-icon + name="checkmark" + size="24" + :color="selectedGoods && selectedGoods.id === goods.id ? '#2979ff' : '#ccc'" + ></u-icon> + </view> + </scroll-view> + </view> + </u-popup> + + <custom-tabbar bgColor="#ffffff" selected="video"></custom-tabbar> + </view> </template> <script> - export default { - data() { - return { - - } - }, - methods: { - - } - } +export default { + data() { + return { + loading: false, + showGoodsPicker: false, + goodsSearch: '', + tagInput: '', + videoInfo: { + url: '', + cover: '', + duration: 0, + size: 0 + }, + formData: { + title: '', + goodsLink: '', + tags: [] + }, + 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' + }, + { + id: '3', + name: '渚挎惡寮忓厖鐢靛疂10000mAh', + price: '99.00', + image: 'https://via.placeholder.com/100' + }, + { + id: '4', + name: '楂樻竻骞胯鎵嬫満闀滃ご', + price: '59.00', + image: 'https://via.placeholder.com/100' + }, + { + id: '5', + name: '澶氬姛鑳芥姌鍙犻敭鐩�', + price: '159.00', + image: 'https://via.placeholder.com/100' + } + ], + hotTopics: [ + '#浜斾竴鏃呰鎵撳崱', + '#缇庨鎺㈠簵', + '#绉戞妧鏂板搧', + '#鍋ヨ韩鏃ュ父', + '#瀹犵墿钀屽疇' + ], + recommendedTopics: [], + rules: { + title: [ + { required: true, message: '璇疯緭鍏ヨ棰戞爣棰�', trigger: 'blur' }, + { min: 2, max: 30, message: '鏍囬闀垮害鍦�2鍒�30涓瓧绗�', trigger: 'blur' } + ], + goodsLink: [ + { required: true, message: '璇烽�夋嫨鍟嗗搧閾炬帴', trigger: 'change' } + ], + tags: [ + { validator: (rule, value, callback) => { + if (value.length === 0) { + callback(new Error('璇疯嚦灏戞坊鍔犱竴涓瘽棰�')); + } else { + callback(); + } + }, trigger: 'change' } + ] + } + }; + }, + computed: { + canPublish() { + return this.videoInfo.url && this.formData.title && this.formData.goodsLink && this.formData.tags.length > 0; + }, + filteredGoods() { + if (!this.goodsSearch) return this.goodsList; + return this.goodsList.filter(goods => + goods.name.toLowerCase().includes(this.goodsSearch.toLowerCase()) + ); + }, + showTopicRecommendations() { + return (this.tagInput === '' || this.recommendedTopics.length > 0) && this.formData.tags.length < 5; + } + }, + created() { + // 鍒濆鍖栨帹鑽愯瘽棰� + this.recommendedTopics = this.hotTopics.slice(0, 3); + }, + methods: { + // 閫夋嫨瑙嗛 + chooseVideo() { + uni.chooseVideo({ + sourceType: ['album', 'camera'], + maxDuration: 60, + camera: 'back', + success: (res) => { + this.videoInfo = { + url: res.tempFilePath, + duration: res.duration, + size: res.size, + cover: res.thumbTempFilePath + }; + }, + fail: (err) => { + uni.showToast({ + title: '閫夋嫨瑙嗛澶辫触', + icon: 'none' + }); + console.error(err); + } + }); + }, + + // 閲嶆柊涓婁紶 + reUpload() { + this.videoInfo = { + url: '', + cover: '', + duration: 0, + size: 0 + }; + this.chooseVideo(); + }, + + // 閫夋嫨灏侀潰 + chooseCover() { + uni.chooseImage({ + count: 1, + sizeType: ['compressed'], + sourceType: ['album'], + success: (res) => { + this.videoInfo.cover = res.tempFilePaths[0]; + } + }); + }, + + // 閫夋嫨鍟嗗搧 + chooseGoods() { + this.showGoodsPicker = true; + }, + + // 閫夋嫨鍏蜂綋鍟嗗搧 + selectGoods(goods) { + this.selectedGoods = goods; + this.formData.goodsLink = `https://example.com/goods/${goods.id}`; + this.showGoodsPicker = false; + }, + + // 娓呴櫎鍟嗗搧 + clearGoods() { + this.selectedGoods = null; + this.formData.goodsLink = ''; + }, + + // 鎼滅储鐑棬璇濋 + searchHotTopics() { + if (this.tagInput.trim() === '') { + // 鏄剧ず鐑棬璇濋 + this.recommendedTopics = this.hotTopics.slice(0, 3); + } else { + // 妯℃嫙鎼滅储鎺ㄨ崘璇濋 + const input = this.tagInput.trim().toLowerCase(); + this.recommendedTopics = this.hotTopics + .filter(topic => topic.toLowerCase().includes(input)) + .slice(0, 3); + } + }, + + // 娣诲姞鏍囩 + addTag() { + const newTag = this.tagInput.trim(); + if (newTag && this.formData.tags.length < 5) { + if (!this.formData.tags.includes(newTag)) { + this.formData.tags.push(newTag); + this.tagInput = ''; + this.recommendedTopics = this.hotTopics.slice(0, 3); // 閲嶇疆鎺ㄨ崘 + } else { + uni.showToast({ + title: '璇濋宸叉坊鍔�', + icon: 'none' + }); + } + } else if (this.formData.tags.length >= 5) { + uni.showToast({ + title: '鏈�澶氭坊鍔�5涓瘽棰�', + icon: 'none' + }); + } + }, + + // 閫夋嫨鎺ㄨ崘璇濋 + selectTopic(topic) { + if (this.formData.tags.length >= 5) { + uni.showToast({ + title: '鏈�澶氭坊鍔�5涓瘽棰�', + icon: 'none' + }); + return; + } + + if (!this.formData.tags.includes(topic)) { + this.formData.tags.push(topic); + 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; + + // 杩欓噷搴旇鏄笂浼犺棰戝埌鏈嶅姟鍣ㄧ殑閫昏緫 + // 妯℃嫙涓婁紶杩囩▼ + setTimeout(() => { + this.loading = false; + uni.showToast({ + title: '鍙戝竷鎴愬姛', + icon: 'success' + }); + + // 閲嶇疆琛ㄥ崟 + this.videoInfo = { + url: '', + cover: '', + duration: 0, + size: 0 + }; + this.formData = { + title: '', + goodsLink: '', + tags: [] + }; + this.selectedGoods = null; + this.tagInput = ''; + this.recommendedTopics = this.hotTopics.slice(0, 3); + + // 杩斿洖涓婁竴椤� + setTimeout(() => { + uni.navigateBack(); + }, 1500); + }, 2000); + } else { + uni.showToast({ + title: '璇峰畬鍠勮棰戜俊鎭�', + icon: 'none' + }); + } + }); + } + } +}; </script> -<style> +<style lang="scss" scoped> +.publish-container { + padding: 20rpx; + padding-bottom: 120rpx; +} -</style> +.upload-section { + background-color: #f8f8f8; + border-radius: 16rpx; + padding: 40rpx; + 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 { + margin-top: 20rpx; + display: flex; + justify-content: 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; + + .goods-image { + width: 80rpx; + height: 80rpx; + border-radius: 8rpx; + margin-right: 15rpx; + } + + .goods-info { + flex: 1; + display: flex; + flex-direction: column; + + .goods-name { + font-size: 26rpx; + color: #333; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .goods-price { + font-size: 28rpx; + color: #f44; + font-weight: bold; + } + } +} + +.tags-input-container { + width: 100%; + + .tags-display { + display: flex; + flex-wrap: wrap; + margin-top: 15rpx; + } + + .hot-topics { + margin-top: 15rpx; + + .section-title { + font-size: 24rpx; + color: #999; + display: block; + margin-bottom: 10rpx; + } + + .topic-list { + display: flex; + flex-wrap: wrap; + } + } + + .tags-count { + display: block; + font-size: 24rpx; + color: #999; + margin-top: 10rpx; + text-align: right; + } +} + +.publish-btn { + position: fixed; + bottom: 100rpx; + left: 20rpx; + right: 20rpx; +} + +.goods-picker { + padding: 30rpx; + height: 100%; + display: flex; + flex-direction: column; + + .picker-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 30rpx; + + .picker-title { + font-size: 36rpx; + font-weight: bold; + } + } + + .search-bar { + margin-bottom: 20rpx; + } + + .goods-list { + flex: 1; + overflow: hidden; + + .goods-item { + display: flex; + align-items: center; + padding: 20rpx 0; + border-bottom: 1rpx solid #f5f5f5; + + .goods-image { + width: 100rpx; + height: 100rpx; + border-radius: 8rpx; + margin-right: 20rpx; + } + + .goods-info { + flex: 1; + + .goods-name { + font-size: 28rpx; + color: #333; + margin-bottom: 10rpx; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + + .goods-price { + font-size: 28rpx; + color: #f44; + font-weight: bold; + } + } + } + } +} +</style> \ No newline at end of file -- Gitblit v1.8.0