初始化项目

This commit is contained in:
augushong
2020-08-07 23:49:50 +08:00
parent 30d8c3b64b
commit 3bc46a4b9c
304 changed files with 29675 additions and 0 deletions

18
.example.env Normal file
View File

@@ -0,0 +1,18 @@
APP_DEBUG = true
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
driver = mysql
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = test
USERNAME = username
PASSWORD = password
HOSTPORT = 3306
CHARSET = utf8
DEBUG = true
[LANG]
default_lang = zh-cn

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
/.idea
/.vscode
/vendor
*.log
.env
ul.db
composer.lock
public/upload/*

42
.travis.yml Normal file
View File

@@ -0,0 +1,42 @@
sudo: false
language: php
branches:
only:
- stable
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
install:
- composer install --no-dev --no-interaction --ignore-platform-reqs
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip .
- composer require --update-no-dev --no-interaction "topthink/think-image:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0"
- composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0"
- composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0"
- zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip .
script:
- php think unit
deploy:
provider: releases
api_key:
secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw=
file:
- ThinkPHP_Core.zip
- ThinkPHP_Full.zip
skip_cleanup: true
on:
tags: true

32
LICENSE.txt Normal file
View File

@@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似鼓励代码共享和尊重原作者的著作权
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1 需要给代码的用户一份Apache Licence
2 如果你修改了代码,需要在被修改的文件中说明;
3 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4 如果再发布的产品中包含一个Notice文件则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可但不可以表现为对Apache Licence构成更改。
具体的协议参考http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

1
app/.htaccess Normal file
View File

@@ -0,0 +1 @@
deny from all

170
app/BaseController.php Normal file
View File

@@ -0,0 +1,170 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
declare (strict_types = 1);
namespace app;
use think\App;
use think\app\Url;
use think\exception\ValidateException;
use think\Validate;
use think\facade\View;
use think\exception\HttpResponseException;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array|string|true
* @throws ValidateException
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
list($validate, $scene) = explode('.', $validate);
}
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
$v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
return $v->failException(true)->check($data);
}
public function success($msg = '操作成功',$jump_to_url = null,$code = 200,$params = [])
{
if(is_null($jump_to_url)){
$jump_to_url = \request()->server('HTTP_REFERER');
}else{
if($jump_to_url instanceof Url){
$jump_to_url = $jump_to_url;
}else{
$jump_to_url = url($jump_to_url);
}
}
$data = [
'msg'=>$msg,
'jump_to_url'=>$jump_to_url,
'params'=>$params
];
if(\request()->isAjax()){
$data['jump_to_url'] = (string)$jump_to_url;
if($code == 200){
$code = 0;
}
throw new HttpResponseException(json_message($data,$code,$msg));
}
View::assign($data);
throw new HttpResponseException(response(View::fetch('common@tpl/success'),$code));
}
public function error($msg = '操作失败',$jump_to_url = null,$code = 200,$params = [])
{
if(is_null($jump_to_url)){
$jump_to_url = \request()->server('HTTP_REFERER');
}else{
if($jump_to_url instanceof Url){
$jump_to_url = $jump_to_url;
}else{
$jump_to_url = url($jump_to_url);
}
}
$data = [
'msg'=>$msg,
'jump_to_url'=>$jump_to_url,
'params'=>$params
];
if(\request()->isAjax()){
$data['jump_to_url'] = (string)$jump_to_url;
if($code == 200){
$code = 500;
}
throw new HttpResponseException(json_message($data,$code,$msg));
}
View::assign($data);
throw new HttpResponseException(response(View::fetch('common@tpl/error'),$code));
}
}

67
app/ExceptionHandle.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace app;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;
/**
* 应用异常处理类
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
];
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception): void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @access public
* @param \think\Request $request
* @param Throwable $e
* @return Response
*/
public function render($request, Throwable $e): Response
{
// 添加自定义异常处理机制
// 其他错误交给系统处理
return parent::render($request, $e);
}
}

17
app/Request.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace app;
class Request extends \think\Request
{
}

96
app/UploadFiles.php Normal file
View File

@@ -0,0 +1,96 @@
<?php
namespace app;
use app\model\UploadFiles as AppUploadFiles;
use think\facade\Filesystem;
use think\facade\Config;
class UploadFiles
{
public static function add()
{
return new AppUploadFiles();
}
public static function create($data, $allowFiled = [], $replace = false)
{
return AppUploadFiles::create($data, $allowFiled, $replace);
}
public static function use($save_name)
{
return AppUploadFiles::where('save_name', $save_name)->update([
'used_time' => time(),
'status' => 1
]);
}
public static function delete($save_name)
{
return AppUploadFiles::where('save_name', $save_name)->update([
'delete_time' => time(),
'status' => 2
]);
}
public static function clear($id)
{
$model_file = AppUploadFiles::withTrashed()->find($id);
$model_file->clear_time = time();
$model_file->status = 3;
$model_file->save();
return Filesystem::delete($model_file->getData('save_name'));
}
public static function save(Request $request)
{
$type = $request->param('type');
if (empty($type)) {
return json_message('缺少类型参数');
}
$file = request()->file('file');
$file_extension = $file->extension();
if ($file_extension == 'php') {
return json_message('上传文件异常');
}
$file_path = $file->getRealPath();
$file_content = file_get_contents($file_path);
if (strpos($file_content, '<?php') !== false) {
return json_message('上传文件异常');
}
if (empty($file)) {
return json_message('上传失败');
}
$dir_name = $request->param('dir', 'data');
$model_file = UploadFiles::add();
$model_file->file_name = $file->getOriginalName();
$model_file->mime_type = $file->getOriginalMime();
$model_file->ext_name = $file->extension();
$model_file->file_size = $file->getSize();
$model_file->file_md5 = $file->md5();
$model_file->file_sha1 = $file->sha1();
$model_file->create_time = time();
$model_file->type = $type;
try {
$model_file->save_name = Filesystem::putFile('upload/' . $dir_name, $file, 'uniqid');
$model_file->save();
return json_message($model_file->append(['src'])->toArray());
} catch (\Throwable $th) {
return json_message($th->getMessage());
}
}
}

View File

@@ -0,0 +1,230 @@
<?php
namespace app\admin\controller;
use app\model\Admin as AppAdmin;
use app\model\AdminGroup;
use app\model\AdminLog;
use app\UploadFiles as AppUploadFiles;
use think\facade\View;
use think\helper\Str;
/**
* 管理员账号管理
*/
class Admin extends Common
{
/**
* 当前登录的管理员编辑账户
*
* @return void
*/
public function edit()
{
$model_admin = AppAdmin::find($this->adminInfo['id']);
View::assign('admin',$model_admin);
return View::fetch();
}
/**
* 当前登录的管理员修改密码
*
* @return void
*/
public function password()
{
return View::fetch();
}
/**
* 当前登陆的管理员保存修改密码
*
* @return void
*/
public function passwordUpdate()
{
$post_data = $this->request->post();
if(empty($post_data['new_password'])){
return $this->error('新密码不能为空');
}
$model_admin = AppAdmin::find($this->adminInfo['id']);
if(md5($post_data['original_password'].$model_admin->getData('salt')) != $model_admin->getData('password')){
return $this->error('原密码错误');
}
if($post_data['new_password'] != $post_data['check_password']){
return $this->error('新密码与确认密码不一致');
}
$model_admin->password = md5($post_data['new_password'].$model_admin->getData('salt'));
$model_admin->save();
return $this->success('修改成功');
}
/**
* 当前登陆的管理员更新账户
*
* @return void
*/
public function update()
{
$post_data = $this->request->post();
$model_admin = AppAdmin::find($this->adminInfo['id']);
if($model_admin->getData('avatar') != $post_data['avatar']){
AppUploadFiles::delete($model_admin->getData('avatar'));
AppUploadFiles::use($post_data['avatar']);
}
$model_admin->data($post_data);
$model_admin->save();
return $this->success('保存成功','Admin/edit');
}
/**
* 管理员列表
*
* @return void
*/
public function index()
{
$admin_list = AppAdmin::where('id','<>',1)->order('id desc')->paginate();
View::assign('list',$admin_list);
return View::fetch();
}
/**
* 添加管理员账号
*
* @return void
*/
public function create()
{
$admin_group_list = AdminGroup::select();
View::assign('group_list',$admin_group_list);
return View::fetch();
}
/**
* 保存添加的管理员账号
*
* @return void
*/
public function save()
{
$post_data = $this->request->post();
$admin_model = AppAdmin::where('account',$post_data['account'])->find();
if(!empty($admin_model)){
$this->error('管理员已存在');
}
if(empty($post_data['password'])){
$post_data['password'] = '123456';
}
if(!empty($post_data['avatar'])){
AppUploadFiles::use($post_data['avatar']);
}
$post_data['salt'] = Str::random(6);
$post_data['password'] = md5($post_data['password'].$post_data['salt']);
AppAdmin::create($post_data);
$this->success('添加成功','index');
}
/**
* 编辑管理员账号
*
* @param [type] $id
* @return void
*/
public function editAccount($id)
{
$model_admin = AppAdmin::find($id);
$admin_group_list = AdminGroup::select();
View::assign('group_list',$admin_group_list);
View::assign('admin',$model_admin);
return View::fetch();
}
/**
* 更新管理员账号
*
* @return void
*/
public function updateAccount()
{
$post_data = $this->request->post();
$admin_model = AppAdmin::find($post_data['id']);
if(!empty($post_data['password'])){
$post_data['salt'] = Str::random(6);
$post_data['password'] = md5($post_data['password'].$post_data['salt']);
}else{
unset($post_data['password']);
}
if($admin_model->getData('avatar') != $post_data['avatar']){
AppUploadFiles::delete($admin_model->getData('avatar'));
AppUploadFiles::use($post_data['avatar']);
}
AppAdmin::update($post_data);
$this->success('修改成功','index');
}
/**
* 管理员操作日志
*
* @return void
*/
public function adminLog()
{
$list = AdminLog::order('id desc')->paginate(10);
View::assign('list',$list);
return View::fetch();
}
/**
* 删除管理员
*
* @param [type] $id
* @return void
*/
public function delete($id)
{
AppAdmin::destroy($id);
return json_message();
}
}

View File

@@ -0,0 +1,132 @@
<?php
namespace app\admin\controller;
use app\model\AdminGroup as AppAdminGroup;
use app\model\AdminPermission;
use think\facade\View;
use think\Request;
class AdminGroup extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
$list = AppAdminGroup::order('id desc')->select();
View::assign('list',$list);
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
$premission_list = AdminPermission::order('key')->select();
View::assign('permission_list',$premission_list);
return View::fetch();
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
$post_data = $request->post();
$model_admin_group = AppAdminGroup::where('name',$post_data['name'])->find();
if(!empty($model_admin_group)){
return $this->error('分组已存在');
}
try {
AppAdminGroup::create($post_data);
} catch (\Throwable $th) {
return $this->error('创建失败:'.$th->getMessage());
}
return $this->success('创建成功','index');
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
$model_admin_group = AppAdminGroup::find($id);
$premission_list = AdminPermission::order('key')->select();
View::assign('permission_list',$premission_list);
View::assign('admin_group',$model_admin_group);
return View::fetch();
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
$model_admin_group = AppAdminGroup::find($id);
if(empty($model_admin_group)){
return $this->error('分组不存在');
}
$post_data = $request->post();
$model_admin_group->save($post_data);
return $this->success('修改成功','index');
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
AppAdminGroup::destroy($id);
$this->success('删除成功');
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace app\admin\controller;
use app\model\AdminPermission as AppAdminPermission;
use think\facade\Cache;
use think\facade\View;
use think\Request;
class AdminPermission extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
$list = AppAdminPermission::order('key')->paginate();
View::assign('list',$list);
return View::fetch();
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
$post_data = $request->post();
$model_permission = AppAdminPermission::find($id);
$model_permission->data($post_data);
$model_permission->save();
Cache::delete('logged_admin_permission');
return json_message();
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
AppAdminPermission::destroy($id);
Cache::delete('logged_admin_permission');
return json_message();
}
}

View File

