Compare commits
12 Commits
7a7d390682
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 34cebffd0c | |||
| 7cc37b0523 | |||
| 7f1d475af9 | |||
| 09302848c9 | |||
| 26bd2029e7 | |||
| 278684d3ff | |||
| f4d57d8e1c | |||
| 0ca6cae01a | |||
| 0a5485ec89 | |||
| 786a58c261 | |||
| f620c01faf | |||
| c179401357 |
29
.gitignore
vendored
29
.gitignore
vendored
@@ -1 +1,30 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
*.tsbuildinfo
|
||||
|
||||
3392
package-lock.json
generated
3392
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -1,9 +1,11 @@
|
||||
{
|
||||
"name": "pmrx-gm",
|
||||
"version": "1.0.0",
|
||||
"description": "飘渺儒仙GM管理平添",
|
||||
"description": "飘渺儒仙GM管理服务",
|
||||
"scripts": {
|
||||
"server": "nodemon server/index.js"
|
||||
"server": "nodemon server/index.js",
|
||||
"dev": "npm run dev --workspace=web",
|
||||
"web": "npm run build --workspace=web"
|
||||
},
|
||||
"keywords": [
|
||||
"node",
|
||||
@@ -13,9 +15,13 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.8.4",
|
||||
"body-parser": "^2.2.0",
|
||||
"dotenv": "^16.5.0",
|
||||
"express": "^5.1.0",
|
||||
"mysql": "^2.18.1",
|
||||
"nodemon": "^3.1.10"
|
||||
}
|
||||
},
|
||||
"workspaces": [
|
||||
"web"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,30 +1,67 @@
|
||||
const express = require('express');
|
||||
const { getConnection, query } = require('../utils/db.util');
|
||||
const express = require("express");
|
||||
const bodyParser = require("body-parser"); // 添加 body-parser 中间件
|
||||
const { getConnection, query } = require("../utils/db.util");
|
||||
const axios = require("axios");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// 添加 body-parser 中间件
|
||||
router.use(bodyParser.json());
|
||||
|
||||
// 获取角色列表
|
||||
router.get('/roles', async (req, res) => {
|
||||
try {
|
||||
const connection = await getConnection();
|
||||
const results = await query('SELECT * FROM role', [], connection);
|
||||
res.json(results);
|
||||
} catch (error) {
|
||||
console.error('获取角色数据失败:', error);
|
||||
res.status(500).json({ error: '获取角色数据失败' });
|
||||
}
|
||||
router.get("/roles", async (req, res) => {
|
||||
try {
|
||||
const { search = "" } = req.query;
|
||||
const connection = await getConnection();
|
||||
const results = await query(`SELECT * FROM role where name like '%${search}%'`, [], connection);
|
||||
res.json(results);
|
||||
} catch (error) {
|
||||
console.error("获取角色数据失败:", error);
|
||||
res.status(500).json({ error: "获取角色数据失败" });
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/item/send", async (req, res) => {
|
||||
try {
|
||||
const { roleName, itemId, itemNum = 1 } = req.body;
|
||||
if (!roleName || !itemId) res.json({ code: 1, msg: "缺少必要参数" });
|
||||
const roleId = await query(`SELECT id FROM role where name = '${roleName}' limit 1`);
|
||||
if (roleId?.length != 1) res.json({ code: 1, msg: "没有找到角色" });
|
||||
const role = roleId[0].id;
|
||||
const result = await axios.post(
|
||||
"http://192.168.25.110:19000/center/gm",
|
||||
{ role, item: [[itemId, itemNum]] },
|
||||
{
|
||||
headers: {
|
||||
Accept: "application/json, text/plain, */*",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
||||
Connection: "keep-alive",
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1 Edg/121.0.0.0",
|
||||
"Accept-Encoding": "gzip",
|
||||
"X-Mgip-sign": "gzip",
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log("物品[%s]发送给[%s]结果:%s", itemId, roleName, result.data);
|
||||
if (result.data == "成功") res.json({ code: 0, msg: "发送成功!" });
|
||||
else res.json({ code: 1, msg: result.data.content });
|
||||
} catch (error) {
|
||||
console.error("获取角色数据失败:", error);
|
||||
res.status(500).json({ error: "获取角色数据失败" });
|
||||
}
|
||||
});
|
||||
|
||||
// 获取充值列表
|
||||
router.get('/recharges', async (req, res) => {
|
||||
try {
|
||||
const connection = await getConnection();
|
||||
const results = await query('SELECT * FROM recharge', [], connection);
|
||||
res.json(results);
|
||||
} catch (error) {
|
||||
console.error('获取充值列表失败:', error);
|
||||
res.status(500).json({ error: '获取充值列表失败' });
|
||||
}
|
||||
router.get("/recharges", async (req, res) => {
|
||||
try {
|
||||
const connection = await getConnection();
|
||||
const results = await query("SELECT * FROM recharge", [], connection);
|
||||
res.json(results);
|
||||
} catch (error) {
|
||||
console.error("获取充值列表失败:", error);
|
||||
res.status(500).json({ error: "获取充值列表失败" });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
module.exports = router;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const mysql = require('mysql');
|
||||
const { cdkDbConfig } = require('../config/db.config');
|
||||
const { cdkDbConfig,gameDbConfig } = require('../config/db.config');
|
||||
|
||||
// 创建连接池
|
||||
const pool = mysql.createPool(cdkDbConfig);
|
||||
const pool = mysql.createPool(gameDbConfig);
|
||||
|
||||
// 获取数据库连接
|
||||
exports.getConnection = () => {
|
||||
|
||||
1
web/.gitattributes
vendored
Normal file
1
web/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
6
web/.prettierrc.json
Normal file
6
web/.prettierrc.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 300
|
||||
}
|
||||
6
web/.vscode/extensions.json
vendored
Normal file
6
web/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"Vue.volar",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
||||
10
web/.vscode/settings.json
vendored
Normal file
10
web/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"explorer.fileNesting.enabled": true,
|
||||
"explorer.fileNesting.patterns": {
|
||||
"tsconfig.json": "tsconfig.*.json, env.d.ts",
|
||||
"vite.config.*": "jsconfig*, vitest.config.*, cypress.config.*, playwright.config.*",
|
||||
"package.json": "package-lock.json, pnpm*, .yarnrc*, yarn*, .eslint*, eslint*, .oxlint*, oxlint*, .prettier*, prettier*, .editorconfig"
|
||||
},
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
14
web/index.html
Normal file
14
web/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="/tailwindcss.js"></script>
|
||||
<title>飘渺儒仙GM后台</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
8
web/jsconfig.json
Normal file
8
web/jsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
25
web/package.json
Normal file
25
web/package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "web",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"dayjs": "^1.11.13",
|
||||
"element-plus": "^2.9.8",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
||||
"prettier": "3.5.3",
|
||||
"vite": "^6.2.4",
|
||||
"vite-plugin-vue-devtools": "^7.7.2"
|
||||
}
|
||||
}
|
||||
BIN
web/public/favicon.ico
Normal file
BIN
web/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
8
web/public/tailwindcss.js
Normal file
8
web/public/tailwindcss.js
Normal file
File diff suppressed because one or more lines are too long
11
web/src/App.vue
Normal file
11
web/src/App.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<script setup>
|
||||
import { RouterView } from 'vue-router';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
86
web/src/assets/base.css
Normal file
86
web/src/assets/base.css
Normal file
@@ -0,0 +1,86 @@
|
||||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
--color-background-mute: var(--vt-c-white-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition:
|
||||
color 0.5s,
|
||||
background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family:
|
||||
Inter,
|
||||
-apple-system,
|
||||
BlinkMacSystemFont,
|
||||
'Segoe UI',
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
'Fira Sans',
|
||||
'Droid Sans',
|
||||
'Helvetica Neue',
|
||||
sans-serif;
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
53
web/src/assets/items.json
Normal file
53
web/src/assets/items.json
Normal file
@@ -0,0 +1,53 @@
|
||||
[{"resId":3,"name":"经验","useType":1},
|
||||
{"resId":6,"name":"钻石","useType":1},
|
||||
{"resId":7,"name":"金币","useType":1},
|
||||
{"resId":8,"name":"洗炼石","useType":1},
|
||||
{"resId":9,"name":"体力","useType":1},
|
||||
{"resId":10,"name":"充值币","useType":1},
|
||||
{"resId":10002,"name":"发冠升级图纸","useType":1},
|
||||
{"resId":10003,"name":"道袍升级图纸","useType":1},
|
||||
{"resId":10004,"name":"项链升级图纸","useType":1},
|
||||
{"resId":10005,"name":"戒指升级图纸","useType":1},
|
||||
{"resId":10006,"name":"靴子升级图纸","useType":1},
|
||||
{"resId":10007,"name":"新手道书","useType":1},
|
||||
{"resId":10008,"name":"五色土","useType":1},
|
||||
{"resId":10009,"name":"女娲石","useType":1},
|
||||
{"resId":10010,"name":"突破丹","useType":1},
|
||||
{"resId":10011,"name":"随机装备图纸","useType":2},
|
||||
{"resId":10012,"name":"随机技能卷轴","useType":4},
|
||||
{"resId":10013,"name":"随机宝石箱子","useType":3},
|
||||
{"resId":10014,"name":"普通宝石箱","useType":3},
|
||||
{"resId":10015,"name":"璀璨宝石箱","useType":3},
|
||||
{"resId":10016,"name":"随机紫色宝石宝箱","useType":3},
|
||||
{"resId":10017,"name":"随机金色宝石宝箱","useType":3},
|
||||
{"resId":10018,"name":"随机红色宝石宝箱","useType":3},
|
||||
{"resId":10019,"name":"随机多彩宝石宝箱","useType":3},
|
||||
{"resId":10020,"name":"宝石抽取券","useType":1},
|
||||
{"resId":10021,"name":"灵宠抽取券","useType":1},
|
||||
{"resId":10022,"name":"随机宝石箱子","useType":3},
|
||||
{"resId":10023,"name":"随机稀有宝石","useType":3},
|
||||
{"resId":10024,"name":"随机宝石箱子","useType":3},
|
||||
{"resId":10101,"name":"御剑术卷轴","useType":1},
|
||||
{"resId":10102,"name":"毒气弹卷轴","useType":1},
|
||||
{"resId":10103,"name":"寒冰箭卷轴","useType":1},
|
||||
{"resId":10104,"name":"惊雷咒卷轴","useType":1},
|
||||
{"resId":10105,"name":"石狮子卷轴","useType":1},
|
||||
{"resId":10106,"name":"剑气斩卷轴","useType":1},
|
||||
{"resId":10107,"name":"万剑诀卷轴","useType":1},
|
||||
{"resId":10108,"name":"寒冰突刺卷轴","useType":1},
|
||||
{"resId":10109,"name":"连环闪电卷轴","useType":1},
|
||||
{"resId":10110,"name":"泰山压顶卷轴","useType":1},
|
||||
{"resId":10111,"name":"风暴术卷轴","useType":1},
|
||||
{"resId":10112,"name":"天雷网卷轴","useType":1},
|
||||
{"resId":10113,"name":"巨石突刺卷轴","useType":1},
|
||||
{"resId":10114,"name":"旋风术卷轴","useType":1},
|
||||
{"resId":10115,"name":"闪电球卷轴","useType":1},
|
||||
{"resId":10116,"name":"改名卡","useType":1},
|
||||
{"resId":10117,"name":"随机宝石箱子","useType":1},
|
||||
{"resId":10118,"name":"随机蓝色宝石宝箱","useType":3},
|
||||
{"resId":10119,"name":"晶石掉落","useType":1},
|
||||
{"resId":10120,"name":"技能卷轴自选宝箱","useType":5},
|
||||
{"resId":10121,"name":"灵宠口粮","useType":1},
|
||||
{"resId":10122,"name":"灵宠抽卡箱","useType":1},
|
||||
{"resId":10123,"name":"灵宠口粮","useType":1},
|
||||
{"resId":10999,"name":"1元代金券","useType":1}]
|
||||
1
web/src/assets/logo.svg
Normal file
1
web/src/assets/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||
|
After Width: | Height: | Size: 276 B |
22
web/src/assets/main.css
Normal file
22
web/src/assets/main.css
Normal file
@@ -0,0 +1,22 @@
|
||||
@import './base.css';
|
||||
|
||||
#app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
15
web/src/main.js
Normal file
15
web/src/main.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(router)
|
||||
app.use(ElementPlus)
|
||||
|
||||
app.mount('#app')
|
||||
15
web/src/router/index.js
Normal file
15
web/src/router/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import HomeView from '../views/HomeView.vue'
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: HomeView,
|
||||
}
|
||||
],
|
||||
})
|
||||
|
||||
export default router
|
||||
162
web/src/views/HomeView.vue
Normal file
162
web/src/views/HomeView.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import axios from 'axios'
|
||||
import itemList from "@/assets/items.json"
|
||||
import dayjs from 'dayjs'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
|
||||
// 第一个卡片:表单数据
|
||||
const gmFormRef = ref()
|
||||
const form = ref({
|
||||
playerName: '',
|
||||
item: '',
|
||||
itemNum: '',
|
||||
recharge: ''
|
||||
})
|
||||
const items = ref(itemList)
|
||||
const recharges = ref(['充值1', '充值2', '充值3'])
|
||||
|
||||
// 第二个卡片:角色表格数据
|
||||
const roleList = ref([])
|
||||
const roleSearch = ref('')
|
||||
const fetchRoleList = async () => {
|
||||
try {
|
||||
const response = await axios.get('/api/roles', {
|
||||
params: { search: roleSearch.value }
|
||||
})
|
||||
roleList.value = response.data.map(e => {
|
||||
e.lastLoginTime = dayjs(e.lastLoginTime).format("YYYY-MM-DD HH:mm:ss")
|
||||
e.createTime = dayjs(e.createTime).format("YYYY-MM-DD HH:mm:ss")
|
||||
return { ...e }
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('获取角色列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 第三个卡片:充值流水表格数据
|
||||
const rechargeList = ref([])
|
||||
const rechargeSearch = ref('')
|
||||
const fetchRechargeList = async () => {
|
||||
try {
|
||||
const response = await axios.get('/api/recharges', {
|
||||
params: { search: rechargeSearch.value }
|
||||
})
|
||||
rechargeList.value = response.data
|
||||
} catch (error) {
|
||||
console.error('获取充值流水失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载时初始化数据
|
||||
onMounted(() => {
|
||||
fetchRoleList()
|
||||
fetchRechargeList()
|
||||
})
|
||||
|
||||
// 提交表单
|
||||
const submitForm = (formEl) => {
|
||||
formEl.validate().then(async () => {
|
||||
const params = form.value
|
||||
const res = await axios.post("/api/item/send", { roleName: params.playerName, itemId: params.item, itemNum: params.itemNum })
|
||||
const result = res?.data
|
||||
if (res.data.code == 0) ElMessage.success(result.msg)
|
||||
else ElMessage.error(result.msg)
|
||||
})
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="home-container">
|
||||
<!-- 第一个卡片:表单 -->
|
||||
<el-card class="card-item">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>GM操作台</span>
|
||||
<el-button type="primary" @click="submitForm(gmFormRef)">提交</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<el-form ref="gmFormRef" :model="form" label-width="100px">
|
||||
<div class="grid grid-cols-2">
|
||||
<el-form-item label="玩家角色名" prop="playerName" required>
|
||||
<el-input v-model="form.playerName" placeholder="请输入玩家角色名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="物品道具" prop="item">
|
||||
<el-select-v2 v-model="form.item" placeholder="请选择物品" :options="items"
|
||||
:props="{ label: 'name', value: 'resId' }" filterable />
|
||||
</el-form-item>
|
||||
<el-form-item label="物品数量" prop="itemNum">
|
||||
<el-input type="number" v-model="form.itemNum" placeholder="请输入发送的物品数量"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="充值" prop="recharges">
|
||||
<el-select v-model="form.recharge" placeholder="请选择充值">
|
||||
<el-option v-for="recharge in recharges" :key="recharge" :label="recharge" :value="recharge"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 第二个卡片:角色表格 -->
|
||||
<el-card class="card-item">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>角色列表</span>
|
||||
<el-input style="width: 240px;" v-model="roleSearch" placeholder="请输入角色名称或ID" @change="fetchRoleList"
|
||||
clearable />
|
||||
</div>
|
||||
</template>
|
||||
<el-table :data="roleList" style="width: 100%" border height="400">
|
||||
<el-table-column prop="id" label="ID"></el-table-column>
|
||||
<el-table-column prop="name" label="角色名称"></el-table-column>
|
||||
<el-table-column prop="lv" label="等级"></el-table-column>
|
||||
<el-table-column prop="lastLoginTime" label="上次登录" width="220" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="220" />
|
||||
<el-table-column label="是否禁用">
|
||||
<template v-slot="{ row }">
|
||||
<el-switch v-model="row.ban" disabled />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 第三个卡片:充值流水表格 -->
|
||||
<el-card class="card-item">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>充值流水</span>
|
||||
<el-input style="width: 240px;" v-model="rechargeSearch" placeholder="请输入角色名称或流水单号"
|
||||
@input="fetchRechargeList"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
<el-table :data="rechargeList" style="width: 100%" border>
|
||||
<el-table-column prop="id" label="流水单号" width="180"></el-table-column>
|
||||
<el-table-column prop="roleName" label="角色名称" width="180"></el-table-column>
|
||||
<el-table-column prop="amount" label="充值金额"></el-table-column>
|
||||
<el-table-column prop="time" label="充值时间"></el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.home-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
27
web/vite.config.js
Normal file
27
web/vite.config.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import { defineConfig } from 'vite'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
// https://vite.dev/config/
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [vue(), vueJsx(), vueDevTools()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
// 使用 import.meta.env.VITE_WEB_PORT 来读取 .env 文件中的环境变量
|
||||
port: 3000,
|
||||
// 新增正向代理配置
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://127.0.0.1:8080',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user