commit
This commit is contained in:
@@ -166,6 +166,44 @@ public class FlowTodoCenterController {
|
|||||||
return Result.success(pagination);
|
return Result.success(pagination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@SaCheckLogin
|
||||||
|
public Result completed(Integer pageNumber, Integer pageSize, String searchKeyword, String category) {
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
ins.id AS instanceId,
|
||||||
|
ins.processDefineId,
|
||||||
|
ins.state,
|
||||||
|
ins.businessNo,
|
||||||
|
ins.operator,
|
||||||
|
ins.variable,
|
||||||
|
ins.createdAt,
|
||||||
|
ins.variable ->> '$.instanceName' AS instanceName,
|
||||||
|
cat.`name` categoryName
|
||||||
|
FROM
|
||||||
|
wf_process_instance ins
|
||||||
|
LEFT JOIN wf_process_define def ON def.id = ins.processDefineId
|
||||||
|
LEFT JOIN wf_process_category cat ON cat.id = def.category
|
||||||
|
$condition
|
||||||
|
""");
|
||||||
|
Cnd cnd = Cnd.NEW();
|
||||||
|
cnd.and("ins.state", "=", 20);
|
||||||
|
cnd.and("ins.operator", "=", SecurityUtil.getUserId());
|
||||||
|
if (StrUtil.isNotBlank(searchKeyword)) {
|
||||||
|
cnd.where().andLike("ins.variable ->> '$.instanceName'", searchKeyword);
|
||||||
|
}
|
||||||
|
cnd.groupBy("ins.id");
|
||||||
|
cnd.desc("ins.createdAt");
|
||||||
|
sql.setCondition(cnd);
|
||||||
|
Pagination pagination = sysUserService.listPageMap(pageNumber, pageSize, sql);
|
||||||
|
List<NutMap> list = pagination.getList();
|
||||||
|
for (NutMap row : list) {
|
||||||
|
NutMap variable = Json.fromJson(NutMap.class, row.getString("variable"));
|
||||||
|
row.put("variable", variable);
|
||||||
|
}
|
||||||
|
return Result.success(pagination);
|
||||||
|
}
|
||||||
|
|
||||||
@At
|
@At
|
||||||
@SaCheckLogin
|
@SaCheckLogin
|
||||||
public Result statistics() {
|
public Result statistics() {
|
||||||
|
|||||||
@@ -264,13 +264,13 @@ public class SysHomeController {
|
|||||||
// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24)
|
// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24)
|
||||||
public Result getNews() {
|
public Result getNews() {
|
||||||
// 定义要爬取的URL
|
// 定义要爬取的URL
|
||||||
String domain = "https://cdgh.ncu.edu.cn/";
|
String domain = "https://gh.hgu.edu.cn/index.htm";
|
||||||
try {
|
try {
|
||||||
// 使用Jsoup连接到URL并获取页面内容
|
// 使用Jsoup连接到URL并获取页面内容
|
||||||
Document doc = Jsoup.connect(domain).get();
|
Document doc = Jsoup.connect(domain).get();
|
||||||
|
|
||||||
JSONObject root = new JSONObject();
|
JSONObject root = new JSONObject();
|
||||||
|
/*
|
||||||
// 1. 新闻快讯(来自 .list1)
|
// 1. 新闻快讯(来自 .list1)
|
||||||
List<JSONObject> newsArray = new ArrayList<>();
|
List<JSONObject> newsArray = new ArrayList<>();
|
||||||
Elements newsItems = doc.select(".group1 .list1 li");
|
Elements newsItems = doc.select(".group1 .list1 li");
|
||||||
@@ -328,7 +328,7 @@ public class SysHomeController {
|
|||||||
node.set("image", domain + imageUrl);
|
node.set("image", domain + imageUrl);
|
||||||
grassrootsArray.add(node);
|
grassrootsArray.add(node);
|
||||||
}
|
}
|
||||||
root.set("grassroots", grassrootsArray);
|
root.set("grassroots", grassrootsArray);*/
|
||||||
return Result.success(root);
|
return Result.success(root);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(e);
|
log.error(e);
|
||||||
|
|||||||
@@ -504,4 +504,25 @@ public class SysRoleController {
|
|||||||
return Result.success(Daos.ext(sysRoleService.dao(), fieldFilter).query(Sys_menu.class, cnd));
|
return Result.success(Daos.ext(sysRoleService.dao(), fieldFilter).query(Sys_menu.class, cnd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@At
|
||||||
|
@Ok("json:full")
|
||||||
|
@SaCheckLogin
|
||||||
|
public Result getRoleNames(){
|
||||||
|
Sql sql = Sqls.create("""
|
||||||
|
SELECT
|
||||||
|
GROUP_CONCAT(DISTINCT sr.`name`) roleNames
|
||||||
|
FROM
|
||||||
|
`sys_user_role` sur
|
||||||
|
LEFT JOIN sys_role sr ON sr.id = sur.roleId
|
||||||
|
WHERE
|
||||||
|
sur.userId = @userId
|
||||||
|
ORDER BY
|
||||||
|
sr.sort DESC
|
||||||
|
""").setParam("userId", SecurityUtil.getUserId());
|
||||||
|
sql.setCallback(Sqls.callback.map());
|
||||||
|
sysRoleService.dao().execute(sql);
|
||||||
|
return Result.success(sql.getResult());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class SysV4AppsController {
|
|||||||
Map<String, Object> category = new HashMap<>();
|
Map<String, Object> category = new HashMap<>();
|
||||||
category.put("id", module.getId());
|
category.put("id", module.getId());
|
||||||
category.put("name", module.getName());
|
category.put("name", module.getName());
|
||||||
category.put("icon", module.getFaIcon());
|
category.put("icon", module.getIcon());
|
||||||
return category;
|
return category;
|
||||||
}).toList();
|
}).toList();
|
||||||
return Result.success("获取应用分类成功").addData(categories);
|
return Result.success("获取应用分类成功").addData(categories);
|
||||||
@@ -67,10 +67,11 @@ public class SysV4AppsController {
|
|||||||
Sql sql = Sqls.create("""
|
Sql sql = Sqls.create("""
|
||||||
SELECT
|
SELECT
|
||||||
m.id,
|
m.id,
|
||||||
m.name,
|
m.`name`,
|
||||||
m.href,
|
m.href,
|
||||||
m.icon,
|
m.icon,
|
||||||
m.picIcon,
|
m.picIcon,
|
||||||
|
sm.`name` AS moduleName,
|
||||||
CASE
|
CASE
|
||||||
WHEN f.userId IS NOT NULL THEN
|
WHEN f.userId IS NOT NULL THEN
|
||||||
1 ELSE 0
|
1 ELSE 0
|
||||||
@@ -79,6 +80,7 @@ public class SysV4AppsController {
|
|||||||
sys_menu m
|
sys_menu m
|
||||||
LEFT JOIN sys_user_favorite_app f ON m.id = f.appId
|
LEFT JOIN sys_user_favorite_app f ON m.id = f.appId
|
||||||
AND f.userId = @userId
|
AND f.userId = @userId
|
||||||
|
LEFT JOIN sys_module sm ON sm.id = m.moduleId
|
||||||
$condition
|
$condition
|
||||||
""");
|
""");
|
||||||
Cnd cnd = Cnd.NEW();
|
Cnd cnd = Cnd.NEW();
|
||||||
@@ -138,10 +140,11 @@ public class SysV4AppsController {
|
|||||||
Sql sql = Sqls.create("""
|
Sql sql = Sqls.create("""
|
||||||
SELECT
|
SELECT
|
||||||
m.id,
|
m.id,
|
||||||
m.name,
|
m.`name`,
|
||||||
m.href,
|
m.href,
|
||||||
m.icon,
|
m.icon,
|
||||||
m.picIcon,
|
m.picIcon,
|
||||||
|
sm.`name` AS moduleName,
|
||||||
1 AS isFavorite
|
1 AS isFavorite
|
||||||
FROM
|
FROM
|
||||||
sys_user_favorite_app f
|
sys_user_favorite_app f
|
||||||
@@ -149,6 +152,7 @@ public class SysV4AppsController {
|
|||||||
sys_menu m
|
sys_menu m
|
||||||
ON
|
ON
|
||||||
f.appId = m.id
|
f.appId = m.id
|
||||||
|
LEFT JOIN sys_module sm ON sm.id = m.moduleId
|
||||||
WHERE
|
WHERE
|
||||||
f.userId = @userId
|
f.userId = @userId
|
||||||
AND m.platform = 'PC'
|
AND m.platform = 'PC'
|
||||||
|
|||||||
@@ -468,9 +468,9 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService
|
|||||||
|
|
||||||
// 生成变更信息描述
|
// 生成变更信息描述
|
||||||
String changeInfos = changeList.stream()
|
String changeInfos = changeList.stream()
|
||||||
.map(v -> v.getString("fieldName") + ":" +
|
.map(v -> v.getString("fieldName", "") + ":" +
|
||||||
HtmlUtil.cleanHtmlTag(v.getString("sourceValue")) + "→" +
|
HtmlUtil.cleanHtmlTag(v.getString("sourceValue", "")) + "→" +
|
||||||
HtmlUtil.cleanHtmlTag(v.getString("newValue")))
|
HtmlUtil.cleanHtmlTag(v.getString("newValue", "")))
|
||||||
.collect(Collectors.joining(";"));
|
.collect(Collectors.joining(";"));
|
||||||
|
|
||||||
// 设置历史记录信息
|
// 设置历史记录信息
|
||||||
|
|||||||
+1
-1
@@ -397,7 +397,7 @@ public class MemberManageServiceImpl extends BaseServiceImpl<Sys_user> implement
|
|||||||
// 如果有工会关系变更,也需要记录变更了什么工会
|
// 如果有工会关系变更,也需要记录变更了什么工会
|
||||||
history.setChangeInfos(changeList);
|
history.setChangeInfos(changeList);
|
||||||
String changeInfos = changeList.stream().map(v -> {
|
String changeInfos = changeList.stream().map(v -> {
|
||||||
return v.getString("fieldName") + ":" + HtmlUtil.cleanHtmlTag(v.getString("sourceValue")) + "->" + HtmlUtil.cleanHtmlTag(v.getString("newValue"));
|
return v.getString("fieldName") + ":" + HtmlUtil.cleanHtmlTag(v.getString("sourceValue", "")) + "->" + HtmlUtil.cleanHtmlTag(v.getString("newValue", ""));
|
||||||
}).collect(Collectors.joining(";"));
|
}).collect(Collectors.joining(";"));
|
||||||
history.setChangeInfosStr(changeInfos);
|
history.setChangeInfosStr(changeInfos);
|
||||||
dao().updateIgnoreNull(info);
|
dao().updateIgnoreNull(info);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const commonUtil = {
|
|||||||
if (response.config.responseType === "blob") {
|
if (response.config.responseType === "blob") {
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
if (response.data && response.data.code !== 0 && response.data.code !== 99) {
|
if (response.data && response.data.code !== "200" && response.data.code !== 0 && response.data.code !== 99) {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
vant.Toast.fail(response.data.msg)
|
vant.Toast.fail(response.data.msg)
|
||||||
} else {
|
} else {
|
||||||
@@ -318,7 +318,7 @@ function base64ToFile(base64Data, filename) {
|
|||||||
return new File([blob], filename, {type: contentType})
|
return new File([blob], filename, {type: contentType})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createLoading(text= '加载中...'){
|
function createLoading(text = '加载中...') {
|
||||||
return ELEMENT.Loading.service({
|
return ELEMENT.Loading.service({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: text,
|
text: text,
|
||||||
|
|||||||
@@ -3,47 +3,52 @@ const act = {
|
|||||||
<!-- 活动 -->
|
<!-- 活动 -->
|
||||||
<div class="section-wrapper">
|
<div class="section-wrapper">
|
||||||
<div class="section-act">
|
<div class="section-act">
|
||||||
<!-- 标题 -->
|
|
||||||
<div class="section-act-title">
|
|
||||||
<span>工会活动</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Swiper容器 -->
|
<!-- Swiper容器 -->
|
||||||
<div class="activity-swiper-container">
|
|
||||||
<!-- 活动数据 - Swiper -->
|
<div v-if="actList && actList.length > 0" class="activity-swiper-container">
|
||||||
<div class="swiper activity-swiper">
|
<div class="activity-swiper-container">
|
||||||
<div class="swiper-wrapper">
|
<!-- 活动数据 - Swiper -->
|
||||||
<div class="swiper-slide" v-for="(activity, index) in actList" :key="activity.id">
|
<div class="swiper activity-swiper">
|
||||||
<div class="item" @click="go(activity)">
|
<div class="swiper-wrapper">
|
||||||
<div class="img-box">
|
<div class="swiper-slide" v-for="(activity, index) in actList" :key="activity.id">
|
||||||
<img :src="activity.cover || 'https://www.ncu.edu.cn/__local/8/52/2C/644986B4C9A030F7B65300178A6_8679CB08_18467.jpg'"
|
<div class="item" @click="go(activity)">
|
||||||
alt="">
|
<div class="img-box">
|
||||||
<span class="status">
|
<img :src="activity.cover || 'https://www.ncu.edu.cn/__local/8/52/2C/644986B4C9A030F7B65300178A6_8679CB08_18467.jpg'"
|
||||||
|
alt="">
|
||||||
|
<span class="status">
|
||||||
{{getStatusText(activity)}}
|
{{getStatusText(activity)}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<h4 class="title">
|
<h4 class="title">
|
||||||
{{ activity.name}}
|
{{ activity.name}}
|
||||||
</h4>
|
</h4>
|
||||||
<!--报名时间-->
|
<!--报名时间-->
|
||||||
<div class="time">
|
<div class="time">
|
||||||
<p>
|
<p>
|
||||||
<i class="fa fa-clock-o"></i>
|
<i class="fa fa-clock-o"></i>
|
||||||
时间:{{ activity.startDate }}至{{ activity.endDate }}
|
时间:{{ activity.startDate }}至{{ activity.endDate }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 导航按钮 -->
|
<!-- 导航按钮 -->
|
||||||
<div class="swiper-button-next"></div>
|
<div class="swiper-button-next"></div>
|
||||||
<div class="swiper-button-prev"></div>
|
<div class="swiper-button-prev"></div>
|
||||||
|
|
||||||
<!-- 进度条 -->
|
<!-- 进度条 -->
|
||||||
<div class="swiper-pagination"></div>
|
<div class="swiper-pagination"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="no-activity-placeholder">
|
||||||
|
<div class="icon">📅</div>
|
||||||
|
<p>暂无近期活动</p>
|
||||||
|
<p class="subtext">敬请关注后续通知</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
@@ -86,13 +91,13 @@ const act = {
|
|||||||
},
|
},
|
||||||
breakpoints: {
|
breakpoints: {
|
||||||
768: {
|
768: {
|
||||||
slidesPerView: 2,
|
slidesPerView: 1,
|
||||||
},
|
},
|
||||||
1024: {
|
1024: {
|
||||||
slidesPerView: 3,
|
slidesPerView: 2,
|
||||||
},
|
},
|
||||||
1200: {
|
1200: {
|
||||||
slidesPerView: 4,
|
slidesPerView: 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -125,12 +130,6 @@ const act = {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-act {
|
|
||||||
width: 80%;
|
|
||||||
max-width: 80%;
|
|
||||||
margin: 30px auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-act .section-act-title span {
|
.section-act .section-act-title span {
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
@@ -172,12 +171,13 @@ const act = {
|
|||||||
.activity-swiper-container {
|
.activity-swiper-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 30px;
|
padding: 20px;
|
||||||
|
/*margin-top: 30px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.activity-swiper {
|
.activity-swiper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0 50px 20px 50px;
|
/*padding: 0 50px 20px 50px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.activity-swiper .swiper-slide {
|
.activity-swiper .swiper-slide {
|
||||||
@@ -235,6 +235,7 @@ const act = {
|
|||||||
.activity-swiper .swiper-slide .item .img-box {
|
.activity-swiper .swiper-slide .item .img-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -282,13 +283,13 @@ const act = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.activity-swiper .swiper-slide .item .time {
|
.activity-swiper .swiper-slide .item .time {
|
||||||
margin-top: 8px;
|
/*margin-top: 8px;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.activity-swiper .swiper-slide .item .time p {
|
.activity-swiper .swiper-slide .item .time p {
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
line-height: 1.5;
|
/*line-height: 1.5;*/
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,5 +297,34 @@ const act = {
|
|||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 无活动占位提示 */
|
||||||
|
.no-activity-placeholder {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 40px 20px;
|
||||||
|
color: #94a3b8;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-activity-placeholder .icon {
|
||||||
|
font-size: 48px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-activity-placeholder p {
|
||||||
|
margin: 4px 0 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-activity-placeholder .subtext {
|
||||||
|
font-size: 13px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,45 +1,35 @@
|
|||||||
const entry = {
|
const entry = {
|
||||||
template: /*language=HTML*/ `
|
template: /*language=HTML*/ `
|
||||||
<div class="entry-wrapper">
|
<div class="entry-wrapper">
|
||||||
<div class="entry-title">
|
<!-- 标签页导航 -->
|
||||||
<span>常用入口</span>
|
<div class="tabs">
|
||||||
</div>
|
<div class="tab-item" :class="{ active: activeCategory === 'serv' }"
|
||||||
|
@click="setActiveCategory('serv')">
|
||||||
|
<i class="fa fa-star"></i> 推荐服务
|
||||||
|
</div>
|
||||||
|
<div class="tab-item" :class="{ active: activeCategory === 'app' }"
|
||||||
|
@click="setActiveCategory('app')">
|
||||||
|
<i class="fa fa-fire"></i> 推荐应用
|
||||||
|
</div>
|
||||||
|
<div class="tab-item" :class="{ active: activeCategory === 'fav' }"
|
||||||
|
@click="setActiveCategory('fav')">
|
||||||
|
<i class="fa fa-heart"></i> 我的收藏
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="entry-container">
|
<!-- 应用块区域 -->
|
||||||
<!-- 左侧分类导航 -->
|
<div class="apps-container">
|
||||||
<div class="sidebar">
|
<div class="app-grid">
|
||||||
<div class="category" :class="{active: activeCategory === 'serv'}"
|
<div class="app-item" v-for="(item, index) in currentServices" :key="index"
|
||||||
@click="setActiveCategory('serv')">
|
@click="openService(item)">
|
||||||
<i class="fa fa-star"></i>
|
<div class="app-icon">
|
||||||
<span>推荐服务</span>
|
<img :src="item.picIcon" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div class="category" :class="{active: activeCategory === 'app'}" @click="setActiveCategory('app')">
|
<div class="app-name">{{ item.name }}</div>
|
||||||
<i class="fa fa-fire"></i>
|
</div>
|
||||||
<span>推荐应用</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="category" :class="{active: activeCategory === 'fav'}"
|
</div>
|
||||||
@click="setActiveCategory('fav')">
|
|
||||||
<i class="fa fa-heart"></i>
|
|
||||||
<span>收藏服务</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 右侧服务卡片区域 -->
|
|
||||||
<div class="content">
|
|
||||||
<div class="services-grid">
|
|
||||||
<div class="service-card" v-for="(service, index) in currentServices" :key="index"
|
|
||||||
@click="openService(service)">
|
|
||||||
<div class="service-icon">
|
|
||||||
<img :src="service.picIcon">
|
|
||||||
</div>
|
|
||||||
<div class="service-info">
|
|
||||||
<h4 class="service-name">{{ service.name }}</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`,
|
`,
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -128,194 +118,131 @@ const entry = {
|
|||||||
style: /*language=CSS*/ `
|
style: /*language=CSS*/ `
|
||||||
.entry-wrapper {
|
.entry-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-image: url(https://www.ncu.edu.cn/images/bbg1.jpg);
|
box-sizing: border-box;
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-title {
|
.tabs {
|
||||||
font-size: 30px;
|
margin-top: 5px;
|
||||||
color: #000000;
|
|
||||||
display: block;
|
|
||||||
font-weight: bold;
|
|
||||||
position: relative;
|
|
||||||
text-align: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/deep/ .entry-title span::before {
|
|
||||||
content: '';
|
|
||||||
width: 24px;
|
|
||||||
height: 11px;
|
|
||||||
background: url(https://www.ncu.edu.cn/images/titl.svg) no-repeat center;
|
|
||||||
background-size: 24px 11px;
|
|
||||||
display: inline-block;
|
|
||||||
margin-right: 0;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/deep/ .entry-title span::after {
|
|
||||||
content: '';
|
|
||||||
width: 24px;
|
|
||||||
height: 11px;
|
|
||||||
background: url(https://www.ncu.edu.cn/images/titr.svg) no-repeat center;
|
|
||||||
background-size: 24px 11px;
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: 0;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-container {
|
|
||||||
width: 80%;
|
|
||||||
max-width: 80%;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 20px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 30px;
|
gap: 20px;
|
||||||
overflow: hidden;
|
margin-bottom: 20px;
|
||||||
|
border-bottom: 2px solid #e8e8e8;
|
||||||
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.tab-item {
|
||||||
width: 200px;
|
display: flex;
|
||||||
flex-shrink: 0;
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
cursor: pointer;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item:hover {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item.active {
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 2px solid #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.apps-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 12px 16px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
border-left: 3px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category:hover {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.category.active {
|
|
||||||
color: var(--color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.category i {
|
|
||||||
font-size: 14px;
|
|
||||||
margin-right: 10px;
|
|
||||||
width: 16px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category span {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
flex: 1;
|
|
||||||
height: 164px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.services-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
grid-template-rows: repeat(2, 1fr);
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card {
|
.app-grid {
|
||||||
padding: 12px;
|
display: grid;
|
||||||
height: 72px;
|
/* 改为自适应列数:每格最小 80px,自动换行 */
|
||||||
cursor: pointer;
|
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
border: none;
|
justify-items: center; /* 子项内容居中(图标和文字) */
|
||||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYEAAAB4CAYAAAAUs05BAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAANrSURBVHgB7dzNapNZAMfh0zbNYGgosYql4wiCFEEZXLiYG3DrdryPuQbvpXMB7t24m4UOCiKuEtCKsaVNiTRaXhshLvyoSd/Yzf95oORA827PLycn5yxsdZ/crKql+6WG1uLy0d3Lm29Pes+jfm+1N9w/VwD4qXtXbmyf9P/Hu29Wng/6K6WOqnq6WACI1ZgM1pqt0Z31qztlBoMPh0sPXr+8OMsztzsbe9fanfcFgG9sdZ+tz/L+6+0LB7c6lw5meWZ7OGg+7HfPj8dWAgDBRAAgmAgABBMBgGAiABBMBACCiQBAsIV5nBiehXMCAD826zmBWpwYBsi2UFXV5vHrP6WGycnhae4QAuD0JncGneak8He8sBIACCYCAMEa//b+bx5vDJ/dRgQAtY2/EprDVdJ9KwGAYLWukgbgbI03g+tuCLtKGoDPRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEKwxGbwbDZtb3WfrpYbW4vLR3cubbwsAv8Tj3Tcrzwf9lTInVgIAwRp///Hn6Ph1u9Qw+HC49OD1y4sFgDNxvX3h4Fbn0kGpZ8dKACCYCAAEW9jqPrlZVUv3yymtNVujv9Y29qb9Ouh2Z2PvWrvzvgDwjWl+oLM/OlwefBw1fm+1682lVfXUSgAg2JefiI4/0d9Zv7oz7YPbw0HzYb97fjxuL/92dO/KjRM3lx/1e6u94f65AsBPnTSnTubfWeftr58fj60EAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgc71Kehr/7b5aHf8VAGqZx7xtJQAQ7BOP4saDQA2PwQAAAABJRU5ErkJggg==) no-repeat;
|
justify-content: start; /* 整体网格靠左对齐,避免居中 */
|
||||||
background-size: 100% 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
max-height: calc(350px - 74px);
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-card:hover {
|
.app-item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-icon {
|
.app-item:hover {
|
||||||
width: 32px;
|
transform: translateY(-2px);
|
||||||
height: 32px;
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-icon img {
|
.app-icon {
|
||||||
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-icon img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-radius: 4px;
|
object-fit: contain;
|
||||||
object-fit: cover;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.service-info {
|
.app-name {
|
||||||
flex: 1;
|
font-size: 12px;
|
||||||
min-width: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.service-name {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #333;
|
color: #333;
|
||||||
margin: 0;
|
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
white-space: nowrap;
|
word-break: break-word;
|
||||||
overflow: hidden;
|
text-align: center;
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 响应式设计 */
|
/* 响应式设计 */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.entry-container {
|
.tabs {
|
||||||
flex-direction: column;
|
flex-wrap: wrap;
|
||||||
gap: 20px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.tab-item {
|
||||||
width: 100%;
|
padding: 8px 0;
|
||||||
display: flex;
|
font-size: 12px;
|
||||||
overflow-x: auto;
|
|
||||||
gap: 0;
|
|
||||||
border-bottom: 1px solid #e8e8e8;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category {
|
.app-grid {
|
||||||
flex-shrink: 0;
|
grid-template-columns: repeat(2, 1fr);
|
||||||
margin-bottom: 0;
|
gap: 15px;
|
||||||
white-space: nowrap;
|
|
||||||
border-left: none;
|
|
||||||
border-bottom: 3px solid transparent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.category.active {
|
.app-item {
|
||||||
border-left: none;
|
padding: 12px;
|
||||||
border-bottom-color: #1890ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.services-grid {
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 480px) {
|
@media (max-width: 480px) {
|
||||||
.services-grid {
|
.app-grid {
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
gap: 12px;
|
||||||
|
|
||||||
.service-card {
|
|
||||||
padding: 12px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
#-->
|
#-->
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.section-banner {
|
.section-banner {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -23,37 +24,71 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.act-wrapper{
|
.home-grid {
|
||||||
width: 100%;
|
width: 80%;
|
||||||
background-image: url(https://www.ncu.edu.cn/images/bbg1.jpg);
|
margin: 20px auto;
|
||||||
background-size: cover;
|
display: grid;
|
||||||
background-position: center center;
|
/*grid-template-columns: 2.2fr 0.8fr;*/
|
||||||
background-repeat: no-repeat;
|
gap: 24px;
|
||||||
|
align-items: stretch;
|
||||||
|
row-gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entry-card {
|
||||||
|
display: flex;
|
||||||
|
/*align-items: 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry-card:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 16px rgba(0,0,0,0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.act-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: 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;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<div class="v4-container" id="v4-home-app">
|
<div class="v4-container" id="v4-home-app">
|
||||||
<!-- 首页banner -->
|
<!-- 首页banner -->
|
||||||
<div class="section-banner">
|
<div class="section-banner">
|
||||||
<div class="banner-img">
|
<div class="banner-img">
|
||||||
<img src="${config.AppHomeImg!}" alt=""/>
|
<img src="${config.AppHomeImg!}" alt=""/>
|
||||||
|
<stats></stats>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<user></user>
|
<div class="">
|
||||||
|
<user></user>
|
||||||
|
|
||||||
<entry></entry>
|
<div class="home-grid">
|
||||||
|
<div class="entry-card">
|
||||||
|
<entry></entry>
|
||||||
|
</div>
|
||||||
|
<div class="act-card">
|
||||||
|
<act></act>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 工会活动 -->
|
|
||||||
<div class="section-wrapper act-wrapper">
|
</div>
|
||||||
<act/>
|
|
||||||
|
<!-- <jcdt :list="websiteNews.grassroots"></jcdt>-->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <jcdt :list="websiteNews.grassroots"></jcdt>-->
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -61,6 +96,9 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
<!--#include("jcdt.js"){}#-->
|
<!--#include("jcdt.js"){}#-->
|
||||||
<!--#include("entry.js"){}#-->
|
<!--#include("entry.js"){}#-->
|
||||||
<!--#include("user.js"){}#-->
|
<!--#include("user.js"){}#-->
|
||||||
|
|
||||||
|
<!--#include("stats.js"){}#-->
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#v4-home-app',
|
el: '#v4-home-app',
|
||||||
data(){
|
data(){
|
||||||
@@ -75,6 +113,7 @@ layout("/layouts/v4/baseLayout.html"){
|
|||||||
'jcdt': jcdt,
|
'jcdt': jcdt,
|
||||||
'entry': entry,
|
'entry': entry,
|
||||||
'user': user,
|
'user': user,
|
||||||
|
'stats': stats,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getWebSiteNews()
|
this.getWebSiteNews()
|
||||||
|
|||||||
@@ -2,18 +2,19 @@ const jcdt = {
|
|||||||
template: /*language=HTML*/ `
|
template: /*language=HTML*/ `
|
||||||
<div class="jcdt-wrapper">
|
<div class="jcdt-wrapper">
|
||||||
<div class="jcdt-container">
|
<div class="jcdt-container">
|
||||||
<div class="jcdt-title">
|
<!-- <div class="jcdt-title">-->
|
||||||
<span>基层动态</span>
|
<!-- <span>基层动态</span>-->
|
||||||
</div>
|
<!-- </div> -->
|
||||||
<div class="jcdt-content">
|
<div class="jcdt-content">
|
||||||
<div class="jcdt-list">
|
<div class="jcdt-list">
|
||||||
<div class="jcdt-item" v-for="item in list" :key="item.title" @click="onLink(item)">
|
<div class="jcdt-item" v-for="item in list" :key="item.title" @click="onLink(item)">
|
||||||
<div class="date">{{item.date}}</div>
|
<div class="date" v-if="item.date">{{item.date}}</div>
|
||||||
<div class="title">{{item.title}}</div>
|
<div class="title">{{item.title}}</div>
|
||||||
<div class="image">
|
<!--<div class="image">
|
||||||
<img :src="item.image" alt="">
|
<img v-if="item.image" :src="item.image" alt="">
|
||||||
</div>
|
<img v-else src="/assets/platform/img/v4/not-image.png" alt="">
|
||||||
<div class="summary">{{item.summary}}</div>
|
</div>-->
|
||||||
|
<!-- <div class="summary">{{item.summary}}</div>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -38,7 +39,6 @@ const jcdt = {
|
|||||||
style: /*language=CSS*/ `
|
style: /*language=CSS*/ `
|
||||||
.jcdt-wrapper {
|
.jcdt-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-image: url(https://cdgh.ncu.edu.cn/images/index_bg2.png);
|
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
@@ -48,6 +48,12 @@ const jcdt = {
|
|||||||
width: 80%;
|
width: 80%;
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
.jcdt-title{
|
.jcdt-title{
|
||||||
@@ -57,7 +63,7 @@ const jcdt = {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px 0;
|
padding: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .jcdt-container .jcdt-title span::before {
|
/deep/ .jcdt-container .jcdt-title span::before {
|
||||||
@@ -97,6 +103,8 @@ const jcdt = {
|
|||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
||||||
|
border-radius: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jcdt-item:hover{
|
.jcdt-item:hover{
|
||||||
@@ -161,4 +169,4 @@ const jcdt = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
`
|
`
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -0,0 +1,196 @@
|
|||||||
|
const stats = {
|
||||||
|
template: /*language=HTML*/ `
|
||||||
|
<div class="stats-section">
|
||||||
|
<div class="stats-grid">
|
||||||
|
<!-- 待办 -->
|
||||||
|
<div
|
||||||
|
class="stat-item pending"
|
||||||
|
@click="handleStatClick('todo')"
|
||||||
|
@mouseenter="onMouseEnter"
|
||||||
|
@mouseleave="onMouseLeave"
|
||||||
|
>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i class="fa fa-clock-o"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-label">待办</div>
|
||||||
|
<div class="stat-number">{{ stats.todoCount }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 已办 -->
|
||||||
|
<div
|
||||||
|
class="stat-item completed"
|
||||||
|
@click="handleStatClick('done')"
|
||||||
|
@mouseenter="onMouseEnter"
|
||||||
|
@mouseleave="onMouseLeave"
|
||||||
|
>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i class="fa fa-check-circle"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-label">已办</div>
|
||||||
|
<div class="stat-number">{{ stats.doneCount }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 消息 -->
|
||||||
|
<div
|
||||||
|
class="stat-item messages"
|
||||||
|
@click="handleStatClick('notification')"
|
||||||
|
@mouseenter="onMouseEnter"
|
||||||
|
@mouseleave="onMouseLeave"
|
||||||
|
>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i class="fa fa-bell"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-label">消息</div>
|
||||||
|
<div class="stat-number">{{ stats.notifications }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 发起 -->
|
||||||
|
<div
|
||||||
|
class="stat-item reminders"
|
||||||
|
@click="handleStatClick('started')"
|
||||||
|
@mouseenter="onMouseEnter"
|
||||||
|
@mouseleave="onMouseLeave"
|
||||||
|
>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i class="fa fa-file-text"></i>
|
||||||
|
</div>
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-label">发起</div>
|
||||||
|
<div class="stat-number">{{ stats.startedCount }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
stats: {
|
||||||
|
todoCount: 0,
|
||||||
|
doneCount: 0,
|
||||||
|
notifications: 0,
|
||||||
|
startedCount: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleStatClick(type) {
|
||||||
|
if (['todo', 'done', 'started'].includes(type)) {
|
||||||
|
window.open('/flow/todoCenter?status=' + type)
|
||||||
|
} else if (type === 'notification') {
|
||||||
|
window.open('/platform/v4/msg')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onMouseEnter(event) {
|
||||||
|
event.target.style.transform = 'translateY(-2px)';
|
||||||
|
event.target.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
|
||||||
|
},
|
||||||
|
onMouseLeave(event) {
|
||||||
|
event.target.style.transform = 'none';
|
||||||
|
event.target.style.boxShadow = '0 2px 6px rgba(0,0,0,0.08)';
|
||||||
|
},
|
||||||
|
|
||||||
|
loadStats() {
|
||||||
|
this.$axios.post("/flow/todoCenter/statistics").then(res => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.stats = res.data;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.loadStats();
|
||||||
|
},
|
||||||
|
style: /*language=CSS*/ `
|
||||||
|
/* 右侧统计区域 */
|
||||||
|
.stats-section {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 24px;
|
||||||
|
right: 24px;
|
||||||
|
/*background: white;*/
|
||||||
|
color: #333;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
|
||||||
|
z-index: 10;
|
||||||
|
width: 680px;
|
||||||
|
/*border: 1px solid #e8e8e8;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
background: #f8f9fa;
|
||||||
|
color: #495057;
|
||||||
|
padding: 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.stat-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
background: #e6f7ff;
|
||||||
|
color: #1890ff;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item.pending .stat-icon,
|
||||||
|
.stat-item.completed .stat-icon,
|
||||||
|
.stat-item.messages .stat-icon,
|
||||||
|
.stat-item.reminders .stat-icon {
|
||||||
|
background: #e6f7ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item.completed .stat-icon {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item.messages .stat-icon {
|
||||||
|
color: #faad14;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item.reminders .stat-icon {
|
||||||
|
color: #13c2c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 15px;
|
||||||
|
opacity: 0.7;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-number {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
};
|
||||||
@@ -1,249 +1,543 @@
|
|||||||
const user = {
|
const user = {
|
||||||
template: /*language=HTML*/ `
|
template: /*language=HTML*/ `
|
||||||
<div class="user-wrapper">
|
<div class="user-wrapper">
|
||||||
|
<!-- 用户容器:左右布局 -->
|
||||||
<div class="user-container">
|
<div class="user-container">
|
||||||
<div class="user-info-section">
|
<!-- 左侧:用户信息卡片 -->
|
||||||
|
<div class="user-info-card">
|
||||||
<div class="user-details">
|
<div class="user-details">
|
||||||
<div class="user-name">${@auth.getPrincipalProperty('username')}</div>
|
<div class="user-name">${@auth.getPrincipalProperty('username')}</div>
|
||||||
<div class="user-meta">
|
|
||||||
<div class="meta-item">
|
<div class="user-meta-grid">
|
||||||
<span class="meta-label">工号:</span>
|
<div class="meta-row">
|
||||||
<span class="meta-value">${@auth.getPrincipalProperty('loginname')}</span>
|
<span class="meta-icon">🆔</span>
|
||||||
|
<div>
|
||||||
|
<span class="meta-label">工号</span>
|
||||||
|
<span class="meta-value">${@auth.getPrincipalProperty('loginname')}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta-item">
|
|
||||||
<span class="meta-label">单位:</span>
|
<div class="meta-row">
|
||||||
<span class="meta-value">
|
<span class="meta-icon">🏢</span>
|
||||||
<!--#if(!isEmpty(@auth.getPrincipalProperty('unit'))){#-->
|
<div>
|
||||||
${@auth.getPrincipalProperty('unit').getName()}
|
<span class="meta-label">单位信息</span>
|
||||||
<!--#}#-->
|
<span class="meta-value">
|
||||||
</span>
|
<!--#if(!isEmpty(@auth.getPrincipalProperty('unit'))){#-->
|
||||||
|
${@auth.getPrincipalProperty('unit').getName()}
|
||||||
|
<!--#}#-->
|
||||||
|
(
|
||||||
|
<!--#if(!isEmpty(@auth.getPrincipalProperty('union'))){#-->
|
||||||
|
${@auth.getPrincipalProperty('union').getName()}
|
||||||
|
<!--#}#-->
|
||||||
|
)
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta-item">
|
<div class="meta-row">
|
||||||
<span class="meta-label">分工会:</span>
|
<span class="meta-icon">🎭</span>
|
||||||
<span class="meta-value">
|
<div>
|
||||||
<!--#if(!isEmpty(@auth.getPrincipalProperty('union'))){#-->
|
<span class="meta-label">角色</span>
|
||||||
${@auth.getPrincipalProperty('union').getName()}
|
<span class="meta-value">{{ roleNames || '—' }}</span>
|
||||||
<!--#}#-->
|
</div>
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
|
|
||||||
<div class="stats-section">
|
<!-- 右侧:待办中心 -->
|
||||||
<div class="stats-grid">
|
<div class="todo-center">
|
||||||
<div class="stat-item pending" @click="handleStatClick('todo')">
|
<!-- 标题和标签 -->
|
||||||
<div class="stat-icon">
|
<div class="header">
|
||||||
<i class="fa fa-clock-o"></i>
|
<h3>待办中心</h3>
|
||||||
</div>
|
<el-tabs v-model="activeTab" type="card" @tab-click="handleTabClick">
|
||||||
<div class="stat-content">
|
<el-tab-pane label="待办事宜" name="todo"></el-tab-pane>
|
||||||
<div class="stat-label">待办</div>
|
<el-tab-pane label="已办事宜" name="done"></el-tab-pane>
|
||||||
<div class="stat-number">{{ stats.todoCount }}</div>
|
<el-tab-pane label="我的发起" name="started"></el-tab-pane>
|
||||||
</div>
|
<el-tab-pane label="办结事务" name="completed"></el-tab-pane>
|
||||||
</div>
|
</el-tabs>
|
||||||
|
|
||||||
<div class="stat-item completed" @click="handleStatClick('done')">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<i class="fa fa-check-circle"></i>
|
|
||||||
</div>
|
|
||||||
<div class="stat-content">
|
|
||||||
<div class="stat-label">已办</div>
|
|
||||||
<div class="stat-number">{{ stats.doneCount }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat-item messages" @click="handleStatClick('notification')">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<i class="fa fa-bell"></i>
|
|
||||||
</div>
|
|
||||||
<div class="stat-content">
|
|
||||||
<div class="stat-label">消息</div>
|
|
||||||
<div class="stat-number">{{ stats.notifications }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stat-item reminders" @click="handleStatClick('started')">
|
|
||||||
<div class="stat-icon">
|
|
||||||
<i class="fa fa-file-text"></i>
|
|
||||||
</div>
|
|
||||||
<div class="stat-content">
|
|
||||||
<div class="stat-label">发起</div>
|
|
||||||
<div class="stat-number">{{ stats.startedCount }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</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="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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
|
mixins: [initTableMixins],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
stats: {
|
activeTab: 'todo',
|
||||||
todoCount: 0,
|
todoList: [],
|
||||||
doneCount: 0,
|
loading: false,
|
||||||
notifications: 0,
|
pageForm: {
|
||||||
startedCount: 0
|
pageNum: 1,
|
||||||
}
|
pageSize: 5,
|
||||||
}
|
totalCount: 0
|
||||||
|
},
|
||||||
|
// 🔆 天气相关数据
|
||||||
|
weatherData: null,
|
||||||
|
weatherError: false,
|
||||||
|
// 🔑 和风天气 API Key(请替换为你自己的)
|
||||||
|
QWEATHER_KEY: 'f916578cbb0e4b55b778b0de5847ecf5', // ←← 务必替换!
|
||||||
|
roleNames: ""
|
||||||
|
|
||||||
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleStatClick(type) {
|
getWeatherInfo(iconCode, temp) {
|
||||||
if (['todo', 'done', 'started'].includes(type)) {
|
const info = {
|
||||||
window.open('/flow/todoCenter?status=' + type)
|
emoji: '🌤️',
|
||||||
} else if (type === 'notification') {
|
tip: '今日天气宜人,心情也该放晴啦!',
|
||||||
window.open('/platform/v4/msg')
|
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")
|
||||||
|
const dataString = sessionStorage.getItem('homeWeatherData');
|
||||||
|
if (dataString) {
|
||||||
|
this.weatherData = JSON.parse(dataString)
|
||||||
|
} else {
|
||||||
|
// 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
|
||||||
|
};
|
||||||
|
sessionStorage.setItem('homeWeatherData', JSON.stringify(this.weatherData));
|
||||||
|
|
||||||
|
this.weatherError = false;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('天气加载失败:', err);
|
||||||
|
this.weatherError = true;
|
||||||
|
this.weatherData = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
loadStats() {
|
// 获取任务列表
|
||||||
this.$axios.post("/flow/todoCenter/statistics").then(res => {
|
async getTasks() {
|
||||||
|
this.loading = true
|
||||||
|
try {
|
||||||
|
const res = await $.post("/flow/todoCenter/" + this.activeTab, this.pageForm)
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
this.stats = res.data;
|
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()
|
||||||
|
},
|
||||||
|
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)
|
||||||
|
},
|
||||||
|
getRoleNames() {
|
||||||
|
$.post("/platform/sys/role/getRoleNames").then(res => {
|
||||||
|
if (res.code === 0) {
|
||||||
|
this.roleNames = res.data.roleNames
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
this.pageData()
|
||||||
|
this.getRoleNames()
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loadStats();
|
this.fetchWeather()
|
||||||
},
|
},
|
||||||
style: /*language=CSS*/ `
|
style: /*language=CSS*/ `
|
||||||
.user-wrapper {
|
.user-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-image: url('/assets/platform/img/home/user-bg.png');
|
background-color: #f5f7fa;
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-container {
|
.user-container {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
max-width: 80%;
|
margin: 20px auto;
|
||||||
margin: 0 auto;
|
display: grid;
|
||||||
padding: 20px;
|
grid-template-columns: 0.7fr 2.3fr;
|
||||||
display: flex;
|
gap: 24px;
|
||||||
gap: 30px;
|
align-items: stretch;
|
||||||
overflow: hidden;
|
row-gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-info-section {
|
.user-info-card {
|
||||||
display: flex;
|
background: white;
|
||||||
align-items: center;
|
border-radius: 16px;
|
||||||
min-width: 0;
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
|
||||||
width: 390px;
|
padding: 24px;
|
||||||
background-image: url('/assets/platform/img/home/user-bg.png');
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-details {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-name {
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #1a1a1a;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-meta {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 20px;
|
||||||
|
transition: transform 0.25s ease, box-shadow 0.25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.meta-item {
|
.user-info-card:hover {
|
||||||
display: flex;
|
transform: translateY(-4px);
|
||||||
align-items: center;
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||||
font-size: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.meta-label {
|
/* 头像占位符 */
|
||||||
color: #666;
|
.user-avatar-placeholder {
|
||||||
min-width: 60px;
|
width: 64px;
|
||||||
flex-shrink: 0;
|
height: 64px;
|
||||||
}
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, #409eff, #1877f2);
|
||||||
.meta-value {
|
color: white;
|
||||||
color: #333;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 右侧统计区域 */
|
|
||||||
.stats-section {
|
|
||||||
flex: 1;
|
|
||||||
min-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: 32px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
padding: 16px;
|
|
||||||
position: relative;
|
|
||||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYEAAAB4CAYAAAAUs05BAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAANrSURBVHgB7dzNapNZAMfh0zbNYGgosYql4wiCFEEZXLiYG3DrdryPuQbvpXMB7t24m4UOCiKuEtCKsaVNiTRaXhshLvyoSd/Yzf95oORA827PLycn5yxsdZ/crKql+6WG1uLy0d3Lm29Pes+jfm+1N9w/VwD4qXtXbmyf9P/Hu29Wng/6K6WOqnq6WACI1ZgM1pqt0Z31qztlBoMPh0sPXr+8OMsztzsbe9fanfcFgG9sdZ+tz/L+6+0LB7c6lw5meWZ7OGg+7HfPj8dWAgDBRAAgmAgABBMBgGAiABBMBACCiQBAsIV5nBiehXMCAD826zmBWpwYBsi2UFXV5vHrP6WGycnhae4QAuD0JncGneak8He8sBIACCYCAMEa//b+bx5vDJ/dRgQAtY2/EprDVdJ9KwGAYLWukgbgbI03g+tuCLtKGoDPRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEEwEAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgIgAQTAQAgokAQDARAAgmAgDBRAAgmAgABBMBgGAiABBMBACCiQBAMBEACCYCAMFEACCYCAAEEwGAYCIAEKwxGbwbDZtb3WfrpYbW4vLR3cubbwsAv8Tj3Tcrzwf9lTInVgIAwRp///Hn6Ph1u9Qw+HC49OD1y4sFgDNxvX3h4Fbn0kGpZ8dKACCYCAAEW9jqPrlZVUv3yymtNVujv9Y29qb9Ouh2Z2PvWrvzvgDwjWl+oLM/OlwefBw1fm+1682lVfXUSgAg2JefiI4/0d9Zv7oz7YPbw0HzYb97fjxuL/92dO/KjRM3lx/1e6u94f65AsBPnTSnTubfWeftr58fj60EAIKJAEAwEQAIJgIAwUQAIJgIAAQTAYBgc71Kehr/7b5aHf8VAGqZx7xtJQAQ7BOP4saDQA2PwQAAAABJRU5ErkJggg==) no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-item:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stat-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 12px;
|
|
||||||
right: 12px;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 6px;
|
font-size: 24px;
|
||||||
font-size: 16px;
|
font-weight: 600;
|
||||||
color: #999;
|
margin: 0 auto;
|
||||||
|
box-shadow: 0 4px 10px rgba(24, 127, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-icon i {
|
/* 用户名 */
|
||||||
font-size: 32px;
|
.user-name {
|
||||||
color: var(--color-primary-3);
|
font-size: 20px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1f2937;
|
||||||
|
text-align: center;
|
||||||
|
margin: 8px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-content {
|
/* 元信息网格 */
|
||||||
flex: 1;
|
.user-meta-grid {
|
||||||
min-width: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 14px;
|
||||||
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-label {
|
.meta-row {
|
||||||
font-size: 16px;
|
display: flex;
|
||||||
color: #333;
|
align-items: flex-start;
|
||||||
font-weight: 700;
|
gap: 12px;
|
||||||
line-height: 1;
|
}
|
||||||
|
|
||||||
|
.meta-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
min-width: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 15px 0;
|
color: #409eff;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-number {
|
.meta-row > div {
|
||||||
font-size: 32px;
|
|
||||||
font-weight: 700;
|
|
||||||
color: var(--color-primary);
|
|
||||||
line-height: 1;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.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%;
|
||||||
|
}
|
||||||
|
}
|
||||||
`
|
`
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const apps = {
|
|||||||
@click="onClickNav(index)"
|
@click="onClickNav(index)"
|
||||||
>
|
>
|
||||||
<div class="nav-icon">
|
<div class="nav-icon">
|
||||||
<i v-if="category.icon" :class="category.icon"></i>
|
<van-icon v-if="category.icon" :name="category.icon" size="28"></van-icon>
|
||||||
<i v-else class="fa fa-book"></i>
|
<i v-else class="fa fa-book"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-text">{{ category.name }}</div>
|
<div class="nav-text">{{ category.name }}</div>
|
||||||
@@ -34,41 +34,31 @@ const apps = {
|
|||||||
<!-- 右侧内容 -->
|
<!-- 右侧内容 -->
|
||||||
<div class="tree-content">
|
<div class="tree-content">
|
||||||
<!-- 应用列表 -->
|
<!-- 应用列表 -->
|
||||||
<div class="app-list" v-if="applications.length > 0">
|
<div :class="['app-grid', { 'app-grid-single': applications.length === 1 }]"
|
||||||
<div
|
v-if="applications.length > 0">
|
||||||
v-for="app in applications"
|
<div v-for="app in applications"
|
||||||
:key="app.id"
|
:key="app.id"
|
||||||
class="app-item"
|
class="app-grid-item"
|
||||||
@click="openApp(app)"
|
:class="{ 'is-favorite': app.isFavorite }"
|
||||||
>
|
@click="openApp(app)"
|
||||||
<div class="app-icon">
|
@touchstart="onTouchStart(app)"
|
||||||
<van-image
|
@touchend="onTouchEnd"
|
||||||
v-if="app.picIcon"
|
@touchmove="onTouchMove">
|
||||||
:src="app.picIcon"
|
<!-- 图标 -->
|
||||||
fit="cover"
|
<div class="app-grid-icon">
|
||||||
width="40"
|
<van-icon v-if="app.picIcon" :name="app.picIcon" size="64"
|
||||||
height="40"
|
style="border-radius: 12px; width: 64px; height: 64px;"></van-icon>
|
||||||
radius="4"
|
<van-icon v-else-if="app.icon" :name="app.icon" size="28"></van-icon>
|
||||||
></van-image>
|
<van-icon v-else name="apps-o" size="28"></van-icon>
|
||||||
<van-icon v-else-if="app.icon" :name="app.icon" size="24"></van-icon>
|
|
||||||
<van-icon v-else name="apps-o" size="24"></van-icon>
|
|
||||||
</div>
|
|
||||||
<div class="app-info">
|
|
||||||
<div class="app-title">{{ app.name }}</div>
|
|
||||||
<div class="app-desc" v-if="app.department">{{ app.department }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="app-action">
|
|
||||||
<van-icon
|
|
||||||
:name="app.isFavorite ? 'star' : 'star-o'"
|
|
||||||
:class="['favorite-icon', app.isFavorite ? 'active' : '']"
|
|
||||||
@click.stop="toggleFavorite(app.id)"
|
|
||||||
></van-icon>
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 名称 -->
|
||||||
|
<div class="app-grid-name">{{ app.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
</div>
|
||||||
<!-- 空状态 -->
|
<!-- 空状态 -->
|
||||||
<van-empty v-else description="暂无应用"></van-empty>
|
<van-empty v-else description="暂无应用"></van-empty>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -118,7 +108,10 @@ const apps = {
|
|||||||
// 弹框相关
|
// 弹框相关
|
||||||
showMenuPopup: false,
|
showMenuPopup: false,
|
||||||
currentApp: {},
|
currentApp: {},
|
||||||
currentMenus: []
|
currentMenus: [],
|
||||||
|
|
||||||
|
touchTimer: null,
|
||||||
|
isTouchMoved: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -129,8 +122,7 @@ const apps = {
|
|||||||
// 当前选中的分类ID
|
// 当前选中的分类ID
|
||||||
currentCategoryId() {
|
currentCategoryId() {
|
||||||
return this.allCategories[this.activeTab]?.id || "all"
|
return this.allCategories[this.activeTab]?.id || "all"
|
||||||
},
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// 页面加载时获取分类和应用数据
|
// 页面加载时获取分类和应用数据
|
||||||
@@ -225,16 +217,38 @@ const apps = {
|
|||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.code === 0) {
|
if (result.code === 0) {
|
||||||
app.isFavorite = !app.isFavorite
|
app.isFavorite = !app.isFavorite
|
||||||
this.$toast(app.isFavorite ? "收藏成功" : "取消收藏成功")
|
this.$toast(app.isFavorite ? ('收藏成功:' + app.name) : ('取消收藏:' + app.name))
|
||||||
} else {
|
} else {
|
||||||
console.error(app.isFavorite ? "取消收藏失败:" : "收藏失败:", result.msg)
|
console.error(app.isFavorite ? ('取消收藏:' + app.name) : ('收藏失败:' + app.name), result.msg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.fail((error) => {
|
.fail((error) => {
|
||||||
console.error(app.isFavorite ? "取消收藏异常:" : "收藏异常:", error)
|
console.error(app.isFavorite ? ('取消收藏:' + app.name) : ('收藏异常:' + app.name), error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 长按开始
|
||||||
|
onTouchStart(app) {
|
||||||
|
this.isTouchMoved = false
|
||||||
|
this.touchTimer = setTimeout(() => {
|
||||||
|
this.toggleFavorite(app.id)
|
||||||
|
}, 800) // 长按 800ms 触发
|
||||||
|
},
|
||||||
|
|
||||||
|
// 触摸移动(判断是否滑动,避免误触长按)
|
||||||
|
onTouchMove() {
|
||||||
|
this.isTouchMoved = true
|
||||||
|
},
|
||||||
|
|
||||||
|
// 触摸结束(清除计时器)
|
||||||
|
onTouchEnd() {
|
||||||
|
if (this.touchTimer) {
|
||||||
|
clearTimeout(this.touchTimer)
|
||||||
|
this.touchTimer = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
onSearch() {
|
onSearch() {
|
||||||
this.applications = []
|
this.applications = []
|
||||||
@@ -283,7 +297,7 @@ const apps = {
|
|||||||
// 导航到菜单
|
// 导航到菜单
|
||||||
navigateToMenu(menu) {
|
navigateToMenu(menu) {
|
||||||
// 关闭弹框
|
// 关闭弹框
|
||||||
this.showMenuPopup = false
|
// this.showMenuPopup = false
|
||||||
if (menu.href) {
|
if (menu.href) {
|
||||||
if(menu.href.startsWith('http://') || menu.href.startsWith('https://')){
|
if(menu.href.startsWith('http://') || menu.href.startsWith('https://')){
|
||||||
window.open(menu.href, '_blank')
|
window.open(menu.href, '_blank')
|
||||||
@@ -295,6 +309,12 @@ const apps = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 初始加载消除长按收藏
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.touchTimer) {
|
||||||
|
clearTimeout(this.touchTimer)
|
||||||
|
}
|
||||||
|
},
|
||||||
style: /*language=CSS*/ `
|
style: /*language=CSS*/ `
|
||||||
.apps-container {
|
.apps-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -385,66 +405,77 @@ const apps = {
|
|||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-list {
|
.app-grid {
|
||||||
flex: 1;
|
display: grid;
|
||||||
overflow-y: auto;
|
/* 改为自适应列数:每格最小 80px,自动换行 */
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
|
||||||
|
|
||||||
|
justify-items: center; /* 子项内容居中(图标和文字) */
|
||||||
|
justify-content: start; /* 整体网格靠左对齐,避免居中 */
|
||||||
|
|
||||||
|
gap: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
background: #fff;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-item {
|
.app-grid-single {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: start;
|
||||||
padding: 12px 16px;
|
padding: 16px 0;
|
||||||
background-color: #fff;
|
|
||||||
margin-bottom: 1px;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-icon {
|
.app-grid-single .app-grid-item {
|
||||||
width: 40px;
|
max-width: 80px;
|
||||||
height: 40px;
|
margin: 0 12px;
|
||||||
border-radius: 4px;
|
}
|
||||||
background-color: #f2f3f5;
|
|
||||||
|
.app-grid-item {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 4px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-grid-icon {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
max-width: 64px;
|
||||||
|
max-height: 64px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #f2f3f5;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-right: 12px;
|
margin-bottom: 6px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
border: 2px solid transparent;
|
||||||
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-info {
|
.app-grid-name {
|
||||||
flex: 1;
|
width: 100%;
|
||||||
}
|
|
||||||
|
|
||||||
.app-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: #323233;
|
|
||||||
}
|
|
||||||
|
|
||||||
.app-desc {
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #969799;
|
color: #323233;
|
||||||
}
|
|
||||||
|
|
||||||
.app-action {
|
|
||||||
padding: 0 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.favorite-icon {
|
|
||||||
font-size: 20px;
|
|
||||||
color: #c8c9cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.favorite-icon.active {
|
|
||||||
color: #ff9800;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-container {
|
|
||||||
padding: 20px 0;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-grid-item.is-favorite .app-grid-icon,
|
||||||
|
.app-grid-icon.is-favorite {
|
||||||
|
border-color: #ff9800;
|
||||||
|
box-shadow: 0 0 0 2px rgba(255, 152, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 菜单弹框样式 */
|
/* 菜单弹框样式 */
|
||||||
/deep/ .menu-popup {
|
/deep/ .menu-popup {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -546,5 +577,6 @@ const apps = {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #c8c9cc;
|
color: #c8c9cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ layout("/layouts/platform_h5.html"){
|
|||||||
<van-tabbar v-model="homeTabbarActive" @change="homeTabbarChange">
|
<van-tabbar v-model="homeTabbarActive" @change="homeTabbarChange">
|
||||||
<van-tabbar-item name="home" icon="wap-home-o">首页</van-tabbar-item>
|
<van-tabbar-item name="home" icon="wap-home-o">首页</van-tabbar-item>
|
||||||
<van-tabbar-item name="apps" icon="apps-o">应用</van-tabbar-item>
|
<van-tabbar-item name="apps" icon="apps-o">应用</van-tabbar-item>
|
||||||
<!-- <van-tabbar-item name="work" icon="gem">工作台</van-tabbar-item>-->
|
<!-- <van-tabbar-item name="work" icon="gem">工作台</van-tabbar-item>-->
|
||||||
<van-tabbar-item name="todo" icon="records-o">待办</van-tabbar-item>
|
<van-tabbar-item name="todo" icon="records-o">待办</van-tabbar-item>
|
||||||
<van-tabbar-item name="msg" icon="envelop-o">消息</van-tabbar-item>
|
<van-tabbar-item name="msg" icon="envelop-o">消息</van-tabbar-item>
|
||||||
<van-tabbar-item name="mine" icon="user-o">我的</van-tabbar-item>
|
<van-tabbar-item name="mine" icon="user-o">我的</van-tabbar-item>
|
||||||
|
|||||||
@@ -5,31 +5,31 @@ const msg= {
|
|||||||
|
|
||||||
<!-- 筛选区域 -->
|
<!-- 筛选区域 -->
|
||||||
<van-sticky offset-top="46px">
|
<van-sticky offset-top="46px">
|
||||||
<!-- <div class="filter-section">-->
|
<!-- <div class="filter-section">-->
|
||||||
<!-- <van-row gutter="10">-->
|
<!-- <van-row gutter="10">-->
|
||||||
<!-- <van-col span="12">-->
|
<!-- <van-col span="12">-->
|
||||||
<!-- <van-field-->
|
<!-- <van-field-->
|
||||||
<!-- v-model="filters.type"-->
|
<!-- v-model="filters.type"-->
|
||||||
<!-- is-link-->
|
<!-- is-link-->
|
||||||
<!-- readonly-->
|
<!-- readonly-->
|
||||||
<!-- label="消息类型"-->
|
<!-- label="消息类型"-->
|
||||||
<!-- placeholder="选择消息类型"-->
|
<!-- placeholder="选择消息类型"-->
|
||||||
<!-- @click="showTypePicker = true"-->
|
<!-- @click="showTypePicker = true"-->
|
||||||
<!-- />-->
|
<!-- />-->
|
||||||
<!-- </van-col>-->
|
<!-- </van-col>-->
|
||||||
<!-- <van-col span="12" v-if="pageForm.isRead == 0">-->
|
<!-- <van-col span="12" v-if="pageForm.isRead == 0">-->
|
||||||
<!-- <van-button -->
|
<!-- <van-button -->
|
||||||
<!-- type="primary" -->
|
<!-- type="primary" -->
|
||||||
<!-- size="small" -->
|
<!-- size="small" -->
|
||||||
<!-- :loading="loading"-->
|
<!-- :loading="loading"-->
|
||||||
<!-- @click="markAllAsRead"-->
|
<!-- @click="markAllAsRead"-->
|
||||||
<!-- style="margin-top: 6px; width: 100%;"-->
|
<!-- style="margin-top: 6px; width: 100%;"-->
|
||||||
<!-- >-->
|
<!-- >-->
|
||||||
<!-- 全部已读-->
|
<!-- 全部已读-->
|
||||||
<!-- </van-button>-->
|
<!-- </van-button>-->
|
||||||
<!-- </van-col>-->
|
<!-- </van-col>-->
|
||||||
<!-- </van-row>-->
|
<!-- </van-row>-->
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
<!-- 标签页 -->
|
<!-- 标签页 -->
|
||||||
<van-tabs v-model="activeTab" @change="handleTabChange">
|
<van-tabs v-model="activeTab" @change="handleTabChange">
|
||||||
<van-tab title="全部消息" name="-1">
|
<van-tab title="全部消息" name="-1">
|
||||||
@@ -56,34 +56,34 @@ const msg= {
|
|||||||
<!-- 消息列表 -->
|
<!-- 消息列表 -->
|
||||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||||
<van-list
|
<van-list
|
||||||
style="padding: 10px"
|
style="padding: 10px"
|
||||||
v-model="loading"
|
v-model="loading"
|
||||||
:finished="finished"
|
:finished="finished"
|
||||||
finished-text="没有更多了"
|
finished-text="没有更多了"
|
||||||
@load="onLoad"
|
@load="onLoad"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="message in messages"
|
v-for="message in messages"
|
||||||
:key="message.id"
|
:key="message.id"
|
||||||
@click="viewMessage(message)"
|
@click="viewMessage(message)"
|
||||||
class="custom-message-item"
|
class="custom-message-item"
|
||||||
:class="{'unread-message': !message.isRead}"
|
:class="{'unread-message': !message.isRead}"
|
||||||
>
|
>
|
||||||
<div class="message-header">
|
<div class="message-header">
|
||||||
<div class="message-title-wrapper">
|
<div class="message-title-wrapper">
|
||||||
<van-tag
|
<van-tag
|
||||||
:type="message.type === 1 ? 'danger' : 'primary'"
|
:type="message.type === 1 ? 'danger' : 'primary'"
|
||||||
size="mini"
|
size="mini"
|
||||||
style="margin-right: 8px;"
|
style="margin-right: 8px;"
|
||||||
>
|
>
|
||||||
{{getMessageTypeName(message.type)}}
|
{{getMessageTypeName(message.type)}}
|
||||||
</van-tag>
|
</van-tag>
|
||||||
<!-- <span class="message-title">{{message.title}}</span>-->
|
<!-- <span class="message-title">{{message.title}}</span>-->
|
||||||
<van-tag
|
<van-tag
|
||||||
v-if="!message.isRead"
|
v-if="!message.isRead"
|
||||||
type="warning"
|
type="warning"
|
||||||
size="mini"
|
size="mini"
|
||||||
style="margin-left: 8px;"
|
style="margin-left: 8px;"
|
||||||
>
|
>
|
||||||
未读
|
未读
|
||||||
</van-tag>
|
</van-tag>
|
||||||
@@ -101,19 +101,19 @@ const msg= {
|
|||||||
<!-- 消息类型选择器 -->
|
<!-- 消息类型选择器 -->
|
||||||
<van-popup v-model="showTypePicker" position="bottom">
|
<van-popup v-model="showTypePicker" position="bottom">
|
||||||
<van-picker
|
<van-picker
|
||||||
:columns="typeColumns"
|
:columns="typeColumns"
|
||||||
@confirm="onTypeConfirm"
|
@confirm="onTypeConfirm"
|
||||||
@cancel="showTypePicker = false"
|
@cancel="showTypePicker = false"
|
||||||
/>
|
/>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
|
|
||||||
<!-- 消息详情弹窗 -->
|
<!-- 消息详情弹窗 -->
|
||||||
<van-popup
|
<van-popup
|
||||||
v-model="detailVisible"
|
v-model="detailVisible"
|
||||||
position="bottom"
|
position="bottom"
|
||||||
:style="{ height: '80%' }"
|
:style="{ height: '80%' }"
|
||||||
closeable
|
closeable
|
||||||
close-icon-position="top-right"
|
close-icon-position="top-right"
|
||||||
>
|
>
|
||||||
<div class="message-detail" v-if="currentMessage.id">
|
<div class="message-detail" v-if="currentMessage.id">
|
||||||
<div class="detail-header">
|
<div class="detail-header">
|
||||||
|
|||||||
Reference in New Issue
Block a user