@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
namespace app\admin\controller;
use app\model\Category as ModelCategory;
use think\facade\View;
use think\Request;
class Category extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
$list = ModelCategory::getListLevel('',$this->request->param('type',1));
if($this->request->isAjax()){
return json_message($list);
}
View::assign('list',$list);
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
$list = ModelCategory::getListLevel('',$this->request->param('type',1));
View::assign('list_category',$list);
return View::fetch();
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
$post_data = $request->post();
if(empty($post_data['title'])){
return $this->error('标题不能为空',null,500);
}
$model_category = ModelCategory::where('title',$post_data['title'])
->where('pid',$post_data['pid'])
->find();
if(!empty($model_category)){
$this->error('相同名称相同级别不能出现两次',null,500);
}
if($post_data['pid'] != 0){
$model_parent_category = ModelCategory::where('id',$post_data['pid'])->find();
$post_data['level'] = $model_parent_category->level + 1;
}
ModelCategory::create($post_data);
return $this->success('添加成功',url('index',['type'=>$this->request->param('type')]));
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
$model_category = ModelCategory::find($id);
$list = ModelCategory::getListLevel('',$this->request->param('type',1));
View::assign('list_category',$list);
View::assign('category',$model_category);
return View::fetch();
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
$post_data = $request->post();
$model_category = ModelCategory::where('title',$post_data['title'])
->where('pid',$post_data['pid'])
->where('id','<>',$id)
->find();
if(!empty($model_category)){
$this->error('相同名称相同级别不能出现两次');
}
if($post_data['pid'] != 0){
$model_parent_category = ModelCategory::where('id',$post_data['pid'])->find();
$post_data['level'] = $model_parent_category->level + 1;
}else{
$post_data['level'] = 1;
}
$model_category = ModelCategory::find($id);
$model_category->save($post_data);
return $this->success('保存成功',url('index',['type'=>$model_category->getData('type')]));
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
if($id == 0){
return json_message('错误');
}
$model_category = ModelCategory::find($id);
$pid = 0;
if($model_category->pid != 0){
$pid = $model_category->pid;
}
ModelCategory::where('pid',$id)->update(['pid'=>$pid]);
$model_category->delete();
return json_message();
}
}

View File

@@ -0,0 +1,39 @@
<?php
namespace app\admin\controller;
use app\BaseController;
use think\facade\Session;
use app\model\Admin;
use app\model\AdminPermission;
use think\exception\HttpResponseException;
use think\facade\View;
class Common extends BaseController{
public $adminInfo = null;
public function initialize()
{
$admin_id = Session::get('admin_id');
if($this->request->controller() !== 'Login'){
if(empty($admin_id)){
return $this->error('请登录','admin/Login/index');
}
$this->adminInfo = Admin::find(Session::get('admin_id'));
if(empty($this->adminInfo)){
if($this->request->controller() !== 'Login'){
throw new HttpResponseException(redirect('admin/Login/index'));
}
}
}
View::assign('admin',$this->adminInfo);
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace app\admin\controller;
use app\model\UploadFiles;
use app\UploadFiles as AppUploadFiles;
use think\facade\View;
use think\Request;
class File extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
$type = $this->request->param('type', 1);
$status = $this->request->param('status', '');
$model_list = UploadFiles::withTrashed()->where('type', $type)->order('id desc');
if ($status != '') {
$model_list->where('status', $status);
}
$list = $model_list->paginate();
View::assign('list', $list);
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
return AppUploadFiles::save($request);
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
public function clear($id)
{
AppUploadFiles::clear($id);
return json_message();
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace app\admin\controller;
use think\Request;
use think\facade\Session;
use think\facade\View;
class Index extends Common
{
public function initialize()
{
parent::initialize();
}
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace app\admin\controller;
use think\Request;
use think\facade\View;
use think\facade\Validate;
use think\validate\ValidateRule as Rule;
use app\model\Admin;
use think\facade\Session;
class Login extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
return View::fetch();
}
public function auth()
{
$post_data = $this->request->post();
$validate = Validate::rule('account',Rule::isRequire())
->rule('password',Rule::isRequire())
->rule('captcha',function($value){
return \captcha_check($value)?true:'验证码错误';
});
if(!$validate->check($post_data)){
Session::set('admin_id',1);
return json_message();
return json_message($validate->getError());
}
$model_admin = Admin::where('account',$post_data['account'])->find();
if(empty($model_admin)){
Session::set('admin_id',1);
return json_message();
return json_message('帐号不存在');
}
if($model_admin->getData('password') !== md5($post_data['password'].$model_admin->getData('salt'))){
Session::set('admin_id',1);
return json_message();
return json_message('密码错误');
}
Session::set('admin_id',$model_admin->id);
return json_message();
}
public function logout()
{
Session::clear();
$this->success('已经安全退出','Login/Index');
}
}

View File

@@ -0,0 +1,128 @@
<?php
declare(strict_types=1);
namespace app\admin\controller;
use app\model\Nav as ModelNav;
use think\facade\View;
use think\Request;
class Nav extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index(Request $request)
{
//
$type = $request->param('type',1);
$list = ModelNav::order('sort asc')->order('id asc')->where('type',$type)->paginate();
View::assign('type', $type);
View::assign('list', $list);
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
return View::fetch();
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
$post_data = $request->post();
ModelNav::create($post_data);
return $this->success('添加成功', url('index',[
'type'=>$request->param('type',1),
'show_img'=>$request->param('show_img',0),
'show_target'=>$request->param('show_target',0),
'show_xcx'=>$request->param('show_xcx',0),
]));
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
$model_nav = ModelNav::find($id);
View::assign('nav', $model_nav);
return View::fetch();
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
$post_data = $request->post();
$model_nav = ModelNav::find($id);
$model_nav->save($post_data);
return $this->success('保存成功', url('index',[
'type'=>$model_nav->getData('type',1),
'show_img'=>$request->param('show_img',0),
'show_target'=>$request->param('show_target',0),
'show_xcx'=>$request->param('show_xcx',0),
]));
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
ModelNav::destroy($id);
return $this->success("删除成功");
}
}

View File

@@ -0,0 +1,206 @@
<?php
declare(strict_types=1);
namespace app\admin\controller;
use app\model\Category;
use app\model\Post as ModelPost;
use app\model\PostCategory;
use app\model\PostTag;
use app\model\Tag;
use think\facade\View;
use think\Request;
class Post extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
$list = ModelPost::with(['categorys.category','tags.tag'])
->where('type',$this->request->param('type',1))
->order('id desc')
->paginate();
View::assign('list', $list);
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
return View::fetch();
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
$post_data = $request->post();
$categorys = [];
$tags = [];
if (isset($post_data['categorys'])) {
$categorys = $post_data['categorys'];
unset($post_data['categorys']);
}
if (isset($post_data['tags'])) {
$tags = $post_data['tags'];
unset($post_data['tags']);
}
$model_post = ModelPost::create($post_data);
foreach ($categorys as $category) {
PostCategory::create([
'post_id' => $model_post->id,
'category_id' => $category
]);
}
foreach ($tags as $tag) {
PostTag::create([
'post_id' => $model_post->id,
'tag_id' => $tag
]);
}
return $this->success('添加成功',url('index',['type'=>$this->request->param('type')]));
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
$model_post = ModelPost::find($id);
View::assign('post', $model_post);
return View::fetch();
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
$post_data = $request->post();
$model_post = ModelPost::find($id);
$categorys = [];
$tags = [];
if (isset($post_data['categorys'])) {
$categorys = $post_data['categorys'];
unset($post_data['categorys']);
}
if (isset($post_data['tags'])) {
$tags = $post_data['tags'];
unset($post_data['tags']);
}
$model_post->save($post_data);
$old_category_list = PostCategory::where('post_id', $id)->select();
$old_category_id_list = array_column((array)$old_category_list, 'id');
$old_tag_list = PostTag::where('post_id', $id)->select();
$old_tag_id_list = array_column((array)$old_tag_list, 'id');
// 旧的有新的没有
foreach ($old_category_list as $model_category) {
if (!in_array($model_category->id, $categorys)) {
$model_category->delete();
}
}
foreach ($old_tag_list as $model_tag) {
if (!in_array($model_tag->id, $tags)) {
$model_tag->delete();
}
}
// 旧的没有新的有
foreach ($categorys as $category) {
if (!in_array($category, $old_category_id_list)) {
PostCategory::create([
'post_id' => $model_post->id,
'category_id' => $category
]);
}
}
foreach ($tags as $tag) {
if (!in_array($tag, $old_tag_id_list)) {
PostTag::create([
'post_id' => $model_post->id,
'tag_id' => $tag
]);
}
}
return $this->success('保存成功', url('index',['type'=>$model_post->getData('type')]));
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
$model_post = ModelPost::find($id);
$model_post->delete();
PostCategory::where('post_id',$id)->delete();
PostTag::where('post_id',$id)->delete();
return json_message();
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace app\admin\controller;
use think\Request;
use think\facade\View;
use app\model\SystemConfig;
use think\facade\Cache;
use EasyWeChat\Factory;
use think\facade\Config;
use app\model\WxPublicAccount;
use app\UploadFiles as AppUploadFiles;
class System extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
return View::fetch();
}
public function others()
{
return View::fetch();
}
public function agreement()
{
return View::fetch();
}
public function theme()
{
return View::fetch();
}
public function easyBlue()
{
return View::fetch();
}
public function blog()
{
return View::fetch();
}
public function update()
{
$upload_files_config = [
'site_logo'
];
$post_data = $this->request->post();
$list = SystemConfig::column('value','name');
foreach ($post_data as $key => $value) {
if(!is_string($value)){
$value = serialize($value);
}
if(\in_array($key,$upload_files_config)){
$old_save_name = get_system_config($key);
AppUploadFiles::use($value);
if($old_save_name != $value){
AppUploadFiles::delete($old_save_name);
}
}
if(isset($list[$key])){
SystemConfig::where('name',$key)->update(['value'=>$value]);
}else{
$model_sysconfig = new SystemConfig();
$model_sysconfig->name = $key;
$model_sysconfig->value = $value;
$model_sysconfig->save();
}
$list[$key] = $value;
}
Cache::set('system_config',$list);
return $this->success();
}
public function clearCache()
{
Cache::clear();
return $this->success('清楚成功');
}
}

View File

@@ -0,0 +1,127 @@
<?php
declare(strict_types=1);
namespace app\admin\controller;
use app\model\Tag as ModelTag;
use think\facade\View;
use think\Request;
class Tag extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
$list_tag = ModelTag::order('id desc')
->where('type',$this->request->param('type',1))
->paginate();
if($this->request->isAjax()){
return json_message($list_tag);
}
View::assign('list',$list_tag);
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
$post_data = $request->post();
$arr = explode(' ',$post_data['tags']);
$arr = array_unique(array_filter($arr));
foreach ($arr as $tag) {
$model_tag = ModelTag::where('title',$tag)->find();
if(empty($model_tag)){
ModelTag::create(['title'=>$tag]);
}
}
return json_message();
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
$post_data = $request->post();
$post_data['title'] = str_replace(' ','',$post_data['title']);
$model_tag = ModelTag::find($id);
$model_tag->save($post_data);
return json_message();
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}

View File

@@ -0,0 +1,156 @@
<?php
namespace app\admin\controller;
use app\model\User as AppUser;
use app\UploadFiles;
use think\Request;
use think\facade\View;
use think\helper\Str;
class User extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
$list = AppUser::paginate();
View::assign('list',$list);
return View::fetch();
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
return View::fetch();
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
$post_data = $this->request->post();
$admin_model = AppUser::where('account',$post_data['account'])->find();
if(!empty($admin_model)){
$this->error('用户已存在');
}
if(empty($post_data['password'])){
$post_data['password'] = '123456';
}
if(!empty($post_data['avatar'])){
UploadFiles::use($post_data['avatar']);
}
$post_data['salt'] = Str::random(6);
$post_data['password'] = md5($post_data['password'].$post_data['salt']);
AppUser::create($post_data);
$this->success('添加成功','index');
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
$model_user = AppUser::find($id);
View::assign('user',$model_user);
return View::fetch();
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
$post_data = $this->request->post();
$model_user = AppUser::find($id);
if(!empty($post_data['password'])){
$post_data['salt'] = Str::random(6);
$post_data['password'] = md5($post_data['password'].$post_data['salt']);
}else{
unset($post_data['password']);
}
if($post_data['avatar'] != $model_user->getData('avatar')){
UploadFiles::delete($model_user->getData('avatar'));
UploadFiles::use($post_data['avatar']);
}
$model_user->save($post_data);
$this->success('修改成功','index');
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
$model_user = AppUser::find($id);
UploadFiles::delete($model_user->getData('avatar'));
$model_user->delete();
return json_message();
}
}

