no message

Mix
鹿和sa0ChunLuyu 3 years ago
parent 6b6b49d20b
commit 0f545e29d8

@ -5,7 +5,7 @@ charset = utf-8
end_of_line = lf end_of_line = lf
insert_final_newline = true insert_final_newline = true
indent_style = space indent_style = space
indent_size = 4 indent_size = 2
trim_trailing_whitespace = true trim_trailing_whitespace = true
[*.md] [*.md]

@ -1,10 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminAccountController extends Controller
{
//
}

@ -1,145 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\EditAdminAuthInput;
use App\Models\AdminAuth;
use App\Models\Auth;
use Login;
use Yo;
class AdminAuthController extends Controller
{
public function check()
{
$id = request()->post('id');
Login::admin($id);
return Yo::echo();
}
public function menu()
{
Login::admin(3);
$menu_group = Auth::select('id', 'name', 'title', 'icon', 'status')
->where('type', 1)->where('show', 1)->where('del', 2)
->orderBy('order', 'desc')->get();
$list = [];
foreach ($menu_group as $item) {
switch (Login::$info->admin_auth_id) {
case -1:
$auth_list = Auth::select('id', 'name', 'title', 'icon', 'status')->where('pid', $item->id)
->where('type', 2)->where('show', 1)->where('del', 2)
->orderBy('order', 'desc')->get();
break;
case 0:
$auth_list = Auth::select('id', 'name', 'title', 'icon', 'status')->where('pid', $item->id)
->where('type', 2)->where('check_type', 1)->where('show', 1)->where('del', 2)
->orderBy('order', 'desc')->get();
break;
default:
$admin_auth = AdminAuth::find(Login::$info->admin_auth_id);
$auth_ids = json_decode($admin_auth->auth_ids, true);
$auth_list = Auth::select('id', 'name', 'title', 'icon', 'status')
->where(function ($query) use ($auth_ids, $item) {
$query->whereIn('id', $auth_ids)->where('pid', $item->id)->where('type', 2)->where('check_type', 2)->where('show', 1)->where('del', 2);
})
->orWhere(function ($query) use ($auth_ids, $item) {
$query->where('type', 2)->where('pid', $item->id)->where('check_type', 1)->where('show', 1)->where('del', 2);
})
->orderBy('order', 'desc')->get();
}
if (count($auth_list) !== 0) $list[] = [
"id" => $item->id,
"name" => $item->name,
"title" => $item->title,
"icon" => $item->icon,
"status" => $item->status,
"children" => $auth_list
];
}
return Yo::echo([
'list' => $list
]);
}
public function all()
{
Login::admin(6);
$admin_auth_list = AdminAuth::select('id', 'name', 'del')->orderBy('updated_at', 'desc')->get();
return Yo::echo([
'list' => $admin_auth_list
]);
}
public function list()
{
Login::admin(5);
$admin_auth_list = AdminAuth::select('id', 'name', 'auth_ids', 'remark')->where('del', 2)->orderBy('updated_at', 'desc')->get();
$list = [];
foreach ($admin_auth_list as $item) {
$auth_ids_turn = [];
foreach (json_decode($item->auth_ids, true) as $i) {
$auth_ids_turn[] = intval($i);
}
$list[] = [
'id' => $item->id,
'name' => $item->name,
'auth_ids' => $item->auth_ids,
'auth_ids_turn' => $auth_ids_turn,
'remark' => $item->remark,
];
}
return Yo::echo([
'list' => $list
]);
}
public function delete()
{
Login::admin(5);
$ids = request()->post('ids');
AdminAuth::whereIn('id', $ids)->update([
'del' => 1
]);
return Yo::delete_echo($ids);
}
public function update(EditAdminAuthInput $request)
{
Login::admin(5);
$id = request()->post('id');
$name = $request->post('name');
$auth_ids = $request->post('auth_ids');
$remark = $request->post('remark');
$auth_ids_arr = [];
foreach ($auth_ids as $auth_id) $auth_ids_arr[] = (string)$auth_id;
$auth_ids_str = json_encode($auth_ids_arr, JSON_UNESCAPED_UNICODE);
if (mb_strlen($auth_ids_str) > 1000) Yo::error_echo(100007);
$admin_auth = AdminAuth::find($id);
if (!$admin_auth) Yo::error_echo(100008);
if ($admin_auth->del !== 2) Yo::error_echo(100008);
$admin_auth->name = $name;
$admin_auth->auth_ids = $auth_ids_str;
$admin_auth->remark = $remark ?? '';
$admin_auth->save();
return Yo::update_echo($admin_auth->id);
}
public function create(EditAdminAuthInput $request)
{
Login::admin(5);
$name = $request->post('name');
$auth_ids = $request->post('auth_ids');
$remark = $request->post('remark');
$auth_ids_arr = [];
foreach ($auth_ids as $auth_id) $auth_ids_arr[] = (string)$auth_id;
$auth_ids_str = json_encode($auth_ids_arr, JSON_UNESCAPED_UNICODE);
if (mb_strlen($auth_ids_str) > 1000) Yo::error_echo(100007);
$admin_auth = AdminAuth::create([
'name' => $name,
'auth_ids' => $auth_ids_str ?? '[]',
'remark' => $remark ?? '',
]);
return Yo::create_echo($admin_auth->id);
}
}

@ -2,219 +2,148 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Http\Requests\CreateAdminInput;
use App\Http\Requests\UpdateAdminNickname; use App\Http\Requests\UpdateAdminNickname;
use App\Http\Requests\UpdateAdminPassword; use App\Http\Requests\UpdateAdminPassword;
use App\Models\Admin; use App\Models\Admin;
use App\Models\AdminAccount; use App\Models\AdminAccount;
use App\Models\AdminAuth;
use App\Models\AdminToken; use App\Models\AdminToken;
use App\Models\Auth;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Yo; use Yo;
use Login; use Login;
class AdminController extends Controller class AdminController extends Controller
{ {
public function change_nickname(UpdateAdminNickname $request) public function change_password(UpdateAdminPassword $request)
{ {
Login::admin(7); Login::admin();
$nickname = $request->post('nickname'); $account_id = request()->post('account_id');
Admin::where('id', Login::$info->id)->update([ $password = $request->post('password');
'nickname' => $nickname $old_password = request()->post('old_password');
]); $admin_account = AdminAccount::where('id', $account_id)->where('admin_id', Login::$info->id)->first();
return Yo::update_echo(Login::$info->id); if (!$admin_account) Yo::error_echo(100002);
} if (!password_verify($old_password, $admin_account->secret)) Yo::error_echo(100010);
if ($old_password === $password) Yo::error_echo(100009);
public function change_password(UpdateAdminPassword $request) $admin_account->secret = bcrypt($password);
{ $admin_account->save();
Login::admin(7); return Yo::update_echo(Login::$info->id);
$id = request()->post('id'); }
$password = $request->post('password');
$old_password = request()->post('old_password'); public function change_nickname(UpdateAdminNickname $request)
$admin_account = AdminAccount::where('id', $id)->where('admin_id', Login::$info->id)->first(); {
if (!$admin_account) Yo::error_echo(100008); Login::admin();
if (!password_verify($old_password, $admin_account->secret)) Yo::error_echo(100017); $nickname = $request->post('nickname');
if ($old_password === $password) Yo::error_echo(100018); Admin::where('id', Login::$info->id)->update([
$admin_account->secret = bcrypt($password); 'nickname' => $nickname
$admin_account->save(); ]);
return Yo::update_echo(Login::$info->id); return Yo::update_echo(Login::$info->id);
} }
public function admin_info() public function menu()
{ {
Login::admin(6); Login::admin();
$id = request()->post('id'); $menu_group = Auth::select('id', 'name', 'title', 'icon', 'status')
$admin = Admin::select('id', 'nickname', 'admin_auth_id', 'status')->find($id); ->where('type', 1)->where('show', 1)->where('del', 2)
$admin_account = AdminAccount::select('id', 'account')->where('admin_id', $admin->id)->where('type', 1)->first(); ->orderBy('order', 'desc')->get();
return Yo::echo([ $list = [];
'info' => $admin, foreach ($menu_group as $item) {
'account' => $admin_account, switch (Login::$info->admin_auth_id) {
]); case -1:
} $auth_list = Auth::select('id', 'name', 'title', 'icon', 'status')->where('pid', $item->id)
->where('type', 2)->where('show', 1)->where('del', 2)
public function list() ->orderBy('order', 'desc')->get();
{ break;
Login::admin(6); case 0:
$status = request()->post('status'); $auth_list = Auth::select('id', 'name', 'title', 'icon', 'status')->where('pid', $item->id)
$search = request()->post('search'); ->where('type', 2)->where('check_type', 1)->where('show', 1)->where('del', 2)
$admin_list = Admin::select('id', 'nickname', 'status') ->orderBy('order', 'desc')->get();
->selectRaw("IFNULL((select account from admin_accounts where admins.id = admin_accounts.admin_id and del = 2),'') as account") break;
->where(function ($query) use ($status) { default:
if ($status != 0) $query->where('status', $status); $admin_auth = AdminAuth::find(Login::$info->admin_auth_id);
$auth_ids = json_decode($admin_auth->auth_ids, true);
$auth_list = Auth::select('id', 'name', 'title', 'icon', 'status')
->where(function ($query) use ($auth_ids, $item) {
$query->whereIn('id', $auth_ids)->where('pid', $item->id)->where('type', 2)->where('check_type', 2)->where('show', 1)->where('del', 2);
}) })
->where('del', 2) ->orWhere(function ($query) use ($auth_ids, $item) {
->where(function ($query) use ($search) { $query->where('type', 2)->where('pid', $item->id)->where('check_type', 1)->where('show', 1)->where('del', 2);
if ($search != '') $query->where('nickname', 'like', "%$search%"); })
})->paginate(15); ->orderBy('order', 'desc')->get();
return Yo::echo($admin_list); }
} if (count($auth_list) !== 0) $list[] = [
"id" => $item->id,
public function delete() "name" => $item->name,
{ "title" => $item->title,
Login::admin(6); "icon" => $item->icon,
$ids = request()->post('ids'); "status" => $item->status,
Admin::whereIn('id', $ids)->update([ "children" => $auth_list
'del' => 1 ];
]);
AdminAccount::whereIn('admin_id', $ids)->where('del', 2)->update([
'del' => 1
]);
return Yo::delete_echo($ids);
}
public function update_status()
{
Login::admin(6);
$id = request()->post('id');
if ($id == 1) Yo::error_echo(100016);
$status = request()->post('status');
if ($status !== 2) $status = 1;
Admin::where('id', $id)->update([
'status' => $status
]);
return Yo::update_echo($id);
}
public function update_auth()
{
Login::admin(6);
$id = request()->post('id');
if ($id == 1) Yo::error_echo(100016);
$admin_auth_id = request()->post('admin_auth_id');
Admin::where('id', $id)->update([
'admin_auth_id' => $admin_auth_id
]);
return Yo::update_echo($id);
}
public function update_nickname(UpdateAdminNickname $request)
{
Login::admin(6);
$id = request()->post('id');
$nickname = $request->post('nickname');
Admin::where('id', $id)->update([
'nickname' => $nickname
]);
return Yo::update_echo($id);
}
public function update_password(UpdateAdminPassword $request)
{
Login::admin(6);
$id = request()->post('id');
$password = $request->post('password');
AdminAccount::where('id', $id)->update([
'secret' => bcrypt($password)
]);
return Yo::update_echo($id);
}
public function create(CreateAdminInput $request)
{
Login::admin(6);
$nickname = $request->post('nickname');
$account = $request->post('account');
$password = $request->post('password');
$admin_auth_id = request()->post('admin_auth_id');
if ($admin_auth_id == -1) Yo::error_echo(100016);
$admin_account_check = AdminAccount::select('id')
->where('account', $account)
->where('type', 1)
->where('del', 2)
->first();
if ($admin_account_check) Yo::error_echo(100015);
$admin = new Admin();
$admin->nickname = $nickname;
$admin->admin_auth_id = $admin_auth_id;
$admin->save();
$admin_account = new AdminAccount();
$admin_account->admin_id = $admin->id;
$admin_account->account = $account;
$admin_account->secret = bcrypt($password);
$admin_account->type = 1;
$admin_account->save();
return Yo::create_echo($admin->id);
}
public function info()
{
Login::admin(3);
$admin_account = AdminAccount::where('admin_id', Login::$info->id)
->where('type', 1)
->where('del', 2)
->first();
return Yo::echo([
'info' => [
'id' => Login::$info->id,
'account' => $admin_account ? $admin_account->account : '',
'account_id' => $admin_account ? $admin_account->id : 0,
'nickname' => Login::$info->nickname,
]
]);
}
public function status()
{
Login::admin(3);
return Yo::echo();
}
public function create_token($admin, $type)
{
if ($admin->status != 1) Yo::error_echo(100002);
if ($admin->del != 2) Yo::error_echo(100002);
$token = Str::orderedUuid();
AdminToken::create([
'admin_id' => $admin->id,
'token' => $token,
'type' => $type,
'del' => 2
]);
return $token;
}
public function admin_login()
{
$account = request()->post('account');
$password = request()->post('password');
$type = 1;
$admin_account = AdminAccount::where('account', $account)
->where('type', 1)
->where('del', 2)
->first();
if (!$admin_account) Yo::error_echo(100001);
if (!password_verify($password, $admin_account->secret)) Yo::error_echo(100002);
$admin = Admin::where('id', $admin_account->admin_id)
->where('status', 1)
->where('del', 2)
->first();
if (!$admin) Yo::error_echo(100001);
Login::$info = $admin;
Login::$login_type = $type;
$auth_check_res = Login::check_admin_auth(2);
if ($auth_check_res !== 0) Yo::error_echo($auth_check_res);
$token = $this->create_token($admin, $type);
return Yo::echo([
'token' => $token
]);
} }
return Yo::echo([
'list' => $list
]);
}
public function info()
{
Login::admin();
$admin_account = AdminAccount::where('admin_id', Login::$info->id)
->where('type', 1)
->where('del', 2)
->first();
return Yo::echo([
'info' => [
'id' => Login::$info->id,
'account' => $admin_account ? $admin_account->account : '',
'account_id' => $admin_account ? $admin_account->id : 0,
'nickname' => Login::$info->nickname,
]
]);
}
public function status()
{
Login::admin();
return Yo::echo();
}
public function create_token($admin, $type): string
{
if ($admin->status != 1 || $admin->del != 2) Yo::error_echo(100002);
$token = Str::orderedUuid();
$admin_token = new AdminToken();
$admin_token->admin_id = $admin->id;
$admin_token->token = $token;
$admin_token->type = $type;
$admin_token->del = 2;
$admin_token->save();
return $token;
}
public function login()
{
$account = request()->post('account');
$password = request()->post('password');
$type = 1;
$admin_account = AdminAccount::where('account', $account)
->where('type', 1)
->where('del', 2)
->first();
if (!$admin_account) Yo::error_echo(100004);
if (!password_verify($password, $admin_account->secret)) Yo::error_echo(100004);
$admin = Admin::where('id', $admin_account->admin_id)
->where('status', 1)
->where('del', 2)
->first();
if (!$admin) Yo::error_echo(100002);
Login::$info = $admin;
Login::$login_type = $type;
$auth_check_res = Login::check_admin_auth([2]);
if ($auth_check_res !== 0) Yo::error_echo($auth_check_res);
$token = $this->create_token($admin, $type);
return Yo::echo([
'token' => $token
]);
}
} }

