diff --git a/addons/game_base/controllers/game_api.py b/addons/game_base/controllers/game_api.py index 02ecff3..db230ca 100644 --- a/addons/game_base/controllers/game_api.py +++ b/addons/game_base/controllers/game_api.py @@ -297,6 +297,8 @@ class GameApiController(http.Controller): User = request.env['res.users'].sudo() if User.search([('login', '=', login)]): return _json({'ok': False, 'error': '该账号已存在'}) + if name and User.search([('name', '=', name)]): + return _json({'ok': False, 'error': '该昵称已被使用'}) try: portal = request.env.ref('base.group_portal') user = User.create({ diff --git a/assets/game-api.js b/assets/game-api.js index ecae512..03fbe5a 100644 --- a/assets/game-api.js +++ b/assets/game-api.js @@ -1,8 +1,8 @@ // 宇森游戏 · 前端与 Odoo 通信层 // 本地调试:前端 8888 -> Odoo 8069(跨域,带调试 CORS 头) // 生产部署:前端与 Odoo 同域,由 nginx 代理 /game/*。 -// 说明:odoo.conf 已 db_name=yt_game 钉死库,URL 上的 ?db= 形同虚设, -// 请求一律落到 yt_game;下列 game/* 沿用统一 API_CONFIG,yt_world/* 单独带 ?db=yt_game。 +// 库名说明:本地 Odoo 用 odoo.conf 钉死 yt_game;线上游戏库名为 game(dbfilter 不含 yt_game)。 +// game/* 走统一 API_CONFIG.db;yt_world/* 单独带 ?db=,按 WORLD_DB 区分本地/线上,避免 git 同步互相覆盖。 const API_CONFIG = { base: (location.hostname === '127.0.0.1' && location.port === '8888') @@ -13,6 +13,9 @@ const API_CONFIG = { db: (location.hostname === '127.0.0.1' && location.port === '8888') ? 'study' : 'game', }; +// 世界(yt_world)所在库:本地 Odoo 钉 yt_game;线上游戏库名为 game。按域名自适应,git 同步不冲突。 +const WORLD_DB = (location.hostname === '127.0.0.1' || location.hostname === 'localhost') ? 'yt_game' : 'game'; + const _cred = API_CONFIG.base ? 'include' : 'same-origin'; function _url(path) { @@ -68,17 +71,17 @@ const API = { }, // ---------- 沙盘记忆(yt_world 模块) ---------- async world() { - return (await fetch('/yt_world/api/world?db=yt_game', { credentials: 'same-origin' })).json(); + return (await fetch('/yt_world/api/world?db=' + WORLD_DB, { credentials: 'same-origin' })).json(); }, async saveTiles(tiles) { - return (await fetch('/yt_world/api/tiles/save?db=yt_game', { + return (await fetch('/yt_world/api/tiles/save?db=' + WORLD_DB, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tiles }), })).json(); }, async saveSettings(settings) { - return (await fetch('/yt_world/api/settings?db=yt_game', { + return (await fetch('/yt_world/api/settings?db=' + WORLD_DB, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ settings }), @@ -87,14 +90,14 @@ const API = { // ---------- 世界数据 / 包裹(后端接口预留:yt_world 暂未实现路由,前端 mock 兜底) ---------- async worldData() { try { - const r = await fetch('/yt_world/api/data?db=yt_game', { credentials: 'same-origin' }); + const r = await fetch('/yt_world/api/data?db=' + WORLD_DB, { credentials: 'same-origin' }); if (!r.ok) return null; return await r.json(); } catch (e) { return null; } }, async inventory() { try { - const r = await fetch('/yt_world/api/inventory?db=yt_game', { credentials: 'same-origin' }); + const r = await fetch('/yt_world/api/inventory?db=' + WORLD_DB, { credentials: 'same-origin' }); if (!r.ok) return null; return await r.json(); } catch (e) { return null; } diff --git a/login.html b/login.html index b2e7e16..83304f6 100644 --- a/login.html +++ b/login.html @@ -45,8 +45,9 @@ .field input:focus{border-color:var(--violet);box-shadow:0 0 0 3px rgba(139,92,246,.18);} .pw-wrap{position:relative;} .pw-wrap input{padding-right:40px;} - .pw-toggle{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:transparent;border:none;color:var(--text-dim);cursor:pointer;font-size:16px;line-height:1;padding:4px 6px;border-radius:6px;transition:.2s;} - .pw-toggle:hover{color:#fff;background:rgba(255,255,255,.08);} + .pw-toggle,.random-btn{position:absolute;right:8px;top:50%;transform:translateY(-50%);background:transparent;border:none;color:var(--text-dim);cursor:pointer;font-size:16px;line-height:1;padding:4px 6px;border-radius:6px;transition:.2s;} + .pw-toggle:hover,.random-btn:hover{color:#fff;background:rgba(255,255,255,.08);} + .random-btn{font-size:15px;} .submit{width:100%;margin-top:6px;font-size:15px;font-weight:700;color:#0b1020;background:linear-gradient(120deg,var(--gold),#f0d49a);padding:12px;border-radius:11px;cursor:pointer;border:none;letter-spacing:2px;transition:.22s;box-shadow:0 0 18px rgba(231,184,92,.35);} .submit:hover{filter:brightness(1.08);} @@ -75,7 +76,6 @@
宇森
YUSEN · GARDEN OF CIVILIZATION
-
你不是玩家,你是园丁。
@@ -108,7 +108,10 @@
- +
+ + +
@@ -124,7 +127,7 @@
- +
@@ -181,14 +184,18 @@ }); }); - // 昵称默认 = 账号:账号变更时若昵称仍空/等于上次账号值,则同步;用户改过昵称则保留 - const rLogin = document.getElementById('rLogin'); - const rName = document.getElementById('rName'); - let lastLoginVal = ''; - rLogin.addEventListener('input', () => { - const v = rLogin.value.trim(); - if (rName.value === '' || rName.value === lastLoginVal) rName.value = v; - lastLoginVal = v; + // 随机昵称生成 + const rName = document.getElementById('rName'); + const ADJ = ['云游','星尘','微光','风吟','夜语','深海','荒原','天穹','逐风','灵叶','虚境','晨星','暮雨','浮世','苍穹']; + const NOUN = ['旅者','观察者','行者','拾光人','园丁','筑梦师','游侠','学者','守夜人','引路人','浪人','渡鸦','白鹿']; + function randomName() { + const a = ADJ[Math.floor(Math.random() * ADJ.length)]; + const n = NOUN[Math.floor(Math.random() * NOUN.length)]; + const num = String(Math.floor(Math.random() * 9000) + 1000); + return a + n + num; + } + document.getElementById('randomNameBtn').addEventListener('click', () => { + rName.value = randomName(); }); loginForm.addEventListener('submit', async (e) => { @@ -230,7 +237,7 @@ } catch (err) { showMsg('网络错误,请稍后重试', 'err'); } finally { - btn.disabled = false; btn.textContent = '创建园丁账号'; + btn.disabled = false; btn.textContent = '创建账号'; } });