添加多语言支持

This commit is contained in:
cxykevin 2024-08-28 20:21:31 +08:00
parent ebe848cd8f
commit e9c8d2710f
10 changed files with 181 additions and 106 deletions

View File

@ -54,7 +54,6 @@ maxsize = 100 最大连接数
minsize = 10 最小连接数 minsize = 10 最小连接数
[common] [common]
algorithm = "HS256" 使用的加密算法
access_token_expire_minutes = 60 token过期时长min access_token_expire_minutes = 60 token过期时长min
access_email_expire_minutes = 10 注册邮件过期时长min access_email_expire_minutes = 10 注册邮件过期时长min
root = !这个帐号服务的域名,需要有 http(s):// root = !这个帐号服务的域名,需要有 http(s)://
@ -68,6 +67,25 @@ port = 465 邮件SMTP端口
addr = !邮箱 addr = !邮箱
passwd = !邮箱的授权码(部分情况就是密码,部分情况需要申请) passwd = !邮箱的授权码(部分情况就是密码,部分情况需要申请)
[ui]
prod_name = !显示的名称
title = !网页标题
manager_email = !管理员邮箱
bar_items = [
[
"开始学习",
"https://learn.study-area.org.cn",
],
[
"讨论区",
"https://forum.study-area.org.cn",
],
[
"查看本站源码",
"https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/",
],
] 电脑端左侧栏显示内容
``` ```
## 内置扩展 ## 内置扩展

View File

@ -1,3 +1,12 @@
[common]
lang = "zh_cn"
access_token_expire_minutes = 60
access_email_expire_minutes = 1
root = "http://127.0.0.1:8000"
clean_timeout = 3600
manage_key = "some_random_key_for_init"
redirect_url_whitelist = ["/user", "/login", "/signup", "127.0.0.1:8000"]
[db] [db]
host = "192.168.10.119" host = "192.168.10.119"
port = 3306 port = 3306
@ -7,21 +16,32 @@ db = "sacn_accout"
maxsize = 100 maxsize = 100
minsize = 10 minsize = 10
[common]
algorithm = "HS256"
access_token_expire_minutes = 60
access_email_expire_minutes = 1
root = "http://127.0.0.1:8000"
clean_timeout = 3600
manage_key = "some_random_key_for_init"
redirect_url_whitelist = ["/user", "/login", "/signup", "127.0.0.1:8000"]
[flarum]
fl_server = "http://127.0.0.1:4000"
fl_apikey = "some_long_key"
[email] [email]
smtp_srv = "smtp.qq.com" smtp_srv = "smtp.qq.com"
port = 465 port = 465
addr = "you_email" addr = "you_email"
passwd = "you_email_access_code" passwd = "you_email_access_code"
[ui]
prod_name = "StudyAreaCN"
title = "StuyAreaCN Account System"
manager_email = ""
bar_items = [
[
"开始学习",
"https://learn.study-area.org.cn",
],
[
"讨论区",
"https://forum.study-area.org.cn",
],
[
"查看本站源码",
"https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/",
],
]
[flarum]
fl_server = "http://127.0.0.1:4000"
fl_apikey = "some_long_key"

26
lang/zh_cn.toml Normal file
View File

@ -0,0 +1,26 @@
redirect = "正在跳转"
login = "登录"
signup = "注册"
username = "用户名"
password = "密码"
email = "邮箱"
reset_passwd = "重置密码"
check_passwd = "确认密码"
change_passwd = "更改密码"
passwd_not_same = "密码不一致"
change_info = "若需要注销或修改账户的邮箱,请发送邮件至"
forgot_password_info = "忘记密码?点我重置"
manage = "用户管理"
send_email = "发送邮件"
unedit_msg = "内容为空"
username_or_password_incorrect = "用户名或密码错误"
weak_passwd = "密码强度弱,请至少包含一个大小写字符与数字且长度>8"
invalid_email = "邮箱不合法"
verification_email = "验证邮件已发送到邮箱,请在{}分钟内完成验证"
username_exists = "用户名重复"
username_not_exists = "用户名不存在"
invalid_regid = "不存在的注册id"
invalid_checkid = "不存在的验证id"
created_successfully = "创建成功"
invalid_token = "token无效"
invalid_redirect_url = "无效的重定向URL"

View File

