Compare commits
23 Commits
main
...
合并OnlineUs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e51780331 | ||
|
|
45d58895cf | ||
|
|
57baf86fbf | ||
|
|
9c3877e937 | ||
|
|
787f48fbdf | ||
|
|
7b52f60c9e | ||
|
|
776d22784b | ||
|
|
ba3728879c | ||
|
|
67ffe48eee | ||
|
|
601d339055 | ||
|
|
3ca1fe23c1 | ||
|
|
7b9fa77249 | ||
|
|
9c174712d5 | ||
|
|
6d22c8c3a1 | ||
|
|
d3fadf8bbe | ||
|
|
049fba65a8 | ||
|
|
651f1528f6 | ||
|
|
a81705ba10 | ||
|
|
a79e0ef66e | ||
|
|
0fbcb50b44 | ||
|
|
ff52ad5806 | ||
|
|
90ef2ed34f | ||
|
|
47167a7489 |
30
deploy_prod_without_package.bat
Normal file
30
deploy_prod_without_package.bat
Normal file
@ -0,0 +1,30 @@
|
||||
@echo off
|
||||
|
||||
:: 1. 设置动态参数
|
||||
set REMOTE_IP=119.29.151.152
|
||||
set REMOTE_PORT=22101
|
||||
set REMOTE_PATH=/tmp
|
||||
set REMOTE_USER=ubuntu
|
||||
set DEPLOY_SCRIPT=/home/ubuntu/deploy_advisor.sh
|
||||
|
||||
:: 2. 将 JAR 包传输到 Linux 服务器
|
||||
echo Copying JAR file to Linux server...
|
||||
call scp -P %REMOTE_PORT% target\AdvisorServer-2.6.7.jar %REMOTE_USER%@%REMOTE_IP%:%REMOTE_PATH%
|
||||
|
||||
:: 检查 SCP 命令是否成功
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
echo File transfer failed, exiting...
|
||||
exit /b %ERRORLEVEL%
|
||||
)
|
||||
|
||||
:: 3. 通过 SSH 运行 deploy.sh 脚本
|
||||
echo Running deploy_advisor.sh script on Linux server...
|
||||
call ssh -p %REMOTE_PORT% %REMOTE_USER%@%REMOTE_IP% "bash %DEPLOY_SCRIPT%"
|
||||
|
||||
:: 检查 SSH 命令是否成功
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
echo Failed to start the application, exiting...
|
||||
exit /b %ERRORLEVEL%
|
||||
)
|
||||
|
||||
echo Deployment successful!
|
||||
42
grep_log.bat
Normal file
42
grep_log.bat
Normal file
@ -0,0 +1,42 @@
|
||||
@echo off
|
||||
|
||||
:: 1. 设置动态参数
|
||||
set REMOTE_IP=119.29.151.152
|
||||
set REMOTE_PORT=22101
|
||||
set REMOTE_USER=ubuntu
|
||||
set SCRIPT_PATH=/home/ubuntu/grep_log.sh
|
||||
|
||||
REM 检查是否提供了参数
|
||||
if "%~1"=="" (
|
||||
echo Usage: grep_log.bat <KEYWORD> [-A <n>] [-B <n>] [-C <n>]
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 设置变量
|
||||
set KEYWORD=%1
|
||||
shift
|
||||
|
||||
REM 解析选项
|
||||
set OPTIONS=
|
||||
|
||||
:parse_options
|
||||
if "%~1"=="" goto done
|
||||
if "%~1"=="-A" (
|
||||
set OPTIONS=-A %2
|
||||
shift
|
||||
)
|
||||
if "%~1"=="-B" (
|
||||
set OPTIONS=-B %2
|
||||
shift
|
||||
)
|
||||
if "%~1"=="-C" (
|
||||
set OPTIONS=-C %2
|
||||
shift
|
||||
)
|
||||
shift
|
||||
goto parse_options
|
||||
|
||||
:done
|
||||
|
||||
REM 远程执行 Linux 脚本
|
||||
call ssh -p %REMOTE_PORT% %REMOTE_USER%@%REMOTE_IP% "bash %SCRIPT_PATH% %KEYWORD% %OPTIONS%"
|
||||
331
html/monitor.html
Normal file
331
html/monitor.html
Normal file
@ -0,0 +1,331 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<link href="https://cdn.staticfile.org/element-ui/2.15.14/theme-chalk/index.min.css" rel="stylesheet">
|
||||
<title>Interface Monitor</title>
|
||||
<script src="https://cdn.staticfile.org/vue/2.7.14/vue.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/blueimp-md5/2.19.0/js/md5.min.js"></script>
|
||||
<script src="https://cdn.staticfile.org/axios/1.6.5/axios.js"></script>
|
||||
<script src="https://cdn.staticfile.org/element-ui/2.15.14/index.js"></script>
|
||||
<script src="https://cdn.staticfile.net/dayjs/1.11.10/dayjs.min.js"></script>
|
||||
<script src="https://cdn.staticfile.net/echarts/5.4.3/echarts.min.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
display: flex;
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.el-form-item__content {
|
||||
margin-left: 6px !important;
|
||||
}
|
||||
|
||||
.resu {
|
||||
margin-left: 360px;
|
||||
width: 1152px;
|
||||
min-height: 700px;
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 1152px;
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<div style="width:320px; position: fixed; padding: 20px 0 0 30px;">
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="Host:">
|
||||
<div style="width: 108%;">
|
||||
<el-select @change="init()" placeholder="请选择" v-model="query.host">
|
||||
<el-option :key="item" :label="item" :value="item" v-for="item in data.host"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间:">
|
||||
<el-date-picker @change="init()" placeholder="选择开始时间" type="datetime" v-model="query.startTime">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="结束时间:">
|
||||
<el-date-picker @change="init()" placeholder="选择结束时间" type="datetime" v-model="query.endTime">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="IP:">
|
||||
<el-select placeholder="请选择" v-model="query.ip">
|
||||
<el-option :key="item" :label="item" :value="item" @change="init()" v-for="item in data.ip">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="接口:">
|
||||
<el-select @change="init(false)" placeholder="请选择" v-model="query.name">
|
||||
<el-option :key="item" :label="item" :value="item" v-for="item in data.name">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="分组方式:">
|
||||
<el-radio :label="item" @change="groupData()" v-for="item in data.groupBy" v-model="query.groupBy">{{ item }}</el-radio>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div style="margin-left: 20%; display: flex;">
|
||||
<el-button @click="listData()" type="primary">查询曲线</el-button>
|
||||
<el-button @click="groupData()" type="primary">查询分组</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="resu">
|
||||
<div id="line" v-show="data.showLine">
|
||||
<div class="line" id="total"></div>
|
||||
<div class="line" id="average"></div>
|
||||
<div class="line" id="failure"></div>
|
||||
<div class="line" id="timeout"></div>
|
||||
</div>
|
||||
<div id="table" v-show="data.showTable">
|
||||
<el-table :data="data.groupData" :default-sort = "{prop: 'total', order: 'descending'}" @sort-change="sortChange" height="700" >
|
||||
<el-table-column label="IP" prop="ip" v-if="query.groupBy === 'ip'" width="120"></el-table-column>
|
||||
<el-table-column label="接口" prop="interfaceName" v-if="query.groupBy === 'name'" width="230"></el-table-column>
|
||||
<el-table-column label="数量" prop="total" width="78" sortable='custom'></el-table-column>
|
||||
<el-table-column label="失败" prop="failure" width="78" sortable='custom'></el-table-column>
|
||||
<el-table-column label="平均" prop="averageTime" width="78" sortable='custom'></el-table-column>
|
||||
<el-table-column label="最大" prop="maxTime" width="78" sortable='custom'></el-table-column>
|
||||
<el-table-column label="最小" prop="minTime" width="78" sortable='custom'></el-table-column>
|
||||
<el-table-column label="10ms" prop="over10ms" width="80" sortable='custom'></el-table-column>
|
||||
<el-table-column label="50ms" prop="over50ms" width="80" sortable='custom'></el-table-column>
|
||||
<el-table-column label="100ms" prop="over100ms" width="88" sortable='custom'></el-table-column>
|
||||
<el-table-column label="500ms" prop="over500ms" width="88" sortable='custom'></el-table-column>
|
||||
<el-table-column label="1000ms" prop="over1000ms" width="96" sortable='custom'></el-table-column>
|
||||
<el-table-column label="5000ms" prop="over5000ms" width="96" sortable='custom'></el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const HttpReq = axios.create({
|
||||
// baseURL, // api的base_url
|
||||
timeout: 10000, // 请求超时时间,
|
||||
method: "post"
|
||||
});
|
||||
|
||||
HttpReq.interceptors.request.use(config => {
|
||||
config.data = config.data || {}
|
||||
config.data.ticket = md5(`hello_syzb_${dayjs().format('YYYYMMDD')}`)
|
||||
if(config.data.ip == '全部'){
|
||||
config.data.ip = ''
|
||||
}
|
||||
if(config.data.name == '全部'){
|
||||
config.data.name = ''
|
||||
}
|
||||
return config;
|
||||
}, error => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
HttpReq.interceptors.response.use(resp => {
|
||||
if (resp.code) {
|
||||
console.log({
|
||||
title: "HttpRequestError-" + resp.code,
|
||||
content: resp.message,
|
||||
});
|
||||
}
|
||||
return resp.data.data;
|
||||
})
|
||||
|
||||
function post(host, url, data) {
|
||||
if (!host) {
|
||||
return;
|
||||
}
|
||||
const targetUrl = (host + url)
|
||||
return HttpReq({
|
||||
url: targetUrl,
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
function fillTimeData(startTime, endTime, data) {
|
||||
const result = [];
|
||||
const timeMap = new Map();
|
||||
|
||||
// 建立已有数据的映射,key 是时间字符串
|
||||
data.forEach(item => {
|
||||
timeMap.set(item.time, item);
|
||||
});
|
||||
|
||||
let current = dayjs(startTime).second(0);
|
||||
console.log(current.minute());
|
||||
while (current.minute() % 5 !== 0) {
|
||||
current = current.add(1, 'minute');
|
||||
}
|
||||
const end = dayjs(endTime);
|
||||
console.log(current.isSameOrBefore);
|
||||
|
||||
while (current.isBefore(end) || current.isSame(end)) {
|
||||
const timeStr = current.format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
if (timeMap.has(timeStr)) {
|
||||
result.push(timeMap.get(timeStr));
|
||||
} else {
|
||||
result.push({
|
||||
averageTime: 0,
|
||||
failure: 0,
|
||||
interfaceName: null,
|
||||
ip: null,
|
||||
maxTime: 0,
|
||||
minTime: 0,
|
||||
over1000ms: 0,
|
||||
over100ms: 0,
|
||||
over10ms: 0,
|
||||
over5000ms: 0,
|
||||
over500ms: 0,
|
||||
over50ms: 0,
|
||||
time: timeStr,
|
||||
total: 0
|
||||
});
|
||||
}
|
||||
current = current.add(5, 'minute');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function drawLine(data, title, div, field, filter) {
|
||||
if (data && data.length) {
|
||||
const xyData = data.map(v => [v.time, v[field]]);
|
||||
const chart = echarts.init(document.getElementById(div));
|
||||
chart.setOption({
|
||||
title: {
|
||||
text: title
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
// data: xDate
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'line',
|
||||
data: xyData,
|
||||
showSymbol: false,
|
||||
lineStyle: {
|
||||
color: '#409eff' // 设置折线的颜色为红色
|
||||
},
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const API = {
|
||||
listIP: function (host, data) {
|
||||
return post(host, '/admin/monitor/listIP', data);
|
||||
},
|
||||
listInterface: function (host, data) {
|
||||
return post(host, '/admin/monitor/listInterface', data);
|
||||
},
|
||||
listData: function (host, data) {
|
||||
return post(host, '/admin/monitor/listData', data);
|
||||
},
|
||||
groupData: function (host, data) {
|
||||
return post(host, '/admin/monitor/groupData', data);
|
||||
},
|
||||
}
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
query: {
|
||||
host: "https://do.tgsys.sztg.com",
|
||||
// startTime: dayjs().format('YYYY-MM-DD 00:00:00'),
|
||||
// endTime: dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'),
|
||||
startTime: dayjs().format('YYYY-MM-DD 00:00:00'),
|
||||
endTime: dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'),
|
||||
ip: "",
|
||||
name: "",
|
||||
groupBy: "name",
|
||||
orderBy: "",
|
||||
},
|
||||
data: {
|
||||
host: ["https://do.tgsys.sztg.com", "http://8.138.144.54:8080", "http://127.0.0.1:8080"],
|
||||
ip: [],
|
||||
name: [],
|
||||
groupBy: ["name", "ip"],
|
||||
groupData: [],
|
||||
showLine: false,
|
||||
showTable: false,
|
||||
},
|
||||
monitor: [],
|
||||
interval: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async init(loadName = true) {
|
||||
const ip = await API.listIP(this.query.host, this.query)
|
||||
if (ip) {
|
||||
ip.unshift("全部")
|
||||
this.data.ip = ip;
|
||||
this.query.ip = ip[0];
|
||||
}
|
||||
if (loadName) {
|
||||
const name = await API.listInterface(this.query.host, this.query)
|
||||
if(name){
|
||||
name.unshift("全部")
|
||||
this.data.name = name;
|
||||
this.query.name = name[0];
|
||||
}
|
||||
}
|
||||
},
|
||||
async listData() {
|
||||
let data = await API.listData(this.query.host, this.query);
|
||||
// console.log('before', data);
|
||||
data = fillTimeData(this.query.startTime, this.query.endTime, data);
|
||||
// console.log('after', data);
|
||||
drawLine(data, '总流量', 'total', 'total');
|
||||
drawLine(data, '平均耗时', 'average', 'averageTime');
|
||||
drawLine(data, '失败流量', 'failure', 'failure');
|
||||
drawLine(data, '超时流量', 'timeout', 'over5000ms');
|
||||
this.data.showLine = true;
|
||||
this.data.showTable = false;
|
||||
},
|
||||
async groupData() {
|
||||
let groupData = await API.groupData(this.query.host, this.query);
|
||||
groupData = groupData.filter(data => data.interfaceName && data.interfaceName.indexOf('/admin/monitor') === -1);
|
||||
this.data.groupData = groupData;
|
||||
this.data.showLine = false;
|
||||
this.data.showTable = true;
|
||||
},
|
||||
async sortChange({column, prop, order}) {
|
||||
console.log('sortChange', column, prop, order);
|
||||
this.query.orderBy = prop;
|
||||
this.query.order = order;
|
||||
console.log(this.query);
|
||||
this.groupData();
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.init();
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
26
shell/prod/advisor/deploy/grep_log.sh
Normal file
26
shell/prod/advisor/deploy/grep_log.sh
Normal file
@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
KEYWORD="3mc31t"
|
||||
|
||||
# 目标服务器信息(格式:IP地址:端口)
|
||||
SERVERS=(
|
||||
"172.26.1.3:22"
|
||||
"172.26.1.7:22"
|
||||
"172.26.1.9:22"
|
||||
"172.26.1.15:22"
|
||||
)
|
||||
|
||||
# 目标路径
|
||||
LOG_DIR="/data/logs/advisor"
|
||||
|
||||
for SERVER in "${SERVERS[@]}"; do
|
||||
# 获取 IP 和端口
|
||||
IP=$(echo $SERVER | cut -d ':' -f 1)
|
||||
PORT=$(echo $SERVER | cut -d ':' -f 2)
|
||||
|
||||
# 查询日期
|
||||
echo "log on $IP:"
|
||||
ssh -p $PORT ubuntu@$IP "grep -n $KEYWORD $LOG_DIR/*.log"
|
||||
done
|
||||
|
||||
echo "All logs printed."
|
||||
42
shell/prod/advisor/win/grep_log.bat
Normal file
42
shell/prod/advisor/win/grep_log.bat
Normal file
@ -0,0 +1,42 @@
|
||||
@echo off
|
||||
|
||||
:: 1. 设置动态参数
|
||||
set REMOTE_IP=119.29.151.152
|
||||
set REMOTE_PORT=22101
|
||||
set REMOTE_USER=ubuntu
|
||||
set SCRIPT_PATH=/home/ubuntu/grep_log.sh
|
||||
|
||||
REM 检查是否提供了参数
|
||||
if "%~1"=="" (
|
||||
echo Usage: grep_log.bat <KEYWORD> [-A <n>] [-B <n>] [-C <n>]
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM 设置变量
|
||||
set KEYWORD=%1
|
||||
shift
|
||||
|
||||
REM 解析选项
|
||||
set OPTIONS=
|
||||
|
||||
:parse_options
|
||||
if "%~1"=="" goto done
|
||||
if "%~1"=="-A" (
|
||||
set OPTIONS=-A %2
|
||||
shift
|
||||
)
|
||||
if "%~1"=="-B" (
|
||||
set OPTIONS=-B %2
|
||||
shift
|
||||
)
|
||||
if "%~1"=="-C" (
|
||||
set OPTIONS=-C %2
|
||||
shift
|
||||
)
|
||||
shift
|
||||
goto parse_options
|
||||
|
||||
:done
|
||||
|
||||
REM 远程执行 Linux 脚本
|
||||
call ssh -p %REMOTE_PORT% %REMOTE_USER%@%REMOTE_IP% "bash %SCRIPT_PATH% %KEYWORD% %OPTIONS%"
|
||||
153
sql/clear_user.sql
Normal file
153
sql/clear_user.sql
Normal file
@ -0,0 +1,153 @@
|
||||
-- 开始事务
|
||||
START TRANSACTION;
|
||||
|
||||
-- 创建临时表
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_user_id AS (
|
||||
SELECT user_id FROM user_dept WHERE user_id IN (0)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS user_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_login_id AS (
|
||||
SELECT login_id FROM user_dept WHERE user_id IN (select user_id from temp_user_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS login_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_advisor_id AS (
|
||||
SELECT id AS advisor_id FROM advisor_info WHERE user_id IN (select user_id from temp_user_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS login_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_video_id AS (
|
||||
SELECT id AS video_id FROM video_live WHERE advisor_id IN (select advisor_id from temp_advisor_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS video_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_group_id AS (
|
||||
SELECT id AS group_id FROM group_info WHERE advisor_id IN (select advisor_id from temp_advisor_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS group_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_group_message_id AS (
|
||||
SELECT id AS message_id FROM group_message WHERE group_id IN (select group_id from temp_group_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS message_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_course_id AS (
|
||||
SELECT id AS course_id FROM course WHERE advisor_id IN (select advisor_id from temp_advisor_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS course_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_serial_id AS (
|
||||
SELECT id AS serial_id FROM serial WHERE advisor_id IN (select advisor_id from temp_advisor_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS serial_id FROM dual
|
||||
);
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS temp_short_video_id AS (
|
||||
SELECT id AS video_id FROM short_video WHERE advisor_id IN (select advisor_id from temp_advisor_id)
|
||||
-- union 0 防止结果集为空
|
||||
UNION ALL
|
||||
SELECT 0 AS video_id FROM dual
|
||||
);
|
||||
|
||||
-- 测试临时表
|
||||
-- SELECT * FROM temp_user_id;
|
||||
-- SELECT * FROM temp_login_id;
|
||||
-- SELECT * FROM temp_advisor_id;
|
||||
-- SELECT * FROM temp_video_id;
|
||||
-- SELECT * FROM temp_group_id;
|
||||
|
||||
-- 清理直播
|
||||
delete from video_user_watch_collect where video_id in (select video_id from temp_video_id);
|
||||
delete from video_user_time_collect where video_id in (select video_id from temp_video_id);
|
||||
delete from video_user_flow where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_user where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_tag where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_risk where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_push where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_mix where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_message where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_library where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_customer_sale where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_column_video where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live_activity where advisor_id in (select advisor_id from temp_advisor_id);
|
||||
delete from video_cart where video_id in (select video_id from temp_video_id);
|
||||
delete from video_browse_detail where video_id in (select video_id from temp_video_id);
|
||||
delete from video_behavior_notify where video_id in (select video_id from temp_video_id);
|
||||
delete from video_live where id in (select video_id from temp_video_id);
|
||||
|
||||
-- 清理圈子
|
||||
delete from group_user_flow where group_id in (select group_id from temp_group_id);
|
||||
delete from group_user_collect where group_id in (select group_id from temp_group_id);
|
||||
delete from group_message_read where message_id in (select message_id from temp_group_message_id);
|
||||
delete from group_message where group_id in (select group_id from temp_group_id);
|
||||
delete from group_collect where group_id in (select group_id from temp_group_id);
|
||||
delete from group_info where id in (select group_id from temp_group_id);
|
||||
|
||||
-- 清理课程
|
||||
delete from course_content where course_id in (select course_id from temp_course_id);
|
||||
delete from course where id in (select course_id from temp_course_id);
|
||||
|
||||
-- 清理合集
|
||||
delete from serial_content where serial_id in (select serial_id from temp_serial_id);
|
||||
delete from serial where id in (select serial_id from temp_serial_id);
|
||||
|
||||
-- 清理短视频
|
||||
delete from short_video_watch where video_id in (select video_id from temp_short_video_id);
|
||||
delete from short_video_share where video_id in (select video_id from temp_short_video_id);
|
||||
delete from short_video_sale where video_id in (select video_id from temp_short_video_id);
|
||||
delete from short_video_favor where video_id in (select video_id from temp_short_video_id);
|
||||
delete from short_video_cart_click where video_id in (select video_id from temp_short_video_id);
|
||||
delete from short_video_cart where video_id in (select video_id from temp_short_video_id);
|
||||
delete from short_video where id in (select video_id from temp_short_video_id);
|
||||
|
||||
-- 清理订单
|
||||
delete from app_order where product_id in (select video_id from temp_video_id) and product_type = 3;
|
||||
delete from app_order where product_id in (select group_id from temp_group_id) and product_type = 41;
|
||||
delete from app_order where product_id in (select course_id from temp_course_id) and product_type = 32;
|
||||
delete from app_order where product_id in (select serial_id from temp_serial_id) and product_type = 33;
|
||||
delete from app_order where product_id in (select video_id from temp_short_video_id) and product_type = 35;
|
||||
|
||||
-- 清理RBAC
|
||||
delete from user_dept where user_id in (select user_id from temp_user_id);
|
||||
delete from user where id in (select user_id from temp_user_id);
|
||||
delete from users_roles where user_id in (select user_id from temp_user_id);
|
||||
delete from user_login where login_id in (select login_id from temp_login_id);
|
||||
|
||||
-- 清理投顾
|
||||
delete from advisor_info where id in (select advisor_id from temp_advisor_id);
|
||||
|
||||
-- 清理临时表
|
||||
DROP TEMPORARY TABLE temp_user_id;
|
||||
|
||||
DROP TEMPORARY TABLE temp_login_id;
|
||||
|
||||
DROP TEMPORARY TABLE temp_advisor_id;
|
||||
|
||||
DROP TEMPORARY TABLE temp_video_id;
|
||||
|
||||
DROP TEMPORARY TABLE temp_group_id;
|
||||
|
||||
DROP TEMPORARY TABLE temp_group_message_id;
|
||||
|
||||
DROP TEMPORARY TABLE temp_course_id;
|
||||
|
||||
DROP TEMPORARY TABLE temp_serial_id;
|
||||
|
||||
-- 提交事务
|
||||
COMMIT;
|
||||
@ -1,11 +1,14 @@
|
||||
package com.syzb.advisor.entity;
|
||||
|
||||
import com.syzb.rbac.entity.UserLogin;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class AdvisorBasic implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public Integer id;
|
||||
public Integer userId;
|
||||
public String workNo;
|
||||
public String name;
|
||||
public String showName;
|
||||
public String avatar;
|
||||
@ -20,9 +23,12 @@ public class AdvisorBasic implements Serializable {
|
||||
public AdvisorBasic() {
|
||||
}
|
||||
|
||||
public AdvisorBasic(AdvisorInfo advisorInfo, String deptName) {
|
||||
public AdvisorBasic(AdvisorInfo advisorInfo, String deptName, UserLogin user) {
|
||||
this.id = advisorInfo.getId();
|
||||
this.userId = advisorInfo.getUserId();
|
||||
if (user != null) {
|
||||
this.workNo = user.getUpId();
|
||||
}
|
||||
this.name = advisorInfo.getName();
|
||||
this.showName = advisorInfo.getShowName();
|
||||
this.avatar = advisorInfo.getAvatar();
|
||||
@ -43,6 +49,14 @@ public class AdvisorBasic implements Serializable {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getWorkNo() {
|
||||
return workNo;
|
||||
}
|
||||
|
||||
public void setWorkNo(String workNo) {
|
||||
this.workNo = workNo;
|
||||
}
|
||||
|
||||
public String getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
@ -42,7 +42,6 @@ import com.syzb.rbac.entity.UsersRoles;
|
||||
import com.syzb.rbac.mapper.UsersRolesMapper;
|
||||
import com.syzb.rbac.service.DeptService;
|
||||
import com.syzb.rbac.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -98,6 +97,9 @@ public class AdvisorInfoService {
|
||||
@Value("${advisor.roleId}")
|
||||
private Integer advisorRoleId;
|
||||
|
||||
@Value("${user.admin.roles}")
|
||||
private Integer adminRoleId;
|
||||
|
||||
public static final Set<Integer> TG_SHOW_STATUS = ImmutableSet.of(
|
||||
AdvisorInfoStatus.PASS.value,
|
||||
AdvisorInfoStatus.EVENT_SUBMIT.value,
|
||||
@ -105,34 +107,39 @@ public class AdvisorInfoService {
|
||||
);
|
||||
|
||||
public Map<Integer, AdvisorBasic> getAdvisorMap() {
|
||||
Map<Integer, UserLogin> userIdLoginMap = userService.getUserUserIdLoginMap();
|
||||
return cacheService.get(ADVISOR_INFO, AdvisorInfoKey.ADVISOR_MAP, () -> {
|
||||
List<AdvisorInfo> advisorList = advisorInfoMapper.selectList(Wrappers.emptyWrapper());
|
||||
return advisorList.stream().collect(Collectors.toMap(AdvisorInfo::getId, advisor ->
|
||||
new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId()))));
|
||||
new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId()), userIdLoginMap.get(advisor.getUserId()))));
|
||||
});
|
||||
}
|
||||
|
||||
public Map<Integer, AdvisorBasicVO> getAdvisorVoMap() {
|
||||
Map<Integer, UserLogin> userIdLoginMap = userService.getUserUserIdLoginMap();
|
||||
return cacheService.get(ADVISOR_INFO, AdvisorInfoKey.ADVISOR_VO_MAP, () -> {
|
||||
List<AdvisorInfo> advisorList = advisorInfoMapper.selectList(Wrappers.emptyWrapper());
|
||||
return advisorList.stream().collect(Collectors.toMap(AdvisorInfo::getId, advisor ->
|
||||
new AdvisorBasicVO(new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId())))));
|
||||
new AdvisorBasicVO(new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId()), userIdLoginMap.get(advisor.getUserId())))));
|
||||
});
|
||||
}
|
||||
|
||||
public Map<Integer, AdvisorBasic> getUserIdAdvisorMap() {
|
||||
Map<Integer, UserLogin> userIdLoginMap = userService.getUserUserIdLoginMap();
|
||||
return cacheService.get(ADVISOR_INFO, AdvisorInfoKey.USER_ADVISOR_MAP, () -> {
|
||||
List<AdvisorInfo> advisorList = advisorInfoMapper.selectList(Wrappers.emptyWrapper());
|
||||
return advisorList.stream().filter(advisor -> advisor.getUserId() != null).collect(Collectors.toMap(AdvisorInfo::getUserId, advisor ->
|
||||
new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId()))));
|
||||
new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId()), userIdLoginMap.get(advisor.getUserId()))));
|
||||
});
|
||||
}
|
||||
|
||||
public Map<String, List<AdvisorBasic>> getDeptIdAdvisorMap() {
|
||||
Map<Integer, UserLogin> userIdLoginMap = userService.getUserUserIdLoginMap();
|
||||
return cacheService.get(ADVISOR_INFO, AdvisorInfoKey.USER_ADVISOR_DEPT_MAP, () -> {
|
||||
List<AdvisorInfo> advisorList = advisorInfoMapper.selectList(Wrappers.emptyWrapper());
|
||||
return advisorList.stream().filter(advisor -> StrUtil.isNotBlank(advisor.getDeptId())).map(advisor ->
|
||||
new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId()))).collect(Collectors.groupingBy(AdvisorBasic::getDeptId));
|
||||
new AdvisorBasic(advisor, deptService.getDeptNameByAdvisorId(advisor.getId()), userIdLoginMap.get(advisor.getUserId())))
|
||||
.collect(Collectors.groupingBy(AdvisorBasic::getDeptId));
|
||||
});
|
||||
}
|
||||
|
||||
@ -150,7 +157,7 @@ public class AdvisorInfoService {
|
||||
if (dept != null && DeptType.HEAD.value.equals(dept.getType())) {
|
||||
deptId = null;
|
||||
}
|
||||
if (backendUserVO.getRoles().contains(StateMachine.ROLE.ADMIN)) {
|
||||
if (backendUserVO.getRoles().contains(adminRoleId)) {
|
||||
deptId = null;
|
||||
}
|
||||
Map<Integer, UserLogin> userLoginMap = userService.getUserLoginMap();
|
||||
|
||||
@ -13,6 +13,12 @@ public class AdvisorBasicVO implements Serializable {
|
||||
@ApiModelProperty("用户id")
|
||||
private Integer userId;
|
||||
|
||||
@ApiModelProperty("用户工号")
|
||||
private String staffNo;
|
||||
|
||||
@ApiModelProperty("工号")
|
||||
private String workNo;
|
||||
|
||||
@ApiModelProperty("投顾名称")
|
||||
private String name;
|
||||
|
||||
@ -37,6 +43,8 @@ public class AdvisorBasicVO implements Serializable {
|
||||
public AdvisorBasicVO(AdvisorBasic advisorBasic) {
|
||||
this.id = advisorBasic.id;
|
||||
this.userId = advisorBasic.userId;
|
||||
this.staffNo = advisorBasic.staffNo;
|
||||
this.workNo = advisorBasic.workNo;
|
||||
this.name = advisorBasic.name;
|
||||
this.showName = advisorBasic.showName;
|
||||
this.avatar = advisorBasic.avatar;
|
||||
@ -61,6 +69,23 @@ public class AdvisorBasicVO implements Serializable {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getStaffNo() {
|
||||
return staffNo;
|
||||
}
|
||||
|
||||
public void setStaffNo(String staffNo) {
|
||||
this.staffNo = staffNo;
|
||||
}
|
||||
|
||||
|
||||
public String getWorkNo() {
|
||||
return workNo;
|
||||
}
|
||||
|
||||
public void setWorkNo(String workNo) {
|
||||
this.workNo = workNo;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@ -108,4 +133,5 @@ public class AdvisorBasicVO implements Serializable {
|
||||
public void setProfile(String profile) {
|
||||
this.profile = profile;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,33 +1,71 @@
|
||||
package com.syzb.app.controller;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.query.AppUserInfoQuery;
|
||||
import com.syzb.common.query.CheckAuthQuery;
|
||||
import com.syzb.common.result.CommonResult;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.service.AppUserService;
|
||||
import com.syzb.common.util.JwtUtil;
|
||||
import com.syzb.common.util.logger.LoggerUtil;
|
||||
import com.syzb.common.vo.AppCUserInfoVO;
|
||||
import com.syzb.common.vo.AuthResultVO;
|
||||
import com.syzb.common.vo.FrontUserVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Api(tags = "App用户信息")
|
||||
@RestController
|
||||
@RequestMapping("/app/user/")
|
||||
@Validated
|
||||
public class AppUserController {
|
||||
|
||||
@Value("${jwt.key}")
|
||||
private String jwtKey;
|
||||
|
||||
@Value("${jwt.secret}")
|
||||
private String jwtSecret;
|
||||
|
||||
@Resource
|
||||
private AppUserService appUserService;
|
||||
|
||||
@ApiOperation("获取C端用户信息")
|
||||
@PostMapping("getUserInfo")
|
||||
@CrossOrigin(origins = "*", allowedHeaders = "*", maxAge = 3600)
|
||||
public CommonResult<AppCUserInfoVO> getUserInfo(@Validated @RequestBody AppUserInfoQuery query) {
|
||||
AppCUserInfoVO vo = appUserService.getUserInfo(query);
|
||||
return CommonResult.success(vo);
|
||||
}
|
||||
|
||||
@ApiOperation("C端用户鉴权")
|
||||
@PostMapping("checkAuth")
|
||||
@CrossOrigin(origins = "*", allowedHeaders = "*", maxAge = 3600)
|
||||
public CommonResult<AuthResultVO> checkAuth(@Validated @RequestBody CheckAuthQuery query) {
|
||||
String token = query.getToken();
|
||||
if (StrUtil.isBlank(token) || "undefined".equals(token)) {
|
||||
throw new BizException(ResponseStatus.SESSION_EXPIRY);
|
||||
}
|
||||
FrontUserVO frontUserVO = null;
|
||||
try {
|
||||
String decodeStr = JwtUtil.verify(jwtSecret, jwtKey, token);
|
||||
if (StrUtil.isNotBlank(decodeStr)) {
|
||||
frontUserVO = JSONObject.parseObject(decodeStr, FrontUserVO.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LoggerUtil.error(e);
|
||||
throw new BizException(ResponseStatus.SESSION_EXPIRY);
|
||||
}
|
||||
if (frontUserVO == null) {
|
||||
throw new BizException(ResponseStatus.SESSION_EXPIRY);
|
||||
}
|
||||
AuthResultVO vo = appUserService.checkAuth(query.getAuth(), frontUserVO);
|
||||
return CommonResult.success(vo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,11 +12,9 @@ import com.syzb.common.util.logger.LoggerUtil;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
@ -11,7 +11,6 @@ import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Date;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@ -36,7 +35,7 @@ public class TaskAspect {
|
||||
@AfterReturning(pointcut = "scheduledPointcut()")
|
||||
public void afterReturningCall(JoinPoint joinPoint) {
|
||||
long start = RequestIdUtil.getTime();
|
||||
long time = new Date().getTime() - start;
|
||||
long time = System.currentTimeMillis() - start;
|
||||
// 获取注解中的参数值
|
||||
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package com.syzb.common.aspect;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.util.RequestIdUtil;
|
||||
import com.syzb.common.util.logger.LoggerUtil;
|
||||
import com.syzb.monitor.service.MonitorService;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.*;
|
||||
@ -12,17 +15,20 @@ import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class WebLogAspect {
|
||||
|
||||
@Resource
|
||||
private MonitorService monitorService;
|
||||
|
||||
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
|
||||
private void requestPointcut() {
|
||||
}
|
||||
@ -51,8 +57,9 @@ public class WebLogAspect {
|
||||
}
|
||||
arguments.add(arg);
|
||||
}
|
||||
if (!request.getRequestURI().contains("/swagger") && !request.getRequestURI().contains("/v3/api-docs")) {
|
||||
LoggerUtil.data.info(String.format("%s:param:%s", request.getRequestURI(), JSONObject.toJSONString(arguments)));
|
||||
String uri = request.getRequestURI();
|
||||
if (!uri.contains("/swagger") && !uri.contains("/v3/api-docs")) {
|
||||
LoggerUtil.data.info(String.format("%s:param:%s", uri, JSONObject.toJSONString(arguments)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,22 +67,29 @@ public class WebLogAspect {
|
||||
@AfterReturning(returning = "returnOb", pointcut = "requestPointcut() || getPointcut() || postPointcut())")
|
||||
public void afterReturningCall(JoinPoint joinPoint, Object returnOb) {
|
||||
long start = RequestIdUtil.getTime();
|
||||
long time = new Date().getTime() - start;
|
||||
long time = System.currentTimeMillis() - start;
|
||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
|
||||
HttpServletRequest request = requestAttributes.getRequest();
|
||||
if (!request.getRequestURI().contains("/swagger") && !request.getRequestURI().contains("/v3/api-docs") && !(returnOb instanceof HttpEntity)) {
|
||||
LoggerUtil.data.info(String.format("%s:耗时:%d", request.getRequestURI(), time));
|
||||
LoggerUtil.data.info(String.format("%s:result:%s", request.getRequestURI(), JSONObject.toJSONString(returnOb)));
|
||||
String uri = request.getRequestURI();
|
||||
if (!uri.contains("/swagger") && !uri.contains("/v3/api-docs") && !(returnOb instanceof HttpEntity)) {
|
||||
LoggerUtil.data.info(String.format("%s:耗时:%d", uri, time));
|
||||
LoggerUtil.data.info(String.format("%s:result:%s", uri, JSONObject.toJSONString(returnOb)));
|
||||
monitorService.add(uri, (int) time);
|
||||
}
|
||||
}
|
||||
|
||||
// 异常通知
|
||||
@AfterThrowing(value = "requestPointcut() || getPointcut() || postPointcut()", throwing = "ex")
|
||||
public void afterThrowing(JoinPoint joinPoint, Exception ex) {
|
||||
long start = RequestIdUtil.getTime();
|
||||
long time = System.currentTimeMillis() - start;
|
||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
|
||||
HttpServletRequest request = requestAttributes.getRequest();
|
||||
if (!request.getRequestURI().contains("/swagger") && !request.getRequestURI().contains("/v3/api-docs")) {
|
||||
LoggerUtil.data.info(String.format("%s:exception:%s", request.getRequestURI(), ExceptionUtils.getStackTrace(ex)));
|
||||
String uri = request.getRequestURI();
|
||||
if (!uri.contains("/swagger") && !uri.contains("/v3/api-docs")) {
|
||||
LoggerUtil.data.info(String.format("%s:exception:%s", uri, ExceptionUtils.getStackTrace(ex)));
|
||||
Integer code = ex instanceof BizException ? ((BizException)ex).getErrorCode() : ResponseStatus.SYS_BUSY.code;
|
||||
monitorService.add(uri, (int) time, code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -169,6 +169,9 @@ public class TencentCloudConfig {
|
||||
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
||||
HttpProfile httpProfile = new HttpProfile();
|
||||
httpProfile.setEndpoint(this.vodEndpoint);
|
||||
httpProfile.setConnTimeout(60);
|
||||
httpProfile.setReadTimeout(60);
|
||||
httpProfile.setWriteTimeout(60);
|
||||
|
||||
// 实例化一个client选项,可选的,没有特殊需求可以跳过
|
||||
ClientProfile clientProfile = new ClientProfile();
|
||||
@ -186,6 +189,9 @@ public class TencentCloudConfig {
|
||||
// 实例化一个http选项,可选的,没有特殊需求可以跳过
|
||||
HttpProfile httpProfile = new HttpProfile();
|
||||
httpProfile.setEndpoint(this.liveEndpoint);
|
||||
httpProfile.setConnTimeout(60);
|
||||
httpProfile.setReadTimeout(60);
|
||||
httpProfile.setWriteTimeout(60);
|
||||
// 实例化一个client选项,可选的,没有特殊需求可以跳过
|
||||
ClientProfile clientProfile = new ClientProfile();
|
||||
clientProfile.setHttpProfile(httpProfile);
|
||||
|
||||
@ -66,6 +66,11 @@ public class CacheConfig {
|
||||
|
||||
configMap.put(COURSE, new LocalMapConfig(10000, 300));
|
||||
configMap.put(GROUP, new LocalMapConfig(10000, 300));
|
||||
configMap.put(WX_USER, new LocalMapConfig(10000, 3600));
|
||||
|
||||
configMap.put(VIDEO_ONLINE_USER, new LocalMapConfig(1000000, 172800, InMemoryFormat.OBJECT));
|
||||
configMap.put(GROUP_ONLINE_USER, new LocalMapConfig(1000000, 172800, InMemoryFormat.OBJECT));
|
||||
|
||||
return configMap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,6 +305,12 @@ public class CacheKey {
|
||||
public static final String CUSTOMER_SALE = "customer_sale|";
|
||||
}
|
||||
|
||||
public static final String WX_USER = "wx_user";
|
||||
|
||||
public static final class WxUserKey {
|
||||
public static final String USER = "user|";
|
||||
}
|
||||
|
||||
public static final String SCREEN = "screen";
|
||||
|
||||
public static final class ScreenKey {
|
||||
|
||||
@ -10,9 +10,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Configuration
|
||||
public class HazelcastConfiguration {
|
||||
@ -23,6 +21,8 @@ public class HazelcastConfiguration {
|
||||
@Value("${hazelcast.serverPort}")
|
||||
private Integer serverPort;
|
||||
|
||||
private Set<String> cacheNameSet = new HashSet<>();
|
||||
|
||||
@Bean
|
||||
public HazelcastInstance hazelcastInstance() {
|
||||
List<String> memberList = Arrays.asList(members.split(","));
|
||||
@ -39,8 +39,10 @@ public class HazelcastConfiguration {
|
||||
config.setInstanceName(instanceName);
|
||||
config.setClusterName(clusterName);
|
||||
for (Map.Entry<String, CacheConfig.LocalMapConfig> entry : CacheConfig.getConfigMap().entrySet()) {
|
||||
String cacheName = entry.getKey();
|
||||
cacheNameSet.add(cacheName);
|
||||
config.addMapConfig(new MapConfig()
|
||||
.setName(entry.getKey())
|
||||
.setName(cacheName)
|
||||
.setEvictionConfig(new EvictionConfig()
|
||||
.setEvictionPolicy(EvictionPolicy.LRU)
|
||||
.setSize(entry.getValue().maxSize)
|
||||
@ -79,6 +81,12 @@ public class HazelcastConfiguration {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void cleanCache() {
|
||||
for (String cacheName : cacheNameSet) {
|
||||
hazelcastInstance().getMap(cacheName).clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static void createMapping(HazelcastInstance instance) {
|
||||
SqlService sqlService = instance.getSql();
|
||||
sqlService.execute("CREATE OR REPLACE MAPPING " + CacheKey.VIDEO_ONLINE_USER + " TYPE IMap OPTIONS (" +
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
package com.syzb.common.controller;
|
||||
|
||||
import com.syzb.common.config.cache.HazelcastConfiguration;
|
||||
import com.syzb.common.result.CommonResult;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@RestController
|
||||
@Validated
|
||||
public class CacheController {
|
||||
|
||||
@Resource
|
||||
private HazelcastConfiguration hazelcastConfiguration;
|
||||
|
||||
@GetMapping("/admin/cache/clean")
|
||||
public CommonResult<Void> clean(@Validated @RequestParam("code") @NotBlank String code) {
|
||||
if (!code.equals("hello_syzb")) {
|
||||
return CommonResult.error(ResponseStatus.PERMISSION_ERROR);
|
||||
}
|
||||
hazelcastConfiguration.cleanCache();
|
||||
return CommonResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,11 +4,10 @@ import com.hazelcast.map.IMap;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.entity.OnlineUser;
|
||||
import com.syzb.common.service.OnlineUserService;
|
||||
import com.syzb.common.vo.FrontUserVO;
|
||||
import com.syzb.group.service.common.GroupCacheService;
|
||||
import com.syzb.group.service.common.GroupMessageService;
|
||||
import com.syzb.video.helper.VideoHelper;
|
||||
import com.syzb.video.service.common.VideoCacheService;
|
||||
import com.syzb.video.service.common.VideoMessageService;
|
||||
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -20,17 +19,14 @@ import java.util.Map;
|
||||
@Component
|
||||
public class WebSocketSessionHandler {
|
||||
|
||||
@Resource
|
||||
private VideoCacheService videoCacheService;
|
||||
|
||||
@Resource
|
||||
private VideoMessageService videoMessageService;
|
||||
|
||||
@Resource
|
||||
private GroupCacheService groupCacheService;
|
||||
private GroupMessageService groupMessageService;
|
||||
|
||||
@Resource
|
||||
private GroupMessageService groupMessageService;
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
public void handleConnect(StompHeaderAccessor header) {
|
||||
Map<String, Object> attributes = header.getSessionAttributes();
|
||||
@ -88,7 +84,7 @@ public class WebSocketSessionHandler {
|
||||
}
|
||||
|
||||
private void updateOnlineStatus(Integer productType, Integer productId, String sessionKey, OnlineUser onlineUser) {
|
||||
IMap<String, OnlineUser> totalOnlineMap = getTotalOnlineMap(productType, productId);
|
||||
IMap<String, OnlineUser> totalOnlineMap = onlineUserService.getTotalOnlineMap(productType);
|
||||
String cacheKey = VideoHelper.buildOnlineUserCacheKey(productId, sessionKey);
|
||||
if (totalOnlineMap != null) {
|
||||
totalOnlineMap.put(cacheKey, onlineUser);
|
||||
@ -104,7 +100,7 @@ public class WebSocketSessionHandler {
|
||||
Integer productType = sessionInfo.getProductType();
|
||||
Integer productId = sessionInfo.getProductId();
|
||||
String sessionKey = sessionInfo.getSessionKey();
|
||||
IMap<String, OnlineUser> totalOnlineMap = getTotalOnlineMap(productType, productId);
|
||||
IMap<String, OnlineUser> totalOnlineMap = onlineUserService.getTotalOnlineMap(productType);
|
||||
String cacheKey = VideoHelper.buildOnlineUserCacheKey(productId, sessionKey);
|
||||
OnlineUser onlineUser = totalOnlineMap.get(cacheKey);
|
||||
if (onlineUser != null) {
|
||||
@ -120,15 +116,6 @@ public class WebSocketSessionHandler {
|
||||
onlineUser.setExitTime(LocalDateTime.now());
|
||||
}
|
||||
|
||||
private IMap<String, OnlineUser> getTotalOnlineMap(Integer productType, Integer productId) {
|
||||
if (ProductType.VIDEO_SINGLE.value.equals(productType)) {
|
||||
return videoCacheService.getTotalOnlineMap();
|
||||
} else if (ProductType.GROUP.value.equals(productType)) {
|
||||
return groupCacheService.getTotalOnlineMap();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void memberNotify(Integer productType, Integer productId, OnlineUser onlineUser) {
|
||||
if (ProductType.VIDEO_SINGLE.value.equals(productType)) {
|
||||
videoMessageService.memberNotify(productId, onlineUser);
|
||||
|
||||
24
src/main/java/com/syzb/common/query/CheckAuthQuery.java
Normal file
24
src/main/java/com/syzb/common/query/CheckAuthQuery.java
Normal file
@ -0,0 +1,24 @@
|
||||
package com.syzb.common.query;
|
||||
|
||||
public class CheckAuthQuery {
|
||||
|
||||
private String auth;
|
||||
|
||||
private String token;
|
||||
|
||||
public String getAuth() {
|
||||
return auth;
|
||||
}
|
||||
|
||||
public void setAuth(String auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
||||
@ -131,7 +131,7 @@ public enum ResponseStatus {
|
||||
STATUS_ERROR(6006, "操作状态不对,不允许操作"),
|
||||
TAF_ERROR(6007, "TAF接口异常"),
|
||||
CURRENT_ORDER_ERROR(6008, "限价委托异常"),
|
||||
STAFF_NO_EXIST(6009, "登录账号或者UP号已存在"),
|
||||
STAFF_NO_EXIST(6009, "登录账号或者登录账号已存在"),
|
||||
VIEW_PACKAGE_NAME_EXIST(6010, "观点包名称已存在"),
|
||||
DEPT_EXIST(6011, "用户部门已存在"),
|
||||
COUNTER_ERROR(6011, "柜台接口异常"),
|
||||
|
||||
@ -28,6 +28,7 @@ import com.syzb.rbac.entity.Dept;
|
||||
import com.syzb.rbac.entity.UserDept;
|
||||
import com.syzb.rbac.service.DeptService;
|
||||
import com.syzb.rbac.service.UserService;
|
||||
import com.syzb.rbac.service.WxUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
@ -63,6 +64,9 @@ public class CommentBlackService {
|
||||
@Resource
|
||||
private DeptService deptService;
|
||||
|
||||
@Resource
|
||||
private WxUserService wxUserService;
|
||||
|
||||
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@ -198,6 +202,7 @@ public class CommentBlackService {
|
||||
commentBlackVO.setUserOrgName(dept.getName());
|
||||
}
|
||||
}
|
||||
commentBlackVO.setUserHeadPic(wxUserService.getHeadPic(commentBlackVO.getPhone()));
|
||||
}
|
||||
return new Pager<>(voList, page.getTotal());
|
||||
}
|
||||
|
||||
134
src/main/java/com/syzb/common/service/OnlineUserService.java
Normal file
134
src/main/java/com/syzb/common/service/OnlineUserService.java
Normal file
@ -0,0 +1,134 @@
|
||||
package com.syzb.common.service;
|
||||
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.map.IMap;
|
||||
import com.hazelcast.sql.SqlResult;
|
||||
import com.hazelcast.sql.SqlRow;
|
||||
import com.syzb.common.config.cache.CacheKey;
|
||||
import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.entity.OnlineUser;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.util.logger.LoggerUtil;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.syzb.common.config.cache.CacheKey.*;
|
||||
|
||||
@Service
|
||||
public class OnlineUserService {
|
||||
|
||||
@Resource
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
/**
|
||||
* 获取总在线用户映射
|
||||
*
|
||||
* @return 在线用户映射
|
||||
*/
|
||||
public IMap<String, OnlineUser> getTotalOnlineMap(Integer productType) {
|
||||
String cacheName = getOnlineCacheName(productType);
|
||||
return hazelcastInstance.getMap(cacheName);
|
||||
}
|
||||
|
||||
public List<OnlineUser> getTotalOnlineList(Integer productType, Integer productId) {
|
||||
String cacheName = getOnlineCacheName(productType);
|
||||
String sql = "SELECT * FROM " + cacheName + " WHERE productId = " + productId;
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
List<OnlineUser> list = new ArrayList<>();
|
||||
for (SqlRow row : result) {
|
||||
OnlineUser user = new OnlineUser();
|
||||
user.setProductType(row.getObject("productType"));
|
||||
user.setProductId(row.getObject("productId"));
|
||||
user.setUserId(row.getObject("userId"));
|
||||
user.setUserName(row.getObject("userName"));
|
||||
user.setImg(row.getObject("img"));
|
||||
user.setSessionId(row.getObject("sessionId"));
|
||||
user.setIsOnline(row.getObject("isOnline"));
|
||||
user.setIsPlay(row.getObject("isPlay"));
|
||||
user.setCreateTime(row.getObject("createTime"));
|
||||
user.setExitTime(row.getObject("exitTime"));
|
||||
list.add(user);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public Set<String> getOnlineUserIds(Integer productType, Integer productId) {
|
||||
String cacheName = getOnlineCacheName(productType);
|
||||
String sql = "SELECT distinct userId FROM " + cacheName + " WHERE productId = " + productId + " and isOnline = 1";
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
Set<String> set = new HashSet<>();
|
||||
for (SqlRow row : result) {
|
||||
set.add(row.getObject("userId"));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线人数
|
||||
*
|
||||
* @return 在线人数
|
||||
*/
|
||||
public int getOnlineCount(Integer productType, Integer productId) {
|
||||
String mainCacheName = getMainCacheName(productType);
|
||||
IMap<String, Object> map = hazelcastInstance.getMap(mainCacheName);
|
||||
String cacheKey = getOnlineCountCacheKey(productType, productId);
|
||||
Integer onlineCount = (Integer) map.get(cacheKey);
|
||||
if (onlineCount != null) {
|
||||
return onlineCount;
|
||||
}
|
||||
synchronized (this) {
|
||||
onlineCount = (Integer) map.get(cacheKey);
|
||||
if (onlineCount != null) {
|
||||
return onlineCount;
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
onlineCount = getOnlineCountWithoutCache(productType, productId);
|
||||
LoggerUtil.websocket.info("getOnlineCount-" + productType + "-" + productId + ":" + (System.currentTimeMillis() - startTime) + "ms");
|
||||
map.put(cacheKey, onlineCount, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
return onlineCount;
|
||||
}
|
||||
|
||||
public int getOnlineCountWithoutCache(Integer productType, Integer productId) {
|
||||
String cacheName = getOnlineCacheName(productType);
|
||||
String sql = "SELECT COUNT(*) FROM " + cacheName + " WHERE productId = " + productId + " and isOnline = 1";
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
Iterator<SqlRow> iter = result.iterator();
|
||||
if (iter.hasNext()) {
|
||||
return ((Long)iter.next().getObject(0)).intValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String getMainCacheName(Integer productType) {
|
||||
if (ProductType.VIDEO_SINGLE.value.equals(productType)) {
|
||||
return VIDEO_LIVE;
|
||||
} else if (ProductType.GROUP.value.equals(productType)) {
|
||||
return GROUP;
|
||||
}
|
||||
throw new BizException(ResponseStatus.SYS_BUSY, "productType错误");
|
||||
}
|
||||
|
||||
private String getOnlineCacheName(Integer productType) {
|
||||
if (ProductType.VIDEO_SINGLE.value.equals(productType)) {
|
||||
return VIDEO_ONLINE_USER;
|
||||
} else if (ProductType.GROUP.value.equals(productType)) {
|
||||
return GROUP_ONLINE_USER;
|
||||
}
|
||||
throw new BizException(ResponseStatus.SYS_BUSY, "productType错误");
|
||||
}
|
||||
|
||||
private String getOnlineCountCacheKey(Integer productType, Integer productId) {
|
||||
if (ProductType.VIDEO_SINGLE.value.equals(productType)) {
|
||||
return CacheKey.VideoLiveKey.ONLINE_COUNT + productId;
|
||||
} else if (ProductType.GROUP.value.equals(productType)) {
|
||||
return CacheKey.GroupKey.ONLINE_COUNT + productId;
|
||||
}
|
||||
throw new BizException(ResponseStatus.SYS_BUSY, "productType错误");
|
||||
}
|
||||
|
||||
}
|
||||
@ -18,14 +18,14 @@ public class AdvisorInfoStateMachine {
|
||||
advisorInfoSM.add(AdvisorInfoStatus.INIT, AdvisorInfoStatus.EVENT_UPDATE, StateMachine.ROLE.ADVISOR, AdvisorInfoStatus.INIT);
|
||||
|
||||
// 待审核 -> 管理员[驳回] -> 已驳回
|
||||
advisorInfoSM.add(AdvisorInfoStatus.TO_AUDIT, AdvisorInfoStatus.EVENT_REJECT, StateMachine.ROLE.ADMIN, AdvisorInfoStatus.REJECTED);
|
||||
advisorInfoSM.add(AdvisorInfoStatus.TO_AUDIT, AdvisorInfoStatus.EVENT_REJECT, StateMachine.ROLE.NOT_ADVISOR, AdvisorInfoStatus.REJECTED);
|
||||
// 待审核 -> 管理员[通过] -> 一级审核通过
|
||||
advisorInfoSM.add(AdvisorInfoStatus.TO_AUDIT, AdvisorInfoStatus.EVENT_PASS, StateMachine.ROLE.ADMIN, AdvisorInfoStatus.PASS);
|
||||
advisorInfoSM.add(AdvisorInfoStatus.TO_AUDIT, AdvisorInfoStatus.EVENT_PASS, StateMachine.ROLE.NOT_ADVISOR, AdvisorInfoStatus.PASS);
|
||||
|
||||
// 已上架 -> 管理员[下架] -> 已下架
|
||||
advisorInfoSM.add(AdvisorInfoStatus.PASS, AdvisorInfoStatus.EVENT_SOLD_OUT, StateMachine.ROLE.ADMIN, AdvisorInfoStatus.SOLD_OUT);
|
||||
advisorInfoSM.add(AdvisorInfoStatus.PASS, AdvisorInfoStatus.EVENT_SOLD_OUT, StateMachine.ROLE.NOT_ADVISOR, AdvisorInfoStatus.SOLD_OUT);
|
||||
// 已上架 -> 管理员[编辑] -> 已上架
|
||||
advisorInfoSM.add(AdvisorInfoStatus.PASS, AdvisorInfoStatus.EVENT_UPDATE, StateMachine.ROLE.ADMIN, AdvisorInfoStatus.PASS);
|
||||
advisorInfoSM.add(AdvisorInfoStatus.PASS, AdvisorInfoStatus.EVENT_UPDATE, StateMachine.ROLE.NOT_ADVISOR, AdvisorInfoStatus.PASS);
|
||||
|
||||
// 已驳回 -> 投顾[编辑] -> 已驳回
|
||||
advisorInfoSM.add(AdvisorInfoStatus.REJECTED, AdvisorInfoStatus.EVENT_UPDATE, StateMachine.ROLE.ADVISOR, AdvisorInfoStatus.REJECTED);
|
||||
@ -37,9 +37,9 @@ public class AdvisorInfoStateMachine {
|
||||
// 已下架 —> 投顾[发布] -> 待审核
|
||||
advisorInfoSM.add(AdvisorInfoStatus.SOLD_OUT, AdvisorInfoStatus.EVENT_UPDATE, StateMachine.ROLE.ADVISOR, AdvisorInfoStatus.TO_AUDIT);
|
||||
// 已下架 -> 管理员[上架] -> 已上架
|
||||
advisorInfoSM.add(AdvisorInfoStatus.SOLD_OUT, AdvisorInfoStatus.EVENT_PUT_ON, StateMachine.ROLE.ADMIN, AdvisorInfoStatus.PASS);
|
||||
advisorInfoSM.add(AdvisorInfoStatus.SOLD_OUT, AdvisorInfoStatus.EVENT_PUT_ON, StateMachine.ROLE.NOT_ADVISOR, AdvisorInfoStatus.PASS);
|
||||
// 已下架 -> 管理员[编辑] -> 已下架
|
||||
advisorInfoSM.add(AdvisorInfoStatus.SOLD_OUT, AdvisorInfoStatus.EVENT_UPDATE, StateMachine.ROLE.ADMIN, AdvisorInfoStatus.SOLD_OUT);
|
||||
advisorInfoSM.add(AdvisorInfoStatus.SOLD_OUT, AdvisorInfoStatus.EVENT_UPDATE, StateMachine.ROLE.NOT_ADVISOR, AdvisorInfoStatus.SOLD_OUT);
|
||||
|
||||
return advisorInfoSM;
|
||||
}
|
||||
|
||||
@ -6,9 +6,7 @@ import com.google.common.collect.Table;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.vo.BackendUserVO;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -20,20 +18,14 @@ import java.util.Map;
|
||||
public class StateMachine<T> {
|
||||
|
||||
public static class ROLE {
|
||||
public static final int ADMIN = 1;
|
||||
public static final int ADVISOR = 2;
|
||||
public static final int COMPLIANCE = 3; // 一级审核
|
||||
public static final int BUSINESS = 4; // 二级审核
|
||||
public static final int OPERATION = 5; // 三级审核
|
||||
public static final int ADVISOR = 1;
|
||||
public static final int NOT_ADVISOR = 2;
|
||||
|
||||
private static final Map<Integer, String> MAP = MapUtil.newHashMap();
|
||||
|
||||
static {
|
||||
MAP.put(ADMIN, "管理员");
|
||||
MAP.put(ADVISOR, "投顾");
|
||||
MAP.put(COMPLIANCE, "合规");
|
||||
MAP.put(BUSINESS, "业务负责人");
|
||||
MAP.put(OPERATION, "运营");
|
||||
MAP.put(NOT_ADVISOR, "非投顾");
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,13 +45,6 @@ public class StateMachine<T> {
|
||||
table.put(source, event + "|" + role, target);
|
||||
}
|
||||
|
||||
// 添加状态事件(不同角色特殊处理。比如下架产品,投顾编辑后为待提交状态;运营人员编辑后仍未下架状态)
|
||||
public void add(T source, T event, List<Integer> roles, T target) {
|
||||
for (int role : roles) {
|
||||
table.put(source, event + "|" + role, target);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加状态事件(事件和目标相同,省略参数)
|
||||
public void add(T source, T target) {
|
||||
table.put(source, target, target);
|
||||
@ -87,34 +72,13 @@ public class StateMachine<T> {
|
||||
return target;
|
||||
}
|
||||
String statusMsg = "原状态:[" + source + "]";
|
||||
String roleMsg = role == null ? "" : ",角色:[" + (ROLE.ADMIN == role ? "管理员" : "投顾") + "]";
|
||||
String roleMsg = role == null ? "" : ",角色:[" + (ROLE.MAP.getOrDefault(role, role.toString())) + "]";
|
||||
String eventMsg = ",不能执行:[" + event + "]动作";
|
||||
throw new BizException(ResponseStatus.STATUS_ERROR, statusMsg + roleMsg + eventMsg);
|
||||
}
|
||||
|
||||
public T send(T source, T event, List<Integer> roles) {
|
||||
T target = null;
|
||||
for (Integer role : roles) {
|
||||
target = this.send(source, event, role);
|
||||
}
|
||||
if (target == null) {
|
||||
String statusMsg = "原状态:[" + source + "]";
|
||||
String roleMsg = "";
|
||||
if (!CollectionUtils.isEmpty(roles)) {
|
||||
roleMsg = " 角色:[";
|
||||
for (Integer role : roles) {
|
||||
roleMsg += "," + ROLE.MAP.get(role);
|
||||
}
|
||||
roleMsg += "]";
|
||||
}
|
||||
String eventMsg = ",不能执行:[" + event + "]动作";
|
||||
throw new BizException(ResponseStatus.STATUS_ERROR, statusMsg + roleMsg + eventMsg);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public T send(T source, T event, BackendUserVO userVO) {
|
||||
int role = userVO.getAdvisorId() == null ? StateMachine.ROLE.ADMIN : StateMachine.ROLE.ADVISOR;
|
||||
int role = userVO.getAdvisorId() == null ? ROLE.NOT_ADVISOR : StateMachine.ROLE.ADVISOR;
|
||||
return this.send(source, event, role);
|
||||
}
|
||||
|
||||
|
||||
@ -16,15 +16,15 @@ public class VideoActivityStateMachine {
|
||||
public StateMachine<VideoActivityStatus> videoActivityStatusSm() {
|
||||
StateMachine<VideoActivityStatus> activityStatusSm = new StateMachine<>();
|
||||
// 待审核 [运营人员]审核 通过 上架
|
||||
activityStatusSm.add(VideoActivityStatus.TO_AUDIT, VideoActivityStatus.EVENT_PASS, StateMachine.ROLE.ADMIN, VideoActivityStatus.PASS);
|
||||
activityStatusSm.add(VideoActivityStatus.TO_AUDIT, VideoActivityStatus.EVENT_PASS, StateMachine.ROLE.NOT_ADVISOR, VideoActivityStatus.PASS);
|
||||
// 待审核 [运营人员]审核 驳回 已驳回
|
||||
activityStatusSm.add(VideoActivityStatus.TO_AUDIT, VideoActivityStatus.EVENT_REJECT, StateMachine.ROLE.ADMIN, VideoActivityStatus.REJECTED);
|
||||
activityStatusSm.add(VideoActivityStatus.TO_AUDIT, VideoActivityStatus.EVENT_REJECT, StateMachine.ROLE.NOT_ADVISOR, VideoActivityStatus.REJECTED);
|
||||
// 已驳回 [投顾]编辑 待审核
|
||||
activityStatusSm.add(VideoActivityStatus.REJECTED, VideoActivityStatus.EVENT_UPDATE, StateMachine.ROLE.ADMIN, VideoActivityStatus.TO_AUDIT);
|
||||
activityStatusSm.add(VideoActivityStatus.REJECTED, VideoActivityStatus.EVENT_UPDATE, StateMachine.ROLE.ADVISOR, VideoActivityStatus.TO_AUDIT);
|
||||
// 已上架 [运营人员] 下架
|
||||
activityStatusSm.add(VideoActivityStatus.PASS, VideoActivityStatus.EVENT_SOLD_OUT, StateMachine.ROLE.ADMIN, VideoActivityStatus.SOLD_OUT);
|
||||
activityStatusSm.add(VideoActivityStatus.PASS, VideoActivityStatus.EVENT_SOLD_OUT, StateMachine.ROLE.NOT_ADVISOR, VideoActivityStatus.SOLD_OUT);
|
||||
// 已下架 [运营人员] 上架
|
||||
activityStatusSm.add(VideoActivityStatus.SOLD_OUT, VideoActivityStatus.EVENT_PUT_ON, StateMachine.ROLE.ADMIN, VideoActivityStatus.PASS);
|
||||
activityStatusSm.add(VideoActivityStatus.SOLD_OUT, VideoActivityStatus.EVENT_PUT_ON, StateMachine.ROLE.NOT_ADVISOR, VideoActivityStatus.PASS);
|
||||
return activityStatusSm;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,47 +4,40 @@ import com.syzb.video.constant.VideoLiveColumnStatus;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Configuration
|
||||
public class VideoLiveColumnStateMachine {
|
||||
@Bean
|
||||
public StateMachine<VideoLiveColumnStatus> videoLiveColumnSM() {
|
||||
StateMachine<VideoLiveColumnStatus> videoLiveColumnSM = new StateMachine<>();
|
||||
|
||||
// 待提交>待提交 (券商投顾操作)(投顾编辑)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UN_SUBMIT, VideoLiveColumnStatus.EVENT_EDIT, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UN_SUBMIT);
|
||||
// 待提交>上架待审核 (券商投顾操作)(投顾申请上架)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UN_SUBMIT, VideoLiveColumnStatus.EVENT_SUBMIT, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
// 待提交>待提交
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UN_SUBMIT, VideoLiveColumnStatus.EVENT_EDIT, VideoLiveColumnStatus.UN_SUBMIT);
|
||||
// 待提交>上架待审核
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UN_SUBMIT, VideoLiveColumnStatus.EVENT_SUBMIT, VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
// 待提交>上架
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UN_SUBMIT, VideoLiveColumnStatus.EVENT_PUT_ON, VideoLiveColumnStatus.UP);
|
||||
|
||||
// 上架待审核>待提交 (券商投顾操作)(投顾撤回)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP_UN_AUDIT, VideoLiveColumnStatus.EVENT_WITHDRAW, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UN_SUBMIT);
|
||||
// 上架待审核>通过上架 (一级投顾管理岗操作)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP_UN_AUDIT, VideoLiveColumnStatus.EVENT_PASS, new ArrayList<>(Arrays.asList(StateMachine.ROLE.COMPLIANCE, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP);
|
||||
// 上架待审核>驳回 (一级投顾管理岗操作)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP_UN_AUDIT, VideoLiveColumnStatus.EVENT_REJECT, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.REJECT);
|
||||
// 上架待审核>待提交
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP_UN_AUDIT, VideoLiveColumnStatus.EVENT_WITHDRAW, VideoLiveColumnStatus.UN_SUBMIT);
|
||||
// 上架待审核>通过上架
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP_UN_AUDIT, VideoLiveColumnStatus.EVENT_PASS, VideoLiveColumnStatus.UP);
|
||||
// 上架待审核>驳回
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP_UN_AUDIT, VideoLiveColumnStatus.EVENT_REJECT, VideoLiveColumnStatus.REJECT);
|
||||
|
||||
// 驳回>上架待审核 (券商投顾操作)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.REJECT, VideoLiveColumnStatus.EVENT_EDIT, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
// 一审驳回>上架待审核/三审驳回>上架待审核/三审驳回>上架待审核 (申请上架)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.REJECT, VideoLiveColumnStatus.EVENT_SUBMIT, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
// 驳回>上架待审核
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.REJECT, VideoLiveColumnStatus.EVENT_EDIT, VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
// 驳回>申请上架
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.REJECT, VideoLiveColumnStatus.EVENT_SUBMIT, VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
|
||||
// 上架>下架
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP, VideoLiveColumnStatus.EVENT_PUT_OFF, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.DOWN);
|
||||
|
||||
// 待审核>上架
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP_UN_AUDIT, VideoLiveColumnStatus.EVENT_PASS, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP);
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UP, VideoLiveColumnStatus.EVENT_PUT_OFF, VideoLiveColumnStatus.DOWN);
|
||||
|
||||
// 下架>上架
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.DOWN, VideoLiveColumnStatus.EVENT_PUT_ON, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP);
|
||||
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.UN_SUBMIT, VideoLiveColumnStatus.EVENT_PUT_ON, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP);
|
||||
|
||||
// 下架>下架 (投顾编辑/管理员编辑)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.DOWN, VideoLiveColumnStatus.EVENT_EDIT, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.DOWN);
|
||||
// 下架>上架待审核 (申请上架)
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.DOWN, VideoLiveColumnStatus.EVENT_SUBMIT, new ArrayList<>(Arrays.asList(StateMachine.ROLE.ADVISOR, StateMachine.ROLE.ADMIN)), VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.DOWN, VideoLiveColumnStatus.EVENT_PUT_ON, VideoLiveColumnStatus.UP);
|
||||
// 下架>下架
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.DOWN, VideoLiveColumnStatus.EVENT_EDIT, VideoLiveColumnStatus.DOWN);
|
||||
// 下架>上架待审核
|
||||
videoLiveColumnSM.add(VideoLiveColumnStatus.DOWN, VideoLiveColumnStatus.EVENT_SUBMIT, VideoLiveColumnStatus.UP_UN_AUDIT);
|
||||
|
||||
return videoLiveColumnSM;
|
||||
}
|
||||
|
||||
@ -4,8 +4,6 @@ import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class RequestIdUtil {
|
||||
|
||||
public static void setValue(String str) {
|
||||
@ -28,7 +26,7 @@ public class RequestIdUtil {
|
||||
}
|
||||
|
||||
public static void setTime() {
|
||||
MDC.put("requestTime", String.valueOf(new Date().getTime()));
|
||||
MDC.put("requestTime", String.valueOf(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public static long getTime() {
|
||||
|
||||
@ -13,6 +13,9 @@ public class CommentBlackVO extends CommonPhoneVO {
|
||||
@ApiModelProperty("用户姓名")
|
||||
private String userName;
|
||||
|
||||
@ApiModelProperty("用户头像")
|
||||
private String userHeadPic;
|
||||
|
||||
@ApiModelProperty("产品id")
|
||||
private Integer productId;
|
||||
|
||||
@ -102,6 +105,14 @@ public class CommentBlackVO extends CommonPhoneVO {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserHeadPic() {
|
||||
return userHeadPic;
|
||||
}
|
||||
|
||||
public void setUserHeadPic(String userHeadPic) {
|
||||
this.userHeadPic = userHeadPic;
|
||||
}
|
||||
|
||||
public Integer getProductId() {
|
||||
return productId;
|
||||
}
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
package com.syzb.group.controller.admin;
|
||||
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.query.OnlyIdQuery;
|
||||
import com.syzb.common.result.AppPager;
|
||||
import com.syzb.common.result.CommonResult;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.vo.BackendUserVO;
|
||||
import com.syzb.common.vo.OnlyIdVO;
|
||||
import com.syzb.group.query.PageCustomerQuery;
|
||||
import com.syzb.group.query.message.*;
|
||||
import com.syzb.group.service.admin.AdminGroupMessageService;
|
||||
import com.syzb.group.vo.GroupCustomerVO;
|
||||
import com.syzb.group.vo.PagePrivateChatQuery;
|
||||
import com.syzb.group.vo.message.GroupMessageVO;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@ -20,7 +22,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "交易圈admin消息接口")
|
||||
@RestController
|
||||
@ -58,10 +59,18 @@ public class AdminGroupMessageController {
|
||||
|
||||
@ApiOperation("后台获取私聊列表")
|
||||
@PostMapping("/admin/group/message/getPrivateChatList")
|
||||
public CommonResult<List<GroupMessageVO>> getPrivateChatList(@Validated @RequestBody @ApiParam(required = true) OnlyIdQuery query,
|
||||
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
|
||||
List<GroupMessageVO> list = adminGroupMessageService.getPrivateChatList(query, backendUserVO);
|
||||
return CommonResult.success(list);
|
||||
public CommonResult<AppPager<GroupMessageVO>> getPrivateChatList(@Validated @RequestBody @ApiParam(required = true) PagePrivateChatQuery query,
|
||||
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
|
||||
AppPager<GroupMessageVO> page = adminGroupMessageService.getPrivateChatList(query, backendUserVO);
|
||||
return CommonResult.success(page);
|
||||
}
|
||||
|
||||
@ApiOperation("后台获取用户列表")
|
||||
@PostMapping("/admin/group/message/getCustomerList")
|
||||
public CommonResult<AppPager<GroupCustomerVO>> getCustomerList(@Validated @RequestBody @ApiParam(required = true) PageCustomerQuery query,
|
||||
@RequestAttribute(value = "backendUser", required = false) BackendUserVO backendUserVO) {
|
||||
AppPager<GroupCustomerVO> page = adminGroupMessageService.getCustomerList(query, backendUserVO);
|
||||
return CommonResult.success(page);
|
||||
}
|
||||
|
||||
@ApiOperation("后台推荐产品消息")
|
||||
|
||||
@ -21,14 +21,14 @@ import java.util.List;
|
||||
*/
|
||||
public interface GroupMessageMapper extends BaseMapper<GroupMessage> {
|
||||
|
||||
@Select("SELECT id \n" +
|
||||
@Select("SELECT id, private_user_id \n" +
|
||||
"FROM ( \n" +
|
||||
" SELECT id, ROW_NUMBER() OVER (PARTITION BY private_user_id ORDER BY id DESC) as rn \n" +
|
||||
" SELECT id, private_user_id, ROW_NUMBER() OVER (PARTITION BY private_user_id ORDER BY id DESC) as rn \n" +
|
||||
" FROM group_message \n" +
|
||||
" WHERE group_id = #{groupId} AND interactive_type = 2 and private_user_id is not null \n" +
|
||||
") t \n" +
|
||||
"WHERE rn = 1")
|
||||
List<GroupMessage> selectPrivateChatList(@Param("groupId") Integer groupId);
|
||||
"${ew.customSqlSegment}")
|
||||
List<GroupMessage> selectPrivateChatList(@Param("groupId") Integer groupId, @Param(Constants.WRAPPER) Wrapper<?> wrapper);
|
||||
|
||||
@Select("SELECT group_id, interactive_type, user_type, COUNT(0) AS id \n" +
|
||||
"FROM group_message \n" +
|
||||
|
||||
@ -24,7 +24,7 @@ public class ListGroupCustomerQuery extends PageQuery {
|
||||
private Integer customerStatus;
|
||||
|
||||
@ApiModelProperty("禁言状态 1:已禁言 2:未禁言")
|
||||
private Integer commentBlackStatus;
|
||||
private Integer isForbidden;
|
||||
|
||||
public Integer getGroupId() {
|
||||
return groupId;
|
||||
@ -66,11 +66,11 @@ public class ListGroupCustomerQuery extends PageQuery {
|
||||
this.customerStatus = customerStatus;
|
||||
}
|
||||
|
||||
public Integer getCommentBlackStatus() {
|
||||
return commentBlackStatus;
|
||||
public Integer getIsForbidden() {
|
||||
return isForbidden;
|
||||
}
|
||||
|
||||
public void setCommentBlackStatus(Integer commentBlackStatus) {
|
||||
this.commentBlackStatus = commentBlackStatus;
|
||||
public void setIsForbidden(Integer isForbidden) {
|
||||
this.isForbidden = isForbidden;
|
||||
}
|
||||
}
|
||||
|
||||
77
src/main/java/com/syzb/group/query/PageCustomerQuery.java
Normal file
77
src/main/java/com/syzb/group/query/PageCustomerQuery.java
Normal file
@ -0,0 +1,77 @@
|
||||
package com.syzb.group.query;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class PageCustomerQuery {
|
||||
|
||||
@ApiModelProperty("交易圈ID")
|
||||
@NotNull
|
||||
private Integer groupId;
|
||||
|
||||
@ApiModelProperty("数量")
|
||||
@NotNull
|
||||
private Integer size;
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private String userId;
|
||||
|
||||
@ApiModelProperty("昵称")
|
||||
private String nickName;
|
||||
|
||||
@ApiModelProperty("上一页最后加入时间")
|
||||
private LocalDateTime lastJoinTime;
|
||||
|
||||
@ApiModelProperty("上一页最后ID")
|
||||
private Integer lastId;
|
||||
|
||||
public Integer getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(Integer groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public Integer getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Integer size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getNickName() {
|
||||
return nickName;
|
||||
}
|
||||
|
||||
public void setNickName(String nickName) {
|
||||
this.nickName = nickName;
|
||||
}
|
||||
|
||||
public LocalDateTime getLastJoinTime() {
|
||||
return lastJoinTime;
|
||||
}
|
||||
|
||||
public void setLastJoinTime(LocalDateTime lastJoinTime) {
|
||||
this.lastJoinTime = lastJoinTime;
|
||||
}
|
||||
|
||||
public Integer getLastId() {
|
||||
return lastId;
|
||||
}
|
||||
|
||||
public void setLastId(Integer lastId) {
|
||||
this.lastId = lastId;
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,6 @@ package com.syzb.group.query.info;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.syzb.common.constant.IsDisplay;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.vo.BackendUserVO;
|
||||
import com.syzb.group.constant.GroupInfoStatus;
|
||||
import com.syzb.group.entity.GroupInfo;
|
||||
|
||||
@ -13,6 +13,7 @@ import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.query.OnlyIdQuery;
|
||||
import com.syzb.common.result.Pager;
|
||||
import com.syzb.common.service.CommentBlackService;
|
||||
import com.syzb.common.service.OnlineUserService;
|
||||
import com.syzb.common.vo.BackendUserVO;
|
||||
import com.syzb.common.vo.IdCountVO;
|
||||
import com.syzb.group.constant.GroupCustomerStatus;
|
||||
@ -25,7 +26,6 @@ import com.syzb.group.entity.GroupUserCollect;
|
||||
import com.syzb.group.mapper.*;
|
||||
import com.syzb.group.query.ListGroupCustomerQuery;
|
||||
import com.syzb.group.query.QueryGroupCollectQuery;
|
||||
import com.syzb.group.service.common.GroupCacheService;
|
||||
import com.syzb.group.service.common.GroupCommonService;
|
||||
import com.syzb.group.vo.GroupCollectVO;
|
||||
import com.syzb.group.vo.GroupCustomerVO;
|
||||
@ -69,7 +69,7 @@ public class AdminGroupCollectService {
|
||||
private CommentBlackService commentBlackService;
|
||||
|
||||
@Resource
|
||||
private GroupCacheService groupCacheService;
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
@Resource
|
||||
private GroupUserFlowMapper groupUserFlowMapper;
|
||||
@ -226,7 +226,7 @@ public class AdminGroupCollectService {
|
||||
String nickName = query.getNickName();
|
||||
Integer isOnline = query.getIsOnline();
|
||||
Integer customerStatus = query.getCustomerStatus();
|
||||
Integer commentBlackStatus = query.getCommentBlackStatus();
|
||||
Integer isForbidden = query.getIsForbidden();
|
||||
Set<Integer> moduleIdSet = groupCommonService.getModuleIds(groupId);
|
||||
if (CollUtil.isEmpty(moduleIdSet)) {
|
||||
return Pager.emptyPager();
|
||||
@ -242,7 +242,7 @@ public class AdminGroupCollectService {
|
||||
.in(WxUser::getId, userIdSet));
|
||||
Map<String, WxUser> wxUserMap = wxUserList.stream().collect(Collectors.toMap(WxUser::getId, Function.identity()));
|
||||
Set<String> blackUserIds = commentBlackService.getBlackUserIds(groupId, ProductType.GROUP.value);
|
||||
Set<String> onlineUserIds = groupCacheService.getOnlineUserIds(groupId);
|
||||
Set<String> onlineUserIds = onlineUserService.getOnlineUserIds(ProductType.GROUP.value, groupId);
|
||||
Map<String, LocalDateTime> lastVisitTimeMap = queryLastVisitTime(groupId);
|
||||
Map<String, LocalDateTime> lastChatTimeMap = queryLastChatTime(groupId);
|
||||
Stream<ModuleUser> stream = moduleUserList.stream();
|
||||
@ -254,17 +254,17 @@ public class AdminGroupCollectService {
|
||||
WxUser wxUser = wxUserMap.get(moduleUser.getUserId());
|
||||
if (wxUser != null) {
|
||||
vo.setNickName(wxUser.getNickName());
|
||||
vo.setHeadPicUrl(wxUser.getImgUrl());
|
||||
vo.setUserHeadPicUrl(wxUser.getImgUrl());
|
||||
}
|
||||
vo.setIsOnline(onlineUserIds.contains(moduleUser.getUserId()) ? IsOrNot.IS.value : IsOrNot.NOT.value);
|
||||
vo.setCommentBlackStatus(blackUserIds.contains(moduleUser.getUserId()) ? IsOrNot.IS.value : IsOrNot.NOT.value);
|
||||
vo.setIsForbidden(blackUserIds.contains(moduleUser.getUserId()) ? IsOrNot.IS.value : IsOrNot.NOT.value);
|
||||
vo.setCustomerStatus(calCustomerStatus(moduleUser).value);
|
||||
vo.setLastVisitTime(lastVisitTimeMap.get(moduleUser.getUserId()));
|
||||
vo.setLastChatTime(lastChatTimeMap.get(moduleUser.getUserId()));
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
Stream<GroupCustomerVO> voStream = list.stream();
|
||||
if (nickName != null) {
|
||||
if (StrUtil.isNotEmpty(nickName)) {
|
||||
voStream = voStream.filter(vo -> nickName.equals(vo.getNickName()));
|
||||
}
|
||||
if (isOnline != null) {
|
||||
@ -273,8 +273,8 @@ public class AdminGroupCollectService {
|
||||
if (customerStatus != null) {
|
||||
voStream = voStream.filter(vo -> customerStatus.equals(vo.getCustomerStatus()));
|
||||
}
|
||||
if (commentBlackStatus != null) {
|
||||
voStream = voStream.filter(vo -> commentBlackStatus.equals(vo.getCommentBlackStatus()));
|
||||
if (isForbidden != null) {
|
||||
voStream = voStream.filter(vo -> isForbidden.equals(vo.getIsForbidden()));
|
||||
}
|
||||
List<GroupCustomerVO> voList = voStream.collect(Collectors.toList());
|
||||
List<GroupCustomerVO> pageList = CollUtil.page(query.getCurrent() - 1, query.getSize(), voList);
|
||||
|
||||
@ -21,7 +21,6 @@ import com.syzb.common.vo.AuthResultVO;
|
||||
import com.syzb.common.vo.BackendUserVO;
|
||||
import com.syzb.common.vo.FrontUserVO;
|
||||
import com.syzb.common.vo.InsertIdVO;
|
||||
import com.syzb.course.entity.ShortVideo;
|
||||
import com.syzb.course.query.SetMainPageQuery;
|
||||
import com.syzb.course.service.PageService;
|
||||
import com.syzb.group.constant.GroupInfoStatus;
|
||||
|
||||
@ -10,11 +10,12 @@ import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.map.IMap;
|
||||
import com.syzb.advisor.service.AdvisorInfoService;
|
||||
import com.syzb.advisor.vo.AdvisorBasicVO;
|
||||
import com.syzb.business.entity.ModuleUser;
|
||||
import com.syzb.business.mapper.ModuleUserMapper;
|
||||
import com.syzb.common.config.cache.CacheKey;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.query.OnlyIdQuery;
|
||||
import com.syzb.common.result.AppPager;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.service.CommentBlackService;
|
||||
@ -28,17 +29,25 @@ import com.syzb.group.entity.GroupMessageRead;
|
||||
import com.syzb.group.mapper.GroupInfoMapper;
|
||||
import com.syzb.group.mapper.GroupMessageMapper;
|
||||
import com.syzb.group.mapper.GroupMessageReadMapper;
|
||||
import com.syzb.group.query.PageCustomerQuery;
|
||||
import com.syzb.group.query.message.*;
|
||||
import com.syzb.group.service.common.GroupCacheService;
|
||||
import com.syzb.group.service.common.GroupCommonService;
|
||||
import com.syzb.group.service.common.GroupMessageService;
|
||||
import com.syzb.group.vo.GroupCustomerVO;
|
||||
import com.syzb.group.vo.PagePrivateChatQuery;
|
||||
import com.syzb.group.vo.message.GroupMessageReadVO;
|
||||
import com.syzb.group.vo.message.GroupMessageVO;
|
||||
import com.syzb.rbac.entity.WxUser;
|
||||
import com.syzb.rbac.mapper.WxUserMapper;
|
||||
import com.syzb.rbac.service.WxUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@ -77,6 +86,18 @@ public class AdminGroupMessageService {
|
||||
@Resource
|
||||
private GroupMessageReadMapper groupMessageReadMapper;
|
||||
|
||||
@Resource
|
||||
private GroupCommonService groupCommonService;
|
||||
|
||||
@Resource
|
||||
private ModuleUserMapper moduleUserMapper;
|
||||
|
||||
@Resource
|
||||
private WxUserMapper wxUserMapper;
|
||||
|
||||
@Resource
|
||||
private WxUserService wxUserService;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public OnlyIdVO sendAdvisorMessage(SendGroupMessageAdminQuery query, BackendUserVO backendUser) {
|
||||
GroupInfo group = groupInfoMapper.selectById(query.getGroupId());
|
||||
@ -167,16 +188,126 @@ public class AdminGroupMessageService {
|
||||
groupCacheService.queryMessageReadCount(vo);
|
||||
}
|
||||
}
|
||||
if (GroupMessageUserType.CUSTOMER.value.equals(vo.getUserType())) {
|
||||
vo.setUserHeadPicUrl(wxUserService.getHeadPic(vo.getUserId()));
|
||||
}
|
||||
if (StrUtil.isNotEmpty(vo.getPrivateUserId())) {
|
||||
vo.setPrivateUserHeadPicUrl(wxUserService.getHeadPic(vo.getPrivateUserId()));
|
||||
}
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
return new AppPager<>(voList, hasNext);
|
||||
}
|
||||
|
||||
public List<GroupMessageVO> getPrivateChatList(OnlyIdQuery query, BackendUserVO backendUserVO) {
|
||||
Integer groupId = query.getId();
|
||||
List<GroupMessage> list = groupMessageMapper.selectPrivateChatList(groupId);
|
||||
// private Map<String, WxUser> getWxUserMap(List<GroupMessage> list) {
|
||||
// Set<String> userIds = new HashSet<>();
|
||||
// for (GroupMessage message : list) {
|
||||
// if (GroupMessageUserType.CUSTOMER.value.equals(message.getUserType())) {
|
||||
// userIds.add(message.getUserId());
|
||||
// }
|
||||
// if (message.getPrivateUserId() != null) {
|
||||
// userIds.add(message.getPrivateUserId());
|
||||
// }
|
||||
// }
|
||||
// Map<String, WxUser> queryUserIdSet = new HashMap<>(userIds.size());
|
||||
// if (CollUtil.isNotEmpty(userIds)) {
|
||||
// LambdaQueryWrapper<WxUser> userWrapper = Wrappers.<WxUser>lambdaQuery()
|
||||
// .in(WxUser::getId, userIds);
|
||||
// List<WxUser> wxUserList = wxUserMapper.selectList(userWrapper);
|
||||
// wxUserList.forEach(user -> queryUserIdSet.put(user.getId(), user));
|
||||
// }
|
||||
// return queryUserIdSet;
|
||||
// }
|
||||
|
||||
public AppPager<GroupMessageVO> getPrivateChatList(PagePrivateChatQuery query, BackendUserVO backendUserVO) {
|
||||
Integer groupId = query.getGroupId();
|
||||
Integer size = query.getSize();
|
||||
String userId = query.getUserId();
|
||||
String nickName = query.getNickName();
|
||||
Integer lastId = query.getLastId();
|
||||
Set<String> queryUserIdSet = null;
|
||||
if (StrUtil.isNotEmpty(userId) || StrUtil.isNotEmpty(nickName)) {
|
||||
LambdaQueryWrapper<WxUser> userWrapper = Wrappers.<WxUser>lambdaQuery()
|
||||
.select(WxUser::getId)
|
||||
.eq(StrUtil.isNotEmpty(userId), WxUser::getId, userId)
|
||||
.like(StrUtil.isNotEmpty(nickName), WxUser::getNickName, nickName);
|
||||
List<WxUser> wxUserList = wxUserMapper.selectList(userWrapper);
|
||||
queryUserIdSet = wxUserList.stream().map(WxUser::getId).collect(Collectors.toSet());
|
||||
if (CollUtil.isEmpty(queryUserIdSet)) {
|
||||
return AppPager.emptyPager();
|
||||
}
|
||||
}
|
||||
QueryWrapper<GroupMessage> wrapper = Wrappers.<GroupMessage>query()
|
||||
.eq("rn", 1)
|
||||
.in(queryUserIdSet != null, "private_user_id", queryUserIdSet)
|
||||
.lt(lastId != null, "id", lastId)
|
||||
.orderByDesc("id")
|
||||
.last("limit " + (size + 1));
|
||||
List<GroupMessage> list = groupMessageMapper.selectPrivateChatList(groupId, wrapper);
|
||||
boolean hasNext = list.size() > size;
|
||||
if (hasNext) {
|
||||
list = list.subList(0, size);
|
||||
}
|
||||
Map<Integer, AdvisorBasicVO> advisorMap = advisorInfoService.getAdvisorVoMap();
|
||||
return list.stream().map(GroupMessage::getId).map(id -> groupCacheService.getMessage(id, advisorMap)).collect(Collectors.toList());
|
||||
List<GroupMessageVO> voList = list.stream().map(GroupMessage::getId).map(id -> groupCacheService.getMessage(id, advisorMap)).collect(Collectors.toList());
|
||||
return new AppPager<>(voList, hasNext);
|
||||
}
|
||||
|
||||
public AppPager<GroupCustomerVO> getCustomerList(PageCustomerQuery query, BackendUserVO backendUserVO) {
|
||||
Integer groupId = query.getGroupId();
|
||||
Integer size = query.getSize();
|
||||
String userId = query.getUserId();
|
||||
String nickName = query.getNickName();
|
||||
LocalDateTime lastJoinTime = query.getLastJoinTime();
|
||||
Integer lastId = query.getLastId();
|
||||
Set<Integer> moduleIdSet = groupCommonService.getModuleIds(groupId);
|
||||
if (CollUtil.isEmpty(moduleIdSet)) {
|
||||
return AppPager.emptyPager();
|
||||
}
|
||||
Set<String> queryUserIdSet = null;
|
||||
if (StrUtil.isNotEmpty(userId) || StrUtil.isNotEmpty(nickName)) {
|
||||
LambdaQueryWrapper<WxUser> userWrapper = Wrappers.<WxUser>lambdaQuery()
|
||||
.select(WxUser::getId)
|
||||
.eq(StrUtil.isNotEmpty(userId), WxUser::getId, userId)
|
||||
.like(StrUtil.isNotEmpty(nickName), WxUser::getNickName, nickName);
|
||||
List<WxUser> wxUserList = wxUserMapper.selectList(userWrapper);
|
||||
queryUserIdSet = wxUserList.stream().map(WxUser::getId).collect(Collectors.toSet());
|
||||
if (CollUtil.isEmpty(queryUserIdSet)) {
|
||||
return AppPager.emptyPager();
|
||||
}
|
||||
}
|
||||
LambdaQueryWrapper<ModuleUser> muWrapper = Wrappers.<ModuleUser>lambdaQuery()
|
||||
.in(ModuleUser::getModuleId, moduleIdSet)
|
||||
.in(queryUserIdSet != null, ModuleUser::getUserId, queryUserIdSet)
|
||||
.orderByDesc(ModuleUser::getCreateTime, ModuleUser::getId);
|
||||
if (lastJoinTime != null && lastId != null) {
|
||||
muWrapper.and(w1 -> w1.lt(ModuleUser::getCreateTime, lastJoinTime).or(w2 -> w2.eq(ModuleUser::getCreateTime, lastJoinTime).lt(ModuleUser::getId, lastId)));
|
||||
}
|
||||
muWrapper.last("limit " + (size + 1));
|
||||
List<ModuleUser> moduleUserList = moduleUserMapper.selectList(muWrapper);
|
||||
if (CollUtil.isEmpty(moduleUserList)) {
|
||||
return AppPager.emptyPager();
|
||||
}
|
||||
boolean hasNext = moduleUserList.size() > size;
|
||||
if (hasNext) {
|
||||
moduleUserList = moduleUserList.subList(0, size);
|
||||
}
|
||||
Set<String> userIdSet = moduleUserList.stream().map(ModuleUser::getUserId).collect(Collectors.toSet());
|
||||
List<WxUser> wxUserList = wxUserMapper.selectList(Wrappers.<WxUser>lambdaQuery()
|
||||
.in(WxUser::getId, userIdSet));
|
||||
Map<String, WxUser> wxUserMap = wxUserList.stream().collect(Collectors.toMap(WxUser::getId, Function.identity()));
|
||||
Set<String> blackUserIds = commentBlackService.getBlackUserIds(groupId, ProductType.GROUP.value);
|
||||
List<GroupCustomerVO> list = moduleUserList.stream().map(moduleUser -> {
|
||||
GroupCustomerVO vo = new GroupCustomerVO(moduleUser);
|
||||
WxUser wxUser = wxUserMap.get(moduleUser.getUserId());
|
||||
if (wxUser != null) {
|
||||
vo.setNickName(wxUser.getNickName());
|
||||
vo.setUserHeadPicUrl(wxUser.getImgUrl());
|
||||
}
|
||||
vo.setIsForbidden(blackUserIds.contains(moduleUser.getUserId()) ? IsOrNot.IS.value : IsOrNot.NOT.value);
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
return new AppPager<>(list, hasNext);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
||||
@ -19,7 +19,6 @@ import com.syzb.group.mapper.GroupInfoMapper;
|
||||
import com.syzb.group.query.info.ListGroupAppQuery;
|
||||
import com.syzb.group.service.admin.AdminGroupInfoService;
|
||||
import com.syzb.group.vo.GroupVO;
|
||||
import com.syzb.rbac.service.AuthService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@ -1,17 +1,14 @@
|
||||
package com.syzb.group.service.common;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.map.IMap;
|
||||
import com.hazelcast.sql.SqlResult;
|
||||
import com.hazelcast.sql.SqlRow;
|
||||
import com.syzb.advisor.vo.AdvisorBasicVO;
|
||||
import com.syzb.common.config.cache.CacheKey;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.entity.OnlineUser;
|
||||
import com.syzb.common.service.CacheService;
|
||||
import com.syzb.common.util.logger.LoggerUtil;
|
||||
import com.syzb.common.vo.DateIdVO;
|
||||
import com.syzb.group.constant.GroupInteractiveType;
|
||||
import com.syzb.group.constant.GroupMessageUserType;
|
||||
@ -22,15 +19,12 @@ import com.syzb.group.mapper.GroupMessageMapper;
|
||||
import com.syzb.group.mapper.GroupMessageReadMapper;
|
||||
import com.syzb.group.vo.message.GroupMessageReadVO;
|
||||
import com.syzb.group.vo.message.GroupMessageVO;
|
||||
import com.syzb.rbac.service.WxUserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.syzb.common.config.cache.CacheKey.GROUP;
|
||||
import static com.syzb.common.config.cache.CacheKey.GROUP_ONLINE_USER;
|
||||
|
||||
@Service
|
||||
public class GroupCacheService {
|
||||
@ -47,6 +41,9 @@ public class GroupCacheService {
|
||||
@Resource
|
||||
private GroupMessageMapper groupMessageMapper;
|
||||
|
||||
@Resource
|
||||
private WxUserService wxUserService;
|
||||
|
||||
@Resource
|
||||
private IMap<String, Object> groupCache;
|
||||
|
||||
@ -142,7 +139,7 @@ public class GroupCacheService {
|
||||
}
|
||||
|
||||
public GroupMessageVO getMessage(Integer messageId, Map<Integer, AdvisorBasicVO> advisorMap) {
|
||||
return cacheService.get(groupCache,
|
||||
GroupMessageVO vo = cacheService.get(groupCache,
|
||||
CacheKey.GroupKey.GROUP_MESSAGE_DETAIL + messageId, () -> {
|
||||
GroupMessage message = groupMessageMapper.selectById(messageId);
|
||||
if (message == null) {
|
||||
@ -150,6 +147,16 @@ public class GroupCacheService {
|
||||
}
|
||||
return getMessage(message, advisorMap);
|
||||
});
|
||||
if (vo == null) {
|
||||
return null;
|
||||
}
|
||||
if (GroupMessageUserType.CUSTOMER.value.equals(vo.getUserType())) {
|
||||
vo.setUserHeadPicUrl(wxUserService.getHeadPic(vo.getUserId()));
|
||||
}
|
||||
if (StrUtil.isNotEmpty(vo.getPrivateUserId())) {
|
||||
vo.setPrivateUserHeadPicUrl(wxUserService.getHeadPic(vo.getPrivateUserId()));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
public GroupMessageVO getMessage(GroupMessage message, Map<Integer, AdvisorBasicVO> advisorMap) {
|
||||
@ -159,82 +166,6 @@ public class GroupCacheService {
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总在线用户映射
|
||||
*
|
||||
* @return 在线用户映射
|
||||
*/
|
||||
public IMap<String, OnlineUser> getTotalOnlineMap() {
|
||||
return hazelcastInstance.getMap(GROUP_ONLINE_USER);
|
||||
}
|
||||
|
||||
public List<OnlineUser> getTotalOnlineList(Integer groupId) {
|
||||
String sql = "SELECT * FROM " + GROUP_ONLINE_USER + " WHERE productId = " + groupId;
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
List<OnlineUser> list = new ArrayList<>();
|
||||
for (SqlRow row : result) {
|
||||
OnlineUser user = new OnlineUser();
|
||||
user.setProductType(row.getObject("productType"));
|
||||
user.setProductId(row.getObject("productId"));
|
||||
user.setUserId(row.getObject("userId"));
|
||||
user.setUserName(row.getObject("userName"));
|
||||
user.setImg(row.getObject("img"));
|
||||
user.setSessionId(row.getObject("sessionId"));
|
||||
user.setIsOnline(row.getObject("isOnline"));
|
||||
user.setIsPlay(row.getObject("isPlay"));
|
||||
user.setCreateTime(row.getObject("createTime"));
|
||||
user.setExitTime(row.getObject("exitTime"));
|
||||
list.add(user);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public Set<String> getOnlineUserIds(Integer groupId) {
|
||||
String sql = "SELECT distinct userId FROM " + GROUP_ONLINE_USER + " WHERE productId = " + groupId;
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
Set<String> set = new HashSet<>();
|
||||
for (SqlRow row : result) {
|
||||
set.add(row.getObject("userId"));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线人数
|
||||
*
|
||||
* @param groupId 视频ID
|
||||
* @return 在线人数
|
||||
*/
|
||||
public int getOnlineCount(Integer groupId) {
|
||||
IMap<String, Object> map = hazelcastInstance.getMap(GROUP);
|
||||
String cacheKey = CacheKey.GroupKey.ONLINE_COUNT + groupId;
|
||||
Integer onlineCount = (Integer) map.get(cacheKey);
|
||||
if (onlineCount != null) {
|
||||
return onlineCount;
|
||||
}
|
||||
synchronized (this) {
|
||||
onlineCount = (Integer) map.get(cacheKey);
|
||||
if (onlineCount != null) {
|
||||
return onlineCount;
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
onlineCount = getOnlineCountWithoutCache(groupId);
|
||||
LoggerUtil.websocket.info("getOnlineCount-" + groupId + ":" + (System.currentTimeMillis() - startTime) + "ms");
|
||||
map.put(cacheKey, onlineCount, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
return onlineCount;
|
||||
}
|
||||
|
||||
public int getOnlineCountWithoutCache(Integer groupId) {
|
||||
String sql = "SELECT COUNT(*) FROM " + GROUP_ONLINE_USER + " WHERE productId = " + groupId + " and isOnline = 1";
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
Iterator<SqlRow> iter = result.iterator();
|
||||
if (iter.hasNext()) {
|
||||
return ((Long)iter.next().getObject(0)).intValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static String buildMessageIdSetKey(String prefix, Integer groupId, String userId, QueryGroupMessageType type) {
|
||||
String cacheKey = prefix + groupId + "|" + type.value;
|
||||
if (QueryGroupMessageType.PRIVATE.equals(type)) {
|
||||
|
||||
@ -9,7 +9,9 @@ import com.hazelcast.map.IMap;
|
||||
import com.syzb.business.entity.ModuleUser;
|
||||
import com.syzb.business.mapper.ModuleUserMapper;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.entity.OnlineUser;
|
||||
import com.syzb.common.service.OnlineUserService;
|
||||
import com.syzb.common.util.logger.LoggerUtil;
|
||||
import com.syzb.group.entity.GroupInfo;
|
||||
import com.syzb.group.entity.GroupUserFlow;
|
||||
@ -28,7 +30,7 @@ import java.util.stream.Collectors;
|
||||
public class GroupCommonService {
|
||||
|
||||
@Resource
|
||||
private GroupCacheService groupCacheService;
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
@Resource
|
||||
private GroupInfoMapper groupInfoMapper;
|
||||
@ -44,7 +46,7 @@ public class GroupCommonService {
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveGroupUser() {
|
||||
IMap<String, OnlineUser> onlineMap = groupCacheService.getTotalOnlineMap();
|
||||
IMap<String, OnlineUser> onlineMap = onlineUserService.getTotalOnlineMap(ProductType.GROUP.value);
|
||||
Collection<OnlineUser> onlineUsers = onlineMap.values();
|
||||
if (CollUtil.isEmpty(onlineUsers)) {
|
||||
return;
|
||||
|
||||
@ -7,6 +7,9 @@ import java.time.LocalDateTime;
|
||||
|
||||
public class GroupCustomerVO {
|
||||
|
||||
@ApiModelProperty("ID")
|
||||
private Integer id;
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private String userId;
|
||||
|
||||
@ -14,7 +17,7 @@ public class GroupCustomerVO {
|
||||
private String nickName;
|
||||
|
||||
@ApiModelProperty("头像")
|
||||
private String headPicUrl;
|
||||
private String userHeadPicUrl;
|
||||
|
||||
@ApiModelProperty("加入时间")
|
||||
private LocalDateTime joinTime;
|
||||
@ -28,8 +31,8 @@ public class GroupCustomerVO {
|
||||
@ApiModelProperty("客户状态 1:在期 2:已到期 3:即将到期 4:新学员")
|
||||
private Integer customerStatus;
|
||||
|
||||
@ApiModelProperty("禁言状态 0生效中 1已解除 2自然过期")
|
||||
private Integer commentBlackStatus;
|
||||
@ApiModelProperty("禁言状态 1:已禁言 2:未禁言")
|
||||
private Integer isForbidden;
|
||||
|
||||
@ApiModelProperty("最近一次访问时间")
|
||||
private LocalDateTime lastVisitTime;
|
||||
@ -38,11 +41,20 @@ public class GroupCustomerVO {
|
||||
private LocalDateTime lastChatTime;
|
||||
|
||||
public GroupCustomerVO(ModuleUser moduleUser) {
|
||||
this.id = moduleUser.getId();
|
||||
this.userId = moduleUser.getUserId();
|
||||
this.joinTime = moduleUser.getCreateTime();
|
||||
this.expireTime = moduleUser.getEndTime();
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
@ -59,12 +71,12 @@ public class GroupCustomerVO {
|
||||
this.nickName = nickName;
|
||||
}
|
||||
|
||||
public String getHeadPicUrl() {
|
||||
return headPicUrl;
|
||||
public String getUserHeadPicUrl() {
|
||||
return userHeadPicUrl;
|
||||
}
|
||||
|
||||
public void setHeadPicUrl(String headPicUrl) {
|
||||
this.headPicUrl = headPicUrl;
|
||||
public void setUserHeadPicUrl(String userHeadPicUrl) {
|
||||
this.userHeadPicUrl = userHeadPicUrl;
|
||||
}
|
||||
|
||||
public LocalDateTime getJoinTime() {
|
||||
@ -99,12 +111,12 @@ public class GroupCustomerVO {
|
||||
this.customerStatus = customerStatus;
|
||||
}
|
||||
|
||||
public Integer getCommentBlackStatus() {
|
||||
return commentBlackStatus;
|
||||
public Integer getIsForbidden() {
|
||||
return isForbidden;
|
||||
}
|
||||
|
||||
public void setCommentBlackStatus(Integer commentBlackStatus) {
|
||||
this.commentBlackStatus = commentBlackStatus;
|
||||
public void setIsForbidden(Integer isForbidden) {
|
||||
this.isForbidden = isForbidden;
|
||||
}
|
||||
|
||||
public LocalDateTime getLastVisitTime() {
|
||||
|
||||
65
src/main/java/com/syzb/group/vo/PagePrivateChatQuery.java
Normal file
65
src/main/java/com/syzb/group/vo/PagePrivateChatQuery.java
Normal file
@ -0,0 +1,65 @@
|
||||
package com.syzb.group.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
public class PagePrivateChatQuery {
|
||||
|
||||
@ApiModelProperty("交易圈ID")
|
||||
@NotNull
|
||||
private Integer groupId;
|
||||
|
||||
@ApiModelProperty("数量")
|
||||
@NotNull
|
||||
private Integer size;
|
||||
|
||||
@ApiModelProperty("用户ID")
|
||||
private String userId;
|
||||
|
||||
@ApiModelProperty("昵称")
|
||||
private String nickName;
|
||||
|
||||
@ApiModelProperty("上一页最后ID")
|
||||
private Integer lastId;
|
||||
|
||||
public Integer getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public void setGroupId(Integer groupId) {
|
||||
this.groupId = groupId;
|
||||
}
|
||||
|
||||
public Integer getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(Integer size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public String getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getNickName() {
|
||||
return nickName;
|
||||
}
|
||||
|
||||
public void setNickName(String nickName) {
|
||||
this.nickName = nickName;
|
||||
}
|
||||
|
||||
public Integer getLastId() {
|
||||
return lastId;
|
||||
}
|
||||
|
||||
public void setLastId(Integer lastId) {
|
||||
this.lastId = lastId;
|
||||
}
|
||||
}
|
||||
@ -30,6 +30,9 @@ public class GroupMessageVO implements Serializable {
|
||||
@ApiModelProperty("用户名称")
|
||||
private String userName;
|
||||
|
||||
@ApiModelProperty("用户头像")
|
||||
private String userHeadPicUrl;
|
||||
|
||||
@ApiModelProperty("接受用户ID")
|
||||
private String toUserId;
|
||||
|
||||
@ -42,6 +45,9 @@ public class GroupMessageVO implements Serializable {
|
||||
@ApiModelProperty("私聊用户名称")
|
||||
private String privateUserName;
|
||||
|
||||
@ApiModelProperty("私聊用户头像")
|
||||
private String privateUserHeadPicUrl;
|
||||
|
||||
@ApiModelProperty("消息内容")
|
||||
private String content;
|
||||
|
||||
@ -87,6 +93,10 @@ public class GroupMessageVO implements Serializable {
|
||||
public GroupMessageVO() {
|
||||
}
|
||||
|
||||
public GroupMessageVO(String userId) {
|
||||
this.privateUserId = userId;
|
||||
}
|
||||
|
||||
public GroupMessageVO(GroupMessage message, AdvisorBasicVO advisor) {
|
||||
this.id = message.getId();
|
||||
this.msgType = message.getMsgType();
|
||||
@ -168,6 +178,14 @@ public class GroupMessageVO implements Serializable {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUserHeadPicUrl() {
|
||||
return userHeadPicUrl;
|
||||
}
|
||||
|
||||
public void setUserHeadPicUrl(String userHeadPicUrl) {
|
||||
this.userHeadPicUrl = userHeadPicUrl;
|
||||
}
|
||||
|
||||
public String getToUserId() {
|
||||
return toUserId;
|
||||
}
|
||||
@ -200,6 +218,14 @@ public class GroupMessageVO implements Serializable {
|
||||
this.privateUserName = privateUserName;
|
||||
}
|
||||
|
||||
public String getPrivateUserHeadPicUrl() {
|
||||
return privateUserHeadPicUrl;
|
||||
}
|
||||
|
||||
public void setPrivateUserHeadPicUrl(String privateUserHeadPicUrl) {
|
||||
this.privateUserHeadPicUrl = privateUserHeadPicUrl;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
package com.syzb.monitor.controller;
|
||||
|
||||
import com.syzb.common.result.CommonResult;
|
||||
import com.syzb.monitor.entity.InterfaceMonitor;
|
||||
import com.syzb.monitor.query.MonitorQuery;
|
||||
import com.syzb.monitor.service.MonitorService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
@Api(tags = "monitor")
|
||||
@RestController
|
||||
@CrossOrigin(origins = "*", allowedHeaders = "*", maxAge = 3600)
|
||||
public class MonitorController {
|
||||
|
||||
@Resource
|
||||
private MonitorService monitorService;
|
||||
|
||||
@PostMapping("/admin/monitor/listIP")
|
||||
public CommonResult<List<String>> listIP(@Validated @RequestBody @ApiParam(required = true) MonitorQuery query) {
|
||||
List<String> list = monitorService.listIP(query);
|
||||
return CommonResult.success(list);
|
||||
}
|
||||
|
||||
@PostMapping("/admin/monitor/listInterface")
|
||||
public CommonResult<List<String>> listInterface(@Validated @RequestBody @ApiParam(required = true) MonitorQuery query) {
|
||||
List<String> list = monitorService.listInterface(query);
|
||||
return CommonResult.success(list);
|
||||
}
|
||||
|
||||
@PostMapping("/admin/monitor/listData")
|
||||
public CommonResult<List<InterfaceMonitor>> listData(@Validated @RequestBody @ApiParam(required = true) MonitorQuery query) {
|
||||
List<InterfaceMonitor> list = monitorService.listData(query);
|
||||
return CommonResult.success(list);
|
||||
}
|
||||
|
||||
@PostMapping("/admin/monitor/groupData")
|
||||
public CommonResult<List<InterfaceMonitor>> groupData(@Validated @RequestBody @ApiParam(required = true) MonitorQuery query) {
|
||||
List<InterfaceMonitor> list = monitorService.groupData(query);
|
||||
return CommonResult.success(list);
|
||||
}
|
||||
|
||||
}
|
||||
218
src/main/java/com/syzb/monitor/entity/InterfaceMonitor.java
Normal file
218
src/main/java/com/syzb/monitor/entity/InterfaceMonitor.java
Normal file
@ -0,0 +1,218 @@
|
||||
package com.syzb.monitor.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 接口监控统计表
|
||||
* </p>
|
||||
*
|
||||
* @author helloSyzb
|
||||
* @since 2025-04-09
|
||||
*/
|
||||
public class InterfaceMonitor implements Serializable {
|
||||
|
||||
|
||||
/**
|
||||
* 统计时间
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
* 接口名称
|
||||
*/
|
||||
@TableId("interface_name")
|
||||
private String interfaceName;
|
||||
|
||||
/**
|
||||
* 请求来源IP地址
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 接口调用总次数
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
/**
|
||||
* 接口调用平均耗时(毫秒)
|
||||
*/
|
||||
@TableField("average_time")
|
||||
private Integer averageTime;
|
||||
|
||||
/**
|
||||
* 接口调用最大耗时(毫秒)
|
||||
*/
|
||||
@TableField("max_time")
|
||||
private Integer maxTime;
|
||||
|
||||
/**
|
||||
* 接口调用最小耗时(毫秒)
|
||||
*/
|
||||
@TableField("min_time")
|
||||
private Integer minTime;
|
||||
|
||||
/**
|
||||
* 接口调用失败次数
|
||||
*/
|
||||
private Integer failure;
|
||||
|
||||
/**
|
||||
* 接口耗时超过10ms的次数
|
||||
*/
|
||||
@TableField("over_10ms")
|
||||
private Integer over10ms;
|
||||
|
||||
/**
|
||||
* 接口耗时超过50ms的次数
|
||||
*/
|
||||
@TableField("over_50ms")
|
||||
private Integer over50ms;
|
||||
|
||||
/**
|
||||
* 接口耗时超过100ms的次数
|
||||
*/
|
||||
@TableField("over_100ms")
|
||||
private Integer over100ms;
|
||||
|
||||
/**
|
||||
* 接口耗时超过500ms的次数
|
||||
*/
|
||||
@TableField("over_500ms")
|
||||
private Integer over500ms;
|
||||
|
||||
/**
|
||||
* 接口耗时超过1000ms的次数
|
||||
*/
|
||||
@TableField("over_1000ms")
|
||||
private Integer over1000ms;
|
||||
|
||||
/**
|
||||
* 接口耗时超过5000ms的次数
|
||||
*/
|
||||
@TableField("over_5000ms")
|
||||
private Integer over5000ms;
|
||||
|
||||
public LocalDateTime getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(LocalDateTime time) {
|
||||
this.time = time;
|
||||
}
|
||||
public String getInterfaceName() {
|
||||
return interfaceName;
|
||||
}
|
||||
|
||||
public void setInterfaceName(String interfaceName) {
|
||||
this.interfaceName = interfaceName;
|
||||
}
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
public Integer getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(Integer total) {
|
||||
this.total = total;
|
||||
}
|
||||
public Integer getAverageTime() {
|
||||
return averageTime;
|
||||
}
|
||||
|
||||
public void setAverageTime(Integer averageTime) {
|
||||
this.averageTime = averageTime;
|
||||
}
|
||||
public Integer getMaxTime() {
|
||||
return maxTime;
|
||||
}
|
||||
|
||||
public void setMaxTime(Integer maxTime) {
|
||||
this.maxTime = maxTime;
|
||||
}
|
||||
public Integer getMinTime() {
|
||||
return minTime;
|
||||
}
|
||||
|
||||
public void setMinTime(Integer minTime) {
|
||||
this.minTime = minTime;
|
||||
}
|
||||
public Integer getFailure() {
|
||||
return failure;
|
||||
}
|
||||
|
||||
public void setFailure(Integer failure) {
|
||||
this.failure = failure;
|
||||
}
|
||||
public Integer getOver10ms() {
|
||||
return over10ms;
|
||||
}
|
||||
|
||||
public void setOver10ms(Integer over10ms) {
|
||||
this.over10ms = over10ms;
|
||||
}
|
||||
public Integer getOver50ms() {
|
||||
return over50ms;
|
||||
}
|
||||
|
||||
public void setOver50ms(Integer over50ms) {
|
||||
this.over50ms = over50ms;
|
||||
}
|
||||
public Integer getOver100ms() {
|
||||
return over100ms;
|
||||
}
|
||||
|
||||
public void setOver100ms(Integer over100ms) {
|
||||
this.over100ms = over100ms;
|
||||
}
|
||||
public Integer getOver500ms() {
|
||||
return over500ms;
|
||||
}
|
||||
|
||||
public void setOver500ms(Integer over500ms) {
|
||||
this.over500ms = over500ms;
|
||||
}
|
||||
public Integer getOver1000ms() {
|
||||
return over1000ms;
|
||||
}
|
||||
|
||||
public void setOver1000ms(Integer over1000ms) {
|
||||
this.over1000ms = over1000ms;
|
||||
}
|
||||
public Integer getOver5000ms() {
|
||||
return over5000ms;
|
||||
}
|
||||
|
||||
public void setOver5000ms(Integer over5000ms) {
|
||||
this.over5000ms = over5000ms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterfaceMonitor{" +
|
||||
"time=" + time +
|
||||
", interfaceName=" + interfaceName +
|
||||
", ip=" + ip +
|
||||
", total=" + total +
|
||||
", averageTime=" + averageTime +
|
||||
", maxTime=" + maxTime +
|
||||
", minTime=" + minTime +
|
||||
", failure=" + failure +
|
||||
", over10ms=" + over10ms +
|
||||
", over50ms=" + over50ms +
|
||||
", over100ms=" + over100ms +
|
||||
", over500ms=" + over500ms +
|
||||
", over1000ms=" + over1000ms +
|
||||
", over5000ms=" + over5000ms +
|
||||
"}";
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.syzb.monitor.mapper;
|
||||
|
||||
import com.syzb.common.mapper.EasyBaseMapper;
|
||||
import com.syzb.monitor.entity.InterfaceMonitor;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 接口监控统计表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author helloSyzb
|
||||
* @since 2025-04-09
|
||||
*/
|
||||
public interface InterfaceMonitorMapper extends EasyBaseMapper<InterfaceMonitor> {
|
||||
|
||||
}
|
||||
89
src/main/java/com/syzb/monitor/query/MonitorQuery.java
Normal file
89
src/main/java/com/syzb/monitor/query/MonitorQuery.java
Normal file
@ -0,0 +1,89 @@
|
||||
package com.syzb.monitor.query;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class MonitorQuery {
|
||||
|
||||
@NotNull
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@NotNull
|
||||
private LocalDateTime endTime;
|
||||
|
||||
private String ip;
|
||||
|
||||
private String name;
|
||||
|
||||
private String ticket;
|
||||
|
||||
private String groupBy;
|
||||
|
||||
private String orderBy;
|
||||
|
||||
private String order;
|
||||
|
||||
public LocalDateTime getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(LocalDateTime startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public LocalDateTime getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(LocalDateTime endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getTicket() {
|
||||
return ticket;
|
||||
}
|
||||
|
||||
public void setTicket(String ticket) {
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
public String getGroupBy() {
|
||||
return groupBy;
|
||||
}
|
||||
|
||||
public void setGroupBy(String groupBy) {
|
||||
this.groupBy = groupBy;
|
||||
}
|
||||
|
||||
public String getOrderBy() {
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
public void setOrderBy(String orderBy) {
|
||||
this.orderBy = orderBy;
|
||||
}
|
||||
|
||||
public String getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(String order) {
|
||||
this.order = order;
|
||||
}
|
||||
}
|
||||
297
src/main/java/com/syzb/monitor/service/MonitorService.java
Normal file
297
src/main/java/com/syzb/monitor/service/MonitorService.java
Normal file
@ -0,0 +1,297 @@
|
||||
package com.syzb.monitor.service;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.SecureUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.monitor.entity.InterfaceMonitor;
|
||||
import com.syzb.monitor.mapper.InterfaceMonitorMapper;
|
||||
import com.syzb.monitor.query.MonitorQuery;
|
||||
import com.syzb.monitor.vo.MonitorResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class MonitorService {
|
||||
|
||||
@Resource
|
||||
private HazelcastInstance hazelcastInstance;
|
||||
|
||||
@Resource
|
||||
private InterfaceMonitorMapper interfaceMonitorMapper;
|
||||
|
||||
private String host;
|
||||
|
||||
// 记录保存天数
|
||||
private static final int SAVE_DAY = 15;
|
||||
|
||||
// 固定排序字段和列关系,防止SQL注入
|
||||
private static Map<String, String> ORDER_BY_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
ORDER_BY_MAP.put("total", "total");
|
||||
ORDER_BY_MAP.put("averageTime", "average_time");
|
||||
ORDER_BY_MAP.put("maxTime", "max_time");
|
||||
ORDER_BY_MAP.put("minTime", "min_time");
|
||||
ORDER_BY_MAP.put("failure", "failure");
|
||||
ORDER_BY_MAP.put("over10ms", "over_10ms");
|
||||
ORDER_BY_MAP.put("over50ms", "over_50ms");
|
||||
ORDER_BY_MAP.put("over100ms", "over_100ms");
|
||||
ORDER_BY_MAP.put("over500ms", "over_500ms");
|
||||
ORDER_BY_MAP.put("over1000ms", "over_1000ms");
|
||||
ORDER_BY_MAP.put("over5000ms", "over_5000ms");
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void loadHost() {
|
||||
host = hazelcastInstance.getCluster().getLocalMember().getAddress().getHost();
|
||||
}
|
||||
|
||||
private List<MonitorResult> results = new ArrayList<>();
|
||||
|
||||
public void add(String name, Integer time) {
|
||||
this.add(name, time, null);
|
||||
}
|
||||
|
||||
public void add(String name, Integer time, Integer code) {
|
||||
this.results.add(new MonitorResult(name, time, code));
|
||||
}
|
||||
|
||||
// 使用自定义线程池+任务实现定时器,避免scheduledEnable条件,只跑admin服务
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// 创建一个调度线程池
|
||||
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
|
||||
|
||||
// 每分钟 保存日志
|
||||
scheduler.scheduleAtFixedRate(() -> save(), 1, 1, TimeUnit.MINUTES);
|
||||
|
||||
// 每天 清理日子
|
||||
scheduler.scheduleAtFixedRate(() -> clear(), 0, 1, TimeUnit.DAYS);
|
||||
}
|
||||
|
||||
// @Scheduled(cron = "0 * * * * ?")
|
||||
public void save() {
|
||||
// 5分钟执行一次
|
||||
if (LocalDateTime.now().getMinute() % 5 != 0) {
|
||||
return;
|
||||
}
|
||||
List<InterfaceMonitor> list = this.statistic();
|
||||
if (CollUtil.isNotEmpty(list)) {
|
||||
interfaceMonitorMapper.insertBatchSomeColumn(list);
|
||||
}
|
||||
}
|
||||
|
||||
// @Scheduled(cron = "0 1 2 * * ?")
|
||||
public void clear() {
|
||||
LocalDateTime time = LocalDate.now().minusDays(SAVE_DAY).atStartOfDay();
|
||||
LambdaQueryWrapper<InterfaceMonitor> wrapper = Wrappers.<InterfaceMonitor>lambdaQuery()
|
||||
.lt(InterfaceMonitor::getTime, time);
|
||||
interfaceMonitorMapper.delete(wrapper);
|
||||
}
|
||||
|
||||
public List<String> listIP(MonitorQuery query) {
|
||||
checkTicket(query);
|
||||
LocalDateTime startTime = query.getStartTime();
|
||||
LocalDateTime endTime = query.getEndTime();
|
||||
QueryWrapper<InterfaceMonitor> wrapper = Wrappers.<InterfaceMonitor>query()
|
||||
.select("distinct ip")
|
||||
.ge("time", startTime)
|
||||
.lt("time", endTime)
|
||||
.orderByAsc("ip");
|
||||
List<InterfaceMonitor> list = interfaceMonitorMapper.selectList(wrapper);
|
||||
return list.stream().map(InterfaceMonitor::getIp).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<String> listInterface(MonitorQuery query) {
|
||||
checkTicket(query);
|
||||
LocalDateTime startTime = query.getStartTime();
|
||||
LocalDateTime endTime = query.getEndTime();
|
||||
QueryWrapper<InterfaceMonitor> wrapper = Wrappers.<InterfaceMonitor>query()
|
||||
.select("distinct interface_name")
|
||||
.ge("time", startTime)
|
||||
.lt("time", endTime)
|
||||
.orderByAsc("interface_name");
|
||||
List<InterfaceMonitor> list = interfaceMonitorMapper.selectList(wrapper);
|
||||
return list.stream().map(InterfaceMonitor::getInterfaceName).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<InterfaceMonitor> listData(MonitorQuery query) {
|
||||
checkTicket(query);
|
||||
LocalDateTime startTime = query.getStartTime();
|
||||
LocalDateTime endTime = query.getEndTime();
|
||||
String ip = query.getIp();
|
||||
String name = query.getName();
|
||||
QueryWrapper<InterfaceMonitor> wrapper = Wrappers.<InterfaceMonitor>query()
|
||||
.select("time", "sum(total) as total", "avg(average_time) as average_time", "max(max_time) as max_time", "min(min_time) as min_time",
|
||||
"sum(failure) as failure", "sum(over_10ms) as over_10ms", "sum(over_50ms) as over_50ms", "sum(over_100ms) as over_100ms",
|
||||
"sum(over_500ms) as over_500ms", "sum(over_1000ms) as over_1000ms", "sum(over_5000ms) as over_5000ms")
|
||||
.ge("time", startTime)
|
||||
.lt("time", endTime)
|
||||
.eq(StrUtil.isNotEmpty(ip), "ip", ip)
|
||||
.likeRight(StrUtil.isNotEmpty(name), "interface_name", name)
|
||||
.groupBy("time")
|
||||
.orderByAsc("time");
|
||||
return interfaceMonitorMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
public List<InterfaceMonitor> groupData(MonitorQuery query) {
|
||||
checkTicket(query);
|
||||
LocalDateTime startTime = query.getStartTime();
|
||||
LocalDateTime endTime = query.getEndTime();
|
||||
String groupBy = query.getGroupBy();
|
||||
String groupColumn;
|
||||
if ("ip".equals(groupBy)) {
|
||||
groupColumn = "ip";
|
||||
} else if ("name".equals(groupBy)) {
|
||||
groupColumn = "interface_name";
|
||||
} else {
|
||||
throw new BizException(ResponseStatus.OUTSYS_ERROR);
|
||||
}
|
||||
String orderBy = query.getOrderBy();
|
||||
if (StrUtil.isNotEmpty(orderBy)) {
|
||||
orderBy = ORDER_BY_MAP.get(orderBy);
|
||||
}
|
||||
String order = query.getOrder();
|
||||
QueryWrapper<InterfaceMonitor> wrapper = Wrappers.<InterfaceMonitor>query()
|
||||
.select(groupColumn,
|
||||
"sum(total) as total", "avg(average_time) as average_time", "max(max_time) as max_time", "min(min_time) as min_time",
|
||||
"sum(failure) as failure", "sum(over_10ms) as over_10ms", "sum(over_50ms) as over_50ms", "sum(over_100ms) as over_100ms",
|
||||
"sum(over_500ms) as over_500ms", "sum(over_1000ms) as over_1000ms", "sum(over_5000ms) as over_5000ms")
|
||||
.ge("time", startTime)
|
||||
.lt("time", endTime)
|
||||
.groupBy(groupColumn)
|
||||
.orderByAsc(StrUtil.isEmpty(orderBy) || (!"ascending".equals(order) && !"descending".equals(order)), groupColumn)
|
||||
.orderByAsc(StrUtil.isNotEmpty(orderBy) && "ascending".equals(order), orderBy)
|
||||
.orderByDesc(StrUtil.isNotEmpty(orderBy) && "descending".equals(order), orderBy);
|
||||
return interfaceMonitorMapper.selectList(wrapper);
|
||||
}
|
||||
|
||||
private List<InterfaceMonitor> statistic() {
|
||||
// 暂存当前结果列表并清空缓存
|
||||
List<MonitorResult> list = results;
|
||||
results = new ArrayList<>();
|
||||
LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
|
||||
|
||||
// 按接口名汇总
|
||||
Map<String, List<MonitorResult>> map = list.stream().collect(Collectors.groupingBy(result -> result.name));
|
||||
|
||||
// 按接口计算总次数、平均耗时、最大耗时、最小耗时、失败次数、各耗时区间次数
|
||||
List<InterfaceMonitor> monitors = new ArrayList<>(map.size());
|
||||
|
||||
map.forEach((interfaceName, resultList) -> {
|
||||
InterfaceMonitor monitor = new InterfaceMonitor();
|
||||
monitor.setTime(now);
|
||||
monitor.setInterfaceName(interfaceName);
|
||||
monitor.setIp(host);
|
||||
|
||||
int total = resultList.size();
|
||||
int failureCount = 0;
|
||||
int totalTime = 0;
|
||||
int maxTime = 0;
|
||||
int minTime = 10000;
|
||||
int over10ms = 0;
|
||||
int over50ms = 0;
|
||||
int over100ms = 0;
|
||||
int over500ms = 0;
|
||||
int over1000ms = 0;
|
||||
int over5000ms = 0;
|
||||
|
||||
for (MonitorResult result : resultList) {
|
||||
int time = result.time;
|
||||
|
||||
// 计算总时间用于后面计算平均值
|
||||
totalTime += time;
|
||||
|
||||
// 计算最大最小时间
|
||||
maxTime = Math.max(time, maxTime);
|
||||
minTime = Math.min(time, minTime);
|
||||
|
||||
// 计算各时间区间次数
|
||||
if (time >= 10) {
|
||||
over10ms++;
|
||||
if (time >= 50) {
|
||||
over50ms++;
|
||||
if (time >= 100) {
|
||||
over100ms++;
|
||||
if (time >= 500) {
|
||||
over500ms++;
|
||||
if (time >= 1000) {
|
||||
over1000ms++;
|
||||
if (time >= 5000) {
|
||||
over5000ms++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算失败次数
|
||||
if (result.code != null && result.code != 0) {
|
||||
failureCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 设置计算结果
|
||||
monitor.setTotal(total);
|
||||
monitor.setFailure(failureCount);
|
||||
|
||||
if (total > 0) {
|
||||
monitor.setAverageTime(totalTime / total);
|
||||
monitor.setMaxTime(maxTime);
|
||||
monitor.setMinTime(minTime);
|
||||
} else {
|
||||
monitor.setAverageTime(0);
|
||||
monitor.setMaxTime(0);
|
||||
monitor.setMinTime(0);
|
||||
}
|
||||
|
||||
monitor.setOver10ms(over10ms);
|
||||
monitor.setOver50ms(over50ms);
|
||||
monitor.setOver100ms(over100ms);
|
||||
monitor.setOver500ms(over500ms);
|
||||
monitor.setOver1000ms(over1000ms);
|
||||
monitor.setOver5000ms(over5000ms);
|
||||
|
||||
monitors.add(monitor);
|
||||
});
|
||||
|
||||
return monitors;
|
||||
}
|
||||
|
||||
private static void checkTicket(MonitorQuery query) {
|
||||
if (!query.getTicket().equals(getTicket())) {
|
||||
throw new BizException(ResponseStatus.OUTSYS_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTicket() {
|
||||
String prefix = "hello_syzb_";
|
||||
String date = LocalDate.now().format(DatePattern.PURE_DATE_FORMATTER);
|
||||
return SecureUtil.md5(prefix + date);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(getTicket());
|
||||
}
|
||||
|
||||
}
|
||||
15
src/main/java/com/syzb/monitor/vo/MonitorResult.java
Normal file
15
src/main/java/com/syzb/monitor/vo/MonitorResult.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.syzb.monitor.vo;
|
||||
|
||||
public class MonitorResult {
|
||||
// 接口名
|
||||
public String name;
|
||||
// 接口耗时
|
||||
public Integer time;
|
||||
// 接口返回码(0:成功;非0:失败)
|
||||
public Integer code;
|
||||
public MonitorResult(String name, Integer time, Integer code) {
|
||||
this.name = name;
|
||||
this.time = time;
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
@ -14,7 +14,6 @@ import com.syzb.common.constant.UserStatus;
|
||||
import com.syzb.common.constant.UserType;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.state.StateMachine;
|
||||
import com.syzb.common.util.CodecUtil;
|
||||
import com.syzb.common.util.JwtUtil;
|
||||
import com.syzb.common.vo.AuthVO;
|
||||
@ -75,6 +74,9 @@ public class AuthService {
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Value("${user.admin.roles}")
|
||||
private Integer adminRoleId;
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public AuthVO login(LoginQuery query) {
|
||||
String uuid = query.getUuid();
|
||||
@ -220,9 +222,8 @@ public class AuthService {
|
||||
}
|
||||
|
||||
public Integer getAuthId(BackendUserVO backendUserVO) {
|
||||
int admin = StateMachine.ROLE.ADMIN;
|
||||
List<Integer> roles = backendUserVO.getRoles();
|
||||
if (roles.contains(admin)) {
|
||||
if (roles.contains(adminRoleId)) {
|
||||
return null;
|
||||
} else {
|
||||
return backendUserVO.getUserId();
|
||||
@ -244,7 +245,7 @@ public class AuthService {
|
||||
String deptId = backendUserVO.getDeptId();
|
||||
Map<String, Dept> deptMap = deptService.getDeptMap();
|
||||
Dept dept = deptMap.get(deptId);
|
||||
boolean contains = backendUserVO.getRoles().contains(StateMachine.ROLE.ADMIN);
|
||||
boolean contains = backendUserVO.getRoles().contains(adminRoleId);
|
||||
if (contains) {
|
||||
//超管
|
||||
return null;
|
||||
@ -292,7 +293,7 @@ public class AuthService {
|
||||
//分部:只查看所属部门的数据
|
||||
//总部:查看所有数据
|
||||
List<Integer> roles = backendUserVO.getRoles();
|
||||
if (roles.contains(StateMachine.ROLE.ADMIN)) {
|
||||
if (roles.contains(adminRoleId)) {
|
||||
return null;
|
||||
}
|
||||
if (DeptType.HEAD.value.equals(type)) {
|
||||
|
||||
@ -104,6 +104,12 @@ public class UserService {
|
||||
});
|
||||
}
|
||||
|
||||
public Map<Integer, UserLogin> getUserUserIdLoginMap() {
|
||||
Map<Integer, UserLogin> userLoginMap = getUserLoginMap();
|
||||
Map<Integer, UserDept> userDeptMap = getUserMap();
|
||||
return userDeptMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> userLoginMap.get(entry.getValue().getUserId())));
|
||||
}
|
||||
|
||||
public Map<String, List<UserDept>> getDeptUserMap() {
|
||||
return cacheService.get(USER, UserKey.USER_DEPT_MAP, () -> {
|
||||
List<UserDept> userList = userDeptMapper.selectList(Wrappers.emptyWrapper());
|
||||
|
||||
41
src/main/java/com/syzb/rbac/service/WxUserService.java
Normal file
41
src/main/java/com/syzb/rbac/service/WxUserService.java
Normal file
@ -0,0 +1,41 @@
|
||||
package com.syzb.rbac.service;
|
||||
|
||||
import com.syzb.common.config.cache.CacheKey;
|
||||
import com.syzb.common.service.CacheService;
|
||||
import com.syzb.rbac.entity.WxUser;
|
||||
import com.syzb.rbac.mapper.WxUserMapper;
|
||||
import com.syzb.rbac.vo.WxUserVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Service
|
||||
public class WxUserService {
|
||||
|
||||
@Resource
|
||||
private WxUserMapper wxUserMapper;
|
||||
|
||||
@Resource
|
||||
private CacheService cacheService;
|
||||
|
||||
public WxUserVO get(String userId) {
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
return cacheService.get(CacheKey.WX_USER, CacheKey.WxUserKey.USER + userId, () -> {
|
||||
WxUser user = wxUserMapper.selectById(userId);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
return new WxUserVO(user);
|
||||
});
|
||||
}
|
||||
|
||||
public String getHeadPic(String userId) {
|
||||
WxUserVO user = get(userId);
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
return user.getImgUrl();
|
||||
}
|
||||
}
|
||||
47
src/main/java/com/syzb/rbac/vo/WxUserVO.java
Normal file
47
src/main/java/com/syzb/rbac/vo/WxUserVO.java
Normal file
@ -0,0 +1,47 @@
|
||||
package com.syzb.rbac.vo;
|
||||
|
||||
import com.syzb.rbac.entity.WxUser;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class WxUserVO implements Serializable {
|
||||
|
||||
private String id;
|
||||
|
||||
private String nickName;
|
||||
|
||||
private String imgUrl;
|
||||
|
||||
public WxUserVO() {
|
||||
}
|
||||
|
||||
public WxUserVO(WxUser user) {
|
||||
this.id = user.getId();
|
||||
this.nickName = user.getNickName();
|
||||
this.imgUrl = user.getImgUrl();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNickName() {
|
||||
return nickName;
|
||||
}
|
||||
|
||||
public void setNickName(String nickName) {
|
||||
this.nickName = nickName;
|
||||
}
|
||||
|
||||
public String getImgUrl() {
|
||||
return imgUrl;
|
||||
}
|
||||
|
||||
public void setImgUrl(String imgUrl) {
|
||||
this.imgUrl = imgUrl;
|
||||
}
|
||||
}
|
||||
@ -110,7 +110,7 @@ public class AdminVideoActivityService {
|
||||
}
|
||||
VideoActivityStatus dbStatus = VideoActivityStatus.fromValue(dbActivity.getStatus());
|
||||
VideoActivityStatus event = VideoActivityStatus.fromValue(query.getStatus());
|
||||
VideoActivityStatus targetStatus = activityStatusSm.send(dbStatus, event, StateMachine.ROLE.ADMIN);
|
||||
VideoActivityStatus targetStatus = activityStatusSm.send(dbStatus, event, backendUserVO);
|
||||
VideoLiveActivity activity = query.toPO(targetStatus, VideoActivityStatus.PASS.equals(targetStatus) ? backendUserVO.getUserId() : null);
|
||||
if (VideoActivityStatus.PASS.equals(targetStatus)) {
|
||||
check(dbActivity.getActivityRang(), dbActivity.getAdvisorId());
|
||||
|
||||
@ -80,7 +80,7 @@ public class AdminVideoCartService {
|
||||
VideoCart dbCart = getVideoCart(videoId, productId, productType);
|
||||
VideoCartStatus dbStatus = VideoCartStatus.fromValue(dbCart.getStatus());
|
||||
VideoCartStatus submitStatus = VideoCartStatus.fromValue(query.getStatus());
|
||||
VideoCartStatus status = videoCartStatusSm.send(dbStatus, submitStatus, StateMachine.ROLE.ADVISOR);
|
||||
VideoCartStatus status = videoCartStatusSm.send(dbStatus, submitStatus, backendUserVO);
|
||||
dbCart.setStatus(status.value);
|
||||
if (query.getNum() != null) {
|
||||
dbCart.setSaleLimit(query.getNum());
|
||||
|
||||
@ -336,7 +336,7 @@ public class AdminVideoInfoService {
|
||||
}
|
||||
}
|
||||
VideoStatus dbStatus = VideoStatus.fromValue(videoInDb.getStatus());
|
||||
VideoStatus targetStatus = videoStatusSm.send(dbStatus, VideoStatus.EVENT_UPDATE, StateMachine.ROLE.ADVISOR);
|
||||
VideoStatus targetStatus = videoStatusSm.send(dbStatus, VideoStatus.EVENT_UPDATE, backendUser);
|
||||
// 管理员修改/待提交/驳回/下架直接修改
|
||||
if (VideoStatus.INIT.equals(dbStatus) || VideoStatus.REJECTED.equals(dbStatus) || VideoStatus.SOLD_OUT.equals(dbStatus) || VideoStatus.PASS.equals(dbStatus)) {
|
||||
// 上架修改需要添加修改待审核
|
||||
@ -535,7 +535,7 @@ public class AdminVideoInfoService {
|
||||
if (isSoldOut) {
|
||||
//下架修改直播状态和推流状态
|
||||
video.setLiveStatus(VideoLiveStatus.HAS_ENDED.value);
|
||||
videoCommonService.endVideo(null, new VideoLive(id, VideoLiveStatus.HAS_ENDED.value, now));
|
||||
videoCommonService.endVideo(null, new VideoLive(id, VideoLiveStatus.HAS_ENDED.value, now), false);
|
||||
}
|
||||
if (VideoLiveStatus.LIVING.value.equals(videoInDb.getLiveStatus())) {
|
||||
video.setRealEndTime(now);
|
||||
|
||||
@ -14,14 +14,15 @@ import com.syzb.advisor.entity.AdvisorFollow;
|
||||
import com.syzb.advisor.mapper.AdvisorFollowMapper;
|
||||
import com.syzb.common.constant.IsFollow;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.entity.OnlineUser;
|
||||
import com.syzb.common.service.OnlineUserService;
|
||||
import com.syzb.video.constant.VideoLiveStatus;
|
||||
import com.syzb.video.constant.VideoMessageContentType;
|
||||
import com.syzb.video.constant.VideoMessageStatus;
|
||||
import com.syzb.video.constant.VideoUserRecordType;
|
||||
import com.syzb.video.entity.*;
|
||||
import com.syzb.video.mapper.*;
|
||||
import com.syzb.video.service.common.VideoCacheService;
|
||||
import com.syzb.video.vo.statistic.VideoStatisticStaffDetailVO;
|
||||
import com.syzb.video.vo.statistic.VideoStatisticUserDetailVO;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -73,7 +74,7 @@ public class AdminVideoInteractionService {
|
||||
private VideoLiveMapper videoLiveMapper;
|
||||
|
||||
@Resource
|
||||
private VideoCacheService videoCacheService;
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
@Value("${video.finishReadRatio}")
|
||||
private Double finishReadRatio;
|
||||
@ -342,7 +343,7 @@ public class AdminVideoInteractionService {
|
||||
public Integer queryWatchUserCount(Collection<Integer> videoIds) {
|
||||
QueryWrapper<VideoUserWatchCollect> wrapper = Wrappers.<VideoUserWatchCollect>query()
|
||||
// 总观看时长使用字段live_seconds,总人数使用字段vod_seconds
|
||||
.select("video_id, ifnull(count(0), 0) as vod_seconds")
|
||||
.select("count(0) as vod_seconds")
|
||||
.in("video_id", videoIds);
|
||||
VideoUserWatchCollect totalWatch = videoUserWatchCollectMapper.selectOne(wrapper);
|
||||
return totalWatch == null ? 0 : totalWatch.getVodSeconds();
|
||||
@ -563,7 +564,7 @@ public class AdminVideoInteractionService {
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveVideoUserDataToDB() {
|
||||
IMap<String, OnlineUser> onlineMap = videoCacheService.getTotalOnlineMap();
|
||||
IMap<String, OnlineUser> onlineMap = onlineUserService.getTotalOnlineMap(ProductType.VIDEO_SINGLE.value);
|
||||
Collection<OnlineUser> onlineUsers = onlineMap.values();
|
||||
if (CollUtil.isEmpty(onlineUsers)) {
|
||||
return;
|
||||
|
||||
@ -19,6 +19,7 @@ import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.Pager;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.service.CacheService;
|
||||
import com.syzb.common.service.OnlineUserService;
|
||||
import com.syzb.common.vo.BackendUserVO;
|
||||
import com.syzb.rbac.entity.Dept;
|
||||
import com.syzb.rbac.entity.UserDept;
|
||||
@ -93,10 +94,12 @@ public class AdminVideoStatisticService {
|
||||
@Resource
|
||||
private VideoCloudService videoCloudService;
|
||||
|
||||
@Resource
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
@Value("${video.finishReadRatio}")
|
||||
private Double finishReadRatio;
|
||||
|
||||
|
||||
/**
|
||||
* 单场分析
|
||||
*
|
||||
@ -357,7 +360,7 @@ public class AdminVideoStatisticService {
|
||||
.eq(VideoDataType.ADVISOR.value.equals(type), VideoLive::getAdvisorId, advisorId)
|
||||
.eq(VideoDataType.VIDEO.value.equals(type), VideoLive::getId, videoId)
|
||||
.in(CollUtil.isNotEmpty(authSet) && videoId == null, VideoLive::getAdvisorId, authSet)
|
||||
.eq(VideoLive::getStatus, VideoStatus.PASS.value)
|
||||
.in(VideoLive::getStatus, VideoStatus.PASS.value, VideoStatus.SOLD_OUT.value)
|
||||
.eq(VideoLive::getIsCart, IsOrNot.IS.value)
|
||||
.between(startTime != null && endTime != null, VideoLive::getRealStartTime, startTime, endTime);
|
||||
List<VideoLive> videoLiveList = videoLiveMapper.selectList(wrapper);
|
||||
@ -637,7 +640,7 @@ public class AdminVideoStatisticService {
|
||||
}
|
||||
Page<VideoStatisticUserDetailVO> page = adminVideoInteractionService.selectVideoUserDetail(query.toPage(), wrapper);
|
||||
List<VideoStatisticUserDetailVO> records = page.getRecords();
|
||||
Set<String> onlineUserIdSet = videoCacheService.getOnlineUserIds(videoId);
|
||||
Set<String> onlineUserIdSet = onlineUserService.getOnlineUserIds(ProductType.VIDEO_SINGLE.value, videoId);
|
||||
Map<Integer, String> userNameMap = userService.getUserMap().values().stream().collect(Collectors.toMap(UserDept::getUserId, UserDept::getName));
|
||||
Map<String, Integer> readMinuteMap = adminVideoInteractionService.calcuVideoReadMap(videoId, null, null, null);
|
||||
Map<String, Integer> messageCountMap = adminVideoInteractionService.calUserMessageCount(videoId, null, VideoMessageContentType.TEXT);
|
||||
@ -857,7 +860,7 @@ public class AdminVideoStatisticService {
|
||||
// 填充实时在线人数
|
||||
// 直播在线人数峰值
|
||||
vo.setOnlineMostNum(adminVideoInteractionService.getOnlineMax(videoId));
|
||||
vo.setOnlineNum(!VideoLiveStatus.HAS_ENDED.value.equals(liveStatus) ? videoCacheService.getOnlineCount(videoId) : 0);
|
||||
vo.setOnlineNum(!VideoLiveStatus.HAS_ENDED.value.equals(liveStatus) ? onlineUserService.getOnlineCountWithoutCache(ProductType.VIDEO_SINGLE.value, videoId) : 0);
|
||||
// 直播观看
|
||||
if (realStartTime == null && Objects.equals(video.getPlayType(), VideoPlayType.LIVE.value)) {
|
||||
vo.setReadNum(0);
|
||||
@ -1047,7 +1050,7 @@ public class AdminVideoStatisticService {
|
||||
*/
|
||||
public UserOnlineVO queryUserOnline(UserOnlineQuery query) {
|
||||
Integer videoId = query.getVideoId();
|
||||
Set<String> onlineUserIds = videoCacheService.getOnlineUserIds(videoId);
|
||||
Set<String> onlineUserIds = onlineUserService.getOnlineUserIds(ProductType.VIDEO_SINGLE.value, videoId);
|
||||
String userId = query.getUserId();
|
||||
Integer isOnline = onlineUserIds.contains(userId) ? IsOrNot.IS.value : IsOrNot.NOT.value;
|
||||
return new UserOnlineVO(userId, videoId, isOnline);
|
||||
|
||||
@ -13,6 +13,7 @@ import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.AppPager;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.service.OnlineUserService;
|
||||
import com.syzb.common.service.RecommendService;
|
||||
import com.syzb.common.vo.FrontUserVO;
|
||||
import com.syzb.rbac.service.UserService;
|
||||
@ -53,6 +54,9 @@ public class AppVideoColumnService {
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Resource
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
/**
|
||||
* 获取主栏目列表
|
||||
*
|
||||
@ -66,7 +70,7 @@ public class AppVideoColumnService {
|
||||
ColumnRecommendAppVO columnRecommendAppVO = new ColumnRecommendAppVO(columnId, columnName, null, null);
|
||||
Integer videoId = videoCacheService.getVideoColumnLivingVideo(columnId);
|
||||
columnRecommendAppVO.setStatus(videoId == null ? null : VideoLiveStatus.LIVING.value);
|
||||
columnRecommendAppVO.setOnline(videoId == null ? null : videoCacheService.getOnlineCount(videoId));
|
||||
columnRecommendAppVO.setOnline(videoId == null ? null : onlineUserService.getOnlineCount(ProductType.VIDEO_SINGLE.value, videoId));
|
||||
return columnRecommendAppVO;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
@ -138,7 +142,7 @@ public class AppVideoColumnService {
|
||||
}
|
||||
VideoColumnAppVO vo = new VideoColumnAppVO(column);
|
||||
Integer lastVideoId = videoCacheService.getVideoColumnLivingVideo(id);
|
||||
vo.setLastVideo(lastVideoId != null ? new VideoBasicInfoVO(lastVideoId, videoCacheService.getOnlineCount(lastVideoId)) : null);
|
||||
vo.setLastVideo(lastVideoId != null ? new VideoBasicInfoVO(lastVideoId, onlineUserService.getOnlineCount(ProductType.VIDEO_SINGLE.value, lastVideoId)) : null);
|
||||
vo.setReadCount(videoCacheService.getVideoColumnReadCount(vo.getId()));
|
||||
if (frontUserVO != null) {
|
||||
vo.setIsSub(videoCacheService.checkFollowColumn(frontUserVO.getUserId(), column.getId()));
|
||||
|
||||
@ -27,6 +27,9 @@ import com.syzb.common.vo.AuthResultVO;
|
||||
import com.syzb.common.vo.FrontUserVO;
|
||||
import com.syzb.common.vo.MergeProductInfoVO;
|
||||
import com.syzb.common.vo.TagVO;
|
||||
import com.syzb.rbac.entity.UserDept;
|
||||
import com.syzb.rbac.entity.UserLogin;
|
||||
import com.syzb.rbac.service.UserService;
|
||||
import com.syzb.video.constant.*;
|
||||
import com.syzb.video.entity.*;
|
||||
import com.syzb.video.helper.AbstractVideoSortComparator;
|
||||
@ -98,6 +101,12 @@ public class AppVideoInfoService {
|
||||
@Resource
|
||||
private VideoLiveMixMapper videoLiveMixMapper;
|
||||
|
||||
@Resource
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Value("${resizeUrl.urlMain}")
|
||||
private String urlMain;
|
||||
|
||||
@ -157,7 +166,15 @@ public class AppVideoInfoService {
|
||||
appVideoCustomerService.saveCustomerSale(saleUserId, userId, id);
|
||||
videoCommonService.publishPcMessageWithDebounce(id);
|
||||
}
|
||||
|
||||
if (saleUserId != null) {
|
||||
UserDept userDept = userService.getUserMap().get(saleUserId);
|
||||
if (userDept != null && userDept.getLoginId() != null) {
|
||||
UserLogin userLogin = userService.getUserLoginMap().get(userDept.getLoginId());
|
||||
if (userLogin != null) {
|
||||
vo.setSaleUserWorkNo(userLogin.getUpId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
@ -379,7 +396,7 @@ public class AppVideoInfoService {
|
||||
Integer liveStatus = vo.getLiveStatus();
|
||||
vo.setOnline(0);
|
||||
if (VideoLiveStatus.LIVING.value.equals(liveStatus)) {
|
||||
vo.setOnline(videoCacheService.getOnlineCount(vo.getId()));
|
||||
vo.setOnline(onlineUserService.getOnlineCount(ProductType.VIDEO_SINGLE.value, vo.getId()));
|
||||
}
|
||||
voList.add(vo);
|
||||
if (--size == 0) {
|
||||
@ -478,7 +495,7 @@ public class AppVideoInfoService {
|
||||
}
|
||||
vo.setFavorUserCount(videoCacheService.getVideoFavorUserCount(videoId));
|
||||
vo.setSubscribeUserCount(videoCacheService.getVideoSubscribeUserCount(videoId));
|
||||
vo.setOnline(videoCacheService.getOnlineCount(videoId));
|
||||
vo.setOnline(onlineUserService.getOnlineCount(ProductType.VIDEO_SINGLE.value, videoId));
|
||||
if (video.getProductId() != null && video.getProductType() != null) {
|
||||
Table<Integer, Integer, MergeProductInfoVO> table = mergeProductService.queryMergeProductInfo(Collections.singletonList(video));
|
||||
vo.setInfoVO(table.get(video.getProductType(), video.getProductId()));
|
||||
@ -608,7 +625,7 @@ public class AppVideoInfoService {
|
||||
List<VideoFollowAdvisorInfoAppVO> mergeVos = getRecommendedVideos(advisorIds, includeVideoIds);
|
||||
appVOS = appVOS.stream().peek(a -> {
|
||||
Integer videoId = a.getVideoId();
|
||||
Integer online = videoCacheService.getOnlineCount(videoId);
|
||||
Integer online = onlineUserService.getOnlineCount(ProductType.VIDEO_SINGLE.value, videoId);
|
||||
a.setOnline(online);
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
|
||||
@ -8,8 +8,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.hazelcast.collection.ISet;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.hazelcast.map.IMap;
|
||||
import com.hazelcast.sql.SqlResult;
|
||||
import com.hazelcast.sql.SqlRow;
|
||||
import com.syzb.advisor.constant.FollowOption;
|
||||
import com.syzb.advisor.entity.AdvisorBasic;
|
||||
import com.syzb.advisor.service.AdvisorInfoService;
|
||||
@ -17,13 +15,11 @@ import com.syzb.common.config.cache.CacheKey;
|
||||
import com.syzb.common.constant.IsActive;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.entity.OnlineUser;
|
||||
import com.syzb.common.result.AppPager;
|
||||
import com.syzb.common.service.AdvertService;
|
||||
import com.syzb.common.service.CacheService;
|
||||
import com.syzb.common.service.RecommendService;
|
||||
import com.syzb.common.service.TagService;
|
||||
import com.syzb.common.util.logger.LoggerUtil;
|
||||
import com.syzb.common.vo.FrontUserVO;
|
||||
import com.syzb.common.vo.TagVO;
|
||||
import com.syzb.course.constant.CourseContentType;
|
||||
@ -56,7 +52,6 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@ -163,82 +158,6 @@ public class VideoCacheService {
|
||||
return hazelcastInstance.getMap(mapName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取总在线用户映射
|
||||
*
|
||||
* @return 在线用户映射
|
||||
*/
|
||||
public IMap<String, OnlineUser> getTotalOnlineMap() {
|
||||
return hazelcastInstance.getMap(VIDEO_ONLINE_USER);
|
||||
}
|
||||
|
||||
public List<OnlineUser> getTotalOnlineList(Integer videoId) {
|
||||
String sql = "SELECT * FROM " + VIDEO_ONLINE_USER + " WHERE productId = " + videoId;
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
List<OnlineUser> list = new ArrayList<>();
|
||||
for (SqlRow row : result) {
|
||||
OnlineUser user = new OnlineUser();
|
||||
user.setProductType(row.getObject("productType"));
|
||||
user.setProductId(row.getObject("productId"));
|
||||
user.setUserId(row.getObject("userId"));
|
||||
user.setUserName(row.getObject("userName"));
|
||||
user.setImg(row.getObject("img"));
|
||||
user.setSessionId(row.getObject("sessionId"));
|
||||
user.setIsOnline(row.getObject("isOnline"));
|
||||
user.setIsPlay(row.getObject("isPlay"));
|
||||
user.setCreateTime(row.getObject("createTime"));
|
||||
user.setExitTime(row.getObject("exitTime"));
|
||||
list.add(user);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public Set<String> getOnlineUserIds(Integer videoId) {
|
||||
String sql = "SELECT distinct userId FROM " + VIDEO_ONLINE_USER + " WHERE productId = " + videoId;
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
Set<String> set = new HashSet<>();
|
||||
for (SqlRow row : result) {
|
||||
set.add(row.getObject("userId"));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线人数
|
||||
*
|
||||
* @param videoId 视频ID
|
||||
* @return 在线人数
|
||||
*/
|
||||
public int getOnlineCount(Integer videoId) {
|
||||
IMap<String, Object> map = hazelcastInstance.getMap(VIDEO_LIVE);
|
||||
String cacheKey = VideoLiveKey.ONLINE_COUNT + videoId;
|
||||
Integer onlineCount = (Integer) map.get(cacheKey);
|
||||
if (onlineCount != null) {
|
||||
return onlineCount;
|
||||
}
|
||||
synchronized (this) {
|
||||
onlineCount = (Integer) map.get(cacheKey);
|
||||
if (onlineCount != null) {
|
||||
return onlineCount;
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
onlineCount = getOnlineCountWithoutCache(videoId);
|
||||
LoggerUtil.websocket.info("getOnlineCount-" + videoId + ":" + (System.currentTimeMillis() - startTime) + "ms");
|
||||
map.put(cacheKey, onlineCount, 2, TimeUnit.SECONDS);
|
||||
}
|
||||
return onlineCount;
|
||||
}
|
||||
|
||||
public int getOnlineCountWithoutCache(Integer videoId) {
|
||||
String sql = "SELECT COUNT(*) FROM " + VIDEO_ONLINE_USER + " WHERE productId = " + videoId + " and isOnline = 1";
|
||||
SqlResult result = hazelcastInstance.getSql().execute(sql);
|
||||
Iterator<SqlRow> iter = result.iterator();
|
||||
if (iter.hasNext()) {
|
||||
return ((Long)iter.next().getObject(0)).intValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Integer getVideoSubscribeUserCount(Integer videoId) {
|
||||
return getVideoUserSubscribeIds(videoId).size();
|
||||
}
|
||||
|
||||
@ -471,16 +471,15 @@ public class VideoCloudService {
|
||||
*
|
||||
* @see [https://console.cloud.tencent.com/api/explorer?Product=live&Version=2018-08-01&Action=CreateRecordTask]
|
||||
*/
|
||||
public String createRecordTask(String streamId) {
|
||||
public String createRecordTask(String streamId, LocalDateTime endTime) {
|
||||
try {
|
||||
// 开启任务流录制
|
||||
LocalDateTime end = LocalDateTime.now().toLocalDate().plusDays(1).atStartOfDay();
|
||||
Instant instant = end.atZone(ZoneId.systemDefault()).toInstant();
|
||||
Instant instant = endTime.atZone(ZoneId.systemDefault()).toInstant();
|
||||
// 将Instant转换为毫秒级时间戳
|
||||
long timestamp = instant.toEpochMilli();
|
||||
long endTime = BigDecimal.valueOf(timestamp).divide(BigDecimal.valueOf(1000), 0, RoundingMode.HALF_UP).longValue();
|
||||
long endTimestamp = BigDecimal.valueOf(timestamp).divide(BigDecimal.valueOf(1000), 0, RoundingMode.HALF_UP).longValue();
|
||||
CreateRecordTaskRequest request = new CreateRecordTaskRequest();
|
||||
request.setEndTime(endTime);
|
||||
request.setEndTime(endTimestamp);
|
||||
request.setStreamName(streamId);
|
||||
request.setDomainName(config.getPushHost());
|
||||
request.setAppName(config.getAppName());
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.syzb.video.service.common;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
@ -110,6 +111,9 @@ public class VideoCommonService {
|
||||
@Resource
|
||||
private CacheService cacheService;
|
||||
|
||||
@Resource
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
// 防抖延时(ms)
|
||||
private final long pushDelay = 10 * 1000;
|
||||
|
||||
@ -212,7 +216,7 @@ public class VideoCommonService {
|
||||
Integer totalReadCount = adminVideoInteractionService.queryInteractionCount(v.getId(), VideoUserRecordType.READ, null, null, false);
|
||||
entity.setLiveNum(totalReadCount);
|
||||
videoLiveMapper.updateById(entity);
|
||||
endVideo(cacheMap, v);
|
||||
endVideo(cacheMap, v, true);
|
||||
adminVideoQuestionService.stopByVideoId(v.getId());
|
||||
});
|
||||
}
|
||||
@ -245,11 +249,21 @@ public class VideoCommonService {
|
||||
* @param cacheMap 缓存
|
||||
* @param video 直播信息
|
||||
*/
|
||||
public void endVideo(Map<String, Object> cacheMap, VideoLive video) {
|
||||
public void endVideo(Map<String, Object> cacheMap, VideoLive video, boolean isTask) {
|
||||
// 清除直播状态缓存
|
||||
videoCacheService.clearVideoInfoCache(video.getId(), cacheMap);
|
||||
// 已结束,中断投顾推流
|
||||
videoCloudService.dropLiveStream(video.getId());
|
||||
// 已结束,禁推投顾推流
|
||||
try {
|
||||
if (isTask) {
|
||||
videoCloudService.stopRecordTask(video);
|
||||
videoCloudService.forbidLiveStream(video.getId().toString());
|
||||
} else {
|
||||
videoCloudService.dropLiveStream(video.getId());
|
||||
}
|
||||
} catch(Exception e) {
|
||||
// 忽略异常
|
||||
LoggerUtil.error("结束直播失败:", ExceptionUtil.stacktraceToString(e));
|
||||
}
|
||||
// 直播结束通知
|
||||
videoMessageService.publishLiveStatusNotification(video.getId(), VideoLiveStatus.HAS_ENDED.value);
|
||||
// 直播状态推送(pc)
|
||||
@ -344,7 +358,7 @@ public class VideoCommonService {
|
||||
try {
|
||||
Integer videoId = video.getId();
|
||||
String videoName = video.getTitle();
|
||||
Set<String> onlineUserIds = videoCacheService.getOnlineUserIds(videoId);
|
||||
Set<String> onlineUserIds = onlineUserService.getOnlineUserIds(ProductType.VIDEO_SINGLE.value, videoId);
|
||||
|
||||
// 查询预约的用户
|
||||
LambdaQueryWrapper<VideoLiveUser> subWrapper = Wrappers.<VideoLiveUser>lambdaQuery()
|
||||
@ -571,7 +585,7 @@ public class VideoCommonService {
|
||||
//观看
|
||||
Integer readCount = videoCacheService.getVideoReadCount(videoId);
|
||||
//在线数
|
||||
int onlineCount = videoCacheService.getOnlineCount(videoId);
|
||||
int onlineCount = onlineUserService.getOnlineCount(ProductType.VIDEO_SINGLE.value, videoId);
|
||||
VideoPcAdvisorMessageVO messageVO = new VideoPcAdvisorMessageVO(favorCount, readCount, onlineCount);
|
||||
videoMessageService.publishPcAdvisorMessage(videoId, messageVO);
|
||||
}
|
||||
|
||||
@ -125,7 +125,8 @@ public class VideoExternalService {
|
||||
// 记录直播前观看人次
|
||||
Integer preNum = adminVideoInteractionService.queryInteractionCount(id, VideoUserRecordType.READ, null, null, false);
|
||||
live.setPreNum(preNum == null ? 0 : preNum);
|
||||
String taskId = videoCloudService.createRecordTask(streamId);
|
||||
LocalDateTime endTime = video.getEndTime().toLocalDate().plusDays(1).atStartOfDay();
|
||||
String taskId = videoCloudService.createRecordTask(streamId, endTime);
|
||||
live.setTaskId(taskId);
|
||||
}
|
||||
live.setLiveStatus(liveStatus);
|
||||
|
||||
@ -10,9 +10,11 @@ import com.hazelcast.map.IMap;
|
||||
import com.hazelcast.topic.ITopic;
|
||||
import com.syzb.advisor.service.AdvisorInfoService;
|
||||
import com.syzb.common.constant.IsOrNot;
|
||||
import com.syzb.common.constant.ProductType;
|
||||
import com.syzb.common.entity.OnlineUser;
|
||||
import com.syzb.common.handler.BizException;
|
||||
import com.syzb.common.result.ResponseStatus;
|
||||
import com.syzb.common.service.OnlineUserService;
|
||||
import com.syzb.common.util.logger.LoggerUtil;
|
||||
import com.syzb.common.vo.FrontUserVO;
|
||||
import com.syzb.rbac.service.UserService;
|
||||
@ -66,6 +68,9 @@ public class VideoMessageService {
|
||||
@Resource
|
||||
private UserService userService;
|
||||
|
||||
@Resource
|
||||
private OnlineUserService onlineUserService;
|
||||
|
||||
private ITopic<VideoWsMessageVO<?>> videoNotifyTopic = null;
|
||||
|
||||
private ITopic<VideoWsMessageVO<?>> videoMessageTopic = null;
|
||||
@ -287,7 +292,7 @@ public class VideoMessageService {
|
||||
}
|
||||
vo.setAdvisorBasic(advisorInfoService.getAdvisorVoMap().get(message.getAdvisorId()));
|
||||
if (VideoMessageContentType.USER_ENTER.value.equals(vo.getType())) {
|
||||
vo.setOnline(videoCacheService.getOnlineCount(vo.getVideoId()));
|
||||
vo.setOnline(onlineUserService.getOnlineCount(ProductType.VIDEO_SINGLE.value,vo.getVideoId()));
|
||||
}
|
||||
if (vo.getCreateUserId() != null) {
|
||||
vo.setCreateUserVO(userService.get(message.getCreateUserId(), false));
|
||||
@ -327,14 +332,14 @@ public class VideoMessageService {
|
||||
*/
|
||||
public void listMember(Integer videoId) {
|
||||
//获取进入过直播间的人数
|
||||
List<OnlineUser> totalOnlineList = videoCacheService.getTotalOnlineList(videoId);
|
||||
List<OnlineUser> totalOnlineList = onlineUserService.getTotalOnlineList(ProductType.VIDEO_SINGLE.value, videoId);
|
||||
int totalCount = totalOnlineList.size();
|
||||
LoggerUtil.info("获取直播间在线人列表入参:" + videoId);
|
||||
LoggerUtil.info("直播间id=" + videoId + "总人数:" + totalCount);
|
||||
VideoCustomerVO videoCustomerVO = new VideoCustomerVO(null, 0, 0);
|
||||
if (totalCount != 0) {
|
||||
//获取在线人数
|
||||
int onlineCount = videoCacheService.getOnlineCount(videoId);
|
||||
int onlineCount = onlineUserService.getOnlineCountWithoutCache(ProductType.VIDEO_SINGLE.value, videoId);
|
||||
LoggerUtil.info("直播间id=" + videoId + "在线人数:" + onlineCount);
|
||||
videoCustomerVO = new VideoCustomerVO(totalOnlineList, onlineCount, totalCount);
|
||||
}
|
||||
@ -464,7 +469,7 @@ public class VideoMessageService {
|
||||
LoggerUtil.error("reportPlayStatus上报类型错误, reportType:" + reportType);
|
||||
throw new BizException(ResponseStatus.PARM_ERROR, "上报类型错误");
|
||||
}
|
||||
IMap<String, OnlineUser> totalOnlineMap = videoCacheService.getTotalOnlineMap();
|
||||
IMap<String, OnlineUser> totalOnlineMap = onlineUserService.getTotalOnlineMap(ProductType.VIDEO_SINGLE.value);
|
||||
String cacheKey = VideoHelper.buildOnlineUserCacheKey(videoId, sessionKey);
|
||||
OnlineUser onlineUser = totalOnlineMap.get(cacheKey);
|
||||
if (onlineUser == null) {
|
||||
|
||||
@ -183,6 +183,9 @@ public class VideoDetailAppVO implements IVideoInfoAppVO, Serializable {
|
||||
@ApiModelProperty("是否显示完整昵称 1 显示 2 屏蔽")
|
||||
private Integer showNickname;
|
||||
|
||||
@ApiModelProperty("营销经理工号")
|
||||
private String saleUserWorkNo;
|
||||
|
||||
public VideoDetailAppVO() {
|
||||
}
|
||||
|
||||
@ -651,4 +654,12 @@ public class VideoDetailAppVO implements IVideoInfoAppVO, Serializable {
|
||||
public void setShowNickname(Integer showNickname) {
|
||||
this.showNickname = showNickname;
|
||||
}
|
||||
|
||||
public String getSaleUserWorkNo() {
|
||||
return saleUserWorkNo;
|
||||
}
|
||||
|
||||
public void setSaleUserWorkNo(String saleUserWorkNo) {
|
||||
this.saleUserWorkNo = saleUserWorkNo;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ cron:
|
||||
syncModuleUser: "40 1/5 * * * ?"
|
||||
user:
|
||||
admin:
|
||||
roles: 1,3,4,5 #管理员角色id,用逗号隔开
|
||||
roles: 1 #管理员角色id,用逗号隔开
|
||||
defaultPwd: syzb.hello.dev
|
||||
dept:
|
||||
head:
|
||||
|
||||
@ -11,24 +11,27 @@ file:
|
||||
prefix: https://do.tgsys.sztg.com/
|
||||
resizePrefix: https://do.tgsys.sztg.com/resize/
|
||||
cron:
|
||||
collectLivingVideo: "20 0/5 * * * ?" #每分钟统计已开始但未结束的视频直播数据
|
||||
saveVideoCount: "20 1/5 * * * ?" #从cache刷新视频播放量到DB 每分钟的第10s执行
|
||||
saveVideoUserDataToDB: "20 2/5 * * * ?"
|
||||
saveCustomerDataToDB: "20 3/5 * * * ?" #收集用户信息
|
||||
refreshTranscodeStatus: "20 4/5 * * * ?" #从腾讯云拉取录播上传视频信息更新到DB
|
||||
updateLiveStatus: "0 1 * * * ?" #更新视频录播状态
|
||||
stopLivingVideo: "0 1-5 0 * * ?" #结束前一天直播中/暂停中的视频直播
|
||||
collectLastWeek: "0 30 3 * * ?" #统计一周内的数据
|
||||
saveWatchSeconds: "0 0/5 * * * ?" #保存短视频观看时长
|
||||
collectRecentEndVideo: "0 1/5 * * * ?" #每5分钟统计已结束48小时以内的视频直播数据
|
||||
saveGroupMessageRead: "0 2/5 * * * ?" #每5分钟统计已结束48小时以内的视频直播数据
|
||||
saveVideoUserDataToDB: "10 * * * * ?"
|
||||
collectLivingVideo: "20 * * * * ?" #每5分钟统计已开始但未结束的视频直播数据
|
||||
saveVideoCount: "30 * * * * ?" #从cache刷新视频播放量到DB 每分钟的第10s执行
|
||||
saveCustomerDataToDB: "40 * * * * ?" #收集用户信息
|
||||
saveGroupMessageRead: "50 * * * * ?" #每5分钟统计已结束48小时以内的视频直播数据
|
||||
|
||||
refreshTranscodeStatus: "0 0/5 * * * ?" #从腾讯云拉取录播上传视频信息更新到DB
|
||||
saveWatchSeconds: "0 1/5 * * * ?" #保存短视频观看时长
|
||||
collectRecentEndVideo: "0 2/5 * * * ?" #每5分钟统计已结束48小时以内的视频直播数据
|
||||
saveGroupUser: "0 3/5 * * * ?"
|
||||
collectGroupData: "0 4/5 * * * ?"
|
||||
syncOrder: "40 0/5 * * * ?"
|
||||
syncModuleUser: "40 1/5 * * * ?"
|
||||
|
||||
updateLiveStatus: "25 1 * * * ?" #更新视频录播状态
|
||||
syncOrder: "25 0/5 * * * ?"
|
||||
syncModuleUser: "25 1/5 * * * ?"
|
||||
|
||||
collectLastWeek: "45 30 3 * * ?" #统计一周内的数据
|
||||
stopLivingVideo: "45 1-5 0 * * ?" #结束前一天直播中/暂停中的视频直播
|
||||
user:
|
||||
admin:
|
||||
roles: 1,3,4,5 #管理员角色id,用逗号隔开
|
||||
roles: 1 #管理员角色id,用逗号隔开
|
||||
defaultPwd: syzb.hello.dev
|
||||
dept:
|
||||
head:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user