<template>
	<view class="pub-page">
		<view class="pub-nav" :style="{ paddingTop: statusBar + 'px' }">
			<view class="pub-nav-row">
				<view class="pub-back" @tap="goBack">
					<text class="pub-back-icon">←</text>
				</view>
				<text class="pub-nav-title">{{ copy.publishTitle }}</text>
				<view class="pub-nav-placeholder" />
			</view>
		</view>

		<scroll-view scroll-y class="pub-scroll" :style="{ height: scrollHeight + 'px' }">
			<view class="pub-body">
			<view class="pub-hero">
				<text class="pub-hero-badge">{{ heroBadge }}</text>
				<text class="pub-hero-title">{{ heroTitle }}</text>
				<text class="pub-hero-sub">{{ heroSub }}</text>
			</view>

			<view class="pub-type-switch">
				<view
					class="pub-type-item"
					:class="{ 'pub-type-item--active': publishType === 'want' }"
					@tap="setPublishType('want')"
				>
					<text class="pub-type-text">{{ copy.publishTypeGrass }}</text>
				</view>
				<view
					class="pub-type-item"
					:class="{ 'pub-type-item--active': publishType === 'video' }"
					@tap="setPublishType('video')"
				>
					<text class="pub-type-text">{{ copy.publishTypeVideo }}</text>
				</view>
			</view>

			<view v-if="publishType === 'want'" class="pub-card">
				<view class="pub-card-hd">
					<text class="pub-card-icon">🖼</text>
					<view class="pub-card-meta">
						<text class="pub-card-title">{{ copy.publishUploadTitle }}</text>
						<text class="pub-card-hint">{{ copy.publishUploadHint }}</text>
					</view>
				</view>
				<view class="pub-grid">
					<view
						v-for="(img, index) in images"
						:key="'img-' + index"
						class="pub-grid-cell"
					>
						<image
							class="pub-grid-img"
							:src="previewUrl(img)"
							mode="aspectFill"
							@tap="previewImage(index)"
						/>
						<view class="pub-grid-del" @tap.stop="removeImage(index)">
							<text class="pub-grid-del-icon">×</text>
						</view>
					</view>
					<view
						v-if="images.length < maxImages"
						class="pub-grid-cell pub-grid-add"
						@tap="pickImages"
					>
						<text class="pub-grid-add-icon">＋</text>
						<text class="pub-grid-add-text">{{ images.length ? copy.publishAddMore : copy.publishAddImage }}</text>
					</view>
				</view>
			</view>

			<view v-if="publishType === 'want'" class="pub-card">
				<view class="pub-card-hd">
					<text class="pub-card-icon">✎</text>
					<view class="pub-card-meta">
						<text class="pub-card-title">{{ copy.publishContentTitle }}</text>
						<text class="pub-card-hint">{{ copy.publishContentHint }}</text>
					</view>
				</view>
				<textarea
					v-model="content"
					class="pub-textarea"
					:placeholder="copy.publishContentPlaceholder"
					placeholder-class="pub-textarea-ph"
					maxlength="2000"
					:auto-height="false"
				/>
				<text class="pub-counter">{{ content.length }}/2000</text>
			</view>

			<view v-if="publishType === 'video'" class="pub-card">
				<view class="pub-card-hd">
					<text class="pub-card-icon">🎬</text>
					<view class="pub-card-meta">
						<text class="pub-card-title">{{ copy.publishVideoUploadTitle }}</text>
						<text class="pub-card-hint">{{ copy.publishVideoUploadHint }}</text>
					</view>
				</view>
				<view class="pub-video-row">
					<view class="pub-video-col">
						<view class="pub-video-upload">
							<view
								v-if="hasVideoPreview"
								class="pub-video-preview-wrap"
								@tap="onVideoAreaTap"
							>
								<!-- #ifdef APP-PLUS -->
								<video
									:key="videoPreviewSrc"
									class="pub-video-preview"
									:src="videoPreviewSrc"
									:controls="false"
									:show-center-play-btn="false"
									object-fit="fill"
									:autoplay="videoReady"
									muted
									:loop="videoReady"
								>
									<cover-view v-if="videoUploading" class="pub-video-cover pub-video-cover--loading">
										<cover-view class="pub-video-cover-progress">{{ video.progress }}%</cover-view>
									</cover-view>
									<cover-view
										v-else-if="videoReady"
										class="pub-video-cover pub-video-cover--play"
										@tap="previewVideo"
									>
										<cover-view class="pub-video-cover-play-btn">▶</cover-view>
									</cover-view>
								</video>
								<!-- #endif -->
								<!-- #ifndef APP-PLUS -->
								<video
									:key="videoPreviewSrc"
									class="pub-video-preview"
									:src="videoPreviewSrc"
									:controls="videoReady"
									:show-center-play-btn="videoReady"
									object-fit="cover"
								/>
								<view v-if="videoUploading" class="pub-video-loading">
									<text class="pub-video-loading-icon">⟳</text>
									<text class="pub-video-loading-text">{{ video.progress }}%</text>
									<text class="pub-video-loading-sub">{{ formatBytes(video.totalBytesSent) }}/{{ formatBytes(video.totalBytesExpectedToSend) }}</text>
								</view>
								<view v-else-if="videoReady" class="pub-video-play-mask">
									<text class="pub-video-play-icon">▶</text>
								</view>
								<!-- #endif -->
							</view>
							<view v-else class="pub-video-add" @tap="pickVideo">
								<text class="pub-grid-add-icon">＋</text>
								<text class="pub-grid-add-text">{{ copy.publishAddVideo }}</text>
							</view>
						</view>
						<view
							v-if="hasVideoPreview"
							class="pub-video-remove-link"
							hover-class="pub-video-remove-link--press"
							@tap.stop="removeVideo"
						>
							<text class="pub-video-remove-link-text">{{ copy.publishRemoveVideo }}</text>
						</view>
					</view>
					<view class="pub-video-editor">
						<textarea
							v-model="content"
							class="pub-textarea pub-textarea--video"
							:placeholder="copy.publishVideoContentPlaceholder"
							placeholder-class="pub-textarea-ph"
							maxlength="2000"
							:auto-height="false"
						/>
					</view>
				</view>
			</view>

			<view v-if="publishType === 'video'" class="pub-card">
				<view class="pub-card-hd">
					<text class="pub-card-icon">🏷</text>
					<view class="pub-card-meta">
						<text class="pub-card-title">{{ copy.publishSelectLabel }}</text>
						<text class="pub-card-hint">{{ copy.publishSelectLabelHint }}</text>
					</view>
				</view>
				<scroll-view scroll-x class="pub-labels-scroll" :show-scrollbar="false">
					<view class="pub-labels">
						<view
							v-for="label in labels"
							:key="label.id"
							class="pub-label"
							:class="{ 'pub-label--active': labelId === label.id }"
							@tap="selectLabel(label)"
						>
							<view class="pub-label-icon-wrap">
								<image v-if="label.icon" class="pub-label-icon" :src="label.icon" mode="aspectFit" />
								<text v-else class="pub-label-icon-fallback">{{ labelFallback(label) }}</text>
							</view>
							<text class="pub-label-name" :lines="2">{{ label.name }}</text>
						</view>
					</view>
				</scroll-view>
				<text v-if="!labels.length && !labelsLoading" class="pub-label-empty">{{ copy.publishNoLabels }}</text>
			</view>

			<view class="pub-bottom-space" />
			</view>
		</scroll-view>

		<view class="pub-foot" :style="{ paddingBottom: safeBottom + 'px' }">
			<view class="pub-review-tip pub-review-tip--foot">
				<text class="pub-review-tip-icon">ℹ</text>
				<text class="pub-review-tip-text">{{ copy.publishVideoReviewTip }}</text>
			</view>
			<button
				class="pub-submit"
				:class="{
					'pub-submit--loading': submitting,
					'pub-submit--locked': !pushAllowed && !submitting
				}"
				:disabled="submitting"
				@tap="onSubmit"
			>
				<text class="pub-submit-text">{{ submitButtonText }}</text>
			</button>
		</view>
	</view>