@ -1,10 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AdminTokenController extends Controller
{
//
}

@ -1,47 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Auth;
use Yo;
use Login;
class AuthController extends Controller
{
public function list()
{
Login::admin(5);
$page_group = Auth::select('id', 'title')
->where('type', 1)->where('del', 2)
->orderBy('order', 'desc')->get();
$page_list = [];
foreach ($page_group as $item) {
$page_auth_list = Auth::select('id', 'title')->where('pid', $item->id)
->where('type', 2)->where('check_type', 2)->where('del', 2)
->orderBy('order', 'desc')->get();
if (count($page_auth_list) !== 0) $page_list[] = [
"id" => $item->id,
"title" => $item->title,
"children" => $page_auth_list
];
}
$api_group = Auth::select('id', 'title')
->where('type', 3)->where('del', 2)
->orderBy('order', 'desc')->get();
$api_list = [];
foreach ($api_group as $item) {
$api_auth_list = Auth::select('id', 'title')->where('pid', $item->id)
->where('type', 4)->where('check_type', 2)->where('del', 2)
->orderBy('order', 'desc')->get();
if (count($api_auth_list) !== 0) $api_list[] = [
"id" => $item->id,
"title" => $item->title,
"children" => $api_auth_list
];
}
return Yo::echo([
'page' => $page_list,
'api' => $api_list,
]);
}
}

@ -9,61 +9,28 @@ use Login;
class ConfigController extends Controller class ConfigController extends Controller
{ {
public function config() public function get()
{ {
$configs = $this->get_config_list([1, 2, 3, 4]); $label_arr = request()->post('label_arr');
$list = []; $configs = $this->get_config_list($label_arr);
foreach ($configs as $config) { $list = [];
$list[$config['mark']] = $config['value']; foreach ($configs as $config) {
} $value = $config->value;
return Yo::echo($list); if (in_array($config->type, [3, 4, 5, 6])) {
$value = json_decode($value, true);
}
$list[$config->label] = $value;
} }
return Yo::echo($list);
}
public function update() public function get_config_list($arr): array
{ {
Login::admin(9); $config_arr = [];
$mark = request()->get('mark'); foreach ($arr as $item) {
$value = request()->get('value'); $config = Config::where('label', $item)->first();
$config = Config::where('mark', $mark)->first(); if ($config) $config_arr[] = $config;
if (!$config) Yo::error_echo(100008);
switch ($mark) {
case 'logo':
case 'favicon':
case 'login_image':
$base64 = $value;
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64, $result)) {
$type = ['png', 'jpeg', 'jpg', 'gif'];
if (!in_array($result[2], $type)) Yo::error_echo(100019);
$disk = Storage::disk('public');
$path = "/assets/$mark.$result[2]";
$put = $disk->put($path, base64_decode(str_replace($result[1], '', $base64)));
if (!$put) Yo::error_echo(100020);
$save = "/storage/assets/$mark.$result[2]?t=" . time();
} else {
Yo::error_echo(100020);
}
break;
default:
$save = $value;
}
$config->value = $save;
$config->save();
return Yo::update_echo($config->id);
}
public function assets_list()
{
Login::admin(9);
$configs = $this->get_config_list([1, 2, 3, 4]);
$list = [];
foreach ($configs as $config) {
$list[$config['mark']] = $config['value'];
}
return Yo::echo($list);
}
public function get_config_list($arr)
{
return Config::whereIn('id', $arr)->get();
} }
return $config_arr;
}
} }

@ -10,9 +10,10 @@ use Lu;
class Controller extends BaseController class Controller extends BaseController
{ {
use AuthorizesRequests, DispatchesJobs, ValidatesRequests; use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct(){ public function __construct()
Lu::RequestLog(); {
} Lu::RequestLog();
}
} }

@ -6,11 +6,11 @@ use Yo as Yoo;
class YoController extends Controller class YoController extends Controller
{ {
public function __invoke() public function __invoke()
{ {
return Yoo::echo([ return Yoo::echo([
'app_name' => env('APP_NAME'), 'app_name' => env('APP_NAME'),
'data' => request()->all() 'data' => request()->all()
]); ]);
} }
} }

@ -1,51 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Yo;
class CreateAdminInput extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'nickname' => ['required', 'between:1,30'],
'account' => ['required', 'between:1,50'],
'password' => ['required', 'between:6,20'],
];
}
public function messages()
{
return [
'nickname.required' => 100009,
'nickname.between' => 100010,
'account.required' => 100011,
'account.between' => 100012,
'password.required' => 100013,
'password.between' => 100014,
];
}
public function failedValidation(Validator $validator)
{
Yo::error_echo($validator->errors()->first());
}
}

@ -1,47 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Yo;
class EditAdminAuthInput extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => ['required', 'between:1,20'],
'remark' => ['between:0,100'],
];
}
public function messages()
{
return [
'name.required' => 100004,
'name.between' => 100005,
'remark.between' => 100006,
];
}
public function failedValidation(Validator $validator)
{
Yo::error_echo($validator->errors()->first());
}
}

@ -8,38 +8,38 @@ use Yo;
class UpdateAdminNickname extends FormRequest class UpdateAdminNickname extends FormRequest
{ {
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
* *
* @return bool * @return bool
*/ */
public function authorize() public function authorize()
{ {
return true; return true;
} }
/** /**
* Get the validation rules that apply to the request. * Get the validation rules that apply to the request.
* *
* @return array * @return array
*/ */
public function rules() public function rules()
{ {
return [ return [
'nickname' => ['required', 'between:1,30'], 'nickname' => ['required', 'between:1,30'],
]; ];
} }
public function messages() public function messages()
{ {
return [ return [
'nickname.required' => 100009, 'nickname.required' => 100005,
'nickname.between' => 100010, 'nickname.between' => 100006,
]; ];
} }
public function failedValidation(Validator $validator) public function failedValidation(Validator $validator)
{ {
Yo::error_echo($validator->errors()->first()); Yo::error_echo($validator->errors()->first());
} }
} }