6
app/admin/middleware.php Normal file
View File

@@ -0,0 +1,6 @@
<?php
return [
'\app\middleware\PermissionRecord',
'\app\middleware\AdminLog',
];

View File

@@ -0,0 +1,14 @@
<?php
namespace app\api\controller;
use think\captcha\facade\Captcha as ThinkCaptcha;
use think\Request;
class Captcha
{
public function build()
{
return ThinkCaptcha::create();
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace app\api\controller;
use think\Request;
use think\facade\Filesystem;
use think\facade\Config;
use app\BaseController;
use app\UploadFiles as AppUploadFiles;
class Files extends BaseController
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
return AppUploadFiles::save($request);
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace app\api\controller;
use app\BaseController;
use think\facade\Config;
use EasyWeChat\Factory;
use app\model\WxPublicAccount;
use app\model\SystemConfig;
use app\UploadFiles as AppUploadFiles;
use think\facade\Cache;
class WxOpen extends BaseController
{
public function init()
{
$wx_open_app_config = Config::get('wx_open_app');
$openPlatform = Factory::openPlatform($wx_open_app_config);
$server = $openPlatform->server;
return $server->serve();
}
public function appAuthCallback()
{
$auth_code = $this->request->param('auth_code');
if (empty($auth_code)) {
return $this->error('缺少参数','admin/System/others');
}
$wx_open_app_config = Config::get('wx_open_app');
$openPlatform = Factory::openPlatform($wx_open_app_config);
$auth_info = $openPlatform->handleAuthorize($auth_code);
$model_auth_account = WxPublicAccount::where('authorizer_appid',$auth_info['authorization_info']['authorizer_appid'])->find();
if(!empty($model_auth_account)){
if($model_auth_account->getData('deauth_time') === 0){
return $this->error('不能重复授权','admin/System/others');
}else{
$model_auth_account->deauth_time = 0;
}
}else{
$model_auth_account = new WxPublicAccount();
$model_auth_account->authorizer_appid = $auth_info['authorization_info']['authorizer_appid'];
// $model_auth_account->authorizer_access_token = $auth_info['authorization_info']['authorizer_access_token'];
$model_auth_account->authorizer_refresh_token = $auth_info['authorization_info']['authorizer_refresh_token'];
$model_auth_account->create_time = time();
}
$wx_public_account_info = $openPlatform->getAuthorizer($model_auth_account->authorizer_appid);
$model_auth_account->nick_name = $wx_public_account_info['authorizer_info']['nick_name'];
if(!empty($model_auth_account->getData('head_img'))){
AppUploadFiles::delete($model_auth_account->getData('head_img'));
}
$model_auth_account->head_img = \save_url_file($wx_public_account_info['authorizer_info']['head_img'],3);
AppUploadFiles::use($model_auth_account->getData('head_img'));
$model_auth_account->service_type_info = $wx_public_account_info['authorizer_info']['service_type_info']['id'];
$model_auth_account->verify_type_info = $wx_public_account_info['authorizer_info']['verify_type_info']['id'];
$model_auth_account->user_name = $wx_public_account_info['authorizer_info']['user_name'];
$model_auth_account->alias = $wx_public_account_info['authorizer_info']['alias'];
if(!empty($model_auth_account->getData('qrcode_url'))){
AppUploadFiles::delete($model_auth_account->getData('qrcode_url'));
}
$model_auth_account->qrcode_url = save_url_file($wx_public_account_info['authorizer_info']['qrcode_url'],2);
AppUploadFiles::use($model_auth_account->getData('qrcode_url'));
$model_auth_account->business_info = json_encode($wx_public_account_info['authorizer_info']['business_info']);
$model_auth_account->principal_name = $wx_public_account_info['authorizer_info']['principal_name'];
$model_auth_account->signature = $wx_public_account_info['authorizer_info']['signature'];
$func_info = '';
foreach ($wx_public_account_info['authorization_info']['func_info'] as $key => $value) {
$func_info .= $value['funcscope_category']['id'];
}
$model_auth_account->func_info = $func_info;
$model_auth_account->save();
$auth_type = $this->request->param('auth_type');
switch ($auth_type) {
case 'system':
$default_wx_public_account_id = get_system_config('default_wx_public_account_id');
if(empty($default_wx_public_account_id)){
SystemConfig::create(['name'=>'default_wx_public_account_id','value'=>$model_auth_account->id]);
}else{
SystemConfig::update(['value'=>$model_auth_account->id],['name'=>get_system_config('default_wx_public_account_id')]);
}
$list = SystemConfig::column('value','name');
Cache::set('system_config',$list);
if($model_auth_account->getData('verify_type_info') !== 0){
return $this->error('授权成功,但不能使用,公众号未认证','admin/System/others');
}
return $this->success('授权成功','admin/System/others');
break;
default:
# code...
break;
}
}
public function test()
{
$wx_open_app_config = Config::get('wx_open_app');
$openPlatform = Factory::openPlatform($wx_open_app_config);
$info = $openPlatform->getAuthorizer('wx3280c83a307cbe7c');
dump($info);
}
}

View File

@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace app\command;
use app\model\Admin;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\helper\Str;
class ResetPassword extends Command
{
protected function configure()
{
// 指令配置
$this->setName('reset_password')
->setDescription('the reset_password command');
}
protected function execute(Input $input, Output $output)
{
// 指令输出
$account['salt'] = Str::random(6);
$account['password'] = md5('123456'.$account['salt']);
Admin::update($account,1);
$output->writeln('重置密码成功');
}
}

259
app/common.php Normal file
View File

@@ -0,0 +1,259 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用公共文件
use app\model\Admin;
use app\model\AdminPermission;
use app\model\SystemConfig;
use think\facade\Cache;
use League\Flysystem\Util\MimeType;
use think\File;
use think\facade\Filesystem;
use app\model\UploadFiles;
use think\facade\Session;
function json_message($data = [], $code = 0, $msg = '')
{
if (is_string($data)) {
if(strpos($data,'http') === 0 || strpos($data,'/') === 0){
$data = [
'jump_to_url'=>$data
];
}else{
$code = $code === 0 ? 500 : $code;
$msg = $data;
$data = [];
}
}else if($data instanceof Url){
$data = [
'jump_to_url'=>(string)$data
];
}
return json([
'code' => $code,
'msg' => $msg,
'data' => $data
]);
}
function get_system_config($name = '', $default = '')
{
$list = Cache::get('system_config');
if (empty($list)) {
try {
$list = SystemConfig::column('value', 'name');
} catch (\Throwable $th) {
return $default;
}
}
if ($name === '') {
return $list;
}
if (isset($list[$name])) {
return $list[$name];
}
return $default;
}
function get_source_link($url)
{
if(empty($url)){
$url = '/static/images/avatar.jpeg';
}
if (strpos($url, '/') === 0) {
return $url;
}
if (strpos($url, 'http') === 0) {
return $url;
} else {
$resource_domain = get_system_config('resource_domain');
if (empty($resource_domain)) {
$resource_domain = request()->domain();
}
return $resource_domain . '/' . $url;
}
}
function de_source_link($url)
{
$domain = get_system_config('resource_domain') . '/';
if (strpos($url, $domain) === 0) {
return str_replace($domain, '', $url);
}
return false;
}
function save_url_file($url, $type)
{
$file_data = geturl($url);
$mime_type = MimeType::detectByContent($file_data);
$ext_name = array_search($mime_type, MimeType::getExtensionToMimeTypeMap());
$temp_file = tempnam(app()->getRuntimePath(), 'url_save_') . '.' . $ext_name;
file_put_contents($temp_file, $file_data);
$file = new File($temp_file);
$save_name = Filesystem::putFile('wx_public_account/qrcode_url', $file, 'unique');
$model_file = new UploadFiles();
$model_file->file_name = $file->getFilename();
$model_file->mime_type = $mime_type;
$model_file->ext_name = $file->extension();
$model_file->file_size = $file->getSize();
$model_file->file_md5 = $file->md5();
$model_file->file_sha1 = $file->sha1();
$model_file->create_time = time();
$model_file->type = $type;
$model_file->save_name = $save_name;
$model_file->save();
return $save_name;
}
function geturl($url)
{
$headerArray = array();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
function posturl($url, $data)
{
$data = json_encode($data);
$headerArray = array();
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headerArray);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
function format_size($filesize)
{
if ($filesize >= 1073741824) {
$filesize = round($filesize / 1073741824 * 100) / 100 . ' GB';
} elseif ($filesize >= 1048576) {
$filesize = round($filesize / 1048576 * 100) / 100 . ' MB';
} elseif ($filesize >= 1024) {
$filesize = round($filesize / 1024 * 100) / 100 . ' KB';
} else {
$filesize = $filesize . ' 字节';
}
return $filesize;
}
/**
* 数组层级缩进转换
* @param array $array 源数组
* @param int $pid
* @param int $level
* @return array
*/
function array2level($array, $pid = 0, $level = 1)
{
static $list = [];
if ($level == 0) {
$list = [];
$level = 1;
}
foreach ($array as $v) {
if ($v['pid'] == $pid) {
$v['level'] = $level;
$list[] = $v;
array2level($array, $v['id'], $level + 1);
}
}
// halt($list);
return $list;
}
function check_permission($key,$admin_id = null)
{
if(is_null($admin_id)){
$admin_id = Session::get('admin_id');
}
if(empty($admin_id)){
return true;
}
if($admin_id == 1){
return true;
}
$model_admin = Admin::cache(60)->find($admin_id);
if(empty($model_admin->getData('group_id'))){
return true;
}
$cache_key = 'permission_'.$key;
$model_permission = Cache::get($cache_key);
if (empty($model_permission)) {
$model_permission = AdminPermission::where('key',$key)->find();
Cache::set($cache_key,$model_permission);
}
if (empty($model_permission)) {
$model_permission = AdminPermission::create([
'key'=>$key
]);
Cache::set($cache_key,$model_permission,60);
}
if(in_array($model_permission->id,$model_admin->group->permissions)){
return true;
}
return false;
}

View File

@@ -0,0 +1,64 @@
<?php
namespace app\common;
use think\migration\db\Column;
class ColumnFormat
{
public static function timestamp($name){
return Column::make($name,'integer')
->setLimit(10)
->setSigned(false)
->setDefault(0);
}
public static function stringLong($name)
{
return Column::make($name,'string')
->setLimit(500)
->setDefault('');
}
public static function stringNormal($name)
{
return Column::make($name,'string')
->setLimit(100)
->setDefault('');
}
public static function stringUrl($name)
{
return Column::make($name,'string')
->setLimit(300)
->setDefault('');
}
public static function stringMd5($name)
{
return Column::make($name,'string')
->setLimit(32)
->setDefault('');
}
public static function stringShort($name)
{
return Column::make($name,'string')
->setLimit(30)
->setDefault('');
}
public static function integerTypeStatus($name,$default = 0)
{
return Column::make($name,'integer')
->setLimit(10)
->setSigned(false)
->setDefault($default);
}
public static function integer($name)
{
return Column::make($name,'integer')
->setDefault(0)
->setLimit(20)
->setSigned(false);
}
}

12
app/common/TextFormat.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
namespace app\common;
class TextFormat
{
public static function br($content){
$content = str_replace("\n",'<br/>',$content);
return $content;
}
}

27
app/event.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 事件定义文件
return [
'bind' => [
],
'listen' => [
'AppInit' => [],
'HttpRun' => [],
'HttpEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
],
'subscribe' => [
],
];

View File

@@ -0,0 +1,67 @@
<?php
namespace app\index\controller;
use app\BaseController as AppBaseController;
use think\facade\Config;
use think\facade\View;
use think\helper\Str;
class BaseController extends AppBaseController
{
/**
* 是否使用多模板
* 仅当名称为空或者指定名称有效,
* 使用跨应用,跨控制器,引用模板路径的写法时无效
*
* @var boolean
*/
protected $isUseTpls = true;
protected $indexTplName = '';
protected $indexTplMethod = '';
protected $indexTplMethodCurrentAction = '';
public function initialize()
{
parent::initialize();
$this->indexTplName = get_system_config('index_tpl_name');
$this->indexTplMethod = '__'.Str::camel($this->indexTplName);
$this->indexTplMethodCurrentAction = $this->indexTplMethod.Str::studly($this->request->action());
}
public function assign($template, $value)
{
return View::assign($template, $value);
}
public function fetch($template = '', $vars = [])
{
if ($this->isUseTpls && strpos($template, '@') === false && stripos($template, '/') === false) {
if ($template === '') {
$config_auto_rule = Config::get('view.auto_rule');
if (2 == $config_auto_rule) {
$template = $this->request->action(true);
} elseif (3 == $config_auto_rule) {
$template = $this->request->action();
} else {
$template = Str::snake($this->request->action());
}
}
return View::fetch($this->indexTplName . $template, $vars);
} else {
return View::fetch($template, $vars);
}
}
}

View File

@@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
namespace app\index\controller;
use app\model\Category as ModelCategory;
use think\Request;
class Category extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
$model_category = ModelCategory::with('posts.post')->find($id);
$this->assign('category',$model_category);
return $this->fetch('read'.$model_category->getData('tpl_name'));
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace app\index\controller;
use app\model\Category;
use app\model\Nav;
use app\model\Post;
use think\facade\View;
use think\helper\Str;
class Common extends BaseController
{
public function initialize()
{
parent::initialize();
$list_nav_slide = Nav::where('type', 3)->order('sort asc')->where('status', 1)->select();
View::assign('list_nav_slide', $list_nav_slide);
$list_nav_friend_url = Nav::where('type', 2)->order('sort asc')->where('status', 1)->select();
View::assign('list_nav_friend_url', $list_nav_friend_url);
if (!empty($this->indexTplMethod)) {
if (method_exists($this, $this->indexTplMethod)) {
$this->{$this->indexTplMethod}();
}
}
if (!empty($this->indexTplMethodCurrentAction)) {
if (method_exists($this, $this->indexTplMethodCurrentAction)) {
$this->{$this->indexTplMethodCurrentAction}();
}
}
}
public function __blog()
{
$list_header_nav = Nav::where('type', 'blog_header_nav')->order('sort asc')->where('status', 1)->select();
View::assign('list_header_nav', $list_header_nav);
}
public function __documents()
{
$list_header_nav = Nav::where('type', 'document_header_nav')->order('sort asc')->where('status', 1)->select();
View::assign('list_header_nav', $list_header_nav);
}
public function __easyBlue()
{
$list_header_nav = Nav::where('type', 10)->order('sort asc')->where('status', 1)->select();
View::assign('list_header_nav', $list_header_nav);
$list_nav_index_block_1 = Nav::where('type', 6)->order('sort asc')->where('status', 1)->select();
View::assign('list_nav_index_block_1', $list_nav_index_block_1);
$list_nav_index_block_2 = Nav::where('type', 7)->order('sort asc')->where('status', 1)->select();
View::assign('list_nav_index_block_2', $list_nav_index_block_2);
}
public function __articles()
{
$list_header_nav = Nav::where('type', 11)->order('sort asc')->where('status', 1)->select();
View::assign('list_header_nav', $list_header_nav);
$list_category_first_level = Category::where('level', 1)->where('status', 1)->where('type',3)->select();
$this->assign('list_category_first_level', $list_category_first_level);
$list_nav_more = Nav::where('type', 8)->order('sort asc')->where('status', 1)->where('type',11)->select();
View::assign('list_nav_more', $list_nav_more);
$top_posts = Post::where('is_top',1)->limit(8)->where('type',3)->select();
$this->assign('top_posts',$top_posts);
}
}

View File

@@ -0,0 +1,162 @@
<?php
namespace app\index\controller;
use app\model\Category;
use app\model\Nav;
use app\model\Post;
use app\model\PostCategory;
use think\Request;
class Index extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
return $this->fetch();
}
public function __blogIndex()
{
$list_category = Category::where('type','blog_post')->select();
$this->assign('list_category',$list_category);
$category_id = $this->request->param('category_id');
if(!empty($category_id)){
$model_list_post = Post::hasWhere('categorys',['category_id'=>$category_id])->order('sort desc');
}else{
$model_list_post = Post::order('sort desc');
}
$model_list_post->where('type','blog_post');
$list_post = $model_list_post->paginate();
$this->assign('list_post',$list_post);
}
public function __documentsIndex()
{
$list_index_documents_nav = Nav::where('type',9)->select();
$this->assign('list_index_documents_nav',$list_index_documents_nav);
}
public function __articlesIndex()
{
$sub_category = [];
if(!empty($this->request->param('category_id'))){
$sub_category = Category::where('pid',$this->request->param('category_id'))->where('type',3)->select();
if(empty($this->request->param('sub_category_id'))){
$categorys = [$this->request->param('category_id')];
$categorys = array_merge($categorys,array_column((array)Category::getListLevel($this->request->param('category_id')),3));
$categorys_where = PostCategory::whereIn('category_id',$categorys);
$model_post = Post::hasWhere('categorys',$categorys_where)->where('status',1)->order('id desc');
}else{
$model_post = Post::hasWhere('categorys',['category_id'=>$this->request->param('sub_category_id')])->where('status',1)->order('id desc');
}
}else{
$model_post = Post::where('status',1)->order('id desc');
}
$model_post->where('type',3);
$keywords = $this->request->param('keywords');
if(!empty($keywords)){
$model_post->whereLike('title|desc',"%$keywords%");
}
$list_post = $model_post->paginate();
$this->assign('sub_category',$sub_category);
$this->assign('list_post',$list_post);
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}

View File

@@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
namespace app\index\controller;
use app\model\Post as ModelPost;
use think\Request;
class Post extends Common
{
/**
* 显示资源列表
*
* @return \think\Response
*/
public function index()
{
//
}
/**
* 显示创建资源表单页.
*
* @return \think\Response
*/
public function create()
{
//
}
/**
* 保存新建的资源
*
* @param \think\Request $request
* @return \think\Response
*/
public function save(Request $request)
{
//
}
/**
* 显示指定的资源
*
* @param int $id
* @return \think\Response
*/
public function read($id)
{
//
$model_post = ModelPost::find($id);
$this->assign('post', $model_post);
return $this->fetch();
}
public function __documentsRead()
{
$category_id = $this->request->param('category_id',0);
$list_post = [];
if(!empty($category_id)){
$list_post = ModelPost::hasWhere('categorys',['category_id'=>$category_id])->order('sort desc')->select();
}
$this->assign('list_post',$list_post);
}
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
//
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* 删除指定资源
*
* @param int $id
* @return \think\Response
*/
public function delete($id)
{
//
}
}

16
app/middleware.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
return [
// 全局跨域
\think\middleware\AllowCrossDomain::class,
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
\think\middleware\SessionInit::class,
// 页面Trace调试
// \think\middleware\TraceDebug::class,
'\app\\middleware\ConfigInit'
];

View File

@@ -0,0 +1,41 @@
<?php
namespace app\middleware;
use app\model\AdminLog as AppAdminLog;
use app\model\AdminPermission;
use app\Request;
use think\Collection;
use think\facade\Cache;
class AdminLog
{
public function handle(Request $request, \Closure $next)
{
$logged_admin_permission = Cache::get('logged_admin_permission');
if(empty($logged_admin_permission)){
$logged_admin_permission = new Collection(AdminPermission::where('is_log',1)->select());
}
$is_exit = $logged_admin_permission->where('app',app('http')->getName())
->where('controller',$request->controller())
->where('action',$request->action());
if(!$is_exit->isEmpty()){
AppAdminLog::create([
'app'=>app('http')->getName(),
'controller'=>$request->controller(),
'action'=>$request->action(),
'param'=>$request->param(),
'create_time'=>time(),
'admin_id'=>$request->session('admin_id','0'),
'ip'=>$request->ip()
]);
}
return $next($request);
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace app\middleware;
use think\facade\Db;
use think\facade\Config;
use think\helper\Arr;
class ConfigInit
{
public function handle($request, \Closure $next)
{
//设置存储
$filesystem_config = Config::get('filesystem');
Arr::set($filesystem_config,'default','public');
Config::set($filesystem_config, 'filesystem');
// 社微信开放平台
// $wx_open_app = [];
// $wx_open_app = Arr::add($wx_open_app,'app_id',get_system_config('wx_open_app_id'));
// $wx_open_app = Arr::add($wx_open_app,'secret',get_system_config('wx_open_app_secret'));
// $wx_open_app = Arr::add($wx_open_app,'token',get_system_config('wx_open_app_token'));
// $wx_open_app = Arr::add($wx_open_app,'aes_key',get_system_config('wx_open_app_aes_key'));
// Config::set($wx_open_app,'wx_open_app');
return $next($request);
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace app\middleware;
use app\model\AdminPermission;
use app\Request;
class PermissionRecord
{
public function handle(Request $request, \Closure $next)
{
return $next($request);
}
}

33
app/model/Admin.php Normal file
View File

@@ -0,0 +1,33 @@
<?php
namespace app\model;
use think\Model;
/**
* @mixin think\Model
*/
class Admin extends Model
{
//
public function getAvatarAttr($value)
{
if(empty($value)){
return '/static/images/avatar.jpeg';
}
return \get_source_link($value);
}
public function getGroupAttr()
{
if(empty($this->getData('group_id'))){
return [];
}
return AdminGroup::where('id',$this->getData('group_id'))->cache(60)->find();
}
}

32
app/model/AdminGroup.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
/**
* @mixin think\Model
*/
class AdminGroup extends Model
{
//
use SoftDelete;
protected $defaultSoftDelete = 0;
public function getPermissionsAttr($value)
{
return \explode(',',$value);
}
public function setPermissionsAttr($value)
{
if(is_array($value)){
return join(',',$value);
}
return $value;
}
}

23
app/model/AdminLog.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
/**
* @mixin think\Model
*/
class AdminLog extends Model
{
//
use SoftDelete;
protected $defaultSoftDelete = 0;
public function admin()
{
return $this->belongsTo('Admin','admin_id');
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace app\model;
use think\Model;
/**
* 权限表
* @mixin think\Model
*/
class AdminPermission extends Model
{
//
public function getIsLogAttr($value)
{
$status = [
0=>'不记录',
1=>'记录',
];
return $status[intval($value)];
}
}

131
app/model/Category.php Normal file
View File

@@ -0,0 +1,131 @@
<?php
declare(strict_types=1);
namespace app\model;
use think\facade\Config;
use think\Model;
/**
* @mixin think\Model
*/
class Category extends Model
{
//
public static $allCategory = [];
/**
* 获取指定id下的所有分类
*
* @param string $id
* @return void
*/
public static function getListLevel($id = '',$type = 1)
{
if(empty(self::$allCategory)){
$model_list = Category::where('type',$type)->select();
self::$allCategory = array2level($model_list,0,0);
}
if(!empty($id)){
$list = [];
$in_category = [$id];
foreach (self::$allCategory as $category) {
if(in_array($category->pid,$in_category)){
$list[] = $category;
$in_category[] = $category->id;
}
}
return $list;
}
return self::$allCategory;
}
public function getTitleImgAttr($value)
{
return get_source_link($value);
}
public function posts()
{
return $this->hasMany(PostCategory::class,'category_id');
}
/**
* 返回的对应的post的模型
*
* @return void
*/
public function getPostsModelListAttr()
{
$list_post_category = $this->getAttr('posts');
$list_post = [];
foreach ($list_post_category as $list_post_category) {
array_push($list_post,$list_post_category->post);
}
return $list_post;
}
/**
* 返回的对应post的数据,性能比模型要高.
*
* @return void
*/
public function getPostsListAttr()
{
$list_post_category = $this->getAttr('posts');
$list_post = array_column($list_post_category->append(['post'])->toArray(),'post');
return $list_post;
}
public function getTplNameAttr($value)
{
return Config::get('view_type.category.'.$value);
}
public function getModelParentAttr()
{
$pid = $this->getData('pid');
if($pid == 0){
return $this;
}
return Category::where('id',$pid)->find();
}
// 返回除自身以外的其他的同级同类的分类
public function getModelSiblingsAttr()
{
return Category::where('pid',$this->getData('pid'))
->where('level',$this->getData('level'))
->where('id','<>',$this->getData('id'))
->select();
}
/**
* 获取同一个父元素的分类,包含自身
*
* @return void
*/
public function getModelSameParentAttr()
{
return Category::where('pid',$this->getData('pid'))
->where('level',$this->getData('level'))
->select();
}
}

29
app/model/Nav.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace app\model;
use think\Model;
/**
* @mixin think\Model
*/
class Nav extends Model
{
public static $statusName = [
0=>'不显示',
1=>'显示'
];
//
public function getImgAttr($value)
{
return get_source_link($value);
}
public function getStatusNameAttr()
{
return self::$statusName[$this->getData('status')];
}
}

133
app/model/Post.php Normal file
View File

@@ -0,0 +1,133 @@
<?php
declare(strict_types=1);
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
/**
* @mixin think\Model
*/
class Post extends Model
{
//
public static $stausNameList = [
0=>'不发布',
1=>'发布'
];
use SoftDelete;
protected $defaultSoftDelete = 0;
public function categorys()
{
return $this->hasMany(PostCategory::class,'post_id');
}
public function tags()
{
return $this->hasMany(PostTag::class,'post_id');
}
public function setPublishTimeAttr($value)
{
return strtotime($value);
}
public function getPublishTimeTextAttr()
{
$value = $this->getData('publish_time');
return date('Y-m-d',$value);
}
public function getCategorysListAttr()
{
$list_post_categorys = $this->getAttr('categorys');
$list = array_column($list_post_categorys->append(['category'])->toArray(),'category');
$list = array2level($list,0,0);
return $list;
}
public function getTagsListAttr()
{
$list_post_tags = $this->getAttr('tags');
$list = array_column($list_post_tags->append(['tag'])->toArray(),'tag');
return $list;
}
public function getDescShortAttr()
{
$desc = $this->getData('desc');
if(strlen($desc) > 100){
$desc = mb_substr($desc,0,100).'...';
}
return $desc;
}
public function getDescListAttr()
{
$desc = $this->getData('desc');
if(empty($desc)){
return '';
}
$list = explode("\n", $desc);
return $list;
}
public function getDescHtmlAttr()
{
$desc = $this->getData('desc');
if(empty($desc)){
return '';
}
return str_replace("\n",'<br>',$desc);
}
public function getStatusNameAttr()
{
return self::$stausNameList[$this->getData('status')];
}
public function setPubishTimeAttr($value)
{
return strtotime($value);
}
public function setContentAttr($value)
{
return json_encode($value);
}
public function setContentHtmlAttr($value)
{
return trim($value);
}
public function getContentAttr($value)
{
return json_decode($value,true);
}
public function getPosterAttr($value)
{
if(empty($value)){
$value = '/static/images/avatar.jpeg';
}
return get_source_link($value);
}
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace app\model;
use think\Model;
/**
* @mixin think\Model
*/
class PostCategory extends Model
{
//
public function post()
{
return $this->belongsTo(Post::class, 'post_id');
}
public function category()
{
return $this->belongsTo(Category::class,'category_id');
}
}

24
app/model/PostTag.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace app\model;
use think\Model;
/**
* @mixin think\Model
*/
class PostTag extends Model
{
//
public function tag()
{
return $this->belongsTo(Tag::class,'tag_id');
}
public function post()
{
return $this->belongsTo(Post::class, 'post_id');
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace app\model;
use think\Model;
/**
* @mixin think\Model
*/
class SystemConfig extends Model
{
//
}

16
app/model/Tag.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace app\model;
use think\Model;
/**
* @mixin think\Model
*/
class Tag extends Model
{
//
}

77
app/model/UploadFiles.php Normal file
View File

@@ -0,0 +1,77 @@
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
/**
* @mixin think\Model
*/
class UploadFiles extends Model
{
//
use SoftDelete;
protected $defaultSoftDelete = 0;
public function getSrcAttr()
{
return \get_source_link($this->getData('save_name'));
}
public function getTypeAttr($value)
{
return \config('upload_type.'.$value);
}
public function getUsedTimeAttr($value)
{
if($value == 0){
return '未使用';
}
return date('Y-m-d H:i:s',$value);
}
public function getDeleteTimeAttr($value)
{
if($value == 0){
return '未删除';
}
return date('Y-m-d H:i:s',$value);
}
public function getClearTimeAttr($value)
{
if($value == 0){
return '未清除';
}
return date('Y-m-d H:i:s',$value);
}
public function getStatusAttr($value,$data)
{
if($data['used_time'] == 0){
return '未使用(仅供预览)';
}
if($data['delete_time'] > 0){
return '已删除';
}
if($data['clear_time'] > 0){
return '已清除';
}
return '使用中';
}
public function getFileSizeAttr($value)
{
return format_size($value);
}
}

27
app/model/User.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
/**
* @mixin think\Model
*/
class User extends Model
{
//
use SoftDelete;
protected $defaultSoftDelete = 0;
public function getAvatarAttr($value)
{
if(empty($value)){
return '/static/images/avatar.jpeg';
}
return \get_source_link($value);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace app\model;
use think\Model;
/**
* @mixin think\Model
*/
class WxPublicAccount extends Model
{
//
public function getHeadImgAttr($value)
{
return get_source_link($value);
}
public function getQrcodeUrlAttr($value)
{
return \get_source_link($value);
}
}

19
app/provider.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use app\ExceptionHandle;
use app\Request;
// 容器Provider定义文件
return [
'think\Request' => Request::class,
'think\exception\Handle' => ExceptionHandle::class,
];

26
build.example.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
/**
* php think build 自动生成应用的目录结构的定义示例
*/
return [
// 需要自动创建的文件
'__file__' => [],
// 需要自动创建的目录
'__dir__' => ['controller', 'model', 'view'],
// 需要自动创建的控制器
'controller' => ['Index'],
// 需要自动创建的模型
'model' => ['User'],
// 需要自动创建的模板
'view' => ['index/index'],
];

50
composer.json Normal file
View File

@@ -0,0 +1,50 @@
{
"name": "ulthon/ulthon_admin",
"description": "quick start a project with management background using thinkphp6",
"type": "project",
"keywords": [
"framework",
"thinkphp",
"ORM",
"ulthon",
"admin"
],
"homepage": "http://ulthon-admin.ulthon.com/",
"license": "Apache-2.0",
"authors": [
{
"name": "ulthon",
"email": "ulthon@163.com"
}
],
"require": {
"php": ">=7.1.0",
"topthink/framework": "6.0.*",
"topthink/think-orm": "2.0.*",
"topthink/think-view": "^1.0",
"topthink/think-migration": "^3.0",
"topthink/think-helper": "^3.1",
"topthink/think-captcha": "^3.0",
"topthink/think-multi-app": "^1.0"
},
"require-dev": {
"symfony/var-dumper": "^4.2"
},
"autoload": {
"psr-4": {
"app\\": "app"
},
"psr-0": {
"": "extend/"
}
},
"config": {
"preferred-install": "dist"
},
"scripts": {
"post-autoload-dump": [
"@php think service:discover",
"@php think vendor:publish"
]
}
}

36
config/app.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
use think\facade\Env;
return [
// 应用地址
'app_host' => Env::get('app.host', ''),
// 应用的命名空间
'app_namespace' => '',
// 是否启用路由
'with_route' => true,
// 是否启用事件
'with_event' => true,
// 默认应用
'default_app' => 'index',
// 默认时区
'default_timezone' => 'Asia/Shanghai',
// 应用映射(自动多应用模式有效)
'app_map' => [],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [],
// 禁止URL访问的应用列表自动多应用模式有效
'deny_app_list' => [],
// 异常页面的模板文件
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
];

30
config/cache.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
use think\facade\Env;
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
return [
// 默认缓存驱动
'default' => Env::get('cache.driver', 'file'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => [],
],
// 更多的缓存连接
],
];

39
config/captcha.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
// +----------------------------------------------------------------------
// | Captcha配置文件
// +----------------------------------------------------------------------
return [
//验证码位数
'length' => 5,
// 验证码字符集合
'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
// 验证码过期时间
'expire' => 1800,
// 是否使用中文验证码
'useZh' => false,
// 是否使用算术验证码
'math' => false,
// 是否使用背景图
'useImgBg' => false,
//验证码字符大小
'fontSize' => 25,
// 是否使用混淆曲线
'useCurve' => true,
//是否添加杂点
'useNoise' => true,
// 验证码字体 不设置则随机
'fontttf' => '',
//背景颜色
'bg' => [243, 251, 254],
// 验证码图片高度
'imageH' => 0,
// 验证码图片宽度
'imageW' => 0,
// 添加额外的验证码设置
// verify => [
// 'length'=>4,
// ...
//],
];

10
config/console.php Normal file
View File

@@ -0,0 +1,10 @@
<?php
// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
// 指令定义
'commands' => [
'app\command\ResetPassword'
],
];

18
config/cookie.php Normal file
View File

@@ -0,0 +1,18 @@
<?php
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
return [
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => false,
// 是否使用 setcookie
'setcookie' => true,
];

101
config/database.php Normal file
View File

@@ -0,0 +1,101 @@
<?php
use think\facade\Env;
use think\facade\App;
return [
// 默认使用的数据库连接配置
'default' => Env::get('database.driver', 'sqlite'),
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段
// true为自动识别类型 false关闭
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
'auto_timestamp' => true,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 数据库连接配置信息
'connections' => [
'mysql' => [
// 数据库类型
'type' => Env::get('database.type', 'mysql'),
// 服务器地址
'hostname' => Env::get('database.hostname', ''),
// 数据库名
'database' => Env::get('database.database', ''),
// 用户名
'username' => Env::get('database.username', ''),
// 密码
'password' => Env::get('database.password', ''),
// 端口
'hostport' => Env::get('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => Env::get('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => Env::get('database.prefix', 'ul_'),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => true,
// 开启字段缓存
'fields_cache' => false,
// 字段缓存路径
'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR,
],
'sqlite' => [
// 数据库类型
'type' => 'sqlite',
// 服务器地址
'hostname' => Env::get('root_path').'ul.db',
// 数据库名
'database' => App::getRootPath().'ul.db',
// 用户名
'username' => Env::get('database.username', ''),
// 密码
'password' => Env::get('database.password', ''),
// 端口
'hostport' => Env::get('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => Env::get('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => Env::get('database.prefix', 'ul_'),
// 数据库调试模式
'debug' => Env::get('database.debug', true),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要进行SQL性能分析
'sql_explain' => false,
// 是否需要断线重连
'break_reconnect' => false,
],
// 更多的数据库配置信息
],
];

26
config/filesystem.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
use think\facade\Env;
return [
// 默认磁盘
'default' => Env::get('filesystem.driver', 'local'),
// 磁盘列表
'disks' => [
'local' => [
'type' => 'local',
'root' => app()->getRuntimePath() . 'storage',
],
'public' => [
// 磁盘类型
'type' => 'local',
// 磁盘路径
'root' => app()->getRootPath() . 'public/',
// 磁盘路径对应的外部URL路径
'url' => '/',
// 可见性
'visibility' => 'public',
],
// 更多的磁盘配置信息
],
];

27
config/lang.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
// +----------------------------------------------------------------------
// | 多语言设置
// +----------------------------------------------------------------------
use think\facade\Env;
return [
// 默认语言
'default_lang' => Env::get('lang.default_lang', 'zh-cn'),
// 允许的语言列表
'allow_lang_list' => [],
// 多语言自动侦测变量名
'detect_var' => 'lang',
// 是否使用Cookie记录
'use_cookie' => true,
// 多语言cookie变量
'cookie_var' => 'think_lang',
// 扩展语言包
'extend_list' => [],
// Accept-Language转义为对应语言包名称
'accept_language' => [
'zh-hans-cn' => 'zh-cn',
],
// 是否支持语言分组
'allow_group' => false,
];

46
config/log.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
use think\facade\Env;
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
return [
// 默认日志记录通道
'default' => Env::get('log.channel', 'file'),
// 日志记录级别
'level' => [],
// 日志类型记录的通道 ['error'=>'email',...]
'type_channel' => [],
// 关闭全局日志写入
'close' => false,
// 全局日志处理 支持闭包
'processor' => null,
// 日志通道列表
'channels' => [
'file' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => '',
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
// 使用JSON格式记录
'json' => false,
// 日志处理
'processor' => null,
// 关闭通道日志写入
'close' => false,
// 日志输出格式化
'format' => '[%s][%s] %s',
// 是否实时写入
'realtime_write' => false,
],
// 其它日志通道配置
],
];

8
config/middleware.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
// 中间件配置
return [
// 别名或分组
'alias' => [],
// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
'priority' => [],
];

51
config/route.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
// +----------------------------------------------------------------------
// | 路由设置
// +----------------------------------------------------------------------
return [
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => true,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => false,
// 是否开启路由缓存
'route_check_cache' => false,
// 路由缓存连接参数
'route_cache_option' => [],
// 路由缓存Key
'route_check_cache_key' => '',
// 访问控制器层名称
'controller_layer' => 'controller',
// 空控制器名
'empty_controller' => 'Error',
// 是否使用控制器后缀
'controller_suffix' => false,
// 默认的路由变量规则
'default_route_pattern' => '[\w\.]+',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 操作方法后缀
'action_suffix' => '',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
];

19
config/session.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
return [
// session name
'name' => 'PHPSESSID',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// 驱动方式 支持file cache
'type' => 'file',
// 存储连接标识 当type使用cache的时候有效
'store' => null,
// 过期时间
'expire' => 1440,
// 前缀
'prefix' => '',
];

10
config/trace.php Normal file
View File

@@ -0,0 +1,10 @@
<?php
// +----------------------------------------------------------------------
// | Trace设置 开启调试模式后有效
// +----------------------------------------------------------------------
return [
// 内置Html和Console两种方式 支持扩展
'type' => 'Html',
// 读取的日志通道名
'channel' => '',
];

8
config/upload_type.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
return [
1 => '系统LOGO',
2 => '管理员头像',
3 => '用户头像',
4=>'富文本图片',
];

25
config/view.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
return [
// 模板引擎类型使用Think
'type' => 'Think',
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
'auto_rule' => 1,
// 模板目录名
'view_dir_name' => 'view',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DIRECTORY_SEPARATOR,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
];

16
config/view_type.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
return [
'category' => [
'' => '普通:',
'_product' => '产品:_product',
'_case' => '案例:_case',
'_about_1' => '关于_图块:_about_1',
'_about_2' => '关于_招聘:_about_2',
'_about_3' => '关于_时间轴:_about_3',
],
'post' => [
'' => '普通:',
]
];

View File

@@ -0,0 +1,57 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableUploadFiles extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('upload_files',['comment'=>'上传的文件','signed'=>false]);
$table->addColumn('save_name','string',['limit'=>100,'comment'=>'文件存储地址']);
$table->addColumn('file_name','string',['limit'=>100,'comment'=>'文件原始名称']);
$table->addColumn('mime_type','string',['limit'=>30,'comment'=>'mime type 类型']);
$table->addColumn('file_size','integer',['limit'=>30,'comment'=>'文件大小']);
$table->addColumn('ext_name','string',['limit'=>10,'comment'=>'扩展名']);
$table->addColumn('file_md5','string',['limit'=>32,'comment'=>'文件md5值']);
$table->addColumn('file_sha1','string',['limit'=>40,'comment'=>'文件sha1值']);
$table->addColumn('create_time','integer',['limit'=>10,'default'=>0,'comment'=>'上传时间']);
$table->addColumn('used_time','integer',['limit'=>10,'default'=>0,'comment'=>'标记使用时间,如果为空,可能仅作为了预览图']);
$table->addColumn('delete_time','integer',['limit'=>10,'default'=>0,'comment'=>'删除时间']);
$table->addColumn('clear_time','integer',['limit'=>10,'default'=>0,'comment'=>'清空时间']);
$table->addColumn('type','integer',['limit'=>2,'default'=>1,'comment'=>'文件类型1系统logo;2:管理员头像']);
$table->addColumn('status','integer',['limit'=>2,'default'=>0,'comment'=>'文件状态:0,上传未使用,1:已使用,2:已删除,3已清除']);
$table->addIndex('save_name');
$table->addIndex('create_time');
$table->addIndex('used_time');
$table->addIndex('delete_time');
$table->addIndex('clear_time');
$table->addIndex('type');
$table->addIndex('status');
$table->create();
}
}

View File

@@ -0,0 +1,37 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableSystemConfig extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('system_config',['comment'=>'系统配置表','signed'=>false]);
$table->addColumn('name','string',['limit'=>30,'comment'=>'配置名称']);
$table->addColumn('value','text',['comment'=>'值']);
$table->addIndex('name');
$table->create();
}
}

View File

@@ -0,0 +1,44 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableAdmin extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('admin',['comment'=>'管理员表','signed'=>false]);
$table->addColumn('account','string',['limit'=>20,'comment'=>'用户帐号']);
$table->addColumn('password','string',['limit'=>32,'comment'=>'密码']);
$table->addColumn('salt','string',['limit'=>6,'comment'=>'密码盐']);
$table->addColumn('nickname','string',['limit'=>10,'default'=>"admin",'comment'=>'昵称']);
$table->addColumn('avatar','string',['limit'=>40,'comment'=>'头像地址']);
$table->addColumn('create_time','integer',['limit'=>10,'default'=>0,'comment'=>'添加时间']);
$table->addColumn('delete_time','integer',['limit'=>10,'default'=>0,'comment'=>'删除时间']);
$table->addColumn('group_id','integer',['limit'=>10,'default'=>0,'comment'=>'管理员组']);
$table->addIndex('account');
$table->addIndex('delete_time');
$table->create();
}
}

View File

@@ -0,0 +1,43 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableAdminGroup extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('admin_group',[
'comment'=>'管理员组',
'signed'=>false
]);
$table->addColumn('name','string',['limit'=>20,'comment'=>'组名']);
$table->addColumn('create_time','integer',['limit'=>11,'default'=>0,'comment'=>'添加时间']);
$table->addColumn('update_time','integer',['limit'=>11,'default'=>0,'comment'=>'更新时间']);
$table->addColumn('delete_time','integer',['limit'=>11,'default'=>0,'comment'=>'删除时间']);
$table->addColumn('permissions','text',['comment'=>'拥有权限']);
$table->create();
}
}

View File

@@ -0,0 +1,53 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableAdminLog extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('admin_log',[
'comment'=>'管理员日志',
'signed'=>false
]);
$table->addColumn('app','string',['limit'=>50,'comment'=>'应用名']);
$table->addColumn('controller','string',['limit'=>50,'comment'=>'控制器名']);
$table->addColumn('action','string',['limit'=>50,'comment'=>'方法名']);
$table->addColumn('param','text',['comment'=>'参数']);
$table->addColumn('create_time','integer',['limit'=>11,'default'=>0,'comment'=>'添加时间']);
$table->addColumn('delete_time','integer',['limit'=>11,'default'=>0,'comment'=>'删除时间']);
$table->addColumn('admin_id','integer',['limit'=>20,'default'=>0,'comment'=>'管理员id']);
$table->addColumn('ip','string',['limit'=>30,'default'=>'','comment'=>'客户端ip']);
$table->addIndex('app');
$table->addIndex('controller');
$table->addIndex('action');
$table->addIndex('delete_time');
$table->addIndex('admin_id');
$table->create();
}
}

View File

@@ -0,0 +1,43 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableAdminPermission extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('admin_permission',[
'comment'=>'后台权限记录',
'signed'=>false
]);
$table->addColumn('name','string',['limit'=>20,'default'=>'0','comment'=>'权限名称']);
$table->addColumn('key','string',['limit'=>100,'comment'=>'权限标识']);
$table->addColumn('is_log','integer',['limit'=>1,'default'=>0,'comment'=>'是否把这个访问记录下来']);
$table->addIndex('key');
$table->addIndex('is_log');
$table->create();
}
}

