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": { | ||||
|         "axios": "^1.8.4", | ||||
|         "body-parser": "^2.2.0", | ||||
|         "dotenv": "^16.5.0", | ||||
|         "express": "^5.1.0", | ||||
|         "mysql": "^2.18.1", | ||||
| @@ -4755,6 +4756,7 @@ | ||||
|     "web": { | ||||
|       "version": "0.0.0", | ||||
|       "dependencies": { | ||||
|         "dayjs": "^1.11.13", | ||||
|         "element-plus": "^2.9.8", | ||||
|         "vue": "^3.5.13", | ||||
|         "vue-router": "^4.5.0" | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
|   "license": "ISC", | ||||
|   "dependencies": { | ||||
|     "axios": "^1.8.4", | ||||
|     "body-parser": "^2.2.0", | ||||
|     "dotenv": "^16.5.0", | ||||
|     "express": "^5.1.0", | ||||
|     "mysql": "^2.18.1", | ||||
|   | ||||
| @@ -1,29 +1,66 @@ | ||||
| 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) => { | ||||
| router.get("/roles", async (req, res) => { | ||||
|   try { | ||||
|     const { search = "" } = req.query; | ||||
|     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); | ||||
|   } catch (error) { | ||||
|         console.error('获取角色数据失败:', error); | ||||
|         res.status(500).json({ 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) => { | ||||
| router.get("/recharges", async (req, res) => { | ||||
|   try { | ||||
|     const connection = await getConnection(); | ||||
|         const results = await query('SELECT * FROM recharge', [], connection); | ||||
|     const results = await query("SELECT * FROM recharge", [], connection); | ||||
|     res.json(results); | ||||
|   } catch (error) { | ||||
|         console.error('获取充值列表失败:', error); | ||||
|         res.status(500).json({ error: '获取充值列表失败' }); | ||||
|     console.error("获取充值列表失败:", error); | ||||
|     res.status(500).json({ error: "获取充值列表失败" }); | ||||
|   } | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
|     "format": "prettier --write src/" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "dayjs": "^1.11.13", | ||||
|     "element-plus": "^2.9.8", | ||||
|     "vue": "^3.5.13", | ||||
|     "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> | ||||
| 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(['物品1', '物品2', '物品3']) | ||||
| const items = ref(itemList) | ||||
| const recharges = ref(['充值1', '充值2', '充值3']) | ||||
|  | ||||
| // 第二个卡片:角色表格数据 | ||||
| @@ -16,10 +22,14 @@ const roleList = ref([]) | ||||
| const roleSearch = ref('') | ||||
| const fetchRoleList = async () => { | ||||
|   try { | ||||
|     const response = await axios.get('/api/role', { | ||||
|     const response = await axios.get('/api/roles', { | ||||
|       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) { | ||||
|     console.error('获取角色列表失败:', error) | ||||
|   } | ||||
| @@ -30,7 +40,7 @@ const rechargeList = ref([]) | ||||
| const rechargeSearch = ref('') | ||||
| const fetchRechargeList = async () => { | ||||
|   try { | ||||
|     const response = await axios.get('/api/recharge', { | ||||
|     const response = await axios.get('/api/recharges', { | ||||
|       params: { search: rechargeSearch.value } | ||||
|     }) | ||||
|     rechargeList.value = response.data | ||||
| @@ -46,8 +56,15 @@ onMounted(() => { | ||||
| }) | ||||
|  | ||||
| // 提交表单 | ||||
| const submitForm = () => { | ||||
|   console.log('提交表单:', form.value) | ||||
| 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> | ||||
|  | ||||
| @@ -58,31 +75,27 @@ const submitForm = () => { | ||||
|       <template #header> | ||||
|         <div class="card-header"> | ||||
|           <span>GM操作台</span> | ||||
|           <el-button type="primary" @click="submitForm">提交</el-button> | ||||
|           <el-button type="primary" @click="submitForm(gmFormRef)">提交</el-button> | ||||
|         </div> | ||||
|       </template> | ||||
|       <el-form :model="form" label-width="100px"> | ||||
|         <el-row :gutter="20"> | ||||
|           <el-col :span="8"> | ||||
|             <el-form-item label="玩家角色名"> | ||||
|       <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-col> | ||||
|           <el-col :span="8"> | ||||
|             <el-form-item label="物品道具"> | ||||
|               <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 label="物品道具" prop="item"> | ||||
|             <el-select-v2 v-model="form.item" placeholder="请选择物品" :options="items" | ||||
|               :props="{ label: 'name', value: 'resId' }" filterable /> | ||||
|           </el-form-item> | ||||
|           </el-col> | ||||
|           <el-col :span="8"> | ||||
|             <el-form-item label="充值"> | ||||
|           <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> | ||||
|           </el-col> | ||||
|         </el-row> | ||||
|         </div> | ||||
|       </el-form> | ||||
|     </el-card> | ||||
|  | ||||
| @@ -91,13 +104,21 @@ const submitForm = () => { | ||||
|       <template #header> | ||||
|         <div class="card-header"> | ||||
|           <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> | ||||
|       </template> | ||||
|       <el-table :data="roleList" style="width: 100%" border> | ||||
|         <el-table-column prop="id" label="ID" width="180"></el-table-column> | ||||
|         <el-table-column prop="name" label="角色名称" width="180"></el-table-column> | ||||
|         <el-table-column prop="level" label="等级"></el-table-column> | ||||
|       <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> | ||||
|  | ||||
| @@ -106,7 +127,8 @@ const submitForm = () => { | ||||
|       <template #header> | ||||
|         <div class="card-header"> | ||||
|           <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> | ||||
|       </template> | ||||
|       <el-table :data="rechargeList" style="width: 100%" border> | ||||
| @@ -127,9 +149,11 @@ const submitForm = () => { | ||||
|   gap: 20px; | ||||
|   padding: 20px; | ||||
| } | ||||
|  | ||||
| .card-item { | ||||
|   width: 100%; | ||||
| } | ||||
|  | ||||
| .card-header { | ||||
|   display: flex; | ||||
|   justify-content: space-between; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user