<template>
	<view class="page">
		<scroll-view scroll-y class="page-scroll">
			<common-hero :title="pageTitle" :use-image-bg="true"></common-hero>
			<view class="hero-card">
				<view class="hero-badge">挑战杯</view>
				<view class="hero-title">{{ pageTitle }}</view>
				<view class="hero-desc">按后台完整字段拆分为项目申报表、项目说明、公开展示信息表。</view>
				<view class="hero-actions">
					<view class="hero-action" @tap="openCreate">立即申报</view>
					<view class="hero-action hero-action--secondary" @tap="loadData">刷新列表</view>
				</view>
			</view>

			<view v-if="loading" class="state-card">
				<view class="state-title">正在加载申报记录...</view>
			</view>
			<view v-else-if="!list.length" class="state-card">
				<view class="state-title">暂无申报记录</view>
				<view class="state-desc">点击上方“立即申报”开始填写挑战杯项目。</view>
			</view>
			<view v-else class="card-list">
				<view v-for="item in list" :key="item.id" class="data-card" @tap="openEdit(item)">
					<view class="card-top">
						<view>
							<view class="card-title">{{ item.projectName || '未命名项目' }}</view>
							<view class="card-subtitle">{{ item.projectType || '-' }} · {{ item.projectGroup || '-' }}</view>
						</view>
						<view class="card-year">{{ item.year || '-' }}</view>
					</view>
					<view class="meta-line">学校：{{ item.schoolName || '-' }}</view>
					<view class="meta-line">负责人：{{ getLeaderInfo(item).leader || '-' }} / {{ getLeaderInfo(item).phone || '-' }}</view>
				</view>
			</view>
		</scroll-view>

		<view v-if="showEdit" class="modal-mask" @tap="closeEdit">
			<view class="modal-panel" @tap.stop>
				<view class="modal-head">
					<view class="modal-title">{{ current.id ? '编辑挑战杯申报' : '新增挑战杯申报' }}</view>
					<view class="modal-close" @tap="closeEdit">关闭</view>
				</view>

				<scroll-view scroll-y class="modal-body">
					<view class="tab-row">
						<view class="tab-item" :class="{ 'tab-item--active': activeTab === 'base' }" @tap="activeTab = 'base'">项目申报表</view>
						<view class="tab-item" :class="{ 'tab-item--active': activeTab === 'detail' }" @tap="activeTab = 'detail'">项目说明</view>
						<view class="tab-item" :class="{ 'tab-item--active': activeTab === 'public' }" @tap="activeTab = 'public'">公开展示信息表</view>
					</view>

					<view v-if="activeTab === 'base'" class="form-section">
						<view class="field-item">
							<view class="field-label">年份</view>
							<uv-input class="field-input field-input--readonly" :modelValue="current.year" border="none" readonly placeholder="当前申报年份" />
						</view>
						<view class="field-grid field-grid--2">
							<view class="field-item">
								<view class="field-label">所在省（区、市）</view>
								<uv-input class="field-input" :modelValue="current.provinceCity" border="none" @input="setField('provinceCity', $event)" placeholder="请输入所在省/市" />
							</view>
							<view class="field-item">
								<view class="field-label">学校名称（全称）</view>
								<uv-input class="field-input" :modelValue="current.schoolName" border="none" @input="setField('schoolName', $event)" placeholder="请输入学校名称" />
							</view>
						</view>
						<view class="field-item">
							<view class="field-label">项目名称</view>
							<uv-input class="field-input" :modelValue="current.projectName" border="none" @input="setField('projectName', $event)" placeholder="请输入项目名称" />
						</view>
						<view class="field-item">
							<view class="field-label">项目类型</view>
							<view class="field-picker" @tap="openFormProjectTypePicker">
								<text :class="current.projectType ? 'field-value' : 'field-placeholder'">
									{{ getOptionLabel(current.projectType, formProjectTypeOptions) || '请选择项目类型' }}
								</text>
							</view>
						</view>
						<view class="field-item">
							<view class="field-label">
								项目分组
								<view class="field-note">仅可选择 1 个组别，按后台申报配置提供选项。</view>
							</view>
							<view class="field-picker" @tap="openFormProjectGroupPicker">
								<text :class="current.projectGroup ? 'field-value' : 'field-placeholder'">
									{{ getOptionLabel(current.projectGroup, formProjectGroupOptions) || '请选择项目分组' }}
								</text>
							</view>
						</view>

						<view class="section-header">
							<view class="section-subtitle">团队成员</view>
							<view class="section-action" @tap="addTeamMember">新增成员</view>
						</view>
						<view v-if="!current.teamMembers.length" class="empty-inline">暂无团队成员，请手动新增。</view>
						<view v-for="(item, index) in current.teamMembers" :key="`member-${index}`" class="group-card">
							<view class="group-head">
								<view class="group-title">成员 {{ index + 1 }}</view>
								<view class="group-remove" @tap="removeTeamMember(index)">删除</view>
							</view>
							<view class="field-grid field-grid--2">
								<view class="field-item"><view class="field-label">姓名</view><uv-input class="field-input" :modelValue="item.name" border="none" @input="setTeamMemberField(index, 'name', $event)" /></view>
								<view class="field-item"><view class="field-label">性别</view><uv-input class="field-input" :modelValue="item.gender" border="none" @input="setTeamMemberField(index, 'gender', $event)" /></view>
								<view class="field-item"><view class="field-label">学院</view><uv-input class="field-input" :modelValue="item.college" border="none" @input="setTeamMemberField(index, 'college', $event)" /></view>
								<view class="field-item"><view class="field-label">年级、专业</view><uv-input class="field-input" :modelValue="item.gradeMajor" border="none" @input="setTeamMemberField(index, 'gradeMajor', $event)" /></view>
								<view class="field-item"><view class="field-label">手机</view><uv-input class="field-input" :modelValue="item.phone" border="none" @input="setTeamMemberField(index, 'phone', $event)" /></view>
								<view class="field-item"><view class="field-label">备注</view><uv-input class="field-input" :modelValue="item.remark" border="none" @input="setTeamMemberField(index, 'remark', $event)" placeholder="负责人及学历等备注" /></view>
							</view>
						</view>

						<view class="section-header">
							<view class="section-subtitle">指导教师</view>
							<view class="section-action" @tap="addAdvisor">新增教师</view>
						</view>
						<view v-if="!current.advisors.length" class="empty-inline">暂无指导教师，请手动新增。</view>
						<view v-for="(item, index) in current.advisors" :key="`advisor-${index}`" class="group-card">
							<view class="group-head">
								<view class="group-title">指导教师 {{ index + 1 }}</view>
								<view class="group-remove" @tap="removeAdvisor(index)">删除</view>
							</view>
							<view class="field-grid field-grid--2">
								<view class="field-item"><view class="field-label">姓名</view><uv-input class="field-input" :modelValue="item.name" border="none" @input="setAdvisorField(index, 'name', $event)" /></view>
								<view class="field-item"><view class="field-label">性别</view><uv-input class="field-input" :modelValue="item.gender" border="none" @input="setAdvisorField(index, 'gender', $event)" /></view>
								<view class="field-item"><view class="field-label">学院</view><uv-input class="field-input" :modelValue="item.college" border="none" @input="setAdvisorField(index, 'college', $event)" /></view>
								<view class="field-item"><view class="field-label">职称</view><uv-input class="field-input" :modelValue="item.title" border="none" @input="setAdvisorField(index, 'title', $event)" /></view>
								<view class="field-item"><view class="field-label">职务</view><uv-input class="field-input" :modelValue="item.duty" border="none" @input="setAdvisorField(index, 'duty', $event)" /></view>
								<view class="field-item"><view class="field-label">手机</view><uv-input class="field-input" :modelValue="item.phone" border="none" @input="setAdvisorField(index, 'phone', $event)" /></view>
							</view>
						</view>

						<view class="field-item">
							<view class="field-label">项目简介（500 字以内）</view>
							<textarea class="field-textarea" :value="current.projectBrief" @input="setField('projectBrief', $event)" placeholder="请输入项目简介" />
						</view>
					</view>

					<view v-else-if="activeTab === 'detail'" class="form-section">
						<view class="field-item"><view class="field-label">社会价值（500 字以内）</view><textarea class="field-textarea" :value="current.socialValue" @input="setField('socialValue', $event)" /></view>
						<view class="field-item"><view class="field-label">实践过程（500 字以内）</view><textarea class="field-textarea" :value="current.practiceProcess" @input="setField('practiceProcess', $event)" /></view>
						<view class="field-item"><view class="field-label">创新意义（500 字以内）</view><textarea class="field-textarea" :value="current.innovationMeaning" @input="setField('innovationMeaning', $event)" /></view>
						<view class="field-item"><view class="field-label">发展前景（500 字以内）</view><textarea class="field-textarea" :value="current.developmentProspect" @input="setField('developmentProspect', $event)" /></view>
						<view class="field-item"><view class="field-label">团队协作（500 字以内）</view><textarea class="field-textarea" :value="current.teamCooperation" @input="setField('teamCooperation', $event)" /></view>
						<view class="field-item"><view class="field-label">项目介绍材料</view><textarea class="field-textarea" :value="current.projectMaterials" @input="setField('projectMaterials', $event)" /></view>
						<view class="field-item"><view class="field-label">其他相关证明材料</view><textarea class="field-textarea" :value="current.otherProofs" @input="setField('otherProofs', $event)" placeholder="选报，相关证明材料说明" /></view>
					</view>

					<view v-else class="form-section">
						<view class="field-item">
							<view class="field-label">项目名称</view>
							<uv-input class="field-input" :modelValue="current.projectName" border="none" @input="setField('projectName', $event)" placeholder="请输入项目名称" />
						</view>
						<view class="field-item">
							<view class="field-label">参赛学校</view>
							<uv-input class="field-input" :modelValue="current.schoolName" border="none" @input="setField('schoolName', $event)" placeholder="请输入参赛学校" />
						</view>
						<view class="field-item">
							<view class="field-label">项目类型</view>
							<view class="field-picker" @tap="openPublicProjectTypePicker">
								<text :class="current.publicProjectType ? 'field-value' : 'field-placeholder'">
									{{ getOptionLabel(current.publicProjectType, publicProjectTypeOptions) || '请选择项目类型' }}
								</text>
							</view>
						</view>
						<view class="field-item">
							<view class="field-label">项目分组</view>
							<view class="field-picker" @tap="openPublicProjectGroupPicker">
								<text :class="current.publicProjectGroup ? 'field-value' : 'field-placeholder'">
									{{ getOptionLabel(current.publicProjectGroup, publicProjectGroupOptions) || '请选择项目分组' }}
								</text>
							</view>
						</view>
						<view class="field-item">
							<view class="field-label">我们的项目</view>
							<textarea class="field-textarea" :value="current.projectSummary" @input="setField('projectSummary', $event)" placeholder="150字以内，阐述项目的实践来源、社会背景、基本情况等" />
						</view>
						<view class="field-item">
							<view class="field-label">我们的团队</view>
							<view class="upload-card">
								<image v-if="current.teamIntro" class="upload-image" :src="current.teamIntro" mode="aspectFill" @tap="previewImage(current.teamIntro)" />
								<view v-else class="upload-empty">请上传团队图片</view>
								<view class="upload-actions">
									<view class="upload-btn" @tap="chooseTeamImage">上传图片</view>
									<view v-if="current.teamIntro" class="upload-btn upload-btn--ghost" @tap="clearField('teamIntro')">移除</view>
								</view>
							</view>
						</view>
						<view class="field-item"><view class="field-label">我们的口号</view><uv-input class="field-input" :modelValue="current.teamSlogan" border="none" @input="setField('teamSlogan', $event)" placeholder="20字以内" /></view>
						<view class="field-item">
							<view class="field-label">我们的实践日志（选填）</view>
							<view class="upload-card">
								<view v-if="current.practiceLog" class="video-box">
									<video class="upload-video" :src="current.practiceLog" controls object-fit="cover"></video>
								</view>
								<view v-else class="upload-empty">请上传实践日志视频</view>
								<view class="upload-actions">
									<view class="upload-btn" @tap="choosePracticeVideo">上传视频</view>
									<view v-if="current.practiceLog" class="upload-btn upload-btn--ghost" @tap="clearField('practiceLog')">移除</view>
								</view>
							</view>
						</view>
					</view>
				</scroll-view>

				<view class="modal-actions">
					<view class="ghost-btn" @tap="closeEdit">取消</view>
					<view class="primary-btn" @tap="save">保存</view>
				</view>
			</view>
		</view>

		<uv-picker
			ref="formProjectTypePicker"
			title="选择项目类型"
			:columns="formProjectTypePickerColumns"
			:defaultIndex="[formProjectTypeIndex]"
			keyName="text"
			@close="noop"
			@cancel="noop"
			@confirm="confirmFormProjectTypePicker"
		></uv-picker>

		<uv-picker
			ref="formProjectGroupPicker"
			title="选择项目分组"
			:columns="formProjectGroupPickerColumns"
			:defaultIndex="[formProjectGroupIndex]"
			keyName="text"
			@close="noop"
			@cancel="noop"
			@confirm="confirmFormProjectGroupPicker"
		></uv-picker>

		<uv-picker
			ref="publicProjectTypePicker"
			title="选择公开项目类型"
			:columns="publicProjectTypePickerColumns"
			:defaultIndex="[publicProjectTypeIndex]"
			keyName="text"
			@close="noop"
			@cancel="noop"
			@confirm="confirmPublicProjectTypePicker"
		></uv-picker>

		<uv-picker
			ref="publicProjectGroupPicker"
			title="选择公开项目分组"
			:columns="publicProjectGroupPickerColumns"
			:defaultIndex="[publicProjectGroupIndex]"
			keyName="text"
			@close="noop"
			@cancel="noop"
			@confirm="confirmPublicProjectGroupPicker"
		></uv-picker>
	</view>