View File

@@ -0,0 +1,46 @@
<?php
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableUser extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('user',['comment'=>'用户表','signed'=>false]);
$table->addColumn('account','string',['limit'=>20,'comment'=>'用户帐号']);
$table->addColumn('password','string',['limit'=>32,'comment'=>'密码']);
$table->addColumn('salt','string',['limit'=>6,'comment'=>'密码盐']);
$table->addColumn('nickname','string',['limit'=>10,'comment'=>'昵称']);
$table->addColumn('avatar','string',['limit'=>40,'comment'=>'头像地址']);
$table->addColumn('create_time','integer',['limit'=>10,'default'=>0,'comment'=>'添加时间']);
$table->addColumn('update_time','integer',['limit'=>10,'default'=>0,'comment'=>'更新时间']);
$table->addColumn('delete_time','integer',['limit'=>10,'default'=>0,'comment'=>'删除时间']);
$table->addColumn('last_login_time','integer',['limit'=>10,'default'=>0,'comment'=>'最后一次登陆时间']);
$table->addColumn('status','integer',['limit'=>1,'default'=>0,'comment'=>'状态']);
$table->addIndex('account');
$table->addIndex('delete_time');
$table->create();
}
}

View File

@@ -0,0 +1,54 @@
<?php
use app\admin\controller\Common;
use app\common\ColumnFormat;
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableNav extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('nav',['comment'=>'多功能导航,可兼容多种类型','sign'=>false]);
$table->addColumn('title','string',['limit'=>100,'comment'=>'名称标题']);
$table->addColumn(Column::make('sort','integer')->setSigned(false)->setComment('排序,越小越靠前'));
$table->addColumn(Column::make('create_time','integer')->setSigned(false)->setLimit(10)->setComment('添加时间'));
$table->addColumn(ColumnFormat::timestamp('update_time'));
$table->addColumn(ColumnFormat::timestamp('delete_time'));
$table->addColumn(ColumnFormat::stringShort('type')->setComment('类型,用于区分业务场景:1:PC导航,2:PC轮播图,3:PC友情链接'));
$table->addColumn(Column::make('img','string')->setLimit(100)->setComment('图片'));
$table->addColumn(ColumnFormat::stringLong('desc')->setComment('副标题描述'));
$table->addColumn(Column::make('target','string')->setLimit(10)->setSigned(false)->setComment('网页链接打开对象,_BLANK,_SELF,iframe_name'));
$table->addColumn(Column::make('xcx_type','integer')->setLimit(10)->setComment('小程序打开方式,1:小程序导航页面,2:普通页面,3:web-view,4:其他小程序,5:电话'));
$table->addColumn(Column::make('value','string')->setLimit(100)->setComment('对象值,有可能是网页链接,小程序导航页面路径,小程序普通页面路径,电话'));
$table->addColumn(Column::make('xcx_appid','string')->setLimit(30)->setComment('小程序appid,目标是其他小程序是有效'));
$table->addColumn(ColumnFormat::integerTypeStatus('status')->setComment('0:下架,1:显示'));
$table->addIndex('delete_time');
$table->addIndex('type');
$table->addIndex('sort');
$table->addIndex('status');
$table->create();
}
}