@ -8,38 +8,38 @@ use Yo;
class UpdateAdminPassword extends FormRequest class UpdateAdminPassword extends FormRequest
{ {
/** /**
* Determine if the user is authorized to make this request. * Determine if the user is authorized to make this request.
* *
* @return bool * @return bool
*/ */
public function authorize() public function authorize()
{ {
return true; return true;
} }
/** /**
* Get the validation rules that apply to the request. * Get the validation rules that apply to the request.
* *
* @return array * @return array
*/ */
public function rules() public function rules()
{ {
return [ return [
'password' => ['required', 'between:6,20'], 'password' => ['required', 'between:6,20'],
]; ];
} }
public function messages() public function messages()
{ {
return [ return [
'password.required' => 100013, 'password.required' => 100007,
'password.between' => 100014, 'password.between' => 100008,
]; ];
} }
public function failedValidation(Validator $validator) public function failedValidation(Validator $validator)
{ {
Yo::error_echo($validator->errors()->first()); Yo::error_echo($validator->errors()->first());
} }
} }

@ -11,13 +11,13 @@ class Login
public static $login_type; public static $login_type;
public static $token_info; public static $token_info;
public static function check_admin_auth($auth_id = 0) public static function check_admin_auth($auth_id = 0): int
{ {
if (self::$info->admin_auth_id === -1) return 0; if (self::$info->admin_auth_id === -1) return 0;
$auth = Auth::where('id', $auth_id)->where('status', 1)->where('del', 2)->first(); $auth = Auth::where('id', $auth_id)->where('status', 1)->where('del', 2)->first();
if (!$auth) return 100016; if (!$auth) return 100003;
if (self::$info->admin_auth_id === 0) { if (self::$info->admin_auth_id === 0) {
if ($auth->check_type !== 1) return 100016; if ($auth->check_type !== 1) return 100003;
} else { } else {
if ($auth->check_type === 1) return 0; if ($auth->check_type === 1) return 0;
$admin_auth = AdminAuth::select('id') $admin_auth = AdminAuth::select('id')
@ -25,35 +25,45 @@ class Login
->where('auth_ids', 'like', "%\"$auth_id\"%") ->where('auth_ids', 'like', "%\"$auth_id\"%")
->where('del', 2) ->where('del', 2)
->first(); ->first();
if (!$admin_auth) return 100016; if (!$admin_auth) return 100003;
} }
return 0; return 0;
} }
public static function admin_check($auth_id = 0) public static function admin_check($auth_ids = [], $or_ids = []): int
{ {
if (!request()->header('Authorization')) return 100003; if (!request()->header('Authorization')) return 100001;
$header_token_arr = explode('Bearer ', request()->header('Authorization')); $header_token_arr = explode('Bearer ', request()->header('Authorization'));
if (!isset($header_token_arr[1])) return 100003; if (!isset($header_token_arr[1])) return 100001;
$header_token = $header_token_arr[1]; $header_token = $header_token_arr[1];
if (!$header_token) return 100003; if (!$header_token) return 100001;
$admin_token_info = AdminToken::where('token', $header_token)->where('del', 2)->where('updated_at', '>', Lu::date(time() - (60 * 60 * 24 * 3)))->first(); $admin_token_info = AdminToken::where('token', $header_token)->where('del', 2)->where('updated_at', '>', Lu::date(time() - (60 * 60 * 24 * 3)))->first();
if (!$admin_token_info) return 100003; if (!$admin_token_info) return 100001;
$admin_info = Admin::where('id', $admin_token_info->admin_id)->where('del', 2)->where('status', 1)->first(); $admin_info = Admin::where('id', $admin_token_info->admin_id)->where('del', 2)->where('status', 1)->first();
if (!$admin_info) return 100003; if (!$admin_info) return 100002;
self::$info = $admin_info; self::$info = $admin_info;
self::$login_type = $admin_token_info->type; self::$login_type = $admin_token_info->type;
self::$token_info = $admin_token_info; self::$token_info = $admin_token_info;
$auth_check_res = self::check_admin_auth($auth_id); foreach ($auth_ids as $item) {
if ($auth_check_res !== 0) return $auth_check_res; $auth_check_res = self::check_admin_auth($item);
if ($auth_check_res != 0) return $auth_check_res;
}
$ret = 0;
$ret_code = 0;
foreach ($or_ids as $item) {
$auth_check_res = self::check_admin_auth($item);
if ($auth_check_res == 0) $ret++;
if ($auth_check_res != 0) $ret_code = $auth_check_res;
}
if ($ret == 0 && $ret_code != 0) return $ret_code;
$admin_token_info->updated_at = Lu::date(); $admin_token_info->updated_at = Lu::date();
$admin_token_info->save(); $admin_token_info->save();
return 0; return 0;
} }
public static function admin($auth_id = 0) public static function admin($auth_ids = [], $or_ids = [])
{ {
$check_res = self::admin_check($auth_id); $check_res = self::admin_check($auth_ids, $or_ids);
if ($check_res !== 0) Yo::error_echo($check_res); if ($check_res != 0) Yo::error_echo($check_res);
} }
} }

@ -8,6 +8,4 @@ use Illuminate\Database\Eloquent\Model;
class AdminAuth extends Model class AdminAuth extends Model
{ {
use HasFactory; use HasFactory;
public $fillable = ['name', 'auth_ids', 'remark'];
} }

@ -8,6 +8,4 @@ use Illuminate\Database\Eloquent\Model;
class AdminToken extends Model class AdminToken extends Model
{ {
use HasFactory; use HasFactory;
public $fillable = ['admin_id', 'token', 'type', 'del'];
} }

@ -1,30 +1,21 @@
<?php <?php
return [ return [
200 => [ 200 => [
'c' => '增加成功', 'c' => '增加成功',
'd' => '删除成功', 'd' => '删除成功',
'u' => '修改成功', 'u' => '修改成功',
'r' => '获取成功', 'r' => '获取成功',
], ],
100001 => '账号不可用', 100000 => '?不存在或不可用',
100002 => '账号或密码错误', 100001 => '请登录',
100003 => '请登录', 100002 => '账号不可用或不存在',
100004 => '请输入名称', 100003 => '权限不足',
100005 => '名称是一个1-20位的字符串', 100004 => '账号不存在或密码错误',
100006 => '备注是一个100位以内的字符串', 100005 => '请输入昵称',
100007 => '权限是一个2-1000位的字符串', 100006 => '昵称长度在1-30位字符之间',
100008 => '内容不存在', 100007 => '请输入密码',
100009 => '请输入昵称', 100008 => '密码长度在6-20位字符之间',
100010 => '昵称是一个1-30位的字符串', 100009 => '新旧密码相同',
100011 => '请输入账号', 100010 => '旧密码输入错误',
100012 => '账号是一个1-50位的字符串',
100013 => '请输入密码',
100014 => '密码是一个6-20位的字符串',
100015 => '账号已存在',
100016 => '权限不足',
100017 => '旧密码输入错误',
100018 => '新旧密码相同',
100019 => '请上传图片',
100020 => '上传失败',
100021 => '?不存在',
]; ];

@ -6,30 +6,30 @@ use Illuminate\Support\Facades\Schema;
class CreateAdminsTable extends Migration class CreateAdminsTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
Schema::create('admins', function (Blueprint $table) { Schema::create('admins', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('nickname', 30)->comment('名称'); $table->string('nickname', 30)->comment('名称');
$table->integer('admin_auth_id')->comment('权限ID'); $table->integer('admin_auth_id')->comment('权限ID');
$table->tinyInteger('status')->default(1)->comment('1-正常 2-禁用'); $table->tinyInteger('status')->default(1)->comment('1-正常 2-禁用');
$table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常');
$table->timestamps(); $table->timestamps();
}); });
} }
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('admins'); Schema::dropIfExists('admins');
} }
} }

@ -6,31 +6,31 @@ use Illuminate\Support\Facades\Schema;
class CreateAdminAccountsTable extends Migration class CreateAdminAccountsTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
Schema::create('admin_accounts', function (Blueprint $table) { Schema::create('admin_accounts', function (Blueprint $table) {
$table->id(); $table->id();
$table->bigInteger('admin_id')->index(); $table->bigInteger('admin_id')->index();
$table->string('account', 50)->index(); $table->string('account', 50)->index();
$table->string('secret', 80); $table->string('secret', 80);
$table->tinyInteger('type')->comment('1-账号密码'); $table->tinyInteger('type')->comment('1-账号密码');
$table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常');
$table->timestamps(); $table->timestamps();
}); });
} }
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('admin_accounts'); Schema::dropIfExists('admin_accounts');
} }
} }

@ -6,30 +6,30 @@ use Illuminate\Support\Facades\Schema;
class CreateAdminAuthsTable extends Migration class CreateAdminAuthsTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
Schema::create('admin_auths', function (Blueprint $table) { Schema::create('admin_auths', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name', 20)->comment('名称'); $table->string('name', 20)->comment('名称');
$table->string('auth_ids', 1000)->comment('权限IDS JSON'); $table->string('auth_ids', 1000)->comment('权限IDS JSON');
$table->string('remark', 100)->comment('备注'); $table->string('remark', 100)->comment('备注');
$table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常');
$table->timestamps(); $table->timestamps();
}); });
} }
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('admin_auths'); Schema::dropIfExists('admin_auths');
} }
} }

@ -6,36 +6,36 @@ use Illuminate\Support\Facades\Schema;
class CreateAuthsTable extends Migration class CreateAuthsTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
Schema::create('auths', function (Blueprint $table) { Schema::create('auths', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name', 20)->comment('项目名称'); $table->string('name', 20)->comment('项目名称');
$table->string('title', 20)->comment('显示标题'); $table->string('title', 20)->comment('显示标题');
$table->string('icon', 50)->default('')->comment('显示图标'); $table->string('icon', 100)->default('')->comment('显示图标');
$table->integer('pid')->comment('上级ID'); $table->integer('pid')->comment('上级ID');
$table->tinyInteger('type')->comment('1-页面分组 2-页面 3-接口分组 4-接口'); $table->tinyInteger('type')->comment('1-分组 2-页面/接口');
$table->tinyInteger('check_type')->comment('1-不需要验证 2-需要验证 3-特殊验证规则'); $table->tinyInteger('check_type')->comment('1-不需要验证 2-需要验证 3-特殊验证规则');
$table->tinyInteger('show')->default(1)->comment('1-显示 2-不显示'); $table->tinyInteger('show')->default(1)->comment('1-显示 2-不显示');
$table->tinyInteger('status')->default(1)->comment('1-正常 2-禁用'); $table->tinyInteger('status')->default(1)->comment('1-正常 2-禁用');
$table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常');
$table->integer('order')->default(0)->comment('排序'); $table->integer('order')->default(0)->comment('排序');
$table->timestamps(); $table->timestamps();
}); });
} }
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('auths'); Schema::dropIfExists('auths');
} }
} }

@ -6,30 +6,30 @@ use Illuminate\Support\Facades\Schema;
class CreateAdminTokensTable extends Migration class CreateAdminTokensTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
Schema::create('admin_tokens', function (Blueprint $table) { Schema::create('admin_tokens', function (Blueprint $table) {
$table->id(); $table->id();
$table->bigInteger('admin_id')->index()->comment('账号ID'); $table->bigInteger('admin_id')->index()->comment('账号ID');
$table->string('token', 50)->comment('TOKEN')->index(); $table->string('token', 50)->comment('TOKEN')->index();
$table->tinyInteger('type')->comment('1-后台'); $table->tinyInteger('type')->comment('1-后台');
$table->tinyInteger('del')->default(2)->comment('1-删除 2-正常'); $table->tinyInteger('del')->default(2)->comment('1-删除 2-正常');
$table->timestamps(); $table->timestamps();
}); });
} }
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('admin_tokens'); Schema::dropIfExists('admin_tokens');
} }
} }

