Files
zhgh_zjvtit/target/classes/views/layouts/v4/home/user.js
T
2026-08-26 14:25:17 +08:00

554 lines
19 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const user = {
template: /*language=HTML*/ `
<div class="user-wrapper">
<!-- 用户容器:左右布局 -->
<div class="user-container">
<!-- 左侧:用户信息卡片 -->
<div class="user-info-card">
<div class="user-details">
<div class="user-name">${@auth.getPrincipalProperty('username')}</div>
<div class="user-meta-grid">
<div class="meta-row">
<span class="meta-icon">🆔</span>
<div>
<span class="meta-label">工号</span>
<span class="meta-value">${@auth.getPrincipalProperty('loginname')}</span>
</div>
</div>
<div class="meta-row">
<span class="meta-icon">🏢</span>
<div>
<span class="meta-label">单位信息</span>
<span class="meta-value">
<!--#if(!isEmpty(@auth.getPrincipalProperty('unit'))){#-->
${@auth.getPrincipalProperty('unit').getName()}
<!--#}#-->
(
<!--#if(!isEmpty(@auth.getPrincipalProperty('union'))){#-->
${@auth.getPrincipalProperty('union').getName()}
<!--#}#-->
)
</span>
</div>
</div>
<div class="meta-row">
<span class="meta-icon">🎭</span>
<div>
<span class="meta-label">角色</span>
<span class="meta-value">{{ roleNames || '—' }}</span>
</div>
</div>
</div>
</div>
<!-- 天气区域 -->
<div v-if="weatherData" class="weather-section" :class="weatherData.bgClass">
<div style="display: flex; justify-content: space-around">
<div class="weather-header">
<span class="weather-location">{{ weatherData.name }}</span>
<span class="weather-text">{{ weatherData.text }}</span>
</div>
<div class="weather-main">
<span class="weather-emoji">{{ weatherData.emoji }}</span>
<span class="weather-temp">{{ weatherData.temp }}°</span>
</div>
</div>
<div class="weather-tip">{{ weatherData.tip }}</div>
</div>
<div v-else-if="weatherError" class="weather-error">
🌤️ 天气服务暂时不可用
</div>
</div>
<!-- 右侧:待办中心 -->
<div class="todo-center">
<!-- 标题和标签 -->
<div class="header">
<h3>待办中心</h3>
<el-tabs v-model="activeTab" type="card" @tab-click="handleTabClick">
<el-tab-pane :label="tabLabel('待办事宜', taskStats.todoCount)" name="todo"></el-tab-pane>
<el-tab-pane :label="tabLabel('已办事宜', taskStats.doneCount)" name="done"></el-tab-pane>
<el-tab-pane :label="tabLabel('我的发起', taskStats.startedCount)" name="started"></el-tab-pane>
<el-tab-pane :label="tabLabel('办结事务', taskStats.completedCount)" name="completed"></el-tab-pane>
</el-tabs>
</div>
<!-- 表格 -->
<el-table
:data="todoList"
style="width: 100%"
border
stripe
v-loading="loading"
:cell-style="{ padding: '8px' }"
:header-cell-style="{ background: '#f8f9fa', color: '#444', fontWeight: '500' }"
>
<el-table-column label="序号" type="index" :index="indexMethod" width="100px"></el-table-column>
<el-table-column prop="categoryName" label="流程分类" width="100"></el-table-column>
<el-table-column prop="title" label="流程名称" min-width="300">
<template slot-scope="scope">
<el-tooltip effect="dark" :content="scope.row.instanceName" placement="top">
<span class="table-title">{{ scope.row.instanceName }}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="sender" label="申请人" width="120">
<template slot-scope="{row}">{{row.variable.initiatorName}}</template>
</el-table-column>
<el-table-column prop="taskName" label="当前流程节点" width="140" show-overflow-tooltip></el-table-column>
<el-table-column prop="date" label="发起日期" width="120">
<template slot-scope="{row}">
{{$moment(row.createdAt).format('YYYY-MM-DD')}}
</template>
</el-table-column>
<el-table-column label="操作" width="100px" fixed="right">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="openView(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</div>
</div>
</div>
`,
mixins: [initTableMixins],
data() {
return {
activeTab: 'todo',
todoList: [],
loading: false,
pageForm: {
pageNum: 1,
pageSize: 5,
totalCount: 0
},
taskStats: {
todoCount: 0,
doneCount: 0,
startedCount: 0,
completedCount: 0
},
// 🔆 天气相关数据
weatherData: null,
weatherError: false,
// 🔑 和风天气 API Key(请替换为你自己的)
QWEATHER_KEY: 'f916578cbb0e4b55b778b0de5847ecf5', // ←← 务必替换!
roleNames: ""
};
},
methods: {
getWeatherInfo(iconCode, temp) {
const info = {
emoji: '🌤️',
tip: '今日天气宜人,心情也该放晴啦!',
bgClass: 'weather-sunny' // 用于 CSS 类
};
const tempNum = parseFloat(temp);
const isCold = tempNum < 10;
const isHot = tempNum > 28;
// 按照和风天气 iconCode 分类
if (['100'].includes(iconCode)) {
info.emoji = '☀️';
info.tip = isHot ? '高温预警!注意防暑降温,多喝水~' : '阳光灿烂,适合外出走走!';
info.bgClass = 'weather-sunny';
} else if (['101', '102', '103', '104'].includes(iconCode)) {
info.emoji = ['101', '103'].includes(iconCode) ? '⛅' : '☁️';
info.tip = isCold ? '天凉加衣,别让感冒找上门!' : '云层温柔,适合静心工作。';
info.bgClass = 'weather-cloudy';
} else if (['300', '301', '302', '305', '306', '399'].some(code => code === iconCode)) {
info.emoji = '🌧️';
info.tip = '🌧️ 下雨啦!记得带伞,小心路滑~';
info.bgClass = 'weather-rainy';
} else if (['307', '308', '309', '310'].includes(iconCode)) {
info.emoji = '⛈️';
info.tip = '⛈️ 雷雨天气,请减少外出,注意安全!';
info.bgClass = 'weather-storm';
} else if (['400', '401', '402', '403'].includes(iconCode)) {
info.emoji = '❄️';
info.tip = '❄️ 天寒地冻,保暖最重要!';
info.bgClass = 'weather-snowy';
} else if (['404', '405', '406', '407', '408', '409', '410'].includes(iconCode)) {
info.emoji = '🌫️';
info.tip = '🌫️ 能见度较低,出行请注意安全。';
info.bgClass = 'weather-foggy';
} else if (['500', '501', '502', '504'].includes(iconCode)) {
info.emoji = '🌀';
info.tip = '🌀 极端天气预警!请关注官方通知。';
info.bgClass = 'weather-extreme';
} else {
info.emoji = '🌤️';
info.tip = '今日天气未知,但愿你心情晴朗!';
info.bgClass = 'weather-default';
}
return info;
},
async getConfigKey(key) {
const resp = await this.$axios.post("/open/common/getConfigKey", { key })
return resp.data
},
// 🔆 获取天气
async fetchWeather() {
try {
// 存localStorage 112.13,32.01 广州 113.27,23.14
const AppMapCenterPointX = await this.getConfigKey("AppMapCenterPointX")
const AppMapCenterPointY = await this.getConfigKey("AppMapCenterPointY")
if (!AppMapCenterPointX || !AppMapCenterPointY){
return
}
// 1. 先通过城市名获取 locationId
this.$axios.get("https://mx5rk62kvj.re.qweatherapi.com/geo/v2/city/lookup?location=" + AppMapCenterPointX + "," + AppMapCenterPointY + "&key=" + this.QWEATHER_KEY).then((geoRes) => {
if (geoRes.code !== '200' || !geoRes.location?.[0]) {
console.log('城市未找到')
}
const locationId = geoRes.location[0].id;
// 2. 获取当前天气
this.$axios.get("https://mx5rk62kvj.re.qweatherapi.com/v7/weather/now?location=" + locationId + "&key=" + this.QWEATHER_KEY).then((weatherRes) => {
if (weatherRes.code !== '200') {
console.warn('天气数据异常:', weatherRes);
}
const weatherInfo = this.getWeatherInfo(weatherRes.now.icon, weatherRes.now.temp);
this.weatherData = {
...weatherInfo,
temp: weatherRes.now.temp,
text: weatherRes.now.text,
name: geoRes.location[0].name
};
this.weatherError = false;
})
})
} catch (err) {
console.warn('天气加载失败:', err);
this.weatherError = true;
this.weatherData = null;
}
},
// 获取任务列表
tabLabel(title, count) {
return title + "" + (count || 0) + ""
},
async getStatistics() {
try {
const res = await $.post("/flow/todoCenter/statistics")
if (res.code === 0) {
this.taskStats = Object.assign({}, this.taskStats, res.data)
}
} catch (error) {
console.error("获取待办统计失败:", error)
}
},
async getTasks() {
this.loading = true
try {
const res = await $.post("/flow/todoCenter/" + this.activeTab, this.pageForm)
if (res.code === 0) {
this.todoList = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
} catch (error) {
this.$message.error("获取任务列表失败")
console.error("获取任务列表失败:", error)
} finally {
this.loading = false
}
},
pageData() {
this.getTasks()
this.getStatistics()
},
handleTabClick(tab) {
this.pageData()
console.log('切换到:', tab.name);
},
// 处理任务
async openView(task) {
console.log(task)
const {taskId, taskKey, taskState, instanceId, businessNo, formKey} = task
if (!formKey) {
this.$message.warning("当前流程没有配置地址")
return
}
window.open(formKey + "?taskId=" + taskId + "&bizId=" + businessNo + "&taskKey=" + taskKey + "&tab=" + this.activeTab)
},
getRoleNames() {
$.post("/platform/sys/role/getRoleNames").then(res => {
if (res.code === 0) {
this.roleNames = res.data.roleNames
}
})
}
},
created() {
this.pageData()
this.getRoleNames()
},
mounted() {
this.fetchWeather()
},
style: /*language=CSS*/ `
.user-wrapper {
width: 100%;
background-color: #f5f7fa;
}
.user-container {
width: 80%;
margin: 12px auto 20px;
display: grid;
grid-template-columns: 0.7fr 2.3fr;
gap: 24px;
align-items: stretch;
row-gap: 24px;
}
.user-info-card {
background: white;
border-radius: 16px;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
padding: 24px;
display: flex;
flex-direction: column;
gap: 20px;
transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.user-info-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}
/* 头像占位符 */
.user-avatar-placeholder {
width: 64px;
height: 64px;
border-radius: 50%;
background: linear-gradient(135deg, #409eff, #1877f2);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
font-weight: 600;
margin: 0 auto;
box-shadow: 0 4px 10px rgba(24, 127, 255, 0.3);
}
/* 用户名 */
.user-name {
font-size: 20px;
font-weight: 700;
color: #1f2937;
text-align: center;
margin: 8px 0 0;
}
/* 元信息网格 */
.user-meta-grid {
display: flex;
flex-direction: column;
gap: 14px;
margin-top: 8px;
}
.meta-row {
display: flex;
align-items: flex-start;
gap: 12px;
}
.meta-icon {
font-size: 18px;
min-width: 24px;
text-align: center;
color: #409eff;
margin-top: 2px;
}
.meta-row > div {
flex: 1;
}
.meta-label {
font-size: 12px;
color: #6b7280;
font-weight: 500;
display: block;
margin-bottom: 2px;
}
.meta-value {
font-size: 15px;
color: #1f2937;
font-weight: 600;
word-break: break-word;
}
/* === 天气卡片 - 情感化设计 === */
.weather-section {
border-radius: 16px;
padding: 20px;
text-align: center;
color: white;
background: linear-gradient(135deg, #a8edea, #fed6e3); /* 默认柔和渐变 */
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
transition: all 0.3s ease;
}
/* 不同天气的背景主题 */
.weather-sunny {
background: linear-gradient(135deg, #FFD700, #FFA500);
color: #2c3e50;
}
.weather-cloudy {
background: linear-gradient(135deg, #B0C4DE, #708090);
color: white;
}
.weather-rainy {
background: linear-gradient(135deg, #4A6FA5, #1E3F66);
color: white;
}
.weather-storm {
background: linear-gradient(135deg, #2F2F2F, #0D0D0D);
color: #FFD700;
}
.weather-snowy {
background: linear-gradient(135deg, #E0F7FA, #B3E5FC);
color: #01579B;
}
.weather-foggy {
background: linear-gradient(135deg, #D7CCC8, #A1887F);
color: white;
}
.weather-extreme {
background: linear-gradient(135deg, #FF5252, #B71C1C);
color: white;
}
.weather-default {
background: linear-gradient(135deg, #E0E0E0, #90A4AE);
color: #333;
}
/* 天气头部:城市 + 描述 */
.weather-header {
margin-bottom: 12px;
}
.weather-location {
font-weight: 700;
font-size: 16px;
display: block;
}
.weather-text {
font-size: 13px;
opacity: 0.9;
display: block;
margin-top: 4px;
}
/* 主体:图标 + 温度 */
.weather-main {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
position: relative;
bottom: 8px;
}
.weather-emoji {
font-size: 36px;
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));
}
.weather-temp {
font-size: 28px;
font-weight: 800;
}
/* 贴心提示语 */
.weather-tip {
font-size: 14px;
line-height: 1.5;
opacity: 0.95;
margin-top: 8px;
padding: 0 8px;
}
/* 错误状态 */
.weather-error {
text-align: center;
color: #94a3b8;
font-size: 14px;
padding: 16px;
background: #f8fafc;
border-radius: 12px;
border: 1px dashed #cbd5e1;
}
/* 右侧待办中心 */
.todo-center {
min-width: 320px;
background: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
padding: 16px;
transition: transform 0.2s, box-shadow 0.2s;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.header h3 {
font-size: 18px;
color: #333;
margin: 0;
border-left: 4px solid #1890ff;
padding-left: 10px;
font-weight: 600;
}
.el-tabs {
margin-top: 10px;
}
.table-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 280px;
display: inline-block;
}
.pagination {
margin-top: 20px;
text-align: right;
}
/* 响应式:小屏下堆叠 */
@media (max-width: 768px) {
.user-container {
flex-direction: column;
width: 95%;
}
.user-info-card, .todo-center {
min-width: 100%;
width: 100%;
}
}
`
};