| | |
| | | <template> |
| | | <view class="page"> |
| | | <scroll-view class="scroll-page" scroll-y @scroll="handleScroll"> |
| | | <view class="hero"> |
| | | <view class="hero-gradient"></view> |
| | | <view v-if="homeVideoUrl != ''" class="play-button" @tap="playVideo"><text>向东看</text></view> |
| | | </view> |
| | | |
| | | <view class="city-panel"> |
| | | <view class="city-heading"><text>才聚东区,共富未来</text><view class="city-label" @tap="openIntro"><text>幸福东区</text><image src="/static/home-assets/arrow-right.svg"></image></view></view> |
| | | <view class="city-grid"> |
| | | <view class="city-card city-intro" @tap="openIntro"><text class="intro-name">东区简介</text><view class="intro-button"><text>查看更多</text><image src="/static/home-assets/arrow-right.svg"></image></view></view> |
| | | <view class="city-side"><view class="city-card city-potential"><text>潜力城</text></view><view class="city-card city-golden"><text>黄金城</text></view></view> |
| | | <view class="city-side"><view class="city-card city-industry"><text>兴业城</text></view><view class="city-card city-livable"><text>宜居城</text></view></view> |
| | | <scroll-view :show-scrollbar="false" class="scroll-page" scroll-y @scroll="handleScroll"> |
| | | <view class="home-overview"> |
| | | <view class="hero"> |
| | | <view class="hero-surface"> |
| | | <image class="hero-image" src="/static/home-assets/home-top.png" mode="aspectFit"></image> |
| | | <view class="hero-gradient"></view> |
| | | <view class="play-button" @tap="playVideo"><text>向东看</text></view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="city-panel"> |
| | | <view class="city-panel-content"> |
| | | <view class="city-heading"><text>才聚东区,共富未来</text><view class="city-label" @tap="openHappyDongqu"><text>幸福东区</text><image src="/static/home-assets/arrow-right.svg"></image></view></view> |
| | | <view class="city-grid"> |
| | | <view class="city-card city-intro" @tap="openIntro"><image class="city-bg" :src="homeImage('city-intro.jpg')" mode="aspectFill"></image><text class="intro-name">东区简介</text><view class="intro-button"><text>查看更多</text><image src="/static/home-assets/arrow-right.svg"></image></view></view> |
| | | <view class="city-side"><view class="city-card city-potential"><image class="city-bg" :src="homeImage('city-potential.jpg')" mode="aspectFill"></image><view class="city-card-caption"></view><text>潜力城</text></view><view class="city-card city-golden"><image class="city-bg" :src="homeImage('city-golden.jpg')" mode="aspectFill"></image><view class="city-card-caption"></view><text>黄金城</text></view></view> |
| | | <view class="city-side"><view class="city-card city-industry"><image class="city-bg" :src="homeImage('city-industry.jpg')" mode="aspectFill"></image><view class="city-card-caption"></view><text>兴业城</text></view><view class="city-card city-livable"><image class="city-bg" :src="homeImage('city-livable.png')" mode="aspectFill"></image><view class="city-card-caption"></view><text>宜居城</text></view></view> |
| | | </view> |
| | | </view> |
| | | <image class="city-mascot" src="/static/home-assets/mascot-rest.png" mode="aspectFit"></image> |
| | | </view> |
| | | <image class="city-stand" src="/static/home-assets/mascot-stand.png" mode="aspectFit"></image> |
| | | </view> |
| | | |
| | | <view class="section-head"><view class="section-title"><text>人才资讯</text></view><text class="more" @tap="goNews">查看更多</text></view> |
| | | <view class="section-head"><view class="section-title"><image class="section-icon" src="/static/home-assets/mascot-leap.png" mode="aspectFit"></image><text>人才资讯</text></view><text class="more" @tap="goNews">查看更多</text></view> |
| | | <view v-if="homeLoading" class="news-state"><text>资讯加载中...</text></view> |
| | | <view v-else-if="homeError" class="news-state" @tap="loadHome"><text>{{homeError}}</text><text class="news-retry">点击重试</text></view> |
| | | <view v-else> |
| | |
| | | import { isApiConfigured } from '../../config/api.uts' |
| | | import { getAppHome } from '../../services/portal.uts' |
| | | import { resolveApiUrl } from '../../services/http.uts' |
| | | |
| | | /** |
| | | * 首页图片放在服务器上(`/uploads/home/…`),代码里只存相对路径: |
| | | * 换图不用改代码、也不用重新上传体验版,和后台域名一起走环境配置。 |
| | | */ |
| | | const homeImage = (name: string): string => resolveApiUrl('/uploads/home/' + name) |
| | | |
| | | const navTop = ref(28) |
| | | const navHeight = ref(32) |
| | |
| | | } |
| | | uni.navigateTo({ url: '/pages/home-video/home-video?url=' + encodeURIComponent(resolveApiUrl(homeVideoUrl.value)) }) |
| | | } |
| | | const openIntro = () => { |
| | | const openIntro = () => uni.navigateTo({ url: '/city-intro/pages/intro/intro' }) |
| | | const openHappyDongqu = () => { |
| | | if (miniProgramAppId.value != '') { |
| | | uni.navigateToMiniProgram({ |
| | | appId: miniProgramAppId.value, |
| | |
| | | <style> |
| | | .page { height: 100%; background-color: #FFFFFF; } |
| | | .scroll-page { height: calc(100% - 126rpx); height: calc(100% - 126rpx - env(safe-area-inset-bottom)); background-color: #FFFFFF; } |
| | | .hero { height: 468rpx; background-color: #FFFFFF; position: relative; overflow: hidden; } |
| | | .hero-gradient { position: absolute; z-index: 1; top: 0; left: 0; right: 0; bottom: 0; border-bottom-left-radius: 48rpx; border-bottom-right-radius: 48rpx; background-image: linear-gradient(145deg, #F45A2A 0%, #FF9E4B 55%, #FFE0AC 100%); } |
| | | .home-overview { position: relative; overflow: visible; flex-shrink: 0; } |
| | | .hero { height: 462rpx; min-height: 462rpx; flex-shrink: 0; position: relative; z-index: 1; overflow: visible; } |
| | | .hero-surface { position: relative; width: 100%; height: 462rpx; flex-shrink: 0; overflow: hidden; border-bottom-left-radius: 72rpx; border-bottom-right-radius: 72rpx; } |
| | | .hero-image { position: absolute; left: 0; top: 0; width: 100%; height: 462rpx; } |
| | | .hero-gradient { position: absolute; z-index: 1; top: 0; left: 0; right: 0; height: 300rpx; background-image: linear-gradient(180deg, rgba(244,90,42,.88) 0%, rgba(255,130,60,.42) 62%, rgba(255,166,80,0) 100%); } |
| | | .safe-space { height: 28px; position: relative; z-index: 2; } |
| | | .nav-row { height: 32px; padding: 0 32rpx; position: relative; z-index: 2; flex-direction: row; align-items: center; justify-content: space-between; } |
| | | .sticky-nav { position: absolute; z-index: 30; top: 0; left: 0; right: 0; padding-bottom: 20rpx; } |
| | | .sticky-nav-bg { position: absolute; z-index: 0; top: 0; left: 0; right: 0; bottom: 0; opacity: 0; background-image: linear-gradient(180deg, #F26A38 0%, #EE542B 100%); transition: opacity 280ms ease-out; } |
| | | .sticky-nav.is-solid .sticky-nav-bg { opacity: 1; } |
| | | .nav-title { position: absolute; z-index: 1; left: 30rpx; top: 10rpx; height: 100%; flex-direction: row; align-items: center; justify-content: flex-start; } |
| | | .nav-title text { color: #FFFFFF; font-size: 28rpx; font-weight: 700; opacity: .95; } |
| | | .nav-title text { color: #FFFFFF; font-family: 'FoodCalligraphyFull', 'FoodCalligraphy'; font-size: 38rpx; font-weight: 700; opacity: .95; } |
| | | .capsule-reserve { width: 88px; height: 100%; flex-shrink: 0; } |
| | | .play-button { position: absolute; z-index: 2; bottom: 20rpx; left: 50%; margin-left: -78rpx; width: 156rpx; height: 56rpx; border-radius: 28rpx; background-image: linear-gradient(180deg, #FFB75A 0%, #FF6A24 100%); border-width: 2rpx; border-color: rgba(255,255,255,.82); box-shadow: 0 7rpx 14rpx rgba(234,92,26,.26); flex-direction: row; justify-content: center; align-items: center; } |
| | | .play-button { position: absolute; z-index: 2; bottom: 52rpx; left: 50%; margin-left: -78rpx; width: 156rpx; height: 56rpx; border-radius: 28rpx; background-image: linear-gradient(180deg, #FFB75A 0%, #FF6A24 100%); border-width: 2rpx; border-color: rgba(255,255,255,.82); box-shadow: 0 7rpx 14rpx rgba(234,92,26,.26); flex-direction: row; justify-content: center; align-items: center; } |
| | | .play-button text { color: #FFFFFF; font-size: 23rpx; } |
| | | |
| | | .city-panel { margin: -10rpx 16rpx 38rpx; padding: 22rpx 0 0; overflow: visible; background-color: #FFFFFF; border-radius: 26rpx; position: relative; box-shadow: 0 -8rpx 14rpx rgba(255, 103, 39, .27); } |
| | | .city-heading { height: 58rpx; margin: 0 22rpx; flex-direction: row; justify-content: space-between; align-items: center; } |
| | | /* |
| | | * 顶图按素材原比例显示透明圆角,城市模块置于前面并上移重叠。 |
| | | * 外层渐变与内层白色卡片相差 2rpx,形成沿圆角延伸的橙色渐变边框。 |
| | | */ |
| | | .city-panel { margin: -32rpx 16rpx 60rpx; padding: 2rpx; border-radius: 40rpx; overflow: visible; position: relative; z-index: 2; background-image: linear-gradient(150deg, #FFDDC9 0%, #FF9C5A 52%, #FFD5B7 100%); } |
| | | .city-panel-content { padding-top: 22rpx; border-radius: 38rpx; overflow: visible; position: relative; background-color: #FFFFFF; } |
| | | .city-heading { height: 58rpx; margin: 0 22rpx; position: relative; flex-direction: row; justify-content: space-between; align-items: center; } |
| | | /* Keep the mascot above both cards; the image canvas includes transparent padding. */ |
| | | .city-stand { position: absolute; right: 18rpx; top: 341rpx; width: 58rpx; height: 168rpx; z-index: 3; } |
| | | /* 吉祥物随标题恢复位置,草坪底边保持在橙色城市区上沿。 */ |
| | | .city-mascot { position: absolute; right: 162rpx; top: 42rpx; width: 128rpx; height: 75rpx; z-index: 3; } |
| | | .city-heading > text { color: #F16624; font-size: 35rpx; font-weight: 700; letter-spacing: 1rpx; background-image: linear-gradient(180deg, #F45A2A 0%, #FFB257 100%); background-clip: text; -webkit-background-clip: text; -webkit-text-fill-color: transparent; } |
| | | .city-label { margin-right: 48rpx; padding: 10rpx 13rpx; border-radius: 18rpx; background-image: linear-gradient(180deg, #FFB85E 0%, #FF6726 100%); box-shadow: 0 5rpx 10rpx rgba(239,101,34,.22); flex-direction: row; align-items: center; } .city-label text { color: #FFFFFF; font-size: 20rpx; } .city-label image { width: 20rpx; height: 20rpx; margin-left: 7rpx; } |
| | | .city-grid { box-sizing: border-box; height: 292rpx; margin-top: 18rpx; padding: 22rpx; overflow: visible; background-image: linear-gradient(180deg, #FF5F2D 0%, #FFB36B 100%); border-bottom-left-radius: 26rpx; border-bottom-right-radius: 26rpx; flex-direction: row; } .city-card { overflow: hidden; border-radius: 17rpx; position: relative; justify-content: flex-end; background-image: linear-gradient(135deg, #E96C3D 0%, #F8AA56 100%); } |
| | | /* |
| | | * 「幸福东区」按钮:原型里按钮右边缘距面板右边缘 18px(面板 287px)→ 45rpx; |
| | | * 面板内缩 16rpx、边框 2rpx、标题边距 22rpx,再留 7rpx 对齐右侧按钮。 |
| | | */ |
| | | .city-label { margin-right: 7rpx; padding: 10rpx 13rpx; border-radius: 18rpx; background-image: linear-gradient(180deg, #FFB85E 0%, #FF6726 100%); box-shadow: 0 5rpx 10rpx rgba(239,101,34,.22); flex-direction: row; align-items: center; } .city-label text { color: #FFFFFF; font-size: 20rpx; } .city-label image { width: 20rpx; height: 20rpx; margin-left: 7rpx; } |
| | | /* Cards extend 22rpx below the background; the panel margin reserves that space. */ |
| | | .city-grid { box-sizing: border-box; height: 308rpx; min-height: 308rpx; margin: 18rpx 0 0; padding: 22rpx; overflow: visible; border-bottom-left-radius: 38rpx; border-bottom-right-radius: 38rpx; background-image: linear-gradient(180deg, #FF5F2D 0%, #FFB36B 100%); flex-direction: row; } .city-card { overflow: hidden; border-radius: 17rpx; position: relative; justify-content: flex-end; background-image: linear-gradient(135deg, #E96C3D 0%, #F8AA56 100%); } |
| | | .city-bg { position: absolute; left: 0; top: 0; width: 100%; height: 100%; } |
| | | .city-intro { width: 242rpx; height: 308rpx; box-sizing: border-box; margin-right: 14rpx; padding: 22rpx; } .intro-name { position: absolute; z-index: 1; top: 50%; left: 0; right: 0; transform: translateY(-50%); color: #FFFFFF; font-size: 37rpx; font-weight: 700; text-align: center; } .intro-button { position: relative; z-index: 1; align-self: center; box-sizing: border-box; width: 146rpx; height: 42rpx; margin-top: 13rpx; padding: 0 12rpx; border-radius: 21rpx; background-image: linear-gradient(90deg, rgba(255,207,138,.92) 0%, rgba(255,101,36,.68) 100%); border-width: 1rpx; border-color: rgba(255,255,255,.42); flex-direction: row; align-items: center; justify-content: space-between; } .intro-button text { color: #FFFFFF; font-size: 19rpx; } .intro-button image { width: 19rpx; height: 19rpx; margin-left: 8rpx; } |
| | | .city-side { height: 308rpx; flex: 1; margin-right: 14rpx; justify-content: space-between; } .city-side:last-child { margin-right: 0; } .city-side .city-card { height: 147rpx; padding: 0; } .city-side .city-card > text { position: absolute; z-index: 1; left: 0; right: 0; bottom: 0; padding: 10rpx 12rpx; color: #FFFFFF; font-size: 22rpx; font-weight: 700; } |
| | | .city-side { height: 308rpx; flex: 1; margin-right: 14rpx; justify-content: space-between; } .city-side:last-child { margin-right: 0; } .city-side .city-card { height: 147rpx; padding: 0; } .city-card-caption { position: absolute; z-index: 1; left: 0; right: 0; bottom: 0; height: 46rpx; background-image: linear-gradient(90deg, rgba(239,91,117,.9) 0%, rgba(243,102,135,.55) 55%, rgba(243,102,135,0) 100%); } .city-side .city-card > text { position: absolute; z-index: 2; left: 0; right: 0; bottom: 0; padding: 10rpx 12rpx; color: #FFFFFF; font-size: 22rpx; font-weight: 700; text-shadow: 0 2rpx 8rpx rgba(0,0,0,.5); } |
| | | |
| | | .section-head { height: 93rpx; padding: 0 31rpx; flex-direction: row; align-items: center; justify-content: space-between; } .section-title { flex-direction: row; align-items: center; } .section-title text { color: #353535; font-size: 31rpx; font-weight: 700; } .more { color: #5C5C5C; font-size: 22rpx; } |
| | | .section-head { height: 93rpx; padding: 0 31rpx; flex-direction: row; align-items: center; justify-content: space-between; } .section-title { flex-direction: row; align-items: center; } .section-icon { width: 44rpx; height: 54rpx; margin-right: 10rpx; } .section-title text { color: #353535; font-size: 31rpx; font-weight: 700; } .more { color: #5C5C5C; font-size: 22rpx; } |
| | | .news-state { min-height: 150rpx; margin: 0 31rpx; justify-content: center; align-items: center; color: #8B8B8B; font-size: 24rpx; } .news-retry { margin-top: 12rpx; color: #F16624; } |
| | | .news-featured { height: 205rpx; margin: 0 19rpx; border-radius: 18rpx; overflow: hidden; position: relative; background-image: linear-gradient(135deg, #F26A38 0%, #F9A551 100%); } .news-featured > image { width: 100%; height: 100%; } .news-shade { position: absolute; left: 0; right: 0; bottom: 0; height: 118rpx; background-color: rgba(0,0,0,.44); } .top-badge { position: absolute; left: 20rpx; top: 18rpx; padding: 7rpx 14rpx; border-radius: 12rpx; background-color: #FFF3D4; } .top-badge text { color: #F2722E; font-size: 20rpx; font-weight: 700; } .featured-copy { position: absolute; left: 20rpx; right: 20rpx; bottom: 17rpx; } .featured-copy text:first-child { display: block; color: #FFFFFF; font-size: 24rpx; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .featured-copy text:last-child { display: block; margin-top: 8rpx; color: #FFFFFF; opacity: .85; font-size: 19rpx; } |
| | | .news-list { margin: 0 31rpx; } .news-row { min-height: 116rpx; padding: 22rpx 0 16rpx; border-bottom-width: 1rpx; border-bottom-color: #EEEEEE; } .news-name { color: #363636; font-size: 25rpx; line-height: 36rpx; } .news-meta { margin-top: 12rpx; flex-direction: row; align-items: center; color: #98A2B3; font-size: 19rpx; } .new-badge { margin-right: 14rpx; padding: 4rpx 10rpx; border-radius: 12rpx; background-color: #FFF0D9; color: #FE7930; font-size: 18rpx; } |