@ -6,43 +6,42 @@ use Illuminate\Support\Facades\Schema;
class PushAdminData extends Migration class PushAdminData extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
$data = [ $data = [
[ [
'account' => 'admin', 'account' => 'admin',
'nickname' => '超级管理员', 'nickname' => '超级管理员',
'password' => bcrypt('123465a'), 'password' => bcrypt('123465a'),
'admin_auth_id' => -1, 'admin_auth_id' => -1,
], ],
]; ];
foreach ($data as $datum) { foreach ($data as $datum) {
$admin = new App\Models\Admin(); $admin = new App\Models\Admin();
$admin->nickname = $datum['nickname']; $admin->nickname = $datum['nickname'];
$admin->admin_auth_id = $datum['admin_auth_id']; $admin->admin_auth_id = $datum['admin_auth_id'];
$admin->save(); $admin->save();
$admin_account = new App\Models\AdminAccount();
$admin_account = new App\Models\AdminAccount(); $admin_account->admin_id = $admin->id;
$admin_account->admin_id = $admin->id; $admin_account->account = $datum['account'];
$admin_account->account = $datum['account']; $admin_account->secret = $datum['password'];
$admin_account->secret = $datum['password']; $admin_account->type = 1;
$admin_account->type = 1; $admin_account->save();
$admin_account->save();
}
} }
}
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
// //
} }
} }

@ -6,100 +6,61 @@ use Illuminate\Support\Facades\Schema;
class PushAuthData extends Migration class PushAuthData extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
$data = [[ $data = [[
'name' => 'AdminApi', 'name' => 'admin_basics',
'title' => '后台接口', 'title' => '后台基础接口',
'icon' => '', 'icon' => '',
'pid' => '0', 'pid' => '0',
'type' => '3', 'type' => '1',
'check_type' => '1', 'check_type' => '1',
], [ 'show' => '2',
'name' => 'AdminApiLogin', ], [
'title' => '后台登录接口', 'name' => 'admin_basics_login',
'icon' => '', 'title' => '后台登录',
'pid' => '1', 'icon' => '',
'type' => '4', 'pid' => '1',
'check_type' => '2', 'type' => '2',
], [ 'check_type' => '1',
'name' => 'AdminApiStatus', 'show' => '2',
'title' => '后台登录状态', ], [
'icon' => '', 'name' => 'admin_basics_status',
'pid' => '1', 'title' => '后台登录状态',
'type' => '4', 'icon' => '',
'check_type' => '1', 'pid' => '1',
], [ 'type' => '2',
'name' => 'admin', 'check_type' => '1',
'title' => '人员管理', 'show' => '2',
'icon' => 'i-ic-baseline-account-box', ]];
'pid' => '0', foreach ($data as $datum) {
'type' => '1', $auth = new App\Models\Auth();
'check_type' => '1', $auth->name = $datum['name'];
], [ $auth->title = $datum['title'];
'name' => 'admin-auth', $auth->icon = $datum['icon'];
'title' => '权限管理', $auth->pid = $datum['pid'];
'icon' => 'i-ic-baseline-admin-panel-settings', $auth->type = $datum['type'];
'pid' => '4', $auth->check_type = $datum['check_type'];
'type' => '2', $auth->show = $datum['show'];
'check_type' => '2', $auth->status = 1;
], [ $auth->del = 2;
'name' => 'admin-list', $auth->order = 0;
'title' => '人员管理', $auth->save();
'icon' => 'i-ic-baseline-account-box',
'pid' => '4',
'type' => '2',
'check_type' => '2',
], [
'name' => 'admin-info',
'title' => '个人信息',
'icon' => 'i-ic-baseline-account-box',
'pid' => '4',
'type' => '2',
'check_type' => '1',
], [
'name' => 'system',
'title' => '系统设置',
'icon' => 'i-ic-baseline-settings-applications',
'pid' => '0',
'type' => '1',
'check_type' => '1',
], [
'name' => 'system-assets',
'title' => '资源设置',
'icon' => 'i-ic-baseline-color-lens',
'pid' => '8',
'type' => '2',
'check_type' => '2',
],];
foreach ($data as $datum) {
$auth = new App\Models\Auth();
$auth->name = $datum['name'];
$auth->title = $datum['title'];
$auth->icon = $datum['icon'];
$auth->pid = $datum['pid'];
$auth->type = $datum['type'];
$auth->check_type = $datum['check_type'];
$auth->show = 1;
$auth->status = 1;
$auth->del = 2;
$auth->order = 0;
$auth->save();
}
} }
}
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
// //
} }
} }

@ -6,29 +6,31 @@ use Illuminate\Support\Facades\Schema;
class CreateConfigsTable extends Migration class CreateConfigsTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
Schema::create('configs', function (Blueprint $table) { Schema::create('configs', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name', 20); $table->string('label', 50);
$table->string('mark', 40); $table->string('group', 50);
$table->string('value', 300); $table->string('value', 1000);
$table->timestamps(); $table->tinyInteger('type')->comment('1-文字 2-图片 3-文字数组 4-图片数组 5-Key_Value 6-JSON')->index();
}); $table->string('remark', 100);
} $table->timestamps();
});
}
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
Schema::dropIfExists('configs'); Schema::dropIfExists('configs');
} }
} }

@ -6,46 +6,52 @@ use Illuminate\Support\Facades\Schema;
class PushConfigData extends Migration class PushConfigData extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
$data = [[ $data = [[
'name' => 'Logo', 'label' => 'Logo',
'mark' => 'logo', 'group' => '基础设置',
'value' => '/storage/assets/logo.png', 'value' => '/storage/assets/logo.png',
], [ 'type' => '2',
'name' => 'Favicon', ], [
'mark' => 'favicon', 'label' => 'Favicon',
'value' => '/storage/assets/favicon.png', 'group' => '基础设置',
], [ 'value' => '/storage/assets/favicon.png',
'name' => 'Login欢迎图片', 'type' => '2',
'mark' => 'login_image', ], [
'value' => '/storage/assets/login_image.jpeg', 'label' => 'Login欢迎图片',
],[ 'group' => '基础设置',
'name' => '网站标题', 'value' => '/storage/assets/login_image.jpeg',
'mark' => 'title', 'type' => '2',
'value' => '鹿和后台', ], [
]]; 'label' => '网站名称',
foreach ($data as $datum) { 'group' => '基础设置',
$config = new App\Models\Config(); 'value' => env('APP_NAME'),
$config->name = $datum['name']; 'type' => '1',
$config->mark = $datum['mark']; ]];
$config->value = $datum['value']; foreach ($data as $datum) {
$config->save(); $config = new App\Models\Config();
} $config->label = $datum['label'];
$config->group = $datum['group'];
$config->value = $datum['value'];
$config->type = $datum['type'];
$config->remark = '';
$config->save();
} }
}
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
// //
} }
} }

@ -16,8 +16,8 @@ define('LARAVEL_START', microtime(true));
| |
*/ */
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) { if (file_exists($maintenance = __DIR__ . '/../storage/framework/maintenance.php')) {
require $maintenance; require $maintenance;
} }
/* /*
@ -31,7 +31,7 @@ if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php'))
| |
*/ */
require __DIR__.'/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -44,12 +44,12 @@ require __DIR__.'/../vendor/autoload.php';
| |
*/ */
$app = require_once __DIR__.'/../bootstrap/app.php'; $app = require_once __DIR__ . '/../bootstrap/app.php';
$kernel = $app->make(Kernel::class); $kernel = $app->make(Kernel::class);
$response = $kernel->handle( $response = $kernel->handle(
$request = Request::capture() $request = Request::capture()
)->send(); )->send();
$kernel->terminate($request, $response); $kernel->terminate($request, $response);

@ -14,37 +14,14 @@ use Illuminate\Support\Facades\Route;
*/ */
$admin_api = 'Admin'; $admin_api = 'Admin';
Route::post("api/$admin_api/system/config", [\App\Http\Controllers\ConfigController::class, 'config']);
Route::post("api/$admin_api/system/update", [\App\Http\Controllers\ConfigController::class, 'update']);
Route::post("api/$admin_api/system/assets/list", [\App\Http\Controllers\ConfigController::class, 'assets_list']);
Route::post("api/$admin_api/auth/select", [\App\Http\Controllers\AdminAuthController::class, 'all']);
Route::post("api/$admin_api/auth/all", [\App\Http\Controllers\AuthController::class, 'list']);
Route::post("api/$admin_api/change/nickname", [\App\Http\Controllers\AdminController::class, 'change_nickname']);
Route::post("api/$admin_api/change/password", [\App\Http\Controllers\AdminController::class, 'change_password']);
Route::post("api/$admin_api/auth/check", [\App\Http\Controllers\AdminAuthController::class, 'check']);
Route::post("api/$admin_api/menu", [\App\Http\Controllers\AdminAuthController::class, 'menu']);
Route::post("api/$admin_api/get/info", [\App\Http\Controllers\AdminController::class, 'admin_info']);
Route::post("api/$admin_api/list", [\App\Http\Controllers\AdminController::class, 'list']);
Route::post("api/$admin_api/delete", [\App\Http\Controllers\AdminController::class, 'delete']);
Route::post("api/$admin_api/update/password", [\App\Http\Controllers\AdminController::class, 'update_password']);
Route::post("api/$admin_api/update/status", [\App\Http\Controllers\AdminController::class, 'update_status']);
Route::post("api/$admin_api/update/auth", [\App\Http\Controllers\AdminController::class, 'update_auth']);
Route::post("api/$admin_api/update/nickname", [\App\Http\Controllers\AdminController::class, 'update_nickname']);
Route::post("api/$admin_api/create", [\App\Http\Controllers\AdminController::class, 'create']);
Route::post("api/$admin_api/auth/list", [\App\Http\Controllers\AdminAuthController::class, 'list']);
Route::post("api/$admin_api/auth/delete", [\App\Http\Controllers\AdminAuthController::class, 'delete']);
Route::post("api/$admin_api/auth/update", [\App\Http\Controllers\AdminAuthController::class, 'update']);
Route::post("api/$admin_api/auth/create", [\App\Http\Controllers\AdminAuthController::class, 'create']);
Route::post("api/$admin_api/info", [\App\Http\Controllers\AdminController::class, 'info']);
Route::post("api/$admin_api/status", [\App\Http\Controllers\AdminController::class, 'status']);
Route::post("api/$admin_api/login", [\App\Http\Controllers\AdminController::class, 'admin_login']);
Route::get('/', function () { Route::get('/', function () {
return view('welcome'); return view('welcome');
}); });
Route::any('api/yo', \App\Http\Controllers\YoController::class);
Route::post('api/yo', \App\Http\Controllers\YoController::class); Route::post("api/$admin_api/Admin/Change/password", [\App\Http\Controllers\AdminController::class, 'change_password']);
Route::post("api/$admin_api/Admin/Change/nickname", [\App\Http\Controllers\AdminController::class, 'change_nickname']);
Route::post("api/$admin_api/Admin/login", [\App\Http\Controllers\AdminController::class, 'login']);
Route::post("api/$admin_api/Admin/status", [\App\Http\Controllers\AdminController::class, 'status']);
Route::post("api/$admin_api/Admin/info", [\App\Http\Controllers\AdminController::class, 'info']);
Route::post("api/$admin_api/Admin/menu", [\App\Http\Controllers\AdminController::class, 'menu']);
Route::post("api/$admin_api/Config/get", [\App\Http\Controllers\ConfigController::class, 'get']);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

