Files
jiu/web/login.njk
T
wangjia d256e7ac85 feat(site): 官网全新重建(App 真相源风格)+ 四档套餐 + 在线购买流
- tokens.css/site.css 逐值对齐原型设计系统,icons 雪碧图,零外链;首页/下载/帮助/法务全站重皮肤,真实截图
- 注册与登录在官网内完成(写 shared_preferences_web 兼容 localStorage,不再跳 App)
- 价格区四档:免费/标准 299/高级 599/定制;登录后标准/高级按钮变「购买 / 续费」
- 新增 /checkout/(套餐+月付年付切换)与 /license/result/(支付回跳轮询到账)
- 登录页支持 ?next= 站内回跳;二维码措辞改「扫码看详情可分享」
- 下载页构建期真实下载链接+运行时 release 刷新;旧 features 页/死 CSS/dist 产物清理

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

85 lines
4.4 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 编码,与插件格式一致),再进入 /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= 仅允许站内路径(防开放跳转)
var next = new URLSearchParams(location.search).get('next') || '';
location.href = (next.charAt(0) === '/' && next.indexOf('//') !== 0) ? next : '/app/';
})
.catch(function (e) {
showErr(e && e.message ? e.message : '无法连接服务器,请稍后重试');
btn.disabled = false; btn.textContent = '登 录';
});
}
$('loginBtn').addEventListener('click', doLogin);
['shop', 'user', 'pass'].forEach(function (id) {
$(id).addEventListener('keydown', function (e) { if (e.key === 'Enter') doLogin(); });
});
})();
</script>