</template>

<script>
import {
	fetchUploadConfig,
	uploadImageFile,
	prepareImageForUpload,
	uploadVideoFile,
	fetchVideoLabels,
	publishGrassPost,
	publishVideoPost
} from '@/features/dynamics/publish-gateway'
import { absolutizePreviewUrls } from '@/features/dynamics/post-media'
import {
	fetchPushPermission,
	canPublishContent,
	showPushBlockedModal
} from '@/features/dynamics/publish-guard'
import {
	chooseImageWithPermission,
	chooseVideoWithPermission,
	showMediaSourceSheet
} from '@/features/dynamics/media-picker-permission'

const MAX_IMAGES = 9

export default {
	data() {
		return {
			statusBar: 0,
			safeBottom: 0,
			windowHeight: 667,
			publishType: 'want',
			images: [],
			content: '',
			submitting: false,
			pushAllowed: true,
			pushPermChecked: false,
			uploading: false,
			videoUploading: false,
			maxImages: MAX_IMAGES,
			video: {
				tempFilePath: null,
				progress: 0,
				totalBytesSent: 0,
				totalBytesExpectedToSend: 0
			},
			videoId: null,
			videoPath: '',
			videoPreviewUrl: '',
			labelId: null,
			labels: [],
			labelsLoading: false
		}
	},
	computed: {
		copy() {
			const t = this.$t.bind(this)
			return {
				publishTitle: t('dynamics.publishTitle'),
				publishBadge: t('dynamics.publishBadge'),
				publishHeroTitle: t('dynamics.publishHeroTitle'),
				publishHeroSub: t('dynamics.publishHeroSub'),
				publishUploadTitle: t('dynamics.publishUploadTitle'),
				publishUploadHint: t('dynamics.publishUploadHint'),
				publishAddImage: t('dynamics.publishAddImage'),
				publishAddMore: t('dynamics.publishAddMore'),
				publishContentTitle: t('dynamics.publishContentTitle'),
				publishContentHint: t('dynamics.publishContentHint'),
				publishContentPlaceholder: t('dynamics.publishContentPlaceholder'),
				publishSubmitting: t('dynamics.publishSubmitting'),
				publishSubmit: t('dynamics.publishSubmit'),
				publishSubmitLocked: t('dynamics.publishSubmitLocked'),
				publishUploading: t('dynamics.publishUploading'),
				publishUploadFailed: t('dynamics.publishUploadFailed'),
				publishFailed: t('dynamics.publishFailed'),
				publishNeedImage: t('dynamics.publishNeedImage'),
				publishNeedContent: t('dynamics.publishNeedContent'),
				publishOk: t('dynamics.publishOk'),
				publishTypeGrass: t('dynamics.publishTypeGrass'),
				publishTypeVideo: t('dynamics.publishTypeVideo'),
				publishVideoBadge: t('dynamics.publishVideoBadge'),
				publishVideoHeroTitle: t('dynamics.publishVideoHeroTitle'),
				publishVideoHeroSub: t('dynamics.publishVideoHeroSub'),
				publishVideoUploadTitle: t('dynamics.publishVideoUploadTitle'),
				publishVideoUploadHint: t('dynamics.publishVideoUploadHint'),
				publishAddVideo: t('dynamics.publishAddVideo'),
				publishVideoContentPlaceholder: t('dynamics.publishVideoContentPlaceholder'),
				publishVideoSubmit: t('dynamics.publishVideoSubmit'),
				publishSelectLabel: t('dynamics.publishSelectLabel'),
				publishSelectLabelHint: t('dynamics.publishSelectLabelHint'),
				publishNoLabels: t('dynamics.publishNoLabels'),
				publishNeedVideo: t('dynamics.publishNeedVideo'),
				publishVideoNotDone: t('dynamics.publishVideoNotDone'),
				publishNeedLabel: t('dynamics.publishNeedLabel'),
				publishVideoUploadFailed: t('dynamics.publishVideoUploadFailed'),
				publishVideoReviewTip: t('dynamics.publishVideoReviewTip'),
				publishPermFailed: t('user.realnameNetworkError'),
				publishRemoveVideo: t('dynamics.publishRemoveVideo')
			}
		},
		heroBadge() {
			return this.publishType === 'video' ? this.copy.publishVideoBadge : this.copy.publishBadge
		},
		heroTitle() {
			return this.publishType === 'video' ? this.copy.publishVideoHeroTitle : this.copy.publishHeroTitle
		},
		heroSub() {
			return this.publishType === 'video' ? this.copy.publishVideoHeroSub : this.copy.publishHeroSub
		},
		submitLabel() {
			return this.publishType === 'video' ? this.copy.publishVideoSubmit : this.copy.publishSubmit
		},
		submitButtonText() {
			if (this.submitting) return this.copy.publishSubmitting
			if (!this.pushAllowed) return this.copy.publishSubmitLocked
			return this.submitLabel
		},
		videoPreviewSrc() {
			// 预览只用带域名的 fullurl；上传中暂用本地临时文件
			if (this.videoPreviewUrl && this.videoId != null) {
				return this.videoPreviewUrl
			}
			return this.video.tempFilePath || ''
		},
		hasVideoPreview() {
			return !!(this.video.tempFilePath || this.videoPreviewUrl)
		},
		videoReady() {
			return this.videoId != null && !this.videoUploading
		},
		scrollHeight() {
			const navH = this.statusBar + uni.upx2px(88)
			return Math.max(200, this.windowHeight - navH - this.footHeightPx)
		},
		footHeightPx() {
			return uni.upx2px(248) + this.safeBottom
		},
		signedIn() {
			return !!(this.$store && this.$store.state && this.$store.state.user.isLogin)
		}
	},
	onLoad(option) {
		try {
			const info = uni.getSystemInfoSync()
			this.statusBar = info.statusBarHeight || 0
			this.safeBottom = (info.safeAreaInsets && info.safeAreaInsets.bottom) || 0
			this.windowHeight = info.windowHeight || 667
		} catch (_) {}
		if (!this.signedIn) {
			this.$appKit && this.$appKit.to('/pages/passport/lobby')
			return
		}
		if (option && option.type === 'video') {
			this.publishType = 'video'
			this.loadLabels()
		}
		this.initPushPermission()
	},
	onShow() {
		if (this.signedIn && this.pushPermChecked) {
			this.refreshPushPermission()
		}
	},
	methods: {
		goBack() {
			uni.navigateBack({
				fail: () => uni.switchTab({ url: '/pages/dynamics/index' })
			})
		},
		async initPushPermission() {
			try {
				const perm = await fetchPushPermission()
				this.pushAllowed = canPublishContent(perm.isCanPass)
				if (!this.pushAllowed) {
					await showPushBlockedModal(this, perm)
				}
			} catch (err) {
				this.pushAllowed = false
				this.$appKit && this.$appKit.msg((err && err.message) || this.copy.publishPermFailed)
			} finally {
				this.pushPermChecked = true
			}
		},
		async refreshPushPermission() {
			try {
				const perm = await fetchPushPermission()
				this.pushAllowed = canPublishContent(perm.isCanPass)
			} catch (_) {}
		},
		setPublishType(type) {
			if (type === this.publishType) return
			if (this.submitting || this.uploading || this.videoUploading) return
			this.publishType = type
			if (type === 'video' && !this.labels.length) {
				this.loadLabels()
			}
		},
		async loadLabels() {
			if (this.labelsLoading) return
			this.labelsLoading = true
			try {
				this.labels = await fetchVideoLabels()
			} catch (_) {
				this.labels = []
			} finally {
				this.labelsLoading = false
			}
		},
		selectLabel(label) {
			if (!label) return
			if (this.labelId === label.id) {
				this.labelId = null
				return
			}
			this.labelId = label.id
		},
		labelFallback(label) {
			const name = (label && label.name) || ''
			return name ? name.slice(0, 1) : '·'
		},
		formatBytes(value) {
			const n = Number(value) || 0
			if (n < 1024) return `${n}B`
			if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`
			return `${(n / 1024 / 1024).toFixed(1)}MB`
		},
		oss(url, w = 200) {
			if (this.$appKit && typeof this.$appKit.oss === 'function') {
				return this.$appKit.oss(url, w, w)
			}
			return url || ''
		},
		previewUrl(path) {
			return this.oss(path, 240)
		},
		pickImages() {
			if (this.uploading || this.submitting) return
			const remain = this.maxImages - this.images.length
			if (remain <= 0) return
			showMediaSourceSheet(this, {
				type: 'image',
				onAlbum: () => {
					chooseImageWithPermission(this, 'album', {
						count: remain,
						sizeType: ['compressed'],
						// 部分端支持，压低相册原图质量
						crop: { quality: 60 },
						success: (res) => {
							const paths = res.tempFilePaths || []
							if (paths.length) this.uploadPaths(paths)
						}
					})
				},
				onCamera: () => {
					chooseImageWithPermission(this, 'camera', {
						count: 1,
						sizeType: ['compressed'],
						crop: { quality: 60 },
						success: (res) => {
							const paths = res.tempFilePaths || []
							if (paths.length) this.uploadPaths(paths)
						}
					})
				}
			})
		},
		async uploadPaths(paths) {
			const list = Array.isArray(paths) ? paths.filter(Boolean) : []
			if (!list.length) return
			this.uploading = true
			uni.showLoading({ title: this.copy.publishUploading, mask: true })
			let failCount = 0
			try {
				const config = await fetchUploadConfig()
				for (let i = 0; i < list.length; i++) {
					if (this.images.length >= this.maxImages) break
					try {
						// 先解码再压缩，再上传，避免 HEIC / 超大图直接 upload 闪退
						const ready = await prepareImageForUpload(list[i])
						const url = await uploadImageFile(ready, config)
						if (url) this.images.push(url)
						else failCount += 1
					} catch (_) {
						failCount += 1
					}
				}
				if (failCount > 0) {
					this.$appKit && this.$appKit.msg(this.copy.publishUploadFailed)
				}
			} catch (err) {
				this.$appKit && this.$appKit.msg((err && err.message) || this.copy.publishUploadFailed)
			} finally {
				this.uploading = false
				try {
					uni.hideLoading()
				} catch (_) {}
			}
		},
		removeImage(index) {
			this.images.splice(index, 1)
		},
		previewImage(index) {
			const urls = absolutizePreviewUrls(this.images, (u) => this.oss(u, 750))
			if (!urls.length) return
			uni.previewImage({
				current: urls[index] || urls[0],
				urls
			})
		},
		pickVideo() {
			if (this.submitting || this.videoUploading) return
			showMediaSourceSheet(this, {
				type: 'video',
				onAlbum: () => {
					chooseVideoWithPermission(this, 'album', {
						compressed: true,
						success: (res) => {
							const path = res.tempFilePath
							if (path) this.uploadVideo(path, res.name)
						}
					})
				},
				onCamera: () => {
					chooseVideoWithPermission(this, 'camera', {
						compressed: true,
						success: (res) => {
							const path = res.tempFilePath
							if (path) this.uploadVideo(path, res.name)
						}
					})
				}
			})
		},
		onVideoAreaTap() {
			if (this.videoUploading) return
			if (this.videoReady) {
				this.previewVideo()
				return
			}
			this.pickVideo()
		},
		previewVideo() {
			const url = this.videoPreviewSrc
			if (!url) return
			if (typeof uni.previewMedia === 'function') {
				uni.previewMedia({
					sources: [{ url, type: 'video' }]
				})
			}
		},
		resetVideoState() {
			this.video = {
				tempFilePath: null,
				progress: 0,
				totalBytesSent: 0,
				totalBytesExpectedToSend: 0
			}
			this.videoId = null
			this.videoPath = ''
			this.videoPreviewUrl = ''
		},
		removeVideo() {
			this.videoUploading = false
			this.resetVideoState()
		},
		async uploadVideo(filePath, fileName) {
			this.resetVideoState()
			this.video.tempFilePath = filePath
			this.videoUploading = true
			this.video.progress = 1
			try {
				const result = await uploadVideoFile(filePath, {
					fileName,
					onProgress: (res) => {
						this.video.progress = res.progress || 0
						this.video.totalBytesSent = res.totalBytesSent || 0
						this.video.totalBytesExpectedToSend = res.totalBytesExpectedToSend || 0
					}
				})
				this.videoId = result.video_id
				this.videoPath = result.url || ''
				this.videoPreviewUrl = result.previewUrl || ''
				this.video.progress = 100
			} catch (err) {
				this.resetVideoState()
				this.$appKit && this.$appKit.msg((err && err.message) || this.copy.publishVideoUploadFailed)
			} finally {
				this.videoUploading = false
			}
		},
		resetSubmitState() {
			this.submitting = false
		},
		showPublishError(err) {
			const kind = err && err.kind
			// 拦截器已对 biz_fail 弹 toast，避免重复提示
			if (kind === 'BUSINESS' || kind === 'SILENT') return
			this.$appKit && this.$appKit.msg((err && err.message) || this.copy.publishFailed)
		},
		async onSubmit() {
			if (!this.pushAllowed) return
			if (this.submitting || this.uploading || this.videoUploading) return
			if (!this.signedIn) {
				this.$appKit && this.$appKit.to('/pages/passport/lobby')
				return
			}
			const text = (this.content || '').trim()
			if (this.publishType === 'video') {
				if (!this.video.tempFilePath || this.videoId == null) {
					this.$appKit && this.$appKit.msg(this.copy.publishNeedVideo)
					return
				}
				if (this.video.progress < 100) {
					this.$appKit && this.$appKit.msg(this.copy.publishVideoNotDone)
					return
				}
				if (!text) {
					this.$appKit && this.$appKit.msg(this.copy.publishNeedContent)
					return
				}
				if (!this.labelId) {
					this.$appKit && this.$appKit.msg(this.copy.publishNeedLabel)
					return
				}
				this.submitting = true
				let ok = false
				try {
					await publishVideoPost({
						content: text,
						videoId: this.videoId,
						videoUrl: this.videoPath,
						labelId: this.labelId
					})
					ok = true
				} catch (err) {
					this.showPublishError(err)
				}
				this.resetSubmitState()
				if (!ok) return
				this.finishPublish()
				return
			}
			if (!this.images.length) {
				this.$appKit && this.$appKit.msg(this.copy.publishNeedImage)
				return
			}
			if (!text) {
				this.$appKit && this.$appKit.msg(this.copy.publishNeedContent)
				return
			}
			this.submitting = true
			let ok = false
			try {
				await publishGrassPost({
					content: text,
					images: this.images.slice()
				})
				ok = true
			} catch (err) {
				this.showPublishError(err)
			}
			this.resetSubmitState()
			if (!ok) return
			this.finishPublish()
		},
		finishPublish() {
			this.$appKit && this.$appKit.msg(this.copy.publishOk)
			setTimeout(() => {
				const pages = getCurrentPages()
				if (pages.length > 1) {
					const prev = pages[pages.length - 2]
					const feed = prev.$vm && prev.$vm.$refs && prev.$vm.$refs.feed
					if (feed && typeof feed.reload === 'function') feed.reload()
					uni.navigateBack()
				} else {
					getApp().globalData = getApp().globalData || {}
					getApp().globalData.dynamicsNeedRefresh = true
					uni.switchTab({ url: '/pages/dynamics/index' })
				}
			}, 600)
		}
	}
}
</script>

<style scoped>
.pub-page {
	min-height: 100vh;
	width: 100%;
	overflow-x: hidden;
	box-sizing: border-box;
	background-color: #eef3fb;
}
.pub-nav {
	background-color: rgba(238, 243, 251, 0.96);
}
.pub-nav-row {
	display: flex;
	flex-direction: row;
	align-items: center;
	height: 88rpx;
	padding: 0 28rpx;
	box-sizing: border-box;
}
.pub-back {
	width: 64rpx;
	height: 64rpx;
	border-radius: 18rpx;
	background-color: #ffffff;
	box-shadow: 0 4rpx 16rpx rgba(74, 140, 255, 0.1);
	display: flex;
	align-items: center;
	justify-content: center;
}
.pub-back-icon {
	font-size: 34rpx;
	color: #4a8cff;
}
.pub-nav-title {
	flex: 1;
	text-align: center;
	font-size: 34rpx;
	font-weight: 700;
	color: #1a1d26;
}
.pub-nav-placeholder {
	width: 64rpx;
}
.pub-scroll {
	width: 100%;
	box-sizing: border-box;
}
.pub-body {
	padding: 0 28rpx;
	box-sizing: border-box;
}
.pub-hero {
	margin: 16rpx 0 24rpx;
	padding: 32rpx 24rpx;
	box-sizing: border-box;
	border-radius: 28rpx;
	background: linear-gradient(135deg, #4a8cff 0%, #6ec8ff 100%);
	box-shadow: 0 12rpx 36rpx rgba(74, 140, 255, 0.28);
}
.pub-hero-badge {
	display: inline-block;
	padding: 6rpx 18rpx;
	border-radius: 999rpx;
	font-size: 22rpx;
	color: #4a8cff;
	background-color: rgba(255, 255, 255, 0.92);
	font-weight: 600;
	margin-bottom: 16rpx;
}
.pub-hero-title {
	display: block;
	font-size: 36rpx;
	font-weight: 700;
	color: #ffffff;
	line-height: 1.35;
}
.pub-hero-sub {
	display: block;
	margin-top: 12rpx;
	font-size: 26rpx;
	color: rgba(255, 255, 255, 0.9);
	line-height: 1.5;
}
.pub-type-switch {
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-bottom: 24rpx;
	padding: 8rpx;
	border-radius: 999rpx;
	background-color: #ffffff;
	box-shadow: 0 8rpx 32rpx rgba(74, 140, 255, 0.08);
}
.pub-type-item {
	flex: 1;
	height: 72rpx;
	border-radius: 999rpx;
	display: flex;
	align-items: center;
	justify-content: center;
}
.pub-type-item--active {
	background: linear-gradient(135deg, #4a8cff 0%, #6ec8ff 100%);
	box-shadow: 0 8rpx 20rpx rgba(74, 140, 255, 0.28);
}
.pub-type-text {
	font-size: 28rpx;
	font-weight: 600;
	color: #8a8d9e;
}
.pub-type-item--active .pub-type-text {
	color: #ffffff;
}
.pub-card {
	margin-bottom: 24rpx;
	padding: 24rpx;
	width: 100%;
	box-sizing: border-box;
	background-color: #ffffff;
	border-radius: 28rpx;
	box-shadow: 0 8rpx 32rpx rgba(74, 140, 255, 0.08);
	overflow: hidden;
}
.pub-card-hd {
	display: flex;
	flex-direction: row;
	align-items: center;
	margin-bottom: 24rpx;
}
.pub-card-icon {
	width: 64rpx;
	height: 64rpx;
	border-radius: 18rpx;
	background-color: rgba(74, 140, 255, 0.12);
	font-size: 32rpx;
	text-align: center;
	line-height: 64rpx;
	margin-right: 16rpx;
}
.pub-card-meta {
	flex: 1;
	min-width: 0;
}
.pub-card-title {
	display: block;
	font-size: 30rpx;
	font-weight: 700;
	color: #1a1d26;
}
.pub-card-hint {
	display: block;
	margin-top: 6rpx;
	font-size: 24rpx;
	color: #8a8d9e;
}
.pub-grid {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	justify-content: space-between;
	width: 100%;
	box-sizing: border-box;
}
.pub-grid-cell {
	position: relative;
	width: 31%;
	height: 210rpx;
	margin-bottom: 12rpx;
	border-radius: 16rpx;
	overflow: hidden;
	box-sizing: border-box;
	background-color: #eef2f8;
}
.pub-grid-img {
	width: 100%;
	height: 100%;
}
.pub-grid-del {
	position: absolute;
	top: 8rpx;
	right: 8rpx;
	width: 40rpx;
	height: 40rpx;
	border-radius: 20rpx;
	background-color: rgba(0, 0, 0, 0.55);
	display: flex;
	align-items: center;
	justify-content: center;
}
.pub-grid-del-icon {
	color: #ffffff;
	font-size: 28rpx;
	line-height: 1;
}
.pub-grid-add {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	border: 2rpx dashed rgba(74, 140, 255, 0.35);
	background-color: #f5f8ff;
}
.pub-grid-add-icon {
	font-size: 48rpx;
	color: #4a8cff;
	line-height: 1;
}
.pub-grid-add-text {
	margin-top: 8rpx;
	font-size: 22rpx;
	color: #8a8d9e;
}
.pub-textarea {
	display: block;
	width: 100%;
	min-height: 240rpx;
	padding: 20rpx;
	box-sizing: border-box;
	max-width: 100%;
	border-radius: 16rpx;
	background-color: #f5f7fb;
	font-size: 28rpx;
	line-height: 44rpx;
	color: #1a1d26;
}
.pub-textarea-ph {
	color: #b0b4c0;
}
.pub-counter {
	display: block;
	margin-top: 12rpx;
	text-align: right;
	font-size: 22rpx;
	color: #b0b4c0;
}
.pub-video-row {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
}
.pub-video-col {
	width: 220rpx;
	flex-shrink: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
}
.pub-video-upload {
	position: relative;
	width: 220rpx;
	height: 300rpx;
	flex-shrink: 0;
	border-radius: 16rpx;
	overflow: hidden;
	background-color: #f5f8ff;
	border: 2rpx dashed rgba(74, 140, 255, 0.35);
}
.pub-video-remove-link {
	margin-top: 12rpx;
	width: 100%;
	min-height: 56rpx;
	padding: 0 12rpx;
	box-sizing: border-box;
	border-radius: 16rpx;
	border: 2rpx dashed rgba(74, 140, 255, 0.35);
	background-color: #f5f8ff;
	display: flex;
	align-items: center;
	justify-content: center;
}
.pub-video-remove-link--press {
	background-color: #eef3fb;
}
.pub-video-remove-link-text {
	font-size: 24rpx;
	color: #5c6070;
	font-weight: 500;
	line-height: 1.3;
	text-align: center;
}
.pub-video-preview-wrap {
	position: relative;
	width: 100%;
	height: 100%;
}
.pub-video-preview {
	width: 100%;
	height: 100%;
}
.pub-video-add,
.pub-video-loading {
	width: 100%;
	height: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}
.pub-video-loading {
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	background-color: rgba(255, 255, 255, 0.88);
}
.pub-video-play-mask {
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0.02) 0%, rgba(0, 0, 0, 0.28) 100%);
	pointer-events: none;
}
.pub-video-play-icon {
	width: 72rpx;
	height: 72rpx;
	border-radius: 36rpx;
	background-color: rgba(0, 0, 0, 0.45);
	color: #ffffff;
	font-size: 30rpx;
	line-height: 72rpx;
	text-align: center;
	padding-left: 6rpx;
}
.pub-video-loading-icon {
	font-size: 44rpx;
	color: #4a8cff;
}
.pub-video-loading-text {
	margin-top: 12rpx;
	font-size: 28rpx;
	font-weight: 700;
	color: #4a8cff;
}
.pub-video-loading-sub {
	margin-top: 8rpx;
	font-size: 22rpx;
	color: #8a8d9e;
}
/* #ifdef APP-PLUS */
.pub-video-cover {
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	display: flex;
	align-items: center;
	justify-content: center;
}
.pub-video-cover--loading {
	background-color: rgba(255, 255, 255, 0.88);
}
.pub-video-cover-progress {
	color: #4a8cff;
	font-size: 14px;
	font-weight: bold;
	text-align: center;
}
.pub-video-cover--play {
	background-color: rgba(0, 0, 0, 0.28);
}
.pub-video-cover-play-btn {
	width: 36px;
	height: 36px;
	border-radius: 18px;
	background-color: rgba(0, 0, 0, 0.45);
	color: #ffffff;
	font-size: 15px;
	line-height: 36px;
	text-align: center;
	padding-left: 3px;
}
/* #endif */
.pub-video-editor {
	flex: 1;
	min-width: 0;
	margin-left: 16rpx;
}
.pub-textarea--video {
	min-height: 300rpx;
	height: 300rpx;
}
.pub-labels-scroll {
	width: 100%;
	white-space: nowrap;
}
.pub-labels {
	display: inline-flex;
	flex-direction: row;
	padding: 8rpx 4rpx 4rpx;
}
.pub-label {
	display: flex;
	flex-direction: column;
	align-items: center;
	width: 148rpx;
	margin-right: 12rpx;
	flex-shrink: 0;
}
.pub-label-icon-wrap {
	width: 100rpx;
	height: 100rpx;
	border-radius: 24rpx;
	background-color: #f5f7fb;
	border: 2rpx solid transparent;
	display: flex;
	align-items: center;
	justify-content: center;
	margin-bottom: 12rpx;
	box-sizing: border-box;
}
.pub-label--active .pub-label-icon-wrap {
	background-color: rgba(74, 140, 255, 0.12);
	border-color: #4a8cff;
	box-shadow: 0 6rpx 18rpx rgba(74, 140, 255, 0.18);
}
.pub-label-icon {
	width: 56rpx;
	height: 56rpx;
}
.pub-label-icon-fallback {
	font-size: 34rpx;
	color: #4a8cff;
	font-weight: 700;
}
.pub-label-name {
	width: 100%;
	font-size: 24rpx;
	line-height: 34rpx;
	color: #4a4d5e;
	text-align: center;
}
.pub-label--active .pub-label-name {
	color: #4a8cff;
	font-weight: 700;
}
.pub-label-empty {
	display: block;
	margin-top: 8rpx;
	font-size: 24rpx;
	color: #b0b4c0;
}
.pub-review-tip {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	padding: 20rpx 24rpx;
	border-radius: 20rpx;
	background-color: rgba(74, 140, 255, 0.08);
	border: 2rpx solid rgba(74, 140, 255, 0.16);
	box-sizing: border-box;
}
.pub-review-tip--foot {
	margin-bottom: 16rpx;
}
.pub-review-tip-icon {
	width: 36rpx;
	height: 36rpx;
	margin-right: 12rpx;
	border-radius: 18rpx;
	background-color: rgba(74, 140, 255, 0.16);
	color: #4a8cff;
	font-size: 24rpx;
	font-weight: 700;
	text-align: center;
	line-height: 36rpx;
	flex-shrink: 0;
}
.pub-review-tip-text {
	flex: 1;
	font-size: 24rpx;
	line-height: 38rpx;
	color: #5a6b8a;
}
.pub-bottom-space {
	height: 32rpx;
}
.pub-foot {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 16rpx 28rpx;
	box-sizing: border-box;
	background-color: rgba(255, 255, 255, 0.96);
	box-shadow: 0 -4rpx 24rpx rgba(74, 140, 255, 0.08);
}
.pub-submit {
	width: 100%;
	height: 88rpx;
	margin: 0;
	padding: 0;
	box-sizing: border-box;
	border-radius: 999rpx;
	border: none;
	background: linear-gradient(135deg, #4a8cff 0%, #6ec8ff 100%);
	box-shadow: 0 10rpx 28rpx rgba(74, 140, 255, 0.35);
	display: flex;
	align-items: center;
	justify-content: center;
}
.pub-submit--loading {
	opacity: 0.72;
}
.pub-submit--locked {
	background: #ffffff;
	border: 2rpx solid rgba(74, 140, 255, 0.28);
	box-shadow: 0 6rpx 20rpx rgba(74, 140, 255, 0.1);
}
.pub-submit--locked .pub-submit-text {
	color: #7a9fd4;
	font-weight: 600;
}
.pub-submit-text {
	font-size: 30rpx;
	font-weight: 700;
	color: #ffffff;
}
</style>
