Files
tuanwei-uniapp/pages/gxmu/wxxzx.vue
2026-07-20 11:56:02 +08:00

193 lines
11 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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">GXMU · 未来学术之星</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>
<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.topicName || '未命名课题' }}</view><view class="card-subtitle">{{ item.collegeGradeClass || '-' }}</view></view>
<view class="card-year">{{ item.year || '-' }}</view>
</view>
<view class="meta-line">负责人{{ item.leader || '-' }}</view>
<view class="meta-line">联系电话{{ 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="form-section">
<view class="form-section-title">基本信息</view>
<view class="field-item"><view class="field-label">年份</view><uv-input class="field-input" :modelValue="current.year" border="none" @input="setField('year', $event)" /></view>
<view class="field-item"><view class="field-label">课题名称</view><uv-input class="field-input" :modelValue="current.topicName" border="none" @input="setField('topicName', $event)" /></view>
<view class="field-item"><view class="field-label">课题负责人</view><uv-input class="field-input" :modelValue="current.leader" border="none" @input="setField('leader', $event)" /></view>
<view class="field-item"><view class="field-label">学院年级班别</view><uv-input class="field-input" :modelValue="current.collegeGradeClass" border="none" @input="setField('collegeGradeClass', $event)" /></view>
<view class="field-item"><view class="field-label">联系电话</view><uv-input class="field-input" :modelValue="current.phone" border="none" @input="setField('phone', $event)" /></view>
<view class="field-item"><view class="field-label">指导老师</view><uv-input class="field-input" :modelValue="current.advisor" border="none" @input="setField('advisor', $event)" /></view>
<view class="field-item"><view class="field-label">课题类型</view><uv-input class="field-input" :modelValue="current.topicType" border="none" @input="setField('topicType', $event)" placeholder="自然科学 / 人文科学" /></view>
<view class="field-item"><view class="field-label">立论依据</view><textarea class="field-textarea" :value="current.rationale" @input="setField('rationale', $event)" /></view>
<!-- <view class="field-item"><view class="field-label">指导老师意见</view><textarea class="field-textarea" :value="current.teacherOpinion" @input="setField('teacherOpinion', $event)" /></view>-->
<!-- <view class="field-item"><view class="field-label">指导老师签名</view><uv-input class="field-input" :modelValue="current.teacherSign" border="none" @input="setField('teacherSign', $event)" /></view>-->
<!-- <view class="field-item"><view class="field-label">评审小组意见</view><textarea class="field-textarea" :value="current.reviewOpinion" @input="setField('reviewOpinion', $event)" /></view>-->
<!-- <view class="field-item"><view class="field-label">评审分数</view><uv-input class="field-input" :modelValue="current.reviewScore" border="none" @input="setField('reviewScore', $event)" /></view>-->
<!-- <view class="field-item"><view class="field-label">评审组长签名</view><uv-input class="field-input" :modelValue="current.reviewLeaderSign" border="none" @input="setField('reviewLeaderSign', $event)" /></view>-->
<!-- <view class="field-item"><view class="field-label">学院意见</view><textarea class="field-textarea" :value="current.collegeOpinion" @input="setField('collegeOpinion', $event)" /></view>-->
<!-- <view class="field-item"><view class="field-label">校团委意见</view><textarea class="field-textarea" :value="current.schoolOpinion" @input="setField('schoolOpinion', $event)" /></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>
</view>
</template>
<script>
import CommonHero from '../../components/common-hero/common-hero.vue'
import { addWxxzxForm, getWxxzxForm, updateWxxzxForm, userPageWxxzxForm } from './module-form-service'
const createDefaultForm = () => ({
id: undefined,
year: '',
topicName: '',
leader: '',
collegeGradeClass: '',
phone: '',
advisor: '',
topicType: '',
rationale: '',
teacherOpinion: '',
teacherSign: '',
reviewOpinion: '',
reviewScore: '',
reviewLeaderSign: '',
collegeOpinion: '',
schoolOpinion: '',
promiseSigner: '',
promiseSignature: '',
reviewCollege: '',
reviewReporter: '',
reviewDate: ''
})
export default {
components: {
CommonHero
},
data() {
return {
loading: false,
showEdit: false,
pageTitle: '未来学术之星申报',
fixedYear: '',
list: [],
current: createDefaultForm()
}
},
onLoad(options) {
this.fixedYear = String(options.year || '').trim()
this.pageTitle = decodeURIComponent(options.declareTitle || '未来学术之星申报').trim() || '未来学术之星申报'
this.loadData()
},
methods: {
async loadData() {
this.loading = true
try {
const result = await userPageWxxzxForm({
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.showEdit = true
},
async openEdit(item) {
try {
const detail = item && item.id ? await getWxxzxForm(item.id) : item
this.current = { ...createDefaultForm(), ...(detail || {}), year: (detail && detail.year) || this.fixedYear || '' }
this.showEdit = true
} catch (error) {
uni.showToast({ title: (error && error.message) || '加载详情失败', icon: 'none' })
}
},
closeEdit() { this.showEdit = false },
setField(key, event) {
const value = typeof event === 'string' ? event : (event.detail && event.detail.value) || ''
this.current[key] = value || ''
},
async save() {
try {
const payload = { ...this.current, year: this.fixedYear || this.current.year }
if (payload.id) {
await updateWxxzxForm(payload)
} else {
await addWxxzxForm(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; }
.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; }
.form-section-title { font-size: 28rpx; font-weight: 700; color: #1f2329; margin-bottom: 16rpx; }
.field-item + .field-item { margin-top: 16rpx; }
.field-label { margin-bottom: 10rpx; font-size: 24rpx; color: #5f6b7a; }
.field-textarea { width: 100%; box-sizing: border-box; border-radius: 20rpx; border: 1rpx solid #dce4ec; background: #fff; padding: 20rpx; font-size: 24rpx; color: #1f2329; }
: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; }
.field-textarea { min-height: 180rpx; }
.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>