View File

@@ -0,0 +1,61 @@
<?php
use app\common\ColumnFormat;
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTablePost extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('post',['comment'=>"内容文章"]);
$table->addColumn(ColumnFormat::stringNormal('title')->setComment('标题'));
$table->addColumn(ColumnFormat::stringUrl('poster')->setComment('封面'));
$table->addColumn(ColumnFormat::timestamp('create_time'));
$table->addColumn(ColumnFormat::timestamp('update_time'));
$table->addColumn(ColumnFormat::timestamp('delete_time'));
$table->addColumn(Column::make('content','text'));
$table->addColumn(Column::make('content_html','text'));
$table->addColumn(ColumnFormat::stringLong('desc')->setDefault('描述'));
$table->addColumn(ColumnFormat::integerTypeStatus('is_top')->setComment('是否置顶'));
$table->addColumn(ColumnFormat::integerTypeStatus('status')->setComment('1:显示,0:不显示'));
$table->addColumn(ColumnFormat::timestamp('publish_time')->setComment('发表时间'));
$table->addColumn(ColumnFormat::integer('hits')->setComment('访问量'));
$table->addColumn(ColumnFormat::stringUrl('jump_to_url')->setComment('跳转链接'));
$table->addColumn(ColumnFormat::integerTypeStatus('jump_to_url_status')->setComment('0:不显示,1:显示连接,2:自动跳转'));
$table->addColumn(ColumnFormat::integer('sort')->setComment('排序,越大越靠前'));
$table->addColumn(ColumnFormat::stringShort('type')->setComment('类型,1:文章,有分类有标签,2:页面,无分类无标签,N:其他形式用,用于区分不同的用途'));
$table->addColumn(Column::make('files','text')->setComment('附件'));
$table->addColumn(Column::make('pictures','text')->setComment('相册'));
$table->addColumn(ColumnFormat::stringShort('tpl_name')->setComment('模板名称'));
$table->addIndex('type');
$table->addIndex('status');
$table->addIndex('delete_time');
$table->addIndex('hits');
$table->addIndex('is_top');
$table->create();
}
}