24
vite/.gitignore vendored

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1,14 @@
# Vue 3 + Vite
```bash
pnpm i
# If you don't have pnpm installed, run: npm install -g pnpm
pnpm dev
pnpm build
```
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>鹿和后台</title>
<link rel="shortcut icon" href="favicon.png" />
<script>
// PUBLIC CONFIG
(function () {
const config_data = {
token_key: 'TOKEN',
api: {
url: 'http://mix.sa0.online',
error_message: '网络请求发生错误',
login: [100003],
success: 200
},
layout: {
logo: 40,
background: '#f5f7f9',
header: 64,
footer: 30,
sider: {
inverted: false,
open: 240,
close: 64,
background: '#ffffff',
},
},
title: document.title,
app_theme: '#1c8eee',
version: {
version: '13.0.1 [Mix]',
date: '2022年12月25日 14:58:11',
desc: '鹿和后台管理系统 北有神鹿 其名鹿和'
}
}
localStorage.setItem('APP_CONFIG', JSON.stringify(config_data))
})()
// PUBLIC CONFIG END
</script>
</head>
<body>
<div id="app"></div>
<script>
(function () {
const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
const setting = localStorage.getItem('color-schema') || 'auto'
if (setting === 'dark' || (prefersDark && setting !== 'light'))
document.documentElement.classList.toggle('dark', true)
})()
</script>
<script type="module" src="/src/main.js"></script>
</body>
</html>

