初始化:职引项目 v1.0
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<view class="page fade-in">
|
||||
<view class="hero">
|
||||
<text class="hero-title">贡献面经</text>
|
||||
<text class="hero-sub">分享你的面试经验,帮助更多同学</text>
|
||||
</view>
|
||||
|
||||
<view class="form card">
|
||||
<view class="form-group">
|
||||
<text class="form-label">公司名称 <text class="required">*</text></text>
|
||||
<input class="form-input" v-model="form.company" placeholder="如:腾讯、字节跳动、阿里巴巴" />
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">面试岗位 <text class="required">*</text></text>
|
||||
<input class="form-input" v-model="form.position" placeholder="如:前端工程师、产品经理" />
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">面试轮次</text>
|
||||
<input class="form-input" v-model="form.rounds" placeholder="如:一面(技术面)" />
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">遇到的面试题(每行一题)</text>
|
||||
<textarea
|
||||
class="form-textarea"
|
||||
v-model="questionsText"
|
||||
placeholder="把你记得的面试题写下来,帮大家提前准备: 1. 请介绍一下你最熟悉的项目 2. 解释一下闭包的原理 ..."
|
||||
:maxlength="2000"
|
||||
></textarea>
|
||||
<text class="form-hint">{{ questionsText.length }}/2000</text>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">面试感受/经验</text>
|
||||
<textarea
|
||||
class="form-textarea"
|
||||
v-model="form.experience"
|
||||
placeholder="分享一下整体感受、面试官风格、需要特别注意的地方..."
|
||||
:maxlength="1000"
|
||||
></textarea>
|
||||
<text class="form-hint">{{ form.experience.length }}/1000</text>
|
||||
</view>
|
||||
|
||||
<view class="form-group">
|
||||
<text class="form-label">标签(可选)</text>
|
||||
<view class="tag-input-area">
|
||||
<view class="tag-list">
|
||||
<view
|
||||
v-for="tag in presetTags"
|
||||
:key="tag"
|
||||
class="tag-item"
|
||||
:class="{ selected: form.tags.includes(tag) }"
|
||||
@click="toggleTag(tag)"
|
||||
>{{ tag }}</view>
|
||||
</view>
|
||||
<input class="form-input" v-model="customTag" placeholder="自定义标签,回车添加" @confirm="addCustomTag" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<button class="btn-submit" @click="submit" :disabled="submitting">
|
||||
{{ submitting ? '提交中...' : '提交面经' }}
|
||||
</button>
|
||||
|
||||
<view class="success-box" v-if="submitted">
|
||||
<text class="success-icon">🎉</text>
|
||||
<text class="success-text">感谢你的分享!你的面经将帮助更多同学准备面试</text>
|
||||
<text class="success-action" @click="goBack">返回</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-spacer"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { api } from '../../config'
|
||||
|
||||
const props = defineProps({ interviewId: String, position: String })
|
||||
const form = ref({ company: '', position: '', rounds: '', experience: '', tags: [] })
|
||||
const questionsText = ref('')
|
||||
const customTag = ref('')
|
||||
const submitting = ref(false)
|
||||
const submitted = ref(false)
|
||||
|
||||
const presetTags = ['算法题多', '重视项目经历', '面试官nice', '压力面', '手撕代码', '系统设计', '行为面试', '八股文']
|
||||
|
||||
const token = () => uni.getStorageSync('token') || ''
|
||||
|
||||
onMounted(() => {
|
||||
if (props.position) form.value.position = props.position
|
||||
})
|
||||
|
||||
const toggleTag = (tag) => {
|
||||
const idx = form.value.tags.indexOf(tag)
|
||||
if (idx > -1) form.value.tags.splice(idx, 1)
|
||||
else form.value.tags.push(tag)
|
||||
}
|
||||
|
||||
const addCustomTag = () => {
|
||||
const t = customTag.value.trim()
|
||||
if (t && !form.value.tags.includes(t) && form.value.tags.length < 10) {
|
||||
form.value.tags.push(t)
|
||||
customTag.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
const submit = async () => {
|
||||
if (!form.value.company.trim()) { uni.showToast({ title: '请填写公司名称', icon: 'none' }); return }
|
||||
if (!form.value.position.trim()) { uni.showToast({ title: '请填写面试岗位', icon: 'none' }); return }
|
||||
|
||||
submitting.value = true
|
||||
try {
|
||||
const questions = questionsText.value
|
||||
.split('\n')
|
||||
.map(q => q.replace(/^\d+[\.\、\s]+/, '').trim())
|
||||
.filter(q => q.length > 0)
|
||||
|
||||
const res = await uni.request({
|
||||
url: api('/contribution'), method: 'POST',
|
||||
header: { 'Authorization': `Bearer ${token()}`, 'Content-Type': 'application/json' },
|
||||
data: {
|
||||
interviewId: props.interviewId || '',
|
||||
company: form.value.company.trim(),
|
||||
position: form.value.position.trim(),
|
||||
rounds: form.value.rounds.trim(),
|
||||
questions,
|
||||
experience: form.value.experience.trim(),
|
||||
tags: form.value.tags,
|
||||
},
|
||||
})
|
||||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||
submitted.value = true
|
||||
uni.showToast({ title: '提交成功!', icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({ title: '提交失败,请重试', icon: 'none' })
|
||||
}
|
||||
} catch (e) {
|
||||
uni.showToast({ title: '网络错误', icon: 'none' })
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const goBack = () => uni.navigateBack()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page { min-height: 100vh; background: var(--color-bg); }
|
||||
.hero { background: linear-gradient(135deg, #10B981, #34D399, #6EE7B7); padding: 48rpx 32rpx 72rpx; border-radius: 0 0 48rpx 48rpx; }
|
||||
.hero-title { font-size: 40rpx; font-weight: 700; color: #FFF; display: block; }
|
||||
.hero-sub { font-size: 22rpx; color: rgba(255,255,255,0.8); margin-top: 8rpx; display: block; }
|
||||
|
||||
.form { margin: -40rpx 32rpx 0; border-radius: var(--radius-xl); padding: 32rpx; }
|
||||
.form-group { margin-bottom: 28rpx; }
|
||||
.form-label { font-size: 26rpx; font-weight: 600; color: var(--color-text); display: block; margin-bottom: 10rpx; }
|
||||
.required { color: #EF4444; }
|
||||
.form-input {
|
||||
width: 100%; height: 72rpx; background: #F9FAFB; border-radius: var(--radius-md);
|
||||
padding: 0 20rpx; font-size: 26rpx; box-sizing: border-box; border: 1rpx solid var(--color-border);
|
||||
}
|
||||
.form-textarea {
|
||||
width: 100%; min-height: 180rpx; background: #F9FAFB; border-radius: var(--radius-md);
|
||||
padding: 16rpx 20rpx; font-size: 26rpx; box-sizing: border-box; border: 1rpx solid var(--color-border);
|
||||
}
|
||||
.form-hint { font-size: 20rpx; color: var(--color-text-tertiary); text-align: right; display: block; margin-top: 6rpx; }
|
||||
|
||||
.tag-input-area { display: flex; flex-direction: column; gap: 12rpx; }
|
||||
.tag-list { display: flex; flex-wrap: wrap; gap: 10rpx; }
|
||||
.tag-item {
|
||||
padding: 6rpx 18rpx; border-radius: var(--radius-round); font-size: 22rpx;
|
||||
background: #F3F4F6; color: var(--color-text-secondary); border: 1rpx solid #E5E7EB;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.tag-item.selected { background: linear-gradient(135deg, #D1FAE5, #A7F3D0); color: #065F46; border-color: #10B981; }
|
||||
|
||||
.btn-submit {
|
||||
width: 100%; height: 88rpx; border-radius: var(--radius-lg);
|
||||
background: linear-gradient(135deg, #10B981, #34D399); color: #FFF;
|
||||
font-size: 30rpx; font-weight: 700; border: none; margin-top: 8rpx;
|
||||
}
|
||||
.btn-submit[disabled] { opacity: 0.6; }
|
||||
|
||||
.success-box { display: flex; flex-direction: column; align-items: center; padding: 40rpx 0; gap: 12rpx; background: #ECFDF5; border-radius: var(--radius-lg); margin-top: 24rpx; }
|
||||
.success-icon { font-size: 56rpx; }
|
||||
.success-text { font-size: 26rpx; color: #065F46; font-weight: 600; text-align: center; line-height: 1.5; }
|
||||
.success-action { font-size: 28rpx; color: var(--color-primary); font-weight: 600; padding: 10rpx 40rpx; }
|
||||
.bottom-spacer { height: 40rpx; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user