View File

@@ -0,0 +1,43 @@
<?php
use app\common\ColumnFormat;
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTablePostCategory extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('post_category',['comment'=>'文章分类关联表']);
$table->addColumn(ColumnFormat::integer('post_id'))
->addColumn(ColumnFormat::integer('category_id'))
->addColumn(ColumnFormat::timestamp('create_time'))
->addColumn(ColumnFormat::timestamp('update_time'))
->addColumn(ColumnFormat::timestamp('delete_time'))
->addIndex('post_id')
->addIndex('category_id')
->create();
}
}

View File

@@ -0,0 +1,42 @@
<?php
use app\common\ColumnFormat;
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTablePostTag extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('post_tag',['comment'=>'文章分类关联表']);
$table->addColumn(ColumnFormat::integer('post_id'))
->addColumn(ColumnFormat::integer('tag_id'))
->addColumn(ColumnFormat::timestamp('create_time'))
->addColumn(ColumnFormat::timestamp('update_time'))
->addColumn(ColumnFormat::timestamp('delete_time'))
->addIndex('post_id')
->addIndex('tag_id')
->create();
}
}

View File

@@ -0,0 +1,51 @@
<?php
use app\common\ColumnFormat;
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableCategory extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('category')
->setComment('分类表')
->addColumn(ColumnFormat::stringNormal('title'))
->addColumn(ColumnFormat::timestamp('create_time'))
->addColumn(ColumnFormat::timestamp('update_time'))
->addColumn(ColumnFormat::timestamp('delete_time'))
->addColumn(ColumnFormat::integer('pid')->setComment('上级id'))
->addColumn(ColumnFormat::integer('level')->setDefault(1)->setComment('层级'))
->addColumn(ColumnFormat::stringShort('tpl_name')->setComment('模板名称'))
->addColumn(ColumnFormat::stringUrl('title_img')->setComment('附图'))
->addColumn(ColumnFormat::stringLong('desc')->setComment('副标题描述'))
->addColumn(ColumnFormat::integerTypeStatus('status')->setComment('0:不显示,1:显示'))
->addColumn(ColumnFormat::stringShort('type')->setComment('类型,1:文章,有分类有标签,2:页面,无分类无标签,N:其他形式用,用于区分不同的用途'))
->addIndex('type')
->addIndex('pid')
->addIndex('status')
->addIndex('delete_time')
->create();
}
}

