feat: unify contact button styles, dynamic version from git tag, enrich AI positions & homepage UX
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<view class="page">
|
||||
<view class="logo-area">
|
||||
<text class="logo">职引</text>
|
||||
<text class="version">v1.0.0</text>
|
||||
<text class="version">v{{ appVersion }}</text>
|
||||
</view>
|
||||
<view class="info-section">
|
||||
<text class="info-label">产品名称</text>
|
||||
@@ -18,12 +18,15 @@
|
||||
</view>
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="contact-btn" open-type="contact">
|
||||
<view class="contact-btn-inner">
|
||||
<text class="contact-icon">💬</text>
|
||||
<text class="contact-text">联系在线客服</text>
|
||||
</view>
|
||||
<view class="link-section contact-link-section">
|
||||
<view class="link-item">
|
||||
<button class="contact-btn-inline" open-type="contact">
|
||||
<text class="contact-btn-icon">💬</text>
|
||||
<text class="link-text">联系客服</text>
|
||||
<text class="link-arrow">›</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<view class="link-section">
|
||||
@@ -47,6 +50,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const appVersion = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '1.0.0'
|
||||
const goAgreement = () => uni.navigateTo({ url: '/pages/agreement/agreement' })
|
||||
const goPrivacy = () => uni.navigateTo({ url: '/pages/privacy/privacy' })
|
||||
</script>
|
||||
@@ -69,9 +73,8 @@ const goPrivacy = () => uni.navigateTo({ url: '/pages/privacy/privacy' })
|
||||
.disclaimer-title { font-size: 24rpx; font-weight: 700; color: #F59E0B; display: block; margin-bottom: 12rpx; }
|
||||
.disclaimer-text { font-size: 22rpx; color: var(--color-text-secondary); line-height: 1.8; }
|
||||
|
||||
.contact-btn { width: 100%; background: #FFF; border: none; border-radius: var(--radius-md); padding: 0; margin-bottom: 12rpx; }
|
||||
.contact-btn-inner { display: flex; align-items: center; gap: 16rpx; padding: 24rpx 30rpx; }
|
||||
.contact-btn:active { opacity: 0.7; }
|
||||
.contact-icon { font-size: 28rpx; }
|
||||
.contact-text { font-size: 26rpx; color: var(--color-text); }
|
||||
.contact-link-section { margin-top: 12rpx; }
|
||||
.contact-btn-inline { width: 100%; background: transparent; border: none; border-radius: 0; padding: 0; margin: 0; line-height: inherit; font-size: inherit; text-align: left; display: flex; align-items: center; min-height: auto; }
|
||||
.contact-btn-inline::after { border: none; }
|
||||
.contact-btn-icon { font-size: 28rpx; margin-right: 16rpx; }
|
||||
</style>
|
||||
|
||||
@@ -122,15 +122,22 @@
|
||||
<text class="section-desc">AI 时代最热方向,点击直接面试</text>
|
||||
</view>
|
||||
<view class="ai-banner card" @click="goInterview">
|
||||
<text class="ai-banner-title">🚀 AI 正在重塑整个行业</text>
|
||||
<view class="ai-banner-icon-wrap">
|
||||
<text class="ai-banner-icon">🤖</text>
|
||||
</view>
|
||||
<view class="ai-banner-body">
|
||||
<text class="ai-banner-title">AI 正在重塑整个行业</text>
|
||||
<text class="ai-banner-desc">大模型应用 / Agent 开发 / Prompt 工程 — 顶尖人才缺口巨大,现在上车正当时</text>
|
||||
</view>
|
||||
<view class="position-list card" v-if="!positionsLoading && aiPositions.length > 0">
|
||||
<view class="pos-item" v-for="(pos, idx) in aiPositions" :key="'ai-' + idx" @click="startInterview(pos)">
|
||||
<text class="ai-banner-arrow">→</text>
|
||||
</view>
|
||||
<view class="position-list card" v-if="!positionsLoading && displayAiPositions.length > 0">
|
||||
<view class="pos-item" v-for="(pos, idx) in displayAiPositions" :key="'ai-' + idx" @click="startInterview(pos)">
|
||||
<view class="pos-left">
|
||||
<text class="pos-icon pos-icon-ai">{{ pos.icon || posIcons[idx % posIcons.length] || '🤖' }}</text>
|
||||
<text class="pos-icon pos-icon-ai">{{ pos.icon || aiPosIcons[idx % aiPosIcons.length] || '🤖' }}</text>
|
||||
<view class="pos-body">
|
||||
<text class="pos-name">{{ pos.name }}</text>
|
||||
<text class="pos-name-tag">AI 方向</text>
|
||||
<view class="pos-meta-row" v-if="pos.company || pos.salary">
|
||||
<text class="pos-company">{{ pos.company }}</text>
|
||||
<text class="pos-salary">{{ pos.salary }}</text>
|
||||
@@ -138,7 +145,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="pos-action">
|
||||
<text class="pos-action-text pos-action-ai">立即模拟</text>
|
||||
<text class="pos-action-btn pos-action-ai">开始面试</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -154,9 +161,10 @@
|
||||
<view class="position-list card" v-if="showMore && !positionsLoading && traditionalPositions.length > 0">
|
||||
<view class="pos-item" v-for="(pos, idx) in traditionalPositions" :key="'tr-' + idx" @click="startInterview(pos)">
|
||||
<view class="pos-left">
|
||||
<text class="pos-icon">{{ pos.icon || posIcons[(aiPositions.length + idx) % posIcons.length] || '💼' }}</text>
|
||||
<text class="pos-icon">{{ pos.icon || posIcons[(displayAiPositions.length + idx) % posIcons.length] || '💼' }}</text>
|
||||
<view class="pos-body">
|
||||
<text class="pos-name">{{ pos.name }}</text>
|
||||
<text class="pos-name-tag pos-name-tag-tr">{{ pos.category === 'intern' ? '实习' : '校招' }}</text>
|
||||
<view class="pos-meta-row" v-if="pos.company || pos.salary">
|
||||
<text class="pos-company">{{ pos.company }}</text>
|
||||
<text class="pos-salary">{{ pos.salary }}</text>
|
||||
@@ -164,7 +172,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="pos-action">
|
||||
<text class="pos-action-text">立即模拟</text>
|
||||
<text class="pos-action-btn">立即模拟</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -184,12 +192,27 @@ const userInfo = ref(null)
|
||||
const greeting = ref('')
|
||||
const hotPositions = ref([])
|
||||
const posIcons = ['💻', '⚙️', '🤖', '📊', '🎨', '🧪', '📱', '🔧']
|
||||
const aiPosIcons = ['🤖', '🧠', '⚡', '🚀', '💡', '🔬']
|
||||
const positionsLoading = ref(true)
|
||||
const dailyQuestion = ref(null)
|
||||
const showAnswer = ref(false)
|
||||
const showMore = ref(false)
|
||||
const showMore = ref(true)
|
||||
|
||||
// 前端兜底 AI 岗位(当 API 返回不足时展示)
|
||||
const FALLBACK_AI_POSITIONS = [
|
||||
{ name: 'AI Agent 开发工程师', category: 'ai', company: '热门方向', salary: '30K-60K', icon: '🧠' },
|
||||
{ name: '大模型应用开发', category: 'ai', company: '热门方向', salary: '25K-50K', icon: '⚡' },
|
||||
]
|
||||
|
||||
const aiPositions = computed(() => hotPositions.value.filter(p => p.category === 'ai'))
|
||||
const displayAiPositions = computed(() => {
|
||||
const fromApi = aiPositions.value
|
||||
if (fromApi.length >= 4) return fromApi
|
||||
// 补充到至少 4 个,去重
|
||||
const existingNames = new Set(fromApi.map(p => p.name))
|
||||
const needed = FALLBACK_AI_POSITIONS.filter(p => !existingNames.has(p.name))
|
||||
return [...fromApi, ...needed]
|
||||
})
|
||||
const traditionalPositions = computed(() => hotPositions.value.filter(p => p.category !== 'ai'))
|
||||
|
||||
const loadUserInfo = () => {
|
||||
@@ -355,40 +378,60 @@ const startInterview = (pos) => uni.navigateTo({ url: `/pages/interview/intervie
|
||||
|
||||
/* AI 岗位专区 */
|
||||
.ai-banner {
|
||||
background: linear-gradient(135deg, #FEF3C7, #FDE68A);
|
||||
background: linear-gradient(135deg, #FEF3C7 0%, #FDE68A 50%, #FCD34D 100%);
|
||||
padding: 20rpx 24rpx; border-radius: var(--radius-lg); margin-bottom: 16rpx;
|
||||
cursor: pointer;
|
||||
display: flex; align-items: center; gap: 16rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(251,191,36,0.2);
|
||||
cursor: pointer; transition: transform 0.15s;
|
||||
}
|
||||
.ai-banner:active { transform: scale(0.98); }
|
||||
.ai-banner-title { font-size: 26rpx; font-weight: 700; color: #92400E; display: block; margin-bottom: 6rpx; }
|
||||
.ai-banner:active { transform: scale(0.97); }
|
||||
.ai-banner-icon-wrap {
|
||||
width: 64rpx; height: 64rpx; border-radius: 18rpx;
|
||||
background: rgba(255,255,255,0.6); display: flex; align-items: center; justify-content: center; flex-shrink: 0;
|
||||
}
|
||||
.ai-banner-icon { font-size: 36rpx; }
|
||||
.ai-banner-body { flex: 1; min-width: 0; }
|
||||
.ai-banner-title { font-size: 26rpx; font-weight: 700; color: #92400E; display: block; margin-bottom: 4rpx; }
|
||||
.ai-banner-desc { font-size: 20rpx; color: #A16207; line-height: 1.5; display: block; }
|
||||
.ai-banner-arrow { font-size: 28rpx; color: #B45309; font-weight: 600; flex-shrink: 0; }
|
||||
|
||||
.position-list { border-radius: var(--radius-lg); overflow: hidden; }
|
||||
.pos-item { padding: 24rpx 28rpx; border-bottom: 1rpx solid var(--color-border); display: flex; justify-content: space-between; align-items: center; }
|
||||
.pos-item { padding: 26rpx 28rpx; border-bottom: 1rpx solid var(--color-border); display: flex; justify-content: space-between; align-items: center; }
|
||||
.pos-item:last-child { border-bottom: none; }
|
||||
.pos-item:active { background: var(--color-bg); }
|
||||
.pos-item:active { background: #F9FAFB; }
|
||||
.pos-left { display: flex; align-items: center; gap: 16rpx; flex: 1; min-width: 0; }
|
||||
.pos-icon { font-size: 36rpx; width: 56rpx; height: 56rpx; display: flex; align-items: center; justify-content: center; background: #F3F4F6; border-radius: 14rpx; flex-shrink: 0; }
|
||||
.pos-icon-ai { background: #FEF3C7; }
|
||||
.pos-icon { font-size: 32rpx; width: 60rpx; height: 60rpx; display: flex; align-items: center; justify-content: center; background: #F3F4F6; border-radius: 16rpx; flex-shrink: 0; }
|
||||
.pos-icon-ai { background: linear-gradient(135deg, #FEF3C7, #FDE68A); }
|
||||
.pos-body { display: flex; flex-direction: column; flex: 1; min-width: 0; }
|
||||
.pos-name { font-size: 28rpx; font-weight: 600; color: var(--color-text); }
|
||||
.pos-name-tag {
|
||||
font-size: 18rpx; color: #D97706; background: #FFFBEB; padding: 1rpx 10rpx;
|
||||
border-radius: 6rpx; align-self: flex-start; margin-top: 6rpx;
|
||||
}
|
||||
.pos-name-tag-tr { color: var(--color-primary); background: #EEF2FF; }
|
||||
.pos-meta-row { display: flex; align-items: center; gap: 10rpx; margin-top: 4rpx; }
|
||||
.pos-company { font-size: 20rpx; color: var(--color-text-tertiary); }
|
||||
.pos-salary { font-size: 20rpx; color: var(--color-primary); background: #EEF2FF; padding: 2rpx 10rpx; border-radius: 6rpx; }
|
||||
.pos-action { flex-shrink: 0; margin-left: 16rpx; }
|
||||
.pos-action-text { font-size: 22rpx; color: var(--color-primary); font-weight: 600; }
|
||||
.pos-action-ai { color: #D97706; }
|
||||
.pos-action-btn {
|
||||
font-size: 22rpx; font-weight: 600; color: var(--color-primary);
|
||||
padding: 10rpx 24rpx; border-radius: var(--radius-round);
|
||||
background: #EEF2FF; display: inline-block;
|
||||
}
|
||||
.pos-action-btn:active { background: #DBEAFE; }
|
||||
.pos-action-ai { color: #D97706; background: #FFFBEB; }
|
||||
|
||||
/* 更多岗位折叠 */
|
||||
/* 更多岗位 */
|
||||
.more-header {
|
||||
display: flex; justify-content: space-between; align-items: center;
|
||||
padding: 20rpx 4rpx; margin-top: 8rpx; cursor: pointer;
|
||||
padding: 24rpx 20rpx 16rpx; margin-top: 8rpx; cursor: pointer;
|
||||
background: #FFFFFF; border-radius: var(--radius-lg) var(--radius-lg) 0 0;
|
||||
}
|
||||
.more-header:active { opacity: 0.7; }
|
||||
.more-header-left { display: flex; align-items: center; gap: 10rpx; }
|
||||
.more-icon { font-size: 28rpx; }
|
||||
.more-title { font-size: 26rpx; font-weight: 600; color: var(--color-text-secondary); }
|
||||
.more-arrow { font-size: 22rpx; color: var(--color-primary); font-weight: 500; }
|
||||
.more-title { font-size: 26rpx; font-weight: 600; color: var(--color-text); }
|
||||
.more-arrow { font-size: 22rpx; color: var(--color-primary); font-weight: 500; background: #EEF2FF; padding: 4rpx 16rpx; border-radius: var(--radius-round); }
|
||||
|
||||
.loading-tip { text-align: center; padding: 40rpx; font-size: 24rpx; color: var(--color-text-tertiary); background: #FFF; border-radius: var(--radius-lg); }
|
||||
.bottom-spacer { height: 40rpx; }
|
||||
|
||||
@@ -98,11 +98,13 @@
|
||||
</view>
|
||||
<view class="menu-group">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<button class="menu-item contact-btn" open-type="contact">
|
||||
<view class="menu-item">
|
||||
<button class="contact-btn-inner" open-type="contact">
|
||||
<view class="menu-icon-wrap wrap-gray"><text class="menu-icon">💬</text></view>
|
||||
<text class="menu-text">联系客服</text>
|
||||
<text class="menu-arrow">›</text>
|
||||
</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="menu-item" @click="goAbout">
|
||||
<view class="menu-icon-wrap wrap-gray"><text class="menu-icon">ℹ️</text></view>
|
||||
@@ -329,9 +331,8 @@ const doLogout = () => {
|
||||
.menu-area { padding: 0 32rpx 32rpx; margin-top: 8rpx; }
|
||||
.menu-group { background: #FFFFFF; border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 24rpx; box-shadow: var(--shadow-sm); }
|
||||
.menu-item { display: flex; align-items: center; padding: 28rpx 32rpx; border-bottom: 1rpx solid var(--color-border); }
|
||||
.contact-btn { width: 100%; background: transparent; border: none; border-radius: 0; padding: 0; margin: 0; line-height: inherit; font-size: inherit; text-align: left; }
|
||||
.contact-btn::after { border: none; }
|
||||
.contact-btn:active { background: #F9FAFB; }
|
||||
.contact-btn-inner { width: 100%; background: transparent; border: none; border-radius: 0; padding: 0; margin: 0; line-height: inherit; font-size: inherit; text-align: left; display: flex; align-items: center; min-height: auto; }
|
||||
.contact-btn-inner::after { border: none; }
|
||||
.menu-item:last-child { border-bottom: none; }
|
||||
.menu-item:active { background: #F9FAFB; }
|
||||
.menu-icon-wrap { width: 60rpx; height: 60rpx; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; margin-right: 20rpx; flex-shrink: 0; }
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import { execSync } from 'child_process';
|
||||
import uni from '@dcloudio/vite-plugin-uni';
|
||||
|
||||
let appVersion = '1.0.0';
|
||||
try {
|
||||
appVersion = execSync('git describe --tags --abbrev=0 2>/dev/null || echo "1.0.0"', { encoding: 'utf8' }).trim().replace(/^v/, '');
|
||||
} catch {}
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [uni()],
|
||||
define: {
|
||||
__APP_VERSION__: JSON.stringify(appVersion),
|
||||
},
|
||||
server: {
|
||||
port: 8888,
|
||||
strictPort: true,
|
||||
|
||||
Reference in New Issue
Block a user