| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579 |
- <template>
- <view class="splash-container" v-if="checked && showSplash && userData.rankingItems.length > 0">
- <!-- 使用image组件作为背景图 -->
- <image class="splash-background-image" src="/static/images/splash/blackground.png" mode="aspectFill"></image>
- <view class="splash-content">
- <!-- 本月工分模块 -->
- <view class="module monthly-score">
- <text class="module-title">本月工分</text>
- <view class="score-container">
- <text class="score-icon">🏆</text>
- <text class="score-value">{{ formatNumber(userData.monthlyScore) }}</text>
- </view>
- </view>
- <!-- 个人排名模块 -->
- <view class="module personal-ranking">
- <text class="module-title">个人排名</text>
- </view>
- <!-- 排名模块 -->
- <view class="module station-ranking" v-for="(item, index) in userData.rankingItems" :key="index">
- <view class="ranking-item">
- <template v-if="getRankingIcon(index).type === 'emoji'">
- <text class="ranking-icon">{{ getRankingIcon(index).value }}</text>
- </template>
- <template v-else>
- <image class="ranking-icon" :src="getRankingIcon(index).value" mode="aspectFit"></image>
- </template>
- <text class="ranking-name">{{ item.name }}</text>
- <view class="ranking-circle-wrapper">
- <view class="ranking-number" :class="getRankingSizeClass(index)">
- <text class="ranking-number-text">{{ item.rank }}/{{ item.total }}</text>
- </view>
- </view>
- <text class="ranking-label">第{{ item.rank }}名</text>
- </view>
- </view>
- </view>
- <!-- 倒计时和关闭按钮 -->
- <view class="splash-footer">
- <view class="countdown" @tap="closeSplash">
- <text class="countdown-text">{{ countdown }}s 后跳过</text>
- </view>
- <view class="close-button" @tap="closeSplash">
- <text class="close-text">关闭</text>
- </view>
- </view>
- </view>
- </template>
- <script lang="uts">
- import { ref, onMounted, onUnmounted } from 'vue';
- import { getConfigKey } from '@/api/system/config';
- import { selectHomePageData } from '@/api/index/index';
- // 用户数据类型定义
- type RankingItem = {
- name: string;
- rank: number;
- total: number;
- }
- type UserData = {
- monthlyScore: number;
- rankingItems: RankingItem[]
- }
- type SplashConfig = {
- enable: boolean
- }
- type RankingIcon = {
- type: 'emoji' | 'image';
- value: string;
- }
- type ApiResponse<T> = {
- data: T;
- }
- export default {
- setup() {
- // 响应式数据
- const countdown = ref<number>(3);
- const showSplash = ref<boolean>(false); // 默认不显示
- const checked = ref<boolean>(false); // 是否已完成配置检查
- /* const userData = ref<UserData>({
- monthlyScore: 120,
- rankingItems: [
- { name: '东山电场', rank: 3, total: 15 },
- { name: '陆上设备维护中心', rank: 12, total: 86 },
- { name: '公司', rank: 45, total: 320 }
- ]
- }); */
- const userData = ref<UserData>({
- monthlyScore: 0,
- rankingItems: []
- });
- let countdownTimer: number | null = null;
- let hasRedirected = false; // 防止重复跳转
-
- // 关闭跳转页
- const closeSplash = (): void => {
- if (hasRedirected) return; // 防止重复跳转
-
- if (countdownTimer != null) {
- clearInterval(countdownTimer as number);
- countdownTimer = null;
- }
-
- hasRedirected = true;
- // 跳转到主页
- uni.redirectTo({
- url: '/pages/index/index'
- });
- };
- // 检查后端配置是否启用跳转页
- const checkSplashConfig = async (): Promise<void> => {
- try {
- // 调用后端API获取配置
- const response = await getConfigKey('gxt.app.splash');
-
- console.log("完整响应:", response);
-
- let showSplashValue = false;
- const respObj = response as UTSJSONObject;
- if (respObj.hasOwnProperty('msg')) {
- const msgValue = respObj['msg'] as string;
- showSplashValue = msgValue == '1';
- console.log("msgValue:", msgValue);
- }
-
- showSplash.value = showSplashValue;
- checked.value = true; // 标记已检查完配置
-
- console.log("showSplash.value:", showSplash.value);
-
- // 如果不启用跳转页,直接关闭
- if (!showSplashValue) {
- closeSplash();
- }
- } catch (error) {
- console.error('获取跳转页配置失败:', error);
- // 出错时默认不显示跳转页
- showSplash.value = false;
- checked.value = true;
- closeSplash();
- }
- };
- // 获取用户数据
- const fetchUserData = async (): Promise<void> => {
- try {
- // 调用后端API获取用户数据
- const response = await selectHomePageData();
- console.log("response====",response)
- // 根据响应结果更新userData
- if (response != null) {
- const respObj = response as UTSJSONObject;
- const data = respObj['data'] as UTSJSONObject;
-
- // 更新月度工分
- if (data.hasOwnProperty('score')) {
- const scoreVal = data['score'] as number;
- userData.value.monthlyScore = Math.round(scoreVal * 100) / 100;
- }
-
- // 初始化默认值
- let deptName = '未知部门';
- let center = '未知中心';
- let companyName = '未知公司';
-
- // 从scoreDept中提取部门、中心和公司名称
- if (data.hasOwnProperty('scoreDept') && Array.isArray(data['scoreDept']) && (data['scoreDept'] as any[]).length > 0) {
- const scoreDept = data['scoreDept'] as UTSJSONObject[];
- const firstItem = scoreDept[0];
- if (firstItem.hasOwnProperty('deptName')) {
- deptName = firstItem['deptName'] as string;
- }
- if (firstItem.hasOwnProperty('center')) {
- center = firstItem['center'] as string;
- }
- if (firstItem.hasOwnProperty('companyName')) {
- companyName = firstItem['companyName'] as string;
- }
- }
-
- // 更新排名信息
- const rankingItems : RankingItem[] = [];
-
- // 部门排名(东山电场)
- if (data.hasOwnProperty('deptSort') && data.hasOwnProperty('scoreDept')) {
- const deptSort = typeof data['deptSort'] === 'number' ? data['deptSort'] as number : 0;
- const scoreDept = Array.isArray(data['scoreDept']) ? data['scoreDept'] as any[] : [];
- // 只有当部门排序大于0且scoreDept数组不为空时才添加
- if (deptSort > 0 && scoreDept.length > 0) {
- rankingItems.push({
- name: deptName,
- rank: deptSort,
- total: scoreDept.length
- });
- }
- }
-
- // 中心排名(陆上设备维护中心)
- if (data.hasOwnProperty('centerSort') && data.hasOwnProperty('scoreCenter')) {
- const centerSort = typeof data['centerSort'] === 'number' ? data['centerSort'] as number : 0;
- const scoreCenter = Array.isArray(data['scoreCenter']) ? data['scoreCenter'] as any[] : [];
- // 只有当中心排序大于0且scoreCenter数组不为空时才添加
- if (centerSort > 0 && scoreCenter.length > 0) {
- rankingItems.push({
- name: center,
- rank: centerSort,
- total: scoreCenter.length
- });
- }
- }
-
- // 公司排名
- if (data.hasOwnProperty('companySort') && data.hasOwnProperty('scoreCompany')) {
- const companySort = typeof data['companySort'] === 'number' ? data['companySort'] as number : 0;
- const scoreCompany = Array.isArray(data['scoreCompany']) ? data['scoreCompany'] as any[] : [];
- // 只有当公司排序大于0且scoreCompany数组不为空时才添加
- if (companySort > 0 && scoreCompany.length > 0) {
- rankingItems.push({
- name: companyName,
- rank: companySort,
- total: scoreCompany.length
- });
- }
- }
-
- // 更新rankingItems
- userData.value.rankingItems = rankingItems;
-
- // 如果rankingItems为空,直接跳转到登录页
- if (rankingItems.length === 0) {
- closeSplash();
- }
- } else {
- // 如果没有获取到数据,直接跳转到登录页
- closeSplash();
- }
- } catch (error) {
- console.error('获取用户数据失败:', error);
- // 出错时直接跳转到登录页
- closeSplash();
- }
- };
- // 开始倒计时
- const startCountdown = (): void => {
- if (hasRedirected) return; // 如果已经跳转则不启动倒计时
-
- countdownTimer = setInterval(() => {
- if (countdown.value > 1) {
- countdown.value--;
- } else {
- closeSplash();
- }
- }, 1000);
- };
- // 生命周期钩子
- onMounted(() => {
- checkSplashConfig().then(() => {
- // 只有在确定显示开屏页的情况下才获取数据和启动倒计时
- if (showSplash.value) {
- fetchUserData().then(() => {
- // 只有在rankingItems有数据的情况下才启动倒计时
- if (userData.value.rankingItems.length > 0) {
- startCountdown();
- } else {
- // 否则直接跳转
- closeSplash();
- }
- });
- }
- });
- });
- // 根据索引获取对应的图标信息
- const getRankingIcon = (index: number): RankingIcon => {
- //索引0对应电场,索引1对应维护中心,索引2对应公司
- const icons: RankingIcon[] = [
- { type: 'emoji', value: '🏭' },
- { type: 'emoji', value: '⚙️' },
- { type: 'emoji', value: '🏢' }
- ];
-
- /* const icons = [
- { type: 'image', value: '/static/icons/power-plant.png' },
- { type: 'image', value: '/static/icons/maintenance-center.png' },
- { type: 'image', value: '/static/icons/company.png' }
- ]; */
- return index >= 0 && index < icons.length ? icons[index] : { type: 'emoji', value: '' };
- };
-
- // 根据索引获取排名圆圈的大小类
- const getRankingSizeClass = (index: number): string => {
- // size-1 对应最小的圆圈,size-3 对应最大的圆圈
- const size = Math.min(index + 1, 3);
- return `size-${size}`;
- };
- function formatNumber(value: number | null) {
- if (value == null) return '0.0'
- return value.toFixed(2)
- }
- onUnmounted(() => {
- if (countdownTimer != null) {
- clearInterval(countdownTimer as number);
- countdownTimer = null;
- }
- });
- return {
- countdown,
- showSplash,
- checked,
- userData,
- closeSplash,
- getRankingIcon,
- getRankingSizeClass,
- formatNumber
- };
- }
- };
- </script>
- <style lang="scss">
- .splash-container {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- z-index: 9999;
- /* background-image: url('/static/images/splash/blackground.png');
- background-size: cover;
- background-position: center; */
- }
- .splash-background-image {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: -1;
- }
- .splash-content {
- width: 100%;
- max-width: 400px;
- margin: 0 auto;
- }
- .module {
- background: linear-gradient(to right, rgba(40, 80, 140, 0.7), rgba(20, 40, 80, 0.8));
- border-radius: 16px;
- padding: 40rpx;
- border: 1.5px solid #93c5fd;
- box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.15);
- margin-bottom: 20rpx;
- margin-left: auto;
- margin-right: auto;
- width: 90%;
- }
- .personal-ranking {
- background: linear-gradient(to right, rgba(40, 80, 140, 0.6), rgba(20, 40, 80, 0.7));
- border-radius: 16px;
- padding: 45rpx;
- border: 1px solid rgba(147, 197, 253, 0.2);
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
- margin-bottom: 20rpx;
- margin-left: auto;
- margin-right: auto;
- width: 90%;
- }
- .monthly-score {
- text-align: center;
- margin-bottom: 10rpx;
- position: relative;
- top: -60rpx;
- z-index: 10;
- padding: 70rpx 40rpx !important;
- margin-top: 60rpx;
- border-radius: 30px !important;
- border: 1.5px solid #93c5fd !important;
- background: linear-gradient(to right, rgba(30, 70, 130, 0.8), rgba(10, 30, 60, 0.9)) !important;
- box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.15);
- }
- .monthly-score .module-title {
- font-size: 50rpx;
- font-weight: bold;
- margin-bottom: 30rpx;
- transform: translateY(-10rpx);
- }
- .personal-ranking .module-title {
- text-align: left !important;
- display: flex;
- align-items: center;
- justify-content: flex-start;
- height: 100%;
- padding: 0;
- margin-bottom: 0;
- }
- .module-title {
- color: #ffffff;
- font-size: 36rpx;
- font-weight: bold;
- margin-bottom: 0;
- text-align: center;
- }
- .score-container {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: center;
- }
- .score-icon {
- font-size: 80rpx;
- margin-right: 30rpx;
- }
- .score-value {
- color: #38bdf8;
- font-size: 96rpx;
- font-weight: bold;
- }
- .ranking-item {
- display: flex;
- flex-direction: row;
- align-items: center;
- width: 100%;
- padding-left: 0;
- margin-left: 0;
- }
- .ranking-icon {
- font-size: 48rpx;
- width: 48rpx;
- height: 48rpx;
- margin-right: 20rpx;
- margin-left: 0rpx;
- color: #94a3b8;
- }
- .ranking-icon[image] {
- width: 48rpx;
- height: 48rpx;
- }
- .ranking-name {
- color: #ffffff;
- font-size: 32rpx;
- font-weight: normal;
- flex: 1;
- margin-left: -10rpx;
- }
- .ranking-number {
- background: #38bdf8;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .ranking-circle-wrapper {
- width: 120rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- margin: 0 20rpx;
- margin-left: 0;
- }
- .ranking-number.size-1 {
- width: 80rpx;
- height: 80rpx;
- border-radius: 40rpx;
- }
- .ranking-number.size-2 {
- width: 90rpx;
- height: 90rpx;
- border-radius: 45rpx;
- }
- .ranking-number.size-3 {
- width: 100rpx;
- height: 100rpx;
- border-radius: 50rpx;
- }
- .ranking-number-text {
- color: #ffffff;
- font-weight: normal;
- text-align: center;
- font-size: 28rpx;
- }
- .ranking-number.size-1 .ranking-number-text {
- font-size: 22rpx;
- }
- .ranking-number.size-2 .ranking-number-text {
- font-size: 24rpx;
- }
- .ranking-number.size-3 .ranking-number-text {
- font-size: 26rpx;
- }
- .ranking-label {
- color: #ffffff;
- font-size: 32rpx;
- white-space: nowrap;
- margin-right: 20rpx;
- }
- .splash-footer {
- position: absolute;
- top: 80rpx;
- right: 30rpx;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- width: 250rpx;
- height: 60rpx;
- background: rgba(0, 0, 0, 0.3);
- border-radius: 30rpx;
- border: 1px solid rgba(147, 197, 253, 0.1);
- padding: 0 20rpx;
- }
- .splash-footer .countdown {
- margin-bottom: 0;
- background: transparent;
- border: none;
- padding: 0;
- }
- .splash-footer .close-button {
- background: transparent;
- border: none;
- padding: 0;
- margin-left: 10rpx;
- }
- .countdown-text {
- color: #ffffff;
- font-size: 28rpx;
- font-weight: bold;
- }
- .close-text {
- color: #ffffff;
- font-size: 28rpx;
- font-weight: normal;
- }
- </style>
|