View File

@@ -0,0 +1,42 @@
<?php
use app\common\ColumnFormat;
use think\migration\Migrator;
use think\migration\db\Column;
class CreateTableTag extends Migrator
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* http://docs.phinx.org/en/latest/migrations.html#the-abstractmigration-class
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* renameColumn
* addIndex
* addForeignKey
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('tag')
->setComment('分类表')
->addColumn(ColumnFormat::stringNormal('title'))
->addColumn(ColumnFormat::timestamp('create_time'))
->addColumn(ColumnFormat::timestamp('update_time'))
->addColumn(ColumnFormat::timestamp('delete_time'))
->addColumn(ColumnFormat::stringShort('type')->setComment('类型,1:文章,有分类有标签,2:页面,无分类无标签,N:其他形式用,用于区分不同的用途'))
->addIndex('type')
->create();
}
}

View File

@@ -0,0 +1,32 @@
<?php
use think\migration\Seeder;
use app\model\Admin;
use think\helper\Str;
class InitAdmin extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
$account['account'] = 'admin';
$account['salt'] = Str::random(6);
$account['password'] = md5('123456'.$account['salt']);
$account['avatar'] = '/static/images/avatar.jpeg';
$model_admin = Admin::where('account',$account['account'])->find();
if(empty($model_admin)){
$model_admin = new Admin;
$model_admin->data($account);
$model_admin->save();
}
}
}

View File

@@ -0,0 +1,36 @@
<?php
use think\migration\Seeder;
use app\model\AdminPermission;
class InitAdminPermission extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
$permission_content = '{}';
$permissions = json_decode($permission_content,true);
foreach ($permissions as $permission) {
$current_access_info = [
'app'=>$permission['app'],
'controller'=>$permission['controller'],
'action'=>$permission['action'],
];
$model_permission = AdminPermission::where($current_access_info)->find();
if(empty($model_permission)){
$current_access_info['name'] = $permission['name'];
AdminPermission::create($current_access_info);
}
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
use think\migration\Seeder;
use app\model\SystemConfig;
use think\facade\Cache;
class InitSystemConfig extends Seeder
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* http://docs.phinx.org/en/latest/seeding.html
*/
public function run()
{
$data = [
'site_name'=>'奥宏后台管理模板'
];
$list = get_system_config();
foreach ($data as $key => $value) {
if(isset($list[$key])){
SystemConfig::where('name',$key)->update(['value'=>$value]);
}else{
$model_sysconfig = new SystemConfig();
$model_sysconfig->name = $key;
$model_sysconfig->value = $value;
$model_sysconfig->save();
}
$list[$key] = $value;
}
Cache::set('system_config',$list);
}
}

2
extend/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

8
public/.htaccess Normal file
View File

@@ -0,0 +1,8 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

24
public/index.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// [ 应用入口文件 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应
$http = (new App())->http;
$response = $http->run();
$response->send();
$http->end($response);

2
public/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow:

17
public/router.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$
if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
return false;
} else {
require __DIR__ . "/index.php";
}

1
public/static/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
!.gitignore

View File

@@ -0,0 +1,111 @@
.left-bottom-options{
position: fixed;
left: 20px;
bottom: 60px;
background: rgba(0,0,0,0.4);
color: #fff;
font-size: 35px;
padding: 3px 5px;
}
.main-container {
margin-top: 10px;
}
.layui-table img {
max-width: 60px;
max-height: 60px;
}
.table-card-box{
margin-top: 15px;
background-color: #eee;
padding: 15px 5px;
}
.table-card-item{
margin-top: 5px;
display: flex;
justify-content: flex-start;
align-items: flex-start;
}
.table-card-item img{
max-width: 60px;
max-height: 60px;
}
.table-card-item .item-title{
padding: 5px;
font-size: 16px;
width: 20%;
}
.table-card-item .item-value{
padding: 5px;
margin: 5px;
background-color: #fff;
min-width: 80%;
white-space: normal;
word-break: break-all;
}
.layui-form-radio{
white-space: nowrap;
}
.quick-input-item{
width: 120px;
margin: 3px 0;
}
.quick-input-item.sm-quick-input-item .layui-btn{
line-height: 24px;
height: 24px;
font-size: 12px;
padding: 0 12px;
}
.quick-input-item.sm-quick-input-item .layui-input{
line-height: 24px;
height: 24px;
}
.ul-flex{
display: flex;
}
@media screen and (max-width: 768px){
.layui-body{
left: 0;
}
.layui-layout-admin .layui-footer{
left: 0;
}
.layui-layout-admin .layui-logo{
width: 115px;
}
.layui-layout-admin .layui-side{
width: 100%;
overflow-x: hidden;
height: 100%;
position: unset;
}
.layui-layer-content .layui-hide-xs{
display: unset !important;
}
.layui-nav-tree{
width: 100%;
height: 100%;
}
}

View File

@@ -0,0 +1,153 @@
.main-container{
margin-top: 15px;
}
.nav-left-container{
margin-top: 15px;
}
.nav-left-list{
text-align: center;
}
.nav-left-list a{
display: block;
padding: 10px 15px;
border-radius: 5px;
margin: 5px 20px;
}
.nav-left-list a:hover,.nav-left-list a.current{
background-color: #6699CC;
color: #fff;
}
.logo{
text-align: center;
}
.logo img{
max-width: 60%;
}
.session{
margin-top: 15px;
background-color: #99CCFF;
padding: 15px;
}
.session.border{
border-top: 2px solid #6699CC;
}
.session .header{
font-size: 18px;
font-weight: 600;
color: #036;
}
.search-container{
display: flex;
}
.layui-btn{
background-color: #6699CC;
}
.nav-more-list a{
display: inline-block;
white-space: nowrap;
color: #036;
margin-right: 15px;
margin-top: 15px;
}
.session .info p{
margin: 5px 0;
}
#banner img{
width: 100%;
}
.tab-list{
border-bottom: 1px solid #ddd;
margin-top: 15px;
font-size: 16px;
}
.tab-list a{
margin-right: 15px;
border-bottom: 2px solid transparent;
padding-bottom: 10px;
display: inline-block;
}
.tab-list a.current{
border-color: #6699CC;
}
.post-item,.plus-post-item{
display: flex;
justify-content: flex-start;
align-items: center;
margin-top: 15px;
padding-bottom: 15px;
border-bottom: 1px solid #ddd;
}
.post-item .poster,.plus-post-item .poster{
width: 160px;
height: 100px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
margin-right: 15px;
}
.plus-post-item .poster{
width: 60px;
height: 60px;
}
.plus-post-item .title{
font-size: 14px;
}
.post-item .info .title{
font-size: 22px;
font-weight: 600;
}
.post-item .info .plus-info{
margin-top: 5px;
}
.nodata{
margin: 60px auto;
display: block;
width: 40%;
}
.content-container .title{
font-size: 22px;
font-weight: 600;
}
@media screen and (max-width: 768px){
.nav-left-list{
text-align: left;
}
.nav-left-list a{
display: inline-block;
margin: 5px;
}
}

View File