</template>

<script>
import CommonHero from '../../components/common-hero/common-hero.vue'
import { addTzbcyForm, getDeclare, getTzbcyForm, uploadTempFile, userPageTzbcyForm } from './module-form-service'

const FALLBACK_PROJECT_TYPE_OPTIONS = [
	{ label: 'I. 普通高校', value: '普通高校' },
	{ label: 'II. 职业院校', value: '职业院校' },
	{ label: 'III. 东盟留学生专项', value: '东盟留学生专项' }
]

const FALLBACK_PROJECT_GROUP_OPTIONS = [
	{ label: 'A. 科技创新和未来产业', value: 'A. 科技创新和未来产业' },
	{ label: 'B. 乡村振兴和农业农村现代化', value: 'B. 乡村振兴和农业农村现代化' },
	{ label: 'C. 社会治理和公共服务', value: 'C. 社会治理和公共服务' },
	{ label: 'D. 生态环保和可持续发展', value: 'D. 生态环保和可持续发展' },
	{ label: 'E. 文化创意和区域合作', value: 'E. 文化创意和区域合作' }
]

const createTeamMember = () => ({
	name: '',
	gender: '',
	college: '',
	gradeMajor: '',
	phone: '',
	remark: ''
})

const createAdvisor = () => ({
	name: '',
	gender: '',
	college: '',
	title: '',
	duty: '',
	phone: ''
})

