You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
748 lines
18 KiB
Vue
748 lines
18 KiB
Vue
<template>
|
|
<view class="page-container tn-gradient-bg__cool-5" @click="hideUserMenu">
|
|
<cheader :show-time="false"></cheader>
|
|
<div class="index-body">
|
|
<view class="duty-rail">
|
|
<text class="duty-clock">{{ clockText }}</text>
|
|
<text class="duty-date">{{ dateText }}</text>
|
|
<view class="duty-block">
|
|
<text class="duty-kicker">当班人员</text>
|
|
<text class="duty-value">{{ userInfo.realName || "未登录" }}</text>
|
|
</view>
|
|
<view class="duty-todos">
|
|
<text class="duty-kicker">待办事项</text>
|
|
<scroll-view class="duty-todo-list" scroll-y>
|
|
<text v-if="todos.length === 0" class="duty-todo-empty">暂无待办</text>
|
|
<view
|
|
v-for="item in todos"
|
|
:key="item.id"
|
|
class="duty-todo-item"
|
|
:class="{ 'duty-todo-done': item.done }"
|
|
>
|
|
<text class="duty-todo-text">{{ item.text }}</text>
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
<view class="duty-tip" @click="goToDutyTodos">
|
|
<text class="duty-tip-text">编辑待办事项</text>
|
|
<uni-icons type="right" size="16" color="#fff"></uni-icons>
|
|
</view>
|
|
</view>
|
|
<div class="main-pane">
|
|
<div class="body-title">
|
|
<view class="title-left">
|
|
<span class="title-mian">导税工作台</span>
|
|
<text class="app-version">v{{ appVersion }}</text>
|
|
</view>
|
|
<view
|
|
class="user-mini"
|
|
:class="{ 'user-mini-open': showUserMenu }"
|
|
@click.stop="toggleUserMenu"
|
|
>
|
|
<image
|
|
v-if="userInfo.image"
|
|
:src="userInfo.image"
|
|
class="user-mini-avatar"
|
|
></image>
|
|
<view v-else class="user-mini-avatar user-mini-fallback">
|
|
<uni-icons type="person-filled" size="16" color="#1e3a8a"></uni-icons>
|
|
</view>
|
|
<text class="user-mini-name">{{ userInfo.realName || "未登录" }}</text>
|
|
<view
|
|
class="user-mini-caret"
|
|
:class="{ 'user-mini-caret-open': showUserMenu }"
|
|
>
|
|
<uni-icons type="bottom" size="12" color="#fff"></uni-icons>
|
|
</view>
|
|
<view v-if="showUserMenu" class="user-menu" @click.stop>
|
|
<view class="user-menu-item" @click.stop="goToAppLog">
|
|
<uni-icons type="list" size="16" color="#1e3a8a"></uni-icons>
|
|
<text>查看日志</text>
|
|
</view>
|
|
<view class="user-menu-sep"></view>
|
|
<view
|
|
class="user-menu-item user-menu-item-danger"
|
|
@click.stop="loginOutAction"
|
|
>
|
|
<uni-icons type="locked" size="16" color="#dc2626"></uni-icons>
|
|
<text>退出登录</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</div>
|
|
<div class="btn-content">
|
|
<div class="btn-row1">
|
|
<div class="home-tile row1-item1 col-center" @click="goToQueue()">
|
|
<uni-icons type="compose" size="60" color="#fff"></uni-icons>
|
|
<p class="btn-p">预检取号</p>
|
|
</div>
|
|
<div class="home-tile row1-item2 col-center" @click="goToTicket()">
|
|
<uni-icons type="list" size="60" color="#fff"></uni-icons>
|
|
<p class="btn-p">票号管理</p>
|
|
</div>
|
|
<div class="home-tile row1-item3 col-center" @click="goToManager()">
|
|
<uni-icons type="staff-filled" size="60" color="#fff"></uni-icons>
|
|
<p class="btn-p">网格员</p>
|
|
</div>
|
|
</div>
|
|
<div class="btn-row2">
|
|
<div class="row2-item1">
|
|
<div class="home-tile row2-item1-top row-center" @click="goToPushMessage()">
|
|
<uni-icons type="info" size="60" color="#fff"></uni-icons>
|
|
<p class="btn-p">信息推送</p>
|
|
</div>
|
|
<div class="home-tile row2-item1-bottom row-center">
|
|
<uni-icons type="compose" size="60" color="#fff"></uni-icons>
|
|
<p class="btn-p">预留功能</p>
|
|
</div>
|
|
</div>
|
|
<div class="row2-item2">
|
|
<div
|
|
class="home-tile row2-item2-left col-center"
|
|
@click="goToSignPriority()"
|
|
>
|
|
<uni-icons
|
|
type="home-filled"
|
|
size="60"
|
|
color="#fff"
|
|
></uni-icons>
|
|
<p class="btn-p">回签优先</p>
|
|
</div>
|
|
<div class="home-tile row2-item2-center col-center">
|
|
<uni-icons
|
|
type="auth-filled"
|
|
size="60"
|
|
color="#fff"
|
|
></uni-icons>
|
|
<p class="btn-p">预留功能</p>
|
|
</div>
|
|
<div class="home-tile row2-item2-right col-center">
|
|
<uni-icons
|
|
type="settings-filled"
|
|
size="60"
|
|
color="#fff"
|
|
></uni-icons>
|
|
<p class="btn-p">预留功能</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { getAuthProfile } from "@/api/index.js";
|
|
import cheader from "@/components/header.vue";
|
|
import { appLog, flushLogs } from "@/utils/appLog.js";
|
|
import { loadDutyTodos } from "@/utils/dutyTodos.js";
|
|
import { waitSessionReady } from "@/utils/request.js";
|
|
import { getAppVersion } from "@/utils/appVersion.js";
|
|
import {
|
|
onBackPress,
|
|
onHide,
|
|
onLoad,
|
|
onShow,
|
|
onUnload,
|
|
} from "@dcloudio/uni-app";
|
|
import { computed, ref } from "vue";
|
|
|
|
const WEEK_DAYS = [
|
|
"星期日",
|
|
"星期一",
|
|
"星期二",
|
|
"星期三",
|
|
"星期四",
|
|
"星期五",
|
|
"星期六",
|
|
];
|
|
|
|
const appVersion = getAppVersion();
|
|
|
|
const userInfo = ref({
|
|
realName: "",
|
|
id: "",
|
|
image: "",
|
|
});
|
|
|
|
const showUserMenu = ref(false);
|
|
const toggleUserMenu = () => {
|
|
showUserMenu.value = !showUserMenu.value;
|
|
};
|
|
const hideUserMenu = () => {
|
|
showUserMenu.value = false;
|
|
};
|
|
|
|
const now = ref(new Date());
|
|
const todos = ref([]);
|
|
let clockTimer = null;
|
|
|
|
const pad2 = (value) => String(value).padStart(2, "0");
|
|
|
|
const clockText = computed(() => {
|
|
const date = now.value;
|
|
return `${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;
|
|
});
|
|
|
|
const dateText = computed(() => {
|
|
const date = now.value;
|
|
return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${WEEK_DAYS[date.getDay()]}`;
|
|
});
|
|
|
|
onBackPress(() => {
|
|
return true;
|
|
});
|
|
|
|
onLoad(() => {
|
|
try {
|
|
const storageData = uni.getStorageSync("userInfo");
|
|
if (storageData) {
|
|
const parsedData = JSON.parse(storageData);
|
|
userInfo.value = {
|
|
realName: parsedData.realName || "",
|
|
id: parsedData.id || "",
|
|
image: parsedData.image || "/static/header_no.png",
|
|
};
|
|
console.log("用户信息:", userInfo.value);
|
|
}
|
|
} catch (error) {
|
|
console.error("获取用户信息失败:", error);
|
|
}
|
|
});
|
|
|
|
const loadHallNameFromProfile = async () => {
|
|
try {
|
|
const profile = await getAuthProfile();
|
|
const swjgMC = profile?.swjgMC || profile?.swjgMc || "";
|
|
console.log("[auth/profile@index] response:", profile);
|
|
console.log("[auth/profile@index] parsed swjgMC:", swjgMC);
|
|
if (swjgMC) {
|
|
uni.setStorageSync("swjgMC", swjgMC);
|
|
uni.$emit("hall-name-updated");
|
|
console.log("[auth/profile@index] swjgMC saved");
|
|
} else {
|
|
console.log("[auth/profile@index] swjgMC is empty, skip save");
|
|
}
|
|
} catch (error) {
|
|
console.log("获取机构名称失败", error);
|
|
}
|
|
};
|
|
|
|
const startClockTimer = () => {
|
|
stopClockTimer();
|
|
now.value = new Date();
|
|
clockTimer = setInterval(() => {
|
|
now.value = new Date();
|
|
}, 1000);
|
|
};
|
|
|
|
const stopClockTimer = () => {
|
|
if (clockTimer) {
|
|
clearInterval(clockTimer);
|
|
clockTimer = null;
|
|
}
|
|
};
|
|
|
|
onShow(async () => {
|
|
await waitSessionReady();
|
|
loadHallNameFromProfile();
|
|
todos.value = loadDutyTodos();
|
|
startClockTimer();
|
|
});
|
|
|
|
onHide(() => {
|
|
stopClockTimer();
|
|
});
|
|
|
|
onUnload(() => {
|
|
stopClockTimer();
|
|
});
|
|
|
|
const goToGuidance = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/mod/guidance?isFromTicket=false",
|
|
});
|
|
};
|
|
|
|
const goToDailyEntry = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/table/dailyEntry",
|
|
});
|
|
};
|
|
|
|
const goToAppointment = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/table/appointment",
|
|
});
|
|
};
|
|
|
|
const goToTicket = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/table/ticket",
|
|
});
|
|
};
|
|
|
|
const goToMultiInOne = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/mod/multiInOne",
|
|
});
|
|
};
|
|
|
|
const goToPushMessage = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/mod/pushMessage",
|
|
});
|
|
};
|
|
|
|
const goToQueue = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/queue/index",
|
|
});
|
|
};
|
|
|
|
const goToManager = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/mod/manager",
|
|
});
|
|
};
|
|
|
|
const goToHallManagment = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/mod/hallManagment",
|
|
});
|
|
};
|
|
|
|
const goToSignPriority = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/mod/sign-priority",
|
|
});
|
|
};
|
|
|
|
const goToDutyTodos = () => {
|
|
uni.navigateTo({
|
|
url: "/pages/mod/duty-todos",
|
|
});
|
|
};
|
|
|
|
const goToAppLog = () => {
|
|
showUserMenu.value = false;
|
|
uni.navigateTo({
|
|
url: "/pages/mod/appLog",
|
|
});
|
|
};
|
|
|
|
const loginOutAction = () => {
|
|
uni.showModal({
|
|
title: "登出",
|
|
content: "是否退出登录,并返回到登录界面?",
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
appLog('info', '[index] 用户退出登录')
|
|
flushLogs()
|
|
stopClockTimer();
|
|
uni.removeStorageSync("token");
|
|
uni.removeStorageSync("refresh_token");
|
|
uni.removeStorageSync("userInfo");
|
|
uni.reLaunch({
|
|
url: "/pages/login/login",
|
|
});
|
|
}
|
|
},
|
|
});
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.page-container {
|
|
height: var(--pad-h);
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.index-body {
|
|
flex: 1;
|
|
min-height: 0;
|
|
width: 100%;
|
|
padding: 12px 5vw 16px;
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: stretch;
|
|
overflow: hidden;
|
|
--module-gap: 10px;
|
|
|
|
.duty-rail {
|
|
width: 20vw;
|
|
flex: 0 0 20vw;
|
|
min-height: 0;
|
|
margin-right: 16px;
|
|
padding: 20px 16px 14px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
border-radius: 16px;
|
|
background: rgba(15, 23, 42, 0.22);
|
|
border: 1px solid rgba(255, 255, 255, 0.22);
|
|
box-shadow: 0 12px 28px rgba(15, 23, 42, 0.18);
|
|
backdrop-filter: blur(14px);
|
|
}
|
|
|
|
.duty-clock {
|
|
font-size: 36px;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
letter-spacing: 1px;
|
|
line-height: 1;
|
|
font-variant-numeric: tabular-nums;
|
|
font-family: "DIN Alternate", "Roboto Mono", "Courier New", monospace;
|
|
}
|
|
|
|
.duty-date {
|
|
margin-top: 8px;
|
|
font-size: 13px;
|
|
color: rgba(255, 255, 255, 0.78);
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.duty-block {
|
|
margin-top: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.duty-kicker {
|
|
font-size: 11px;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
letter-spacing: 2px;
|
|
}
|
|
|
|
.duty-value {
|
|
margin-top: 6px;
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
color: #fff;
|
|
line-height: 1.4;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.duty-todos {
|
|
flex: 1;
|
|
min-height: 0;
|
|
margin-top: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.duty-todo-list {
|
|
flex: 1;
|
|
min-height: 0;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
.duty-todo-empty {
|
|
font-size: 13px;
|
|
color: rgba(255, 255, 255, 0.45);
|
|
}
|
|
|
|
.duty-todo-item {
|
|
margin-bottom: 8px;
|
|
padding-left: 8px;
|
|
border-left: 2px solid rgba(255, 255, 255, 0.35);
|
|
}
|
|
|
|
.duty-todo-done {
|
|
opacity: 0.55;
|
|
}
|
|
|
|
.duty-todo-text {
|
|
font-size: 13px;
|
|
line-height: 1.4;
|
|
color: #fff;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.duty-todo-done .duty-todo-text {
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.duty-tip {
|
|
margin-top: 12px;
|
|
padding: 10px 12px;
|
|
border-radius: 12px;
|
|
background: rgba(255, 255, 255, 0.12);
|
|
border: 1px solid rgba(255, 255, 255, 0.16);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.duty-tip-text {
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
color: #fff;
|
|
}
|
|
|
|
.main-pane {
|
|
flex: 1;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: visible;
|
|
}
|
|
|
|
.body-title {
|
|
min-height: 0;
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
flex-shrink: 0;
|
|
position: relative;
|
|
z-index: 30;
|
|
overflow: visible;
|
|
|
|
.title-left {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 12px;
|
|
}
|
|
|
|
.title-mian {
|
|
color: #fff;
|
|
font-size: 32px;
|
|
font-weight: 700;
|
|
letter-spacing: 1px;
|
|
text-shadow: 0 6px 18px rgba(15, 23, 42, 0.25);
|
|
}
|
|
|
|
.app-version {
|
|
font-size: 14px;
|
|
color: rgba(255, 255, 255, 0.78);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.user-mini {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
background-color: rgba(255, 255, 255, 0.18);
|
|
border: 1px solid rgba(255, 255, 255, 0.32);
|
|
border-radius: 22px;
|
|
padding: 4px 10px 4px 4px;
|
|
backdrop-filter: blur(8px);
|
|
flex-shrink: 0;
|
|
box-shadow: 0 6px 16px rgba(15, 23, 42, 0.12);
|
|
|
|
.user-mini-avatar {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
border: 1px solid rgba(255, 255, 255, 0.85);
|
|
margin-right: 8px;
|
|
object-fit: cover;
|
|
background: #e8eef7;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.user-mini-fallback {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: #fff;
|
|
border-color: #fff;
|
|
}
|
|
|
|
.user-mini-name {
|
|
font-size: 14px;
|
|
color: #fff;
|
|
font-weight: 600;
|
|
max-width: 120px;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.user-mini-caret {
|
|
margin-left: 6px;
|
|
display: flex;
|
|
align-items: center;
|
|
opacity: 0.9;
|
|
}
|
|
|
|
.user-mini-caret-open {
|
|
transform: rotate(180deg);
|
|
}
|
|
|
|
.user-menu {
|
|
position: absolute;
|
|
top: calc(100% + 8px);
|
|
right: 0;
|
|
background-color: #fff;
|
|
border-radius: 12px;
|
|
border: 1px solid #d7e2ee;
|
|
box-shadow: 0 14px 32px rgba(15, 23, 42, 0.18);
|
|
overflow: hidden;
|
|
min-width: 156px;
|
|
padding: 6px;
|
|
z-index: 40;
|
|
|
|
.user-menu-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 10px 12px;
|
|
border-radius: 8px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #1e3a8a;
|
|
text-align: left;
|
|
}
|
|
|
|
.user-menu-item-danger {
|
|
color: #dc2626;
|
|
}
|
|
|
|
.user-menu-sep {
|
|
height: 1px;
|
|
margin: 4px 8px;
|
|
background: #e2e8f0;
|
|
}
|
|
|
|
.user-menu-item:active {
|
|
background-color: #eef3f9;
|
|
}
|
|
}
|
|
}
|
|
|
|
.user-mini-open {
|
|
background-color: rgba(255, 255, 255, 0.3);
|
|
border-color: rgba(255, 255, 255, 0.5);
|
|
}
|
|
}
|
|
|
|
.btn-content {
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--module-gap);
|
|
overflow: hidden;
|
|
|
|
.home-tile {
|
|
min-height: 0;
|
|
border-radius: $card-border-radius;
|
|
overflow: hidden;
|
|
box-shadow: 0 12px 24px rgba(15, 23, 42, 0.18);
|
|
}
|
|
|
|
.btn-row1 {
|
|
flex: 1;
|
|
min-height: 0;
|
|
width: 100%;
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: var(--module-gap);
|
|
|
|
.row1-item1 {
|
|
background-color: #2563eb;
|
|
background-image: linear-gradient(to bottom right, #93c5fd 0%, #2563eb 48%, #1e3a8a 100%);
|
|
}
|
|
|
|
.row1-item2 {
|
|
background-color: #1d4ed8;
|
|
background-image: linear-gradient(to bottom right, #7dd3fc 0%, #3b82f6 48%, #1e40af 100%);
|
|
}
|
|
|
|
.row1-item3 {
|
|
background-color: #0284c7;
|
|
background-image: linear-gradient(to bottom right, #67e8f9 0%, #0ea5e9 48%, #0369a1 100%);
|
|
}
|
|
}
|
|
|
|
.btn-row2 {
|
|
flex: 1.6;
|
|
min-height: 0;
|
|
width: 100%;
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: var(--module-gap);
|
|
|
|
.row2-item1 {
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--module-gap);
|
|
|
|
.row2-item1-top {
|
|
flex: 1;
|
|
min-height: 0;
|
|
background-color: #4f46e5;
|
|
background-image: linear-gradient(to bottom right, #a5b4fc 0%, #6366f1 48%, #3730a3 100%);
|
|
}
|
|
|
|
.row2-item1-bottom {
|
|
flex: 1;
|
|
min-height: 0;
|
|
background-color: #64748b;
|
|
background-image: linear-gradient(to bottom right, #cbd5e1 0%, #94a3b8 48%, #475569 100%);
|
|
}
|
|
}
|
|
|
|
.row2-item2 {
|
|
grid-column: span 2;
|
|
min-height: 0;
|
|
display: flex;
|
|
flex-direction: row;
|
|
gap: var(--module-gap);
|
|
|
|
.row2-item2-left {
|
|
flex: 1;
|
|
background-color: #0e7490;
|
|
background-image: linear-gradient(to bottom right, #67e8f9 0%, #06b6d4 48%, #155e75 100%);
|
|
}
|
|
|
|
.row2-item2-center {
|
|
flex: 1;
|
|
background-color: #64748b;
|
|
background-image: linear-gradient(to bottom right, #cbd5e1 0%, #94a3b8 48%, #475569 100%);
|
|
}
|
|
|
|
.row2-item2-right {
|
|
flex: 1;
|
|
background-color: #64748b;
|
|
background-image: linear-gradient(to bottom right, #e2e8f0 0%, #94a3b8 48%, #334155 100%);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.col-center {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.row-center {
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.btn-p {
|
|
font-size: 22px;
|
|
font-weight: 800;
|
|
color: #fff;
|
|
margin: 8px;
|
|
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
|
|
}
|
|
</style>
|