提交代码

This commit is contained in:
zpc 2024-12-04 14:22:48 +08:00
parent db78ab0a66
commit 6c7b5f2895
41 changed files with 1954 additions and 82 deletions

View File

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

View File

@ -1,11 +1,11 @@
{
"name": "hzy-admin",
"name": "cloudgaming-admin",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "hzy-admin",
"name": "cloudgaming-admin",
"version": "1.0.0",
"dependencies": {
"@antv/g2": "^5.1.5",
@ -45,6 +45,7 @@
"universal-cookie": "^7.2.1",
"unplugin-vue-macros": "^2.13.0",
"vite": "^5.4.9",
"vite-plugin-monaco-editor": "^1.1.0",
"vue": "^3.5.12",
"vue-i18n": "10.0.4",
"vue-router": "^4.4.5",
@ -10869,6 +10870,15 @@
}
}
},
"node_modules/vite-plugin-monaco-editor": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/vite-plugin-monaco-editor/-/vite-plugin-monaco-editor-1.1.0.tgz",
"integrity": "sha512-IvtUqZotrRoVqwT0PBBDIZPNraya3BxN/bfcNfnxZ5rkJiGcNtO5eAOWWSgT7zullIAEqQwxMU83yL9J5k7gww==",
"dev": true,
"peerDependencies": {
"monaco-editor": ">=0.33.0"
}
},
"node_modules/vite/node_modules/@esbuild/win32-x64": {
"version": "0.21.5",
"resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",

View File

@ -1,5 +1,5 @@
{
"name": "hzy-admin",
"name": "cloudgaming-admin",
"private": true,
"version": "1.0.0",
"type": "module",
@ -48,6 +48,7 @@
"universal-cookie": "^7.2.1",
"unplugin-vue-macros": "^2.13.0",
"vite": "^5.4.9",
"vite-plugin-monaco-editor": "^1.1.0",
"vue": "^3.5.12",
"vue-i18n": "10.0.4",
"vue-router": "^4.4.5",

View File

@ -82,6 +82,7 @@ declare module 'vue' {
BarChartTransverse: typeof import('./core/components/charts/BarChartTransverse.vue')['default']
ColumnSetting: typeof import('./core/components/curd/components/ColumnSetting.vue')['default']
ElAside: typeof import('element-plus/es')['ElAside']
ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
@ -129,6 +130,7 @@ declare module 'vue' {
LineChartMultiple: typeof import('./core/components/charts/LineChartMultiple.vue')['default']
LineChartSingle: typeof import('./core/components/charts/LineChartSingle.vue')['default']
MdEditorShowCode: typeof import('./core/components/MdEditorShowCode.vue')['default']
MonacoEditor: typeof import('./core/components/MonacoEditor.vue')['default']
PageContainer: typeof import('./core/components/PageContainer.vue')['default']
PageContainerGame: typeof import('./core/components/PageContainerGame.vue')['default']
PieChart: typeof import('./core/components/charts/PieChart.vue')['default']

View File

@ -0,0 +1,73 @@
<template>
<div class="monaco-editor" ref="editorContainer"></div>
</template>
<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
import * as monaco from "monaco-editor";
import "monaco-editor/min/vs/editor/editor.main.css";
const props = defineProps<{
modelValue: string;
language: string;
theme: string;
}>();
// const emit = defineEmits(["update:modelValue"]);
//
const emit = defineEmits(["update:modelValue"]);
const editorContainer = ref<HTMLElement | null>(null);
let editorInstance: monaco.editor.IStandaloneCodeEditor | null = null;
//
function initializeEditor(container: HTMLElement, value: string) {
const editor = monaco.editor.create(container, {
value,
language: props.language || "javascript",
theme: props.theme || "vs-dark",
automaticLayout: true,
wordWrap: "on",
minimap: {
enabled: false,
},
lineNumbers: "on",
});
//
editor.onDidChangeModelContent(() => {
const content = editor.getValue();
emit("update:modelValue", content);
});
return editor;
}
onMounted(() => {
if (editorContainer.value) {
editorInstance = initializeEditor(editorContainer.value, props.modelValue);
}
});
onBeforeUnmount(() => {
if (editorInstance) {
editorInstance.dispose();
}
});
// modelValue
watch(
() => props.modelValue,
(newValue) => {
if (editorInstance && editorInstance.getValue() !== newValue) {
editorInstance.setValue(newValue);
}
}
);
</script>
<style>
.monaco-editor {
width: 100%;
height: 100%;
}
</style>

View File

@ -1,7 +1,12 @@
<script lang="ts" setup>
import { onMounted, reactive, onBeforeUnmount, watch } from "vue";
import "@wangeditor/editor/dist/css/style.css";
import { createEditor, createToolbar, IDomEditor, Toolbar } from "@wangeditor/editor";
import {
createEditor,
createToolbar,
IDomEditor,
Toolbar,
} from "@wangeditor/editor";
interface IProps {
el: string;
@ -121,9 +126,16 @@ editorConfig.MENU_CONF["uploadImage"] = {
watch(
() => props.html,
(value) => {
// console.log("props.html", state.editor);
if (state.editor) {
state.editor.clear();
state.editor.dangerouslyInsertHtml(props.html);
if (state.editor.getHtml() != props.html) {
state.editor.clear();
state.editor.setHtml(props.html);
}
// state.editor.dangerouslyInsertHtml(props.html);
} else {
console.log("props.html111111111111111111111111111");
// setTimeout(() => state.editor.dangerouslyInsertHtml(props.html), 500);
}
}
);
@ -171,8 +183,14 @@ function destroy() {
<template>
<div style="z-index: 99; border: 1px solid #ccc">
<div :id="state.toolbarContainer" style="border-bottom: 1px solid #ccc"></div>
<div :id="state.editorContainer" :style="{ height: props.height + 'px' }"></div>
<div
:id="state.toolbarContainer"
style="border-bottom: 1px solid #ccc"
></div>
<div
:id="state.editorContainer"
:style="{ height: props.height + 'px' }"
></div>
</div>
</template>

View File

@ -32,7 +32,10 @@ class Http {
if (authorization) {
config!.headers![AppConsts.authorizationKeyName] = authorization;
}
var tenantId = Tools.getTenantId();
if (tenantId) {
config!.headers!["tenantId"] = tenantId;
}
config!.headers!["X-Requested-With"] = "XMLHttpRequest";
if (!config!.headers!["Content-Type"]) {
@ -86,7 +89,7 @@ class Http {
if (error.response.status === 401) {
if(!tokenTimeOut){
if (!tokenTimeOut) {
Tools.notice.warning("未授权!");
router.replace(AppConsts.loginPath);
return error;

View File

@ -336,6 +336,7 @@ class Tools {
return refreshToken;
}
/**
*
@ -350,6 +351,39 @@ class Tools {
return true;
}
/**
*
* @returns
*/
static getTenantId(): string {
const cookies = useCookies();
let token = cookies.get<string>("Authorization_TenantId");
if (!token) {
token = localStorage.getItem("Authorization_TenantId")!;
}
return token;
}
/**
*
* @param tokenValue
*/
static setTenantId(tokenValue: string): void {
const cookies = useCookies();
// console.log(cookies);
cookies.set("Authorization_TenantId", tokenValue, {
// domain: location.host,
path: "/",
// secure: true,
sameSite: "none",
});
localStorage.setItem("Authorization_TenantId", tokenValue);
}
/**
*
* @param fullPath

View File

@ -1,5 +1,5 @@
export default {
"login.title": "WelcomeHzyAdmin",
"login.title": "WelcomeCloudGamingAdmin",
"login.submit": "Login",
"login.validate.username": "Please enter a username",
"login.validate.userPassword": "Please enter the password",

View File

@ -1,5 +1,5 @@
export default {
"login.title": "欢迎使用HzyAdmin",
"login.title": "蒸汽云游后台管理",
"login.submit": "登录",
"login.validate.username": "请输入用户名",
"login.validate.userPassword": "请输入密码",

View File

@ -0,0 +1,33 @@
import Http from "@/core/utils/Http";
import AppConsts from "@/utils/AppConsts";
/**
* AppConfig服务
*/
export default class AppMonitorService {
static urlPrefix = AppConsts.domainExServerApi + "/api/Monitor";
/**
*
* @param current
* @param pageSize
* @param search
* @param searchSort
* @returns
*/
static GetAppMonitorInfo() {
return Http.get(`${this.urlPrefix}/GetAppMonitorInfo`, {}, false)
}
/**
*
* @param current
* @param pageSize
* @param search
* @param searchSort
* @returns
*/
static GetActiveUserCount() {
return Http.get(`${this.urlPrefix}/GetActiveUserCount`, {}, false)
}
}

View File

@ -0,0 +1,74 @@
import Http from "@/core/utils/Http";
/**
* T_App_Channel服务
*/
export default class T_App_ChannelService {
static urlPrefix = "/api/v1/admin/Game/T_App_Channel";
/**
*
* @param current
* @param pageSize
* @param search
* @param searchSort
* @returns
*/
static findList(current: number, pageSize: number, search: any = {}, searchSort: any[] = []) {
return Http.post(`${this.urlPrefix}/findList`, {
page: current,
size: pageSize,
search,
searchSort
})
}
/**
*
*
* @param ids
* @returns
*/
static deleteList(ids: string[]) {
return Http.post(`${this.urlPrefix}/deleteList`, ids)
}
/**
*
*
* @param id
* @returns
*/
static findForm(id?: string | undefined) {
return Http.get(`${this.urlPrefix}/findForm${(id ? '/' + id : '')}`)
}
/**
*
*
* @param id
* @param formData
* @returns
*/
static saveForm(id: string | undefined, formData: any) {
return Http.post(`${this.urlPrefix}/${id ? 'update' : 'create'}`, formData)
}
/**
* excel
*
* @param search
* @param searchSort
* @returns
*/
static exportExcel(search: any = {}, searchSort: any[] = []) {
return Http.download(`${this.urlPrefix}/exportExcel`, {
page: -1,
size: -1,
search,
searchSort
});
}
}

View File

@ -0,0 +1,74 @@
import Http from "@/core/utils/Http";
/**
* T_App_Config服务
*/
export default class T_App_ConfigService {
static urlPrefix = "/api/v1/admin/Game/T_App_Config";
/**
*
* @param current
* @param pageSize
* @param search
* @param searchSort
* @returns
*/
static findList(current: number, pageSize: number, search: any = {}, searchSort: any[] = []) {
return Http.post(`${this.urlPrefix}/findList`, {
page: current,
size: pageSize,
search,
searchSort
})
}
/**
*
*
* @param ids
* @returns
*/
static deleteList(ids: string[]) {
return Http.post(`${this.urlPrefix}/deleteList`, ids)
}
/**
*
*
* @param id
* @returns
*/
static findForm(id?: string | undefined) {
return Http.get(`${this.urlPrefix}/findForm${(id ? '/' + id : '')}`)
}
/**
*
*
* @param id
* @param formData
* @returns
*/
static saveForm(id: string | undefined, formData: any) {
return Http.post(`${this.urlPrefix}/${id ? 'update' : 'create'}`, formData)
}
/**
* excel
*
* @param search
* @param searchSort
* @returns
*/
static exportExcel(search: any = {}, searchSort: any[] = []) {
return Http.download(`${this.urlPrefix}/exportExcel`, {
page: -1,
size: -1,
search,
searchSort
});
}
}

View File

@ -1,5 +1,5 @@
import Http from "@/core/utils/Http";
import Tools from "@/core/utils/Tools";
/**
*
*/
@ -73,7 +73,17 @@ export default class SysUserService {
*
* @returns
*/
static currentUser() {
return Http.get(`${this.urlPrefix}/info`);
static async currentUser() {
var data = await Http.get(`${this.urlPrefix}/info`);
// console.log(data);
if (data != null && data.code == 200) {
if (data.data.sysOrganization != null) {
if (data.data.sysOrganization.tenantId != null) {
console.log(data.data.sysOrganization.tenantId);
Tools.setTenantId(data.data.sysOrganization.tenantId);
}
}
}
return data;
}
}

View File

@ -30,6 +30,11 @@ class AppConsts {
*/
static domainServerApi: string = `${import.meta.env.VITE_API_URL}`;
/**
*
*/
static domainExServerApi: string = `${import.meta.env.VITE_EXTAPI_URL}`;
/**
* app key
*/
@ -103,6 +108,6 @@ class AppConsts {
}
}
console.log(import.meta.env.VITE_API_URL,AppConsts.domainServerApi);
console.log(import.meta.env.VITE_API_URL, AppConsts.domainServerApi);
export default AppConsts;

View File

@ -10,6 +10,7 @@ import {
import * as monaco from "monaco-editor";
import "monaco-editor/min/vs/editor/editor.main.css";
import Tools from "@/core/utils/Tools";
import MonacoEditor from "@/core/components/MonacoEditor.vue";
const props = defineProps<{ onSuccess: () => void }>();
let editorContainer = ref<HTMLElement>();
let editorInstance: monaco.editor.IStandaloneCodeEditor | null = null;
@ -133,6 +134,7 @@ function showJyRequestData(t: any) {
}
}
}
let xxx="321321";
</script>
<template>
@ -194,6 +196,7 @@ function showJyRequestData(t: any) {
<div class="monaco-editor" ref="editorContainer"></div>
返回消息
<div class="monaco-editor" ref="responseEditorContainer"></div>
</el-main>
</el-container>
</a-spin>

View File

@ -0,0 +1,256 @@
<script lang="ts" setup>
import { reactive, ref, onMounted } from "vue";
import { FormInstance } from "ant-design-vue";
import { useAuthority } from "@/utils/Authority";
import AppIcon from "@/core/components/AppIcon.vue";
import Info from "./Info.vue";
import Tools from "@/core/utils/Tools";
import PageContainerGame from "@/core/components/PageContainerGame.vue";
import TableCurdV1 from "@/core/components/curd/TableCurdV1.vue";
import T_App_ChannelService from "@/services/apps/Ext/T_App_ChannelService";
defineOptions({ name: "t_App_ChannelIndex" });
var columns = [
{
dataIndex: "name",
title: "渠道名称",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "channelId",
title: "渠道号",
show: true,
width: 60,
sorter: true,
},
{
dataIndex: "createAt",
title: "创建时间",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "updateAt",
title: "修改时间",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "desc",
title: "备注",
show: true,
width: 40,
sorter: true,
},
];
const state = reactive({
search: {
state: true,
vm: {
channelid: undefined,
name: undefined,
},
sort: [] as any[],
},
loading: false,
page: 1,
size: 50,
total: 100,
columns: [] as any,
data: [] as any,
});
//
const power = useAuthority();
//
const refTableCurd = ref < InstanceType < typeof TableCurdV1 >> ();
//
const refInfo = ref<InstanceType<typeof Info>>();
//
const refSearchForm = ref<FormInstance>();
/**
* 初始化
*/
onMounted(() => {
findList();
});
/**
*获取数据
*/
async function findList() {
try{
state.loading = true;
const result = await T_App_ChannelService.findList(state.page, state.size, state.search.vm, state.search.sort);
state.loading = false;
if (result.code != 200) return;
state.page = result.data.page;
state.size = result.data.size;
state.total = result.data.total;
state.columns = columns;// result.data.columns;
state.data = result.data.dataSource;
// state.visible = false;
} catch (error) {
state.loading = false;
}
}
/**
* 删除数据
* @param id
*/
async function deleteList(id?: string) {
let ids: string[] = [];
if (id) {
ids.push(id);
} else {
ids = refTableCurd.value?.getSelectedRowKeys() ?? [];
}
if (ids.length == 0) return Tools.message.error("请选择要删除的行!");
try{
state.loading = true;
const result = await T_App_ChannelService.deleteList(ids);
state.loading = false;
if (result.code != 200) return;
Tools.message.success("删除成功!");
findList();
} catch (error) {
state.loading = false;
}
}
/**
* 导出excel
*/
function exportExcel() {
T_App_ChannelService.exportExcel(state.search.vm, state.search.sort);
}
</script>
<template>
<PageContainerGame>
<TableCurdV1 ref="refTableCurd"
:config="state"
@change="
(changeTable) => {
state.page = changeTable.pagination.current ?? 1;
state.size = changeTable.pagination.pageSize ?? state.size;
state.search.sort = changeTable.sorter instanceof Array ? [...changeTable.sorter] : [changeTable.sorter];
findList();
}
"
@show-size-change="
({ current, size }) => {
state.page = current == 0 ? 1 : current;
state.size = size;
findList();
}
"
>
<!-- search -->
<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.channelid" 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="渠道名称">
<a-input v-model:value="state.search.vm.name" placeholder="渠道名称" />
</a-form-item>
</a-col>
<!--button-->
<a-col :xs="2" :sm="2" :md="2" :lg="2" :xl="2" class="text-right">
<a-space :size="8">
<a-button
@click="
state.page = 1;
refSearchForm?.resetFields();
findList();
"
>
重置
</a-button>
<a-button
type="primary"
@click="
state.page = 1;
findList();
"
>
查询
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
<!-- toolbar-left -->
<template #toolbar-left>
<!-- <a-button @click="state.search.state = !state.search.state" v-if="power.search">
<div v-if="state.search.state"><AppIcon name="UpOutlined" />&nbsp;&nbsp;收起</div>
<div v-else><AppIcon name="DownOutlined" />&nbsp;&nbsp;展开</div>
</a-button> -->
<a-button type="primary" @click="() => refInfo?.open()" v-if="power.insert">
<template #icon>
<AppIcon name="PlusOutlined" />
</template>
新建
</a-button>
<a-popconfirm title="您确定要删除?" @confirm="deleteList()" okText="确定" cancelText="取消" v-if="power.delete">
<a-button type="primary" danger>
<template #icon>
<AppIcon name="DeleteOutlined" />
</template>
批量删除
</a-button>
</a-popconfirm>
</template>
<!-- toolbar-right -->
<template #toolbar-right>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="exportExcel()">导出 Excel</a-menu-item>
</a-menu>
</template>
<a-button> 更多 <AppIcon name="ellipsis-outlined" /> </a-button>
</a-dropdown>
</template>
<!-- table-col -->
<template #table-col>
<template v-for="item,index in state.columns.filter((w:any) => w.dataIndex !== 'id' && w.show)" :key="item.dataIndex">
<a-table-column :title="item.title" :width="item.width" :data-index="item.dataIndex" :sorter="item.sort ? { multiple: index + 1 } : false" />
</template>
<!-- 操作 -->
<a-table-column title="操作" data-index="id" width="200px" fixed="right" v-if="power.update || power.delete">
<template #default="{ record }">
<a-button type="link" @click="() => refInfo?.open(record.id)" v-if="power.update">编辑</a-button>
<a-divider type="vertical" />
<a-popconfirm title="您确定要删除?" @confirm="deleteList(record.id)" okText="确定" cancelText="取消"
v-if="power.delete">
<a-button type="link" danger>删除</a-button>
</a-popconfirm>
</template>
</a-table-column>
</template>
</TableCurdV1>
<!-- Info -->
<Info ref="refInfo" :onSuccess="() => findList()" />
</PageContainerGame>
</template>

View File

@ -0,0 +1,92 @@
<script lang="ts" setup>
import { reactive, ref } from "vue";
import { FormInstance } from "ant-design-vue";
import Tools from "@/core/utils/Tools";
import T_App_ChannelService from "@/services/apps/Ext/T_App_ChannelService";
//
const props = defineProps<{ onSuccess: () => void }>();
const state = reactive({
vm: {
id: "",
form: {} as any,
},
visible: false,
loading: false,
});
//
const refForm = ref<FormInstance>();
//
defineExpose({
/**
* 打开表单初始化
* @param key
*/
open: (key: string = "") => {
state.visible = true;
if (state.visible) {
state.vm.id = key;
}
refForm.value?.resetFields();
//
state.loading = true;
T_App_ChannelService.findForm(key).then((res) => {
state.loading = false;
if (res.code != 200) return;
state.vm = res.data;
}
);
},
});
/**
*保存数据
*/
function save() {
refForm.value?.validate().then(async () => {
try{
state.loading = true;
const result = await T_App_ChannelService.saveForm(state.vm.id, state.vm.form);
state.loading = false;
if (result.code !=200) return;
Tools.message.success("操作成功!");
props.onSuccess();
state.visible = false;
} catch (error) {
state.loading = false;
}
});
}
</script>
<template>
<a-modal v-model:open="state.visible" :title="state.vm.id ? '编辑' : '新建'" centered @ok="state.visible = false" :maskClosable="false" :width="900">
<template #footer>
<a-button type="primary" :loading="state.loading" @click="save()"> 提交</a-button>
<a-button @click="state.visible = false">关闭</a-button>
</template>
<a-spin :spinning="state.loading">
<a-form ref="refForm" layout="vertical" :model="state.vm.form">
<a-row :gutter="[16, 0]">
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="渠道名称" name="name" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.name" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="渠道号" name="channelId" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.channelId" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="备注" name="desc" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.desc" placeholder="请输入" />
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-spin>
</a-modal>
</template>

View File

@ -0,0 +1,385 @@
<script lang="ts" setup>
import { reactive, ref, onMounted } from "vue";
import { FormInstance } from "ant-design-vue";
import { useAuthority } from "@/utils/Authority";
import AppIcon from "@/core/components/AppIcon.vue";
import Info from "./Info.vue";
import Tools from "@/core/utils/Tools";
import PageContainerGame from "@/core/components/PageContainerGame.vue";
import TableCurdV1 from "@/core/components/curd/TableCurdV1.vue";
import T_App_ConfigService from "@/services/apps/Ext/T_App_ConfigService";
defineOptions({ name: "t_App_ConfigIndex" });
var columns = [
{
dataIndex: "name",
title: "配置名称",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "configType",
title: "配置类型",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "actionId",
title: "配置值类型",
show: false,
width: 120,
sorter: true,
},
{
dataIndex: "configValue",
title: "配置值",
show: true,
width: 500,
sorter: true,
},
{
dataIndex: "isEnabled",
title: "是否启用",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "desc",
title: "备注",
show: true,
width: 40,
sorter: true,
},
{
dataIndex: "channelId",
title: "渠道号",
show: true,
width: 60,
sorter: true,
},
{
dataIndex: "plat",
title: "平台类型",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "appVersion",
title: "app版本号",
show: true,
width: 120,
sorter: true,
},
{
dataIndex: "continent",
title: "州",
show: false,
width: 20,
sorter: true,
},
{
dataIndex: "countryName",
title: "国家",
show: false,
width: 40,
sorter: true,
},
{
dataIndex: "creatTime",
title: "创建时间",
show: true,
width: 80,
sorter: true,
},
{
dataIndex: "updateTime",
title: "修改时间",
show: true,
width: 80,
sorter: true,
},
];
const state = reactive({
search: {
state: true,
vm: {
configtype: undefined,
name: undefined,
},
sort: [] as any[],
},
loading: false,
page: 1,
size: 50,
total: 100,
columns: [] as any,
data: [] as any,
});
//
const power = useAuthority();
//
const refTableCurd = ref<InstanceType<typeof TableCurdV1>>();
//
const refInfo = ref<InstanceType<typeof Info>>();
//
const refSearchForm = ref<FormInstance>();
/**
* 初始化
*/
onMounted(() => {
findList();
});
/**
*获取数据
*/
async function findList() {
try {
state.loading = true;
const result = await T_App_ConfigService.findList(
state.page,
state.size,
state.search.vm,
state.search.sort
);
state.loading = false;
if (result.code != 200) return;
state.page = result.data.page;
state.size = result.data.size;
state.total = result.data.total;
state.columns = columns; // result.data.columns;
state.data = result.data.dataSource;
// state.visible = false;
} catch (error) {
state.loading = false;
}
}
/**
* 删除数据
* @param id
*/
async function deleteList(id?: string) {
let ids: string[] = [];
if (id) {
ids.push(id);
} else {
ids = refTableCurd.value?.getSelectedRowKeys() ?? [];
}
if (ids.length == 0) return Tools.message.error("请选择要删除的行!");
try {
state.loading = true;
const result = await T_App_ConfigService.deleteList(ids);
state.loading = false;
if (result.code != 200) return;
Tools.message.success("删除成功!");
findList();
} catch (error) {
state.loading = false;
}
}
/**
* 导出excel
*/
function exportExcel() {
T_App_ConfigService.exportExcel(state.search.vm, state.search.sort);
}
</script>
<template>
<PageContainerGame>
<TableCurdV1
ref="refTableCurd"
:config="state"
@change="
(changeTable) => {
state.page = changeTable.pagination.current ?? 1;
state.size = changeTable.pagination.pageSize ?? state.size;
state.search.sort =
changeTable.sorter instanceof Array
? [...changeTable.sorter]
: [changeTable.sorter];
findList();
}
"
@show-size-change="
({ current, size }) => {
state.page = current == 0 ? 1 : current;
state.size = size;
findList();
}
"
>
<!-- search -->
<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="配置类型">
<h-common-select
code="appconfigManage_type"
v-model="state.search.vm.configtype"
:ShowAll="true"
:defaultValue="0"
/>
</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="配置名称">
<a-input
v-model:value="state.search.vm.name"
placeholder="配置名称"
/>
</a-form-item>
</a-col>
<!--button-->
<a-col :xs="2" :sm="2" :md="2" :lg="2" :xl="2" class="text-right">
<a-space :size="8">
<a-button
@click="
state.page = 1;
refSearchForm?.resetFields();
findList();
"
>
重置
</a-button>
<a-button
type="primary"
@click="
state.page = 1;
findList();
"
>
查询
</a-button>
</a-space>
</a-col>
</a-row>
</a-form>
</template>
<!-- toolbar-left -->
<template #toolbar-left>
<!-- <a-button @click="state.search.state = !state.search.state" v-if="power.search">
<div v-if="state.search.state"><AppIcon name="UpOutlined" />&nbsp;&nbsp;收起</div>
<div v-else><AppIcon name="DownOutlined" />&nbsp;&nbsp;展开</div>
</a-button> -->
<a-button
type="primary"
@click="() => refInfo?.open()"
v-if="power.insert"
>
<template #icon>
<AppIcon name="PlusOutlined" />
</template>
新建
</a-button>
<a-popconfirm
title="您确定要删除?"
@confirm="deleteList()"
okText="确定"
cancelText="取消"
v-if="power.delete"
>
<a-button type="primary" danger>
<template #icon>
<AppIcon name="DeleteOutlined" />
</template>
批量删除
</a-button>
</a-popconfirm>
</template>
<!-- toolbar-right -->
<template #toolbar-right>
<a-dropdown>
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="exportExcel()"
>导出 Excel</a-menu-item
>
</a-menu>
</template>
<a-button> 更多 <AppIcon name="ellipsis-outlined" /> </a-button>
</a-dropdown>
</template>
<!-- table-col -->
<template #table-col>
<template
v-for="item,index in state.columns.filter((w:any) => w.dataIndex !== 'id' && w.show)"
:key="item.dataIndex"
>
<a-table-column
:title="item.title"
:width="item.width"
:data-index="item.dataIndex"
:sorter="item.sort ? { multiple: index + 1 } : false"
>
<template
#default="{ record }"
v-if="item.dataIndex === 'configValue'"
>
<div
v-html="record.configValue"
style="max-height: 200px; overflow: auto"
></div>
</template>
</a-table-column>
</template>
<!-- 操作 -->
<a-table-column
title="操作"
data-index="id"
:width="200"
fixed="right"
v-if="power.update || power.delete"
>
<template #default="{ record }">
<a-button
type="link"
@click="() => refInfo?.open(record.id)"
v-if="power.update"
>编辑</a-button
>
<a-divider type="vertical" />
<a-popconfirm
title="您确定要删除?"
@confirm="deleteList(record.id)"
okText="确定"
cancelText="取消"
v-if="power.delete"
>
<a-button type="link" danger>删除</a-button>
</a-popconfirm>
</template>
</a-table-column>
</template>
</TableCurdV1>
<!-- Info -->
<Info ref="refInfo" :onSuccess="() => findList()" />
</PageContainerGame>
</template>

View File

@ -0,0 +1,266 @@
<script lang="ts" setup>
import { reactive, ref } from "vue";
import { FormInstance } from "ant-design-vue";
import Tools from "@/core/utils/Tools";
import T_App_ConfigService from "@/services/apps/Ext/T_App_ConfigService";
import MonacoEditor from "@/core/components/MonacoEditor.vue";
//
const props = defineProps<{ onSuccess: () => void }>();
const state = reactive({
vm: {
id: "",
form: {} as any,
},
visible: false,
loading: false,
});
//
const refForm = ref<FormInstance>();
//
defineExpose({
/**
* 打开表单初始化
* @param key
*/
open: (key: string = "") => {
state.visible = true;
if (state.visible) {
state.vm.id = key;
}
refForm.value?.resetFields();
//
state.loading = true;
T_App_ConfigService.findForm(key).then((res) => {
state.loading = false;
if (res.code != 200) return;
if (res.data.form.id == 0) {
res.data.form.configType = 1;
// res.data.form.actionId = 0;
res.data.form.isEnabled = true;
}
if (res.data.form.configValue == null) {
res.data.form.configValue = "";
}
if (res.data.form.isEnabled == null) {
res.data.form.isEnabled = false;
}
state.vm = res.data;
});
},
});
/**
*保存数据
*/
function save() {
refForm.value?.validate().then(async () => {
try {
state.loading = true;
const result = await T_App_ConfigService.saveForm(
state.vm.id,
state.vm.form
);
state.loading = false;
if (result.code != 200) return;
Tools.message.success("操作成功!");
props.onSuccess();
state.visible = false;
} catch (error) {
state.loading = false;
}
});
}
var xxx = "32132132";
var x = [
{ configType: 3, value: 1, lable: "游戏配置-玩游戏统一消耗费用" },
{ configType: 7, value: 1, lable: "审核配置" },
{ configType: 8, value: 1, lable: "用户协议配置" },
{ configType: 8, value: 2, lable: "隐私协议配置" },
];
const querySearch = (queryString: string, cb: any) => {
// call callback function to return suggestions
if (state.vm.form.configType != 0) {
var c = x.filter((it) => it.configType == state.vm.form.configType);
cb(c);
return;
}
cb([]);
};
</script>
<template>
<a-modal
v-model:open="state.visible"
:title="state.vm.id ? '编辑' : '新建'"
centered
@ok="state.visible = false"
:maskClosable="false"
:width="900"
>
<template #footer>
<a-button type="primary" :loading="state.loading" @click="save()">
提交</a-button
>
<a-button @click="state.visible = false">关闭</a-button>
</template>
<a-spin :spinning="state.loading">
<a-form ref="refForm" layout="vertical" :model="state.vm.form">
<a-row :gutter="[16, 0]">
<a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<a-form-item
label="配置名称"
name="name"
:rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
>
<a-input
v-model:value="state.vm.form.name"
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="配置类型" name="configType">
<h-common-select
code="appconfigManage_type"
v-model="state.vm.form.configType"
:ShowAll="false"
:defaultValue="1"
/>
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="配置ID" name="configId" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<el-autocomplete
style=""
v-model="state.vm.form.configId"
:fetch-suggestions="querySearch"
clearable
class="inline-input"
placeholder=""
>
<template #default="{ item }">
<span class="link">[{{ item.value }}]{{ item.lable }}</span>
</template>
</el-autocomplete>
</a-form-item>
</a-col>
<a-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6">
<a-form-item label="渠道号" name="channelId">
<a-input
v-model:value="state.vm.form.channelId"
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6">
<a-form-item label="平台类型" name="plat">
<h-common-select
code="platform"
v-model="state.vm.form.plat"
:ShowAll="true"
defaultValue=""
/>
</a-form-item>
</a-col>
<a-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6">
<a-form-item label="app版本号" name="appVersion">
<a-tooltip
placement="bottomLeft"
title="1.0.1表示app等于1.0.1版本, +1.0.1表示app大于1.0.1的版本,-1.0.1表示app小于1.0.1版本"
>
<a-input
v-model:value="state.vm.form.appVersion"
placeholder="请输入"
/>
</a-tooltip>
</a-form-item>
</a-col>
<a-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6">
<a-form-item label="是否启用" name="isEnabled">
<a-radio-group
v-model:value="state.vm.form.isEnabled"
name="isEnabled"
>
<a-radio :value="false"></a-radio>
<a-radio :value="true"></a-radio>
</a-radio-group>
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="配置值类型" name="actionId">
<h-common-select
code="appconfigManage_action"
v-model="state.vm.form.actionId"
:defaultValue="0"
/>
</a-form-item>
</a-col>
<a-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6">
<a-form-item label="州" name="continent">
<a-input
v-model:value="state.vm.form.continent"
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :xs="6" :sm="6" :md="6" :lg="6" :xl="6">
<a-form-item label="国家" name="countryName">
<a-input
v-model:value="state.vm.form.countryName"
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<a-form-item label="配置值" name="configValue">
<a-textarea
v-if="state.vm.form.actionId == 0"
v-model:value="state.vm.form.configValue"
placeholder=""
:auto-size="{ minRows: 10, maxRows: 10 }"
/>
<h-image-btn
v-if="state.vm.form.actionId == 1"
v-model="state.vm.form.configValue"
/>
<MonacoEditor
v-if="state.vm.form.actionId == 3"
v-model:model-value="state.vm.form.configValue"
></MonacoEditor>
<WangEditor
v-if="state.vm.form.actionId == 2"
v-model:html="state.vm.form.configValue"
domainName="http://localhost:5600"
previewDomainName="http://localhost:5600"
:height="200"
/>
</a-form-item>
</a-col>
<a-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<a-form-item label="备注" name="desc">
<a-input
v-model:value="state.vm.form.desc"
placeholder="请输入"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-spin>
</a-modal>
</template>
<style>
.monaco-editor {
width: 100%;
height: 200px;
}
</style>

View File

@ -68,14 +68,6 @@ defineOptions({ name: "t_User_IntentOrderIndex" });
sorter: true,
},
{
dataIndex: "intentAt",
title: "订单创建时间",
show: true,
width: 120,
sorter: true,
},
{
dataIndex: "createdAt",
title: "创建时间",
@ -99,6 +91,22 @@ defineOptions({ name: "t_User_IntentOrderIndex" });
width: 80,
sorter: true,
},
{
dataIndex: "createdDay",
title: "创建时间",
show: false,
width: 80,
sorter: true,
},
{
dataIndex: "channel",
title: "创建小时",
show: false,
width: 80,
sorter: true,
},
];
const state = reactive({
search: {

View File

@ -106,13 +106,18 @@ function save() {
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="订单创建时间" name="intentAt" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.intentAt" placeholder="请输入" />
<a-form-item label="订单Id" name="orderId" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.orderId" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="订单Id" name="orderId" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.orderId" placeholder="请输入" />
<a-form-item label="创建时间" name="createdDay" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.createdDay" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="创建小时" name="channel" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.channel" placeholder="请输入" />
</a-form-item>
</a-col>
</a-row>

View File

@ -95,15 +95,24 @@ defineOptions({ name: "t_User_OrderIndex" });
{
dataIndex: "paymentDay",
title: "订单创建天",
show: true,
show: false,
width: 100,
sorter: true,
},
{
dataIndex: "channel",
title: "渠道",
show: false,
width: 40,
sorter: true,
},
];
const state = reactive({
search: {
state: true,
vm: {
orderdate: undefined,
orderid: undefined,
userid: undefined,
},
@ -211,6 +220,11 @@ 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.orderdate" 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="订单编号">
<a-input v-model:value="state.search.vm.orderid" placeholder="订单编号" />

View File

@ -114,6 +114,11 @@ function save() {
<a-form-item label="订单创建天" name="paymentDay" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.paymentDay" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12">
<a-form-item label="渠道" name="channel" :rules="[{ required: true, message: '请输入', trigger: 'blur' }]">
<a-input v-model:value="state.vm.form.channel" placeholder="请输入" />
</a-form-item>
</a-col>
</a-row>
</a-form>

View File

@ -1,7 +1,7 @@
<script lang="ts" setup>
import { ref, onBeforeUnmount } from "vue";
import AppIcon from "@/core/components/AppIcon.vue";
import AppMonitorService from "@/services/Apps/Ext/AppMonitorService";
interface CardData {
title: string;
unit: string;
@ -13,13 +13,6 @@ interface CardData {
const iconSize = ref(60);
const timer = ref<NodeJS.Timer | null>(null);
const cards = ref<CardData[]>([
{
title: "今日注册人数",
unit: "人",
value: 107,
icon: "UserAddOutlined",
color: "#32CD32",
},
{
title: "今日登录人数",
unit: "人",
@ -27,6 +20,13 @@ const cards = ref<CardData[]>([
icon: "UserOutlined",
color: "#9370DB",
},
{
title: "今日注册人数",
unit: "人",
value: 107,
icon: "UserAddOutlined",
color: "#32CD32",
},
{
title: "当前在线人数",
unit: "人",
@ -71,20 +71,39 @@ const cards = ref<CardData[]>([
},
]);
const updateValues = () => {
cards.value = cards.value.map((card) => {
const max = card.unit === "台" ? 1000 : card.unit === "次" ? 500 : 90;
return { ...card, value: Math.floor(Math.random() * max) };
});
AppMonitorService.GetAppMonitorInfo().then((data) => {
if (data != null) {
cards.value[0].value = data.todayLoggedInUsers;
cards.value[1].value = data.todayRegisteredUsers;
cards.value[2].value = data.currentOnlineUsers;
cards.value[3].value = data.currentPlayingUsers;
cards.value[4].value = data.currentQueuedUsers;
cards.value[5].value = data.todayIntendedOrders;
cards.value[6].value = data.todayPaidOrders;
cards.value[7].value = data.todayRechargeAmount;
}
});
const updateValues = async () => {
var data = await AppMonitorService.GetAppMonitorInfo();
if (data != null) {
cards.value[0].value = data.todayLoggedInUsers;
cards.value[1].value = data.todayRegisteredUsers;
cards.value[2].value = data.currentOnlineUsers;
cards.value[3].value = data.currentPlayingUsers;
cards.value[4].value = data.currentQueuedUsers;
cards.value[5].value = data.todayIntendedOrders;
cards.value[6].value = data.todayPaidOrders;
cards.value[7].value = data.todayRechargeAmount;
}
};
// timer.value = setInterval(updateValues, 2000);
timer.value = setInterval(updateValues, 2000);
// onBeforeUnmount(() => {
// if (timer.value) {
// // clearInterval(timer.value);
// }
// });
onBeforeUnmount(() => {
if (timer.value) {
clearInterval(timer.value);
}
});
</script>
<template>

View File

@ -20,6 +20,7 @@ for (let i = 0; i < 30; i++) {
category: "小米渠道",
});
}
console.log(data);
let timer = ref();

View File

@ -4,12 +4,13 @@ import { resolve } from "path";
import vueJsx from "@vitejs/plugin-vue-jsx";
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite';
import { AntDesignVueResolver,ElementPlusResolver } from 'unplugin-vue-components/resolvers';
// import monacoEditorPlugin from "vite-plugin-monaco-editor";
// https://vitejs.dev/config/
import { AntDesignVueResolver, ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import monacoEditorPlugin from 'vite-plugin-monaco-editor';
export default defineConfig({
plugins: [
vue(),
// monacoEditorPlugin({}),
vueJsx({
// https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx
// options are passed on to @vue/babel-plugin-jsx
@ -23,7 +24,7 @@ export default defineConfig({
dts: 'src/auto-imports.d.ts', // 可以生成 TypeScript 声明文件
}),
Components({
dirs: ['src/core/components'],
extensions: ['vue'],
deep: true,
@ -35,13 +36,25 @@ export default defineConfig({
}),
],
}),
monacoEditorPlugin.default({}),
// MonacoEditorPlugin({
// // 这里可以配置插件的选项
// // plugins: [monacoEditorPlugin()],
// languageWorkers: ['editorWorkerService', 'json', 'css', 'html', 'typescript'], // 默认会加载这些 worker
// // customWorkers: [
// // {
// // label: 'myCustomWorker',
// // entry: 'path/to/customWorker.js',
// // },
// // ],
// }),
],
/**
*
* client
* /
*/
base:"",// process.env.NODE_ENV == "production" ? "/client/" : "/",
base: "",// process.env.NODE_ENV == "production" ? "/client/" : "/",
server: {
port: 702,
host: true,

View File

@ -0,0 +1,51 @@
using CloudGaming.Repository.Game.Entities.Ext;
namespace CloudGaming.Api.Admin.ApplicationServices.Apps.Ext;
/// <summary>
/// app渠道表 服务 T_App_ChannelService
/// </summary>
public class T_App_ChannelService(IServiceProvider serviceProvider)
: ApplicationGameService<T_App_Channel, int, T_App_Channel, T_App_Channel>(serviceProvider)
{
/// <summary>
/// 获取列表数据
/// </summary>
/// <param name="pagingSearchInput"></param>
/// <returns></returns>
public async override Task<PagingView> FindListAsync(PagingSearchInput<T_App_Channel> pagingSearchInput)
{
var query = this.Repository.Select
//渠道号
.WhereIf(!string.IsNullOrWhiteSpace(pagingSearchInput.Search?.ChannelId),
w => w.ChannelId.Contains(pagingSearchInput.Search.ChannelId ?? ""))
//渠道名称
.WhereIf(!string.IsNullOrWhiteSpace(pagingSearchInput.Search?.Name),
w => w.Name.Contains(pagingSearchInput.Search.Name ?? ""))
.OrderByDescending(w => w.Id)
.Select(w => new
{
w.Id,
w.Name,
w.ChannelId,
w.CreateAt,
w.UpdateAt,
w.Desc,
})
;
var result = await Repository.AsPagingViewAsync(query, pagingSearchInput);
// 设置列
//result.GetColumn(query, w => w.OperatorName).SetColumn("操作人");
//result.GetColumn(query, w => w. !).SetColumn<SysUser>(w => w.Name!);
result
.FormatValue(query, w => w.CreateAt, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
.FormatValue(query, w => w.UpdateAt, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
;
return result;
}
}

View File

@ -0,0 +1,60 @@
using CloudGaming.Repository.Game.Entities.Ext;
namespace CloudGaming.Api.Admin.ApplicationServices.Apps.Ext;
/// <summary>
/// App配置表 服务 T_App_ConfigService
/// </summary>
public class T_App_ConfigService(IServiceProvider serviceProvider)
: ApplicationGameService<T_App_Config, int, T_App_Config, T_App_Config>(serviceProvider)
{
/// <summary>
/// 获取列表数据
/// </summary>
/// <param name="pagingSearchInput"></param>
/// <returns></returns>
public async override Task<PagingView> FindListAsync(PagingSearchInput<T_App_Config> pagingSearchInput)
{
var query = this.Repository.Select
//配置类型
.WhereIf(pagingSearchInput.Search?.ConfigType != null && pagingSearchInput.Search?.ConfigType > 0,
w => w.ConfigType == pagingSearchInput.Search.ConfigType)
//配置名称
.WhereIf(!string.IsNullOrWhiteSpace(pagingSearchInput.Search?.Name),
w => w.Name.Contains(pagingSearchInput.Search.Name ?? ""))
.OrderByDescending(w => w.Id)
.Select(w => new
{
w.Id,
w.ConfigId,
w.ConfigType,
w.ActionId,
w.ConfigValue,
w.IsEnabled,
w.Name,
w.Desc,
w.ChannelId,
w.Plat,
w.AppVersion,
w.Continent,
w.CountryName,
w.CreateTime,
w.UpdateTime,
})
;
var result = await Repository.AsPagingViewAsync(query, pagingSearchInput);
// 设置列
//result.GetColumn(query, w => w.OperatorName).SetColumn("操作人");
//result.GetColumn(query, w => w. !).SetColumn<SysUser>(w => w.Name!);
result
.FormatValue(query, w => w.CreateTime, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
.FormatValue(query, w => w.UpdateTime, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
;
return result;
}
}

View File

@ -27,7 +27,7 @@ public class T_User_IntentOrderService(IServiceProvider serviceProvider)
.Select(w => new
{
w.Id,
w.UserId,w.ProductId,w.Method,w.Price,w.Quantity,w.Status,w.Notes,w.IntentAt,w.CreatedAt,w.UpdatedAt,w.TenantId,w.OrderId,
w.UserId,w.ProductId,w.Method,w.Price,w.Quantity,w.Status,w.Notes,w.CreatedAt,w.UpdatedAt,w.TenantId,w.OrderId,w.CreatedDay,w.Channel,
})
;
var result = await Repository.AsPagingViewAsync(query, pagingSearchInput);
@ -37,9 +37,8 @@ public class T_User_IntentOrderService(IServiceProvider serviceProvider)
//result.GetColumn(query, w => w. !).SetColumn<SysUser>(w => w.Name!);
result
.FormatValue(query, w => w.IntentAt, (oldValue) => oldValue.ToString("yyyy-MM-dd"))
.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

@ -5,7 +5,7 @@ namespace CloudGaming.Api.Admin.ApplicationServices.Apps.User;
/// 订单完成表 服务 T_User_OrderService
/// </summary>
public class T_User_OrderService(IServiceProvider serviceProvider)
: ApplicationUserService<T_User_Order,int,T_User_Order,T_User_Order>(serviceProvider)
: ApplicationUserService<T_User_Order, int, T_User_Order, T_User_Order>(serviceProvider)
{
@ -17,17 +17,32 @@ public class T_User_OrderService(IServiceProvider serviceProvider)
public async override Task<PagingView> FindListAsync(PagingSearchInput<T_User_Order> pagingSearchInput)
{
var query = this.Repository.Select
////订单创建时间
//.WhereIf(!pagingSearchInput.Search?.OrderDate,
// w => w.OrderDate.Contains(pagingSearchInput.Search.OrderDate ?? ""))
//订单编号
.WhereIf(!string.IsNullOrWhiteSpace(pagingSearchInput.Search?.OrderId),
w => w.OrderId.Contains(pagingSearchInput.Search.OrderId ?? ""))
//用户Id
.WhereIf(pagingSearchInput.Search?.UserId!=null&&pagingSearchInput.Search?.UserId>0,
w => w.UserId== pagingSearchInput.Search.UserId)
.WhereIf(pagingSearchInput.Search?.UserId != null && pagingSearchInput.Search?.UserId > 0,
w => w.UserId == pagingSearchInput.Search.UserId)
.OrderByDescending(w => w.Id)
.Select(w => new
{
w.Id,
w.TenantId,w.OrderId,w.UserId,w.OrderDate,w.PaymentDate,w.PaymentMethod,w.ProductId,w.TotalPrice,w.Status,w.CreatedAt,w.UpdatedAt,w.PaymentDay,
w.TenantId,
w.OrderId,
w.UserId,
w.OrderDate,
w.PaymentDate,
w.PaymentMethod,
w.ProductId,
w.TotalPrice,
w.Status,
w.CreatedAt,
w.UpdatedAt,
w.PaymentDay,
w.Channel,
})
;
var result = await Repository.AsPagingViewAsync(query, pagingSearchInput);
@ -35,15 +50,15 @@ public class T_User_OrderService(IServiceProvider serviceProvider)
// 设置列
//result.GetColumn(query, w => w.OperatorName).SetColumn("操作人");
//result.GetColumn(query, w => w. !).SetColumn<SysUser>(w => w.Name!);
result
.FormatValue(query, w => w.OrderDate, (oldValue) => oldValue.ToString("yyyy-MM-dd"))
.FormatValue(query, w => w.PaymentDate, (oldValue) => oldValue.ToString("yyyy-MM-dd"))
.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.PaymentDay, (oldValue) => oldValue.ToString("yyyy-MM-dd"))
.FormatValue(query, w => w.OrderDate, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
.FormatValue(query, w => w.PaymentDate, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
.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"))
.FormatValue(query, w => w.PaymentDay, (oldValue) => oldValue.ToString("yyyy-MM-dd HH:mm:ss"))
;
return result;
}

View File

@ -638,6 +638,40 @@
<param name="form"></param>
<returns></returns>
</member>
<member name="T:CloudGaming.Api.Admin.ApplicationServices.Apps.Ext.T_App_ChannelService">
<summary>
app渠道表 服务 T_App_ChannelService
</summary>
</member>
<member name="M:CloudGaming.Api.Admin.ApplicationServices.Apps.Ext.T_App_ChannelService.#ctor(System.IServiceProvider)">
<summary>
app渠道表 服务 T_App_ChannelService
</summary>
</member>
<member name="M:CloudGaming.Api.Admin.ApplicationServices.Apps.Ext.T_App_ChannelService.FindListAsync(CloudGaming.Shared.Models.PagingViews.PagingSearchInput{CloudGaming.Repository.Game.Entities.Ext.T_App_Channel})">
<summary>
获取列表数据
</summary>
<param name="pagingSearchInput"></param>
<returns></returns>
</member>
<member name="T:CloudGaming.Api.Admin.ApplicationServices.Apps.Ext.T_App_ConfigService">
<summary>
App配置表 服务 T_App_ConfigService
</summary>
</member>
<member name="M:CloudGaming.Api.Admin.ApplicationServices.Apps.Ext.T_App_ConfigService.#ctor(System.IServiceProvider)">
<summary>
App配置表 服务 T_App_ConfigService
</summary>
</member>
<member name="M:CloudGaming.Api.Admin.ApplicationServices.Apps.Ext.T_App_ConfigService.FindListAsync(CloudGaming.Shared.Models.PagingViews.PagingSearchInput{CloudGaming.Repository.Game.Entities.Ext.T_App_Config})">
<summary>
获取列表数据
</summary>
<param name="pagingSearchInput"></param>
<returns></returns>
</member>
<member name="T:CloudGaming.Api.Admin.ApplicationServices.Apps.Ext.T_App_ImageService">
<summary>
图片列表 服务 T_App_ImageService
@ -2547,6 +2581,26 @@
<param name="form"></param>
<returns></returns>
</member>
<member name="T:CloudGaming.Api.Admin.Controllers.Apps.Ext.T_App_ChannelController">
<summary>
app渠道表 控制器
</summary>
</member>
<member name="M:CloudGaming.Api.Admin.Controllers.Apps.Ext.T_App_ChannelController.#ctor(System.IServiceProvider)">
<summary>
app渠道表 控制器
</summary>
</member>
<member name="T:CloudGaming.Api.Admin.Controllers.Apps.Ext.T_App_ConfigController">
<summary>
App配置表 控制器
</summary>
</member>
<member name="M:CloudGaming.Api.Admin.Controllers.Apps.Ext.T_App_ConfigController.#ctor(System.IServiceProvider)">
<summary>
App配置表 控制器
</summary>
</member>
<member name="T:CloudGaming.Api.Admin.Controllers.Apps.Ext.T_App_ImageController">
<summary>
图片列表 控制器

View File

@ -0,0 +1,13 @@
using CloudGaming.Repository.Game.Entities.Ext;
using CloudGaming.Api.Admin.ApplicationServices.Apps.Ext;
namespace CloudGaming.Api.Admin.Controllers.Apps.Ext;
/// <summary>
/// app渠道表 控制器
/// </summary>
[ControllerDescriptor(MenuId = "请设置菜单Id 系统菜单表中查找,如果不设置不受权限保护!", DisplayName = "app渠道表")]
public class T_App_ChannelController(IServiceProvider serviceProvider)
: AdminGameControllerBase<T_App_ChannelService,T_App_Channel,int,T_App_Channel,T_App_Channel>(serviceProvider)
{
}

View File

@ -0,0 +1,13 @@
using CloudGaming.Repository.Game.Entities.Ext;
using CloudGaming.Api.Admin.ApplicationServices.Apps.Ext;
namespace CloudGaming.Api.Admin.Controllers.Apps.Ext;
/// <summary>
/// App配置表 控制器
/// </summary>
[ControllerDescriptor(MenuId = "请设置菜单Id 系统菜单表中查找,如果不设置不受权限保护!", DisplayName = "App配置表")]
public class T_App_ConfigController(IServiceProvider serviceProvider)
: AdminGameControllerBase<T_App_ConfigService,T_App_Config,int,T_App_Config,T_App_Config>(serviceProvider)
{
}

View File

@ -18,8 +18,8 @@
"JwtValidAudience": "CloudGaming",
"JwtValidIssuer": "CloudGaming",
"JwtIssuerSigningKey": "1CC76841-F25D-4389-89FE-0F9451163CF1",
"JwtExpirationTime": 1,
"JwtRefreshTime": 12
"JwtExpirationTime": 3000,
"JwtRefreshTime": 6000
},
//api
"ApiWhiteList": [

View File

@ -1099,6 +1099,111 @@
搜索时间 => 备注: 搜索时间,天
</summary>
</member>
<member name="T:CloudGaming.Repository.Game.Entities.Ext.T_App_Channel">
<summary>
app渠道表
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Channel.Name">
<summary>
渠道名称 => 备注: 渠道名称
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Channel.ChannelId">
<summary>
渠道号 => 备注: 渠道号
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Channel.CreateAt">
<summary>
创建时间 => 备注: 创建时间
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Channel.UpdateAt">
<summary>
修改时间 => 备注: 修改时间
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Channel.Desc">
<summary>
备注 => 备注: 备注
</summary>
</member>
<member name="T:CloudGaming.Repository.Game.Entities.Ext.T_App_Config">
<summary>
App配置表
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.ConfigType">
<summary>
配置类型 => 备注: 配置类型
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.ActionId">
<summary>
配置值类型 => 备注: 配置值类型
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.ConfigId">
<summary>
配置id
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.ConfigValue">
<summary>
配置值 => 备注: 配置值
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.IsEnabled">
<summary>
是否启用 => 备注: 是否启用
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.Name">
<summary>
配置名称 => 备注: 配置名称
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.Desc">
<summary>
备注 => 备注: 备注
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.ChannelId">
<summary>
渠道号 => 备注: 渠道号
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.Plat">
<summary>
平台类型 => 备注: 平台。安卓还是苹果
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.AppVersion">
<summary>
app版本号 => 备注: app版本号
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.Continent">
<summary>
州 => 备注: 州 例:亚洲
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.CountryName">
<summary>
国家 => 备注: 国家 例:中国
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.CreateTime">
<summary>
创建时间 => 备注: 创建时间
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.Ext.T_App_Config.UpdateTime">
<summary>
修改时间 => 备注: 修改时间
</summary>
</member>
<member name="T:CloudGaming.Repository.Game.Entities.Ext.T_App_Image">
<summary>
图片列表
@ -1539,11 +1644,6 @@
备注 => 备注: 备注
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.User.T_User_IntentOrder.IntentAt">
<summary>
订单创建时间 => 备注: 订单创建时间
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.User.T_User_IntentOrder.CreatedAt">
<summary>
创建时间 => 备注: 创建时间
@ -1559,6 +1659,16 @@
订单Id => 备注: 订单Id
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.User.T_User_IntentOrder.CreatedDay">
<summary>
创建时间 => 备注: 创建天
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.User.T_User_IntentOrder.Channel">
<summary>
创建小时 => 备注: 渠道号
</summary>
</member>
<member name="T:CloudGaming.Repository.Game.Entities.User.T_User_Order">
<summary>
订单完成表
@ -1619,6 +1729,11 @@
订单创建天 => 备注: 订单创建天
</summary>
</member>
<member name="P:CloudGaming.Repository.Game.Entities.User.T_User_Order.Channel">
<summary>
渠道 => 备注: 渠道
</summary>
</member>
<member name="T:CloudGaming.Repository.Game.Entities.User.T_User_OrderItems">
<summary>
订单详情表

View File

@ -0,0 +1,42 @@
namespace CloudGaming.Repository.Game.Entities.Ext;
/// <summary>
/// app渠道表
/// </summary>
[Table("T_App_Channel")]
[EntityDescription(NameRuleMode = NameRuleMode.TableName, NameRuleType= NameRuleType.UpperSnakeCase)]
public class T_App_Channel : DefaultGameEntity
{
/// <summary>
/// 渠道名称 => 备注: 渠道名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 渠道号 => 备注: 渠道号
/// </summary>
public string? ChannelId { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateAt { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdateAt { get; set; }
/// <summary>
/// 备注 => 备注: 备注
/// </summary>
public string? Desc { get; set; }
}

View File

@ -0,0 +1,93 @@
namespace CloudGaming.Repository.Game.Entities.Ext;
/// <summary>
/// App配置表
/// </summary>
[Table("T_App_Config")]
[EntityDescription(NameRuleMode = NameRuleMode.TableName, NameRuleType= NameRuleType.UpperSnakeCase)]
public class T_App_Config : DefaultGameEntity
{
/// <summary>
/// 配置类型 => 备注: 配置类型
/// </summary>
public Int32 ConfigType { get; set; }
/// <summary>
/// 配置值类型 => 备注: 配置值类型
/// </summary>
public Int32 ActionId { get; set; }
/// <summary>
/// 配置id
/// </summary>
public Int32 ConfigId { get; set; }
/// <summary>
/// 配置值 => 备注: 配置值
/// </summary>
public string? ConfigValue { get; set; }
/// <summary>
/// 是否启用 => 备注: 是否启用
/// </summary>
public Boolean IsEnabled { get; set; }
/// <summary>
/// 配置名称 => 备注: 配置名称
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 备注 => 备注: 备注
/// </summary>
public string? Desc { get; set; }
/// <summary>
/// 渠道号 => 备注: 渠道号
/// </summary>
public string? ChannelId { get; set; }
/// <summary>
/// 平台类型 => 备注: 平台。安卓还是苹果
/// </summary>
public string? Plat { get; set; }
/// <summary>
/// app版本号 => 备注: app版本号
/// </summary>
public string? AppVersion { get; set; }
/// <summary>
/// 州 => 备注: 州 例:亚洲
/// </summary>
public string? Continent { get; set; }
/// <summary>
/// 国家 => 备注: 国家 例:中国
/// </summary>
public string? CountryName { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间 => 备注: 修改时间
/// </summary>
public DateTime UpdateTime { get; set; }
}

View File

@ -51,12 +51,6 @@ public class T_User_IntentOrder : DefaultGameAppEntity
public string? Notes { get; set; }
/// <summary>
/// 订单创建时间 => 备注: 订单创建时间
/// </summary>
public DateTime IntentAt { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建时间
/// </summary>
@ -74,5 +68,17 @@ public class T_User_IntentOrder : DefaultGameAppEntity
/// </summary>
public string? OrderId { get; set; }
/// <summary>
/// 创建时间 => 备注: 创建天
/// </summary>
public Int32 CreatedDay { get; set; }
/// <summary>
/// 创建小时 => 备注: 渠道号
/// </summary>
public string? Channel { get; set; }
}

View File

@ -74,5 +74,11 @@ public class T_User_Order : DefaultGameAppEntity
/// </summary>
public DateTime PaymentDay { get; set; }
/// <summary>
/// 渠道 => 备注: 渠道
/// </summary>
public string? Channel { get; set; }
}

View File

@ -56,7 +56,7 @@ namespace CloudGaming.Shared.Admin.ApplicationServices
foreach (var property in properties)
{
// 判断属性类型是否为 DateTime且名称是否以 "Create" 开头
// 判断属性类型是否为 DateTime且名称是否以 "Create" 开头 Create creat
if (property.PropertyType == typeof(DateTime) && (property.Name.StartsWith("Create") || property.Name.StartsWith("Update")))
{
// 获取属性的值