working on admin panel

This commit is contained in:
printempw 2016-07-22 19:36:24 +08:00
parent b4f1e12c00
commit 0de5c4ad53
17 changed files with 1128 additions and 44 deletions

View File

@ -0,0 +1,125 @@
<?php
namespace App\Controllers;
use App\Models\User;
use App\Models\UserModel;
use App\Exceptions\E;
use Option;
use Utils;
use View;
class AdminController extends BaseController
{
public function index()
{
echo View::make('admin.index')->render();
}
public function ajaxHandler()
{
$action = isset($_GET['action']) ? $_GET['action'] : "";
if ($action == "color") {
Utils::checkPost(['color_scheme']);
$color_scheme = str_replace('_', '-', $_POST['color_scheme']);
Option::set('color_scheme', $color_scheme);
View::json('修改配色成功', 0);
}
$user = new User('', Utils::getValue('uid', $_POST));
if (!$user->is_registered)
throw new E('用户不存在', 1);
if ($action == "email") {
Utils::checkPost(['email']);
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
View::json('邮箱格式错误', 3);
}
if ($user->setEmail($_POST['email']))
View::json('邮箱修改成功', 0);
} if ($action == "nickname") {
Utils::checkPost(['nickname']);
if (Utils::convertString($_POST['nickname']) != $_POST['nickname'])
View::json('无效的昵称。昵称中包含了奇怪的字符。', 1);
if ($user->setNickName($_POST['nickname']))
View::json('昵称已成功设置为 '.$_POST['nickname'], 0);
} else if ($action == "password") {
Utils::checkPost(['password']);
if (\Validate::checkValidPwd($_POST['password'])) {
if ($user->changePasswd($_POST['password']))
View::json('密码修改成功', 0);
}
} else if ($action == "score") {
Utils::checkPost(['score']);
if ($user->setScore($_POST['score']))
View::json('积分修改成功', 0);
} else if ($action == "delete") {
if ($user->delete())
View::json('账号已被成功删除', 0);
} else {
throw new E('Illegal parameters', 1);
}
}
public function customize()
{
echo View::make('admin.customize')->render();
}
public function options()
{
echo View::make('admin.options')->render();
}
public function users()
{/*
for ($i=0; $i < 60; $i++) {
$user = new UserModel();
$user->email = Utils::generateRndString(6)."@".Utils::generateRndString(3).".com";
$user->nickname = Utils::generateRndString(5);
$user->score = 666;
$user->ip = '111.111.111.111';
$user->permission = "0";
$user->register_at = Utils::getTimeFormatted();
$user->save();
echo "Seed: ".$user->email." added. <br />";
}
exit;*/
$page = isset($_GET['page']) ? $_GET['page'] : 1;
$filter = isset($_GET['filter']) ? $_GET['filter'] : "";
if ($filter == "") {
$users = UserModel::orderBy('uid');
$total_pages = ceil($users->count() / 30);
$users = $users->skip(($page - 1) * 30)->take(30)->get();
} else {
$users = UserModel::like('nickname', $filter)->orderBy('uid');
$total_pages = ceil($users->count() / 30);
$users = $users->skip(($page - 1) * 30)->take(30)->get();
}
echo View::make('admin.users')->with('users', $users)
->with('page', $page)
->with('total_pages', $total_pages)
->render();
}
public function players()
{
echo View::make('admin.players')->render();
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Middlewares;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
class CheckAdminMiddleware implements IMiddleware
{
public function handle(Request $request)
{
$user = (new CheckLoggedInMiddleware)->handle($request);
if (!$user->is_admin) {
\Http::redirect('../user', '看起来你并不是管理员哦');
}
}
}

View File

@ -5,8 +5,6 @@ namespace App\Middlewares;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
use App\Models\User;
use App\Exceptions\E;
use Utils;
class CheckLoggedInMiddleware implements IMiddleware
{
@ -18,10 +16,11 @@ class CheckLoggedInMiddleware implements IMiddleware
}
if (isset($_SESSION['email'])) {
if ($_SESSION['token'] != (new User($_SESSION['email']))->getToken())
{
$user = new User($_SESSION['email']);
if ($_SESSION['token'] != $user->getToken())
\Http::redirect('../auth/login', '无效的 token请重新登录~');
}
return $user;
} else {
\Http::redirect('../auth/login', '非法访问,请先登录');
}

View File

@ -4,9 +4,7 @@ namespace App\Middlewares;
use Pecee\Http\Middleware\IMiddleware;
use Pecee\Http\Request;
use App\Models\User;
use App\Models\PlayerModel;
use App\Exceptions\E;
class CheckPlayerExistMiddleware implements IMiddleware
{

View File

@ -4,7 +4,6 @@ namespace App\Middlewares;
use \Pecee\Http\Middleware\IMiddleware;
use \Pecee\Http\Request;
use View;
use App\Exceptions\E;
class CheckPostMiddleware implements IMiddleware

View File

@ -41,33 +41,37 @@ class Closet
{
$this->uid = $uid;
$this->eloquent_model = ClosetModel::find($uid);
$this->textures = json_decode($this->eloquent_model->textures, true);
$this->textures = is_null($this->textures) ? [] : $this->textures;
$textures_invalid = [];
if ($this->eloquent_model) {
$this->textures = json_decode($this->eloquent_model->textures, true);
$this->textures = is_null($this->textures) ? [] : $this->textures;
foreach ($this->textures as $texture) {
$result = Texture::find($texture['tid']);
if ($result) {
// user custom texture name
$result->name = $texture['name'];
$textures_invalid = [];
if ($result->type == "cape") {
$this->textures_cape[] = $result;
foreach ($this->textures as $texture) {
$result = Texture::find($texture['tid']);
if ($result) {
// user custom texture name
$result->name = $texture['name'];
if ($result->type == "cape") {
$this->textures_cape[] = $result;
} else {
$this->textures_skin[] = $result;
}
} else {
$this->textures_skin[] = $result;
$textures_invalid[] = $texture['tid'];
continue;
}
} else {
$textures_invalid[] = $texture['tid'];
continue;
}
foreach ($textures_invalid as $tid) {
$this->remove($tid);
}
unset($textures_invalid);
}
foreach ($textures_invalid as $tid) {
$this->remove($tid);
}
unset($textures_invalid);
}
/**

View File

@ -232,4 +232,9 @@ class UserModel extends \Illuminate\Database\Eloquent\Model
public $primaryKey = 'uid';
protected $table = 'users';
public $timestamps = false;
public function scopeLike($query, $field, $value)
{
return $query->where($field, 'LIKE', "%$value%");
}
}

View File

@ -16,8 +16,10 @@ class Option
}
public static function set($key, $value) {
$option = OptionModel::firstOrCreate('option_name', $key);
$option->update(['option_value' => $value]);
$option = OptionModel::where('option_name', $key)->first();
if (!$option) throw new E('Unexistent option.', 1);
$option->option_value = $value;
return $option->save();
}
public static function add($key, $value) {
@ -47,4 +49,6 @@ class OptionModel extends Model
{
protected $table = 'options';
public $timestamps = false;
protected $fillable = ['option_value'];
}

163
assets/src/js/admin.js Normal file
View File

@ -0,0 +1,163 @@
/*
* @Author: printempw
* @Date: 2016-07-22 14:02:44
* @Last Modified by: printempw
* @Last Modified time: 2016-07-22 19:27:20
*/
'use strict';
$(document).ready(function() {
$('input').iCheck({
checkboxClass: 'icheckbox_square-blue'
});
});
$('#layout-skins-list [data-skin]').click(function(e) {
e.preventDefault();
var skin_name = $(this).data('skin');
$('body').removeClass(current_skin).addClass(skin_name);
current_skin = skin_name;
});
$('#color-submit').click(function() {
$.ajax({
type: "POST",
url: "../admin?action=color",
dataType: "json",
data: { "color_scheme": current_skin },
success: function(json) {
if (json.errno == 0)
toastr.success(json.msg);
else
toastr.warning(json.msg);
},
error: function(json) {
showModal(json.responseText.replace(/\n/g, '<br />'), 'Fatal Error请联系作者', 'danger');
}
});
});
$('#page-select').on('change', function() {
window.location = "?page=" + $(this).val();
});
function changeUserEmail(uid) {
var email = prompt("请输入新邮箱:");
if (!email) return;
$.ajax({
type: "POST",
url: "../admin?action=email",
dataType: "json",
data: { 'uid': uid, 'email': email },
success: function(json) {
if (json.errno == 0) {
$($('tr#'+uid+' > td')[1]).html(email);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: function(json) {
showModal(json.responseText.replace(/\n/g, '<br />'), 'Fatal Error请联系作者', 'danger');
}
});
}
function changeUserNickName(uid) {
var nickname = prompt("请输入新昵称:");
if (!nickname) return;
$.ajax({
type: "POST",
url: "../admin?action=nickname",
dataType: "json",
data: { 'uid': uid, 'nickname': nickname },
success: function(json) {
if (json.errno == 0) {
$($('tr#'+uid+' > td')[2]).html(nickname);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: function(json) {
showModal(json.responseText.replace(/\n/g, '<br />'), 'Fatal Error请联系作者', 'danger');
}
});
}
function changeUserPwd(uid) {
var password = prompt("请输入新密码:");
if (!password) return;
$.ajax({
type: "POST",
url: "../admin?action=password",
dataType: "json",
data: { 'uid': uid, 'password': password },
success: function(json) {
if (json.errno == 0)
toastr.success(json.msg);
else
toastr.warning(json.msg);
},
error: function(json) {
showModal(json.responseText.replace(/\n/g, '<br />'), 'Fatal Error请联系作者', 'danger');
}
});
}
function changeUserScore(uid, score) {
$.ajax({
type: "POST",
url: "../admin?action=score",
dataType: "json",
data: { 'uid': uid, 'score': score },
success: function(json) {
if (json.errno == 0) {
$('tr#'+uid+' > td > .score').val(score);
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: function(json) {
showModal(json.responseText.replace(/\n/g, '<br />'), 'Fatal Error请联系作者', 'danger');
}
});
}
function deleteUserAccount(uid) {
if (!window.confirm('真的要删除此用户吗?此操作不可恢复')) return;
$.ajax({
type: "POST",
url: "../admin?action=delete",
dataType: "json",
data: { 'uid': uid },
success: function(json) {
if (json.errno == 0) {
$('tr#'+uid).remove();
toastr.success(json.msg);
} else {
toastr.warning(json.msg);
}
},
error: function(json) {
showModal(json.responseText.replace(/\n/g, '<br />'), 'Fatal Error请联系作者', 'danger');
}
});
}
$('.score').on('keypress', function(event){
if (event.which == 13)
changeUserScore($(this).parent().parent().attr('id'), $(this).val());
}).click(function() {
$(this).tooltip('show');
})

View File

@ -0,0 +1,51 @@
/*
* @Author: printempw
* @Date: 2016-07-22 14:08:41
* @Last Modified by: printempw
* @Last Modified time: 2016-07-22 19:33:23
*/
@import "style.scss";
.info-box > a {
color: #333;
font-size: 18px;
}
.key {
vertical-align: middle !important;
}
.value {
width: 70%;
}
td[class='key'], td[class='value'] {
border-top: 0 !important;
}
.btn-group {
.btn {
margin-right: 10px;
}
}
#page-select {
padding-left: 0;
margin: 0 20px 0 0;
border-radius: 4px;
padding: 5.5px 14px;
}
input.score {
width: 80px;
}
.user-search-form {
display: inline;
}
.user-search-input {
display: inline;
width: 30%;
float: right;
margin: 0;
}

View File

@ -9,21 +9,19 @@
*/
$menu['user'] = array(
1 => ['title' => '仪表盘', 'link' => '/user', 'icon' => 'fa-dashboard'],
2 => ['title' => '我的衣柜', 'link' => '/user/closet', 'icon' => 'fa-star'],
3 => ['title' => '角色管理', 'link' => '/user/player', 'icon' => 'fa-users'],
4 => ['title' => '配置生成', 'link' => '/user/config', 'icon' => 'fa-book'],
5 => ['title' => '个人资料', 'link' => '/user/profile', 'icon' => 'fa-user']
1 => ['title' => '仪表盘', 'link' => '/user', 'icon' => 'fa-dashboard'],
2 => ['title' => '我的衣柜', 'link' => '/user/closet', 'icon' => 'fa-star'],
3 => ['title' => '角色管理', 'link' => '/user/player', 'icon' => 'fa-users'],
4 => ['title' => '配置生成', 'link' => '/user/config', 'icon' => 'fa-book'],
5 => ['title' => '个人资料', 'link' => '/user/profile', 'icon' => 'fa-user']
);
$menu['admin'] = array(
1 => ['title' => '仪表盘', 'link' => '/admin', 'icon' => 'fa-dashboard'],
2 => ['title' => '用户管理', 'link' => '/admin/manage/user', 'icon' => 'fa-users'],
3 => ['title' => '角色管理', 'link' => '/admin/manage/player', 'icon' => 'fa-users'],
4 => ['title' => '材质管理', 'link' => '/admin/manage/texture', 'icon' => 'fa-users'],
5 => ['title' => '个性化', 'link' => '/admin/customize', 'icon' => 'fa-paint-brush'],
6 => ['title' => '站点配置', 'link' => '/admin/options', 'icon' => 'fa-cog'],
7 => ['title' => '检查更新', 'link' => '/admin/update', 'icon' => 'fa-arrow-up']
1 => ['title' => '仪表盘', 'link' => '/admin', 'icon' => 'fa-dashboard'],
2 => ['title' => '用户管理', 'link' => '/admin/users', 'icon' => 'fa-users'],
3 => ['title' => '角色管理', 'link' => '/admin/players', 'icon' => 'fa-gamepad'],
4 => ['title' => '个性化', 'link' => '/admin/customize', 'icon' => 'fa-paint-brush'],
5 => ['title' => '站点配置', 'link' => '/admin/options', 'icon' => 'fa-cog']
);
return $menu;

View File

@ -41,7 +41,7 @@ Route::group(['prefix' => 'auth'], function()
/**
* User Center
*/
Route::group(['prefix' => 'user', 'middleware' => 'App\Middlewares\CheckLoggedInMiddleware'], function()
Route::group(['middleware' => 'App\Middlewares\CheckLoggedInMiddleware', 'prefix' => 'user'], function()
{
Route::all ('', 'UserController@index');
Route::all ('/sign', 'UserController@sign');
@ -82,7 +82,7 @@ Route::group(['prefix' => 'skinlib'], function()
Route::post('/privacy/{tid}', 'SkinlibController@privacy');
Route::group(['middleware' => 'App\Middlewares\CheckLoggedInMiddleware'], function()
Route::group(['middleware' => 'App\Middlewares\CheckLoggedInMiddleware'], function()
{
Route::get ('/upload', 'SkinlibController@upload');
Route::post('/upload', 'SkinlibController@handleUpload');
@ -91,10 +91,26 @@ Route::group(['prefix' => 'skinlib'], function()
});
});
/**
* Admin Panel
*/
Route::group(['middleware' => 'App\Middlewares\CheckAdminMiddleware', 'prefix' => 'admin'], function()
{
Route::get('/', 'AdminController@index');
Route::post('/', 'AdminController@ajaxHandler');
Route::all('/customize', 'AdminController@customize');
Route::all('/options', 'AdminController@options');
Route::get('/users', 'AdminController@users');
Route::get('/players', 'AdminController@players');
});
/**
* Resources
*/
Route::group(['middleware' => 'App\Middlewares\CheckPlayerExistMiddleware'], function()
Route::group(['middleware' => 'App\Middlewares\CheckPlayerExistMiddleware'], function()
{
// Json profile
Route::get('/{player_name}.json', 'TextureController@json')->where(['player_name' => '[^\\/]+?']);

View File

@ -0,0 +1,186 @@
@extends('admin.master')
@section('title', '个性化')
@section('style')
<link rel="stylesheet" href="../assets/libs/skins/_all-skins.min.css">
@endsection
@section('content')
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
个性化
<small>Customize</small>
</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-md-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">更改配色</h3>
</div><!-- /.box-header -->
<div class="box-body no-padding">
<table id="layout-skins-list" class="table table-striped bring-up nth-2-center">
<tbody>
<tr>
<td>蓝色主题(默认)</td>
<td><a href="#" data-skin="skin-blue" class="btn btn-primary btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>蓝色主题-白色侧边栏</td>
<td><a href="#" data-skin="skin-blue-light" class="btn btn-primary btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>黄色主题</td>
<td><a href="#" data-skin="skin-yellow" class="btn btn-warning btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>黄色主题-白色侧边栏</td>
<td><a href="#" data-skin="skin-yellow-light" class="btn btn-warning btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>绿色主题</td>
<td><a href="#" data-skin="skin-green" class="btn btn-success btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>绿色主题-白色侧边栏</td>
<td><a href="#" data-skin="skin-green-light" class="btn btn-success btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>基佬紫</td>
<td><a href="#" data-skin="skin-purple" class="btn bg-purple btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>紫色主题-白色侧边栏</td>
<td><a href="#" data-skin="skin-purple-light" class="btn bg-purple btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>喜庆红(笑)</td>
<td><a href="#" data-skin="skin-red" class="btn btn-danger btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>红色主题-白色侧边栏</td>
<td><a href="#" data-skin="skin-red-light" class="btn btn-danger btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>高端黑</td>
<td><a href="#" data-skin="skin-black" class="btn bg-black btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
<tr>
<td>黑色主题-白色侧边栏</td>
<td><a href="#" data-skin="skin-black-light" class="btn bg-black btn-xs"><i class="fa fa-eye"></i></a></td>
</tr>
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
<button id="color-submit" class="btn btn-primary">提交</button>
</div>
</div><!-- /.box -->
</div>
<div class="col-md-6">
<div class="box box-warning">
<div class="box-header with-border">
<h3 class="box-title">首页配置</h3>
</div><!-- /.box-header -->
<form method="post" action="../admin/customize">
<input type="hidden" name="option" value="adapter">
<div class="box-body">
<?php
if (isset($_POST['home_pic_url'])) {
if (!isset($_POST['show_footer_copyright'])) $_POST['show_footer_copyright'] = '0';
Option::set('home_pic_url', $_POST['home_pic_url']);
Option::set('show_footer_copyright', $_POST['show_footer_copyright']);
echo '<div class="callout callout-success">设置已保存。</div>';
} ?>
<table class="table">
<tbody>
<tr>
<td class="key">首页图片地址</td>
<td class="value">
<input type="text" title="相对与首页的路径或绝对路径。" data-toggle="tooltip" data-placement="bottom" class="form-control" name="home_pic_url" value="<?php echo Option::get('home_pic_url'); ?>">
</td>
</tr>
<tr>
<td class="key">版权信息</td>
<td class="value">
<label for="show_footer_copyright" title="推荐开启,求扩散 qwq" data-toggle="tooltip" data-placement="top">
<input <?php echo (Option::get('show_footer_copyright') == '1') ? 'checked="true"' : ''; ?> type="checkbox" id="show_footer_copyright" name="show_footer_copyright" value="1"> 显示页面右下角的版权信息
</label>
</td>
</tr>
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
<button type="submit" name="submit" class="btn btn-primary">提交</button>
</div>
</form>
</div>
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">自定义 CSS/JavaScript
<i class="fa fa-question-circle" data-toggle="tooltip" data-placement="bottom" title="字符串将会被转义"></i>
</h3>
</div><!-- /.box-header -->
<form method="post" action="../admin/customize">
<input type="hidden" name="option" value="adapter">
<div class="box-body">
<?php
if (isset($_POST['custom_css']) && isset($_POST['custom_js'])) {
Option::set('custom_css', Utils::convertString($_POST['custom_css']));
Option::set('custom_js', Utils::convertString($_POST['custom_js']));
echo '<div class="callout callout-success">设置已保存。</div>';
} else {
echo '<div class="callout callout-info">内容将会被追加至每个页面的 &lt;style&gt; 和 &lt;script&gt; 标签中</div>';
} ?>
<table class="table">
<tbody>
<tr>
<td class="key">CSS</td>
<td class="value">
<textarea name="custom_css" class="form-control" rows="3"><?php echo Option::get('custom_css'); ?></textarea>
</td>
</tr>
<tr>
<td class="key">JavaScript</td>
<td class="value">
<textarea name="custom_js" class="form-control" rows="3"><?php echo Option::get('custom_js'); ?></textarea>
</td>
</tr>
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
<button type="submit" name="submit" class="btn btn-primary">提交</button>
</div>
</form>
</div>
</div>
</div>
</section><!-- /.content -->
</div><!-- /.content-wrapper -->
<script type="text/javascript">
var current_skin = "{{ Option::get('color_scheme') }}";
</script>
@endsection

View File

@ -0,0 +1,73 @@
@extends('admin.master')
@section('title', '仪表盘')
@section('content')
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
仪表盘
<small>Dashboard</small>
</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-6">
<div class="info-box">
<a href="../admin/user">
<span class="info-box-icon bg-aqua"><i class="fa fa-users"></i></span>
<div class="info-box-content">
<span class="info-box-text">注册用户</span>
<span class="info-box-number">{{ App\Models\UserModel::all()->count() }}</span>
</div><!-- /.info-box-content -->
</a>
</div><!-- /.info-box -->
</div>
<div class="col-md-6">
<div class="info-box">
<a href="../admin/player">
<div class="info-box-content" style="margin-left: 0;">
<span class="info-box-text">角色总数</span>
<span class="info-box-number">{{ App\Models\PlayerModel::all()->count() }}</span>
</div><!-- /.info-box-content -->
</a>
</div><!-- /.info-box -->
</div>
</div>
<div class="info-box">
<span class="info-box-icon bg-green"><i class="fa fa-files-o"></i></span>
<div class="info-box-content">
<span class="info-box-text">上传材质总数</span>
<span class="info-box-number">{{ \Storage::getFileNum(BASE_DIR."/textures/") }}</span>
</div><!-- /.info-box-content -->
</div><!-- /.info-box -->
<div class="info-box">
<span class="info-box-icon bg-yellow"><i class="fa fa-hdd-o"></i></span>
<div class="info-box-content">
<span class="info-box-text">占用空间大小</span>
<span class="info-box-number">{{ floor(\Storage::getDirSize(BASE_DIR."/textures/")/1024)."KB" }}</span>
</div><!-- /.info-box-content -->
</div><!-- /.info-box -->
</div>
</div>
</section><!-- /.content -->
</div><!-- /.content-wrapper -->
@endsection

View File

@ -0,0 +1,141 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>@yield('title') - {{ Option::get('site_name') }}</title>
<link rel="shortcut icon" href="../assets/images/favicon.ico">
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- App Styles -->
<link rel="stylesheet" href="../assets/dist/app.min.css">
<!-- AdminLTE Skins -->
<link rel="stylesheet" href="../assets/libs/skins/{{ Option::get('color_scheme') }}.min.css">
<link rel="stylesheet" href="../assets/dist/css/admin.css">
@yield('style')
<style>{{ Option::get('custom_css') }}</style>
</head>
<?php $user = new App\Models\User($_SESSION['email']); ?>
<body class="hold-transition {{ Option::get('color_scheme') }} sidebar-mini">
<div class="wrapper">
<!-- Main Header -->
<header class="main-header">
<!-- Logo -->
<a href="{{ Option::get('site_url') }}" class="logo">
<!-- mini logo for sidebar mini 50x50 pixels -->
<span class="logo-mini"> <i class="fa fa-bookmark"></i> </span>
<!-- logo for regular state and mobile devices -->
<span class="logo-lg">{{ Option::get('site_name') }}</span>
</a>
<!-- Header Navbar -->
<nav class="navbar navbar-static-top" role="navigation">
<!-- Sidebar toggle button-->
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
<span class="sr-only">Toggle navigation</span>
</a>
<!-- Navbar Right Menu -->
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<!-- User Account Menu -->
<li class="dropdown user user-menu">
<!-- Menu Toggle Button -->
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-user"></i>
<!-- hidden-xs hides the username on small devices so only the image appears. -->
<span class="hidden-xs nickname">{{ ($user->getNickName() == '') ? $_SESSION['email'] : $user->getNickName() }}</span>
</a>
<ul class="dropdown-menu">
<!-- The user image in the menu -->
<li class="user-header">
<img src="../avatar/128/{{ base64_encode($_SESSION['email']) }}.png" alt="User Image">
<p>{{ $_SESSION['email'] }}</p>
</li>
<!-- Menu Footer-->
<li class="user-footer">
<div class="pull-left">
<a href="../user/profile" class="btn btn-default btn-flat">我的资料</a>
</div>
<div class="pull-right">
<a href="javascript:logout();" class="btn btn-default btn-flat">登出</a>
</div>
</li>
</ul>
</li>
</ul>
</div>
</nav>
</header>
<!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar">
<!-- sidebar: style can be found in sidebar.less -->
<section class="sidebar">
<!-- Sidebar user panel (optional) -->
<div class="user-panel">
<div class="pull-left image">
<img src="../avatar/45/<?php echo base64_encode($_SESSION['email']); ?>.png" alt="User Image">
</div>
<div class="pull-left info">
<p class="nickname">{{ ($user->getNickName() == '') ? $_SESSION['email'] : $user->getNickName() }}</p>
<i class="fa fa-circle text-success"></i> Online
</div>
</div>
<!-- Sidebar Menu -->
<ul class="sidebar-menu">
<li class="header">管理面板</li>
<?php $menu = require BASE_DIR."/config/menu.php"; ?>
@foreach ($menu['admin'] as $key => $value)
<li class="{{ ($__env->yieldContent('title') == $value['title']) ? 'active' : '' }}">
<a href="{{ $value['link'] }}"><i class="fa {{ $value['icon'] }}"></i> <span>{{ $value['title'] }}</span></a>
</li>
@endforeach
<li class="header">皮肤库</li>
<li><a href="../admin/texture"><i class="fa fa-archive"></i> <span>材质管理</span></a></li>
@if ($user->is_admin)
<li class="header">返回</li>
<li><a href="../user"><i class="fa fa-user"></i> <span>用户中心</span></a></li>
@endif
</ul><!-- /.sidebar-menu -->
</section>
<!-- /.sidebar -->
</aside>
@yield('content')
<!-- Main Footer -->
<footer class="main-footer">
@if (Option::get('show_footer_copyright'))
<!-- To the right -->
<div class="pull-right hidden-xs">
Powered with ❤ by <a href="https://github.com/printempw/blessing-skin-server">Blessing Skin Server</a>.
</div>
@endif
<!-- Default to the left -->
<strong>Copyright &copy; 2016 <a href="{{ Option::get('site_url') }}">{{ Option::get('site_name') }}</a>.</strong> All rights reserved.
</footer>
</div><!-- ./wrapper -->
<!-- App Scripts -->
<script type="text/javascript" src="../assets/dist/app.min.js"></script>
<script type="text/javascript" src="../assets/dist/js/admin.js"></script>
@yield('script')
<script>{{ Option::get('custom_js') }}</script>
</body>
</html>

View File

@ -0,0 +1,188 @@
@extends('admin.master')
@section('title', '站点配置')
@section('style')
<style type="text/css">
.box-body > textarea {
height: 200px;
}
</style>
@endsection
@section('content')
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
站点配置
<small>Options</small>
</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-md-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">常规选项</h3>
</div><!-- /.box-header -->
<form method="post" action="../admin/options">
<input type="hidden" name="option" value="general">
<div class="box-body">
<?php
if (isset($_POST['option']) && ($_POST['option'] == "general")) {
// pre-set user_can_register because it will not be posted if not checked
$_POST['user_can_register'] = isset($_POST['user_can_register']) ? $_POST['user_can_register'] : "0";
$_POST['allow_chinese_playername'] = isset($_POST['allow_chinese_playername']) ? $_POST['allow_chinese_playername'] : "0";
foreach ($_POST as $key => $value) {
// remove slash if site_url is ended with slash
if ($key == "site_url" && substr($value, -1) == "/")
$value = substr($value, 0, -1);
if ($key != "option" && $key != "submit")
Option::set($key, $value);
}
echo '<div class="callout callout-success">设置已保存。</div>';
} ?>
<table class="table">
<tbody>
<tr>
<td class="key">站点标题</td>
<td class="value">
<input type="text" class="form-control" name="site_name" value="{{ Option::get('site_name') }}">
</td>
</tr>
<tr>
<td class="key">站点描述</td>
<td class="value">
<input type="text" class="form-control" name="site_description" value="{{ Option::get('site_description') }}">
</td>
</tr>
<tr title="以 http:// 开头,不要以 / 结尾" data-toggle="tooltip" data-placement="top">
<td class="key">站点地址URL</td>
<td class="value">
<input type="text" class="form-control" name="site_url" value="{{ Option::get('site_url') }}">
</td>
</tr>
<tr>
<td class="key">开放注册</td>
<td class="value">
<label for="user_can_register">
<input {{ (Option::get('user_can_register') == '1') ? 'checked="true"' : '' }} type="checkbox" id="user_can_register" name="user_can_register" value="1"> 任何人都可以注册
</label>
</td>
</tr>
<tr>
<td class="key">每个 IP 限制注册数</td>
<td class="value">
<input type="text" class="form-control" name="regs_per_ip" value="{{ Option::get('regs_per_ip') }}">
</td>
</tr>
<tr>
<td class="key">新用户默认积分</td>
<td class="value">
<div class="input-group">
<input type="text" class="form-control" name="user_initial_score" value="{{ Option::get('user_initial_score') }}">
</div>
</td>
</tr>
<tr>
<td class="key">角色名</td>
<td class="value">
<label for="allow_chinese_playername">
<input {{ (Option::get('allow_chinese_playername') == '1') ? 'checked="true"' : '' }} type="checkbox" id="allow_chinese_playername" name="allow_chinese_playername" value="1"> 允许中文角色名
</label>
</td>
</tr>
<tr>
<td class="key">首选 JSON API</td>
<td class="value">
<select class="form-control" name="api_type">
<option {{ (Option::get('api_type') == '0') ? 'selected="selected"' : '' }} value="0">CustomSkinLoader API</option>
<option {{ (Option::get('api_type') == '1') ? 'selected="selected"' : '' }} value="1">UniversalSkinAPI</option>
</select>
</td>
</tr>
<tr title="留空以停用评论功能" data-toggle="tooltip" data-placement="top">
<td class="key">Disqus 短域名</td>
<td class="value">
<input type="text" class="form-control" name="disqus-shortname" value="{{ Option::get('disqus-shortname') }}">
</td>
</tr>
<tr>
<td class="key">签到间隔时间</td>
<td class="value">
<div class="input-group">
<input type="text" class="form-control" name="sign_gap_time" value="{{ Option::get('sign_gap_time') }}">
<span class="input-group-addon">小时</span>
</div>
</td>
</tr>
</tbody>
</table>
</div><!-- /.box-body -->
<div class="box-footer">
<button type="submit" name="submit" class="btn btn-primary">提交</button>
</div>
</form>
</div>
</div>
<div class="col-md-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">站点公告</h3>
</div><!-- /.box-header -->
<form method="post" action="../admin/options">
<input type="hidden" name="option" value="announcement">
<div class="box-body">
<?php
if (isset($_POST['option']) && ($_POST['option'] == "announcement")) {
Option::set('announcement', $_POST['announcement']);
echo '<div class="callout callout-success">设置已保存。</div>';
} ?>
<textarea name="announcement" class="form-control" rows="3">{{ Option::get('announcement') }}</textarea>
</div><!-- /.box-body -->
<div class="box-footer">
<button type="submit" name="submit" class="btn btn-primary">提交</button>
</div>
</form>
</div>
<div class="box box-warning">
<div class="box-header with-border">
<h3 class="box-title">数据对接配置</h3>
</div><!-- /.box-header -->
<form method="post" action="../admin/options">
<input type="hidden" name="option" value="adapter">
<div class="box-body">
<p>当前版本数据对接不可用。</p>
</div><!-- /.box-body -->
</form>
</div>
</div>
</div>
</section><!-- /.content -->
</div><!-- /.content-wrapper -->
@endsection

View File

@ -0,0 +1,116 @@
@extends('admin.master')
@section('title', '用户管理')
@section('content')
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
@if (isset($_GET['filter']))
搜索结果:{{ $_GET['filter'] }}
@else
用户管理
@endif
<small>User Management</small>
<form method="get" action="" class="user-search-form">
<input type="text" name="filter" class="form-control user-search-input" placeholder="输入昵称,回车搜索。" value="<?php echo Utils::getValue('search-username', $_POST); ?>">
</form>
</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="box">
<div class="box-body table-responsive no-padding">
<table class="table table-hover">
<thead>
<tr>
<th>UID</th>
<th>邮箱</th>
<th>昵称</th>
<th>积分</th>
<th>注册时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@forelse($users as $user)
<tr id="{{ $user->uid }}">
<td>{{ $user->uid }}</td>
<td id="email">{{ $user->email }}</td>
<td id="nickname">{{ $user->nickname }}</td>
<td><input type="text" class="form-control score" value="{{ $user->score }}" title="输入修改后的积分,回车提交" data-placement="top"></td>
<td>{{ $user->register_at }}</td>
<td>
<div class="btn-group">
<button type="button" class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
更多操作 <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a href="javascript:changeUserEmail('{{ $user->uid }}');">修改邮箱</a></li>
<li><a href="javascript:changeUserNickName('{{ $user->uid }}');">修改昵称</a></li>
<li><a href="javascript:changeUserPwd('{{ $user->uid }}');">更改密码</a></li>
</ul>
</div>
<a class="btn btn-danger btn-sm"
@if ($user->permission == "1")
disabled="disabled" data-toggle="tooltip" data-placement="bottom" title="少年,不要作死哦"
@else
href="javascript:deleteUserAccount('{{ $user->uid }}');"
@endif>
删除用户
</a>
</td>
</tr>
@empty
<tr>
<td>0</td>
<td>无结果</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="box-footer">
<ul class="pagination pagination-sm no-margin pull-right">
<li><a href="?page=1">«</a></li>
@if ($page != 1)
<li><a href="?page={{ $page-1 }}">{{ $page - 1 }}</a></li>
@endif
<li><a href="?page={{ $page }}" class="active">{{ $page }}</a></li>
@if ($total_pages > $page)
<li><a href="?page={{ $page+1 }}">{{ $page+1 }}</a></li>
@endif
<li><a href="?page={{ $total_pages }}">»</a></li>
</ul>
<select id="page-select" class="pull-right">
@for ($i = 1; $i <= $total_pages; $i++)
@if ($i == $page)
<option value='{{ $i }}' selected="selected">{{ $i }}</option>
@else
<option value='{{ $i }}'>{{ $i }}</option>
@endif
@endfor
</select>
<p class="pull-right">第 {{ $page }} 页,共 {{ $total_pages }} 页</p>
</div>
</div>
</section><!-- /.content -->
</div><!-- /.content-wrapper -->
@endsection