Compare commits
5 Commits
278684d3ff
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 34cebffd0c | |||
| 7cc37b0523 | |||
| 7f1d475af9 | |||
| 09302848c9 | |||
| 26bd2029e7 |
2
package-lock.json
generated
2
package-lock.json
generated
@@ -13,6 +13,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
|
"body-parser": "^2.2.0",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^16.5.0",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
@@ -4755,6 +4756,7 @@
|
|||||||
"web": {
|
"web": {
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"element-plus": "^2.9.8",
|
"element-plus": "^2.9.8",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-router": "^4.5.0"
|
"vue-router": "^4.5.0"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
|
"body-parser": "^2.2.0",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^16.5.0",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
|
|||||||
@@ -1,29 +1,66 @@
|
|||||||
const express = require('express');
|
const express = require("express");
|
||||||
const { getConnection, query } = require('../utils/db.util');
|
const bodyParser = require("body-parser"); // 添加 body-parser 中间件
|
||||||
|
const { getConnection, query } = require("../utils/db.util");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
// 添加 body-parser 中间件
|
||||||
|
router.use(bodyParser.json());
|
||||||
|
|
||||||
// 获取角色列表
|
// 获取角色列表
|
||||||
router.get('/roles', async (req, res) => {
|
router.get("/roles", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
const { search = "" } = req.query;
|
||||||
const connection = await getConnection();
|
const connection = await getConnection();
|
||||||
const results = await query('SELECT * FROM role', [], connection);
|
const results = await query(`SELECT * FROM role where name like '%${search}%'`, [], connection);
|
||||||
res.json(results);
|
res.json(results);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取角色数据失败:', error);
|
console.error("获取角色数据失败:", error);
|
||||||
res.status(500).json({ 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) => {
|
router.get("/recharges", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const connection = await getConnection();
|
const connection = await getConnection();
|
||||||
const results = await query('SELECT * FROM recharge', [], connection);
|
const results = await query("SELECT * FROM recharge", [], connection);
|
||||||
res.json(results);
|
res.json(results);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取充值列表失败:', error);
|
console.error("获取充值列表失败:", error);
|
||||||
res.status(500).json({ error: '获取充值列表失败' });
|
res.status(500).json({ error: "获取充值列表失败" });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"format": "prettier --write src/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"dayjs": "^1.11.13",
|
||||||
"element-plus": "^2.9.8",
|
"element-plus": "^2.9.8",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vue-router": "^4.5.0"
|
"vue-router": "^4.5.0"
|
||||||
|
|||||||
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,14 +1,20 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import axios from 'axios'
|
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({
|
const form = ref({
|
||||||
playerName: '',
|
playerName: '',
|
||||||
item: '',
|
item: '',
|
||||||
|
itemNum: '',
|
||||||
recharge: ''
|
recharge: ''
|
||||||
})
|
})
|
||||||
const items = ref(['物品1', '物品2', '物品3'])
|
const items = ref(itemList)
|
||||||
const recharges = ref(['充值1', '充值2', '充值3'])
|
const recharges = ref(['充值1', '充值2', '充值3'])
|
||||||
|
|
||||||
// 第二个卡片:角色表格数据
|
// 第二个卡片:角色表格数据
|
||||||
@@ -16,10 +22,14 @@ const roleList = ref([])
|
|||||||
const roleSearch = ref('')
|
const roleSearch = ref('')
|
||||||
const fetchRoleList = async () => {
|
const fetchRoleList = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('/api/role', {
|
const response = await axios.get('/api/roles', {
|
||||||
params: { search: roleSearch.value }
|
params: { search: roleSearch.value }
|
||||||
})
|
})
|
||||||
roleList.value = response.data
|
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) {
|
} catch (error) {
|
||||||
console.error('获取角色列表失败:', error)
|
console.error('获取角色列表失败:', error)
|
||||||
}
|
}
|
||||||
@@ -30,7 +40,7 @@ const rechargeList = ref([])
|
|||||||
const rechargeSearch = ref('')
|
const rechargeSearch = ref('')
|
||||||
const fetchRechargeList = async () => {
|
const fetchRechargeList = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get('/api/recharge', {
|
const response = await axios.get('/api/recharges', {
|
||||||
params: { search: rechargeSearch.value }
|
params: { search: rechargeSearch.value }
|
||||||
})
|
})
|
||||||
rechargeList.value = response.data
|
rechargeList.value = response.data
|
||||||
@@ -46,8 +56,15 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const submitForm = () => {
|
const submitForm = (formEl) => {
|
||||||
console.log('提交表单:', form.value)
|
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>
|
</script>
|
||||||
|
|
||||||
@@ -58,31 +75,27 @@ const submitForm = () => {
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>GM操作台</span>
|
<span>GM操作台</span>
|
||||||
<el-button type="primary" @click="submitForm">提交</el-button>
|
<el-button type="primary" @click="submitForm(gmFormRef)">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-form :model="form" label-width="100px">
|
<el-form ref="gmFormRef" :model="form" label-width="100px">
|
||||||
<el-row :gutter="20">
|
<div class="grid grid-cols-2">
|
||||||
<el-col :span="8">
|
<el-form-item label="玩家角色名" prop="playerName" required>
|
||||||
<el-form-item label="玩家角色名">
|
|
||||||
<el-input v-model="form.playerName" placeholder="请输入玩家角色名"></el-input>
|
<el-input v-model="form.playerName" placeholder="请输入玩家角色名"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
<el-form-item label="物品道具" prop="item">
|
||||||
<el-col :span="8">
|
<el-select-v2 v-model="form.item" placeholder="请选择物品" :options="items"
|
||||||
<el-form-item label="物品道具">
|
:props="{ label: 'name', value: 'resId' }" filterable />
|
||||||
<el-select v-model="form.item" placeholder="请选择物品">
|
|
||||||
<el-option v-for="item in items" :key="item" :label="item" :value="item"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
<el-form-item label="物品数量" prop="itemNum">
|
||||||
<el-col :span="8">
|
<el-input type="number" v-model="form.itemNum" placeholder="请输入发送的物品数量"></el-input>
|
||||||
<el-form-item label="充值">
|
</el-form-item>
|
||||||
|
<el-form-item label="充值" prop="recharges">
|
||||||
<el-select v-model="form.recharge" placeholder="请选择充值">
|
<el-select v-model="form.recharge" placeholder="请选择充值">
|
||||||
<el-option v-for="recharge in recharges" :key="recharge" :label="recharge" :value="recharge"></el-option>
|
<el-option v-for="recharge in recharges" :key="recharge" :label="recharge" :value="recharge"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</div>
|
||||||
</el-row>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
@@ -91,13 +104,21 @@ const submitForm = () => {
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>角色列表</span>
|
<span>角色列表</span>
|
||||||
<el-input style="width: 240px;" v-model="roleSearch" placeholder="请输入角色名称或ID" @input="fetchRoleList"></el-input>
|
<el-input style="width: 240px;" v-model="roleSearch" placeholder="请输入角色名称或ID" @change="fetchRoleList"
|
||||||
|
clearable />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-table :data="roleList" style="width: 100%" border>
|
<el-table :data="roleList" style="width: 100%" border height="400">
|
||||||
<el-table-column prop="id" label="ID" width="180"></el-table-column>
|
<el-table-column prop="id" label="ID"></el-table-column>
|
||||||
<el-table-column prop="name" label="角色名称" width="180"></el-table-column>
|
<el-table-column prop="name" label="角色名称"></el-table-column>
|
||||||
<el-table-column prop="level" 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-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
@@ -106,7 +127,8 @@ const submitForm = () => {
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span>充值流水</span>
|
<span>充值流水</span>
|
||||||
<el-input style="width: 240px;" v-model="rechargeSearch" placeholder="请输入角色名称或流水单号" @input="fetchRechargeList"></el-input>
|
<el-input style="width: 240px;" v-model="rechargeSearch" placeholder="请输入角色名称或流水单号"
|
||||||
|
@input="fetchRechargeList"></el-input>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-table :data="rechargeList" style="width: 100%" border>
|
<el-table :data="rechargeList" style="width: 100%" border>
|
||||||
@@ -127,9 +149,11 @@ const submitForm = () => {
|
|||||||
gap: 20px;
|
gap: 20px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-item {
|
.card-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-header {
|
.card-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
Reference in New Issue
Block a user