@ -1,9 +1,13 @@
import tomllib import tomllib
import os import os
with open("config/config.toml", "rb") as f: with open("config/config.toml", "rb") as f:
config = tomllib.load(f) config = tomllib.load(f)
with open(f"lang/{config["common"]["lang"]}.toml", "rb") as f:
lang = tomllib.load(f)
def reload(): def reload():
global config global config

View File

@ -21,7 +21,6 @@ import importlib
def load_cfg(): def load_cfg():
global ALGORITHM
global ACCESS_TOKEN_EXPIRE_MINUTES global ACCESS_TOKEN_EXPIRE_MINUTES
global ACCESS_EMAIL_EXPIRE_MINUTES global ACCESS_EMAIL_EXPIRE_MINUTES
global ROOT global ROOT
@ -29,7 +28,6 @@ def load_cfg():
global MANAGE_KEY global MANAGE_KEY
global REDIRECT_URL_WHITELIST global REDIRECT_URL_WHITELIST
ALGORITHM = cfg.config["common"]["algorithm"]
ACCESS_TOKEN_EXPIRE_MINUTES = cfg.config["common"]["access_token_expire_minutes"] ACCESS_TOKEN_EXPIRE_MINUTES = cfg.config["common"]["access_token_expire_minutes"]
ACCESS_EMAIL_EXPIRE_MINUTES = cfg.config["common"]["access_email_expire_minutes"] ACCESS_EMAIL_EXPIRE_MINUTES = cfg.config["common"]["access_email_expire_minutes"]
ROOT = cfg.config["common"]["root"] ROOT = cfg.config["common"]["root"]
@ -148,7 +146,7 @@ async def login_callback(response: Response, username: str = Form(), password: s
response.set_cookie("session", clean_uuid(tokennow)) response.set_cookie("session", clean_uuid(tokennow))
return {"msg": "", "key": clean_uuid(tkn)} return {"msg": "", "key": clean_uuid(tkn)}
else: else:
return {"msg": "用户名或密码错误", "key": ""} return {"msg": cfg.lang["username_or_password_incorrect"], "key": ""}
regex = re.compile( regex = re.compile(
@ -158,9 +156,9 @@ regex = re.compile(
@app.post("/api/signup") @app.post("/api/signup")
async def login_callback(username: str = Form(), password: str = Form(), email: str = Form()): async def login_callback(username: str = Form(), password: str = Form(), email: str = Form()):
if (check_passwd(password)): if (check_passwd(password)):
return {"msg": "密码强度弱,请至少包含一个大小写字符与数字且长度>8", "code": 1} return {"msg": cfg.lang["weak_passwd"], "code": 1}
if (not re.fullmatch(regex, email)): if (not re.fullmatch(regex, email)):
return {"msg": "邮箱不合法", "code": 1} return {"msg": cfg.lang["invalid_email"], "code": 1}
if not (await db.check_user(username)): if not (await db.check_user(username)):
tkn = prep_uuid(uuid.uuid4().hex) tkn = prep_uuid(uuid.uuid4().hex)
emails[tkn] = (username, hashlib.sha256( emails[tkn] = (username, hashlib.sha256(
@ -169,45 +167,45 @@ async def login_callback(username: str = Form(), password: str = Form(), email:
email_send_lst.append( email_send_lst.append(
(email, ROOT+"/api/checkemail?uid="+clean_uuid(tkn))) (email, ROOT+"/api/checkemail?uid="+clean_uuid(tkn)))
return {"msg": "验证邮件已发送到邮箱请在10分钟内完成验证", "code": 0} return {"msg": cfg.lang["verification_email"].format(ACCESS_EMAIL_EXPIRE_MINUTES), "code": 0}
else: else:
return {"msg": "用户名重复", "code": 1} return {"msg": cfg.lang["username_exists"], "code": 1}
@app.get("/api/checkemail") @app.get("/api/checkemail")
async def checkemail(uid: str): async def checkemail(uid: str):
uid = prep_uuid(uid) uid = prep_uuid(uid)
if (uid not in emails): if (uid not in emails):
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的注册id"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["invalid_regid"], "ui": cfg.config["ui"], "lang": cfg.lang})
if (emails[uid][2] < datetime.now()): if (emails[uid][2] < datetime.now()):
del emails[uid] del emails[uid]
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "链接已过期"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["invalid_regid"], "ui": cfg.config["ui"], "lang": cfg.lang})
if (emails[uid][1] == ""): if (emails[uid][1] == ""):
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的注册id"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["invalid_regid"], "ui": cfg.config["ui"], "lang": cfg.lang})
if await db.create_user(emails[uid][0], emails[uid][1], emails[uid][3]) == 0: if await db.create_user(emails[uid][0], emails[uid][1], emails[uid][3]) == 0:
del emails[uid] del emails[uid]
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "创建成功"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["created_successfully"], "ui": cfg.config["ui"], "lang": cfg.lang})
else: else:
del emails[uid] del emails[uid]
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "重复的用户名"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["username_exists"], "ui": cfg.config["ui"], "lang": cfg.lang})
@app.get("/api/resetpasswd", response_class=HTMLResponse) @app.get("/api/resetpasswd", response_class=HTMLResponse)
async def resetpasswd(uid: str, response: Response): async def resetpasswd(uid: str, response: Response):
uid = prep_uuid(uid) uid = prep_uuid(uid)
if (uid not in emails): if (uid not in emails):
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的验证id"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["invalid_checkid"], "ui": cfg.config["ui"], "lang": cfg.lang})
if (emails[uid][2] < datetime.now()): if (emails[uid][2] < datetime.now()):
del emails[uid] del emails[uid]
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "链接已过期"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["invalid_checkid"], "ui": cfg.config["ui"], "lang": cfg.lang})
if (emails[uid][1] != ""): if (emails[uid][1] != ""):
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的注册id"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["invalid_checkid"], "ui": cfg.config["ui"], "lang": cfg.lang})
tokennow = await create_token(emails[uid][0]) tokennow = await create_token(emails[uid][0])
tkn = prep_uuid(uuid.uuid4().hex) tkn = prep_uuid(uuid.uuid4().hex)
apikeys[tkn] = tokens[tokennow] apikeys[tkn] = tokens[tokennow]
response.set_cookie("session", clean_uuid(tokennow)) response.set_cookie("session", clean_uuid(tokennow))
del emails[uid] del emails[uid]
return '<html><head><meta http-equiv="refresh" content="0;url=/user"><title>正在跳转</title></head><body>正在跳转</body></html>' return f'<html><head><meta http-equiv="refresh" content="0;url=/user"><title>{cfg.lang["redirect"]}</title></head><body>{cfg.lang["redirect"]}</body></html>'
@app.post("/api/send_resetpasswd") @app.post("/api/send_resetpasswd")
@ -220,9 +218,9 @@ async def resetpasswd(username: str = Form()):
email_send_lst.append( email_send_lst.append(
(email, ROOT+"/api/resetpasswd?uid="+clean_uuid(tkn))) (email, ROOT+"/api/resetpasswd?uid="+clean_uuid(tkn)))
return {"msg": "验证邮件已发送到邮箱请在10分钟内完成验证", "code": 0} return {"msg": cfg.lang["verification_email"].format(ACCESS_EMAIL_EXPIRE_MINUTES), "code": 0}
else: else:
return {"msg": "用户名不存在", "code": 1} return {"msg": cfg.lang["username_not_exists"], "code": 1}
@app.get("/api/getinfo") @app.get("/api/getinfo")
@ -230,14 +228,14 @@ async def get_user_info(uid: str):
uid = prep_uuid(uid) uid = prep_uuid(uid)
username = await check_apikey(uid) username = await check_apikey(uid)
if (username == ""): if (username == ""):
return {"code": 1, "msg": "token无效", "data": {}} return {"code": 1, "msg": cfg.lang["invalid_token"], "data": {}}
return {"code": 0, "msg": "", "data": {"username": username, "email": await db.get_email(username)}} return {"code": 0, "msg": "", "data": {"username": username, "email": await db.get_email(username)}}
@app.post("/api/changepasswd") @app.post("/api/changepasswd")
async def changepasswd(password: str = Form(), session: Annotated[str | None, Cookie()] = None): async def changepasswd(password: str = Form(), session: Annotated[str | None, Cookie()] = None):
if (check_passwd(password)): if (check_passwd(password)):
return {"msg": "密码强度弱,请至少包含一个大小写字符与数字且长度>8"} return {"msg": cfg.lang["weak_passwd"]}
if (session is not None): if (session is not None):
session = prep_uuid(session) session = prep_uuid(session)
username = await check_token(session) username = await check_token(session)
@ -247,9 +245,9 @@ async def changepasswd(password: str = Form(), session: Annotated[str | None, Co
del tokens[session] del tokens[session]
return {"msg": ""} return {"msg": ""}
else: else:
return {"msg": "无效的登录token"} return {"msg": cfg.lang["invalid_token"]}
else: else:
return {"msg": "无效的登录token"} return {"msg": cfg.lang["invalid_token"]}
@app.get("/login") @app.get("/login")
@ -257,7 +255,7 @@ async def login(state: str = "", client_id: str = "", redirect_url: str = "/user
now_redirect_url = redirect_url.replace( now_redirect_url = redirect_url.replace(
"https://", "").replace("http://", "").split("#")[0].rstrip("/") "https://", "").replace("http://", "").split("#")[0].rstrip("/")
if (now_redirect_url not in REDIRECT_URL_WHITELIST): if (now_redirect_url not in REDIRECT_URL_WHITELIST):
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "无效的重定向URL"}) return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": cfg.lang["invalid_redirect_url"], "ui": cfg.config["ui"], "lang": cfg.lang})
if (session is not None): if (session is not None):
session = prep_uuid(session) session = prep_uuid(session)
username = await check_token(session) username = await check_token(session)
@ -265,12 +263,12 @@ async def login(state: str = "", client_id: str = "", redirect_url: str = "/user
tkn = prep_uuid(uuid.uuid4().hex) tkn = prep_uuid(uuid.uuid4().hex)
apikeys[tkn] = tokens[session] apikeys[tkn] = tokens[session]
return RedirectResponse(url=redirect_url+f"#access_token={clean_uuid(tkn)}&token_type=Bearer&state={state}") return RedirectResponse(url=redirect_url+f"#access_token={clean_uuid(tkn)}&token_type=Bearer&state={state}")
return templates.TemplateResponse("login.html", {"request": {}, "redirect_url": redirect_url, "state": state}) return templates.TemplateResponse("login.html", {"request": {}, "redirect_url": redirect_url, "state": state, "ui": cfg.config["ui"], "lang": cfg.lang})
@app.get("/signup") @app.get("/signup")
async def login(redirect_url: str): async def login(redirect_url: str):
return templates.TemplateResponse("signup.html", {"request": {}, "redirect_url": redirect_url}) return templates.TemplateResponse("signup.html", {"request": {}, "redirect_url": redirect_url, "ui": cfg.config["ui"], "lang": cfg.lang})
@app.get("/user") @app.get("/user")
@ -281,12 +279,12 @@ async def login(session: Annotated[str | None, Cookie()] = None):
username = await check_token(session) username = await check_token(session)
if (username == ""): if (username == ""):
return RedirectResponse(url="/login?redirect_url=/user") return RedirectResponse(url="/login?redirect_url=/user")
return templates.TemplateResponse("manage.html", {"request": {}}) return templates.TemplateResponse("manage.html", {"request": {}, "ui": cfg.config["ui"], "lang": cfg.lang})
@app.get("/resetpasswd") @app.get("/resetpasswd")
async def resetpasswd(response: Response): async def resetpasswd(response: Response):
return templates.TemplateResponse("resetpasswd.html", {"request": {}}) return templates.TemplateResponse("resetpasswd.html", {"request": {}, "ui": cfg.config["ui"], "lang": cfg.lang})
@app.get("/manager/init") @app.get("/manager/init")

View File

@ -4,7 +4,7 @@
<link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css"> <link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css">
<script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script> <script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script>
<link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet"> <link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet">
<title>StuyAreaCN Accout System</title> <title>{{ui.title}}</title>
<style> <style>
* { * {
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
@ -21,17 +21,14 @@
</mdui-dialog> </mdui-dialog>
<mdui-layout style="height: 100%"> <mdui-layout style="height: 100%">
<mdui-top-app-bar> <mdui-top-app-bar>
<mdui-top-app-bar-title>StudyAreaCN</mdui-top-app-bar-title> <mdui-top-app-bar-title>{{ui.prod_name}}</mdui-top-app-bar-title>
</mdui-top-app-bar> </mdui-top-app-bar>
<mdui-navigation-drawer class="navi-drawer" id="toc-drawer"> <mdui-navigation-drawer class="navi-drawer" id="toc-drawer">
<mdui-list> <mdui-list>
<mdui-list-item end-icon="arrow_right" href="https://learn.study-area.org.cn" {% for item in ui.bar_items %}
rounded>开始学习</mdui-list-item> <mdui-list-item end-icon="arrow_right" href="{{item[1]}}" rounded>{{item[0]}}</mdui-list-item>
<mdui-list-item end-icon="arrow_right" href="https://forum.study-area.org.cn" {% endfor %}
rounded>讨论区</mdui-list-item>
<mdui-list-item end-icon="arrow_right"
href="https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/" rounded>查看本站源码</mdui-list-item>
</mdui-list> </mdui-list>
</mdui-navigation-drawer> </mdui-navigation-drawer>

View File

@ -4,7 +4,7 @@
<link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css"> <link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css">
<script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script> <script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script>
<link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet"> <link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet">
<title>StuyAreaCN Accout System</title> <title>{{ui.title}}</title>
<style> <style>
* { * {
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
@ -20,17 +20,14 @@
</mdui-dialog> </mdui-dialog>
<mdui-layout style="height: 100%"> <mdui-layout style="height: 100%">
<mdui-top-app-bar> <mdui-top-app-bar>
<mdui-top-app-bar-title>StudyAreaCN</mdui-top-app-bar-title> <mdui-top-app-bar-title>{{ui.prod_name}}</mdui-top-app-bar-title>
</mdui-top-app-bar> </mdui-top-app-bar>
<mdui-navigation-drawer class="navi-drawer" id="toc-drawer"> <mdui-navigation-drawer class="navi-drawer" id="toc-drawer">
<mdui-list> <mdui-list>
<mdui-list-item end-icon="arrow_right" href="https://learn.study-area.org.cn" {% for item in ui.bar_items %}
rounded>开始学习</mdui-list-item> <mdui-list-item end-icon="arrow_right" href="{{item[1]}}" rounded>{{item[0]}}</mdui-list-item>
<mdui-list-item end-icon="arrow_right" href="https://forum.study-area.org.cn" {% endfor %}
rounded>讨论区</mdui-list-item>
<mdui-list-item end-icon="arrow_right"
href="https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/" rounded>查看本站源码</mdui-list-item>
</mdui-list> </mdui-list>
</mdui-navigation-drawer> </mdui-navigation-drawer>
@ -41,20 +38,20 @@
id="cards"> id="cards">
<div class="header" <div class="header"
style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;"> style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;">
登录 StudyAreaCN {{lang.login}} {{ui.prod_name}}
</div> </div>
<mdui-text-field id="username" <mdui-text-field id="username"
style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px" style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px"
label="用户名"></mdui-text-field> label="{{lang.username}}"></mdui-text-field>
<mdui-text-field id="passwd" style="display:block;height:54px;width:90%;left:10%;margin:auto" <mdui-text-field id="passwd" style="display:block;height:54px;width:90%;left:10%;margin:auto"
label="密码" type="password" toggle-password></mdui-text-field> label="{{lang.password}}" type="password" toggle-password></mdui-text-field>
<mdui-button style="width:90%;margin-left:5%" variant="elevated" <mdui-button style="width:90%;margin-left:5%" variant="elevated"
href="/resetpasswd">忘记密码?点我重置</mdui-button> href="/resetpasswd">{{lang.forgot_password_info}}</mdui-button>
<div style="position: absolute;bottom:20px;width:100%"> <div style="position: absolute;bottom:20px;width:100%">
<mdui-button id="loginbtn" style="width:calc(90% - 110px);margin-right:10px;margin-left:5%" <mdui-button id="loginbtn" style="width:calc(90% - 110px);margin-right:10px;margin-left:5%"
onclick="logins()">登录</mdui-button> onclick="logins()">{{lang.login}}</mdui-button>
<mdui-button style="width:100px" variant="elevated" <mdui-button style="width:100px" variant="elevated"
href="/signup?redirect_url={{redirect_url}}">注册</mdui-button> href="/signup?redirect_url={{redirect_url}}">{{lang.signup}}</mdui-button>
</div> </div>
</mdui-card> </mdui-card>
</div> </div>
@ -77,6 +74,12 @@
Http.addEventListener('loadend', () => { Http.addEventListener('loadend', () => {
var ret = JSON.parse(Http.responseText) var ret = JSON.parse(Http.responseText)
if (ret.msg == undefined) {
document.getElementById("dialog").innerHTML = "{{lang.unedit_msg}}"
document.getElementById("dialog").setAttribute("open", "")
document.getElementById("loginbtn").removeAttribute('loading');
return
}
if (ret.msg == "") { if (ret.msg == "") {
const searchParams = new URLSearchParams(window.location.search); const searchParams = new URLSearchParams(window.location.search);
var redi = searchParams.get("redirect_url") var redi = searchParams.get("redirect_url")

View File

@ -4,7 +4,7 @@
<link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css"> <link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css">
<script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script> <script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script>
<link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet"> <link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet">
<title>StuyAreaCN Accout System</title> <title>{{ui.title}}</title>
<style> <style>
* { * {
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
@ -20,17 +20,14 @@
</mdui-dialog> </mdui-dialog>
<mdui-layout style="height: 100%"> <mdui-layout style="height: 100%">
<mdui-top-app-bar> <mdui-top-app-bar>
<mdui-top-app-bar-title>StudyAreaCN</mdui-top-app-bar-title> <mdui-top-app-bar-title>{{ui.prod_name}}</mdui-top-app-bar-title>
</mdui-top-app-bar> </mdui-top-app-bar>
<mdui-navigation-drawer class="navi-drawer" id="toc-drawer"> <mdui-navigation-drawer class="navi-drawer" id="toc-drawer">
<mdui-list> <mdui-list>
<mdui-list-item end-icon="arrow_right" href="https://learn.study-area.org.cn" {% for item in ui.bar_items %}
rounded>开始学习</mdui-list-item> <mdui-list-item end-icon="arrow_right" href="{{item[1]}}" rounded>{{item[0]}}</mdui-list-item>
<mdui-list-item end-icon="arrow_right" href="https://forum.study-area.org.cn" {% endfor %}
rounded>讨论区</mdui-list-item>
<mdui-list-item end-icon="arrow_right"
href="https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/" rounded>查看本站源码</mdui-list-item>
</mdui-list> </mdui-list>
</mdui-navigation-drawer> </mdui-navigation-drawer>
@ -41,20 +38,20 @@
id="cards"> id="cards">
<div class="header" <div class="header"
style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;"> style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;">
用户管理 {{lang.manage}}
</div> </div>
<mdui-text-field <mdui-text-field
style="display:block;height:54px;width:90%;left:10%;margin:auto;margin-bottom:16px;" label="密码" style="display:block;height:54px;width:90%;left:10%;margin:auto;margin-bottom:16px;"
type="password" toggle-password id="passwd"> label="{{lang.password}}" type="password" toggle-password id="passwd">
</mdui-text-field> </mdui-text-field>
<mdui-text-field <mdui-text-field
style="display:block;height:54px;width:90%;left:10%;margin:auto;margin-bottom:16px;" style="display:block;height:54px;width:90%;left:10%;margin:auto;margin-bottom:16px;"
label="确认密码" type="password" id="check_passwd"> label="{{lang.check_passwd}}" type="password" id="check_passwd">
</mdui-text-field> </mdui-text-field>
<mdui-button style="width:90%;margin-right:5px;margin-left:5%;margin-bottom:16px;" <mdui-button style="width:90%;margin-right:5px;margin-left:5%;margin-bottom:16px;"
onclick="change_passwd()" id="loginbtn">更改密码</mdui-button> onclick="change_passwd()" id="loginbtn">{{lang.change_passwd}}</mdui-button>
<div style="font-size: 16px;text-align: center;"> <div style="font-size: 16px;text-align: center;">
若需要注销或修改账户的邮箱,请发送邮件至 SACN 任意管理员邮箱 {{lang.change_info}} {{ui.manager_email}}
</div> </div>
</mdui-card> </mdui-card>
</div> </div>
@ -78,6 +75,12 @@
Http.addEventListener('loadend', () => { Http.addEventListener('loadend', () => {
var ret = JSON.parse(Http.responseText) var ret = JSON.parse(Http.responseText)
if (ret.msg == undefined) {
document.getElementById("dialog").innerHTML = "{{lang.unedit_msg}}"
document.getElementById("dialog").setAttribute("open", "")
document.getElementById("loginbtn").removeAttribute('loading');
return
}
if (ret.msg == "") { if (ret.msg == "") {
window.location.href = "/login?redirect_url=/user" window.location.href = "/login?redirect_url=/user"
} else { } else {
@ -87,7 +90,7 @@
document.getElementById("loginbtn").removeAttribute('loading'); document.getElementById("loginbtn").removeAttribute('loading');
}) })
} else { } else {
document.getElementById("dialog").innerHTML = "密码不一致" document.getElementById("dialog").innerHTML = "{{lang.passwd_not_same}}"
document.getElementById("dialog").setAttribute("open", "") document.getElementById("dialog").setAttribute("open", "")
} }
} }

View File

@ -4,7 +4,7 @@
<link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css"> <link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css">
<script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script> <script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script>
<link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet"> <link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet">
<title>StuyAreaCN Accout System</title> <title>{{ui.title}}</title>
<style> <style>
* { * {
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
@ -20,17 +20,14 @@
</mdui-dialog> </mdui-dialog>
<mdui-layout style="height: 100%"> <mdui-layout style="height: 100%">
<mdui-top-app-bar> <mdui-top-app-bar>
<mdui-top-app-bar-title>StudyAreaCN</mdui-top-app-bar-title> <mdui-top-app-bar-title>{{ui.prod_name}}</mdui-top-app-bar-title>
</mdui-top-app-bar> </mdui-top-app-bar>
<mdui-navigation-drawer class="navi-drawer" id="toc-drawer"> <mdui-navigation-drawer class="navi-drawer" id="toc-drawer">
<mdui-list> <mdui-list>
<mdui-list-item end-icon="arrow_right" href="https://learn.study-area.org.cn" {% for item in ui.bar_items %}
rounded>开始学习</mdui-list-item> <mdui-list-item end-icon="arrow_right" href="{{item[1]}}" rounded>{{item[0]}}</mdui-list-item>
<mdui-list-item end-icon="arrow_right" href="https://forum.study-area.org.cn" {% endfor %}
rounded>讨论区</mdui-list-item>
<mdui-list-item end-icon="arrow_right"
href="https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/" rounded>查看本站源码</mdui-list-item>
</mdui-list> </mdui-list>
</mdui-navigation-drawer> </mdui-navigation-drawer>
@ -41,14 +38,14 @@
id="cards"> id="cards">
<div class="header" <div class="header"
style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;"> style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;">
重置密码 {{lang.reset_passwd}}
</div> </div>
<mdui-text-field id="username" <mdui-text-field id="username"
style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px" style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px"
label="用户名"></mdui-text-field> label="{{lang.username}}"></mdui-text-field>
<div style="position: absolute;bottom:20px;width:100%"> <div style="position: absolute;bottom:20px;width:100%">
<mdui-button id="loginbtn" style="width:90%;margin-right:10px;margin-left:5%" <mdui-button id="loginbtn" style="width:90%;margin-right:10px;margin-left:5%"
onclick="logins()">发送邮件</mdui-button> onclick="logins()">{{lang.send_email}}</mdui-button>
</div> </div>
</mdui-card> </mdui-card>
</div> </div>
@ -70,6 +67,12 @@
Http.addEventListener('loadend', () => { Http.addEventListener('loadend', () => {
var ret = JSON.parse(Http.responseText) var ret = JSON.parse(Http.responseText)
if (ret.msg == undefined) {
document.getElementById("dialog").innerHTML = "{{lang.unedit_msg}}"
document.getElementById("dialog").setAttribute("open", "")
document.getElementById("loginbtn").removeAttribute('loading');
return
}
if (ret.msg == "") { if (ret.msg == "") {
const searchParams = new URLSearchParams(window.location.search); const searchParams = new URLSearchParams(window.location.search);
window.location.href = "/login/?redirect_url=/user" window.location.href = "/login/?redirect_url=/user"

View File

@ -4,7 +4,7 @@
<link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css"> <link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css">
<script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script> <script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script>
<link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet"> <link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet">
<title>StuyAreaCN Accout System</title> <title>{{ui.title}}</title>
<style> <style>
* { * {
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
@ -20,17 +20,14 @@
</mdui-dialog> </mdui-dialog>
<mdui-layout style="height: 100%"> <mdui-layout style="height: 100%">
<mdui-top-app-bar> <mdui-top-app-bar>
<mdui-top-app-bar-title>StudyAreaCN</mdui-top-app-bar-title> <mdui-top-app-bar-title>{{ui.prod_name}}</mdui-top-app-bar-title>
</mdui-top-app-bar> </mdui-top-app-bar>
<mdui-navigation-drawer class="navi-drawer" id="toc-drawer"> <mdui-navigation-drawer class="navi-drawer" id="toc-drawer">
<mdui-list> <mdui-list>
<mdui-list-item end-icon="arrow_right" href="https://learn.study-area.org.cn" {% for item in ui.bar_items %}
rounded>开始学习</mdui-list-item> <mdui-list-item end-icon="arrow_right" href="{{item[1]}}" rounded>{{item[0]}}</mdui-list-item>
<mdui-list-item end-icon="arrow_right" href="https://forum.study-area.org.cn" {% endfor %}
rounded>讨论区</mdui-list-item>
<mdui-list-item end-icon="arrow_right"
href="https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/" rounded>查看本站源码</mdui-list-item>
</mdui-list> </mdui-list>
</mdui-navigation-drawer> </mdui-navigation-drawer>
@ -41,21 +38,21 @@
id="cards"> id="cards">
<div class="header" <div class="header"
style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;"> style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;">
注册 StudyAreaCN {{lang.signup}} {{ui.prod_name}}
</div> </div>
<mdui-text-field style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px" <mdui-text-field style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px"
label="用户名" id="username"></mdui-text-field> label="{{lang.username}}" id="username"></mdui-text-field>
<mdui-text-field style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px" <mdui-text-field style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px"
label="邮箱" id="email"></mdui-text-field> label="{{lang.email}}" id="email"></mdui-text-field>
<mdui-text-field style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px" <mdui-text-field style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px"
label="密码" type="password" toggle-password id="passwd"></mdui-text-field> label="{{lang.password}}" type="password" toggle-password id="passwd"></mdui-text-field>
<mdui-text-field style="display:block;height:54px;width:90%;left:10%;margin:auto" label="确认密码" <mdui-text-field style="display:block;height:54px;width:90%;left:10%;margin:auto"
type="password" id="check_passwd"></mdui-text-field> label="{{lang.check_passwd}}" type="password" id="check_passwd"></mdui-text-field>
<div style="position: absolute;bottom:20px;width:100%"> <div style="position: absolute;bottom:20px;width:100%">
<mdui-button style="width:calc(90% - 110px);margin-right:10px;margin-left:5%" <mdui-button style="width:calc(90% - 110px);margin-right:10px;margin-left:5%"
onclick="signup();" id="loginbtn">注册</mdui-button> onclick="signup();" id="loginbtn">{{lang.signup}}</mdui-button>
<mdui-button style="width:100px" variant="elevated" <mdui-button style="width:100px" variant="elevated"
onclick="window.history.back();">登录</mdui-button> onclick="window.history.back();">{{lang.login}}</mdui-button>
</div> </div>
</mdui-card> </mdui-card>
</div> </div>
@ -81,6 +78,12 @@
Http.addEventListener('loadend', () => { Http.addEventListener('loadend', () => {
var ret = JSON.parse(Http.responseText) var ret = JSON.parse(Http.responseText)
if (ret.msg == undefined) {
document.getElementById("dialog").innerHTML = "{{lang.unedit_msg}}"
document.getElementById("dialog").setAttribute("open", "")
document.getElementById("loginbtn").removeAttribute('loading');
return
}
document.getElementById("dialog").innerHTML = ret.msg document.getElementById("dialog").innerHTML = ret.msg
document.getElementById("dialog").setAttribute("open", "") document.getElementById("dialog").setAttribute("open", "")
if (ret.code === 0) { if (ret.code === 0) {
@ -89,7 +92,7 @@
document.getElementById("loginbtn").removeAttribute('loading'); document.getElementById("loginbtn").removeAttribute('loading');
}) })
} else { } else {
document.getElementById("dialog").innerHTML = "密码不一致" document.getElementById("dialog").innerHTML = "{{lang.passwd_not_same}}"
document.getElementById("dialog").setAttribute("open", "") document.getElementById("dialog").setAttribute("open", "")
} }
} }