修改后台

This commit is contained in:
zpc 2024-12-09 01:49:30 +08:00
parent f3a9acb0ca
commit 6811afe714
17 changed files with 351 additions and 147 deletions

View File

@ -1,2 +1,5 @@
VUE_APP_BASE=/ #打包路径 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。你可以在应用的代码中这样访问它们
VITE_API_URL=https://steamcloud.shhuanmeng.com
# VITE_API_URL=https://steamcloud.shhuanmeng.com
VITE_API_URL=http://192.168.1.23:91
VITE_EXTAPI_URL=http://192.168.1.23:83

View File

@ -1,4 +1,5 @@
VUE_APP_BASE=/ #打包路径
VITE_API_URL=http://127.0.0.1:802
# VITE_API_URL=http://192.168.1.23:91
VITE_EXTAPI_URL=http://192.168.1.23:83
# VITE_API_URL=https://steamcloud.shhuanmeng.com

View File

@ -57,31 +57,29 @@ function jumpPro() {
<template>
<a-layout-header class="hzy-layout-header">
<div class="hzy-header-btn" @click="menuStore.onChangeCollapse(!menuStore.state.isCollapse)">
<div
class="hzy-header-btn"
@click="menuStore.onChangeCollapse(!menuStore.state.isCollapse)"
>
<!-- <a-tooltip>
<template #title>菜单收展</template>
<AppIcon :name="menuStore.state.isCollapse ? 'MenuUnfoldOutlined' : 'MenuFoldOutlined'" :size="iconSize" />
</a-tooltip> -->
<AppIcon :name="menuStore.state.isCollapse ? 'MenuUnfoldOutlined' : 'MenuFoldOutlined'" :size="iconSize" />
<AppIcon
:name="
menuStore.state.isCollapse ? 'MenuUnfoldOutlined' : 'MenuFoldOutlined'
"
:size="iconSize"
/>
</div>
<div style="flex: 1 1 0%; height: 100%; display: flex" v-if="menuStore.state.menuMode == EMenuMode.top">
<div
style="flex: 1 1 0%; height: 100%; display: flex"
v-if="menuStore.state.menuMode == EMenuMode.top"
>
<LayoutOneLevelMenu />
</div>
<div style="flex: 1 1 0%" v-else></div>
<!-- Pro -->
<div class="hzy-header-btn text-danger" @click="jumpPro()" style="font-weight: bold"
v-if="!coreStore.state.isMobile">
Pro By React</div>
<!-- HzyAdmin 文档 -->
<a-tooltip>
<template #title>HzyAdmin 文档</template>
<div class="hzy-header-btn" @click="jumpDoc" v-if="!coreStore.state.isMobile">
<a-badge status="success" dot>
<AppIcon name="rocket-outlined" :size="iconSize" />
</a-badge>
</div>
</a-tooltip>
<!-- 刷新当前选项卡 -->
<a-tooltip>
<template #title>刷新当前选项卡</template>
@ -93,16 +91,31 @@ function jumpPro() {
<!-- 全屏 -->
<a-tooltip>
<template #title>全屏</template>
<div class="hzy-header-btn" @click="toggle" v-if="!coreStore.state.isMobile">
<AppIcon :name="isFullscreen ? 'FullscreenExitOutlined' : 'FullscreenOutlined'" :size="iconSize" />
<div
class="hzy-header-btn"
@click="toggle"
v-if="!coreStore.state.isMobile"
>
<AppIcon
:name="isFullscreen ? 'FullscreenExitOutlined' : 'FullscreenOutlined'"
:size="iconSize"
/>
</div>
</a-tooltip>
<!-- 白昼 / 黑夜 -->
<a-tooltip>
<template #title>白昼 / 黑夜</template>
<div class="hzy-header-btn" @click="themeStore.changeTheme(!themeStore.state.isDark)">
<AppIcon name="MoonNight" :size="iconSize + 5" style="color:white" v-if="themeStore.state.isDark" />
<div
class="hzy-header-btn"
@click="themeStore.changeTheme(!themeStore.state.isDark)"
>
<AppIcon
name="MoonNight"
:size="iconSize + 5"
style="color: white"
v-if="themeStore.state.isDark"
/>
<AppIcon name="Sunny" :size="iconSize + 5" v-else />
</div>
</a-tooltip>
@ -118,7 +131,11 @@ function jumpPro() {
<div class="hzy-header-btn">
<AppIcon name="UserOutlined" :size="iconSize" />
&nbsp;&nbsp;
<span>{{ appStore.state.userInfo.name ? appStore.state.userInfo.name : "未知用户" }}</span>
<span>{{
appStore.state.userInfo.name
? appStore.state.userInfo.name
: "未知用户"
}}</span>
</div>
<template #overlay>
<a-menu>
@ -143,7 +160,6 @@ function jumpPro() {
<style lang="less">
.hzy-layout {
//
.ant-layout-header {
position: relative;

View File

@ -29,5 +29,12 @@ export default class AppMonitorService {
static GetActiveUserCount() {
return Http.get(`${this.urlPrefix}/GetActiveUserCount`, {}, false)
}
/**
*
* @returns
*/
static GetAppMonitorHour() {
return Http.get(`${this.urlPrefix}/GetAppMonitorHour`, {}, false)
}
}

View File

@ -194,7 +194,7 @@ function exportExcel() {
<a-row :gutter="[16, 0]">
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item
label="系统标识"
label="系统标识"
name="tenantId"
:rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
>
@ -211,7 +211,11 @@ function exportExcel() {
name="name"
:rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
>
<a-input v-model:value="state.vm.form.name" :readonly="readonly" placeholder="请输入" />
<a-input
v-model:value="state.vm.form.name"
:readonly="readonly"
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
@ -240,6 +244,33 @@ function exportExcel() {
/>
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item
label="隐私协议地址"
name="privacyAgreement"
:readonly="readonly"
>
<a-input
v-model:value="state.vm.form.privacyAgreement"
:readonly="readonly"
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item
label="用户协议地址"
name="userAgreement"
:readonly="readonly"
>
<a-input
v-model:value="state.vm.form.userAgreement"
:readonly="readonly"
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item
label="app版本"
@ -254,7 +285,6 @@ function exportExcel() {
/>
</a-form-item>
</a-col>
<a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<a-form-item
label="缓存数据"
@ -325,9 +355,12 @@ function exportExcel() {
</a-row>
</a-form>
<a-space :size="15">
<a-button type="primary" v-if="power.update" @click="readonly = !readonly">{{
readonly ? "修改" : "取消修改"
}}</a-button>
<a-button
type="primary"
v-if="power.update"
@click="readonly = !readonly"
>{{ readonly ? "修改" : "取消修改" }}</a-button
>
<a-button
type="primary"
:loading="state.loading"

View File

@ -15,7 +15,7 @@ defineOptions({ name: "t_User_Phone_AccountIndex" });
{
dataIndex: "userId",
title: "用户Id",
show: false,
show: true,
width: 80,
sorter: true,
},
@ -23,7 +23,7 @@ defineOptions({ name: "t_User_Phone_AccountIndex" });
{
dataIndex: "phoneNum",
title: "手机号",
show: false,
show: true,
width: 60,
sorter: true,
},
@ -31,7 +31,7 @@ defineOptions({ name: "t_User_Phone_AccountIndex" });
{
dataIndex: "createdAt",
title: "修改时间",
show: false,
show: true,
width: 80,
sorter: true,
},
@ -39,7 +39,7 @@ defineOptions({ name: "t_User_Phone_AccountIndex" });
{
dataIndex: "updatedAt",
title: "创建时间",
show: false,
show: true,
width: 80,
sorter: true,
},
@ -47,7 +47,7 @@ defineOptions({ name: "t_User_Phone_AccountIndex" });
{
dataIndex: "nikeName",
title: "用户昵称",
show: false,
show: true,
width: 80,
sorter: true,
},
@ -55,7 +55,7 @@ defineOptions({ name: "t_User_Phone_AccountIndex" });
{
dataIndex: "isLogout",
title: "是否注销",
show: false,
show: true,
width: 80,
sorter: true,
},
@ -64,6 +64,8 @@ const state = reactive({
search: {
state: true,
vm: {
phonenum: undefined,
userid: undefined,
},
sort: [] as any[],
},
@ -169,6 +171,16 @@ function exportExcel() {
<template #search>
<a-form ref="refSearchForm" :model="state.search.vm" v-if="power.search">
<a-row :gutter="[16, 0]">
<a-col :xs="4" :sm="4" :md="4" :lg="4" :xl="4">
<a-form-item class="mb-0" name="name" label="手机号">
<a-input v-model:value="state.search.vm.phonenum" placeholder="手机号" />
</a-form-item>
</a-col>
<a-col :xs="4" :sm="4" :md="4" :lg="4" :xl="4">
<a-form-item class="mb-0" name="name" label="用户Id">
<a-input v-model:value="state.search.vm.userid" placeholder="用户Id" />
</a-form-item>
</a-col>
<!--button-->
<a-col :xs="2" :sm="2" :md="2" :lg="2" :xl="2" class="text-right">

View File

@ -1,22 +1,28 @@
<script lang="ts" setup>
import {ref} from "vue";
import { ref } from "vue";
import WorkOrder from "./components/WorkOrder.vue";
import WorkOrderStatistics from "./components/WorkOrderStatistics.vue";
import UserSignStatistics from "./components/UserSignStatistics.vue";
import PlayGameTimeStatistics from "./components/PlayGameTimeStatistics.vue";
import HomeChart1 from "./components/HomeChart1.vue";
import HomeChart2 from "./components/HomeChart2.vue";
import HomeChart3 from "./components/HomeChart3.vue";
import PlayGameStatistics from "./components/PlayGameStatistics.vue";
import Home1 from "./Index1.vue";
import image1 from "@/assets/images/img1.png";
import image2 from "@/assets/images/img2.png";
import image3 from "@/assets/images/img3.png";
import PageContainer from "@/core/components/PageContainer.vue";
defineOptions({name: "HomeIndexCom"});
import AppMonitorService from "@/services/Apps/Ext/AppMonitorService";
defineOptions({ name: "HomeIndexCom" });
let login = ref([]);
let registr = ref([]);
let playTimeGame = ref([]);
let playGame = ref([]);
AppMonitorService.GetAppMonitorHour().then((data) => {
// console.log(data);
login.value.splice(0, login.value.length);
login.value = data.login;
registr.value = data.registr;
playTimeGame.value = data.playTimeGame;
playGame.value = data.playGame;
// console.log(login.value);
});
let visible = ref(false);
</script>
@ -24,27 +30,37 @@ let visible = ref(false);
<PageContainer :show="false" class="p-16">
<!-- 基础统计数据 -->
<div @click="visible = !visible">
<WorkOrder/>
<WorkOrder />
</div>
<!-- 近一年设备销售量 -->
<div class="mt-16">
<a-row :gutter="[16, 16]">
<a-col :xs="24" :sm="24" :md="12" :lg="16" :xl="12">
<WorkOrderStatistics/>
<WorkOrderStatistics
:data="login"
v-if="login != null && login.length > 0"
/>
</a-col>
<a-col :xs="24" :sm="24" :md="12" :lg="16" :xl="12">
<UserSignStatistics />
<UserSignStatistics
:data="registr"
v-if="registr != null && registr.length > 0"
/>
</a-col>
<a-col :xs="24" :sm="24" :md="12" :lg="16" :xl="12">
<PlayGameTimeStatistics />
<PlayGameStatistics :data="playGame" />
</a-col>
<a-col :xs="24" :sm="24" :md="12" :lg="16" :xl="12">
<PlayGameTimeStatistics :data="playTimeGame" />
</a-col>
</a-row>
<!-- PlayGameTimeStatistics -->
</div>
<!-- 抽屉 -->
<a-drawer v-model:open="visible" title="更多" placement="right" width="90%">
<Home1/>
<Home1 />
</a-drawer>
</PageContainer>
</template>

View File

@ -0,0 +1,72 @@
<script lang="ts" setup>
import { onMounted, ref, onBeforeUnmount } from "vue";
import { Line } from "@antv/g2plot";
let line = null;
const props = withDefaults(
defineProps<{
data: any;
}>(),
{}
);
watch(
() => props.data,
(newValue) => {
console.log("23213123linelinelineline");
if (props.data != null && props.data.length > 0) {
var tempData = [];
for (let index = 0; index < props.data.length; index++) {
const element = props.data[index];
tempData.push(Object.assign({}, element));
}
line.changeData(tempData);
console.log(tempData);
}
}
);
let data = [];
onMounted(() => {
document.getElementById("PlayGameContainer")!.innerHTML = "";
line = new Line("PlayGameContainer", {
data,
xField: "timeStamp",
yField: "value",
seriesField: "category",
yAxis: {
label: {
//
formatter: (v) =>
`${v}`.replace(/\d{1,3}(?=(\d{3})+$)/g, (s) => `${s},`),
},
},
color: ["#1979C9", "#D62A0D", "#FAA219"],
});
line.render();
});
</script>
<template>
<a-card
title="近24小时玩游戏人数统计"
:bordered="false"
:headStyle="{ 'border-bottom': 0 }"
>
<template #extra>
<a
href="https://g2plot.antv.vision/zh/docs/manual/getting-started"
target="_black"
>更多数据</a
>
</template>
<div id="PlayGameContainer"></div>
</a-card>
</template>
<style lang="less">
.work-order {
.icon-size {
font-size: 70px;
}
}
</style>

View File

@ -1,34 +1,43 @@
<script lang="ts" setup>
import { onMounted, ref, onBeforeUnmount } from "vue";
import { Line } from "@antv/g2plot";
let line = null;
const props = withDefaults(
defineProps<{
data: any;
}>(),
{}
);
watch(
() => props.data,
(newValue) => {
console.log("23213123linelinelineline");
if (props.data != null && props.data.length > 0) {
// data.splice(0, data.length);
// data = props.data;
var tempData = [];
for (let index = 0; index < props.data.length; index++) {
const element = props.data[index];
tempData.push(Object.assign({}, element));
}
line.changeData(tempData);
console.log(tempData);
}
}
);
//
let data = [];
for (let i = 0; i < 30; i++) {
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 400),
category: "总数",
});
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 200),
category: "华为渠道",
});
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 200),
category: "小米渠道",
});
}
let timer = ref();
onMounted(() => {
document.getElementById("PlayGameTimeContainer")!.innerHTML = "";
const line = new Line("PlayGameTimeContainer", {
line = new Line("PlayGameTimeContainer", {
data,
xField: "type",
yField: "sales",
xField: "timeStamp",
yField: "value",
seriesField: "category",
yAxis: {
label: {
@ -46,7 +55,7 @@ onMounted(() => {
<template>
<a-card
title="近一月玩游戏时长统计"
title="近24小时玩游戏时长统计"
:bordered="false"
:headStyle="{ 'border-bottom': 0 }"
>

View File

@ -1,34 +1,53 @@
<script lang="ts" setup>
import { onMounted, ref, onBeforeUnmount } from "vue";
import { Line } from "@antv/g2plot";
//
let data = [];
for (let i = 0; i < 30; i++) {
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 400),
category: "总数",
});
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 200),
category: "华为渠道",
});
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 200),
category: "小米渠道",
});
}
import {
onMounted,
ref,
onBeforeUnmount,
defineProps,
defineEmits,
watch,
} from "vue";
import { Column, Line } from "@antv/g2plot";
let timer = ref();
let data = [];
const props = withDefaults(
defineProps<{
data: any;
}>(),
{}
);
if (props.data != null && props.data.length > 0) {
data = props.data;
}
watch(
() => props.data,
(newValue) => {
if (props.data != null && props.data.length > 0) {
// data.splice(0, data.length);
// data = props.data;
for (let index = 0; index < props.data.length; index++) {
const element = props.data[index];
data[index].value = element.value;
// data[index].timeStamp = element.timeStamp;
data[index].category = element.category;
}
// console.log(data);
}
}
);
onMounted(() => {
console.log("aaaa");
document.getElementById("UserSignStatisticsContainer")!.innerHTML = "";
// console.log(data);
const line = new Line("UserSignStatisticsContainer", {
data,
xField: "type",
yField: "sales",
xField: "timeStamp",
yField: "value",
seriesField: "category",
yAxis: {
label: {
@ -46,7 +65,7 @@ onMounted(() => {
<template>
<a-card
title="近一月注册人数统计"
title="近24小时注册人数统计"
:bordered="false"
:headStyle="{ 'border-bottom': 0 }"
>

View File

@ -64,7 +64,7 @@ const cards = ref<CardData[]>([
},
{
title: "今日充值金额",
unit: "",
unit: "",
value: 5,
icon: "AccountBookOutlined",
color: "#FF6347",
@ -97,7 +97,7 @@ const updateValues = async () => {
}
};
timer.value = setInterval(updateValues, 2000);
timer.value = setInterval(updateValues, 10000);
onBeforeUnmount(() => {
if (timer.value) {

View File

@ -1,35 +1,54 @@
<script lang="ts" setup>
import { onMounted, ref, onBeforeUnmount } from "vue";
import {
onMounted,
ref,
onBeforeUnmount,
defineProps,
defineEmits,
watch,
} from "vue";
import { Column, Line } from "@antv/g2plot";
let data = [];
for (let i = 0; i < 30; i++) {
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 400),
category: "总数",
});
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 200),
category: "华为渠道",
});
data.push({
type: i + 1 + "号",
sales: Math.floor(Math.random() * 200),
category: "小米渠道",
});
const props = withDefaults(
defineProps<{
data: any;
}>(),
{}
);
if (props.data != null && props.data.length > 0) {
data = props.data;
}
console.log(data);
watch(
() => props.data,
(newValue) => {
console.log("aaaaaaaaa23432");
let timer = ref();
if (props.data != null && props.data.length > 0) {
// data.splice(0, data.length);
// data = props.data;
for (let index = 0; index < props.data.length; index++) {
const element = props.data[index];
data[index].value = element.value;
// data[index].timeStamp = element.timeStamp;
data[index].category = element.category;
}
// console.log(data);
}
}
);
onMounted(() => {
console.log("aaaa");
document.getElementById("WorkOrderStatisticsContainer")!.innerHTML = "";
// console.log(data);
const line = new Line("WorkOrderStatisticsContainer", {
data,
xField: "type",
yField: "sales",
xField: "timeStamp",
yField: "value",
seriesField: "category",
yAxis: {
label: {
@ -47,7 +66,7 @@ onMounted(() => {
<template>
<a-card
title="近一月活跃人数统计"
title="24小时登录人数统计"
:bordered="false"
:headStyle="{ 'border-bottom': 0 }"
>

View File

@ -17,6 +17,12 @@ public class T_User_Phone_AccountService(IServiceProvider serviceProvider)
public async override Task<PagingView> FindListAsync(PagingSearchInput<T_User_Phone_Account> pagingSearchInput)
{
var query = this.Repository.Select
//手机号
.WhereIf(!string.IsNullOrWhiteSpace(pagingSearchInput.Search?.PhoneNum),
w => w.PhoneNum.Contains(pagingSearchInput.Search.PhoneNum ?? ""))
//用户Id
.WhereIf(pagingSearchInput.Search?.UserId!=null&&pagingSearchInput.Search?.UserId>0,
w => w.UserId== pagingSearchInput.Search.UserId)
.OrderByDescending(w => w.Id)
.Select(w => new
{
@ -31,8 +37,8 @@ public class T_User_Phone_AccountService(IServiceProvider serviceProvider)
//result.GetColumn(query, w => w. !).SetColumn<SysUser>(w => w.Name!);
result
.FormatValue(query, w => w.CreatedAt, (oldValue) => oldValue.ToString("yyyy-MM-dd"))
.FormatValue(query, w => w.UpdatedAt, (oldValue) => oldValue.ToString("yyyy-MM-dd"))
.FormatValue(query, w => w.CreatedAt, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
.FormatValue(query, w => w.UpdatedAt, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
;
return result;

View File

@ -94,7 +94,7 @@ public class @(className)Service(IServiceProvider serviceProvider)
result
@foreach (var x in dateList)
{
<pre>.FormatValue(query, w => w.@(x.ColumnName), (oldValue) => oldValue?.ToString("yyyy-MM-dd"))</pre>
<pre>.FormatValue(query, w => w.@(x.ColumnName), (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))</pre>
}
;
</pre>

View File

@ -94,7 +94,7 @@ public class @(className)Service(IServiceProvider serviceProvider)
result
@foreach (var x in dateList)
{
<pre>.FormatValue(query, w => w.@(x.ColumnName), (oldValue) => oldValue?.ToString("yyyy-MM-dd"))</pre>
<pre>.FormatValue(query, w => w.@(x.ColumnName), (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))</pre>
}
;
</pre>

View File

@ -93,8 +93,8 @@ public static class AppConfigExtend
appConfig.UserConfig = _appConfig.UserConfig;
appConfig.Payment = _appConfig.Payment;
appConfig.GameConfig = _appConfig.GameConfig;
appConfig.UserAgreement = _appConfig.UserAgreement;
appConfig.PrivacyAgreement = _appConfig.PrivacyAgreement;
}
/// <summary>

View File

@ -14,23 +14,14 @@ public static class CrossOriginConfig
// 跨域配置 配置跨域处理
webApplicationBuilder.Services.AddCors(options =>
{
options.AddPolicy("_myAllowSpecificOrigins",
builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
//options.AddDefaultPolicy(builder =>
//{
// builder
// .SetIsOriginAllowed(_ => true)
// .AllowAnyMethod()
// .AllowAnyHeader()
// .AllowCredentials();
//});
options.AddDefaultPolicy(builder =>
{
builder
.SetIsOriginAllowed(_ => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
}
@ -40,7 +31,7 @@ public static class CrossOriginConfig
public static void UseCrossOrigin(this WebApplication webApplication)
{
// 使用跨域 警告: 通过终结点路由CORS 中间件必须配置为在对UseRouting和UseEndpoints的调用之间执行。 配置不正确将导致中间件停止正常运行。
webApplication.UseCors("_myAllowSpecificOrigins");
webApplication.UseCors();
}
}