@ -0,0 +1,31 @@
{
"private": true,
"name": "lu-code-vue-user",
"packageManager": "pnpm@7.0.0",
"version": "0.0.0",
"scripts": {
"dev": "vite --port 3333 --open",
"build": "vite build"
},
"dependencies": {
"@icon-park/vue-next": "^1.4.2",
"@vueuse/core": "^8.4.2",
"animate.css": "^4.1.1",
"axios": "^0.26.1",
"naive-ui": "^2.34.3",
"normalize.css": "^8.0.1",
"pinia": "^2.0.14",
"vue": "^3.2.33",
"vue-router": "^4.0.15"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.3.3",
"pnpm": "^7.0.1",
"unocss": "^0.33.2",
"unplugin-auto-import": "^0.7.1",
"unplugin-vue-components": "^0.19.5",
"vite": "^2.9.9",
"vite-plugin-pages": "^0.23.0",
"vite-plugin-vue-layouts": "^0.6.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

@ -0,0 +1,53 @@
<script setup>
import {zhCN, dateZhCN, darkTheme} from 'naive-ui'
import color from '~/tool/color'
import {isDark} from '~/composables'
import {useStore, useConfig} from '~/store'
const $store = useStore()
const $config = useConfig()
const get_theme_overrides = $computed(() => {
const app_theme = $config.value.app_theme;
const lighten_str = color.lighten($config.value.app_theme, 6);
return {
common: {
primaryColor: app_theme,
primaryColorHover: lighten_str,
primaryColorSuppl: lighten_str,
primaryColorPressed: lighten_str,
},
LoadingBar: {
colorLoading: app_theme,
},
};
});
</script>
<template>
<n-config-provider :theme-overrides="get_theme_overrides" :theme="isDark?darkTheme:{}" :locale="zhCN"
:date-locale="dateZhCN">
<n-spin class="spin_wrapper" :show="$store.api_loading > 0">
<n-notification-provider>
<n-loading-bar-provider>
<n-message-provider>
<n-dialog-provider>
<Mounting/>
<main font-sans>
<router-view/>
</main>
</n-dialog-provider>
</n-message-provider>
</n-loading-bar-provider>
</n-notification-provider>
</n-spin>
</n-config-provider>
</template>
<style>
.form_tag_wrapper {
width: 80px;
text-align: center;
}
.form_input_wrapper {
width: 200px;
}
</style>

@ -0,0 +1,67 @@
import {$post} from '~/tool/axios'
import {useConfig, useSessionToken, useSaveTokenType, useToken} from "~/store";
import $router from "~/router";
const $save_token_type = useSaveTokenType()
const $session_token = useSessionToken()
const $token = useToken()
const $config = useConfig()
const admin_api = 'Admin'
export const yo = async (data) => await $post({url: `${$config.value.api.url}/api/yo`, data}, true)
export const ConfigGetAction = async (label_arr) => await $post({
url: `${$config.value.api.url}/api/${admin_api}/Config/get`, data: {label_arr}
}, true)
export const AdminChangeNicknameAction = async (nickname) => await $post({
url: `${$config.value.api.url}/api/${admin_api}/Admin/Change/nickname`, data: {nickname}
}, true)
export const AdminChangePasswordAction = async (data) => await $post({
url: `${$config.value.api.url}/api/${admin_api}/Admin/Change/password`, data
}, true)
export const AdminLoginAction = async (data) => await $post({
url: `${$config.value.api.url}/api/${admin_api}/Admin/login`, data
}, true)
export const AdminMenuAction = async (data) => await $post({
url: `${$config.value.api.url}/api/${admin_api}/Admin/menu`, data
}, true)
export const AdminStatusAction = async () => await $post({
url: `${$config.value.api.url}/api/${admin_api}/Admin/status`
}, false)
export const AdminInfoAction = async () => await $post({
url: `${$config.value.api.url}/api/${admin_api}/Admin/info`
}, false)
export const $headers = () => {
let $token
if ($save_token_type.value === 'local') {
$token = useToken()
} else {
$token = useSessionToken()
}
return {
'Authorization': 'Bearer ' + $token.value
}
}
export const $image = (path) => {
const path_ret = ['http://', 'https://', ';base64,']
for (let i = 0; i < path_ret.length; i++) {
if (path.indexOf(path_ret[i]) !== -1) {
return path
}
}
return `${$config.value.api.url}${path}`
}
export const $response = (res, then, next = false) => {
if (res) {
if ($config.value.api.login.indexOf(res.code) !== -1) {
$session_token.value = null
$token.value = null
if (!!next) {
next('/login')
} else {
$router.push('/login')
}
}
if (res.code !== $config.value.api.success) return window.$message().error(res.message)
then()
}
}

@ -0,0 +1,36 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022-05-24 11:23:13
*/
import {useStore, useRouterActive} from '~/store'
const $store = useStore()
const $router_active = useRouterActive()
const breadcrumb_list = computed(() => {
let list = []
for (let i in $router_active.value) {
if ($router_active.value[i].key !== 'index') {
list.push($router_active.value[i])
}
}
return list
})
</script>
<template>
<n-breadcrumb ml-5>
<n-breadcrumb-item v-if="breadcrumb_list.length !== 0" href="#">
<n-space align="center">
<Icon type="home"></Icon>
<div>{{ $store.config['网站名称'] }}</div>
</n-space>
</n-breadcrumb-item>
<n-breadcrumb-item v-for="(bi,bk) in breadcrumb_list" :key="bk" :disabled="bk !== breadcrumb_list.length - 1">
<n-space align="center">
<Icon :type="bi.icon"></Icon>
<div>{{ bi.title }}</div>
</n-space>
</n-breadcrumb-item>
</n-breadcrumb>
</template>

@ -0,0 +1,29 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022年12月25日 19:57:16
*/
import {IconPark} from '@icon-park/vue-next/es/all';
const $props = defineProps({
type: {
type: String,
default: 'AddText'
},
size: {
type: Number,
default: 20
},
theme: {
type: String,
default: 'outline'
}
})
</script>
<template>
<div>
<IconPark :type="$props.type" :size="$props.size" :theme="$props.theme"></IconPark>
</div>
</template>

@ -0,0 +1,94 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022-05-24 10:19:45
*/
import {useConfig, useStore} from "~/store";
import {isDark} from '~/composables'
import $router from "~/router";
import {$image} from '~/api'
const $store = useStore()
const $config = useConfig()
const layout_header_wrapper_height = computed(() => {
return `${$config.value.layout.header}px`
})
const layout_header_wrapper_blank_height = computed(() => {
return `${$config.value.layout.header - 25}px`
})
const logo_size = computed(() => {
return `${$config.value.layout.logo}px`
})
const logo_menu_wrapper_left = ref(`${($config.value.layout.sider.close - $config.value.layout.logo) / 2}px`)
</script>
<template>
<div class="logo_wrapper">
<div @click="$router.push('/')" class="logo_cover_wrapper"></div>
<div class="logo_container_wrapper">
<img class="logo_image_wrapper" :class="($config.layout.sider.inverted || isDark) ?'logo_image_filter':''"
:src="$image($store.config['Logo'])" alt="">
<n-menu class="logo_menu_wrapper" :indent="12" :inverted="$config.layout.sider.inverted || isDark"
:icon-size="$config.layout.logo" :collapsed-width="$config.layout.sider.close"
:value="($config.layout.sider.inverted || isDark)?'logo':''"
:options="[{label: $store.config['网站名称'],key: 'logo'}]"/>
</div>
</div>
<n-divider dashed></n-divider>
</template>
<style>
.logo_wrapper .logo_menu_wrapper {
--n-item-color-active: #00000000 !important;
}
</style>
<style scoped>
.logo_wrapper .logo_image_filter {
background: #ffffff;
border-radius: 6px;
}
.logo_wrapper .logo_image_wrapper {
width: v-bind(logo_size);
height: v-bind(logo_size);
position: absolute;
top: 50%;
transform: translateY(-50%);
left: v-bind(logo_menu_wrapper_left);
z-index: 999;
}
.logo_container_wrapper {
position: absolute;
left: 0;
right: 0;
top: 0;
height: v-bind(layout_header_wrapper_height);
}
.logo_menu_wrapper {
position: absolute;
top: 50%;
left: 0;
right: 0;
text-align: center;
transform: translateY(-50%);
}
.logo_cover_wrapper {
position: absolute;
cursor: pointer;
top: 0;
height: v-bind(layout_header_wrapper_height);
left: 0;
right: 0;
z-index: 2;
}
.logo_wrapper {
position: relative;
height: v-bind(layout_header_wrapper_blank_height);
}
</style>

@ -0,0 +1,107 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022-05-24 10:19:45
*/
import {isDark} from '~/composables'
import {h} from 'vue'
import {useRouterActive, useConfig} from '~/store'
import $router from '~/router'
import Icon from "~/components/Icon.vue";
import {AdminMenuAction, $response} from '~/api'
const menuListItem = (item) => {
let data = {
title: item.title,
name: item.name,
status: item.status,
icon: item.icon
}
if ('children' in item) {
data.children = item.children.map((i) => {
return menuListItem(i)
})
}
return data
}
const getMenu = async () => {
const response = await AdminMenuAction()
$response(response, () => {
menu_list.value = response.data.list.map((item) => {
return menuListItem(item)
})
})
menu_list.value.unshift({
title: '首页',
name: 'index',
status: 1,
icon: 'home'
})
}
onMounted(() => {
getMenu()
})
function renderIcon(icon) {
return () => h(Icon, {
size: 20,
type: icon
}, {default: () => h(icon)})
}
const menu_list = ref([])
const menuItem = (list) => {
return list.map((item) => {
let item_info = {label: item.title, key: item.name, disabled: item.status === 2}
if ('children' in item) {
if (item.children.length === 1) {
item_info = {
label: item.children[0].title,
key: item.children[0].name,
icon: renderIcon(item.children[0].icon)
}
} else {
if (item.children.length !== 0) {
item_info = {label: item.title, key: item.name, children: menuItem(item.children)}
}
}
}
if ('query' in item && item.query !== '{}') item_info.query = JSON.parse(item.query)
if ('params' in item && item.params !== '{}') item_info.params = JSON.parse(item.params)
if ('icon' in item && item.icon !== '') {
if (!('icon' in item_info)) item_info.icon = renderIcon(item.icon)
}
return item_info
})
}
const menu_options = computed(() => {
return menuItem(menu_list.value)
})
const menuUpdate = (_, item) => {
let push = {name: item.key}
if ('query' in item) push.query = item.query
if ('params' in item) push.params = item.params
try {
$router.push(push)
} catch (e) {
$router.push({
name: 'index'
})
}
}
const $router_active = useRouterActive()
const expanded_keys = computed(() => {
return $router_active.value.map((item) => {
return item.key
})
})
const $config = useConfig()
</script>
<template>
<n-menu class="menu_wrapper" :indent="12" :value="expanded_keys[expanded_keys.length - 1]" :options="menu_options"
:watch-props="['defaultExpandedKeys']" :default-expanded-keys="expanded_keys" @update:value="menuUpdate"
:inverted="$config.layout.sider.inverted || isDark" :collapsed-width="64" :icon-size="20"/>
</template>

@ -0,0 +1,13 @@
<template></template>
<script setup>
import {useMessage, useLoadingBar, useDialog, useNotification} from 'naive-ui'
const $message = useMessage()
window.$message = () => {
$message.destroyAll()
return $message
}
window.$dialog = useDialog();
window.$loading = useLoadingBar();
window.$notification = useNotification();
</script>

@ -0,0 +1,73 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022-05-24 14:48:31
*/
import {useStore, useConfig} from "~/store";
import {isDark, toggleDark, isFull, toggleFull} from '~/composables'
import $router from "~/router";
import {$image} from '~/api'
const $store = useStore()
const $config = useConfig()
const layout_header_wrapper_height = computed(() => {
return `${$config.value.layout.header}px`
})
const options = [{
label: '个人设置',
key: 'set',
props: {
onClick: () => {
$router.push({
name: 'admin-info'
})
}
}
}, {
label: '退出登录',
key: "quit",
props: {
onClick: () => {
$router.push({
name: 'login'
})
}
}
}]
</script>
<template>
<div class="user_wrapper">
<n-button text @click="toggleFull()" mr-5>
<Icon v-if="isFull" type="off-screen"></Icon>
<Icon v-else type="full-screen"></Icon>
</n-button>
<n-button text @click="toggleDark()" mr-5>
<Icon v-if="isDark" type="sun-one"></Icon>
<Icon v-else type="moon"></Icon>
</n-button>
<div mr-5>
<n-dropdown trigger="hover" :options="options">
<n-space align="center">
<n-avatar round :size="40" class="avatar_wrapper" :src="$image($store.config['Logo'])"
:fallback-src="$image($store.config['Logo'])"/>
<span>{{ $store.admin_info ? $store.admin_info.nickname : $store.config['网站名称'] }}</span>
</n-space>
</n-dropdown>
</div>
</div>
</template>
<style scoped>
.avatar_wrapper {
background: #ffffff;
}
.user_wrapper {
position: absolute;
right: 0;
top: 0;
height: v-bind(layout_header_wrapper_height);
display: flex;
align-items: center;
}
</style>

@ -0,0 +1,23 @@
<script setup>
/***
* nameApi 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
import {yo} from '~/api'
const response_content = ref('')
const yoClick = async () => {
const response = await yo({yoo: 'foo'})
if (response) response_content.value = JSON.stringify(response)
}
</script>
<template>
<tr>
<td>Api</td>
<td>{{ response_content }}</td>
<td>
<n-button @click="yoClick()" secondary strong>发送</n-button>
</td>
</tr>
</template>

@ -0,0 +1,28 @@
<script setup>
/***
* name图标 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
const toIconDoc = () => {
window.open('https://iconpark.oceanengine.com/official')
}
</script>
<template>
<tr>
<td>图标</td>
<td>
<n-space>
<Icon type="off-screen"></Icon>
<Icon type="full-screen"></Icon>
<Icon type="sun-one"></Icon>
<Icon type="moon"></Icon>
</n-space>
</td>
<td>
<n-button secondary strong @click="toIconDoc()">
文档
</n-button>
</td>
</tr>
</template>

@ -0,0 +1,20 @@
<script setup>
/***
* name路由Params参数 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
const $props = defineProps({
name: {
type: String,
default: '鹿和'
}
})
</script>
<template>
<tr>
<td>Params & Props</td>
<td>{{ JSON.stringify($props) }}</td>
<td></td>
</tr>
</template>

@ -0,0 +1,19 @@
<script setup>
/***
* name路由跳转 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
import $router from '~/router'
</script>
<template>
<tr>
<td>路由跳转</td>
<td></td>
<td>
<n-button secondary strong @click="$router.push({name: 'index'})">
首页
</n-button>
</td>
</tr>
</template>

@ -0,0 +1,34 @@
<script setup>
/***
* name路由Query参数 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
import $router from '~/router'
import {onBeforeRouteUpdate} from "vue-router";
const default_page_options = {
name: '鹿和'
}
const page_options = ref(JSON.parse(JSON.stringify(default_page_options)))
onBeforeRouteUpdate((to) => {
routerChange(to.query)
})
const routerChange = (query) => {
page_options.value = {
name: query.name || default_page_options.name
}
}
onMounted(() => {
routerChange($router.currentRoute.value.query)
})
</script>
<template>
<tr>
<td>Query</td>
<td>{{ JSON.stringify(page_options) }}</td>
<td></td>
</tr>
</template>

@ -0,0 +1,32 @@
<script setup>
/**
* name子父组件通信 父组件
* usersa0ChunLuyu
* date2022-04-13 11:14:00
*/
import SonComponent from './components/Son.vue'
const fa_value = ref('fa_value')
const son_ref = ref(false)
const SonRef = (e) => {
son_ref.value = e
}
const faFunc = () => {
console.log('faFunc')
}
</script>
<template>
<tr>
<td rowspan="2">子父组件通信</td>
<td>
<n-input v-model:value="fa_value"></n-input>
<n-input mt-1 v-model:value="son_ref.son_value"></n-input>
</td>
<td>
<n-button secondary strong @click="son_ref.sonFunc()">
子函数
</n-button>
</td>
</tr>
<SonComponent @faFunc="faFunc" :fa_value="fa_value" :ref="SonRef"></SonComponent>
</template>

@ -0,0 +1,35 @@
<script setup>
/**
* name子父组件通信 子组件
* usersa0ChunLuyu
* date2022-04-13 11:14:00
*/
const $emit = defineEmits(['faFunc'])
const $props = defineProps({
fa_value: {
type: String,
default: ''
}
})
const son_value = ref('son_value')
const sonFunc = () => {
console.log('sonFunc')
}
defineExpose({
son_value,
sonFunc
})
</script>
<template>
<tr>
<td>
<n-input disabled v-model:value="$props.fa_value"></n-input>
<n-input mt-1 v-model:value="son_value"></n-input>
</td>
<td>
<n-button secondary strong @click="$emit('faFunc')">
父函数
</n-button>
</td>
</tr>
</template>

@ -0,0 +1,52 @@
<script setup>
/***
* name状态管理 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
// Pinia
import {useStore} from "~/store";
const $store = useStore()
// Pinia end
// Session
const session_count = useStorage('session_count', 0, sessionStorage)
// Session end
// Local
const local_count = useStorage('local_count', 0)
// Local end
</script>
<template>
<tr>
<td>Pinia</td>
<td>{{ $store.count }}</td>
<td>
<n-space>
<n-button secondary strong @click="$store.count++"></n-button>
<n-button secondary strong @click="$store.count--"></n-button>
</n-space>
</td>
</tr>
<tr>
<td>Session</td>
<td>{{ session_count }}</td>
<td>
<n-space>
<n-button secondary strong @click="session_count++"></n-button>
<n-button secondary strong @click="session_count--"></n-button>
</n-space>
</td>
</tr>
<tr>
<td>Local</td>
<td>{{ local_count }}</td>
<td>
<n-space>
<n-button secondary strong @click="local_count++"></n-button>
<n-button secondary strong @click="local_count--"></n-button>
</n-space>
</td>
</tr>
</template>

@ -0,0 +1,21 @@
<script setup>/***
* namestyle v-bind 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
const opacity = ref(1)
</script>
<template>
<tr>
<td>动态 Style v-bind</td>
<td class="opt">滑动滑块查看效果</td>
<td>
<n-slider v-model:value="opacity" :step="0.01" :min="0" :max="1"/>
</td>
</tr>
</template>
<style scoped>
.opt {
opacity: v-bind(opacity);
}
</style>

@ -0,0 +1,17 @@
<script setup>
/**
* nameUnoCSS 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
</script>
<template>
<tr>
<td>UnoCSS</td>
<td>
<div bg-dark-50 text-light-50 p="y-1 x-3">YO</div>
</td>
<td></td>
</tr>
</template>

@ -0,0 +1,21 @@
<script setup>
/***
* nameNaive Message 示例
* usersa0ChunLuyu
* date2022-04-13 09:20:12
*/
const showMessage = (msg) => {
window.$message().success(msg)
}
</script>
<template>
<tr>
<td>Naive Message</td>
<td></td>
<td>
<n-button secondary strong @click="showMessage('Yo')">
弹出
</n-button>
</td>
</tr>
</template>

@ -0,0 +1,2 @@
export const isDark = useDark()
export const toggleDark = useToggle(isDark)

@ -0,0 +1,3 @@
const {isFullscreen, toggle} = useFullscreen()
export const isFull = isFullscreen
export const toggleFull = toggle

@ -0,0 +1,2 @@
export * from './dark'
export * from './fullscreen'

@ -0,0 +1,9 @@
<script setup>
const $router = useRouter()
</script>
<template>
<main p="x4 y10" text="center blue-500 dark:gray-200">
<RouterView/>
</main>
</template>

@ -0,0 +1,116 @@
<script setup>
import {useConfig, useCollapsed} from "~/store"
import {isDark} from '~/composables'
const $config = useConfig()
const layout_content_wrapper_background = ref($config.value.layout.background)
const layout_sider_wrapper_background = ref($config.value.layout.sider.background)
const layout_header_wrapper_height = ref(`${$config.value.layout.header}px`)
const layout_footer_wrapper_height = ref(`${$config.value.layout.footer}px`)
const layout_router_view_margin_bottom = ref('10px');
const layout_router_view_wrapper_min_height = ref(`calc(100vh - ${$config.value.layout.header}px - ${$config.value.layout.footer}px - 1px - ${layout_router_view_margin_bottom.value})`)
const layout_content_wrapper_height = ref(`calc(100vh - ${$config.value.layout.header}px)`)
const layout_content_container_wrapper_height = ref(`calc(100vh - ${$config.value.layout.header}px)`)
const $collapsed = useCollapsed()
const collapsedOnUpdate = (e) => {
$collapsed.value = e
}
</script>
<template>
<div class="layout_wrapper">
<n-layout has-sider class="layout_header_container_wrapper">
<n-layout-sider :collapsed="$collapsed" :class="[isDark?'':'layout_sider_background']"
collapse-mode="width" :collapsed-width="$config.layout.sider.close"
:width="$config.layout.sider.open" :inverted="$config.layout.sider.inverted || isDark"
:native-scrollbar="false" bordered>
<Logo></Logo>
</n-layout-sider>
<n-layout>
<n-layout-header class="layout_header_wrapper" bordered>
<n-button ml-5 text @click="collapsedOnUpdate(!$collapsed)">
<Icon v-if="$collapsed" type="menu-unfold-one"></Icon>
<Icon v-else type="menu-fold-one"></Icon>
</n-button>
<Breadcrumb></Breadcrumb>
<User></User>
</n-layout-header>
</n-layout>
</n-layout>
<n-layout has-sider class="layout_content_container_wrapper">
<n-layout-sider :collapsed="$collapsed" :class="[isDark?'':'layout_sider_background']"
collapse-mode="width" :collapsed-width="$config.layout.sider.close"
:width="$config.layout.sider.open" :inverted="$config.layout.sider.inverted || isDark"
:native-scrollbar="false" bordered>
<Menu></Menu>
</n-layout-sider>
<n-layout :class="[isDark?'':'layout_content_background']">
<n-layout position="absolute" :native-scrollbar="false" class="layout_content_wrapper">
<div class="layout_router_view_wrapper" px-2>
<router-view v-slot="{ Component }">
<component :is="Component"/>
</router-view>
</div>
<n-layout-footer class="layout_footer_wrapper" text="xs center gray-500" bordered>
<span>{{ $config.version.desc }}</span>
<span mx-3>{{ $config.version.version }}</span>
<span>{{ $config.version.date }}</span>
</n-layout-footer>
</n-layout>
</n-layout>
</n-layout>
</div>
</template>
<style scoped>
.layout_wrapper {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.layout_content_container_wrapper {
height: v-bind(layout_content_container_wrapper_height);
}
.layout_header_container_wrapper {
height: v-bind(layout_header_wrapper_height);
}
.layout_header_wrapper {
position: relative;
height: v-bind(layout_header_wrapper_height);
display: flex;
align-items: center;
}
.layout_sider_background {
background: v-bind(layout_sider_wrapper_background);
}
.layout_content_background {
background: v-bind(layout_content_wrapper_background);
}
.layout_footer_wrapper {
line-height: v-bind(layout_footer_wrapper_height);
height: v-bind(layout_footer_wrapper_height);
}
.layout_content_wrapper {
top: 0.5rem;
background: #00000000;
height: v-bind(layout_content_wrapper_height);
overflow: hidden;
}
.layout_router_view_wrapper {
min-height: v-bind(layout_router_view_wrapper_min_height);
overflow: hidden;
margin-bottom: v-bind(layout_router_view_margin_bottom);
}
</style>

@ -0,0 +1,7 @@
<script setup>
</script>
<template>
<main class="px-4 py-10 text-gray-700 dark:text-gray-200">
<RouterView/>
</main>
</template>

@ -0,0 +1,14 @@
import {createApp} from 'vue'
import App from './App.vue'
import router from '~/router'
import {createPinia} from 'pinia'
import './styles/main.css'
import 'uno.css'
import 'normalize.css'
import 'animate.css';
import '@icon-park/vue-next/styles/index.css';
const app = createApp(App)
app.use(router)
app.use(createPinia())
app.mount('#app')

@ -0,0 +1,26 @@
<script setup>
</script>
<template>
<div>
<div class="i404_wrapper">
<img src="https://iph.href.lu/300x300/?text=404" alt="">
</div>
未找到页面
<div mt-10>
<n-button type="primary" @click="$router.back()"></n-button>
</div>
</div>
</template>
<style scoped>
.i404_wrapper {
width: 300px;
margin: 0 auto;
}
.i404_wrapper img {
width: 300px;
}
</style>
<route>
{"name":"404","meta":{"layout":"404"}}
</route>

@ -0,0 +1,13 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022年12月25日 20:49:28
*/
</script>
<template>
<router-view></router-view>
</template>
<route>
{redirect: '/admin/info',"meta":{"title":"管理员设置","icon":"every-user"}}
</route>

@ -0,0 +1,21 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022年12月25日 20:50:25
*/
</script>
<template>
<div>
<n-card title="权限管理">
<div></div>
</n-card>
</div>
</template>
<style scoped>
</style>
<route>
{"meta":{"title":"权限管理","icon":"personal-privacy"}}
</route>

@ -0,0 +1,103 @@
<script setup>/**
* name
* usersa0ChunLuyu
* date2022年12月25日 20:50:25
*/
import {$response, AdminChangeNicknameAction, AdminInfoAction, AdminChangePasswordAction} from "~/api";
import {useStore} from "~/store";
import {onMounted} from "vue";
const $store = useStore()
const admin_info = ref({
account_id: 0,
nickname: ''
})
const AdminInfo = async () => {
const response = await AdminInfoAction()
$response(response, () => {
$store.admin_info = response.data.info
admin_info.value = JSON.parse(JSON.stringify(response.data.info))
})
}
onMounted(() => {
AdminInfo()
})
const AdminChangeNickname = async () => {
if (admin_info.value.nickname === $store.admin_info.nickname) return
const response = await AdminChangeNicknameAction(admin_info.value.nickname)
$response(response, () => {
AdminInfo()
window.$message().success('修改成功')
})
}
const password_data_default = {
old: '',
new: '',
check: '',
}
const AdminChangePassword = async () => {
if (changePasswordDisabled()) return
const response = await AdminChangePasswordAction({
account_id: admin_info.value.account_id,
password: password_data.value.new,
old_password: password_data.value.old,
})
$response(response, () => {
password_data.value = JSON.parse(JSON.stringify(password_data_default))
window.$message().success('修改成功')
})
}
const password_data = ref(JSON.parse(JSON.stringify(password_data_default)))
const changePasswordDisabled = () => {
if (password_data.value.old.length < 6 || password_data.value.old.length > 20) return true
if (password_data.value.new.length < 6 || password_data.value.new.length > 20) return true
if (password_data.value.new !== password_data.value.check) return true
return false
}
</script>
<template>
<div>
<n-card title="个人设置">
<div>
<n-space align="center">
<n-tag>
<div class="form_tag_wrapper">昵称</div>
</n-tag>
<n-input class="form_title_wrapper" v-model:value="admin_info.nickname"></n-input>
<n-button :disabled="admin_info.nickname === $store.admin_info.nickname" @click="AdminChangeNickname()"
type="info">修改昵称
</n-button>
</n-space>
<n-space mt-5 align="center">
<n-tag>
<div class="form_tag_wrapper">旧密码</div>
</n-tag>
<n-input type="password" class="form_title_wrapper" v-model:value="password_data.old"></n-input>
</n-space>
<n-space mt-2 align="center">
<n-tag>
<div class="form_tag_wrapper">新密码</div>
</n-tag>
<n-input type="password" class="form_title_wrapper" v-model:value="password_data.new"></n-input>
</n-space>
<n-space mt-2 align="center">
<n-tag>
<div class="form_tag_wrapper">确认密码</div>
</n-tag>
<n-input type="password" class="form_title_wrapper" v-model:value="password_data.check"></n-input>
</n-space>
<n-button :disabled="changePasswordDisabled()" @click="AdminChangePassword()" mt-5 type="info">修改密码
</n-button>
</div>
</n-card>
</div>
</template>
<style scoped>
</style>
<route>
{"meta":{"title":"个人设置","icon":"user"}}
</route>

@ -0,0 +1,21 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022年12月25日 20:50:25
*/
</script>
<template>
<div>
<n-card title="管理员列表">
<div></div>
</n-card>
</div>
</template>
<style scoped>
</style>
<route>
{"meta":{"title":"管理员列表","icon":"every-user"}}
</route>

@ -0,0 +1,49 @@
<script setup>
import ApiComponent from '~/components/dev/Api.vue'
import StoreComponent from '~/components/dev/Store.vue'
import RouterQueryComponent from '~/components/dev/RouterQuery.vue'
import RouterPushComponent from '~/components/dev/RouterPush.vue'
import RouterParamsComponent from '~/components/dev/RouterParams.vue'
import IconParkComponent from '~/components/dev/IconPark.vue'
import StyleVBindComponent from '~/components/dev/StyleVBind.vue'
import UnoCSSComponent from '~/components/dev/UnoCSS.vue'
import UseMessageComponent from '~/components/dev/UseMessage.vue'
import SonFatherComponent from '~/components/dev/SonFather/Father.vue'
const $props = defineProps({
name: {
type: String,
default: '鹿和'
}
})
const $router = useRouter()
</script>
<template>
<div>
<n-table striped size="small">
<thead>
<tr>
<th>功能</th>
<th>内容</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<ApiComponent></ApiComponent>
<StoreComponent></StoreComponent>
<RouterQueryComponent></RouterQueryComponent>
<RouterParamsComponent :name="$props.name"></RouterParamsComponent>
<RouterPushComponent></RouterPushComponent>
<IconParkComponent></IconParkComponent>
<StyleVBindComponent></StyleVBindComponent>
<UnoCSSComponent></UnoCSSComponent>
<UseMessageComponent></UseMessageComponent>
<SonFatherComponent></SonFatherComponent>
</tbody>
</n-table>
</div>
</template>
<route>
{"meta":{"title":"基础功能示例","icon":"i-ic-round-code"}}
</route>

@ -0,0 +1,24 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022-05-19 09:18:31
*/
import {useStore} from "~/store"
const $store = useStore()
</script>
<template>
<div>
<n-alert :title="`你好 ${$store.admin_info.nickname?$store.admin_info.nickname:''}!`" type="info">
<template #icon>
<n-icon>
<div i-ic-round-music-note></div>
</n-icon>
</template>
</n-alert>
</div>
</template>
<route>
{"meta":{"title":"首页"}}
</route>

@ -0,0 +1,191 @@
<script setup>
/**
* name
* usersa0ChunLuyu
* date2022-05-19 09:18:31
*/
import $router from '~/router'
import {
useConfig,
useSaveTokenType,
useSessionToken,
useStore,
useToken,
} from '~/store'
const $config = useConfig()
import {reGetAdmin} from "~/tool/info"
import {$image, $response, AdminLoginAction} from '~/api'
import {onBeforeRouteUpdate} from "vue-router";
import {isDark, toggleDark, isFull, toggleFull} from '~/composables'
const $store = useStore()
const $save_token_type = useSaveTokenType()
const $session_token = useSessionToken()
const $token = useToken()
const account = ref('')
const password = ref('')
const local_token = ref(false)
const localTokenClick = (e) => {
local_token.value = e
}
const default_page_options = {
f: '/'
}
const page_options = ref(default_page_options)
onBeforeRouteUpdate((to) => {
routerChange(to.query)
})
const routerChange = (query) => {
page_options.value = {
f: query.f || default_page_options.f
}
}
onMounted(() => {
routerChange($router.currentRoute.value.query)
})
const loginClick = async () => {
const account_ = account.value.replace(/^\s+|\s+$/g, "")
if (account_ === '') return window.$message().error('请输入账号')
if (password.value === '') return window.$message().error('请输入密码')
const response = await AdminLoginAction({
'account': account_,
'password': password.value,
})
$response(response, () => {
if (local_token.value) {
$save_token_type.value = 'local'
$session_token.value = ''
$token.value = response.data.token
} else {
$save_token_type.value = 'session'
$session_token.value = response.data.token
$token.value = ''
}
reGetAdmin()
$router.push(decodeURIComponent(page_options.value.f))
})
}
const accountEnter = () => {
if (password.value === '') {
password_input.value.focus()
} else {
loginClick()
}
}
const password_input = ref(null)
const passwordInputRef = (e) => {
password_input.value = e
}
</script>
<template>
<div class="login_page_wrapper" :style="{
background:$config.app_theme+'20',
}">
<div class="login_logo_wrapper">
<img :src="$image($store.config['Logo'])" alt="">
</div>
<div class="login_space_wrapper shadow-lg" :style="{
background: isDark?'#333333':'#ffffff'
}">
<div class="login_space_image_wrapper">
<img :src="$image($store.config['Login欢迎图片'])" alt="">
</div>
<div class="login_space_form_wrapper">
<div mt-5>
<n-h1>登录</n-h1>
</div>
<div mt-5>
<n-input v-model:value="account" @keydown.enter="accountEnter()"
placeholder="请输入账号"></n-input>
</div>
<div mt-5>
<n-input :ref="passwordInputRef" type="password" @keydown.enter="loginClick()"
v-model:value="password"
placeholder="请输入密码"></n-input>
</div>
<div mt-10>
<n-button @click="loginClick()" type="primary" w-full>登录</n-button>
</div>
<div mt-5>
<n-checkbox @update:checked="localTokenClick" :default-checked="local_token">自动登录</n-checkbox>
</div>
<div class="login_space_form_divider_wrapper"></div>
<n-divider dashed></n-divider>
<n-space justify="center">
<n-button text @click="toggleFull()" mr-5>
<Icon v-if="isFull" type="off-screen"></Icon>
<Icon v-else type="full-screen"></Icon>
</n-button>
<n-button text @click="toggleDark()" mr-5>
<Icon v-if="isDark" type="sun-one"></Icon>
<Icon v-else type="moon"></Icon>
</n-button>
</n-space>
</div>
</div>
</div>
</template>
<style scoped>
.login_space_form_divider_wrapper {
margin-top: 210px;
}
.login_space_form_wrapper {
width: 500px;
padding: 30px;
}
.login_logo_wrapper img {
width: 80px;
height: 80px;
display: block;
}
.login_logo_wrapper {
position: absolute;
top: 20px;
left: 20px;
width: 80px;
height: 80px;
}
.login_space_image_wrapper img {
width: 400px;
height: 600px;
display: block;
}
.login_space_image_wrapper {
width: 400px;
height: 600px;
}
.login_space_wrapper {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 900px;
height: 600px;
border-radius: 6px;
display: flex;
overflow: hidden;
}
.login_page_wrapper {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
<route>
{"meta":{"layout":"login","title":"登录"}}
</route>

@ -0,0 +1,75 @@
import {createRouter, createWebHashHistory} from 'vue-router'
import {setupLayouts} from 'virtual:generated-layouts'
import generatedRoutes from 'virtual:generated-pages'
import {ConfigGetAction, $response, AdminStatusAction} from "~/api"
import {reGetAdmin} from "~/tool/info"
import {$favicon} from "~/tool/favicon"
import {
useStore, useSaveTokenType, useSessionToken, useToken, useRouterActive
} from '~/store'
const no_login_list = ['login', '404'];
const $router_active = useRouterActive()
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL), routes: setupLayouts(generatedRoutes)
})
const updateRouterActive = (matched) => {
matched.shift()
const last = matched[matched.length - 1]
$router_active.value = []
if (no_login_list.indexOf(last.name) !== -1) return
setTimeout(() => {
$router_active.value = matched.map((item) => {
return {
title: 'title' in item.meta ? item.meta.title : item.name,
icon: 'icon' in item.meta ? item.meta.icon : false,
key: item.name
}
})
})
}
router.beforeEach(async (to, from, next) => {
window.$loading.start()
const $store = useStore()
if (!$store.config) {
const response = await ConfigGetAction(['Logo', 'Favicon', 'Login欢迎图片', '网站名称'])
$response(response, () => {
$store.config = response.data
})
$favicon($store.config['Favicon'])
}
document.title = ('title' in to.meta && to.meta.title !== '首页') ? `${to.meta.title} ${$store.config['网站名称']}` : $store.config['网站名称']
if (no_login_list.indexOf(to.name) === -1) {
const $save_token_type = useSaveTokenType()
let $token;
if ($save_token_type.value === 'local') {
$token = useToken()
} else {
$token = useSessionToken()
}
if ($token.value === '') {
next('/login?f=' + encodeURIComponent(to.fullPath))
setTimeout(() => {
window.$loading.finish()
})
} else {
const response = await AdminStatusAction()
$response(response, () => {
if (!$store.admin_info) reGetAdmin()
updateRouterActive(to.matched.map(item => item))
next()
}, next)
setTimeout(() => {
window.$loading.finish()
})
}
} else {
next()
setTimeout(() => {
window.$loading.finish()
})
}
})
export default router