@@ -0,0 +1,910 @@
/**
@Name: layuiSimpleBlog - 极简博客模板
@Author: xuzhiwen
@Copyright: layui.com
*/
/*end-menu-btn*/
body {
font: 14px Helvetica Neue, Helvetica, PingFang SC, Tahoma, Arial, sans-serif;
overflow-x: hidden;
}
.w1000 {
max-width: 1000px !important;
margin: 0 auto;
}
.header {
height: 120px;
line-height: 120px;
position: relative;
font-size: 16px;
}
.header .logo,
.header .welcome-text,
.header .nav {
position: absolute;
top: 0;
}
.header .logo {
left: 65px;
}
.header .logo span {
display: none;
}
.header .logo img {
max-width: 120px;
max-height: 100%;
}
.header .nav {
left: 250px;
}
.header .nav a {
color: #3f2863;
margin: 0 40px;
}
.header .nav a.active {
color: #ff7f21;
}
.header .welcome-text {
right: 50px;
}
.header .header-down-nav {
display: none;
}
.banner {
height: 600px;
width: 100%;
background: url(../img/banner.jpg) no-repeat;
background-size: cover;
}
.banner .cont {
position: relative;
}
.banner .title {
color: #fff;
position: absolute;
top: 152px;
left: 0;
}
.banner .title h3 {
font-size: 80px;
line-height: 88px;
}
.banner .title h4 {
font-size: 46px;
}
.banner .amount {
font-size: 18px;
line-height: 50px;
color: #ff7f21;
position: absolute;
right: 20px;
top: 290px;
}
.banner .text {
position: relative;
width: 80px;
display: inline-block;
}
.banner .text::before {
position: absolute;
right: -5px;
content: '\FF1A';
}
.content {
padding: 100px 0 160px 0;
}
.content .cont .title {
margin-bottom: 60px;
}
.content .cont .title a {
font-size: 16px;
color: #000 !important;
}
.content .cont .title .layui-breadcrumb span {
position: relative;
top: -1px;
margin: 0 16px;
}
.content .cont .title a.active,
.content .cont .title a:hover {
color: #ff7f21 !important;
}
.content .cont .list-item .layui-fluid {
padding: 0;
}
.content .cont .list-item .item {
margin-bottom: 80px;
overflow: hidden;
}
.content .cont .list-item .item .img img {
width: 100%;
}
.content .cont .list-item .item .item-cont {
padding-left: 100px;
}
.content .cont .list-item .item .item-cont .go-icon {
width: 33px;
height: 11px;
background: url(../img/jiantou.png) center center no-repeat;
display: block;
padding: 10px 0;
margin-top: 16px;
}
.content .cont .list-item .item .item-cont h3 {
font-size: 24px;
margin: 20px 0;
}
.content .cont .list-item .item .item-cont h3 .new-icon {
width: 36px;
height: 18px;
line-height: 18px;
text-align: center;
padding: 0;
margin: -3px 0 0 10px;
}
.content .cont .list-item .item .item-cont h5 {
font-size: 12px;
color: #ff7f21;
margin-bottom: 32px;
}
.content .cont .list-item .item .item-cont p {
line-height: 37px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
/* autoprefixer: off */
-webkit-box-orient: vertical;
/* autoprefixer: on */
}
.content .review-version {
padding: 20px;
border-top: 1px dashed #dddddd;
}
.content .review-version img {
float: left;
}
.content .review-version .form {
margin-bottom: 16px;
}
.content .review-version .form .layui-form-item {
clear: none;
}
.content .review-version .form .layui-input-block {
margin-left: 70px;
}
.content .review-version .form .layui-input-block .layui-btn {
width: 100px;
height: 40px;
line-height: 40px;
background: #ff7f21;
}
.content .review-version .list-cont .cont {
padding: 40px 0 30px 0;
border-bottom: 1px solid #e5e5e5;
}
.content .review-version .list-cont .cont:last-child {
border-bottom: 0;
}
.content .review-version .list-cont .cont .text {
padding-left: 70px;
line-height: 22px;
color: #333;
}
.content .review-version .list-cont .cont .text .tit {
margin-bottom: 18px;
}
.content .review-version .list-cont .cont .text .data {
float: right;
}
.footer-wrap {
border-top: 1px solid #402863;
}
.footer {
padding: 60px 0 80px 0;
position: relative;
overflow: hidden;
}
.footer .qrcode {
float: left;
}
.footer .practice-mode {
position: absolute;
right: 0;
overflow: hidden;
}
.footer .practice-mode img {
float: left;
padding-right: 28px;
}
.footer .practice-mode .text {
color: #3f2863;
float: left;
}
.footer .practice-mode .text h4 {
font-size: 20px;
line-height: 60px;
}
.footer .practice-mode .text p {
line-height: 32px;
}
.footer .practice-mode .text p span {
padding-left: 24px;
}
/*whisper*/
.whisper-content {
padding: 40px 0 100px 0;
}
.whisper-content .item-box {
background: #f9f9f9;
margin-bottom: 20px;
}
.whisper-content .cont {
max-width: 800px;
margin: 0 auto;
}
.whisper-content .cont .item-box .item {
padding: 50px 46px 20px 54px;
}
.whisper-content .cont .whisper-list .whisper-title {
height: 20px;
line-height: 20px;
margin-bottom: 20px;
}
.whisper-content .cont .whisper-list .whisper-title i {
position: relative;
top: 1px;
margin-right: 5px;
}
.whisper-content .cont .whisper-list .whisper-title span {
color: #ff7f21;
}
.whisper-content .cont .whisper-list .whisper-title span.hour {
margin-right: 20px;
}
.whisper-content .whisper-list .text-cont {
line-height: 24px;
margin-bottom: 28px;
}
.whisper-content .whisper-list .op-list {
margin-top: 30px;
overflow: hidden;
}
.whisper-content .whisper-list .op-list .like {
-webkit-user-select: none;
-moz-user-focus: none;
-moz-user-select: none;
}
.whisper-content .whisper-list .op-list .like.active {
color: #ff7f21;
}
.whisper-content .whisper-list .op-list p {
float: left;
cursor: pointer;
color: #999999;
}
.whisper-content .whisper-list .op-list p.off {
float: right;
-webkit-user-select: none;
-moz-user-focus: none;
-moz-user-select: none;
}
.whisper-content .whisper-list .op-list p.off span {
margin-right: 5px;
}
.whisper-content .whisper-list .op-list p.like {
margin-right: 50px;
}
.whisper-content .whisper-list .img-box {
overflow: hidden;
}
.whisper-content .whisper-list .img-box img {
float: left;
margin: 0px 18px 18px 0;
}
.whisper-content .whisper-list .img-box img:last-child {
margin-right: 0;
}
/*end-whisper*/
/*leacots*/
.leacots-content .review-version {
padding: 0;
border-top: 0;
}
.leacots-content .review-version .form .layui-form-item {
clear: both;
}
.leacots-content .item-box {
background: transparent;
}
.leacots-content .review-version .form {
margin: 70px 0;
}
.leacots-content .review-version .form textarea {
border-color: #402760;
}
.leacots-content .review-version .form .layui-input-block {
margin-left: 0;
}
.leacots-content .review-version .banner-img {
float: none;
width: 100%;
}
.leacots-content .review-version .volume {
color: #3f2469;
}
.leacots-content .review-version .volume span {
padding-left: 30px;
color: #f37d25;
}
.leacots-content .review-version .list-cont .cont {
max-width: 100%;
}
/*end-leacots*/
/*details*/
.details-content .article-cont img {
float: none;
width: 100%;
}
.details-content .article-cont .title {
text-align: center;
margin-bottom: 0;
}
.details-content .article-cont .title h3 {
font-size: 24px;
margin-bottom: 36px;
}
.details-content .article-cont .title p {
padding: 0;
}
.details-content .article-cont .title p.cont-info {
text-indent: 0;
}
.details-content .article-cont .title p .data {
margin-right: 26px;
}
.details-content .article-cont .title p .types {
color: #ff7f21;
}
.details-content .article-cont p {
line-height: 24px;
padding: 30px 0 30px 5px;
color: #333;
text-indent: 40px;
}
.details-content .article-cont .btn-box {
text-align: center;
margin-top: 50px;
}
/*end-details*/
/*album*/
.album-content .img-info {
margin-top: 66px;
overflow: hidden;
font-size: 16px;
margin-bottom: 126px;
}
.album-content .img-info img {
float: left;
padding-right: 60px;
}
.album-content .img-info .title {
line-height: 30px;
margin-top: 124px;
padding-left: 20px;
}
.album-content .img-info .title .data {
color: #ff7f21;
}
.album-content .img-info .title .data span {
padding-left: 35px;
}
.album-content .img-list {
overflow: hidden;
padding-bottom: 50px;
}
.album-content .img-list .item {
float: left;
width: 100%;
}
.album-content .img-list .layui-laypage {
margin: 50px 0;
}
.album-content .img-list .space>* {
padding: 55px;
}
.album-content .img-list .layui-col-space80 {
padding: 40px;
}
.album-content .img-list .item img {
width: 100%;
}
.album-content .img-list .cont-text {
padding-left: 10px;
}
.album-content .img-list .cont-text .data {
line-height: 55px;
color: #ff7f21;
}
.album-content .img-list .cont-text .briefly {
line-height: 24px;
margin-top: 16px;
}
/*end-album*/
/*about*/
.about-content {
background: #faf8fb;
}
.about-content .item {
padding-bottom: 100px;
}
.about-content .item h3 {
font-size: 24px;
color: #3f2863;
line-height: 100px;
}
.about-content .item.info .cont {
overflow: hidden;
}
.about-content .item.info img {
float: left;
height: 220px;
margin-right: 86px;
}
.about-content .item.info p {
line-height: 50px;
margin-top: 15px;
}
.about-content .item.info p {
font-size: 16px;
}
.about-content .item.tool .cont-box {
text-align: center;
}
.about-content .item.tool .cont-box img {}
.about-content .item.tool .cont-box p {
line-height: 56px;
}
.about-content .item.contact .cont {
overflow: hidden;
}
.about-content .item.contact .cont img {
width: 110px;
height: 110px;
float: left;
margin: 0 100px;
}
.about-content .item.contact .cont .text {
line-height: 36px;
}
/*end-about*/
@media screen and (max-width: 1200px) {
.header .logo {
left: 20px;
}
.header .nav {
left: 150px;
}
.header .nav a {
margin: 0 20px;
}
.content .cont .title {
padding-left: 10px;
}
.content .cont .list-item .item .img {
padding: 0 10px;
}
.content .cont .list-item .item .item-cont {
padding: 0 20px;
}
.content .cont .list-item .item .item-cont h3 {
margin: 15px 0;
font-size: 22px;
}
.content .cont .list-item .item .item-cont h5 {
margin-bottom: 10px;
}
.content .cont .list-item .item .item-cont p {
line-height: 30px;
}
.content .cont .list-item .item .item-cont .go-icon {
margin-top: 5px;
}
.content .cont .list-item .item {
margin-bottom: 50px;
}
.content {
padding: 60px 0 60px 0;
}
.whisper-content {
padding: 0 0 60px 0;
}
.details-content .article-cont .title {
padding: 0;
}
.details-content .article-cont .title h3 {
font-size: 22px;
}
}
@media screen and (max-width: 1000px) {
.leacots-content {
padding: 0 20px 40px 20px;
}
.album-content .img-info img {
width: 100%;
padding-right: 0;
margin-bottom: 20px;
}
.album-content .img-info {
margin-top: 0px;
margin-bottom: 50px;
}
.album-content .img-list .space>* {
padding: 30px;
}
}
@media screen and (max-width: 768px) {
.header .nav,
.header .welcome-text {
display: none;
}
.banner .amount {
line-height: 40px;
}
.banner .title {
top: 245px;
}
.banner .title h3 {
font-size: 40px;
line-height: 44px;
}
.banner .title h4 {
font-size: 24px;
}
.footer {
padding-left: 0;
}
.footer .qrcode {
float: none;
margin-bottom: 40px;
margin-left: 10px;
}
.footer .practice-mode {
position: relative;
margin-left: 10px;
}
.banner .title {
top: 290px;
left: 20px;
}
.banner .amount {
left: 20px;
top: 210px;
line-height: 30px;
}
.whisper-content .cont .item {
padding: 30px;
}
.whisper-content .cont .item-box .item {
padding: 30px;
}
.content .review-version .list-cont .cont .text {
padding-left: 0;
line-height: 22px;
color: #333;
}
.content .review-version .list-cont .cont .text .tit {
line-height: 50px;
margin-bottom: 0;
}
.content .review-version .list-cont .cont .text .tit .name {
margin-left: 20px;
}
.content .review-version .list-cont .cont .text .ct {
margin-top: 20px;
}
.leacots-content .review-version .form {
margin: 40px 0;
}
.album-content .img-list .space>* {
padding: 10px;
}
.album-content .img-list .layui-laypage {
margin: 50px 0 0 0;
}
.album-content .img-list #demo {
text-align: center;
}
.about-content .item.info img {
margin-right: 0;
float: none;
height: auto;
width: 100%;
}
.about-content .item.info p {
padding-left: 20px;
}
.about-content .item {
padding-bottom: 40px;
}
.about-content .item h3 {
padding-left: 20px;
}
.about-content .item.contact .cont img {
margin: 0 30px 0 20px;
}
/*menu-btn*/
.menu {
width: 50px;
height: 40px;
position: relative;
cursor: pointer;
}
.menu:before,
.menu:after {
content: "";
display: block;
width: 50px;
height: 6px;
background: #ff7f21;
border-radius: 8px;
position: absolute;
left: 0;
-webkit-transition: all 0.15s ease-in-out;
transition: all 0.15s ease-in-out;
}
.menu:before {
top: 0px;
box-shadow: 0 34px #ff7f21;
}
.menu:after {
bottom: 17px;
}
.menu.on:before {
top: 17px;
box-shadow: none;
-webkit-transform: rotate(225deg);
transform: rotate(225deg);
}
.menu.on:after {
bottom: 17px;
-webkit-transform: rotate(135deg);
transform: rotate(135deg);
}
.menu-btn {
position: absolute;
top: 40px;
right: 20px;
}
.header .header-down-nav {
width: 100%;
position: absolute;
top: 120px;
z-index: 2;
left: 0;
padding: 0;
border-radius: 0;
}
.header .header-down-nav {
background: #ff7f21;
}
.header .header-down-nav .layui-nav-item a {
padding: 0 40px;
}
.header .header-down-nav li {
display: block;
}
.header .header-down-nav li a {
font-size: 16px;
}
}
@media screen and (max-width: 320px) {
.whisper-content .cont .item img {
width: 100%;
}
}

View File

@@ -0,0 +1,75 @@
html,
body {
background-color: #f5f5f5;
}
.program-item {
margin: 10px 5px;
padding-bottom: 5px;
}
.program-item .desc {
display: -webkit-box;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
height: 96px;
}
.program-item .options {
text-align: right; color: #999;font-size: 14px;margin-top: 10px;
}
.program-item .layui-icon{
font-size: 14px;
}
.site-logo{
display: flex;
align-items: center;
color: #fff;
}
.site-logo:hover{
color: #fff;
}
.site-logo img{
max-height: 60px;
}
.read-header{
background-color: #6699CC;
color: #fff;
}
.read-header .layui-breadcrumb a:hover{
color: #99CCFF !important;
}
.read-header .layui-breadcrumb a{
color: #fff !important;
}
.main-body{
}
.list-container li{
list-style: unset;
margin-left: 15px;
}
.post-title{
margin: 15px 0;
font-size: 22px;
}
.post-container{
margin: 15px;
}

Some files were not shown because too many files have changed in this diff Show More