Files
jiu/web/login.njk
T
wangjia c7de728c18 feat(site): 导航登录态下拉菜单 + 个人信息/退出登录页,登录不再直跳 App
- 导航「进入系统 · 名字」改为下拉:个人信息 / 进入系统 / 退出登录,导航可重入刷新(window.jiuNavRender)
- 新增 /profile/(账号 / 门店 / 授权三卡,authFetch 实时拉取)与 /logout/(撤销会话 + 清本地凭证)
- 登录成功默认落地 /profile/(?next= 站内白名单不变),不再直跳 /app/
- auth.js 增加 jiuAuth.clear();site.css 含本轮下拉 / profile / 特惠卡样式

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-03 22:24:55 +08:00

92 lines
4.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
layout: base.njk
title: 登录
description: 登录岩美酒库管理系统。
permalink: /login/
---
{# 官网内登录(不跳 App):POST /api/v1/auth/login,成功后把凭证写入与
Web 版 Appshared_preferences_web)共享的 localStorage['flutter.*']
(值为 JSON 编码,与插件格式一致),默认落地 /profile/;后续打开 /app/ 即已登录。 #}
<div class="auth-wrap">
<div class="auth">
<div class="auth-brand">
<img class="mk" src="/assets/logo-mark.svg" alt="岩美酒库" />
<div class="bname">岩美酒库</div>
<div class="btag">酒水进销存 · 审核驱动业务流</div>
<div class="pts">
<div class="pt"><span class="pi"><svg class="ic"><use href="#i-box"/></svg></span>入库出库 · 审核后实时改库存</div>
<div class="pt"><span class="pi"><svg class="ic"><use href="#i-ic08"/></svg></span>往来对账 · 财务一目了然</div>
<div class="pt"><span class="pi"><svg class="ic"><use href="#i-ic23"/></svg></span>多端协同 · 多租户安全隔离</div>
</div>
</div>
<div class="auth-form">
<h1>登录</h1>
<p class="alead">欢迎回来,请输入账号信息</p>
<div class="auth-alert" id="loginErr"></div>
<div class="field"><label>门店编号<span class="req">*</span></label><input class="input" id="shop" placeholder="例如 S000001" autocomplete="organization" /></div>
<div class="field"><label>登录账号<span class="req">*</span></label><input class="input" id="user" placeholder="请输入登录账号" autocomplete="username" /></div>
<div class="field"><label>密码<span class="req">*</span></label><input class="input" id="pass" type="password" placeholder="请输入密码" autocomplete="current-password" /></div>
<button class="btn primary lg" id="loginBtn" style="margin-top:8px">登 录</button>
<div class="auth-foot">还没有门店账号?<a href="/register/" style="font-weight:600">注册新门店 →</a></div>
<div class="auth-foot" style="margin-top:6px;color:var(--faint);font-size:var(--fs-xs)">岩美酒库 © 2026 · 仅授权门店可登录</div>
</div>
</div>
</div>
<script>
(function () {
var API = '{{ site.appBaseUrl }}';
function $(id) { return document.getElementById(id); }
function showErr(msg) { var el = $('loginErr'); el.textContent = msg; el.classList.add('show'); }
// 与 shared_preferences_web 同格式(值 JSON 编码),Web 版 App 可直接恢复会话
function persist(data, shopNo) {
var u = data.user || {};
var kv = {
access_token: data.access_token, refresh_token: data.refresh_token,
user_id: u.id || 0, username: u.username || '', real_name: u.real_name || '',
shop_no: shopNo, shop_id: String(data.shop_id || ''), role: u.role || 'operator',
};
Object.keys(kv).forEach(function (k) {
localStorage.setItem('flutter.' + k, JSON.stringify(kv[k]));
});
}
function doLogin() {
var shop = $('shop').value.trim(), user = $('user').value.trim(), pass = $('pass').value;
if (!shop) return showErr('请输入门店编号');
if (!user) return showErr('请输入登录账号');
if (!pass) return showErr('请输入密码');
$('loginErr').classList.remove('show');
var btn = $('loginBtn'); btn.disabled = true; btn.textContent = '登录中…';
fetch(API + '/api/v1/auth/login', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ shop_code: shop, username: user, password: pass }),
})
.then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
.then(function (res) {
if (!res.ok) throw new Error((res.j && res.j.error) || '登录失败,请检查账号信息');
persist(res.j.data || {}, shop);
// ?next= 仅允许站内路径(防开放跳转);默认留在官网(个人信息页),不跳 App
var next = new URLSearchParams(location.search).get('next') || '';
location.href = (next.charAt(0) === '/' && next.indexOf('//') !== 0) ? next : '/profile/';
})
.catch(function (e) {
showErr(e && e.message ? e.message : '无法连接服务器,请稍后重试');
btn.disabled = false; btn.textContent = '登 录';
});
}
// 登录过的浏览器回填门店编号/账号(token 过期重登时少敲两栏)
if (window.jiuAuth) {
var savedShop = jiuAuth.get('shop_no'), savedUser = jiuAuth.get('username');
if (savedShop && !$('shop').value) $('shop').value = savedShop;
if (savedUser && !$('user').value) $('user').value = savedUser;
}
$('loginBtn').addEventListener('click', doLogin);
['shop', 'user', 'pass'].forEach(function (id) {
$(id).addEventListener('keydown', function (e) { if (e.key === 'Enter') doLogin(); });
});
})();
</script>