const createDefaultForm = () => ({
	id: undefined,
	year: '',
	provinceCity: '',
	schoolName: '广西医科大学',
	projectName: '',
	projectType: '',
	projectGroup: '',
	publicProjectType: '',
	publicProjectGroup: '',
	leader: '',
	phone: '',
	teamMembers: [],
	advisors: [],
	projectBrief: '',
	socialValue: '',
	practiceProcess: '',
	innovationMeaning: '',
	developmentProspect: '',
	teamCooperation: '',
	projectMaterials: '',
	otherProofs: '',
	projectSummary: '',
	teamIntro: '',
	teamSlogan: '',
	practiceLog: ''
})

const parseMultiValueField = (value) => {
	if (Array.isArray(value)) {
		return value.map((item) => String(item || '').trim()).filter(Boolean)
	}
	if (typeof value !== 'string') {
		return []
	}
	const trimmed = value.trim()
	if (!trimmed) {
		return []
	}
	try {
		const parsed = JSON.parse(trimmed)
		if (Array.isArray(parsed)) {
			return parsed.map((item) => String(item || '').trim()).filter(Boolean)
		}
	} catch (error) {}
	return [trimmed]
}

const buildChoiceOptions = (customValues, fallback, currentValue) => {
	const values = (customValues && customValues.length ? customValues : fallback.map((item) => item.value))
		.map((item) => String(item || '').trim())
		.filter((item, index, arr) => item && arr.indexOf(item) === index)
	if (currentValue && String(currentValue).trim() && !values.includes(String(currentValue).trim())) {
		values.push(String(currentValue).trim())
	}
	return values.map((value) => {
		const matched = fallback.find((item) => item.value === value)
		return {
			label: matched && matched.label ? matched.label : value,
			value
		}
	})
}