@ -0,0 +1,17 @@
import {defineStore} from 'pinia'
export const useStore = defineStore('main', {
state: () => {
return {
config: false,
admin_info: false, api_loading: 0, count: 0
}
}
})
const TOKEN_KEY = JSON.parse(localStorage.getItem('APP_CONFIG') ?? '{}').token_key
export const useConfig = createGlobalState(() => useStorage('APP_CONFIG', JSON.parse(localStorage.getItem('APP_CONFIG') ?? '{}')))
export const useToken = createGlobalState(() => useStorage(TOKEN_KEY, ''))
export const useSessionToken = createGlobalState(() => useStorage(TOKEN_KEY, '', sessionStorage))
export const useSaveTokenType = createGlobalState(() => useStorage('SAVE_TOKEN_TYPE', 'session'))
export const useRouterActive = createGlobalState(() => useStorage('ROUTER_ACTIVE', []))
export const useCollapsed = createGlobalState(() => useStorage('COLLAPSED', false))

@ -0,0 +1,11 @@
html,
body,
#app {
height: 100%;
margin: 0;
padding: 0;
}
html.dark {
background: #333;
}

@ -0,0 +1,30 @@
import axios from 'axios'
import {useToken, useStore, useConfig, useSaveTokenType, useSessionToken} from '~/store'
const $save_token_type = useSaveTokenType()
let $token;
const post = axios.create({
method: 'POST'
})
post.interceptors.request.use(config => {
if ($save_token_type.value === 'local') {
$token = useToken()
} else {
$token = useSessionToken()
}
config.headers['Authorization'] = 'Bearer ' + $token.value
return config
}, error => Promise.reject(error))
post.interceptors.response.use(response => {
return (response.status === 200) ? response : Promise.reject('[ERROR] response.status: ' + response.status)
}, error => Promise.reject(error))
const $config = useConfig()
export const $post = async (request, loading = false) => {
const $store = useStore()
if (loading) $store.api_loading++
const response = await post(request).catch((e) => {
window.$message().error($config.value.api.error_message)
})
if (loading) $store.api_loading--
return !!response ? response.data : false
}

