feat:首页样式优化,增加应用-我的收藏
This commit is contained in:
@@ -436,6 +436,8 @@
|
||||
.v4-logo {
|
||||
height: 100%;
|
||||
width: auto;
|
||||
/* 保留 Logo 透明轮廓,将所有可见颜色统一转换为白色。 */
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
.v4-nav {
|
||||
@@ -754,7 +756,8 @@
|
||||
var currentPath = getBaseSubAppPath()
|
||||
var footer = $("#v4-footer")
|
||||
|
||||
if (currentPath === "/platform/v4/home") {
|
||||
// 服务门户首页不显示版权栏,PJAX 切换时同步判断当前页面。
|
||||
if (currentPath === "/platform/v4/home" && !$("#v4-home-app").hasClass("home-portal")) {
|
||||
footer.show()
|
||||
} else {
|
||||
footer.hide()
|
||||
|
||||
@@ -10,22 +10,23 @@ const act = {
|
||||
<div ref="activitySwiper" class="swiper activity-swiper">
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-slide" v-for="(activity, index) in actList" :key="activity.id">
|
||||
<div class="item" @click="go(activity)">
|
||||
<div class="item" role="button" tabindex="0" @click="go(activity)" @keydown.enter="go(activity)" @keydown.space.prevent="go(activity)">
|
||||
<div class="img-box">
|
||||
<img :src="activity.cover || 'https://www.ncu.edu.cn/__local/8/52/2C/644986B4C9A030F7B65300178A6_8679CB08_18467.jpg'"
|
||||
alt="">
|
||||
<span class="status">
|
||||
<el-image :src="activity.cover" fit="cover" :alt="activity.name">
|
||||
<div slot="error" class="portal-cover-empty"><i class="fa fa-picture-o" aria-hidden="true"></i><span>暂无图片</span></div>
|
||||
</el-image>
|
||||
<span class="status" :class="{'status-ended': getStatusText(activity) === '已结束', 'status-upcoming': getStatusText(activity) === '未开始'}">
|
||||
{{getStatusText(activity)}}
|
||||
</span>
|
||||
</div>
|
||||
<h4 class="title">
|
||||
<h4 class="title" :title="activity.name">
|
||||
{{ activity.name}}
|
||||
</h4>
|
||||
<!--报名时间-->
|
||||
<div class="time">
|
||||
<p>
|
||||
<p :title="[activity.startDate, activity.endDate].filter(Boolean).join(' 至 ')">
|
||||
<i class="fa fa-clock-o"></i>
|
||||
时间:{{ activity.startDate }}至{{ activity.endDate }}
|
||||
{{ formatActivityDate(activity.startDate) }} 至 {{ formatActivityDate(activity.endDate) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -34,15 +35,15 @@ const act = {
|
||||
</div>
|
||||
|
||||
<!-- 导航按钮 -->
|
||||
<div ref="nextButton" class="swiper-button-next"></div>
|
||||
<div ref="prevButton" class="swiper-button-prev"></div>
|
||||
<button type="button" ref="nextButton" class="swiper-button-next" aria-label="下一组活动"></button>
|
||||
<button type="button" ref="prevButton" class="swiper-button-prev" aria-label="上一组活动"></button>
|
||||
|
||||
<!-- 进度条 -->
|
||||
<div ref="pagination" class="swiper-pagination"></div>
|
||||
</div>
|
||||
|
||||
<div v-else class="no-activity-placeholder">
|
||||
<div class="icon">📅</div>
|
||||
<div class="icon"><i class="fa fa-calendar" aria-hidden="true"></i></div>
|
||||
<p>暂无近期活动</p>
|
||||
<p class="subtext">敬请关注后续通知</p>
|
||||
</div>
|
||||
@@ -57,6 +58,24 @@ const act = {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateNavigationPosition() {
|
||||
const swiperElement = this.$refs.activitySwiper
|
||||
const cover = swiperElement && swiperElement.querySelector('.img-box')
|
||||
if (!cover) return
|
||||
// 按实际封面高度定位,避免标题换行或响应式列数变化导致箭头偏移。
|
||||
const container = swiperElement.parentElement
|
||||
const top = cover.getBoundingClientRect().top - container.getBoundingClientRect().top + cover.offsetHeight / 2
|
||||
;[this.$refs.prevButton, this.$refs.nextButton].forEach(button => {
|
||||
if (button) button.style.top = top + 'px'
|
||||
})
|
||||
},
|
||||
formatActivityDate(value) {
|
||||
return value ? this.$moment(value).format('YYYY-MM-DD') : '待定'
|
||||
},
|
||||
browseNext() {
|
||||
if (!this.swiper) return
|
||||
this.swiper.isEnd ? this.swiper.slideTo(0) : this.swiper.slideNext()
|
||||
},
|
||||
/*查询活动*/
|
||||
listAct() {
|
||||
this.$axios.post("/platform/home/listHomeActivity").then((res) => {
|
||||
@@ -89,13 +108,22 @@ const act = {
|
||||
centeredSlides: false,
|
||||
loop: false,
|
||||
watchOverflow: true,
|
||||
// 双栏中的活动按容器宽度排布,避免用整个窗口宽度挤出过多卡片。
|
||||
breakpointsBase: 'container',
|
||||
observer: false,
|
||||
observeParents: false,
|
||||
resizeObserver: false,
|
||||
// 页面内容加载后可能出现滚动条,需重新计算列宽,避免末张封面及圆角被裁切。
|
||||
resizeObserver: true,
|
||||
roundLengths: true,
|
||||
on: {
|
||||
init: () => this.$nextTick(() => this.updateNavigationPosition()),
|
||||
resize: () => this.$nextTick(() => this.updateNavigationPosition()),
|
||||
slidesUpdated: () => this.$nextTick(() => this.updateNavigationPosition()),
|
||||
},
|
||||
// 鼠标停留在活动区域时可横向浏览,到首尾后释放页面滚动。
|
||||
mousewheel: {
|
||||
enabled: true,
|
||||
forceToAxis: false,
|
||||
forceToAxis: true,
|
||||
releaseOnEdges: true,
|
||||
sensitivity: 0.8,
|
||||
},
|
||||
@@ -108,14 +136,11 @@ const act = {
|
||||
type: 'progressbar',
|
||||
},
|
||||
breakpoints: {
|
||||
768: {
|
||||
480: {
|
||||
slidesPerView: 2,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 4,
|
||||
},
|
||||
1200: {
|
||||
slidesPerView: 5,
|
||||
740: {
|
||||
slidesPerView: 3,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
const entry = {
|
||||
template: /*language=HTML*/ `
|
||||
<div class="entry-wrapper">
|
||||
<div :class="['entry-section', 'entry-section-' + section.key]" v-for="section in entrySections" :key="section.key">
|
||||
<div class="entry-section-header">
|
||||
<div class="entry-section-title">
|
||||
<i :class="section.icon"></i>
|
||||
<span>{{ section.title }}</span>
|
||||
<em>/Applications</em>
|
||||
</div>
|
||||
<div class="portal-entry-header">
|
||||
<div class="portal-entry-tabs" role="tablist" aria-label="推荐入口">
|
||||
<button v-for="section in entrySections" :key="section.key"
|
||||
type="button" role="tab" :aria-selected="activeSection === section.key"
|
||||
:class="{active: activeSection === section.key}" @click="activeSection = section.key">{{ section.title }}</button>
|
||||
</div>
|
||||
<a class="portal-more" href="/platform/v4/apps">全部应用 <i class="fa fa-arrow-right" aria-hidden="true"></i></a>
|
||||
</div>
|
||||
<div :class="['entry-section', 'entry-section-' + section.key]" v-for="section in entrySections" :key="section.key" v-show="activeSection === section.key" role="tabpanel">
|
||||
|
||||
<div class="apps-container">
|
||||
<div class="app-grid">
|
||||
<div class="app-item"
|
||||
<div class="app-grid" tabindex="0" :aria-label="section.title + ',可横向滚动浏览'">
|
||||
<button type="button" class="app-item"
|
||||
v-for="(item, index) in section.list"
|
||||
:key="item.id || index"
|
||||
@click="openService(item, section.key)">
|
||||
@@ -20,8 +21,8 @@ const entry = {
|
||||
<img v-if="item.picIcon" class="app-icon-img" :src="item.picIcon" alt="" />
|
||||
<i v-else class="fa fa-cube app-icon-fallback"></i>
|
||||
</div>
|
||||
<div class="app-name">{{ item.name }}</div>
|
||||
</div>
|
||||
<div class="app-name" :title="item.name">{{ item.name }}</div>
|
||||
</button>
|
||||
<el-empty class="app-empty"
|
||||
v-if="!section.list || section.list.length === 0"
|
||||
description="暂无数据"
|
||||
@@ -34,6 +35,7 @@ const entry = {
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
activeSection: 'serv',
|
||||
hasMore: true,
|
||||
entries: {
|
||||
serv: [],
|
||||
@@ -127,11 +129,6 @@ const entry = {
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
/* 临时屏蔽“我的收藏”分组,保留原节点和数据逻辑便于恢复 */
|
||||
.entry-section-fav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.entry-section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -118,42 +118,51 @@ layout("/layouts/v4/baseLayout.html"){
|
||||
|
||||
</style>
|
||||
|
||||
<div class="v4-container" id="v4-home-app">
|
||||
<link rel="stylesheet" href="${base!}/assets/platform/css/home-portal.css?v=20260929-1" />
|
||||
|
||||
<div class="v4-container home-portal" id="v4-home-app">
|
||||
<!-- 首页banner -->
|
||||
<div class="section-banner">
|
||||
<div class="banner-img">
|
||||
<img :src="homeBannerList[0] || ''" alt=""/>
|
||||
<stats></stats>
|
||||
<div class="portal-top">
|
||||
<div class="portal-hero">
|
||||
<div class="portal-hero-inner">
|
||||
<div class="portal-hero-copy">
|
||||
<div class="portal-hero-eyebrow">教职工一站式服务平台</div>
|
||||
<h1>智慧工会系统</h1>
|
||||
<p>情系教职工,服务零距离</p>
|
||||
<div class="portal-values">
|
||||
<span><i class="fa fa-heart" aria-hidden="true"></i>服务职工</span>
|
||||
<span><i class="fa fa-users" aria-hidden="true"></i>凝聚职工</span>
|
||||
<span><i class="fa fa-leaf" aria-hidden="true"></i>关爱职工</span>
|
||||
<span><i class="fa fa-file-text" aria-hidden="true"></i>助力发展</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<user class="portal-member" :profile-only="true"></user>
|
||||
</div>
|
||||
|
||||
<div class="" style="padding-bottom: 20px">
|
||||
<user></user>
|
||||
|
||||
<div class="home-grid">
|
||||
<div class="portal-content">
|
||||
<div class="entry-card">
|
||||
<entry></entry>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="home-grid">
|
||||
<div class="home-section">
|
||||
<div class="portal-columns">
|
||||
<div class="home-section portal-panel portal-activities">
|
||||
<div class="home-section-header">
|
||||
<div class="home-section-title">
|
||||
<i class="fa fa-calendar"></i>
|
||||
<span>最新活动</span>
|
||||
<em>/Activities</em>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="portal-more" @click="$refs.homeActivities.browseNext()">浏览更多 <i class="fa fa-arrow-right" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
<div class="act-card">
|
||||
<act></act>
|
||||
<act ref="homeActivities"></act>
|
||||
</div>
|
||||
</div>
|
||||
<user ref="homeTodo" class="portal-todo"></user>
|
||||
<work-template class="portal-templates" v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"></work-template>
|
||||
<jcdt class="portal-news" :class="{'portal-news-wide': !$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])}" :list="websiteNews"></jcdt>
|
||||
</div>
|
||||
|
||||
<work-template v-if="$auth.hasRoleOr(['SYSADMIN','SCHOOL_UNION_ADMIN'])"></work-template>
|
||||
|
||||
<jcdt :list="websiteNews"></jcdt>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -2,42 +2,63 @@ const jcdt = {
|
||||
template: /*language=HTML*/ `
|
||||
<div class="jcdt-wrapper">
|
||||
<div class="jcdt-container">
|
||||
<el-carousel height="360px" :interval="10000" indicator-position="none">
|
||||
<el-carousel-item v-for="item,index in list" :key="index">
|
||||
<div class="jcdt-title">
|
||||
<span>{{ item.label }}</span>
|
||||
</div>
|
||||
<div class="jcdt-content">
|
||||
<div class="jcdt-list">
|
||||
<div class="jcdt-item" v-for="o,i in item.value" :key="i" @click="onLink(o)">
|
||||
<div class="date" v-if="o.time">
|
||||
<i class="el-icon-alarm-clock"></i>
|
||||
<span>{{o.time}}</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center">
|
||||
<div>
|
||||
|
||||
</div>
|
||||
<div class="title">{{o.text}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
<div class="portal-news-header">
|
||||
<el-dropdown @command="selectSection" trigger="click">
|
||||
<button type="button" class="portal-news-title"><i class="fa fa-bullhorn" aria-hidden="true"></i> {{ currentNews.label }} <i v-if="list.length > 1" class="fa fa-angle-down" aria-hidden="true"></i></button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item v-for="(section, index) in list" :key="index" :command="index">{{ section.label }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<div v-if="pageCount > 1" class="portal-news-pager" aria-label="动态分页">
|
||||
<span class="portal-news-count">共 {{ currentNews.value.length }} 条</span>
|
||||
<button type="button" :disabled="pageNumber === 1" title="上一页动态" aria-label="上一页动态" @click="pageNumber--"><i class="fa fa-angle-left" aria-hidden="true"></i></button>
|
||||
<span class="portal-news-page" aria-live="polite">{{ pageNumber }} / {{ pageCount }}</span>
|
||||
<button type="button" :disabled="pageNumber === pageCount" title="下一页动态" aria-label="下一页动态" @click="pageNumber++"><i class="fa fa-angle-right" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="portal-news-list">
|
||||
<button type="button" class="portal-news-row" v-for="(item, index) in visibleNews" :key="index" @click="onLink(item)">
|
||||
<time v-if="item.time" :title="item.time">{{ item.time.slice(5) }}</time>
|
||||
<span :title="item.text">{{ item.text }}</span>
|
||||
</button>
|
||||
<div v-if="!currentNews.value.length" class="portal-empty">暂无动态</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
data() {
|
||||
return {}
|
||||
return {activeIndex: 0, pageNumber: 1, pageSize: 3}
|
||||
},
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: []
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentNews() {
|
||||
// 默认遵循接口栏目顺序,不再按栏目名称优先选择。
|
||||
const section = this.list[this.activeIndex] || this.list[0]
|
||||
return section ? {label: section.label, value: section.value || []} : {label: '最新动态', value: []}
|
||||
},
|
||||
visibleNews() {
|
||||
const start = (this.pageNumber - 1) * this.pageSize
|
||||
return this.currentNews.value.slice(start, start + this.pageSize)
|
||||
},
|
||||
pageCount() {
|
||||
return Math.max(1, Math.ceil(this.currentNews.value.length / this.pageSize))
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
list() {
|
||||
this.selectSection(0)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectSection(index) {
|
||||
this.activeIndex = index
|
||||
this.pageNumber = 1
|
||||
},
|
||||
onLink(item) {
|
||||
const url = this.isHttpOrHttps(item.href) ? item.href : "https://xgh.cug.edu.cn/" + item.href
|
||||
window.open(url)
|
||||
@@ -47,6 +68,15 @@ const jcdt = {
|
||||
}
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
/* 每页固定三行,不因展开或末页条数变化撑高相邻的模板卡片。 */
|
||||
#v4-home-app .portal-news-list { min-height: 132px; }
|
||||
#v4-home-app .portal-news-list .portal-news-row { height: 44px; padding: 9px 0; }
|
||||
#v4-home-app .portal-news-pager { display: flex; flex-shrink: 0; align-items: center; gap: 8px; }
|
||||
#v4-home-app .portal-news-count { margin-right: 4px; color: #8a9aac; font-size: 12px; }
|
||||
#v4-home-app .portal-news-page { min-width: 32px; color: #637b96; text-align: center; font-size: 12px; font-variant-numeric: tabular-nums; }
|
||||
#v4-home-app .portal-news-pager button { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; border: 1px solid #e4edf7; border-radius: 6px; background: #fff; color: #1687f5; font-size: 18px; cursor: pointer; }
|
||||
#v4-home-app .portal-news-pager button:hover:not(:disabled) { border-color: #b9d8fb; background: #f0f7ff; }
|
||||
#v4-home-app .portal-news-pager button:disabled { border-color: #eef2f7; background: #f8fafc; color: #c3cedb; cursor: default; }
|
||||
.jcdt-wrapper {
|
||||
width: 100%;
|
||||
background-size: cover;
|
||||
|
||||
@@ -5,21 +5,22 @@ const workTemplate = {
|
||||
<div class="work-template-title">
|
||||
<i class="fa fa-clipboard"></i>
|
||||
<span>工作模板</span>
|
||||
<em>/Templates</em>
|
||||
</div>
|
||||
<button type="button" class="portal-more" @click="browseTemplates">更多模板 <i class="fa fa-arrow-right" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
<div class="work-template-card">
|
||||
<div v-if="templateList && templateList.length > 0" class="work-template-grid">
|
||||
<div class="work-template-item"
|
||||
<div ref="templateGrid" v-if="templateList && templateList.length > 0" class="work-template-grid">
|
||||
<button type="button" class="work-template-item"
|
||||
v-for="template in templateList"
|
||||
:key="template.id"
|
||||
@click="go(template)">
|
||||
<div class="work-template-icon">
|
||||
<img :src="template.templateIcon || template.cover || 'https://www.ncu.edu.cn/__local/8/52/2C/644986B4C9A030F7B65300178A6_8679CB08_18467.jpg'"
|
||||
alt="">
|
||||
<el-image :src="template.templateIcon || template.cover" fit="contain">
|
||||
<i slot="error" class="fa fa-clipboard" aria-hidden="true"></i>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="work-template-name">{{ template.templateName || template.name }}</div>
|
||||
</div>
|
||||
<div class="work-template-name" :title="template.templateName || template.name">{{ template.templateName || template.name }}</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="no-activity-placeholder">
|
||||
@@ -36,6 +37,13 @@ const workTemplate = {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
browseTemplates() {
|
||||
const grid = this.$refs.templateGrid
|
||||
if (!grid) return
|
||||
// 模板仍使用全部真实数据,横向翻页不截断管理员可用的入口。
|
||||
const atEnd = grid.scrollLeft + grid.clientWidth >= grid.scrollWidth - 2
|
||||
grid.scrollTo({left: atEnd ? 0 : grid.scrollLeft + grid.clientWidth, behavior: 'smooth'})
|
||||
},
|
||||
listTemplate() {
|
||||
this.$axios.post("/platform/home/listHomeTemplate").then((res) => {
|
||||
if (res.code === 0) {
|
||||
|
||||
@@ -4,13 +4,17 @@ const user = {
|
||||
<!-- 用户容器:左右布局 -->
|
||||
<div class="user-container">
|
||||
<!-- 左侧:用户信息卡片 -->
|
||||
<div class="user-info-card">
|
||||
<div v-if="profileOnly" class="user-info-card">
|
||||
<div class="portal-member-date"><i class="fa fa-calendar-o" aria-hidden="true"></i>{{ $moment().format('YYYY年MM月DD日') }} {{ ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'][$moment().day()] }}</div>
|
||||
<div class="user-details">
|
||||
<div class="user-name">${@auth.getPrincipalProperty('username')}</div>
|
||||
<div class="portal-member-heading">
|
||||
<span class="portal-member-avatar"><i class="fa fa-user" aria-hidden="true"></i></span>
|
||||
<div><div class="portal-member-welcome">欢迎回来</div><div class="user-name">${@auth.getPrincipalProperty('username')}</div></div>
|
||||
</div>
|
||||
|
||||
<div class="user-meta-grid">
|
||||
<div class="meta-row">
|
||||
<span class="meta-icon">🆔</span>
|
||||
<span class="meta-icon"><i class="fa fa-id-card-o" aria-hidden="true"></i></span>
|
||||
<div>
|
||||
<span class="meta-label">工号</span>
|
||||
<span class="meta-value">${@auth.getPrincipalProperty('loginname')}</span>
|
||||
@@ -18,7 +22,7 @@ const user = {
|
||||
</div>
|
||||
|
||||
<div class="meta-row">
|
||||
<span class="meta-icon">🏢</span>
|
||||
<span class="meta-icon"><i class="fa fa-building-o" aria-hidden="true"></i></span>
|
||||
<div>
|
||||
<span class="meta-label">单位信息</span>
|
||||
<span class="meta-value">
|
||||
@@ -33,11 +37,11 @@ const user = {
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-icon">🎭</span>
|
||||
<div class="meta-row meta-row-roles">
|
||||
<span class="meta-icon"><i class="fa fa-shield" aria-hidden="true"></i></span>
|
||||
<div>
|
||||
<span class="meta-label">角色</span>
|
||||
<span class="meta-value">{{ roleNames || '—' }}</span>
|
||||
<div class="portal-member-roles"><span v-for="(role, index) in roleTags" :key="index" class="portal-member-role">{{ role }}</span><span v-if="!roleTags.length" class="meta-value">—</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,10 +67,13 @@ const user = {
|
||||
</div>
|
||||
|
||||
<!-- 右侧:待办中心 -->
|
||||
<div class="todo-center">
|
||||
<div v-if="!profileOnly" class="todo-center">
|
||||
<!-- 标题和标签 -->
|
||||
<div class="header">
|
||||
<h3>待办中心</h3>
|
||||
<div class="portal-todo-heading">
|
||||
<h3><i class="fa fa-list-ul" aria-hidden="true"></i> 待办中心</h3>
|
||||
<a class="portal-more" :href="'/flow/todoCenter?status=' + activeTab" target="_blank">全部待办 <i class="fa fa-arrow-right" aria-hidden="true"></i></a>
|
||||
</div>
|
||||
<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>
|
||||
@@ -75,54 +82,41 @@ const user = {
|
||||
</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 class="portal-task-list" v-loading="loading">
|
||||
<div class="portal-task-row" v-for="(task, index) in todoList" :key="task.taskId || task.instanceId || index">
|
||||
<i class="fa fa-file-text-o portal-task-icon" aria-hidden="true"></i>
|
||||
<div class="portal-task-content">
|
||||
<div class="portal-task-title" :title="task.instanceName">{{ task.instanceName }}</div>
|
||||
<div class="portal-task-meta">
|
||||
<span :title="task.variable && task.variable.initiatorName">申请人:{{ (task.variable && task.variable.initiatorName) || '—' }}</span>
|
||||
<span class="portal-task-node" :title="[task.categoryName, task.taskName].filter(Boolean).join(' · ')">{{ [task.categoryName, task.taskName].filter(Boolean).join(' · ') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<time class="portal-task-date">{{ task.createdAt ? $moment(task.createdAt).format('YYYY-MM-DD') : '—' }}</time>
|
||||
<el-button type="primary" size="mini" @click="openView(task)">查看</el-button>
|
||||
</div>
|
||||
<div v-if="!loading && !todoList.length" class="portal-empty"><i class="fa fa-check-circle-o" aria-hidden="true"></i><span>暂无{{ activeTab === 'todo' ? '待办事项' : '相关记录' }}</span></div>
|
||||
</div>
|
||||
<el-pagination v-if="pageForm.totalCount > pageForm.pageSize" class="portal-task-pagination"
|
||||
@current-change="pageNumberChange" :current-page="pageForm.pageNumber" :page-size="pageForm.pageSize"
|
||||
layout="total, prev, next" :total="pageForm.totalCount"></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
mixins: [initTableMixins],
|
||||
// 同一组件分别承载会员卡和待办卡,各自只加载需要的数据。
|
||||
props: {
|
||||
profileOnly: { type: Boolean, default: false }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'todo',
|
||||
todoList: [],
|
||||
loading: false,
|
||||
pageForm: {
|
||||
pageNum: 1,
|
||||
pageSize: 5,
|
||||
pageNumber: 1,
|
||||
pageSize: 3,
|
||||
totalCount: 0
|
||||
},
|
||||
taskStats: {
|
||||
@@ -140,6 +134,12 @@ const user = {
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
roleTags() {
|
||||
// 兼容角色接口已有的中英文分隔符,仅改变展示,不改变角色权限。
|
||||
return String(this.roleNames || '').split(/[,,、;;]/).map(role => role.trim()).filter(Boolean)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getWeatherInfo(iconCode, temp) {
|
||||
const info = {
|
||||
@@ -268,6 +268,7 @@ const user = {
|
||||
this.getStatistics()
|
||||
},
|
||||
handleTabClick(tab) {
|
||||
this.pageForm.pageNumber = 1
|
||||
this.pageData()
|
||||
console.log('切换到:', tab.name);
|
||||
},
|
||||
@@ -291,13 +292,42 @@ const user = {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.pageData()
|
||||
this.getRoleNames()
|
||||
if (this.profileOnly) {
|
||||
this.getRoleNames()
|
||||
} else {
|
||||
this.pageData()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchWeather()
|
||||
if (this.profileOnly) this.fetchWeather()
|
||||
},
|
||||
style: /*language=CSS*/ `
|
||||
/* 会员卡样式随组件注入,确保与卡片结构同步加载,避免旧外链样式造成排版缺失。 */
|
||||
#v4-home-app .portal-member { min-width: 0; }
|
||||
#v4-home-app .portal-member .user-info-card { height: 100%; padding: 20px; gap: 14px; border: 1px solid #e3edf8; border-radius: 12px; background: linear-gradient(180deg, #f1f7ff 0, #fff 110px); box-shadow: 0 3px 14px rgba(30,66,108,.035); }
|
||||
#v4-home-app .portal-member-date { display: flex; align-items: center; gap: 8px; color: #71839b; font-size: 12px; line-height: 20px; }
|
||||
#v4-home-app .portal-member-heading { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid #eaf0f7; }
|
||||
#v4-home-app .portal-member-heading > div { min-width: 0; }
|
||||
#v4-home-app .portal-member-avatar { display: flex; align-items: center; justify-content: center; flex: 0 0 46px; height: 46px; border-radius: 50%; background: #e1eeff; color: #1687f5; font-size: 25px; }
|
||||
#v4-home-app .portal-member-welcome { margin-bottom: 3px; color: #8797a9; font-size: 12px; line-height: 18px; }
|
||||
#v4-home-app .portal-member .user-name { margin: 0; color: #163c61; text-align: left; font-size: 18px; line-height: 24px; overflow-wrap: anywhere; }
|
||||
#v4-home-app .portal-member .user-meta-grid { gap: 12px; margin: 0; }
|
||||
#v4-home-app .portal-member .meta-row { gap: 8px; }
|
||||
#v4-home-app .portal-member .meta-icon { min-width: 18px; color: #81a4c9; font-size: 14px; }
|
||||
#v4-home-app .portal-member .meta-row > div { display: grid; grid-template-columns: 54px minmax(0, 1fr); gap: 8px; min-width: 0; }
|
||||
#v4-home-app .portal-member .meta-label { margin: 0; color: #8995a5; font-size: 12px; line-height: 20px; }
|
||||
#v4-home-app .portal-member .meta-value { color: #283c54; font-size: 12px; font-weight: 400; line-height: 20px; overflow-wrap: anywhere; }
|
||||
#v4-home-app .portal-member .meta-row-roles > div { display: block; }
|
||||
#v4-home-app .portal-member-roles { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px; }
|
||||
#v4-home-app .portal-member-role { max-width: 100%; display: inline-block; padding: 3px 8px; border: 1px solid #e1ebf7; border-radius: 5px; background: #f3f7fc; color: #46617f; font-size: 12px; line-height: 18px; overflow-wrap: anywhere; }
|
||||
#v4-home-app .portal-member .weather-section { margin-top: auto; padding: 8px 10px; border-radius: 8px; background: #f0f7ff; color: #527494; }
|
||||
#v4-home-app .portal-member .weather-header { gap: 6px; }
|
||||
#v4-home-app .portal-member .weather-location,
|
||||
#v4-home-app .portal-member .weather-text { font-size: 12px; }
|
||||
#v4-home-app .portal-member .weather-emoji { font-size: 20px; }
|
||||
#v4-home-app .portal-member .weather-temp { font-size: 18px; }
|
||||
#v4-home-app .portal-member .weather-tip { margin-top: 4px; font-size: 11px; line-height: 18px; }
|
||||
#v4-home-app .portal-member .weather-error { margin-top: auto; padding: 8px; font-size: 12px; }
|
||||
.user-wrapper {
|
||||
width: 100%;
|
||||
background-color: #f5f7fa;
|
||||
|
||||
Reference in New Issue
Block a user