export default {
	components: {
		CommonHero
	},
	data() {
		return {
			loading: false,
			initializingDetail: false,
			showEdit: false,
			activeTab: 'base',
			pageTitle: '挑战杯申报',
			fixedYear: '',
			declareId: '',
			list: [],
			current: createDefaultForm(),
			declareConfig: null
		}
	},
	computed: {
		formProjectTypeOptions() {
			const config = this.declareConfig || {}
			return buildChoiceOptions(
				parseMultiValueField(config.formProjectType || config.projectType),
				FALLBACK_PROJECT_TYPE_OPTIONS,
				this.current.projectType
			)
		},
		formProjectGroupOptions() {
			const config = this.declareConfig || {}
			return buildChoiceOptions(
				parseMultiValueField(config.formProjectGroup || config.projectGroup),
				FALLBACK_PROJECT_GROUP_OPTIONS,
				this.current.projectGroup
			)
		},
		publicProjectTypeOptions() {
			const config = this.declareConfig || {}
			return buildChoiceOptions(
				parseMultiValueField(config.publicProjectType || config.projectType),
				FALLBACK_PROJECT_TYPE_OPTIONS,
				this.current.publicProjectType
			)
		},
		publicProjectGroupOptions() {
			const config = this.declareConfig || {}
			return buildChoiceOptions(
				parseMultiValueField(config.publicProjectGroup || config.projectGroup),
				FALLBACK_PROJECT_GROUP_OPTIONS,
				this.current.publicProjectGroup
			)
		},
		formProjectTypePickerColumns() {
			return [this.formProjectTypeOptions.map((item) => ({ text: item.label, value: item.value }))]
		},
		formProjectGroupPickerColumns() {
			return [this.formProjectGroupOptions.map((item) => ({ text: item.label, value: item.value }))]
		},
		publicProjectTypePickerColumns() {
			return [this.publicProjectTypeOptions.map((item) => ({ text: item.label, value: item.value }))]
		},
		publicProjectGroupPickerColumns() {
			return [this.publicProjectGroupOptions.map((item) => ({ text: item.label, value: item.value }))]
		},
		formProjectTypeIndex() {
			return this.getOptionIndex(this.current.projectType, this.formProjectTypeOptions)
		},
		formProjectGroupIndex() {
			return this.getOptionIndex(this.current.projectGroup, this.formProjectGroupOptions)
		},
		publicProjectTypeIndex() {
			return this.getOptionIndex(this.current.publicProjectType, this.publicProjectTypeOptions)
		},
		publicProjectGroupIndex() {
			return this.getOptionIndex(this.current.publicProjectGroup, this.publicProjectGroupOptions)
		}
	},
	onLoad(options) {
		this.fixedYear = String(options.year || '').trim()
		this.declareId = String(options.id || '').trim()
		this.pageTitle = decodeURIComponent(options.declareTitle || '挑战杯申报').trim() || '挑战杯申报'
		this.loadData()
		this.loadDeclareConfig()
		this.loadInitialDetail(options)
	},
	methods: {
		getOptionIndex(value, options) {
			const index = (options || []).findIndex((item) => item.value === value)
			return index > -1 ? index : 0
		},
		getOptionLabel(value, options) {
			const matched = (options || []).find((item) => item.value === value)
			return matched ? matched.label : value
		},
		normalizeDetail(detail) {
			const defaults = createDefaultForm()
			const normalizedProjectType = (detail && detail.projectType) || ''
			const normalizedProjectGroup = (detail && detail.projectGroup) || ''
			return {
				...defaults,
				...(detail || {}),
				projectType: normalizedProjectType,
				projectGroup: normalizedProjectGroup,
				publicProjectType: (detail && detail.publicProjectType) || normalizedProjectType,
				publicProjectGroup: (detail && detail.publicProjectGroup) || normalizedProjectGroup,
				teamMembers: Array.isArray(detail && detail.teamMembers) ? detail.teamMembers.map((item) => ({ ...createTeamMember(), ...(item || {}) })) : [],
				advisors: Array.isArray(detail && detail.advisors) ? detail.advisors.map((item) => ({ ...createAdvisor(), ...(item || {}) })) : []
			}
		},
		getLeaderInfo(record) {
			const members = Array.isArray(record && record.teamMembers) ? record.teamMembers : []
			const firstMember = members.find((item) => String(item && (item.name || item.phone) || '').trim())
			return {
				leader: (record && record.leader) || (firstMember && firstMember.name) || '',
				phone: (record && record.phone) || (firstMember && firstMember.phone) || ''
			}
		},
		async loadDeclareConfig() {
			if (!this.declareId) {
				return
			}
			try {
				const result = await getDeclare(this.declareId)
				this.declareConfig = result || null
				const declareYear = String((result && result.year) || '').trim()
				if (declareYear) {
					this.fixedYear = declareYear
					this.current.year = declareYear
				}
			} catch (error) {
				uni.showToast({ title: (error && error.message) || '申报配置加载失败', icon: 'none' })
			}
		},
		async loadInitialDetail(options) {
			const id = String((options && options.id) || '').trim()
			if (!id) {
				return
			}
			this.initializingDetail = true
			try {
				const detail = await getTzbcyForm(id)
				this.current = {
					...this.normalizeDetail(detail),
					year: String((detail && detail.year) || this.fixedYear || '').trim()
				}
				if (this.current.year) {
					this.fixedYear = this.current.year
				}
				// this.showEdit = true
			} catch (error) {
				uni.showToast({ title: (error && error.message) || '加载详情失败', icon: 'none' })
			} finally {
				this.initializingDetail = false
			}
		},
		async loadData() {
			this.loading = true
			try {
				const result = await userPageTzbcyForm({
					page: 1,
					limit: 50,
					year: this.fixedYear || undefined
				})
				this.list = Array.isArray(result && result.list) ? result.list : []
			} catch (error) {
				uni.showToast({ title: (error && error.message) || '加载失败', icon: 'none' })
			} finally {
				this.loading = false
			}
		},
		openCreate() {
			this.current = {
				...createDefaultForm(),
				year: this.fixedYear || ''
			}
			this.activeTab = 'base'
			this.showEdit = true
		},
		async openEdit(item) {
			try {
				const detail = item && item.id ? await getTzbcyForm(item.id) : item
				this.current = {
					...this.normalizeDetail(detail),
					year: String((detail && detail.year) || this.fixedYear || '').trim()
				}
				this.activeTab = 'base'
				this.showEdit = true
			} catch (error) {
				uni.showToast({ title: (error && error.message) || '加载详情失败', icon: 'none' })
			}
		},
		closeEdit() {
			this.showEdit = false
		},
		noop() {
			return
		},
		setField(key, event) {
			const value = typeof event === 'string' ? event : (event.detail && event.detail.value) || ''
			this.current[key] = value || ''
		},
		clearField(key) {
			this.current[key] = ''
		},
		async chooseTeamImage() {
			try {
				const result = await new Promise((resolve, reject) => {
					uni.chooseImage({
						count: 1,
						sizeType: ['compressed'],
						sourceType: ['album', 'camera'],
						success: resolve,
						fail: reject
					})
				})
				const file = ((result && result.tempFiles) || [])[0]
				if (!file) {
					return
				}
				uni.showLoading({ title: '上传中', mask: true })
				const uploaded = await uploadTempFile(file)
				this.current.teamIntro = uploaded.url || uploaded.downloadUrl || uploaded.path || ''
				uni.showToast({ title: '图片上传成功', icon: 'none' })
			} catch (error) {
				if (error && error.errMsg && String(error.errMsg).includes('cancel')) {
					return
				}
				uni.showToast({ title: (error && error.message) || '图片上传失败', icon: 'none' })
			} finally {
				uni.hideLoading()
			}
		},
		async choosePracticeVideo() {
			try {
				const result = await new Promise((resolve, reject) => {
					uni.chooseVideo({
						sourceType: ['album', 'camera'],
						maxDuration: 120,
						compressed: true,
						success: resolve,
						fail: reject
					})
				})
				if (!result || !result.tempFilePath) {
					return
				}
				const file = {
					path: result.tempFilePath,
					name: result.name || 'practice-log.mp4',
					size: result.size || 0
				}
				uni.showLoading({ title: '上传中', mask: true })
				const uploaded = await uploadTempFile(file)
				this.current.practiceLog = uploaded.url || uploaded.downloadUrl || uploaded.path || ''
				uni.showToast({ title: '视频上传成功', icon: 'none' })
			} catch (error) {
				if (error && error.errMsg && String(error.errMsg).includes('cancel')) {
					return
				}
				uni.showToast({ title: (error && error.message) || '视频上传失败', icon: 'none' })
			} finally {
				uni.hideLoading()
			}
		},
		previewImage(url) {
			if (!url) {
				return
			}
			uni.previewImage({
				urls: [url],
				current: url
			})
		},
		setTeamMemberField(index, key, event) {
			const value = typeof event === 'string' ? event : (event.detail && event.detail.value) || ''
			this.current.teamMembers[index][key] = value || ''
		},
		addTeamMember() {
			this.current.teamMembers = [...this.current.teamMembers, createTeamMember()]
		},
		removeTeamMember(index) {
			this.current.teamMembers = this.current.teamMembers.filter((_, currentIndex) => currentIndex !== index)
		},
		setAdvisorField(index, key, event) {
			const value = typeof event === 'string' ? event : (event.detail && event.detail.value) || ''
			this.current.advisors[index][key] = value || ''
		},
		addAdvisor() {
			this.current.advisors = [...this.current.advisors, createAdvisor()]
		},
		removeAdvisor(index) {
			this.current.advisors = this.current.advisors.filter((_, currentIndex) => currentIndex !== index)
		},
		openFormProjectTypePicker() {
			this.$nextTick(() => {
				this.$refs.formProjectTypePicker && this.$refs.formProjectTypePicker.open()
			})
		},
		openFormProjectGroupPicker() {
			this.$nextTick(() => {
				this.$refs.formProjectGroupPicker && this.$refs.formProjectGroupPicker.open()
			})
		},
		openPublicProjectTypePicker() {
			this.$nextTick(() => {
				this.$refs.publicProjectTypePicker && this.$refs.publicProjectTypePicker.open()
			})
		},
		openPublicProjectGroupPicker() {
			this.$nextTick(() => {
				this.$refs.publicProjectGroupPicker && this.$refs.publicProjectGroupPicker.open()
			})
		},
		confirmFormProjectTypePicker(event) {
			const value = (((event || {}).value || [])[0] || {}).value || ''
			this.current.projectType = value
		},
		confirmFormProjectGroupPicker(event) {
			const value = (((event || {}).value || [])[0] || {}).value || ''
			this.current.projectGroup = value
		},
		confirmPublicProjectTypePicker(event) {
			const value = (((event || {}).value || [])[0] || {}).value || ''
			this.current.publicProjectType = value
		},
		confirmPublicProjectGroupPicker(event) {
			const value = (((event || {}).value || [])[0] || {}).value || ''
			this.current.publicProjectGroup = value
		},
		buildSavePayload() {
			const leaderInfo = this.getLeaderInfo(this.current)
			return {
				...this.current,
				year: this.fixedYear || this.current.year,
				leader: leaderInfo.leader,
				phone: leaderInfo.phone
			}
		},
		hasValidTeamMember() {
			return (this.current.teamMembers || []).some((item) => {
				return [item.name, item.phone, item.college, item.gradeMajor].some((value) => String(value || '').trim())
			})
		},
		hasValidAdvisor() {
			return (this.current.advisors || []).some((item) => {
				return [item.name, item.phone, item.college, item.title, item.duty].some((value) => String(value || '').trim())
			})
		},
		async save() {
			try {
				if (!this.hasValidTeamMember()) {
					uni.showToast({ title: '请至少填写 1 名团队成员', icon: 'none' })
					return
				}
				if (!this.hasValidAdvisor()) {
					uni.showToast({ title: '请至少填写 1 名指导教师', icon: 'none' })
					return
				}
				const payload = this.buildSavePayload()
				await addTzbcyForm(payload)
				uni.showToast({ title: '保存成功', icon: 'none' })
				this.closeEdit()
				this.loadData()
			} catch (error) {
				uni.showToast({ title: (error && error.message) || '保存失败', icon: 'none' })
			}
		}
	}
}
</script>