@ -0,0 +1,13 @@
function addLight(color, amount) {
const cc = parseInt(color, 16) + amount;
const c = cc > 255 ? 255 : cc;
return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
}
function lighten(color, amount) {
color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
amount = Math.trunc((255 * amount) / 100);
return `#${addLight(color.substring(0, 2), amount)}${addLight(color.substring(2, 4), amount)}${addLight(color.substring(4, 6), amount)}`;
}
export default {lighten}

@ -0,0 +1,10 @@
import {$image} from "~/api";
export const $favicon = (path, t = false) => {
const link = document.querySelector("link[rel*='icon']") || document.createElement('link')
link.type = 'image/x-icon'
link.rel = 'shortcut icon'
let href = $image(path)
link.href = t ? [href, 't=' + String(new Date() / 1)].join(href.indexOf('?') === -1 ? '?' : '&') : href
document.getElementsByTagName('head')[0].appendChild(link)
}

@ -0,0 +1,10 @@
import {useStore} from "~/store";
import {$response, AdminInfoAction} from "~/api";
export const reGetAdmin = async () => {
const response = await AdminInfoAction()
$response(response, () => {
const $store = useStore()
$store.admin_info = response.data.info
})
}

@ -0,0 +1,26 @@
import {defineConfig} from 'vite'
import Vue from '@vitejs/plugin-vue'
import path from 'path'
import Pages from 'vite-plugin-pages'
import Layouts from 'vite-plugin-vue-layouts'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import {NaiveUiResolver} from 'unplugin-vue-components/resolvers'
import Unocss from 'unocss/vite'
import {presetAttributify, presetUno, presetIcons} from 'unocss'
const admin_path = 'admin'
export default defineConfig({
base: `/${admin_path}/`,
build: {
outDir: `../../public/${admin_path}`, assetsDir: 'lib'
},
resolve: {alias: {'~/': `${path.resolve(__dirname, 'src')}/`}},
plugins: [Vue({reactivityTransform: true}), Pages(), Layouts(), AutoImport({
imports: ['vue', 'vue/macros', 'vue-router', '@vueuse/core',],
}), Components({resolvers: [NaiveUiResolver()]}), Unocss({
presets: [presetAttributify({}), presetUno(), presetIcons({
warn: true,
})],
})]
})
Loading…
Cancel
Save