Initial project files: BESCMS full source

This commit is contained in:
bes
2026-08-13 23:37:46 +08:00
parent fa6cddb540
commit 2e26f85723
2166 changed files with 396625 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
{template "install/header.html"}
<div class="portlet light">
<div class="portlet-title">
<div class="caption">
<i class="fa fa-file-text-o font-green"></i>
<span class="caption-subject font-green">软件使用协议</span>
</div>
</div>
<div class="portlet-body" style="line-height: 24px;">
</div>
<div class="portlet-title" style="min-height: 18px;">
</div>
<div class="portlet-body text-center">
<a href="javascript:;" disabled="" id="ok" class="btn btn-success"> ... </a>
</div>
</div>
<script>
var Seconds = 10;
var setIntervalID;
function ok() {
var ok = $("#ok");
if (Seconds <= 0) {
ok.html("同意协议");
ok.attr('href', '{$next_url}');
ok.attr('disabled', false);
clearInterval(setIntervalID);
} else {
ok.html("请仔细阅读协议还剩下(" + Seconds + ")秒");
}
Seconds--;
}
setIntervalID=setInterval("ok()", 1000);
</script>
{template "install/footer.html"}
+204
View File
@@ -0,0 +1,204 @@
{template "install/header.html"}
<style>
.install-check-form .form-group {
margin: 0;
}
.install-check-form .control-label {
color: #334155;
font-weight: 600;
}
.install-check-form .form-control-static {
color: #4a5568;
}
.install-check-box {
margin-top: -1px;
padding: 8px 0;
}
.install-check-list {
margin: 0;
padding: 0;
list-style: none;
}
.install-check-item {
display: flex;
align-items: center;
gap: 12px;
margin: 0 0 10px;
padding: 6px 14px;
border: 1px solid #e7edf4;
border-radius: 10px;
background: #f8fbfd;
color: #475569;
line-height: 1.7;
}
.install-check-item:last-child {
margin-bottom: 0;
}
.install-check-status {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 50px;
padding: 2px 10px;
border-radius: 999px;
background: #eaf7ef;
color: #1f8a4c;
font-size: 12px;
font-weight: 600;
white-space: nowrap;
}
.install-check-item.is-error {
border-color: #f3d0d0;
background: #fff6f6;
color: #7f1d1d;
}
.install-check-item.is-error .install-check-status {
background: #fdeaea;
color: #d83a3a;
}
.install-check-help {
margin-left: auto;
color: #1a73b8;
text-decoration: none;
white-space: nowrap;
}
.install-check-help:hover,
.install-check-help:focus {
color: #0f5f9b;
text-decoration: underline;
}
.install-action-disabled {
min-width: 200px;
border-radius: 22px;
color: #7b8794;
background: #eef2f6;
border-color: #dde5ed;
}
.install-action-disabled:hover,
.install-action-disabled:focus,
.install-action-disabled:active {
color: #7b8794;
background: #eef2f6;
border-color: #dde5ed;
}
@media (max-width: 767px) {
.install-check-item {
flex-wrap: wrap;
gap: 8px;
}
.install-check-help {
margin-left: 0;
}
}
</style>
<div class="portlet light">
<div class="portlet-title">
<div class="caption">
<i class="fa fa-refresh font-green"></i>
<span class="caption-subject font-green">{dr_lang('环境监测')}</span>
</div>
</div>
<div class="portlet-body ">
<form action="#" class="form-horizontal form-bordered install-check-form">
<div class="form-body">
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('目录读写权限')}</label>
<div class="col-md-9 install-check-box">
<div class="install-check-list">
{loop $path $name $code}
<p class="install-check-item {if !$code}is-error{/if}">
<span class="install-check-status">{if !$code}{dr_lang('错误')}{else}{dr_lang('正确')}{/if}</span>
<span>{$name}</span>
</p>
{/loop}
</div>
</div>
</div>
<div class="form-group">
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('PHP版本')}</label>
<div class="col-md-9">
<p class="form-control-static"> {PHP_VERSION} ({FRAME_PHP_VERSION}{dr_lang('及以上版本')})</p>
</div>
</div>
<label class="control-label col-md-3">{dr_lang('环境检测')}</label>
<div class="col-md-9 install-check-box">
<div class="install-check-list">
{loop $php $t}
{if !$t.code}
<p class="install-check-item is-error">
<?php $error = 1;?>
<span class="install-check-status">{dr_lang('不支持')}</span>
<span>{$t.name}</span>
<a href="{$t.help}" target="_blank" class="install-check-help">{dr_lang('查看帮助')}</a>
</p>
{else}
<p class="install-check-item">
<span class="install-check-status">{dr_lang('支持')}</span>
<span>{$t.name}</span>
</p>
{/if}
{/loop}
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('数据库扩展')}</label>
<div class="col-md-9 install-check-box">
<div class="install-check-list">
{loop $db_ext $t}
<p class="install-check-item {if !$t.code}is-error{/if}">
<span class="install-check-status">{if !$t.code}{dr_lang('不支持')}{else}{dr_lang('支持')}{/if}</span>
<span>{$t.name}</span>
{if !$t.code && $t.help}
<a href="{$t.help}" target="_blank" class="install-check-help">{dr_lang('查看帮助')}</a>
{/if}
</p>
{/loop}
{if !$has_db_ext}
<p class="install-check-item is-error">
<span class="install-check-status">{dr_lang('错误')}</span>
<span>{dr_lang('mysqli 与 sqlite3 至少需要启用一个')}</span>
</p>
{else}
<p class="install-check-item">
<span class="install-check-status">{dr_lang('正确')}</span>
<span>{dr_lang('已满足:至少一种数据库扩展可用')}</span>
</p>
{/if}
</div>
</div>
</div>
</div>
</form>
</div>
<div class="portlet-title" style="min-height: 18px;">
</div>
<div class="portlet-body text-center">
{if $error}
<button type="button" class="btn default install-action-disabled"> {dr_lang('无法进行下一步安装')} </button>
{else}
<a href="{$next_url}" class="btn btn-success"> {dr_lang('下一步安装')} </a>
{/if}
</div>
</div>
{template "install/footer.html"}
+361
View File
@@ -0,0 +1,361 @@
{template "install/header.html"}
<style>
.install-option-group {
display: inline-flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
padding: 6px;
border: 1px solid #e4ebf3;
border-radius: 12px;
background: linear-gradient(180deg, #f8fbff 0%, #f3f7fb 100%);
}
/* 覆盖框架 .mt-radio 默认样式,避免圆点压住文字 */
.install-option-group .install-option-card.mt-radio {
position: relative;
display: inline-flex;
align-items: center;
min-width: 118px;
margin: 0 0 0 0 !important;
padding: 10px 18px 10px 40px !important;
border: 1px solid #d7e3f0;
border-radius: 10px;
background: #fff;
color: #4a5568;
font-size: 14px;
font-weight: 500;
line-height: 1.4;
cursor: pointer;
transition: all 0.2s ease;
}
.install-option-group .install-option-card.mt-radio:hover {
border-color: #8db7e3;
box-shadow: 0 6px 18px rgba(56, 110, 171, 0.10);
}
.install-option-group .install-option-card.mt-radio > input[type="radio"] {
position: absolute;
left: 14px;
top: 50%;
margin: -8px 0 0 0;
width: 16px;
height: 16px;
opacity: 0;
z-index: 1;
cursor: pointer;
}
.install-option-group .install-option-card.mt-radio > span {
position: absolute !important;
left: 14px !important;
top: 50% !important;
right: auto !important;
bottom: auto !important;
width: 16px !important;
height: 16px !important;
margin: -8px 0 0 0 !important;
padding: 0 !important;
border: 2px solid #b8c7d9 !important;
border-radius: 50% !important;
background: #fff !important;
box-shadow: none;
transition: all 0.2s ease;
}
.install-option-group .install-option-card.mt-radio > span:after {
content: "" !important;
position: absolute !important;
left: 50% !important;
top: 50% !important;
width: 6px !important;
height: 6px !important;
margin: -3px 0 0 -3px !important;
border: 0 !important;
border-radius: 50% !important;
background: #26a65b !important;
opacity: 0;
transform: scale(0.6);
transition: all 0.2s ease;
}
.install-option-group .install-option-card.mt-radio > input[type="radio"]:checked + span {
border-color: #26a65b !important;
box-shadow: 0 0 0 4px rgba(38, 166, 91, 0.10);
}
.install-option-group .install-option-card.mt-radio > input[type="radio"]:checked + span:after {
opacity: 1;
transform: scale(1);
}
.install-option-group .install-option-card.mt-radio:has(input[type="radio"]:checked) {
border-color: #26a65b;
background: #f4fcf7;
color: #1d7f45;
box-shadow: 0 10px 22px rgba(38, 166, 91, 0.12);
}
.install-option-group .install-option-card.mt-radio.is-disabled,
.install-option-group .install-option-card.mt-radio:has(input[type="radio"]:disabled) {
opacity: .55;
cursor: pointer;
box-shadow: none;
color: #8a96a6;
background: #f5f7fa;
}
.install-option-group .install-option-card.mt-radio.is-disabled:hover {
border-color: #c5d0dc;
box-shadow: none;
}
.install-option-group .install-option-card.mt-radio.is-disabled > input[type="radio"] {
pointer-events: none;
}
.install-option-help {
margin: 12px 0 0;
padding: 10px 14px;
border-radius: 8px;
background: #f8fbff;
color: #6b7a8c;
line-height: 1.8;
}
@media (max-width: 767px) {
.install-option-group {
display: flex;
}
.install-option-group .install-option-card.mt-radio {
width: 100%;
min-width: 0;
}
}
</style>
<div class="portlet light">
<div class="portlet-title">
<div class="caption">
<i class="fa fa-edit font-green"></i>
<span class="caption-subject font-green">{dr_lang('项目信息')}</span>
</div>
</div>
<div class="portlet-body ">
<form action="#" id="myform" class="form-horizontal form-bordered ">
{dr_form_hidden()}
<div class="form-body">
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('项目地址')}</label>
<div class="col-md-7">
<p class="form-control-static" id="url"> {FC_NOW_HOST} </p>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('项目名称')}</label>
<div class="col-md-7">
<input type="text" name="data[name]" value="{dr_lang('我的项目')}" class="form-control" placeholder="">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('创始人邮箱')}</label>
<div class="col-md-7">
<input type="text" name="data[email]" value="admin@admin.com" class="form-control" placeholder="">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('创始人账号')}</label>
<div class="col-md-7">
<input type="text" name="data[username]" value="admin" class="form-control" placeholder="">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('创始人密码')}</label>
<div class="col-md-7">
<input type="text" name="data[password]" value="admin" class="form-control" placeholder="">
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('数据库驱动')}</label>
<div class="col-md-7">
<div class="install-option-group mt-radio-inline">
{loop $db_drivers $d}
<label class="install-option-card mt-radio {if !$d.enabled}is-disabled js-db-driver-disabled{/if}"
{if !$d.enabled}data-tip="{$d.tip}"{/if}>
<input type="radio" name="data[db_driver]" value="{$d.name}" data-form="{$d.form}"
{if $db_driver==$d.name && $d.enabled}checked{/if}
{if !$d.enabled}disabled{/if}>
<span></span>
{$d.label}
</label>
{/loop}
</div>
{if $db_dir_missing || $force_mysqli}
<p class="help-block install-option-help">
{if $db_dir_missing}
<span style="color:#d68910;">{dr_lang('未检测到 System/Database 目录,已默认使用 MySQLiMySQL)模式')}</span>
{elseif $force_mysqli}
<span style="color:#d68910;">{dr_lang('检测到自定义 Install.sql,仅支持 MySQLi 安装')}</span>
{/if}
</p>
{/if}
</div>
</div>
<div class="form-group js-db-server">
<label class="control-label col-md-3">{dr_lang('数据库地址')}</label>
<div class="col-md-7">
<input type="text" name="data[db_host]" value="{$db_host}" class="form-control" placeholder="">
</div>
</div>
<div class="form-group js-db-server">
<label class="control-label col-md-3">{dr_lang('数据库账号')}</label>
<div class="col-md-7">
<input type="text" name="data[db_user]" value="{$db_user}" class="form-control" placeholder="">
</div>
</div>
<div class="form-group js-db-server">
<label class="control-label col-md-3">{dr_lang('数据库密码')}</label>
<div class="col-md-7">
<input type="text" name="data[db_pass]" value="{$db_pass}" class="form-control js-db-pass" placeholder="">
</div>
</div>
<div class="form-group js-db-server">
<label class="control-label col-md-3">{dr_lang('数据库名称')}</label>
<div class="col-md-7">
<input type="text" name="data[db_name]" value="{$db_name}" class="form-control js-db-name-mysql" placeholder="">
<p class="help-block"> {dr_lang('当提示Unknown database时,请先创建数据库后再进行下一步')} </p>
</div>
</div>
<div class="form-group js-db-sqlite" style="display:none;">
<label class="control-label col-md-3">{dr_lang('数据库文件')}</label>
<div class="col-md-7">
<input type="text" name="data[db_name_sqlite]" value="{$sqlite_name}" class="form-control js-db-name-sqlite" placeholder="database/SQLite3/" readonly>
<p class="help-block"> {dr_lang('保存在 cache/database/SQLite3/ 下,文件名安装时随机生成,避免路径被猜测')} </p>
</div>
</div>
<div class="form-group js-db-sqlite" style="display:none;">
<label class="control-label col-md-3">{dr_lang('加密密码')}</label>
<div class="col-md-7">
<input type="text" name="data[db_pass_sqlite]" value="" class="form-control js-db-pass-sqlite" placeholder="{dr_lang('可选,一般留空')}">
<p class="help-block"> {dr_lang('可选。若填写则作为 SQLite 加密口令(需 PHP 支持)')} </p>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('数据表前缀')}</label>
<div class="col-md-7">
<input type="text" name="data[db_prefix]" value="{$db_prefix}" class="form-control" placeholder="">
</div>
</div>
{if $is_demo}
<div class="form-group">
<label class="control-label col-md-3">{dr_lang('安装测试数据')}</label>
<div class="col-md-7">
<div class="mt-radio-inline ">
<label class="mt-radio">
<input type="radio" name="is_install_db" value="1" checked=""> {dr_lang('安装')}
<span></span>
</label>
<label class="mt-radio">
<input type="radio" name="is_install_db" value="0"> {dr_lang('不安装')}
<span></span>
</label>
</div>
<p class="help-block install-option-help"> {dr_lang('新手建议选择安装测试数据,方便快速入门')} </p>
</div>
</div>
{/if}
</div>
</form>
</div>
<div class="portlet-title" style="min-height: 18px;"></div>
<div class="portlet-body text-center">
<a href="javascript:dr_next_install();" type='submit' class="btn btn-success"> {dr_lang('下一步安装')} </a>
</div>
<div class="portlet-body text-center" id="dr_loading" style="display: none; color:blue;">
{dr_lang('正在安装中(这个过程一般不超过30秒)')}...
</div>
</div>
<script>
$('#url').html(document.location.protocol+'//{DOMAIN_NAME}/');
function dr_toggle_db_driver() {
var $checked = $('input[name="data[db_driver]"]:checked:not(:disabled)');
if (!$checked.length) {
$checked = $('input[name="data[db_driver]"]:not(:disabled)').first().prop('checked', true);
}
var formType = $checked.attr('data-form') || 'server';
if (formType === 'sqlite') {
$('.js-db-server').hide().find('input,select,textarea').prop('disabled', true);
$('.js-db-sqlite').show().find('input,select,textarea').prop('disabled', false);
$('.js-db-name-sqlite').attr('name', 'data[db_name]');
$('.js-db-pass-sqlite').attr('name', 'data[db_pass]');
} else {
$('.js-db-sqlite').hide().find('input,select,textarea').prop('disabled', true);
$('.js-db-server').show().find('input,select,textarea').prop('disabled', false);
$('.js-db-name-sqlite').attr('name', 'data[db_name_sqlite]');
$('.js-db-pass-sqlite').attr('name', 'data[db_pass_sqlite]');
}
}
$(function () {
// 若默认驱动不可用则自动切换
var $checked = $('input[name="data[db_driver]"]:checked');
if ($checked.length && $checked.prop('disabled')) {
$('input[name="data[db_driver]"]:not(:disabled)').first().prop('checked', true);
}
dr_toggle_db_driver();
$('input[name="data[db_driver]"]').on('change', dr_toggle_db_driver);
// 灰色不可用驱动:点击弹窗提示原因
$(document).on('click', '.js-db-driver-disabled', function (e) {
e.preventDefault();
e.stopPropagation();
var tip = $(this).attr('data-tip') || '{dr_lang("该数据库驱动暂不可选")}';
if (typeof layer !== 'undefined' && layer.alert) {
layer.alert(tip);
} else if (typeof dr_tips === 'function') {
dr_tips(0, tip);
} else {
alert(tip);
}
return false;
});
});
function dr_next_install() {
var loading = layer.load(2, {
shade: [0.3,'#fff'], //0.1透明度的白色背景
time: 100000000
});
$('#dr_loading').show();
$.ajax({type: "POST",dataType:"json", url: '{$do_url}', data: $("#myform").serialize(),
success: function(json) {
if (json.code == 1) {
window.location.href = json.msg;
} else {
layer.close(loading);
layer.alert(json.msg);
$('#dr_loading').hide();
}
},
error: function(HttpRequest, ajaxOptions, thrownError) {
layer.closeAll('loading');
$('#dr_loading').hide();
layer.open({
type: 1,
title: "{dr_lang('系统故障')}",
fix:true,
shadeClose: true,
shade: 0,
area: ['50%', '50%'],
content: "<div style=\"padding:10px;\">"+HttpRequest.responseText+"</div>"
});
}
});
}
</script>
{template "install/footer.html"}
+74
View File
@@ -0,0 +1,74 @@
{template "install/header.html"}
<div class="portlet light">
<div class="portlet-title">
<div class="caption">
<i class="fa fa-laptop font-green"></i>
<span class="caption-subject font-green">{dr_lang('正在安装数据结构')}</span>
</div>
</div>
<div class="portlet-body " style="">
{if $error}
<div class="scroller" style="height:300px;" data-rail-visible="1">
{nl2br($error)}
</div>
{else}
<div class="scroller" style="height:300px; font-size: 12px;" data-rail-visible="1" id="dr_check_html">
<p>{dr_lang('正在执行安装程序')}</p>
</div>
<div id="dr_error_html" style="display: none">
</div>
<script>
$(function(){
dr_ajax2ajax(1);
});
function dr_ajax2ajax(page) {
$.ajax({
type: "GET",
dataType: "json",
timeout: 0,
url: "{$do_url}&page="+page,
success: function (json) {
$('#dr_check_html').append("<p>"+json.msg+"</p>");
document.getElementById('dr_check_html').scrollTop = document.getElementById('dr_check_html').scrollHeight;
if (json.code == 0) {
$('#dr_check_html').append("<p style='color:red'>出现故障:"+json.msg+"</p>");
$('#dr_error_html').show();
return;
} else {
if (json.data.page == 99 ) {
// 完成
var loading = layer.load(2, {
shade: [0.3,'#fff'], //0.1透明度的白色背景
time: 100000000
});
window.location.href = "{$next_url}&protocol="+document.location.protocol;
} else {
dr_ajax2ajax(json.data.page);
}
}
},
error: function(HttpRequest, ajaxOptions, thrownError) {
dr_ajax_alert_error(HttpRequest, this, thrownError);;
$('#dr_check_html').append("<p style='color:red'>出现故障:"+HttpRequest.responseText+"</p>");
}
});
}
</script>
{/if}
</div>
<div class="portlet-title" style="min-height: 18px;">
</div>
<div class="portlet-body text-center">
{if $error}
<a href="{$pre_url}" class="btn btn-success"> {dr_lang('返回上一步')} </a>
{/if}
</div>
</div>
{template "install/footer.html"}
+109
View File
@@ -0,0 +1,109 @@
{template "install/header.html"}
<style>
.install-result-wrap {
text-align: center;
}
.install-result-icon {
text-align: center;
padding-top: 20px;
}
.install-result-icon i {
display: inline-block;
font-size: 88px;
line-height: 1;
color: #26a65b;
text-shadow: 0 8px 24px rgba(38, 166, 91, 0.18);
}
.install-result-main {
color: #26a65b;
padding-top: 6px;
}
.install-result-title {
margin: 0 0 18px;
font-size: 32px;
font-weight: 600;
line-height: 1.3;
}
.install-result-item {
margin: 0 0 10px;
font-size: 16px;
color: #3a4a5b;
}
.install-result-item strong {
display: inline-block;
min-width: 68px;
color: #26a65b;
font-weight: 600;
}
.install-result-action {
padding-top: 18px;
}
.install-result-action .btn {
min-width: 160px;
height: 42px;
padding-top:5px;
color: #26a65b;
line-height: 28px;
border-radius: 21px;
font-size: 15px;
box-shadow: 0 10px 20px rgba(38, 166, 91, 0.18);
}
</style>
<div class="portlet light">
<div class="portlet-title">
<div class="caption">
<i class="fa fa-laptop font-green"></i>
<span class="caption-subject font-green">{dr_lang('安装结果')}</span>
</div>
</div>
<div class="portlet-body " style="padding:0 50px;">
{if $error}
<div class="scroller" style="height:300px" data-rail-visible="1">
{nl2br($error)}
</div>
{else}
<div class="row install-result-wrap">
<div class="col-md-12 install-result-icon">
<i class="fa fa-check-circle"></i>
</div>
<div class="col-md-12 install-result-main">
<p class="install-result-title">{dr_lang('安装完成')}</p>
{if $data.username}<p class="install-result-item"><strong>{dr_lang('账号')}</strong>{$data.username}</p>{/if}
{if $data.password}<p class="install-result-item"><strong>{dr_lang('密码')}</strong>{$data.password}</p>{/if}
<p class="install-result-action"><a href="{$admin}.php?c=login" onclick="dr_next_install()" class="btn btn-success">{dr_lang('登录项目后台')}</a></p>
</div>
</div>
<script>
function dr_next_install() {
var loading = layer.load(2, {
shade: [0.3,'#fff'], //0.1透明度的白色背景
time: 100000000
});
}
</script>
{/if}
</div>
<div class="portlet-title" style="min-height: 18px;">
</div>
<div class="portlet-body text-center">
{if $error}
<a href="{$pre_url}" class="btn btn-success"> {dr_lang('返回上一步')} </a>
{/if}
</div>
</div>
{template "install/footer.html"}
+10
View File
@@ -0,0 +1,10 @@
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+115
View File
@@ -0,0 +1,115 @@
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8" />
<title>{dr_lang('安装程序')} - {DR_NAME}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link href="{THEME_PATH}assets/icon/css/icon.css?v={CMF_UPDATE_TIME}" rel="stylesheet" type="text/css" />
<link href="{THEME_PATH}assets/global/css/login.min.css?v={CMF_UPDATE_TIME}" rel="stylesheet" type="text/css" />
<script type="text/javascript">var admin_file = '{SELF}'; var assets_path = '{THEME_PATH}assets/';</script>
<script src="{THEME_PATH}assets/global/plugins/jquery.min.js?v={CMF_UPDATE_TIME}" type="text/javascript"></script>
<script src="{THEME_PATH}assets/global/plugins/bootstrap/js/bootstrap.min.js?v={CMF_UPDATE_TIME}" type="text/javascript"></script>
<script src="{THEME_PATH}assets/global/scripts/app.min.js?v={CMF_UPDATE_TIME}" type="text/javascript"></script>
<script src="{LANG_PATH}lang.js" type="text/javascript"></script>
<script src="{THEME_PATH}assets/js/cms.js?v={CMF_UPDATE_TIME}" type="text/javascript"></script>
<style>
body.page-container-bg-solid.login {
min-height: 100vh;
margin: 0;
background: linear-gradient(165deg, #e3f0ff 0%, #eef2f7 42%, #dfe8f3 100%) !important;
background-attachment: fixed;
}
.portlet-body.text-center {
text-align: center;
}
.page-container-bg-solid.login .page-content {
background: none !important;
}
.page-container-bg-solid.login .page-content-wrapper .page-content {
margin-left: 0 !important;
padding-top: 0;
padding-bottom: 48px;
}
.page-container-bg-solid.login > .logo {
margin: 36px auto 28px;
text-align: center;
}
.page-container-bg-solid.login > .logo img {
width: auto;
vertical-align: middle;
}
.page-container-bg-solid.login > .logo a {
display: inline-block;
text-decoration: none;
}
.page-container-bg-solid.login .page-content .container {
width: 100%;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.page-container-bg-solid.login .portlet.light {
border: none;
border-radius: 12px;
box-shadow: 0 8px 32px rgba(15, 45, 90, 0.08), 0 1px 0 rgba(255, 255, 255, 0.9) inset;
overflow: hidden;
background: #fff;
}
.page-container-bg-solid.login .portlet.light > .portlet-title {
border-bottom: 1px solid #eef1f5;
padding: 18px 24px 14px;
}
.page-container-bg-solid.login .portlet.light > .portlet-body {
padding: 20px 24px 8px;
}
.page-container-bg-solid.login .portlet.light .portlet-body.text-center {
padding: 16px 24px 28px;
border-top: 1px solid #f4f6f9;
background: #fafbfd;
}
.page-container-bg-solid.login .portlet.light .portlet-body.text-center .btn,
.page-container-bg-solid.login .portlet.light .portlet-body.text-center .btn:hover,
.page-container-bg-solid.login .portlet.light .portlet-body.text-center .btn:focus,
.page-container-bg-solid.login .portlet.light .portlet-body.text-center .btn:active {
color: #111 !important;
}
.page-container-bg-solid.login .portlet.light .portlet-body.text-center#dr_loading {
font-size: 14px;
font-weight: 500;
color: #1a6cb5 !important;
background: linear-gradient(180deg, #f0f7ff 0%, #e8f2fc 100%);
border-top: 1px dashed rgba(26, 108, 181, 0.25);
}
.page-container-bg-solid.login .form-horizontal .form-group {
border-color: #f0f2f5;
}
.page-container-bg-solid.login .form-control-static {
color: #4a5568;
}
</style>
</head>
<body class="page-container-bg-solid login" style="background: #e3f0ff !important;">
<div class="logo">
<a href="javascript:;"><img src="{THEME_PATH}assets/logo-web.png" alt=""></a>
</div>
<div class="page-container">
<div class="page-content-wrapper">
<div class="page-content">
<div class="container">
<div class="page-content-inner">