<style lang="scss" scoped>
.page { min-height: 100vh; background: linear-gradient(180deg, #f5fbff 0%, #eef7ff 100%); }
.page-scroll { height: 100vh; padding: 24rpx; box-sizing: border-box; }
.hero-card,.state-card,.data-card { border-radius: 28rpx; }
.hero-card { padding: 34rpx 36rpx; background: rgba(255,255,255,.5); box-shadow: 0 4rpx 12rpx 0 rgba(174,174,174,.4); backdrop-filter: blur(24rpx); -webkit-backdrop-filter: blur(24rpx); border: 1rpx solid rgba(255,255,255,.5); }
.hero-badge { display: inline-flex; padding: 10rpx 18rpx; border-radius: 999rpx; background: rgba(20,150,242,.1); font-size: 22rpx; color: #1496f2; }
.hero-title { margin-top: 8rpx; padding-left: 10rpx; font-size: 30rpx; font-weight: 700; line-height: 1.35; color: #18a0f7; border-left: 5px solid #0f94ef; }
.hero-desc { margin-top: 20rpx; font-size: 24rpx; line-height: 1.8; color: #7f7f7f; }
.hero-actions { display: flex; gap: 16rpx; margin-top: 24rpx; }
.hero-action { padding: 14rpx 24rpx; border-radius: 999rpx; background: rgba(20,150,242,.12); font-size: 24rpx; color: #1496f2; }
.hero-action--secondary { background: rgba(31,35,41,.08); color: #5f6b76; }
.state-card,.data-card { margin-top: 24rpx; padding: 24rpx; background: rgba(255,255,255,.96); box-shadow: 0 10rpx 28rpx rgba(34,94,142,.08); }
.state-title,.card-title { font-size: 30rpx; font-weight: 700; color: #1f2329; }
.state-desc,.card-subtitle,.meta-line { margin-top: 10rpx; font-size: 24rpx; line-height: 1.6; color: #786e69; }
.card-list { margin-top: 24rpx; display: flex; flex-direction: column; gap: 16rpx; }
.card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16rpx; }
.card-year { padding: 10rpx 16rpx; border-radius: 999rpx; background: #eef5ff; color: #1554ad; font-size: 22rpx; }
.modal-mask { position: fixed; inset: 0; background: rgba(15,23,42,.34); display: flex; align-items: flex-end; z-index: 99; }
.modal-panel { width: 100%; max-height: 92vh; border-radius: 32rpx 32rpx 0 0; background: #fff; display: flex; flex-direction: column; }
.modal-head { display: flex; justify-content: space-between; align-items: center; padding: 24rpx; border-bottom: 1rpx solid #eef1f4; }
.modal-title { font-size: 30rpx; font-weight: 700; color: #1f2329; }
.modal-close { font-size: 24rpx; color: #7c8a96; }
.modal-body { max-height: 70vh; padding: 24rpx; box-sizing: border-box; }
.tab-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12rpx; margin-bottom: 20rpx; }
.tab-item { height: 76rpx; line-height: 76rpx; border-radius: 18rpx; background: #eff5ff; color: #1554ad; font-size: 24rpx; text-align: center; }
.tab-item--active { background: linear-gradient(135deg, #0f7dd1 0%, #1496f2 100%); color: #fff; }
.form-section + .form-section { margin-top: 24rpx; }
.form-section-title,.section-subtitle { font-size: 28rpx; font-weight: 700; color: #1f2329; margin-bottom: 16rpx; }
.section-header { display: flex; align-items: center; justify-content: space-between; gap: 16rpx; margin-top: 24rpx; }
.section-action { flex-shrink: 0; font-size: 22rpx; font-weight: 600; color: #1496f2; }
.section-subtitle { margin-top: 24rpx; }
.empty-inline { margin-top: 12rpx; padding: 20rpx; border-radius: 16rpx; background: #f8fafc; color: #98a2b3; font-size: 24rpx; text-align: center; }
.group-card { margin-top: 16rpx; padding: 20rpx; border-radius: 20rpx; background: #f8fbff; border: 1rpx solid #dce4ec; }
.group-head { display: flex; align-items: center; justify-content: space-between; gap: 16rpx; margin-bottom: 16rpx; }
.group-title { margin-bottom: 16rpx; font-size: 24rpx; font-weight: 700; color: #1554ad; }
.group-remove { flex-shrink: 0; font-size: 22rpx; color: #d92d20; }
.field-grid { display: grid; gap: 16rpx; }
.field-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field-item + .field-item { margin-top: 16rpx; }
.field-label { margin-bottom: 10rpx; font-size: 24rpx; color: #5f6b7a; }
.field-note { margin-top: 6rpx; font-size: 20rpx; line-height: 1.6; color: #98a2b3; }
.field-textarea { width: 100%; box-sizing: border-box; border-radius: 20rpx; border: 1rpx solid #dce4ec; background: #fff; padding: 20rpx; font-size: 24rpx; color: #1f2329; min-height: 180rpx; }
:deep(.field-input.uv-input) { width: 100%; box-sizing: border-box; border-radius: 20rpx; border: 1rpx solid #dce4ec !important; background: #fff !important; padding: 20rpx !important; }
:deep(.field-input.uv-input .uv-input__content__field-wrapper__field) { font-size: 24rpx; color: #1f2329; min-height: 40rpx; }
:deep(.field-input--readonly.uv-input) { background: #f8fafc !important; }
:deep(.field-input--readonly.uv-input .uv-input__content__field-wrapper__field) { color: #667085; }
.field-picker { width: 100%; box-sizing: border-box; padding: 20rpx; border-radius: 20rpx; border: 1rpx solid rgba(220,220,220,1); background: #F4FCFF; font-size: 24rpx; }
.field-placeholder { color: #98a2b3; }
.field-value { color: #1f2329; }
.upload-card { padding: 20rpx; border-radius: 20rpx; border: 1rpx solid #dce4ec; background: #fff; }
.upload-empty { display: flex; align-items: center; justify-content: center; min-height: 220rpx; border-radius: 16rpx; background: #f8fafc; color: #98a2b3; font-size: 24rpx; }
.upload-image { width: 100%; height: 280rpx; border-radius: 16rpx; background: #f3f4f6; }
.video-box { border-radius: 16rpx; overflow: hidden; background: #0f172a; }
.upload-video { width: 100%; height: 320rpx; }
.upload-actions { display: flex; gap: 16rpx; margin-top: 18rpx; }
.upload-btn { flex: 1; height: 76rpx; line-height: 76rpx; border-radius: 18rpx; background: linear-gradient(135deg, #0f7dd1 0%, #1496f2 100%); color: #fff; text-align: center; font-size: 24rpx; font-weight: 600; }
.upload-btn--ghost { background: #eef5ff; color: #1554ad; }
.modal-actions { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16rpx; padding: 24rpx; border-top: 1rpx solid #eef1f4; }
.ghost-btn,.primary-btn { height: 84rpx; line-height: 84rpx; border-radius: 22rpx; text-align: center; font-size: 26rpx; font-weight: 700; }
.ghost-btn { background: #f6f7fa; color: #50617a; }
.primary-btn { background: linear-gradient(135deg, #0f7dd1 0%, #1496f2 100%); color: #fff; }
</style>
