diff --git a/zhiyin-app/src/pages/about/about.vue b/zhiyin-app/src/pages/about/about.vue index b6fae16..2ee111a 100644 --- a/zhiyin-app/src/pages/about/about.vue +++ b/zhiyin-app/src/pages/about/about.vue @@ -2,7 +2,7 @@ - v1.0.0 + v{{ appVersion }} 产品名称 @@ -18,12 +18,15 @@ - - + @@ -47,6 +50,7 @@ @@ -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; } diff --git a/zhiyin-app/src/pages/index/index.vue b/zhiyin-app/src/pages/index/index.vue index 20d5111..99a6d61 100644 --- a/zhiyin-app/src/pages/index/index.vue +++ b/zhiyin-app/src/pages/index/index.vue @@ -122,15 +122,22 @@ AI 时代最热方向,点击直接面试 - 🚀 AI 正在重塑整个行业 - 大模型应用 / Agent 开发 / Prompt 工程 — 顶尖人才缺口巨大,现在上车正当时 + + 🤖 + + + AI 正在重塑整个行业 + 大模型应用 / Agent 开发 / Prompt 工程 — 顶尖人才缺口巨大,现在上车正当时 + + - - + + - {{ pos.icon || posIcons[idx % posIcons.length] || '🤖' }} + {{ pos.icon || aiPosIcons[idx % aiPosIcons.length] || '🤖' }} {{ pos.name }} + AI 方向 {{ pos.company }} {{ pos.salary }} @@ -138,7 +145,7 @@ - 立即模拟 + 开始面试 @@ -154,9 +161,10 @@ - {{ pos.icon || posIcons[(aiPositions.length + idx) % posIcons.length] || '💼' }} + {{ pos.icon || posIcons[(displayAiPositions.length + idx) % posIcons.length] || '💼' }} {{ pos.name }} + {{ pos.category === 'intern' ? '实习' : '校招' }} {{ pos.company }} {{ pos.salary }} @@ -164,7 +172,7 @@ - 立即模拟 + 立即模拟 @@ -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; } diff --git a/zhiyin-app/src/pages/user/user.vue b/zhiyin-app/src/pages/user/user.vue index 3384795..e1f7f92 100644 --- a/zhiyin-app/src/pages/user/user.vue +++ b/zhiyin-app/src/pages/user/user.vue @@ -98,11 +98,13 @@ - + + + ℹ️ @@ -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; } diff --git a/zhiyin-app/vite.config.js b/zhiyin-app/vite.config.js index c0ed2a7..74f323d 100644 --- a/zhiyin-app/vite.config.js +++ b/zhiyin-app/vite.config.js @@ -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,