新地址
This commit is contained in:
659
src/views/index.vue
Normal file
659
src/views/index.vue
Normal file
@@ -0,0 +1,659 @@
|
||||
<template>
|
||||
<div class="app-container home">
|
||||
|
||||
<!-- <el-divider /> -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="11">
|
||||
<el-card class="update-log" >
|
||||
<template v-slot:header>
|
||||
<div class="titleBox">
|
||||
<div class="line"></div>
|
||||
<div class="name">
|
||||
<div>配送订单总览</div>
|
||||
<el-date-picker
|
||||
v-model="dateInventoryTypeObj"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="margin: 0 20px;"
|
||||
/>
|
||||
<el-button type="primary" size="small" @click="getTotalOverview">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="body" id="orderOverview">
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="13">
|
||||
<el-card class="update-log" >
|
||||
<template v-slot:header>
|
||||
<div class="titleBox">
|
||||
<div class="line"></div>
|
||||
<div class="name">
|
||||
<div>配送费统计</div>
|
||||
<el-date-picker
|
||||
v-model="twoTimeArr"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="margin: 0 20px;"
|
||||
/>
|
||||
<el-button type="primary" size="small" @click="getFee">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="body" id="orderFee">
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row :gutter="20" style="margin-top: 20px;">
|
||||
|
||||
<el-col :span="13">
|
||||
<el-card class="update-log" >
|
||||
<template v-slot:header>
|
||||
<div class="titleBox">
|
||||
<div class="line"></div>
|
||||
<div class="name">
|
||||
<div>每日订单统计</div>
|
||||
<!-- <el-date-picker
|
||||
v-model="dateInventoryTypeObj"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="margin: 0 20px;"
|
||||
/> -->
|
||||
<el-select v-model="monthValue" placeholder="选择月份" style="width: 200px;margin: 0 20px;">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<el-button type="primary" size="small" @click="getDayOrder('search')">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="body" id="everyDayCount">
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="11" >
|
||||
<el-card class="update-log" >
|
||||
<template v-slot:header>
|
||||
<div class="titleBox">
|
||||
<div class="line"></div>
|
||||
<div class="name">
|
||||
<div>各类车型配送统计</div>
|
||||
<el-date-picker
|
||||
v-model="threeTimeArr"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="margin: 0 20px;"
|
||||
/>
|
||||
<el-button type="primary" size="small" @click="getOrderCarType">搜索</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="body" id="orderCarType">
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- @click="goAi" -->
|
||||
<div class="imgBox" ref="iconRef" @mousedown="startDrag" :style="{
|
||||
left: position.x ? position.x + 'px' :'',
|
||||
top: position.y + 'px'
|
||||
}" >
|
||||
<img src="@/assets/images/rgzn.png" style="width: 100%;height: 100%;" @click="goAi" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Index">
|
||||
import * as echarts from 'echarts';
|
||||
import {getOrderStatus,getDeliveryFee,getOrderCar,everyDayOrder} from "@/api/index/index";
|
||||
const version = ref('3.9.0')
|
||||
import { parseTime } from '@/utils/ruoyi'
|
||||
// import { getTime } from '@/utils/index'
|
||||
import { get } from '@vueuse/core';
|
||||
// let statDate = parseTime(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000), '{y}-{m}-{d}') // 14天前
|
||||
// let endDate = parseTime(new Date(), '{y}-{m}-{d}') // 当前时间
|
||||
|
||||
let currentDate = new Date();
|
||||
let currentYear = currentDate.getFullYear();
|
||||
let monthVal = currentDate.getMonth() + 1;
|
||||
let statDate = parseTime(new Date(currentYear,monthVal-1,1), '{y}-{m}-{d}')
|
||||
let endDate = parseTime(new Date(currentYear,monthVal,0), '{y}-{m}-{d}')
|
||||
|
||||
|
||||
// let statDate = parseTime(getTime('start'))
|
||||
// let endDate = parseTime(getTime(''))
|
||||
const dateInventoryTypeObj = ref([statDate,endDate]) //第一个接口时间参数
|
||||
const twoTimeArr = ref([statDate,endDate]) //第二个接口时间参数
|
||||
const threeTimeArr = ref([statDate,endDate]) //第三个接口、各类车型 时间参数
|
||||
const fourTimeArr = ref([statDate,endDate]) //第四个接口、每日订单时间参数
|
||||
const { proxy } = getCurrentInstance()
|
||||
const options = [
|
||||
{ value: '01', label: '1月' },
|
||||
{ value: '02', label: '2月' },
|
||||
{ value: '03', label: '3月' },
|
||||
{ value: '04', label: '4月' },
|
||||
{ value: '05', label: '5月' },
|
||||
{ value: '06', label: '6月' },
|
||||
{ value: '07', label: '7月' },
|
||||
{ value: '08', label: '8月' },
|
||||
{ value: '09', label: '9月' },
|
||||
{ value: '10', label: '10月' },
|
||||
{ value: '11', label: '11月' },
|
||||
{ value: '12', label: '12月' }
|
||||
]
|
||||
const monthValue = ref('')
|
||||
onMounted(() => {
|
||||
getTotalOverview()
|
||||
getFee()
|
||||
getOrderCarType()
|
||||
getDayOrder('') //每日订单统计
|
||||
});
|
||||
//第一个接口,订单总览
|
||||
function getTotalOverview(){
|
||||
|
||||
const dataArr = {
|
||||
statDate: dateInventoryTypeObj.value[0],
|
||||
endDate: dateInventoryTypeObj.value[1]
|
||||
}
|
||||
getOrderStatus(dataArr).then(Response => {
|
||||
const dataInfo = Response.data
|
||||
const data = [
|
||||
{name:'已完成',value:dataInfo.signedCount},
|
||||
{name:'配送中',value:dataInfo.deliveringCount},
|
||||
{name:'待配送',value:dataInfo.waitCount},
|
||||
]
|
||||
getChart(data)
|
||||
// console.log(Response)
|
||||
})
|
||||
}
|
||||
//第二个接口,各月配送费用
|
||||
function getFee(){
|
||||
const dataArr = {
|
||||
statDate: twoTimeArr.value[0],
|
||||
endDate: twoTimeArr.value[1]
|
||||
}
|
||||
getDeliveryFee(dataArr).then(Response => {
|
||||
// console.log(Response)
|
||||
getFeeChart(Response.data)
|
||||
})
|
||||
}
|
||||
//第三个接口,各类车型订单数
|
||||
function getOrderCarType(){
|
||||
const dataArr = {
|
||||
statDate: threeTimeArr.value[0],
|
||||
endDate: threeTimeArr.value[1]
|
||||
}
|
||||
getOrderCar(dataArr).then(Response => {
|
||||
const dataInfo = Response.data
|
||||
getCarTypeChart(dataInfo)
|
||||
// const data = [
|
||||
// {name:'小车',value:dataInfo.smallCarCount},
|
||||
// {name:'中车',value:dataInfo.middleCarCount},
|
||||
// ]
|
||||
})
|
||||
}
|
||||
//第四个接口,每日订单数
|
||||
function getDayOrder(isSearch){
|
||||
|
||||
// monthValue.value = monthVal+'' //下拉框显示
|
||||
|
||||
if(isSearch == 'search'){
|
||||
if(monthValue.value == ''){
|
||||
proxy.$modal.msgError("请选择月份");
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// console.log(currentYear)
|
||||
fourTimeArr.value[0] = parseTime(new Date(currentYear,monthValue.value-1,1), '{y}-{m}-{d}')
|
||||
fourTimeArr.value[1] = parseTime(new Date(currentYear,monthValue.value,0), '{y}-{m}-{d}')
|
||||
|
||||
}
|
||||
else{
|
||||
monthValue.value = monthVal+''
|
||||
}
|
||||
// console.log(11111)
|
||||
// console.log(dateInventoryTypeObj.vlaue[0])
|
||||
const dataArr = {
|
||||
statDate: fourTimeArr.value[0],
|
||||
endDate: fourTimeArr.value[1]
|
||||
}
|
||||
// console.log(dataArr)
|
||||
everyDayOrder(dataArr).then(Response => {
|
||||
const dataInfo = Response.data
|
||||
getEveryDayChart(dataInfo)
|
||||
})
|
||||
}
|
||||
//第一个图表
|
||||
function getChart(data) {
|
||||
let chartDom = document.getElementById('orderOverview');
|
||||
let myChart = echarts.init(chartDom, null, {
|
||||
// width: 600, // 宽度
|
||||
height: 300 // 高度
|
||||
});
|
||||
// console.log(data)
|
||||
myChart.setOption({
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'pie',
|
||||
radius: '50%',
|
||||
data: data,
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
//第二个图表,各月配送费用
|
||||
function getFeeChart(dataInfo){
|
||||
// dataInfo = [
|
||||
// {statMonth:'2025-01',totalActualFee:1000},
|
||||
// {statMonth:'2025-02',totalActualFee:1221},
|
||||
// {statMonth:'2025-03',totalActualFee:1543},
|
||||
// {statMonth:'2025-04',totalActualFee:2000},
|
||||
// {statMonth:'2025-05',totalActualFee:699},
|
||||
// {statMonth:'2025-06',totalActualFee:4000},
|
||||
// {statMonth:'2025-07',totalActualFee:6000},
|
||||
// {statMonth:'2025-08',totalActualFee:5000},
|
||||
// {statMonth:'2025-09',totalActualFee:3000},
|
||||
// {statMonth:'2025-10',totalActualFee:2000},
|
||||
// {statMonth:'2025-11',totalActualFee:1288},
|
||||
// {statMonth:'2025-12',totalActualFee:1000},
|
||||
// ]
|
||||
var chartDom = document.getElementById('orderFee');
|
||||
var myChart = echarts.init(chartDom, null, {
|
||||
// width: 600, // 宽度
|
||||
height: 300 // 高度
|
||||
});
|
||||
var option;
|
||||
let xAxisData = []
|
||||
let seriesData = []
|
||||
if(dataInfo.length > 0){
|
||||
dataInfo.forEach(item => {
|
||||
xAxisData.push(item.statMonth)
|
||||
seriesData.push(item.totalActualFee)
|
||||
})
|
||||
}
|
||||
option = {
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
axisLabel: {
|
||||
rotate: 30,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: seriesData,
|
||||
type: 'line',
|
||||
label: {
|
||||
show: true, // 显示数值
|
||||
position: 'top', // 数值显示的位置,可以是'top', 'bottom', 'left', 'right'等
|
||||
formatter: '{c}',
|
||||
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
option && myChart.setOption(option);
|
||||
}
|
||||
//第三个图表,各类车型订单数
|
||||
function getCarTypeChart(dataInfo){
|
||||
let xAxisData = [] //车型
|
||||
let totalOrder = [] //订单数
|
||||
let totalActualFee = [] //总费用
|
||||
let totalKm = [] //总里程
|
||||
if(dataInfo.length > 0){
|
||||
dataInfo.forEach(item => {
|
||||
xAxisData.push(item.vehicleTypeName)
|
||||
totalOrder.push(item.orderCount)
|
||||
totalActualFee.push(item.totalActualFee)
|
||||
totalKm.push(item.totalKm)
|
||||
})
|
||||
}
|
||||
|
||||
var chartDom = document.getElementById('orderCarType');
|
||||
var myChart = echarts.init(chartDom, null, {
|
||||
// width: 600, // 宽度
|
||||
height: 300 // 高度
|
||||
});
|
||||
myChart.setOption({
|
||||
// title: {
|
||||
// text: 'World Population'
|
||||
// },
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
// bottom: '8%',
|
||||
},
|
||||
legend: {},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01]
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
axisLabel: {
|
||||
rotate: 30,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '订单数',
|
||||
type: 'bar',
|
||||
data: totalOrder
|
||||
},
|
||||
{
|
||||
name: '总费用',
|
||||
type: 'bar',
|
||||
data: totalActualFee
|
||||
},
|
||||
{
|
||||
name: '公里数',
|
||||
type: 'bar',
|
||||
data: totalKm
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
//第四个图表,每日订单数
|
||||
function getEveryDayChart(dataInfo){
|
||||
// let xAxisData = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31] //日期
|
||||
// let totalOrder = [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10] //订单数
|
||||
// let totalActualFee = [20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20] //总费用
|
||||
// let totalKm = [30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30] //总里程
|
||||
let xAxisData = [] //日期
|
||||
let totalOrder = [] //订单数
|
||||
let totalActualFee = [] //总费用
|
||||
let totalKm = [] //总里程
|
||||
if(dataInfo.length > 0){
|
||||
dataInfo.forEach(item => {
|
||||
xAxisData.push(item.statDate)
|
||||
totalOrder.push(item.orderCount)
|
||||
totalActualFee.push(item.totalActualFee)
|
||||
totalKm.push(item.totalKm)
|
||||
})
|
||||
}
|
||||
|
||||
var chartDom = document.getElementById('everyDayCount');
|
||||
var myChart = echarts.init(chartDom, null, {
|
||||
// width: 600, // 宽度
|
||||
height: 300 // 高度
|
||||
});
|
||||
myChart.setOption({
|
||||
// title: {
|
||||
// text: 'World Population'
|
||||
// },
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
// bottom: '8%',
|
||||
},
|
||||
legend: {},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
boundaryGap: [0, 0.01]
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xAxisData,
|
||||
axisLabel: {
|
||||
// rotate: 50,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '订单数',
|
||||
type: 'bar',
|
||||
data: totalOrder
|
||||
},
|
||||
{
|
||||
name: '总费用',
|
||||
type: 'bar',
|
||||
data: totalActualFee
|
||||
},
|
||||
{
|
||||
name: '公里数',
|
||||
type: 'bar',
|
||||
data: totalKm
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
function goTarget(url) {
|
||||
window.open(url, '__blank')
|
||||
}
|
||||
|
||||
// 图标元素引用
|
||||
const iconRef = ref(null)
|
||||
|
||||
// 图标当前位置
|
||||
const position = reactive({ x: 0, y: 300 })
|
||||
|
||||
// 拖拽状态
|
||||
let isDragging = false
|
||||
let offsetX = 0
|
||||
let offsetY = 0
|
||||
let isMove
|
||||
// 获取边界限制
|
||||
function getBoundaries() {
|
||||
if (!iconRef.value) return { minX: 0, maxX: 0, minY: 0, maxY: 0 }
|
||||
const rect = iconRef.value.getBoundingClientRect()
|
||||
const width = rect.width
|
||||
const height = rect.height
|
||||
|
||||
// 浏览器视口尺寸
|
||||
const viewportWidth = window.innerWidth
|
||||
const viewportHeight = window.innerHeight
|
||||
|
||||
return {
|
||||
minX: 0,
|
||||
maxX: viewportWidth - width, // 最大 left 值
|
||||
minY: 0,
|
||||
maxY: viewportHeight - height // 最大 top 值
|
||||
}
|
||||
}
|
||||
// 开始拖拽
|
||||
function startDrag(e) {
|
||||
// console.log(1111)
|
||||
if (!iconRef.value) return
|
||||
isDragging = true
|
||||
isMove = false
|
||||
const rect = iconRef.value.getBoundingClientRect()
|
||||
offsetX = e.clientX - rect.left
|
||||
offsetY = e.clientY - rect.top
|
||||
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
// 全局鼠标移动监听
|
||||
function handleMouseMove(e) {
|
||||
if (!isDragging || !iconRef.value) return
|
||||
isMove = true
|
||||
const boundaries = getBoundaries()
|
||||
let newX = e.clientX - offsetX
|
||||
let newY = e.clientY - offsetY
|
||||
|
||||
// 限制在视口内
|
||||
// console.log(boundaries.minX+'--'+)
|
||||
newX = Math.max(boundaries.minX, Math.min(newX, boundaries.maxX))
|
||||
newY = Math.max(boundaries.minY, Math.min(newY, boundaries.maxY))
|
||||
|
||||
position.x = newX
|
||||
position.y = newY
|
||||
}
|
||||
|
||||
// 停止拖拽
|
||||
function handleMouseUp() {
|
||||
// console.log(2222)
|
||||
// if(!isMove && iconRef.value){
|
||||
// window.open('http://192.168.1.28:8000/#/chat/index', '_blank')
|
||||
// }
|
||||
isDragging = false
|
||||
}
|
||||
|
||||
// 绑定全局事件(组件挂载时)
|
||||
window.addEventListener('mousemove', handleMouseMove)
|
||||
window.addEventListener('mouseup', handleMouseUp)
|
||||
|
||||
// 可选:组件卸载时清理(防止内存泄漏)
|
||||
// 在 Vue 3 中,如果使用 <script setup>,可以用 onBeforeUnmount
|
||||
import { onBeforeUnmount } from 'vue'
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('mousemove', handleMouseMove)
|
||||
window.removeEventListener('mouseup', handleMouseUp)
|
||||
})
|
||||
|
||||
function goAi(){
|
||||
// console.log(33333)
|
||||
// setTimeout(() => {
|
||||
if(!isMove){
|
||||
window.open('http://192.168.1.28:8000/#/chat/index', '_blank')
|
||||
}
|
||||
// }, 200);
|
||||
// window.open('http://192.168.1.28:8000/#/chat/index', '_blank')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.home {
|
||||
blockquote {
|
||||
padding: 10px 20px;
|
||||
margin: 0 0 20px;
|
||||
font-size: 17.5px;
|
||||
border-left: 5px solid #eee;
|
||||
}
|
||||
hr {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
border: 0;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.col-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-size: 13px;
|
||||
color: #676a6c;
|
||||
overflow-x: hidden;
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
font-size: 26px;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
|
||||
b {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.update-log {
|
||||
ol {
|
||||
display: block;
|
||||
list-style-type: decimal;
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
padding-inline-start: 40px;
|
||||
}
|
||||
}
|
||||
.titleBox{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.line {
|
||||
width: 6px;
|
||||
height: 15px;
|
||||
background: #199793;
|
||||
border-radius: 12px 12px 12px 12px;
|
||||
transform: rotateX(360deg);
|
||||
}
|
||||
.name{
|
||||
margin-left: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 28px;
|
||||
font-family: PingFang SC, PingFang SC;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
color: #333333;
|
||||
line-height: 23px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
.imgBox{
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position:fixed;
|
||||
right: 0;
|
||||
// top: 50%;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user