feat: 重构服务支持双模式并接入 MongoDB 数据库
- 新增 MongoDB 存储层实现英雄、预设和版本数据的持久化 - 新增 push-meta 和 migrate-to-mongo 脚本支持数据同步迁移 - 支持开发版和线上设计版双模式运行 - 新增版本闸门机制,线上设计版落后时进入只读模式 - 优化前端 API 配置适配不同部署环境 - 新增线上设计版静态资源托管和路由回退
This commit is contained in:
88
put/web/dist/assets/index-CZTxENXL.js
vendored
Normal file
88
put/web/dist/assets/index-CZTxENXL.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
put/web/dist/assets/index-Dzv_EDk3.css
vendored
Normal file
1
put/web/dist/assets/index-Dzv_EDk3.css
vendored
Normal file
File diff suppressed because one or more lines are too long
13
put/web/dist/index.html
vendored
Normal file
13
put/web/dist/index.html
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>英雄配置编辑器</title>
|
||||
<script type="module" crossorigin src="/assets/index-CZTxENXL.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Dzv_EDk3.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +1,33 @@
|
||||
<template>
|
||||
<div class="hero-app">
|
||||
<header class="hero-header">
|
||||
<h1>英雄配置编辑器</h1>
|
||||
<h1>
|
||||
英雄配置编辑器
|
||||
<el-tag size="small" :type="isDev ? 'success' : 'warning'" effect="plain">
|
||||
{{ isDev ? '项目开发版' : '线上设计版' }} v{{ meta?.schemaVersion ?? '-' }}
|
||||
</el-tag>
|
||||
</h1>
|
||||
<div class="actions">
|
||||
<el-radio-group v-model="view" size="small">
|
||||
<el-radio-button value="heroes">英雄列表</el-radio-button>
|
||||
<el-radio-button value="templates">预设库</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-button size="small" @click="refreshMeta" :loading="loadingMeta">刷新配置数据</el-button>
|
||||
<el-button size="small" type="success" @click="doSave" :disabled="!heroes.length">保存到服务器</el-button>
|
||||
<el-button size="small" type="primary" @click="doApply" :disabled="!heroes.length">写入 heroSet.ts</el-button>
|
||||
<el-button size="small" type="danger" @click="doExportCsv" :disabled="!heroes.length">导出英雄设计表.csv</el-button>
|
||||
<el-button size="small" type="success" @click="doSave" :disabled="!heroes.length || outdated">保存到数据库</el-button>
|
||||
<template v-if="isDev">
|
||||
<el-button size="small" type="primary" @click="doApply" :disabled="!heroes.length">写入 heroSet.ts</el-button>
|
||||
<el-button size="small" type="danger" @click="doExportCsv" :disabled="!heroes.length">导出英雄设计表.csv</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</header>
|
||||
<el-alert
|
||||
v-if="outdated"
|
||||
type="error"
|
||||
:closable="false"
|
||||
show-icon
|
||||
:title="`数据库结构已升级到 v${meta.dbSchemaVersion},当前线上设计版(v${meta.schemaVersion})已切换为只读,请更新部署后再修改`"
|
||||
style="margin-bottom: 8px"
|
||||
/>
|
||||
<div class="hero-main">
|
||||
<!-- 预设库视图 -->
|
||||
<TemplateManager
|
||||
@@ -252,6 +267,10 @@ const editVisible = ref(false)
|
||||
|
||||
const current = computed(() => heroes.value[activeIdx.value])
|
||||
|
||||
// 版本/模式:isDev 区分开发版全功能;outdated 时线上设计版只读
|
||||
const isDev = computed(() => meta.value?.mode === 'local')
|
||||
const outdated = computed(() => (meta.value?.dbSchemaVersion ?? 0) > (meta.value?.schemaVersion ?? 0))
|
||||
|
||||
// 首页列表排序:none 原始顺序 / role 按职业枚举序(坦克→辅助)/ rarity 按星级
|
||||
const sortKey = ref('none')
|
||||
const sortOrder = ref('desc')
|
||||
@@ -510,7 +529,7 @@ async function loadTemplates() {
|
||||
async function doSave() {
|
||||
try {
|
||||
const r = await api.saveHeroes(heroes.value)
|
||||
ElMessage.success(`已保存 ${r.count} 个英雄 → ${r.path}`)
|
||||
ElMessage.success(`已保存 ${r.count} 个英雄到数据库`)
|
||||
} catch (e) {
|
||||
ElMessage.error('保存失败: ' + (e?.response?.data?.error || e.message))
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import axios from 'axios'
|
||||
|
||||
// 开发环境走 vite 代理(留空即可);部署静态站点时用 VITE_API_BASE 指向后端服务
|
||||
const baseURL = import.meta.env.VITE_API_BASE || ''
|
||||
const http = axios.create({ baseURL })
|
||||
|
||||
export const api = {
|
||||
meta: () => axios.get('/api/meta').then((r) => r.data),
|
||||
refresh: () => axios.post('/api/refresh').then((r) => r.data),
|
||||
fetchHeroes: () => axios.get('/api/heroes').then((r) => r.data),
|
||||
saveHeroes: (heroes) => axios.post('/api/heroes', { heroes }).then((r) => r.data),
|
||||
applyHeroes: (heroes) => axios.post('/api/apply', { heroes }).then((r) => r.data),
|
||||
exportCsv: (heroes) => axios.post('/api/export-csv', { heroes }).then((r) => r.data),
|
||||
fetchTemplates: () => axios.get('/api/templates').then((r) => r.data),
|
||||
saveTemplates: (templates) => axios.post('/api/templates', { templates }).then((r) => r.data),
|
||||
meta: () => http.get('/api/meta').then((r) => r.data),
|
||||
refresh: () => http.post('/api/refresh').then((r) => r.data),
|
||||
fetchHeroes: () => http.get('/api/heroes').then((r) => r.data),
|
||||
saveHeroes: (heroes) => http.post('/api/heroes', { heroes }).then((r) => r.data),
|
||||
applyHeroes: (heroes) => http.post('/api/apply', { heroes }).then((r) => r.data),
|
||||
exportCsv: (heroes) => http.post('/api/export-csv', { heroes }).then((r) => r.data),
|
||||
fetchTemplates: () => http.get('/api/templates').then((r) => r.data),
|
||||
saveTemplates: (templates) => http.post('/api/templates', { templates }).then((r) => r.data),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user