feat: 新增bbs排行榜功能
This commit is contained in:
@@ -5,9 +5,9 @@ namespace Yi.Framework.Bbs.Application.Contracts.Dtos.BbsUser;
|
||||
public class MoneyTopUserDto
|
||||
{
|
||||
public string UserName { get; set; }
|
||||
public string? Nice { get; set; }
|
||||
public string? Nick { get; set; }
|
||||
public decimal Money { get; set; }
|
||||
public string Order { get; set; }
|
||||
public int Order { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
public int Level { get; set; }
|
||||
/// <summary>
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
{
|
||||
private BbsUserManager _bbsUserManager;
|
||||
private IOnlineService _onlineService;
|
||||
|
||||
public BbsUserAnalyseService(BbsUserManager bbsUserManager, IOnlineService onlineService)
|
||||
{
|
||||
_bbsUserManager = bbsUserManager;
|
||||
@@ -36,22 +37,24 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
{
|
||||
RefAsync<int> total = 0;
|
||||
var output = await _bbsUserManager._userRepository._DbQueryable
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((u,info)=>u.Id==info.UserId)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((u, info) => u.Id == info.UserId)
|
||||
.OrderByDescending((u,info) => info.Money)
|
||||
.Select((u, info) =>
|
||||
new MoneyTopUserDto
|
||||
{
|
||||
UserName = u.UserName,
|
||||
Nice = u.Nick,
|
||||
Nick = u.Nick,
|
||||
Money = info.Money,
|
||||
Icon = u.Icon,
|
||||
Level = info.Level,
|
||||
UserLimit = info.UserLimit
|
||||
UserLimit = info.UserLimit,
|
||||
Order = SqlFunc.RowNumber(u.Id)
|
||||
}
|
||||
)
|
||||
.OrderBy(info=>info.Money)
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount,total);
|
||||
|
||||
output.ForEach(x => { x.LevelName = _bbsUserManager._levelCacheDic[x.Level].Name;});
|
||||
|
||||
.ToPageListAsync(input.SkipCount, input.MaxResultCount, total);
|
||||
|
||||
output.ForEach(x => { x.LevelName = _bbsUserManager._levelCacheDic[x.Level].Name; });
|
||||
return new PagedResultDto<MoneyTopUserDto>
|
||||
{
|
||||
Items = output,
|
||||
@@ -71,10 +74,9 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
using (DataFilter.DisablePermissionHandler())
|
||||
{
|
||||
var randUserIds = await _bbsUserManager._userRepository._DbQueryable
|
||||
//.Where(x => x.UserName != UserConst.Admin)
|
||||
.OrderBy(x => SqlFunc.GetRandom())
|
||||
.Select(x => x.Id).
|
||||
ToPageListAsync(input.SkipCount, input.MaxResultCount);
|
||||
//.Where(x => x.UserName != UserConst.Admin)
|
||||
.OrderBy(x => SqlFunc.GetRandom())
|
||||
.Select(x => x.Id).ToPageListAsync(input.SkipCount, input.MaxResultCount);
|
||||
var output = await _bbsUserManager.GetBbsUserInfoAsync(randUserIds);
|
||||
return output.Adapt<List<BbsUserGetListOutputDto>>();
|
||||
|
||||
@@ -83,26 +85,6 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
//这里有数据权限,会根据用户角色进行过滤
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 积分钱钱排行榜
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("analyse/bbs-user/integral-top")]
|
||||
public async Task<List<BbsUserGetListOutputDto>> GetIntegralTopUserAsync([FromQuery] PagedResultRequestDto input)
|
||||
{
|
||||
using (DataFilter.DisablePermissionHandler())
|
||||
{
|
||||
var randUserIds = await _bbsUserManager._userRepository._DbQueryable
|
||||
// .Where(user => user.UserName != UserConst.Admin)
|
||||
.LeftJoin<BbsUserExtraInfoEntity>((user, info) => user.Id == info.UserId)
|
||||
.OrderByDescending((user, info) => info.Money)
|
||||
.Select((user, info) => user.Id).
|
||||
ToPageListAsync(input.SkipCount, input.MaxResultCount);
|
||||
var output = await _bbsUserManager.GetBbsUserInfoAsync(randUserIds);
|
||||
return output.OrderByDescending(x => x.Money).ToList().Adapt<List<BbsUserGetListOutputDto>>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户分析
|
||||
/// </summary>
|
||||
@@ -112,7 +94,7 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
{
|
||||
using (DataFilter.DisablePermissionHandler())
|
||||
{
|
||||
var sss= DataFilter.IsEnabled<IDataPermission>();
|
||||
var sss = DataFilter.IsEnabled<IDataPermission>();
|
||||
var registerUser = await _bbsUserManager._userRepository._DbQueryable.CountAsync();
|
||||
|
||||
|
||||
@@ -121,16 +103,15 @@ namespace Yi.Framework.Bbs.Application.Services.Analyses
|
||||
DateTime startTime = new DateTime(yesterday.Year, yesterday.Month, yesterday.Day, 0, 0, 0);
|
||||
DateTime endTime = startTime.AddHours(24);
|
||||
var yesterdayNewUser = await _bbsUserManager._userRepository._DbQueryable
|
||||
.Where(x => x.CreationTime >= startTime && x.CreationTime <= endTime).CountAsync();
|
||||
.Where(x => x.CreationTime >= startTime && x.CreationTime <= endTime).CountAsync();
|
||||
|
||||
var userOnline = (await _onlineService.GetListAsync(new OnlineUserModel { })).TotalCount;
|
||||
|
||||
var output = new BbsUserAnalyseGetOutput() { OnlineNumber = userOnline, RegisterNumber = registerUser, YesterdayNewUser = yesterdayNewUser };
|
||||
var output = new BbsUserAnalyseGetOutput()
|
||||
{ OnlineNumber = userOnline, RegisterNumber = registerUser, YesterdayNewUser = yesterdayNewUser };
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,9 +33,9 @@ export function getRecommendedFriend(data) {
|
||||
*/
|
||||
export function getRankingPoints(data) {
|
||||
return request({
|
||||
url: "/analyse/bbs-user/integral-top",
|
||||
url: "/analyse/bbs-user/money-top",
|
||||
method: "get",
|
||||
data,
|
||||
params: data
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,15 @@ const router = createRouter({
|
||||
title: "联系我们",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name:"money",
|
||||
path:"/money",
|
||||
component: () => import("../views/money/Index.vue"),
|
||||
meta: {
|
||||
title: "钱钱",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -81,13 +81,13 @@
|
||||
<template #content>
|
||||
<div class="top">你好,很高兴今天又遇到你呀~</div>
|
||||
<el-row class="active">
|
||||
|
||||
|
||||
<el-col v-for="item in activeList" :span="6" @click="handleToRouter(item.path)">
|
||||
|
||||
<el-icon color="#70aafb" size="30px" >
|
||||
<el-icon color="#70aafb" size="30px">
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
<span> {{item.name}}</span>
|
||||
<span> {{ item.name }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
@@ -102,7 +102,18 @@
|
||||
</InfoCard>
|
||||
|
||||
<el-dialog v-model="accessLogDialogVisible" title="全站历史统计" width="1200px" center>
|
||||
<AccessLogChart :option="accessLogOptins" class="accessLogChart" />
|
||||
<el-tabs v-model="accessLogTab">
|
||||
<el-tab-pane label="访问统计" name="AccessLogChart" style="display: flex;justify-content: center;">
|
||||
<AccessLogChart :option="accessLogOptins" style="height: 600px;width: 1200px;" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="注册统计" name="RegisterChart" style="display: flex;justify-content: center;">
|
||||
即将上线,敬请期待
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
|
||||
|
||||
|
||||
</el-dialog>
|
||||
</el-col>
|
||||
|
||||
@@ -118,7 +129,7 @@
|
||||
|
||||
<el-col :span="24">
|
||||
<template v-if="isPointFinished">
|
||||
<InfoCard :items="pointList" header="财富排行榜" text="关于钱钱" height="400">
|
||||
<InfoCard :items="pointList" header="财富排行榜" text="查看我的位置" height="400" @onClickText="onClickMoneyTop">
|
||||
<template #item="temp">
|
||||
<PointsRanking :pointsData="temp" />
|
||||
</template>
|
||||
@@ -176,8 +187,8 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref, reactive, computed, nextTick, watch} from "vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import { onMounted, ref, reactive, computed, nextTick, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import DisscussCard from "@/components/DisscussCard.vue";
|
||||
import InfoCard from "@/components/InfoCard.vue";
|
||||
import PlateCard from "@/components/PlateCard.vue";
|
||||
@@ -185,18 +196,18 @@ import ScrollbarInfo from "@/components/ScrollbarInfo.vue";
|
||||
import BottomInfo from "@/components/BottomInfo.vue";
|
||||
import VisitsLineChart from "./components/VisitsLineChart/index.vue";
|
||||
import AccessLogChart from "./components/AccessLogChart/Index.vue"
|
||||
import {access, getAccessList} from "@/apis/accessApi.js";
|
||||
import {getList} from "@/apis/plateApi.js";
|
||||
import {getList as bannerGetList} from "@/apis/bannerApi.js";
|
||||
import {getHomeDiscuss} from "@/apis/discussApi.js";
|
||||
import {getWeek} from "@/apis/accessApi.js";
|
||||
import { access, getAccessList } from "@/apis/accessApi.js";
|
||||
import { getList } from "@/apis/plateApi.js";
|
||||
import { getList as bannerGetList } from "@/apis/bannerApi.js";
|
||||
import { getHomeDiscuss } from "@/apis/discussApi.js";
|
||||
import { getWeek } from "@/apis/accessApi.js";
|
||||
import {
|
||||
getRecommendedTopic,
|
||||
getRecommendedFriend,
|
||||
getRankingPoints,
|
||||
getUserAnalyse,
|
||||
} from "@/apis/analyseApi.js";
|
||||
import {getList as getAllDiscussList} from "@/apis/discussApi.js";
|
||||
import { getList as getAllDiscussList } from "@/apis/discussApi.js";
|
||||
import PointsRanking from "./components/PointsRanking/index.vue";
|
||||
import RecommendFriend from "./components/RecommendFriend/index.vue";
|
||||
import ThemeData from "./components/RecommendTheme/index.vue";
|
||||
@@ -223,17 +234,17 @@ const allDiscussList = ref([]);
|
||||
const isAllDiscussFinished = ref(false);
|
||||
const userAnalyseInfo = ref({});
|
||||
const onlineNumber = ref(0);
|
||||
|
||||
const accessLogTab = ref()
|
||||
const activeList = [
|
||||
{name: "签到", path: "/activity/sign", icon: "Present"},
|
||||
{name: "等级", path: "/activity/level", icon: "Ticket"},
|
||||
{name: "大转盘", path: "/activity/lucky", icon: "Sunny"},
|
||||
{name: "银行", path: "/activity/bank", icon: "Money"},
|
||||
{ name: "签到", path: "/activity/sign", icon: "Present" },
|
||||
{ name: "等级", path: "/activity/level", icon: "Ticket" },
|
||||
{ name: "大转盘", path: "/activity/lucky", icon: "Sunny" },
|
||||
{ name: "银行", path: "/activity/bank", icon: "Money" },
|
||||
|
||||
{name: "任务", path: "/activity/sign", icon: "Memo"},
|
||||
{name: "娱乐城", path: "/activity/sign", icon: "Sunrise"},
|
||||
{name: "开始", path: "/start", icon: "Position"},
|
||||
{name: "聊天室", path: "/chat", icon: "ChatRound"},
|
||||
{ name: "任务", path: "/activity/sign", icon: "Memo" },
|
||||
{ name: "娱乐城", path: "/activity/sign", icon: "Sunrise" },
|
||||
{ name: "开始", path: "/start", icon: "Position" },
|
||||
{ name: "聊天室", path: "/chat", icon: "ChatRound" },
|
||||
];
|
||||
|
||||
//主题查询参数
|
||||
@@ -246,34 +257,34 @@ const query = reactive({
|
||||
//初始化
|
||||
onMounted(async () => {
|
||||
access();
|
||||
const {data: plateData} = await getList();
|
||||
const { data: plateData } = await getList();
|
||||
plateList.value = plateData.items;
|
||||
const {data: discussData, config: discussConfig} = await getHomeDiscuss();
|
||||
const { data: discussData, config: discussConfig } = await getHomeDiscuss();
|
||||
discussList.value = discussData;
|
||||
isDiscussFinished.value = discussConfig.isFinish;
|
||||
const {data: bannerData} = await bannerGetList();
|
||||
const { data: bannerData } = await bannerGetList();
|
||||
bannerList.value = bannerData.items;
|
||||
const {data: weekData} = await getWeek();
|
||||
const { data: weekData } = await getWeek();
|
||||
weekList.value = weekData;
|
||||
const {data: pointData, config: pointConfig} = await getRankingPoints();
|
||||
pointList.value = pointData;
|
||||
const { data: pointData, config: pointConfig } = await getRankingPoints();
|
||||
pointList.value = pointData.items;
|
||||
isPointFinished.value = pointConfig.isFinish;
|
||||
const {data: friendData, config: friendConfig} =
|
||||
await getRecommendedFriend();
|
||||
const { data: friendData, config: friendConfig } =
|
||||
await getRecommendedFriend();
|
||||
friendList.value = friendData;
|
||||
isFriendFinished.value = friendConfig.isFinish;
|
||||
const {data: themeData, config: themeConfig} = await getRecommendedTopic();
|
||||
const { data: themeData, config: themeConfig } = await getRecommendedTopic();
|
||||
themeList.value = themeData;
|
||||
isThemeFinished.value = themeConfig.isFinish;
|
||||
const {data: allDiscussData, config: allDiscussConfig} =
|
||||
await getAllDiscussList({
|
||||
Type: 0,
|
||||
skipCount: 1,
|
||||
maxResultCount: 30,
|
||||
});
|
||||
const { data: allDiscussData, config: allDiscussConfig } =
|
||||
await getAllDiscussList({
|
||||
Type: 0,
|
||||
skipCount: 1,
|
||||
maxResultCount: 30,
|
||||
});
|
||||
isAllDiscussFinished.value = allDiscussConfig.isFinish;
|
||||
allDiscussList.value = allDiscussData.items;
|
||||
const {data: userAnalyseInfoData} = await getUserAnalyse();
|
||||
const { data: userAnalyseInfoData } = await getUserAnalyse();
|
||||
onlineNumber.value = userAnalyseInfoData.onlineNumber;
|
||||
userAnalyseInfo.value = userAnalyseInfoData;
|
||||
});
|
||||
@@ -312,6 +323,11 @@ const accessLogOptins = computed(() => {
|
||||
]
|
||||
}
|
||||
});
|
||||
const onClickMoneyTop = () => {
|
||||
|
||||
router.push("/money");
|
||||
};
|
||||
|
||||
const onClickToChatHub = () => {
|
||||
router.push("/chat");
|
||||
};
|
||||
@@ -323,18 +339,31 @@ const handleToRouter = (path) => {
|
||||
// 推送的实时人数获取
|
||||
const currentOnlineNum = computed(() => useSocketStore().getOnlineNum());
|
||||
watch(
|
||||
() => currentOnlineNum.value,
|
||||
(val) => {
|
||||
onlineNumber.value = val;
|
||||
},
|
||||
{deep: true}
|
||||
() => currentOnlineNum.value,
|
||||
(val) => {
|
||||
onlineNumber.value = val;
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
watch(
|
||||
() => accessLogTab.value,
|
||||
async(value) => {
|
||||
switch (value) {
|
||||
case "AccessLogChart":
|
||||
const {data} = await getAccessList();
|
||||
accessAllList.value = data;
|
||||
|
||||
break;
|
||||
case "RegisterChart":
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
const onClickAccessLog = async () => {
|
||||
accessLogDialogVisible.value = true;
|
||||
const {data} = await getAccessList();
|
||||
accessLogTab.value = "AccessLogChart";
|
||||
|
||||
accessAllList.value = data;
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -439,10 +468,12 @@ const onClickAccessLog = async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
.top{
|
||||
text-align: center;
|
||||
|
||||
.top {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -454,13 +485,16 @@ const onClickAccessLog = async () => {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
padding: 10px 0px;
|
||||
}
|
||||
|
||||
.el-col:hover {
|
||||
background-color: #cce1ff; /* 悬浮时背景色变化 */
|
||||
color: #70aafb; /* 悬浮时文字颜色变化 */
|
||||
}
|
||||
background-color: #cce1ff;
|
||||
/* 悬浮时背景色变化 */
|
||||
color: #70aafb;
|
||||
/* 悬浮时文字颜色变化 */
|
||||
}
|
||||
|
||||
&-btn {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -10,25 +10,26 @@
|
||||
>
|
||||
|
||||
|
||||
<UserLimitTag :userLimit="pointsData.userLimit" />
|
||||
<!-- <UserLimitTag :userLimit="pointsData.userLimit" /> -->
|
||||
</div>
|
||||
|
||||
<div class="bottom">
|
||||
<div class="name">
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
effect="dark"
|
||||
:content="pointsData.userName"
|
||||
:content="pointsData.nick"
|
||||
placement="top"
|
||||
>
|
||||
{{ pointsData.userName }}
|
||||
{{ pointsData.nick }}
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="follow">
|
||||
<el-icon class="el-icon--right"><Plus /></el-icon>
|
||||
<div class="text">关注</div>
|
||||
|
||||
<div class="follow-text"> <el-icon class="el-icon--right"><Plus /></el-icon>关注</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,4 +112,8 @@ const userImageSrc = computed(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
.follow-text
|
||||
{ cursor: pointer;
|
||||
font-size: small;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,27 +9,27 @@
|
||||
<el-tooltip
|
||||
class="box-item"
|
||||
effect="dark"
|
||||
:content="friendData.userName"
|
||||
:content="friendData.nick"
|
||||
placement="top"
|
||||
>
|
||||
{{ friendData.userName }}
|
||||
{{ friendData.nick }}
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<el-tag effect="light" type="success"
|
||||
<!-- <el-tag effect="light" type="success"
|
||||
>{{ friendData.level }}-{{friendData.levelName}} 等级</el-tag
|
||||
>
|
||||
> -->
|
||||
|
||||
<UserLimitTag :userLimit="friendData.userLimit" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="follow">
|
||||
<el-icon class="el-icon--right"><Plus /></el-icon>
|
||||
<div class="text">关注</div>
|
||||
|
||||
<div class="follow-text"> <el-icon class="el-icon--right"><Plus /></el-icon>关注</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -86,7 +86,7 @@ const userImageSrc = computed(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.name {
|
||||
width: 50px;
|
||||
width: 100px;
|
||||
color: #252933;
|
||||
margin-left: 5px;
|
||||
white-space: nowrap;
|
||||
@@ -111,4 +111,9 @@ const userImageSrc = computed(() => {
|
||||
}
|
||||
}
|
||||
}
|
||||
.follow-text
|
||||
{
|
||||
font-size: small;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
export const accessLogEchartsConfig = {
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
|
||||
Reference in New Issue
Block a user