中秋节快乐
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
APP_DEBUG = false
|
||||
SYSTEM_SALT= YAdmin
|
||||
|
||||
[APP]
|
||||
DEFAULT_TIMEZONE = Asia/Chongqing
|
||||
|
||||
[DATABASE]
|
||||
TYPE = mysql
|
||||
HOSTNAME = 127.0.0.1
|
||||
DATABASE = www_dj_com
|
||||
USERNAME = 123456
|
||||
PASSWORD = 123456
|
||||
HOSTPORT = 3306
|
||||
CHARSET = utf8mb4
|
||||
DEBUG = false
|
||||
PREFIX = qf_
|
||||
|
||||
[LANG]
|
||||
default_lang = zh-cn
|
||||
@@ -0,0 +1,2 @@
|
||||
/.svn
|
||||
/.vscode
|
||||
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<head><title>404 Not Found</title></head>
|
||||
<body>
|
||||
<center><h1>404 Not Found</h1></center>
|
||||
<hr><center>nginx</center>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +1,28 @@
|
||||
## 心悦搜剧
|
||||
## 心悦搜索
|
||||
|
||||
免费分享百万级网盘资源,致力打造顶尖网盘搜索引擎,让您畅享资源无忧!
|
||||
|
||||
## 更新日志
|
||||
|
||||
### v2
|
||||
|
||||
- UI改版:不再使用uniapp
|
||||
- 优化Seo:增加后台配置seo参数、伪静态网址、网站地图等
|
||||
- 自定义首页背景图、背景色等样式
|
||||
- 优化搜索模式:支持精准搜索、模糊搜索、分词搜索
|
||||
- 增加转存过滤删除广告的功能
|
||||
- 增加批量导入转存功能
|
||||
- 支持多网盘导入功能(目前仅夸克支持转存分享)
|
||||
- 增加资源分类功能
|
||||
|
||||
注:鉴于数据库改动大,最快升级方式:1、重新搭建新项目;2、旧项目后台导出资源表格;3、新项目导入这个表格
|
||||
|
||||
## 演示
|
||||
|
||||
[前端体验](https://pan.xinyuedh.com)
|
||||
|
||||
<https://pan.xinyuedh.com>
|
||||
|
||||
[前端项目地址](https://ext.dcloud.net.cn/plugin?id=17278)
|
||||
|
||||
<https://ext.dcloud.net.cn/plugin?id=17278>
|
||||
|
||||
注:鉴于太多人不会uniapp,程序安装后默认已打包好uniapp,可正常使用;如需修改前端页面可自行查看以上地址。
|
||||
|
||||
## 后台安装教程
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app;
|
||||
|
||||
use think\Service;
|
||||
|
||||
/**
|
||||
* 应用服务类
|
||||
*/
|
||||
class AppService extends Service
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
// 服务注册
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
// 服务启动
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
namespace app;
|
||||
|
||||
// 应用请求对象类
|
||||
class Request extends \think\Request
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,697 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\admin;
|
||||
|
||||
use think\App;
|
||||
use think\facade\View;
|
||||
|
||||
use app\model\Admin as AdminModel;
|
||||
use app\model\Access as AccessModel;
|
||||
use app\model\Auth as AuthModel;
|
||||
use app\model\Node as NodeModel;
|
||||
use app\model\Group as GroupModel;
|
||||
use app\model\Conf as ConfModel;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
abstract class QfShop
|
||||
{
|
||||
protected $model = null;
|
||||
//搜索字段
|
||||
protected $selectList = '*';
|
||||
protected $selectDetail = '*';
|
||||
//筛选字段
|
||||
protected $searchFilter = [];
|
||||
//更新字段
|
||||
protected $updateFields = [];
|
||||
//更新时的必须字段
|
||||
protected $updateRequire = [];
|
||||
//添加字段
|
||||
protected $insertFields = [];
|
||||
//添加时的必须字段
|
||||
protected $insertRequire = [];
|
||||
//excel查询字段 用来查询
|
||||
protected $excelField = [
|
||||
"join_id" => "编号",
|
||||
];
|
||||
//excel 表头
|
||||
protected $excelTitle = "数据导出表";
|
||||
//EXCEL 单元格字母
|
||||
protected $excelCells = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD'];
|
||||
|
||||
//主键key
|
||||
protected $pk = '';
|
||||
//表名称
|
||||
protected $table = '';
|
||||
//主键value
|
||||
protected $pk_value = 0;
|
||||
|
||||
|
||||
//模型
|
||||
protected $adminModel;
|
||||
protected $accessModel;
|
||||
protected $authModel;
|
||||
protected $nodeModel;
|
||||
protected $groupModel;
|
||||
protected $confModel;
|
||||
|
||||
/**
|
||||
* Request实例
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
protected $plat = 'all';
|
||||
protected $version = 0;
|
||||
|
||||
|
||||
protected $module;
|
||||
protected $controller;
|
||||
protected $action;
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
//TODO !!!如有特殊需求请重写下面的方法到子类,请勿修改此处!!! BEGIN.........//
|
||||
/**
|
||||
* 添加接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//校验Insert字段是否填写
|
||||
$error = $this->validateInsertFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Insert数据
|
||||
$data = $this->getInsertDataFromRequest();
|
||||
//添加这行数据
|
||||
$this->insertRow($data);
|
||||
return jok('添加成功');
|
||||
}
|
||||
/**
|
||||
* 修改接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//校验Update字段是否填写
|
||||
$error = $this->validateUpdateFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Update数据
|
||||
$data = $this->getUpdateDataFromRequest();
|
||||
//根据主键更新这条数据
|
||||
$this->updateByPk($data);
|
||||
return jok('修改成功');
|
||||
}
|
||||
/**
|
||||
* 禁用接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//单个操作
|
||||
$this->disableBySingle();
|
||||
} else {
|
||||
//批量操作
|
||||
$this->disableByMultiple();
|
||||
}
|
||||
return jok("禁用成功");
|
||||
}
|
||||
/**
|
||||
* 启用接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//单个操作
|
||||
$this->enableBySingle();
|
||||
} else {
|
||||
//批量操作
|
||||
$this->enableByMultiple();
|
||||
}
|
||||
return jok("启用成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//单个操作
|
||||
$this->deleteBySingle();
|
||||
} else {
|
||||
//批量操作
|
||||
$this->deleteByMultiple();
|
||||
}
|
||||
return jok('删除成功');
|
||||
}
|
||||
/**
|
||||
* 获取列表接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取筛选数据的数组
|
||||
$map = $this->getDataFilterFromRequest();
|
||||
//从请求中获取排序方式
|
||||
$order = $this->getorderfromRequest();
|
||||
//设置Model中的 per_page
|
||||
$this->setGetListPerPage();
|
||||
//查询数据
|
||||
$dataList = $this->model->getListByPage($map, $order, $this->selectList);
|
||||
return jok('数据获取成功', $dataList);
|
||||
}
|
||||
/**
|
||||
* 获取详情基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("没有查询到数据", 404);
|
||||
}
|
||||
return jok('数据加载成功', $item);
|
||||
}
|
||||
/**
|
||||
* 导出Excel基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function excel()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$this->exportExcelData();
|
||||
}
|
||||
// !!!如有特殊需求请重写下面的方法到子类,请勿修改此处!!! END.........//
|
||||
|
||||
// 初始化
|
||||
protected function initialize()
|
||||
{
|
||||
$this->module = "api";
|
||||
$this->controller = $this->request->controller() ? $this->request->controller() : "Index";
|
||||
$this->action = strtolower($this->request->action()) ? strtolower($this->request->action()) : "index";
|
||||
View::assign('controller', strtolower($this->controller));
|
||||
View::assign('action', strtolower($this->action));
|
||||
|
||||
$this->table = strtolower($this->controller);
|
||||
$this->pk = $this->table . "_id";
|
||||
$this->pk_value = input($this->pk);
|
||||
|
||||
$this->adminModel = new AdminModel();
|
||||
$this->accessModel = new AccessModel();
|
||||
$this->authModel = new AuthModel();
|
||||
$this->nodeModel = new NodeModel();
|
||||
$this->groupModel = new GroupModel();
|
||||
$this->confModel = new ConfModel();
|
||||
|
||||
$configs = $this->confModel->select()->toArray();
|
||||
$c = [];
|
||||
foreach ($configs as $config) {
|
||||
$c[$config['conf_key']] = $config['conf_value'];
|
||||
}
|
||||
config($c, 'qfshop');
|
||||
}
|
||||
/**
|
||||
* 检测授权
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function access()
|
||||
{
|
||||
if (!input("plat")) {
|
||||
return jerr("plat参数为必须", 400);
|
||||
}
|
||||
$this->plat = input('plat');
|
||||
if (!input("version")) {
|
||||
return jerr("version参数为必须", 400);
|
||||
}
|
||||
$this->version = input('version');
|
||||
|
||||
if (!input("access_token")) {
|
||||
return jerr("AccessToken为必要参数", 400);
|
||||
}
|
||||
$access_token = input("access_token");
|
||||
$this->admin = $this->adminModel->getAdminByAccessToken($access_token);
|
||||
if (!$this->admin) {
|
||||
return jerr("登录过期,请重新登录", 401);
|
||||
}
|
||||
if ($this->admin['admin_status'] == 1) {
|
||||
return jerr("你的账户被禁用,登录失败", 401);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 从请求中获取Request数据
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function getInsertDataFromRequest()
|
||||
{
|
||||
$data = [];
|
||||
foreach (input('post.') as $k => $v) {
|
||||
if (in_array($k, $this->insertFields)) {
|
||||
$data[$k] = $v;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* 校验Insert的字段
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function validateInsertFields()
|
||||
{
|
||||
foreach ($this->insertRequire as $k => $v) {
|
||||
if (!input($k)) {
|
||||
return jerr($v, 400);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 从请求中获取Update数据
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function getUpdateDataFromRequest()
|
||||
{
|
||||
$data = [];
|
||||
foreach (input('post.') as $k => $v) {
|
||||
if (in_array($k, $this->updateFields)) {
|
||||
$data[$k] = $v;
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* 校验Update的字段
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function validateUpdateFields()
|
||||
{
|
||||
foreach ($this->updateRequire as $k => $v) {
|
||||
if (!input($k)) {
|
||||
return jerr($v, 400);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* 按主键集合批量禁用 1,2,3,4
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function disableByMultiple()
|
||||
{
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->update([
|
||||
$this->table . "_status" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* 单个禁用 可传入自定义$map
|
||||
* 默认按主键ID禁用
|
||||
*
|
||||
* @param array $map
|
||||
* @return void
|
||||
*/
|
||||
protected function disableBySingle($map = null)
|
||||
{
|
||||
if ($map == null) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
}
|
||||
$this->model->where($map)->update([
|
||||
$this->table . "_status" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* 按主键集合批量启用 1,2,3,4
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function enableByMultiple()
|
||||
{
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->update([
|
||||
$this->table . "_status" => 0,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* 单个启用 可传入自定义$map
|
||||
* 默认按主键ID启用
|
||||
*
|
||||
* @param array $map
|
||||
* @return void
|
||||
*/
|
||||
protected function enableBySingle($map = null)
|
||||
{
|
||||
if ($map == null) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
}
|
||||
$this->model->where($map)->update([
|
||||
$this->table . "_status" => 0,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* 按主键集合批量删除1,2,3,4
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function deleteByMultiple()
|
||||
{
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->delete();
|
||||
}
|
||||
/**
|
||||
* 单个删除 默认主键ID
|
||||
*
|
||||
* @param array $map
|
||||
* @return void
|
||||
*/
|
||||
protected function deleteBySingle($map = null)
|
||||
{
|
||||
if ($map == null) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
}
|
||||
$this->model->where($map)->delete();
|
||||
}
|
||||
/**
|
||||
* 根据主键ID获取一行数据
|
||||
*
|
||||
* @param int|null 主键ID
|
||||
* @return array|null
|
||||
*/
|
||||
protected function getRowByPk($pk_value = null)
|
||||
{
|
||||
if (!$pk_value) {
|
||||
$pk_value = $this->pk_value;
|
||||
}
|
||||
$item = $this->model->where($this->pk, $pk_value)->field($this->selectDetail)->find();
|
||||
return $item ? $item->toArray() : null;
|
||||
}
|
||||
/**
|
||||
* 根据主键ID更新数据
|
||||
*
|
||||
* @param array 需要更新的KV数组
|
||||
* @param int|null 主键ID 默认$this->pk_value
|
||||
* @param bool 是否更新_updatetime字段 默认TRUE
|
||||
* @return void
|
||||
*/
|
||||
protected function updateByPk($data, $pk_value = null, $auto_updatetime = true)
|
||||
{
|
||||
if (!$pk_value) {
|
||||
$pk_value = $this->pk_value;
|
||||
}
|
||||
if ($auto_updatetime) {
|
||||
$data[$this->table . "_updatetime"] = time();
|
||||
}
|
||||
$this->model->where($this->pk, $this->pk_value)->update($data);
|
||||
}
|
||||
/**
|
||||
* 添加一行数据
|
||||
*
|
||||
* @param array 需要添加的KV数组
|
||||
* @param bool 是否自动记录_createtime和_updatetime字段 默认true
|
||||
* @return int 添加返回的主键ID
|
||||
*/
|
||||
protected function insertRow($data, $auto_inserttime = true)
|
||||
{
|
||||
if ($auto_inserttime) {
|
||||
$data[$this->table . "_updatetime"] = time();
|
||||
$data[$this->table . "_createtime"] = time();
|
||||
} else {
|
||||
$data[$this->table . "_updatetime"] = 0;
|
||||
$data[$this->table . "_createtime"] = 0;
|
||||
}
|
||||
$id = $this->model->insertGetId($data);
|
||||
return $id;
|
||||
}
|
||||
/**
|
||||
* 从请求中获取查询排序(默认主键DESC)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function getOrderFromRequest()
|
||||
{
|
||||
if (input('order')) {
|
||||
$order = urldecode(input('order'));
|
||||
} else {
|
||||
$order = strtolower($this->controller) . "_id desc";
|
||||
}
|
||||
return $order;
|
||||
}
|
||||
/**
|
||||
* 设置分页查询每页数量
|
||||
*
|
||||
* @param int|null 每页数量
|
||||
* @return void
|
||||
*/
|
||||
protected function setGetListPerPage($per_page = null)
|
||||
{
|
||||
if ($per_page) {
|
||||
$this->model->per_page = intval($per_page);
|
||||
} else if (input('per_page')) {
|
||||
$this->model->per_page = input('per_page');
|
||||
} else {
|
||||
$this->model->per_page = 10;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取查询列表的Where参数
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getDataFilterFromRequest()
|
||||
{
|
||||
$map = [];
|
||||
$filter = input('post.');
|
||||
foreach ($filter as $k => $v) {
|
||||
if ($k == 'filter') {
|
||||
$k = input('filter');
|
||||
$v = input('keyword');
|
||||
}
|
||||
if ($v === '' || $v === null) {
|
||||
continue;
|
||||
}
|
||||
if (array_key_exists($k, $this->searchFilter)) {
|
||||
switch ($this->searchFilter[$k]) {
|
||||
case "like":
|
||||
array_push($map, [$k, 'like', "%" . $v . "%"]);
|
||||
break;
|
||||
case "=":
|
||||
array_push($map, [$k, '=', $v]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
protected function getExcelFields()
|
||||
{
|
||||
$excelField = [];
|
||||
foreach ($this->excelField as $k => $v) {
|
||||
if ($k == "*") {
|
||||
continue;
|
||||
} else {
|
||||
array_push($excelField, [
|
||||
$k, $v
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $excelField;
|
||||
}
|
||||
/**
|
||||
* 导出Excel
|
||||
*
|
||||
* @return string 下载文件名
|
||||
*/
|
||||
protected function exportExcelData($data)
|
||||
{
|
||||
$datalist = $data ? $data->toArray() : [];
|
||||
$excelField = $this->getExcelFields();
|
||||
$PHPExcel = new \PHPExcel(); //实例化
|
||||
$PHPExcel
|
||||
->getProperties() //获得文件属性对象,给下文提供设置资源
|
||||
->setCreator("qfshop") //设置文件的创建者
|
||||
->setLastModifiedBy("qfshop") //设置最后修改者
|
||||
->setDescription("Export by qfshop"); //设置备注
|
||||
|
||||
$PHPSheet = $PHPExcel->getActiveSheet();
|
||||
$PHPSheet->setTitle($this->excelTitle); //给当前活动sheet设置名称
|
||||
|
||||
$PHPSheet->mergeCells('A1:' . $this->excelCells[count($excelField) - 1] . "1");
|
||||
$PHPSheet->setCellValue('A1', $this->excelTitle);
|
||||
$PHPSheet->getRowDimension(1)->setRowHeight(40);
|
||||
$PHPSheet->getStyle('A1')->getFont()->setSize(16)->setBold(true); //字体大小
|
||||
|
||||
$PHPSheet->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER); //水平方向上对齐
|
||||
$PHPSheet->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); //垂直方向上中间居中
|
||||
$PHPSheet->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER); //垂直方向上中间居中
|
||||
|
||||
if (count($excelField) > count($this->excelCells)) {
|
||||
echo 'Error and you need check Excel Cells Keys...';
|
||||
die;
|
||||
}
|
||||
$PHPSheet->getRowDimension(2)->setRowHeight(30);
|
||||
for ($column = 0; $column < count($excelField); $column++) {
|
||||
$PHPSheet->setCellValue($this->excelCells[$column] . "2", $excelField[$column][1]);
|
||||
$PHPSheet->getStyle($this->excelCells[$column])->getNumberFormat()
|
||||
->setFormatCode(\PHPExcel_Style_NumberFormat::FORMAT_TEXT);
|
||||
for ($line = 0; $line < count($datalist); $line++) {
|
||||
$string = $datalist[$line][$excelField[$column][0]];
|
||||
$PHPSheet->getColumnDimension($this->excelCells[$column])->setWidth(20);
|
||||
$PHPSheet->setCellValueExplicit($this->excelCells[$column] . ($line + 3), $string, \PHPExcel_Cell_DataType::TYPE_STRING);
|
||||
}
|
||||
}
|
||||
//***********************画出单元格边框*****************************
|
||||
$styleArray = array(
|
||||
'borders' => array(
|
||||
'inside' => array(
|
||||
'style' => \PHPExcel_Style_Border::BORDER_THIN, //细边框
|
||||
//'color' => array('argb' => 'FFFF0000'),
|
||||
),
|
||||
'outline' => array(
|
||||
'style' => \PHPExcel_Style_Border::BORDER_THICK, //边框是粗的
|
||||
//'color' => array('argb' => 'FFFF0000'),
|
||||
),
|
||||
),
|
||||
);
|
||||
$PHPSheet->getStyle('A2:' . $this->excelCells[count($excelField) - 1] . (count(
|
||||
$datalist
|
||||
) + 2))->applyFromArray($styleArray);
|
||||
//***********************画出单元格边框结束*****************************
|
||||
|
||||
//设置全部居中对齐
|
||||
$PHPSheet->getStyle('A1:' . $this->excelCells[count($excelField) - 1] . (count(
|
||||
$datalist
|
||||
) + 2))->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER)->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER)->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
|
||||
//设置全部字体
|
||||
$PHPSheet->getStyle('A1:' . $this->excelCells[count($excelField) - 1] . (count(
|
||||
$datalist
|
||||
) + 2))->getFont()->setName('微软雅黑');
|
||||
$PHPWriter = \PHPExcel_IOFactory::createWriter($PHPExcel, "Excel2007"); //创建生成的格式
|
||||
header('Content-Disposition: attachment;filename="' . $this->excelTitle . "_" . date('Y-m-d_H:i:s') . '.xlsx"'); //下载下来的表格名
|
||||
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
$PHPWriter->save("php://output"); //表示在$path路径下面生成demo.xlsx文件
|
||||
exit;
|
||||
return $this->excelTitle . "_" . date('Y-m-d_H:i:s') . '.xlsx"';
|
||||
}
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return jerr("访问异常", 404);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,480 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Admin as model;
|
||||
use app\model\Sms as SmsModel;
|
||||
use app\model\Validate as ValidateModel;
|
||||
|
||||
class Admin extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//查询字段
|
||||
$this->selectList = "*";
|
||||
$this->selectDetail = "*";
|
||||
//筛选字段
|
||||
$this->searchFilter = [
|
||||
"admin_id" => "=",
|
||||
"admin_account" => "like",
|
||||
"admin_name" => "like",
|
||||
"admin_truename" => "like",
|
||||
"admin_status" => "=",
|
||||
];
|
||||
$this->insertFields = [
|
||||
"admin_account", "admin_password", "admin_name", "admin_idcard", "admin_email", "admin_group", "admin_truename"
|
||||
];
|
||||
$this->updateFields = [
|
||||
"admin_account", "admin_password", "admin_name", "admin_idcard", "admin_email", "admin_group", "admin_truename"
|
||||
];
|
||||
$this->insertRequire = [
|
||||
'admin_name' => "用户昵称必须填写",
|
||||
'admin_account' => "用户帐号必须填写",
|
||||
'admin_password' => "密码必须填写",
|
||||
'admin_group' => "用户组必须填写",
|
||||
];
|
||||
$this->updateRequire = [
|
||||
'admin_name' => "用户昵称必须填写",
|
||||
'admin_account' => "用户帐号必须填写",
|
||||
'admin_group' => "用户组必须填写",
|
||||
];
|
||||
$this->excelField = [
|
||||
"id" => "编号",
|
||||
"account" => "帐号",
|
||||
"name" => "昵称",
|
||||
"idcard" => "身份证",
|
||||
"email" => "邮箱",
|
||||
"createtime" => "创建时间",
|
||||
"updatetime" => "修改时间"
|
||||
];
|
||||
$this->model = new model();
|
||||
}
|
||||
public function add()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$error = $this->validateInsertFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$data = $this->getInsertDataFromRequest();
|
||||
$data['admin_ipreg'] = "127.0.0.1";
|
||||
$admin = $this->model->getAdminByAccount($data["admin_account"]);
|
||||
if ($admin) {
|
||||
return jerr("帐号已存在,请重新输入");
|
||||
}
|
||||
$salt = getRandString(4);
|
||||
$password = $data["admin_password"];
|
||||
$password = encodePassword($password, $salt);
|
||||
$data["admin_salt"] = $salt;
|
||||
$data["admin_password"] = $password;
|
||||
$this->insertRow($data);
|
||||
return jok('用户添加成功');
|
||||
}
|
||||
public function update()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (!isInteger($this->pk_value)) {
|
||||
return jerr("修改失败,参数错误", 400);
|
||||
}
|
||||
$item = $this->model->where($this->pk, $this->pk_value)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if (intval($this->pk_value) == 1) {
|
||||
return jerr("无法修改超管用户信息");
|
||||
}
|
||||
foreach ($this->updateRequire as $k => $v) {
|
||||
if (!input($k)) {
|
||||
return jerr($v);
|
||||
}
|
||||
}
|
||||
$data = [];
|
||||
foreach (input('post.') as $k => $v) {
|
||||
if (in_array($k, $this->updateFields)) {
|
||||
$data[$k] = $v;
|
||||
}
|
||||
}
|
||||
$admin = $this->model->getAdminByAccount($data["admin_account"]);
|
||||
if ($admin && $admin[$this->pk] != $item[$this->pk]) {
|
||||
return jerr("帐号已存在,请重新输入");
|
||||
}
|
||||
if (input('new_password')) {
|
||||
//设置密码
|
||||
$salt = getRandString(4);
|
||||
$password = input('new_password');
|
||||
$password = encodePassword($password, $salt);
|
||||
$data["admin_salt"] = $salt;
|
||||
$data["admin_password"] = $password;
|
||||
}
|
||||
if ($this->admin['admin_group'] != 1) {
|
||||
//除超级管理员组外 其他任何组不允许修改用户组
|
||||
unset($data['admin_group']);
|
||||
}
|
||||
$data[$this->table . "_updatetime"] = time();
|
||||
$this->model->where($this->pk, $this->pk_value)->update($data);
|
||||
return jok('用户信息更新成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用用户
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
$item = $this->model->where($map)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if ($item["admin_group"] == 1) {
|
||||
return jerr("超级管理员不允许操作!");
|
||||
}
|
||||
$this->model->where($map)->update([
|
||||
$this->table . "_status" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->where("admin_group > 1")->update([
|
||||
$this->table . "_status" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("禁用用户成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用用户
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
$item = $this->model->where($map)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if ($item["admin_group"] == 1) {
|
||||
return jerr("超级管理员不允许操作!");
|
||||
}
|
||||
$this->model->where($map)->update([
|
||||
$this->table . "_status" => 0,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->where("admin_group > 1")->update([
|
||||
$this->table . "_status" => 0,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("启用用户成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
$item = $this->model->where($map)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//
|
||||
if ($item["admin_group"] == 1) {
|
||||
return jerr("超级管理员不允许操作!");
|
||||
}
|
||||
$this->model->where($map)->delete();
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
//批量删除只允许删除用户组不为1的用户
|
||||
$this->model->where($this->pk, 'in', $list)->where("admin_group > 1")->delete();
|
||||
}
|
||||
return jok('删除用户成功');
|
||||
}
|
||||
public function detail()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
$item = $this->model->field($this->selectDetail)->where($this->pk, $this->pk_value)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("没有查询到数据", 404);
|
||||
}
|
||||
return jok('数据加载成功', $item);
|
||||
}
|
||||
public function getList()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$map = [];
|
||||
$filter = input('post.');
|
||||
foreach ($filter as $k => $v) {
|
||||
if ($k == 'filter') {
|
||||
$k = input('filter');
|
||||
$v = input('keyword');
|
||||
}
|
||||
if ($v === '' || $v === null) {
|
||||
continue;
|
||||
}
|
||||
if (array_key_exists($k, $this->searchFilter)) {
|
||||
switch ($this->searchFilter[$k]) {
|
||||
case "like":
|
||||
array_push($map, [$k, 'like', "%" . $v . "%"]);
|
||||
break;
|
||||
case "=":
|
||||
array_push($map, [$k, '=', $v]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
$order = strtolower($this->controller) . "_id desc";
|
||||
if (input('order')) {
|
||||
$order = urldecode(input('order'));
|
||||
}
|
||||
if (input('per_page')) {
|
||||
$this->model->per_page = intval(input('per_page'));
|
||||
}
|
||||
$dataList = $this->model->getListByPage($map, $order, $this->selectList);
|
||||
return jok('用户列表获取成功', $dataList);
|
||||
}
|
||||
public function login()
|
||||
{
|
||||
if (!input("admin_account")) {
|
||||
return jerr('请确认帐号是否正确填写', 400);
|
||||
}
|
||||
if (!input("admin_password")) {
|
||||
return jerr('请确认密码是否正确填写', 400);
|
||||
}
|
||||
if (!input("admin_code")) {
|
||||
return jerr('请确认图形验证码是否填写', 400);
|
||||
}
|
||||
$plat = input("plat");
|
||||
$admin_account = input("admin_account");
|
||||
$admin_password = input("admin_password");
|
||||
|
||||
//验证图形验证码
|
||||
$validateModel = new ValidateModel();
|
||||
$error = $validateModel->validateImgCode(input('token'), input('admin_code'));
|
||||
if ($error) {
|
||||
return jerr('验证码错误', 400);
|
||||
}
|
||||
//登录获取用户信息
|
||||
$admin = $this->model->login($admin_account, $admin_password);
|
||||
if ($admin) {
|
||||
//创建一个新的授权
|
||||
$access = $this->accessModel->createAccess($admin['admin_id'], $plat);
|
||||
if ($access) {
|
||||
setCookie('access_token', $access['access_token'], time() + 3600, '/');
|
||||
return jok('登录成功', ['access_token' => $access['access_token']]);
|
||||
} else {
|
||||
return jerr('登录系统异常');
|
||||
}
|
||||
} else {
|
||||
return jerr('帐号或密码错误');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
$access_token = input("access_token");
|
||||
cookie('access_token', null);
|
||||
$this->accessModel->where('access_token', $access_token)->update(["access_status" => 1]);
|
||||
return jok('已退出登录');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册接口
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reg()
|
||||
{
|
||||
if (!input("phone")) {
|
||||
return jerr("手机号不能为空!", 400);
|
||||
}
|
||||
$phone = input("phone");
|
||||
if (!input("code")) {
|
||||
return jerr("短信验证码不能为空!", 400);
|
||||
}
|
||||
$code = input("code");
|
||||
if (!input("password")) {
|
||||
return jerr("密码不能为空!", 400);
|
||||
}
|
||||
$password = input("password");
|
||||
$name = $phone;
|
||||
if (input("name")) {
|
||||
$name = input("name");
|
||||
}
|
||||
$smsModel = new SmsModel();
|
||||
if ($smsModel->validSmsCode($phone, $code)) {
|
||||
$admin = $this->model->where([
|
||||
"admin_account" => $phone
|
||||
])->find();
|
||||
if ($admin) {
|
||||
return jerr("该手机号已经注册!");
|
||||
}
|
||||
$result = $this->model->reg($phone, $password, $name);
|
||||
if ($result) {
|
||||
return jok("用户注册成功");
|
||||
} else {
|
||||
return jerr("注册失败,请重试!");
|
||||
}
|
||||
} else {
|
||||
return jerr("短信验证码已过期,请重新获取");
|
||||
}
|
||||
}
|
||||
public function motifyPassword()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!input("oldPassword")) {
|
||||
return jerr("你必须要输入你的原密码!", 400);
|
||||
}
|
||||
if (!input("newPassword")) {
|
||||
return jerr("你必须输入一个新的密码!", 400);
|
||||
}
|
||||
$old_password = input("oldPassword");
|
||||
$new_password = input("newPassword");
|
||||
if (strlen($new_password) < 6 || strlen($new_password) > 16) {
|
||||
return jerr("新密码因为6-16位!");
|
||||
}
|
||||
if ($this->admin['admin_password'] != encodePassword($old_password, $this->admin['admin_salt'])) {
|
||||
return jerr("原密码输入不正确,请重试!");
|
||||
}
|
||||
$result = $this->model->motifyPassword($this->admin['admin_id'], $new_password);
|
||||
if ($result) {
|
||||
return jok("密码已重置,请使用新密码登录");
|
||||
} else {
|
||||
return jerr("注册失败,请重试!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetPassword()
|
||||
{
|
||||
if (!input("phone")) {
|
||||
return jerr("手机号不能为空!", 400);
|
||||
}
|
||||
if (!input("code")) {
|
||||
return jerr("短信验证码不能为空!", 400);
|
||||
}
|
||||
if (!input("password")) {
|
||||
return jerr("密码不能为空!", 400);
|
||||
}
|
||||
$phone = input("phone");
|
||||
$code = input("code");
|
||||
$password = input("password");
|
||||
$smsModel = new SmsModel();
|
||||
if ($smsModel->validSmsCode($phone, $code)) {
|
||||
$admin = $this->model->where([
|
||||
"admin_account" => $phone
|
||||
])->find();
|
||||
if (!$admin) {
|
||||
return jerr("该手机号尚未注册!", 404);
|
||||
}
|
||||
$result = $this->model->motifyPassword($admin['admin_id'], $password);
|
||||
if ($result) {
|
||||
return jok("密码已重置,请使用新密码登录");
|
||||
} else {
|
||||
return jerr("注册失败,请重试!");
|
||||
}
|
||||
} else {
|
||||
return jerr("短信验证码已过期,请重新获取");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取我的信息
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getMyInfo()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$myInfo = $this->admin;
|
||||
foreach (['admin_password', 'admin_salt', 'admin_accesstoken', 'admin_tokentime', 'admin_status'] as $key) {
|
||||
unset($myInfo[$key]);
|
||||
}
|
||||
return jok('数据获取成功', $myInfo);
|
||||
}
|
||||
public function updateMyInfo()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!input("admin_name")) {
|
||||
return jerr("你确定飘到连名字都可以不要了吗?", 400);
|
||||
}
|
||||
$data = [
|
||||
"admin_name" => input("admin_name"),
|
||||
"admin_truename" => input("admin_truename"),
|
||||
"admin_email" => input("admin_email"),
|
||||
"admin_idcard" => input("admin_idcard"),
|
||||
];
|
||||
$this->model->where("admin_id", $this->admin['admin_id'])->update($data);
|
||||
return jok("资料更新成功");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\Filesystem;
|
||||
use think\exception\ValidateException;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Attach as AttachModel;
|
||||
|
||||
class Attach extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//筛选字段
|
||||
$this->searchFilter = [
|
||||
"attach_id" => "=", //相同筛选
|
||||
"attach_key" => "like", //相似筛选
|
||||
"attach_value" => "like", //相似筛选
|
||||
"attach_desc" => "like", //相似筛选
|
||||
"attach_readonly" => "=", //相似筛选
|
||||
];
|
||||
$this->model = new AttachModel();
|
||||
}
|
||||
/**
|
||||
* 上传图片
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function uploadImage()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
try {
|
||||
$file = request()->file('file');
|
||||
try {
|
||||
validate(['file' => 'filesize:' . config("qfshop.upload_max_image") . '|fileExt:' . config("qfshop.upload_image_type")])
|
||||
->check(['file' => $file]);
|
||||
$saveName = Filesystem::putFile('image', $file);
|
||||
$attach_data = array(
|
||||
'attach_path' => "/uploads/".$saveName,
|
||||
'attach_name' => $file->getOriginalName(),
|
||||
'attach_type' => $file->extension(),
|
||||
'attach_size' => $file->getSize(),
|
||||
'attach_admin' => $this->admin['admin_id']
|
||||
);
|
||||
$attach_id = $this->insertRow($attach_data);
|
||||
$attach_data = $this->getRowByPk($attach_id);
|
||||
if (input("?extend")) {
|
||||
$attach_data['extend'] = input("extend");
|
||||
}
|
||||
return jok('上传成功!', $attach_data);
|
||||
} catch (ValidateException $e) {
|
||||
return jerr($e->getMessage());
|
||||
}
|
||||
} catch (\Exception $error) {
|
||||
return jerr('上传文件失败,请检查你的文件!');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 删除图片
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//单个操作
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
$res = $this->model->where($map)->delete();
|
||||
if($res){
|
||||
try {
|
||||
unlink("./uploads/".$item['attach_path']);
|
||||
} catch (\Throwable $th) {
|
||||
//throw $th;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//批量操作
|
||||
$list = explode(',', $this->pk_value);
|
||||
foreach ($list as $key => $value) {
|
||||
$item = $this->model->where("attach_id",$value)->find();
|
||||
if($item){
|
||||
try {
|
||||
unlink("./uploads/".$item['attach_path']);
|
||||
} catch (\Throwable $th) {
|
||||
//throw $th;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->model->where($this->pk, 'in', $list)->delete();
|
||||
}
|
||||
return jok('删除成功');
|
||||
}
|
||||
/**
|
||||
* 上传文件
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function uploadFile()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
try {
|
||||
$file = request()->file('file');
|
||||
try {
|
||||
validate(['file' => 'filesize:' . config("qfshop.upload_max_file") . '|fileExt:' . config("qfshop.upload_file_type")])
|
||||
->check(['file' => $file]);
|
||||
$saveName = Filesystem::putFile('normal', $file);
|
||||
$attach_data = array(
|
||||
'attach_path' => $saveName,
|
||||
'attach_type' => $file->extension(),
|
||||
'attach_size' => $file->getSize(),
|
||||
'attach_admin' => $this->admin['admin_id']
|
||||
);
|
||||
$attach_id = $this->insertRow($attach_data);
|
||||
$attach_data = $this->getRowByPk($attach_id);
|
||||
if (input("?extend")) {
|
||||
$attach_data['extend'] = input("extend");
|
||||
}
|
||||
return jok('上传成功!', $attach_data);
|
||||
} catch (ValidateException $e) {
|
||||
return jerr($e);
|
||||
}
|
||||
} catch (\Exception $error) {
|
||||
return jerr('上传文件失败,请检查你的文件!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 富文本上传图片
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function uploads()
|
||||
{
|
||||
header("Content-Type: text/html; charset=utf-8");
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$CONFIG = json_decode(preg_replace("/\/\*[\s\S]+?\*\//", "", file_get_contents("./static/admin/UEditor/config.json")), true);
|
||||
$action = $_GET['action'];
|
||||
|
||||
switch ($action) {
|
||||
case 'config':
|
||||
$result = json_encode($CONFIG);
|
||||
break;
|
||||
|
||||
/* 上传图片 */
|
||||
case 'uploadimage':
|
||||
/* 上传涂鸦 */
|
||||
case 'uploadscrawl':
|
||||
/* 上传视频 */
|
||||
case 'uploadvideo':
|
||||
/* 上传文件 */
|
||||
case 'uploadfile':
|
||||
try {
|
||||
$file = request()->file('upfile');
|
||||
try {
|
||||
validate(['file' => 'filesize:' . config("qfshop.upload_max_image") . '|fileExt:' . config("qfshop.upload_image_type")])
|
||||
->check(['file' => $file]);
|
||||
$saveName = Filesystem::putFile('normal', $file);
|
||||
$result = json_encode(array(
|
||||
'original'=> $file->getOriginalName(),
|
||||
'state'=> "SUCCESS",
|
||||
'title'=> $file->getOriginalName(),
|
||||
'url'=> "/uploads/".$saveName,
|
||||
'type'=> $file->extension(),
|
||||
));
|
||||
} catch (ValidateException $e) {
|
||||
$result = json_encode(array(
|
||||
'state'=> $e->getMessage()
|
||||
));
|
||||
}
|
||||
} catch (\Exception $error) {
|
||||
$result = json_encode(array(
|
||||
'state'=> '上传文件失败,请检查你的文件!'
|
||||
));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$result = json_encode(array(
|
||||
'state'=> '请求地址出错'
|
||||
));
|
||||
break;
|
||||
}
|
||||
|
||||
/* 输出结果 */
|
||||
if (isset($_GET["callback"])) {
|
||||
if (preg_match("/^[\w_]+$/", $_GET["callback"])) {
|
||||
echo htmlspecialchars($_GET["callback"]) . '(' . $result . ')';
|
||||
} else {
|
||||
echo json_encode(array(
|
||||
'state'=> 'callback参数不合法'
|
||||
));
|
||||
}
|
||||
} else {
|
||||
echo $result;
|
||||
}
|
||||
die;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Auth as AuthModel;
|
||||
|
||||
class Auth extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//筛选字段
|
||||
$this->searchFilter = [
|
||||
"auth_id" => "=", //相同筛选
|
||||
];
|
||||
$this->model = new AuthModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除访问日志
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clean()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$this->model->cleanAuth();
|
||||
return jok('授权信息清理成功');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Conf as ConfModel;
|
||||
|
||||
class Conf extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//筛选字段
|
||||
$this->searchFilter = [
|
||||
"conf_id" => "=", //相同筛选
|
||||
"conf_key" => "like", //相似筛选
|
||||
"conf_value" => "like", //相似筛选
|
||||
"conf_title" => "like", //相似筛选
|
||||
"conf_status" => "=", //相同筛选
|
||||
"conf_type" => "=", //相同筛选
|
||||
];
|
||||
$this->insertFields = [
|
||||
"conf_key", "conf_value", "conf_title", "conf_desc", "conf_status", "conf_type", "conf_spec", "conf_content", "conf_sort", "conf_system"
|
||||
];
|
||||
$this->updateFields = [
|
||||
"conf_key", "conf_value", "conf_title", "conf_desc", "conf_status", "conf_type", "conf_spec", "conf_content", "conf_sort", "conf_system"
|
||||
];
|
||||
$this->insertRequire = [
|
||||
'conf_title' => "参数名称必须填写",
|
||||
'conf_key' => "参数字段必须填写",
|
||||
];
|
||||
$this->updateRequire = [
|
||||
'conf_title' => "参数名称必须填写",
|
||||
'conf_key' => "参数字段必须填写",
|
||||
];
|
||||
$this->model = new ConfModel();
|
||||
}
|
||||
/**
|
||||
* 获取列表接口基类
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取筛选数据的数组
|
||||
$map = $this->getDataFilterFromRequest();
|
||||
//从请求中获取排序方式
|
||||
$order = "conf_sort desc, conf_id asc";
|
||||
//设置Model中的 per_page
|
||||
$this->setGetListPerPage();
|
||||
//查询数据
|
||||
$dataList = $this->model->getListByPage($map, $order, $this->selectList);
|
||||
return jok('数据获取成功', $dataList);
|
||||
}
|
||||
/**
|
||||
* 读取基本配置
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getBaseConfig()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$datalist = $this->model->where('conf_status', 1)->order("conf_sort desc ".$this->pk . " asc")->select();
|
||||
foreach ($datalist as $key => $value) {
|
||||
if($value['conf_content']){
|
||||
$value['conf_content'] = explode("\n",$value['conf_content']);
|
||||
}
|
||||
}
|
||||
return jok('', $datalist);
|
||||
}
|
||||
/**
|
||||
* 更新基础配置
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateBaseConfig()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
foreach (input("post.") as $k => $v) {
|
||||
$map["conf_key"] = $k;
|
||||
$item = $this->model->where($map)->find();
|
||||
if (empty($item)) {
|
||||
continue;
|
||||
}
|
||||
if(is_array($v)){
|
||||
$v = implode(",",$v);
|
||||
}
|
||||
$this->model->where("conf_key", $k)->update(["conf_value" => $v]);
|
||||
}
|
||||
return jok("配置修改成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//校验Insert字段是否填写
|
||||
$error = $this->validateInsertFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Insert数据
|
||||
$data = $this->getInsertDataFromRequest();
|
||||
|
||||
$res = $this->model->where('conf_key',$data['conf_key'])->find();
|
||||
if ($res) {
|
||||
return jerr("参数字段已存在");
|
||||
}
|
||||
|
||||
//添加这行数据
|
||||
$data['conf_value'] = '';
|
||||
$this->insertRow($data);
|
||||
return jok('添加成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//校验Update字段是否填写
|
||||
$error = $this->validateUpdateFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Update数据
|
||||
$data = $this->getUpdateDataFromRequest();
|
||||
|
||||
$res = $this->model->where('conf_key',$data['conf_key'])->find();
|
||||
if ($res['conf_id']!= input("conf_id") && $res) {
|
||||
return jerr("参数字段已存在");
|
||||
}
|
||||
//根据主键更新这条数据
|
||||
$this->updateByPk($data);
|
||||
return jok('修改成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除接口基类
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if($item['conf_system']==1){
|
||||
return jerr("系统参数,禁止删除", 404);
|
||||
}
|
||||
//单个操作
|
||||
$this->deleteBySingle();
|
||||
} else {
|
||||
//批量操作
|
||||
return jerr("暂不支持批量删除", 400);
|
||||
}
|
||||
return jok('删除成功');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\QfShop;
|
||||
|
||||
class Error extends QfShop
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return jerr("admin not found", 404);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\Filesystem;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Feedback as FeedbackModel;
|
||||
|
||||
class Feedback extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//查询列表时允许的字段
|
||||
$this->selectList = "*";
|
||||
//查询详情时允许的字段
|
||||
$this->selectDetail = "*";
|
||||
$this->model = new FeedbackModel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取列表接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取筛选数据的数组
|
||||
$map = $this->getDataFilterFromRequest();
|
||||
//从请求中获取排序方式
|
||||
$order = $this->getorderfromRequest();
|
||||
//设置Model中的 per_page
|
||||
$this->setGetListPerPage();
|
||||
//查询数据
|
||||
$dataList = $this->model->getListByPage($map, $order, $this->selectList);
|
||||
return jok('数据获取成功', $dataList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Group as GroupModel;
|
||||
|
||||
class Group extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//筛选字段
|
||||
$this->searchFilter = [
|
||||
"group_id" => "=", //相同筛选
|
||||
"group_name" => "like", //相似筛选
|
||||
];
|
||||
$this->insertFields = [
|
||||
"group_name", "group_desc"
|
||||
];
|
||||
$this->updateFields = [
|
||||
"group_name", "group_desc"
|
||||
];
|
||||
$this->insertRequire = [
|
||||
'group_name' => "组名称必须填写"
|
||||
];
|
||||
$this->updateRequire = [
|
||||
'group_name' => "组名称必须填写"
|
||||
];
|
||||
$this->model = new GroupModel();
|
||||
}
|
||||
/**
|
||||
* 修改用户组
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (!isInteger($this->pk_value)) {
|
||||
return jerr("修改失败,参数错误", 400);
|
||||
}
|
||||
$item = $this->model->where($this->pk, $this->pk_value)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if ($item[$this->pk] == 1) {
|
||||
return jerr("无法操作超级管理员组信息");
|
||||
}
|
||||
foreach ($this->updateRequire as $k => $v) {
|
||||
if (!input($k)) {
|
||||
return jerr($v);
|
||||
}
|
||||
}
|
||||
$data = [];
|
||||
foreach (input('post.') as $k => $v) {
|
||||
if (in_array($k, $this->updateFields)) {
|
||||
$data[$k] = $v;
|
||||
}
|
||||
}
|
||||
if (!input($this->table . "_name")) {
|
||||
return jerr("组名称必须填写", 400);
|
||||
}
|
||||
$data[$this->table . "_updatetime"] = time();
|
||||
$this->model->where($this->pk, $this->pk_value)->update($data);
|
||||
return jok('用户组信息更新成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用用户组
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
$item = $this->model->where($map)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if ($item[$this->pk] == 1) {
|
||||
return jerr("无法操作超级管理员组信息");
|
||||
}
|
||||
$this->model->where($map)->update([
|
||||
$this->table . "_status" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->where("group_id > 1")->update([
|
||||
$this->table . "_status" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("禁用用户组成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用用户组
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
$item = $this->model->where($map)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if ($item[$this->pk] == 1) {
|
||||
return jerr("无法操作超级管理员组信息");
|
||||
}
|
||||
$this->model->where($map)->update([
|
||||
$this->table . "_status" => 0,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->where("group_id > 1")->update([
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("启用用户组成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户组
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
if ($item[$this->pk] == 1) {
|
||||
return jerr("无法删除超级管理员组");
|
||||
}
|
||||
$this->deleteBySingle();
|
||||
//删除对应ID的授权记录
|
||||
$this->authModel->where([
|
||||
"auth_group" => $this->pk_value
|
||||
])->delete();
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->where("group_id > 1")->delete();
|
||||
//删除对应ID的授权记录
|
||||
$this->authModel->where("auth_group", "in", $list)->delete();
|
||||
}
|
||||
return jok('删除用户组成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 为用户组授权节点
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (!isInteger($this->pk_value)) {
|
||||
return jerr("修改失败,参数错误", 400);
|
||||
}
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("用户组信息查询失败,授权失败", 404);
|
||||
}
|
||||
$this->authModel->where([
|
||||
"auth_group" => $this->pk_value
|
||||
])->delete();
|
||||
if ($item[$this->pk] == 1) {
|
||||
return jerr("超级管理组无需授权!");
|
||||
}
|
||||
$node_ids = explode(",", input("node_ids"));
|
||||
foreach ($node_ids as $node_id) {
|
||||
if (intval($node_id) == 0) {
|
||||
continue;
|
||||
}
|
||||
$this->authModel->insert([
|
||||
"auth_group" => $this->pk_value,
|
||||
"auth_node" => $node_id,
|
||||
"auth_createtime" => time(),
|
||||
"auth_updatetime" => time()
|
||||
]);
|
||||
}
|
||||
return jok('用户组授权成功');
|
||||
}
|
||||
/**
|
||||
* 获取用户组拥有的权限
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getAuthorize()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (!isInteger($this->pk_value)) {
|
||||
return jerr("修改失败,参数错误", 400);
|
||||
}
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("用户组信息查询失败,授权失败", 404);
|
||||
}
|
||||
$myAuthorizeList = $this->authModel->where("auth_group", $this->pk_value)->select();
|
||||
return jok('ok', $myAuthorizeList);
|
||||
}
|
||||
/**
|
||||
* 获取所有用户组
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$dataList = $this->model->select();
|
||||
return jok('用户组列表获取成功', $dataList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use app\admin\QfShop;
|
||||
use think\facade\Config;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Db;
|
||||
use util\Time;
|
||||
|
||||
class Index extends QfShop
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\Filesystem;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Log as LogModel;
|
||||
|
||||
class Log extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//查询列表时允许的字段
|
||||
$this->selectList = "*";
|
||||
//查询详情时允许的字段
|
||||
$this->selectDetail = "*";
|
||||
$this->model = new LogModel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取列表接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取筛选数据的数组
|
||||
$map = $this->getDataFilterFromRequest();
|
||||
//从请求中获取排序方式
|
||||
$order = "update_time desc";
|
||||
//设置Model中的 per_page
|
||||
$this->setGetListPerPage();
|
||||
//查询数据
|
||||
$dataList = $this->model->getListByPage($map, $order, $this->selectList);
|
||||
return jok('数据获取成功', $dataList);
|
||||
}
|
||||
|
||||
public function setDomain()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$data = ['domain'=>input('domain')];
|
||||
$this->model->where('id', input('id'))->update($data);
|
||||
return jok('更新成功');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Node as NodeModel;
|
||||
|
||||
class Node extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//筛选字段
|
||||
$this->searchFilter = [
|
||||
"node_id" => "=", //相同筛选
|
||||
"node_show" => "=", //相同筛选
|
||||
"node_title" => "like", //相似筛选
|
||||
"node_desc" => "like", //相似筛选
|
||||
"node_module" => "like", //相似筛选
|
||||
"node_controller" => "like", //相似筛选
|
||||
"node_action" => "like", //相似筛选
|
||||
];
|
||||
$this->insertFields = [
|
||||
"node_title", "node_desc", "node_module", "node_action", "node_controller", "node_icon", "node_show", "node_pid", "node_order", "node_login", "node_access"
|
||||
];
|
||||
$this->updateFields = [
|
||||
"node_title", "node_desc", "node_module", "node_action", "node_controller", "node_icon", "node_show", "node_pid", "node_order", "node_login", "node_access"
|
||||
];
|
||||
$this->insertRequire = [
|
||||
'node_title' => "节点名称必须填写",
|
||||
'node_module' => "节点模块必须填写",
|
||||
];
|
||||
$this->updateRequire = [
|
||||
'node_title' => "节点名称必须填写",
|
||||
'node_module' => "节点模块必须填写",
|
||||
];
|
||||
$this->model = new NodeModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加节点
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$error = $this->validateInsertFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$data = $this->getInsertDataFromRequest();
|
||||
$data['node_module'] = strtolower($data['node_module']);
|
||||
$data['node_controller'] = input("node_controller") ? strtolower($data['node_controller']) : "";
|
||||
$data['node_action'] = input("node_action") ? strtolower($data['node_action']) : "";
|
||||
$this->insertRow($data);
|
||||
return jok('用户添加成功');
|
||||
}
|
||||
/**
|
||||
* 更新节点
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
if (!isInteger($this->pk_value)) {
|
||||
return jerr("修改失败,参数错误", 400);
|
||||
}
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
$error = $this->validateUpdateFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$data = $this->getUpdateDataFromRequest();
|
||||
if($item['node_id'] == $data['node_pid']){
|
||||
return jerr("不能选择自己为上级菜单", 404);
|
||||
}
|
||||
$data['node_module'] = strtolower($data['node_module']);
|
||||
$data['node_controller'] = input("node_controller") ? strtolower($data['node_controller']) : "";
|
||||
$data['node_action'] = input("node_action") ? strtolower($data['node_action']) : "";
|
||||
$this->updateByPk($data);
|
||||
return jok('节点信息更新成功');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除节点
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写");
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$map = [$this->pk => $this->pk_value];
|
||||
$item = $this->model->where($map)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败");
|
||||
}
|
||||
$this->deleteBySingle();
|
||||
//删除对应ID的授权记录
|
||||
$this->authModel->where("auth_node", $this->pk_value)->delete();
|
||||
} else {
|
||||
$this->deleteByMultiple();
|
||||
//删除对应ID的授权记录
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->authModel->where("auth_node", 'in', $list)->delete();
|
||||
}
|
||||
return jok('删除节点成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有节点
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$order = $this->table . "_order desc," . $this->pk . " asc";
|
||||
$map = [
|
||||
"node_pid" => 0
|
||||
];
|
||||
$datalist = $this->model->where($map)->order($order)->select();
|
||||
$subMap = $this->getDataFilterFromRequest();
|
||||
for ($i = 0; $i < count($datalist); $i++) {
|
||||
$subDatalist = $this->model->field($this->selectList)->where($subMap)->where($this->table . "_pid", $datalist[$i][$this->pk])->order($order)->select();
|
||||
$datalist[$i]['sub'] = $subDatalist;
|
||||
for ($j = 0; $j < count($datalist[$i]['sub']); $j++) {
|
||||
$subDatalist2 = $this->model->field($this->selectList)->where($subMap)->where($this->table . "_pid", $datalist[$i]['sub'][$j][$this->pk])->order($order)->select();
|
||||
$datalist[$i]['sub'][$j]['sub'] = $subDatalist2;
|
||||
}
|
||||
}
|
||||
return jok('success', [
|
||||
'data' => $datalist,
|
||||
'map' => $map
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* 显示到菜单中
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function show_menu()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$this->model->where($this->pk, $this->pk_value)->update([
|
||||
$this->table . "_show" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->update([
|
||||
$this->table . "_show" => 1,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("显示成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 从菜单中隐藏
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hide_menu()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (isInteger($this->pk_value)) {
|
||||
$this->model->where($this->pk, $this->pk_value)->update([
|
||||
$this->table . "_show" => 0,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
} else {
|
||||
$list = explode(',', $this->pk_value);
|
||||
$this->model->where($this->pk, 'in', $list)->update([
|
||||
$this->table . "_show" => 0,
|
||||
$this->table . "_updatetime" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("隐藏成功");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Sms as SmsModel;
|
||||
use app\model\Validate as ValidateModel;
|
||||
|
||||
class Sms extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->model = new SmsModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function send()
|
||||
{
|
||||
//验证图形验证码
|
||||
$validateModel = new ValidateModel();
|
||||
$error = $validateModel->validateImgCode(input('token'), input('code'));
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (input("phone")) {
|
||||
$phone = input('phone');
|
||||
$code = cache("SMS_" . $phone);
|
||||
if ($code) {
|
||||
return jerr('发送短信太频繁,请稍候再试');
|
||||
}
|
||||
|
||||
$code = rand(100000, 999999);
|
||||
$error = $this->model->sendSms($phone, $code);
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
cache('SMS_' . $phone, $code, 300);
|
||||
return jok('短信验证码已经发送至你的手机');
|
||||
} else {
|
||||
return jerr("手机号为必填信息,请填写后提交");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\Filesystem;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Source as SourceModel;
|
||||
use app\model\SourceLog as SourceLogModel;
|
||||
use quarkPlugin\QuarkPlugin;
|
||||
|
||||
class Source extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//查询列表时允许的字段
|
||||
$this->selectList = "*";
|
||||
//查询详情时允许的字段
|
||||
$this->selectDetail = "*";
|
||||
//筛选字段
|
||||
$this->searchFilter = [];
|
||||
$this->insertFields = [
|
||||
//允许添加的字段列表
|
||||
"source_category_id","title","description","url","status","is_delete","sort","is_top","vod_content","is_type"
|
||||
];
|
||||
$this->updateFields = [
|
||||
//允许更新的字段列表
|
||||
"source_category_id","title","description","url","status","is_delete","sort","is_top","vod_content","is_type"
|
||||
];
|
||||
$this->insertRequire = [
|
||||
//添加时必须填写的字段
|
||||
// "字段名称"=>"该字段不能为空"
|
||||
"title"=>"资源名称必须填写",
|
||||
"url"=>"资源地址必须填写",
|
||||
];
|
||||
$this->updateRequire = [
|
||||
//修改时必须填写的字段
|
||||
// "字段名称"=>"该字段不能为空"
|
||||
"source_id"=>"资源ID必须填写",
|
||||
"title"=>"资源名称必须填写",
|
||||
"url"=>"资源地址必须填写",
|
||||
];
|
||||
$this->model = new SourceModel();
|
||||
$this->SourceLogModel = new SourceLogModel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取列表接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取筛选数据的数组
|
||||
$map = $this->getDataFilterFromRequest();
|
||||
$map[] = ['is_delete','=',0];
|
||||
if(!empty(input('source_category_id'))){
|
||||
$map[] = ['source_category_id','=',input('source_category_id')];
|
||||
}
|
||||
empty(input('keyword')) ?: $map[] = ['title|description', 'like', '%' . input('keyword') . '%'];
|
||||
//从请求中获取排序方式
|
||||
$order = $this->getorderfromRequest();
|
||||
//设置Model中的 per_page
|
||||
$this->setGetListPerPage();
|
||||
//查询数据
|
||||
$dataList = $this->model->getListByPage($map, $order, $this->selectList);
|
||||
return jok('数据获取成功', $dataList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//校验Insert字段是否填写
|
||||
$error = $this->validateInsertFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Insert数据
|
||||
$data = $this->getInsertDataFromRequest();
|
||||
//添加这行数据
|
||||
$data["update_time"] = time();
|
||||
$data["create_time"] = time();
|
||||
$data["is_type"] = determineIsType($data["url"]);
|
||||
$this->model->insertGetId($data);
|
||||
return jok('添加成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "参数必须填写", 400);
|
||||
}
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//校验Update字段是否填写
|
||||
$error = $this->validateUpdateFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Update数据
|
||||
$data = $this->getUpdateDataFromRequest();
|
||||
//根据主键更新这条数据
|
||||
$data["update_time"] = time();
|
||||
$data["is_type"] = determineIsType($data["url"]);
|
||||
$this->model->where($this->pk, $this->pk_value)->update($data);
|
||||
return jok('修改成功');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 删除接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if (!$this->pk_value) {
|
||||
return jerr($this->pk . "必须填写", 400);
|
||||
}
|
||||
|
||||
//根据主键获取一行数据
|
||||
$item = $this->getRowByPk();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
$this->model->where($this->pk, $this->pk_value)->delete();
|
||||
|
||||
return jok('删除成功');
|
||||
}
|
||||
|
||||
// 判断文件编码
|
||||
function detectFileEncoding($filename) {
|
||||
$handle = fopen($filename, 'r');
|
||||
$firstLine = fread($handle, 1024); // 读取文件的开头一部分内容
|
||||
fclose($handle);
|
||||
// 尝试使用不同的编码进行解码,并检查是否成功
|
||||
if (mb_check_encoding($firstLine, 'UTF-8')) {
|
||||
return 'UTF-8';
|
||||
} elseif (mb_check_encoding($firstLine, 'GBK')) {
|
||||
return 'GBK';
|
||||
} else {
|
||||
// 如果无法确定编码,则返回默认编码
|
||||
return 'UTF-8'; // 或者根据需要返回其他默认编码
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Excel导入
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function imports()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
// try {
|
||||
$file = request()->file('file');
|
||||
try {
|
||||
validate(['file' => 'filesize:' . config("qfshop.upload_max_file") . '|fileExt:' . config("qfshop.upload_file_type")])
|
||||
->check(['file' => $file]);
|
||||
$saveName = Filesystem::putFile('excel', $file, 'excel.csv');
|
||||
|
||||
ini_set("memory_limit",-1);
|
||||
|
||||
$file_name = app()->getRootPath()."public/uploads/".$saveName;
|
||||
|
||||
$extension = pathinfo($file_name, PATHINFO_EXTENSION);
|
||||
if ($extension == 'csv') {
|
||||
$PHPReader = new \PHPExcel_Reader_CSV();
|
||||
$encoding = $this->detectFileEncoding($file_name);
|
||||
$PHPReader->setInputEncoding($encoding);
|
||||
$PHPReader->setDelimiter(',');
|
||||
} elseif ($extension == 'xlsx') {
|
||||
$PHPReader = new \PHPExcel_Reader_Excel2007();
|
||||
} elseif ($extension == 'xls') {
|
||||
$PHPReader = new \PHPExcel_Reader_Excel5();
|
||||
} else {
|
||||
return jerr('不支持的文件类型');
|
||||
}
|
||||
|
||||
// //读取excel文件
|
||||
// $PHPReader = new \PHPExcel_Reader_CSV();
|
||||
// //默认输入字符集// 判断文件编码
|
||||
// $encoding = $this->detectFileEncoding($file_name);
|
||||
// $PHPReader->setInputEncoding($encoding);
|
||||
// //默认的分隔符
|
||||
// $PHPReader->setDelimiter(',');
|
||||
|
||||
|
||||
//载入文件
|
||||
$objExcel = $PHPReader->load($file_name);
|
||||
$excel_array = $objExcel ->getSheet(0)->toArray();
|
||||
array_shift($excel_array); //删除第一个数组(标题);
|
||||
$data = [];
|
||||
$i = 0;
|
||||
|
||||
//删除这个文件
|
||||
unlink("./uploads/".$saveName);
|
||||
|
||||
foreach ($excel_array as $k => $v) {
|
||||
$patterns = '/^\d+\.|\d+\-/';
|
||||
$title = '';
|
||||
$url = '';
|
||||
|
||||
for ($index = 1; $index <= 3; $index++) {
|
||||
// 检查 $v[$index] 是否存在
|
||||
if (isset($v[$index]) && preg_match('/http[^ ]+/', $v[$index], $matches)) {
|
||||
// 检查 $v[$index - 1] 是否存在
|
||||
if (isset($v[$index - 1])) {
|
||||
$title = preg_replace($patterns, '', $v[$index - 1]);
|
||||
}
|
||||
$url = $matches[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$map = [];
|
||||
$map[] = ['title', '=',$title];
|
||||
$res = $this->model->where($map)->find();
|
||||
if (empty($res) && $url) {
|
||||
$data[$k]['title'] = $title;
|
||||
$data[$k]['url'] = $url;
|
||||
$data[$k]["is_type"] = determineIsType($url);
|
||||
$data[$k]['source_category_id'] = input('source_category_id')??0;
|
||||
$data[$k]['update_time'] = time();
|
||||
$data[$k]['create_time'] = time();
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->model->insertAll($data);
|
||||
if($i == 0){
|
||||
return jok('无可导入的资源,请检查表格格式');
|
||||
}
|
||||
return jok('导入成功'.$i.'个资源');
|
||||
|
||||
} catch (ValidateException $e) {
|
||||
return jerr($e->getMessage());
|
||||
}
|
||||
// } catch (\Exception $error) {
|
||||
// return jerr('上传文件失败,请检查你的文件!');
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 导出
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function excel()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
//查询数据
|
||||
$map = [];
|
||||
$filter = input('');
|
||||
foreach ($filter as $k => $v) {
|
||||
if ($k == 'filter') {
|
||||
$k = input('filter');
|
||||
$v = input('keyword');
|
||||
}
|
||||
if ($v === '' || $v === null) {
|
||||
continue;
|
||||
}
|
||||
if (array_key_exists($k, $this->searchFilter)) {
|
||||
switch ($this->searchFilter[$k]) {
|
||||
case "like":
|
||||
array_push($map, [$k, 'like', "%" . $v . "%"]);
|
||||
break;
|
||||
case "=":
|
||||
array_push($map, [$k, '=', $v]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$field = 'title,url';
|
||||
$dataList = $this->model->field($field)->where($map)->select();
|
||||
$excelField = [
|
||||
"title" => "资源名称",
|
||||
"url" => "资源地址",
|
||||
];
|
||||
$data = $dataList->toArray();
|
||||
|
||||
$this->excelField = $excelField;
|
||||
$this->exportExcelData($dataList);
|
||||
print_r(12);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键转存并分享夸克资源
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function transfer()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if(empty(input("type")) || empty(input("urls"))){
|
||||
return jerr('参数不能为空');
|
||||
}
|
||||
|
||||
$source_category_id = input('source_category_id')??0;
|
||||
|
||||
$urls = input("urls");
|
||||
|
||||
$urls = explode("\n", $urls);
|
||||
|
||||
// 去掉数组元素中的空白字符
|
||||
$urls = array_map('trim', $urls);
|
||||
|
||||
// 过滤掉空值的数组元素
|
||||
$urls = array_filter($urls);
|
||||
|
||||
$allData = array_map(function($item) {
|
||||
$url = $item;
|
||||
$code = '';
|
||||
|
||||
// 检查是否包含 '?pwd=' 提取码格式
|
||||
if (strpos($item, '?pwd=') !== false) {
|
||||
// 使用 '?pwd=' 分割链接和提取码
|
||||
list($url, $code) = explode('?pwd=', $item, 2);
|
||||
$url = trim($url); // 去掉 URL 中的空白字符
|
||||
$code = trim($code); // 提取码去掉空白字符
|
||||
}
|
||||
// 检查是否包含逗号 ',' 提取码格式
|
||||
else if (strpos($item, ',') !== false) {
|
||||
// 使用 ',' 分割链接和提取码
|
||||
list($url, $code) = explode(',', $item, 2);
|
||||
$url = trim($url); // 去掉 URL 中的空白字符
|
||||
$code = trim($code); // 提取码去掉空白字符
|
||||
}
|
||||
|
||||
return [
|
||||
'url' => $url, // 只取链接部分
|
||||
'title' => '',
|
||||
'code' => $code, // 提取码部分
|
||||
];
|
||||
}, $urls);
|
||||
|
||||
// 去重,使用 'url' 字段来去重
|
||||
$uniqueUrls = [];
|
||||
$allData = array_filter($allData, function($item) use (&$uniqueUrls) {
|
||||
if (!in_array($item['url'], $uniqueUrls)) {
|
||||
$uniqueUrls[] = $item['url']; // 添加到已处理的 URL 列表
|
||||
return true; // 保留此项目
|
||||
}
|
||||
return false; // 去掉重复的项目
|
||||
});
|
||||
|
||||
$quarkPlugin = new QuarkPlugin();
|
||||
if(input("type")==2){
|
||||
//转存分享导入
|
||||
$res = $quarkPlugin->transfer($allData,$source_category_id);
|
||||
}else{
|
||||
// 直接导入
|
||||
$res = $quarkPlugin->import($allData,$source_category_id);
|
||||
}
|
||||
|
||||
return jok('已提交任务,稍后查看结果2',$res);
|
||||
}
|
||||
|
||||
/**
|
||||
* 全部转存
|
||||
* 转存心悦搜剧资源
|
||||
* @return void
|
||||
*/
|
||||
public function transferAll()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
if(empty(input('source_category_id'))){
|
||||
return jerr('参数异常');
|
||||
}
|
||||
$quarkPlugin = new QuarkPlugin();
|
||||
$quarkPlugin->transferAll(input('source_category_id'));
|
||||
return jok('已提交任务,稍后查看结果');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取夸克网盘文件夹
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getFiles()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$quarkPlugin = new QuarkPlugin();
|
||||
$result = $quarkPlugin->getFiles(Config('qfshop.quark_cookie'));
|
||||
return jok('获取成功',$result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use app\admin\QfShop;
|
||||
use app\model\SourceCategory as SourceCategoryModel;
|
||||
|
||||
class SourceCategory extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//查询列表时允许的字段
|
||||
$this->selectList = "*";
|
||||
//查询详情时允许的字段
|
||||
$this->selectDetail = "*";
|
||||
//筛选字段
|
||||
$this->searchFilter = [
|
||||
"source_category_id" => "=",
|
||||
"name"=>"like"
|
||||
];
|
||||
$this->insertFields = [
|
||||
//允许添加的字段列表
|
||||
"name","sort","status","image"
|
||||
];
|
||||
$this->updateFields = [
|
||||
//允许更新的字段列表
|
||||
"name","sort","status","image"
|
||||
];
|
||||
$this->insertRequire = [
|
||||
//添加时必须填写的字段
|
||||
// "字段名称"=>"该字段不能为空"
|
||||
"name"=>"分类名称必须填写",
|
||||
];
|
||||
$this->updateRequire = [
|
||||
//修改时必须填写的字段
|
||||
// "字段名称"=>"该字段不能为空"
|
||||
"name"=>"分类名称必须填写",
|
||||
];
|
||||
$this->model = new SourceCategoryModel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取列表接口
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//查询数据
|
||||
$dataList = $this->model->order('sort', 'desc')->select();
|
||||
return jok('数据获取成功', $dataList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取详情基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function detail()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$source_category_id = input("source_category_id");
|
||||
if (!$source_category_id) {
|
||||
return jerr("ID参数必须填写", 400);
|
||||
}
|
||||
//根据主键获取一行数据
|
||||
$item = $this->model->where("source_category_id", $source_category_id)->field($this->selectDetail)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("没有查询到数据", 404);
|
||||
}
|
||||
return jok('数据加载成功', $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//校验Insert字段是否填写
|
||||
$error = $this->validateInsertFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Insert数据
|
||||
$data = $this->getInsertDataFromRequest();
|
||||
//添加这行数据
|
||||
$data['create_time'] = time();
|
||||
$data['update_time'] = time();
|
||||
$this->model->insertGetId($data);
|
||||
return jok('添加成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$source_category_id = input("source_category_id");
|
||||
if (!$source_category_id) {
|
||||
return jerr("ID参数必须填写", 400);
|
||||
}
|
||||
|
||||
//根据主键获取一行数据
|
||||
$item = $this->model->where("source_category_id", $source_category_id)->field($this->selectDetail)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
|
||||
//校验Update字段是否填写
|
||||
$error = $this->validateUpdateFields();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取Update数据
|
||||
$data = $this->getUpdateDataFromRequest();
|
||||
//根据主键更新这条数据
|
||||
$data['update_time'] = time();
|
||||
$this->model->where("source_category_id", $source_category_id)->update($data);
|
||||
return jok('修改成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$source_category_id = input("source_category_id");
|
||||
if (!$source_category_id) {
|
||||
return jerr("ID参数必须填写", 400);
|
||||
}
|
||||
|
||||
//根据主键获取一行数据
|
||||
$item = $this->model->where("source_category_id", $source_category_id)->field($this->selectDetail)->find();
|
||||
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
|
||||
if ($item['is_sys']==1) {
|
||||
return jerr("该类别不能删除");
|
||||
}
|
||||
|
||||
//单个操作
|
||||
$map = ["source_category_id" => $source_category_id];
|
||||
$this->model->where($map)->delete();
|
||||
|
||||
return jok('删除成功');
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$source_category_id = input("source_category_id");
|
||||
if (!$source_category_id) {
|
||||
return jerr("ID参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($source_category_id)) {
|
||||
//根据主键获取一行数据
|
||||
$item = $this->model->where("source_category_id", $source_category_id)->field($this->selectDetail)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//单个操作
|
||||
$map = ["source_category_id" => $source_category_id];
|
||||
$this->model->where($map)->update([
|
||||
"status" => 1,
|
||||
"update_time" => time(),
|
||||
]);
|
||||
} else {
|
||||
//批量操作
|
||||
$list = explode(',', $source_category_id);
|
||||
$this->model->where("source_category_id", 'in', $list)->update([
|
||||
"status" => 1,
|
||||
"update_time" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("禁用成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启用接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
$source_category_id = input("source_category_id");
|
||||
if (!$source_category_id) {
|
||||
return jerr("ID参数必须填写", 400);
|
||||
}
|
||||
if (isInteger($source_category_id)) {
|
||||
//根据主键获取一行数据
|
||||
$item = $this->model->where("source_category_id", $source_category_id)->field($this->selectDetail)->find();
|
||||
if (empty($item)) {
|
||||
return jerr("数据查询失败", 404);
|
||||
}
|
||||
//单个操作
|
||||
$map = ["source_category_id" => $source_category_id];
|
||||
$this->model->where($map)->update([
|
||||
"status" => 0,
|
||||
"update_time" => time(),
|
||||
]);
|
||||
} else {
|
||||
//批量操作
|
||||
$list = explode(',', $source_category_id);
|
||||
$this->model->where("source_category_id", 'in', $list)->update([
|
||||
"status" => 0,
|
||||
"update_time" => time(),
|
||||
]);
|
||||
}
|
||||
return jok("启用成功");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\Filesystem;
|
||||
use app\admin\QfShop;
|
||||
use app\model\SourceLog as SourceLogModel;
|
||||
|
||||
class SourceLog extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//查询列表时允许的字段
|
||||
$this->selectList = "*";
|
||||
//查询详情时允许的字段
|
||||
$this->selectDetail = "*";
|
||||
$this->model = new SourceLogModel();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取列表接口基类 子类自动继承 如有特殊需求 可重写到子类 请勿修改父类方法
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getList()
|
||||
{
|
||||
//校验Access与RBAC
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
//从请求中获取筛选数据的数组
|
||||
$map = $this->getDataFilterFromRequest();
|
||||
//从请求中获取排序方式
|
||||
$order = $this->getorderfromRequest();
|
||||
//设置Model中的 per_page
|
||||
$this->setGetListPerPage();
|
||||
//查询数据
|
||||
$dataList = $this->model->getListByPage($map, $order, $this->selectList);
|
||||
return jok('数据获取成功', $dataList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\Db;
|
||||
use think\facade\Cache;
|
||||
use app\admin\QfShop;
|
||||
use app\model\Validate as ValidateModel;
|
||||
|
||||
class System extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
}
|
||||
/**
|
||||
* 获取图形验证码
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getCaptcha()
|
||||
{
|
||||
// $error = $this->access();
|
||||
// if ($error) {
|
||||
// return $error;
|
||||
// }
|
||||
$validateModel = new ValidateModel();
|
||||
$imgData = $validateModel->getImg();
|
||||
$code = strtoupper($validateModel->getCode());
|
||||
$token = sha1($code . time()) . rand(100000, 999999);
|
||||
cache($token, $code, 60);
|
||||
return jok('验证码生成成功', [
|
||||
'img' => $imgData,
|
||||
'token' => $token
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* 清除缓存
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clean()
|
||||
{
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
Cache::clear();
|
||||
|
||||
if($this->del_dir("../runtime/")){
|
||||
return jok('缓存已清空');
|
||||
}else{
|
||||
return jerr('缓存清除失败');
|
||||
}
|
||||
}
|
||||
|
||||
function del_dir($dir) {
|
||||
$dh=opendir($dir);
|
||||
while ($file=readdir($dh)) {
|
||||
if($file!="." && $file!="..") {
|
||||
$fullpath=$dir."/".$file;
|
||||
if(!is_dir($fullpath)) {
|
||||
@unlink($fullpath);
|
||||
} else {
|
||||
$this->del_dir($fullpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
if(rmdir($dir)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api;
|
||||
|
||||
use think\App;
|
||||
use think\facade\View;
|
||||
|
||||
use app\model\Conf as ConfModel;
|
||||
use app\model\Token as TokenModel;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
abstract class QfShop
|
||||
{
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
// 初始化
|
||||
protected function initialize()
|
||||
{
|
||||
//访问XMLHttpRequest已被CORS政策阻止
|
||||
header('Access-Control-Allow-Origin: *');
|
||||
|
||||
$this->confModel = new ConfModel();
|
||||
$configs = $this->confModel->select()->toArray();
|
||||
$c = [];
|
||||
foreach ($configs as $config) {
|
||||
$c[$config['conf_key']] = $config['conf_value'];
|
||||
}
|
||||
config($c, 'qfshop');
|
||||
}
|
||||
public function __call($method, $args)
|
||||
{
|
||||
return jerr("API接口方法不存在", 404);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检测授权 获取当前用户登录信息
|
||||
* @param $type false不提示登录失败状态
|
||||
* @param user_id 顾客时为用户id
|
||||
* @param action 操作者 顾客端为手机号,管理端为登录账号
|
||||
* @param client_type 0=顾客 1=管理组 -1=游客
|
||||
*/
|
||||
protected function getLoginUser($type = true)
|
||||
{
|
||||
$is_login = true;
|
||||
// 获取请求中的token
|
||||
$access_token = request()->header('X-CSRF-TOKEN');
|
||||
if (!$access_token) {
|
||||
if($type){
|
||||
return jerr("用户未登录", 401);
|
||||
}else{
|
||||
$is_login = false;
|
||||
}
|
||||
}
|
||||
$Token = new TokenModel();
|
||||
$user = $Token->getToken($access_token);
|
||||
if (!$user) {
|
||||
if($type){
|
||||
return jerr("登录过期,请重新登录", 401);
|
||||
}else{
|
||||
$is_login = false;
|
||||
}
|
||||
}
|
||||
if($is_login){
|
||||
$user['action'] = $user['mobile'];
|
||||
$user['client_type'] = 0;
|
||||
unset($user['mobile']);
|
||||
unset($user['status']);
|
||||
return $user;
|
||||
}else{
|
||||
$user['client_type'] = -1;
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\QfShop;
|
||||
|
||||
class Error extends QfShop
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return jerr("Error", 404);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\QfShop;
|
||||
|
||||
use Lizhichao\Word\VicWord;
|
||||
|
||||
|
||||
|
||||
class Index extends QfShop
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return jok("Hello World!");
|
||||
}
|
||||
public function search() {
|
||||
$fc = new VicWord();
|
||||
$keywords = input('keywords');
|
||||
$keywords = $fc->getAutoWord($keywords);
|
||||
|
||||
$keywords = filterAndExtractWords($keywords);
|
||||
|
||||
|
||||
return jok("Hello World!",$keywords);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,710 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\Cache;
|
||||
use app\api\QfShop;
|
||||
|
||||
class Open extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->url = "";
|
||||
$this->is_type = 0;
|
||||
$this->cookie = ""; //夸克登录凭证
|
||||
$this->Authorization = ""; //阿里登录凭证
|
||||
$this->expired_type = 1; //1分享永久 2临时
|
||||
$this->to_pdir_fid = ""; //存入目标文件
|
||||
$this->ad_fid = "";
|
||||
$this->code = ""; //提取码
|
||||
$this->isType = 0; //等于1时仅校验是否有效并提取资源信息
|
||||
$this->urlHeader = array(
|
||||
'Accept: application/json, text/plain, */*',
|
||||
'Accept-Language: zh-CN,zh;q=0.9',
|
||||
'content-type: application/json;charset=UTF-8',
|
||||
'sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'sec-ch-ua-mobile: ?0',
|
||||
'sec-ch-ua-platform: "Windows"',
|
||||
'sec-fetch-dest: empty',
|
||||
'sec-fetch-mode: cors',
|
||||
'sec-fetch-site: same-site',
|
||||
'Referer: https://pan.quark.cn/',
|
||||
'Referrer-Policy: strict-origin-when-cross-origin',
|
||||
'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
);
|
||||
}
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return jok('Hello World');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取夸克网盘文件夹
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getFiles()
|
||||
{
|
||||
$this->cookie = input('cookie')??'';
|
||||
$urlData = [];
|
||||
$queryParams = [
|
||||
'pr' => 'ucpro',
|
||||
'fr' => 'pc',
|
||||
'uc_param_str' => '',
|
||||
'pdir_fid' => 0,
|
||||
'_page' => 1,
|
||||
'_size' => 50,
|
||||
'_fetch_total' => 1,
|
||||
'_fetch_sub_dirs' => 0,
|
||||
'_sort' => 'file_type:asc,updated_at:desc',
|
||||
];
|
||||
|
||||
$this->urlHeader[] = 'cookie: ' . $this->cookie;
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/file/sort", "GET", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']=='require login [guest]'?'夸克未登录,请检查cookie':$res['message']);
|
||||
}
|
||||
|
||||
return jok('获取成功',$res['data']['list']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键转存并分享资源
|
||||
*
|
||||
* type 0 夸克 1阿里
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function transfer()
|
||||
{
|
||||
$url = input("url");
|
||||
$this->code = input('code')??'';
|
||||
$this->isType = input('isType')??0;
|
||||
|
||||
if($this->isType != 1){ //直接入口就不用cookie 防止账号异常
|
||||
$this->cookie = input('cookie')??'';
|
||||
$this->Authorization = input('Authorization')??'';
|
||||
}
|
||||
|
||||
$this->expired_type = input('expired_type')??1;
|
||||
$this->to_pdir_fid = input('to_pdir_fid')??"";
|
||||
$this->ad_fid = input('ad_fid')??"";
|
||||
|
||||
if (strpos($url, '?entry=') !== false) {
|
||||
$entry = preg_match('/\?entry=([^&]+)/', $url, $matches) ? $matches[1] : '';
|
||||
$url = preg_match('/.*(?=\?entry=)/', $url, $matches) ? $matches[0] : '';
|
||||
}
|
||||
|
||||
$substring = strstr($url, 's/');
|
||||
if ($substring !== false) {
|
||||
$pwd_id = substr($substring, 2); // 去除 's/' 部分
|
||||
} else {
|
||||
return jerr("资源地址格式有误");
|
||||
}
|
||||
|
||||
$this->urlHeader[] = 'cookie: ' . $this->cookie;
|
||||
|
||||
$patterns = [
|
||||
'pan.quark.cn' => 0,
|
||||
'www.alipan.com' => 1,
|
||||
'www.aliyundrive.com' => 1,
|
||||
// 'pan.baidu.com' => 2,
|
||||
'drive.uc.cn' => 3,
|
||||
// 'pan.xunlei.com' => 4,
|
||||
];
|
||||
|
||||
$url_type = -1; // 默认值为 -1
|
||||
foreach ($patterns as $pattern => $type) {
|
||||
if (strpos($url, $pattern) !== false) {
|
||||
$url_type = $type;
|
||||
break; // 一旦匹配成功,退出循环
|
||||
}
|
||||
}
|
||||
|
||||
$this->url = $url;
|
||||
|
||||
if ($url_type == 0) {
|
||||
//夸克
|
||||
if(empty($this->cookie) && $this->isType==0){
|
||||
jerr("参数有误");
|
||||
}
|
||||
$this->transferQuark(strtok($pwd_id, '#'));
|
||||
} else if($url_type == 1){
|
||||
//阿里
|
||||
if(empty($this->Authorization) && $this->isType==0){
|
||||
jerr("参数有误");
|
||||
}
|
||||
$this->transferAlipan($pwd_id);
|
||||
} else if($url_type == 2){
|
||||
//百度
|
||||
// $this->transferBaidu($pwd_id);
|
||||
} else if($url_type == 3){
|
||||
//UC
|
||||
$this->transferUc($pwd_id);
|
||||
} else {
|
||||
return jerr("资源地址格式有误");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 夸克 - 一键转存并分享资源
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function transferQuark($pwd_id){
|
||||
//获取要转存夸克资源的stoken
|
||||
$infoData = $this->getStoken($pwd_id);
|
||||
|
||||
if($this->isType == 1){
|
||||
$urls['title'] = $infoData['title'];
|
||||
$urls['share_url'] = $this->url;
|
||||
return jok('检验成功', $urls);
|
||||
}
|
||||
|
||||
|
||||
$stoken = $infoData['stoken'];
|
||||
|
||||
|
||||
//获取要转存夸克资源的详细内容
|
||||
$detail = $this->getShare($pwd_id,$stoken);
|
||||
|
||||
$fid_list = [];
|
||||
$fid_token_list = [];
|
||||
$title = $detail['share']['title']; //资源名称
|
||||
foreach ($detail['list'] as $key => $value) {
|
||||
$fid_list[] = $value['fid'];
|
||||
$fid_token_list[] = $value['share_fid_token'];
|
||||
}
|
||||
|
||||
//转存资源到指定文件夹
|
||||
$task_id = $this->getShareSave($pwd_id,$stoken,$fid_list,$fid_token_list);
|
||||
|
||||
//转存后根据task_id获取转存到自己网盘后的信息
|
||||
$retry_index = 0;
|
||||
$myData = '';
|
||||
while ($myData=='' || $myData['status'] != 2) {
|
||||
$myData = $this->getShareTask($task_id, $retry_index);
|
||||
$retry_index++;
|
||||
// 可以添加一个最大重试次数的限制,防止无限循环
|
||||
if ($retry_index > 50) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
//删除转存后可能有的广告
|
||||
$banned = Config('qfshop.quark_banned')??''; //如果出现这些字样就删除
|
||||
if(!empty($banned)){
|
||||
$bannedList = explode(',', $banned);
|
||||
$pdir_fid = $myData['save_as']['save_as_top_fids'][0];
|
||||
$dellist = [];
|
||||
$plist = $this->getPdirFid($pdir_fid);
|
||||
if(!empty($plist)){
|
||||
foreach ($plist as $key => $value) {
|
||||
// 检查$value['file_name']是否包含$bannedList中的任何一项
|
||||
$contains = false;
|
||||
foreach ($bannedList as $item) {
|
||||
if (strpos($value['file_name'], $item) !== false) {
|
||||
$contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($contains) {
|
||||
$dellist[] = $value['fid'];
|
||||
}
|
||||
}
|
||||
if(count($plist) === count($dellist)){
|
||||
//要删除的资源数如果和原数据资源数一样 就全部删除并终止下面的分享
|
||||
$this->deletepdirFid([$pdir_fid]);
|
||||
return jerr("资源内容为空");
|
||||
}else{
|
||||
if (!empty($dellist)) {
|
||||
$this->deletepdirFid($dellist);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
|
||||
//分享资源并拿到更新后的task_id
|
||||
$task_id = $this->getShareBtn($myData['save_as']['save_as_top_fids'],$title);
|
||||
|
||||
//根据task_id拿到share_id
|
||||
$retry_index = 0;
|
||||
$myData = '';
|
||||
while ($myData=='' || $myData['status'] != 2) {
|
||||
$myData = $this->getShareTask($task_id, $retry_index);
|
||||
$retry_index++;
|
||||
// 可以添加一个最大重试次数的限制,防止无限循环
|
||||
if ($retry_index > 50) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//根据share_id 获取到分享链接
|
||||
$share = $this->getSharePassword($myData['share_id']);
|
||||
$share['fid'] = $share['first_file']['fid'];
|
||||
|
||||
return jok('转存成功', $share);
|
||||
}
|
||||
|
||||
/**
|
||||
* 阿里 - 一键转存并分享资源
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function transferAlipan($share_id)
|
||||
{
|
||||
$data = [];
|
||||
$infos = $this->getAlipan1($share_id);
|
||||
|
||||
if($this->isType == 1){
|
||||
$urls['title'] = $infos['share_name'];
|
||||
$urls['share_url'] = $this->url;
|
||||
return jok('检验成功', $urls);
|
||||
}
|
||||
|
||||
|
||||
//通过分享id获取file_id
|
||||
$file_infos = $infos['file_infos'];
|
||||
|
||||
//通过分享id获取X-Share-Token
|
||||
$share_token = $this->getAlipan2($share_id);
|
||||
|
||||
$data3['requests'] = [];
|
||||
$data3['resource'] = 'file';
|
||||
|
||||
foreach ($file_infos as $key=>$value) {
|
||||
$data3['requests'][$key]['body']['auto_rename'] = true;
|
||||
$data3['requests'][$key]['body']['file_id'] = $value['file_id'];
|
||||
$data3['requests'][$key]['body']['share_id'] = $share_id;
|
||||
$data3['requests'][$key]['body']['to_drive_id'] = '2008425230';
|
||||
$data3['requests'][$key]['body']['to_parent_file_id'] = '66a20824c3846d890f6542c6aac2c79822d2a64f';
|
||||
$data3['requests'][$key]['headers']['Content-Type'] = 'application/json';
|
||||
$data3['requests'][$key]['id'] = $key.'';
|
||||
$data3['requests'][$key]['method'] = 'POST';
|
||||
$data3['requests'][$key]['url'] = '/file/copy';
|
||||
}
|
||||
|
||||
//保存
|
||||
$responses = $this->getAlipan3($data3,$share_token);
|
||||
$data4['drive_id'] = '2008425230';
|
||||
$data4['expiration'] = '';
|
||||
$data4['share_pwd'] = '';
|
||||
$data4['file_id_list'] = [];
|
||||
|
||||
foreach ($responses as $key=>$value){
|
||||
$data4['file_id_list'][] = $value['body']['file_id'];
|
||||
}
|
||||
|
||||
//分享
|
||||
$share = $this->getAlipan4($data4);
|
||||
|
||||
$data['share_url'] = $share['share_url'];
|
||||
$data['title'] = $share['share_title'];
|
||||
|
||||
return jok('转存成功', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* UC- 一键转存并分享资源
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function transferUc($pwd_id){
|
||||
$infoData = $this->getStokenUc($pwd_id);
|
||||
|
||||
if($this->isType == 1){
|
||||
$urls['title'] = $infoData['title'];
|
||||
$urls['share_url'] = $this->url;
|
||||
return jok('检验成功', $urls);
|
||||
}else{
|
||||
return jerr('暂不支持转存');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取要转存资源的stoken
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getStoken($pwd_id)
|
||||
{
|
||||
$urlData = array(
|
||||
'passcode' => '',
|
||||
'pwd_id' => $pwd_id,
|
||||
);
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/share/sharepage/token?pr=ucpro&fr=pc&uc_param_str=", "POST",json_encode($urlData), $this->urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']);
|
||||
}
|
||||
$data = $res['data'];
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取要转存资源的详细内容
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getShare($pwd_id,$stoken)
|
||||
{
|
||||
$urlData = array();
|
||||
$queryParams = [
|
||||
"pr" => "ucpro",
|
||||
"fr" => "pc",
|
||||
"uc_param_str" => "",
|
||||
"pwd_id" => $pwd_id,
|
||||
"stoken" => $stoken,
|
||||
"pdir_fid" => "0",
|
||||
"force" => "0",
|
||||
"_page" => "1",
|
||||
"_size" => "100",
|
||||
"_fetch_banner" => "1",
|
||||
"_fetch_share" => "1",
|
||||
"_fetch_total" => "1",
|
||||
"_sort" => "file_type:asc,updated_at:desc"
|
||||
];
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/share/sharepage/detail", "GET", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']);
|
||||
}
|
||||
return $res['data'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转存资源到指定文件夹
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getShareSave($pwd_id,$stoken,$fid_list,$fid_token_list)
|
||||
{
|
||||
$to_pdir_fid = $this->to_pdir_fid??"";
|
||||
$urlData = array(
|
||||
'fid_list' => $fid_list,
|
||||
'fid_token_list' => $fid_token_list,
|
||||
'to_pdir_fid' => $to_pdir_fid,
|
||||
'pwd_id' => $pwd_id,
|
||||
'stoken' => $stoken,
|
||||
'pdir_fid' => "0",
|
||||
'scene' => "link",
|
||||
);
|
||||
$queryParams = [
|
||||
"entry" => "update_share",
|
||||
"pr" => "ucpro",
|
||||
"fr" => "pc",
|
||||
"uc_param_str" => ""
|
||||
];
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/share/sharepage/save", "POST", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']=='require login [guest]'?'夸克未登录,请检查cookie':$res['message']);
|
||||
}
|
||||
return $res['data']['task_id'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 分享资源拿到task_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getShareBtn($fid_list,$title)
|
||||
{
|
||||
if(!empty($this->ad_fid)){
|
||||
$fid_list[] = $this->ad_fid;
|
||||
}
|
||||
$urlData = array(
|
||||
'fid_list' => $fid_list,
|
||||
'expired_type' => $this->expired_type,
|
||||
'title' => $title,
|
||||
'url_type' => 1,
|
||||
);
|
||||
$queryParams = [
|
||||
"pr" => "ucpro",
|
||||
"fr" => "pc",
|
||||
"uc_param_str" => ""
|
||||
];
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/share", "POST", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']);
|
||||
}
|
||||
return $res['data']['task_id'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据task_id拿到自己的资源信息
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getShareTask($task_id,$retry_index)
|
||||
{
|
||||
$urlData = array();
|
||||
$queryParams = [
|
||||
"pr" => "ucpro",
|
||||
"fr" => "pc",
|
||||
"uc_param_str" => "",
|
||||
"task_id" => $task_id,
|
||||
"retry_index" => $retry_index
|
||||
];
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/task", "GET", json_encode($urlData), $this->urlHeader, $queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']);
|
||||
}
|
||||
return $res['data'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据share_id 获取到分享链接
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getSharePassword($share_id)
|
||||
{
|
||||
$urlData = array(
|
||||
'share_id' => $share_id,
|
||||
);
|
||||
$queryParams = [
|
||||
"pr" => "ucpro",
|
||||
"fr" => "pc",
|
||||
"uc_param_str" => ""
|
||||
];
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/share/password", "POST", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']);
|
||||
}
|
||||
return $res['data'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除指定资源
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deletepdirFid($filelist)
|
||||
{
|
||||
$urlData = array(
|
||||
'action_type' => 2,
|
||||
'exclude_fids' => [],
|
||||
'filelist' => $filelist,
|
||||
);
|
||||
$queryParams = [
|
||||
"pr" => "ucpro",
|
||||
"fr" => "pc",
|
||||
"uc_param_str" => ""
|
||||
];
|
||||
curlHelper("https://drive-pc.quark.cn/1/clouddrive/file/delete", "POST", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取夸克网盘指定文件夹内容
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getPdirFid($pdir_fid)
|
||||
{
|
||||
$urlData = [];
|
||||
$queryParams = [
|
||||
'pr' => 'ucpro',
|
||||
'fr' => 'pc',
|
||||
'uc_param_str' => '',
|
||||
'pdir_fid' => $pdir_fid,
|
||||
'_page' => 1,
|
||||
'_size' => 200,
|
||||
'_fetch_total' => 1,
|
||||
'_fetch_sub_dirs' => 0,
|
||||
'_sort' => 'file_type:asc,updated_at:desc',
|
||||
];
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/file/sort", "GET", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return [];
|
||||
}
|
||||
return $res['data']['list'];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 阿里-0-通过分享id获取file_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getAlipan1($share_id)
|
||||
{
|
||||
$urlData = [
|
||||
'share_id' => $share_id,
|
||||
];
|
||||
$urlHeader = array(
|
||||
'Content-Type: application/json',
|
||||
);
|
||||
$res = curlHelper("https://api.aliyundrive.com/adrive/v3/share_link/get_share_by_anonymous", "POST", json_encode($urlData),$urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if(!isset($res['file_infos'])){
|
||||
return jerr($res['message']??'转存失败1');
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 阿里-0-通过分享id获取X-Share-Token
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getAlipan2($share_id)
|
||||
{
|
||||
$urlData = array(
|
||||
'share_id' => $share_id,
|
||||
);
|
||||
$urlHeader = array(
|
||||
'Accept: application/json, text/plain, */*',
|
||||
'Accept-Encoding: gzip, deflate, br, zstd',
|
||||
'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||||
'Authorization: '.$this->Authorization,
|
||||
'Content-Type: application/json',
|
||||
'Origin: https://www.alipan.com',
|
||||
'Priority: u=1, i',
|
||||
'Referer: https://www.alipan.com/',
|
||||
'Sec-Ch-Ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'Sec-Ch-Ua-Mobile: ?0',
|
||||
'Sec-Ch-Ua-Platform: "Windows"',
|
||||
'Sec-Fetch-Dest: empty',
|
||||
'Sec-Fetch-Mode: cors',
|
||||
'Sec-Fetch-Site: same-site',
|
||||
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',
|
||||
'X-Canary: client=web,app=share,version=v2.3.1'
|
||||
);
|
||||
$res = curlHelper("https://api.aliyundrive.com/v2/share_link/get_share_token", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if(!isset($res['share_token'])){
|
||||
return jerr($res['message']??'转存失败2');
|
||||
}
|
||||
return $res['share_token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 阿里-1-保存
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getAlipan3($urlData,$share_token)
|
||||
{
|
||||
$urlHeader = array(
|
||||
'Accept: application/json, text/plain, */*',
|
||||
'Accept-Encoding: gzip, deflate, br, zstd',
|
||||
'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||||
'Authorization: '.$this->Authorization,
|
||||
'Content-Type: application/json',
|
||||
'Origin: https://www.alipan.com',
|
||||
'Priority: u=1, i',
|
||||
'Referer: https://www.alipan.com/',
|
||||
'Sec-Ch-Ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'Sec-Ch-Ua-Mobile: ?0',
|
||||
'Sec-Ch-Ua-Platform: "Windows"',
|
||||
'Sec-Fetch-Dest: empty',
|
||||
'Sec-Fetch-Mode: cors',
|
||||
'Sec-Fetch-Site: same-site',
|
||||
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',
|
||||
'X-Canary: client=web,app=share,version=v2.3.1',
|
||||
'X-Share-Token: '.$share_token
|
||||
);
|
||||
$res = curlHelper("https://api.aliyundrive.com/adrive/v4/batch", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if(!isset($res['responses'])){
|
||||
return jerr($res['message']??'转存失败3');
|
||||
}
|
||||
return $res['responses'];
|
||||
}
|
||||
|
||||
/**
|
||||
* 阿里-2-分享
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getAlipan4($urlData)
|
||||
{
|
||||
$urlHeader = array(
|
||||
'Accept: application/json, text/plain, */*',
|
||||
'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
|
||||
'Authorization: '.$this->Authorization,
|
||||
'Content-Type: application/json',
|
||||
'Origin: https://www.alipan.com',
|
||||
'Priority: u=1, i',
|
||||
'Referer: https://www.alipan.com/',
|
||||
'Sec-Ch-Ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'Sec-Ch-Ua-Mobile: ?0',
|
||||
'Sec-Ch-Ua-Platform: "Windows"',
|
||||
'Sec-Fetch-Dest: empty',
|
||||
'Sec-Fetch-Mode: cors',
|
||||
'Sec-Fetch-Site: same-site',
|
||||
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0',
|
||||
'X-Canary: client=web,app=share,version=v2.3.1'
|
||||
);
|
||||
$res = curlHelper("https://api.aliyundrive.com/adrive/v2/share_link/create", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
return jerr($res);
|
||||
if(!isset($res['share_url'])){
|
||||
return jerr($res['message']??'转存失败4');
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* UC 00000
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getStokenUc($pwd_id)
|
||||
{
|
||||
$urlData = array(
|
||||
'passcode' => '',
|
||||
'pwd_id' => $pwd_id,
|
||||
);
|
||||
$urlHeader = array(
|
||||
'Accept: application/json, text/plain, */*',
|
||||
'Accept-Language: zh-CN,zh;q=0.9',
|
||||
'content-type: application/json;charset=UTF-8',
|
||||
'sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'sec-ch-ua-mobile: ?0',
|
||||
'sec-ch-ua-platform: "Windows"',
|
||||
'sec-fetch-dest: empty',
|
||||
'sec-fetch-mode: cors',
|
||||
'sec-fetch-site: same-site',
|
||||
'Referer: https://drive.uc.cn/',
|
||||
'Referrer-Policy: strict-origin-when-cross-origin',
|
||||
'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
);
|
||||
|
||||
$res = curlHelper("https://pc-api.uc.cn/1/clouddrive/share/sharepage/token?pr=UCBrowser&fr=pc", "POST",json_encode($urlData),$urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] !== 200){
|
||||
return jerr($res['message']);
|
||||
}
|
||||
$data = $res['data'];
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,628 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use think\App;
|
||||
use app\api\QfShop;
|
||||
use app\model\Source as SourceModel;
|
||||
use app\model\Days as DaysModel;
|
||||
|
||||
class Other extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
//第三方转存接口地址
|
||||
$this->url = "https://pan.xinyuedh.com";
|
||||
$this->model = new SourceModel();
|
||||
$this->cookie = Config('qfshop.quark_cookie');
|
||||
}
|
||||
|
||||
public function Alone_search2()
|
||||
{
|
||||
$searchdata = input('');
|
||||
if (empty($searchdata['alone_title'])) {
|
||||
return jerr("请输入要看的内容");
|
||||
}
|
||||
|
||||
$type = $searchdata['type']??0;
|
||||
$title = $searchdata['alone_title'];
|
||||
|
||||
$searchList = []; //查询的结果集
|
||||
$num_total = $type?2:20; //最多想要几条结果
|
||||
$num_success = 0;
|
||||
|
||||
// 处理第2个源
|
||||
foreach (source2($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$num_success++;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理第4个源
|
||||
if ($num_success < $num_total) {
|
||||
foreach (source4($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$num_success++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 处理第3个源
|
||||
if ($num_success < $num_total) {
|
||||
foreach (source3($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$num_success++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 处理第1个源 第一个源放最后
|
||||
if ($num_success < $num_total) {
|
||||
foreach (source1($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$num_success++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jok('临时资源获取成功',$searchList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 全网搜索 该接口仅用于微信自动回复
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Alone_search()
|
||||
{
|
||||
|
||||
$searchdata = input('post.');
|
||||
if (empty($searchdata['alone_title'])) {
|
||||
return jerr("请输入要看的内容");
|
||||
}
|
||||
$title = $searchdata['alone_title'];
|
||||
|
||||
|
||||
$map[] = ['status', '=', 1];
|
||||
$map[] = ['is_delete', '=', 0];
|
||||
$map[] = ['is_time', '=', 1];
|
||||
$map[] = ['title|description', 'like', '%' . trim($title) . '%'];
|
||||
|
||||
$urls = $this->model->where($map)->field('source_id as id, title, url')->order('update_time', 'desc')->limit(5)->select()->toArray();
|
||||
if (!empty($urls)) {
|
||||
|
||||
// 获取所有需要更新的ID
|
||||
$ids = [];
|
||||
foreach ($urls as $item) {
|
||||
$ids[] = $item['id'];
|
||||
}
|
||||
|
||||
// 更新数据库中的 update_time 字段
|
||||
if (!empty($ids)) {
|
||||
$this->model->whereIn('source_id', $ids)->update(['update_time' => time()]);
|
||||
}
|
||||
|
||||
return jok('临时资源获取成功',$urls);
|
||||
}
|
||||
|
||||
$searchList = []; //查询的结果集
|
||||
$datas = []; //最终数据
|
||||
$num_total = 2; //最多想要几条结果
|
||||
$num_success = 0;
|
||||
|
||||
// 处理第2个源
|
||||
foreach (source2($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$this->processUrl($value, $num_success, $datas);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 处理第4个源
|
||||
if ($num_success < $num_total) {
|
||||
foreach (source4($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$this->processUrl($value, $num_success, $datas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 处理第3个源
|
||||
if ($num_success < $num_total) {
|
||||
foreach (source3($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$this->processUrl($value, $num_success, $datas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 处理第1个源 第一个源放最后
|
||||
if ($num_success < $num_total) {
|
||||
foreach (source1($title) as $value) {
|
||||
if ($num_success >= $num_total) {
|
||||
break; // 有效结果数量已达到,则跳出循环
|
||||
}
|
||||
// 如果 URL 不存在则新增 $value
|
||||
if (!$this->urlExists($searchList, $value['url'])) {
|
||||
$searchList[] = $value;
|
||||
$this->processUrl($value, $num_success, $datas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jok('临时资源获取成功',$datas);
|
||||
}
|
||||
|
||||
// 检查 URL 是否已存在(忽略查询参数)
|
||||
public function urlExists($searchList, $urlToCheck) {
|
||||
// 解析待检查的 URL
|
||||
$parsedUrlToCheck = parse_url($urlToCheck);
|
||||
|
||||
foreach ($searchList as $item) {
|
||||
$parsedUrl = parse_url($item['url']);
|
||||
|
||||
// 比较 scheme, host 和 path
|
||||
if ($parsedUrlToCheck['scheme'] === $parsedUrl['scheme'] &&
|
||||
$parsedUrlToCheck['host'] === $parsedUrl['host'] &&
|
||||
$parsedUrlToCheck['path'] === $parsedUrl['path']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 临时资源转存
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function processUrl($value, &$num_success, &$datas)
|
||||
{
|
||||
$substring = strstr($value['url'], 's/');
|
||||
if ($substring === false) {
|
||||
return; // 模拟 continue 行为
|
||||
}
|
||||
|
||||
$pwd_id = substr($substring, 2); // 去除 's/' 部分
|
||||
|
||||
$urlData = array(
|
||||
'cookie' => $this->cookie,
|
||||
'url' => $value['url'],
|
||||
'expired_type' => 2,
|
||||
'to_pdir_fid' => '61bad1e1380d47c78d6f5d86c877efb9', //存入目标文件
|
||||
'ad_fid' => '3b57147245774d88bafba7f43152f4bd', //分享时带上这个文件
|
||||
);
|
||||
$res = curlHelper($this->url."/api/open/transfer", "POST", $urlData)['body'];
|
||||
$res = json_decode($res, true);
|
||||
|
||||
if($res['code'] !== 200){
|
||||
return; // 模拟 continue 行为
|
||||
}
|
||||
|
||||
$patterns = '/^\d+\./';
|
||||
$title = preg_replace($patterns, '', $value['title']);
|
||||
// 添加资源到系统中
|
||||
$data["title"] =$title;
|
||||
$data["url"] =$res['data']['share_url'];
|
||||
$data["is_type"] = determineIsType($data["url"]);
|
||||
$data["fid"] =$res['data']['fid']??'';
|
||||
$data["is_time"] = 1;
|
||||
$data["update_time"] = time();
|
||||
$data["create_time"] = time();
|
||||
$this->model->insertGetId($data);
|
||||
$datas[] =$data;
|
||||
$num_success++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 十分钟后清除临时资源
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_search()
|
||||
{
|
||||
// 搜索条件
|
||||
$map[] = ['is_time', '=', 1];
|
||||
$map[] = ['update_time', '<=', time() - (30 * 60)];
|
||||
$abc = $this->model->where($map)->select();
|
||||
|
||||
|
||||
$this->model->where($map)->chunk(100, function ($order) {
|
||||
foreach ($order as $value) {
|
||||
$deles = $value->toArray();
|
||||
$filelist = [];
|
||||
$filelist[] = $deles['fid'];
|
||||
|
||||
|
||||
$urlData = array(
|
||||
'action_type' => 2,
|
||||
'exclude_fids' => [],
|
||||
'filelist' => $filelist,
|
||||
);
|
||||
$urlHeader = array(
|
||||
'Accept: application/json, text/plain, */*',
|
||||
'Accept-Language: zh-CN,zh;q=0.9',
|
||||
'content-type: application/json;charset=UTF-8',
|
||||
'sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'sec-ch-ua-mobile: ?0',
|
||||
'sec-ch-ua-platform: "Windows"',
|
||||
'sec-fetch-dest: empty',
|
||||
'sec-fetch-mode: cors',
|
||||
'sec-fetch-site: same-site',
|
||||
'Referer: https://pan.quark.cn/',
|
||||
'Referrer-Policy: strict-origin-when-cross-origin',
|
||||
'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'cookie: '.$this->cookie,
|
||||
);
|
||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/file/delete?pr=ucpro&fr=pc&uc_param_str=", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['status'] == 200){
|
||||
$this->model->where('fid', $deles['fid'])->delete();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return jok('临时资源删除成功',$abc);
|
||||
}
|
||||
|
||||
|
||||
public function alone_zhuanshu22222()
|
||||
{
|
||||
$list = [];
|
||||
try {
|
||||
$result = curlHelper("https://duanju.niurl.cn/api.php", "GET")['body'];
|
||||
$list = json_decode($result, true);
|
||||
$list = $list['data'];
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
if (count($list) > 100) {
|
||||
$list = array_slice($list, 0, 100); // 如果超过100位,则截取前100位
|
||||
}
|
||||
$list = array_reverse($list);
|
||||
|
||||
foreach ($list as $key => $value){
|
||||
//如果资源不是今天或者昨天的 就跳过 只采集今天昨天的资源
|
||||
if($value['addtime'] != date('Y-m-d') && $value['addtime'] != date('Y-m-d', strtotime('-1 day'))){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//如已有此资源 跳过
|
||||
$detail = $this->model->where('title', $value['name'])->find();
|
||||
if(!empty($detail)){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$url = $value['url'];
|
||||
$substring = strstr($url, 's/');
|
||||
if ($substring !== false) {
|
||||
$pwd_id = substr($substring, 2); // 去除 's/' 部分
|
||||
} else {
|
||||
//资源地址格式有误
|
||||
continue;
|
||||
}
|
||||
$urlData = array(
|
||||
'cookie' => Config('qfshop.quark_cookie'),
|
||||
'url' => $url,
|
||||
);
|
||||
$res = curlHelper($this->url."/api/open/transfer", "POST", $urlData)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['code'] !== 200){
|
||||
continue;
|
||||
}
|
||||
|
||||
//添加资源到系统中
|
||||
$data["title"] = $value['name'];
|
||||
$data["url"] = $res['data']['share_url'];
|
||||
$data["update_time"] = time();
|
||||
$data["create_time"] = time();
|
||||
$this->model->insertGetId($data);
|
||||
}
|
||||
|
||||
return jok('123456');
|
||||
}
|
||||
|
||||
public function alone_zhuanshu()
|
||||
{
|
||||
$list = [];
|
||||
$add_num = 0;
|
||||
$parameters = array(
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'6fbefc1f535f48a38cbb580f9553fcea', //4月夸克文件夹fid
|
||||
'6da509da98124e1d98cd3aa70f1ad7fa',
|
||||
'2b805566aee0430ca6a3a0ba995685bd',
|
||||
'93996a5d87b64c36849c442374fd1bbf',
|
||||
'499e29a766704e00ac0e6e3d1c7b252a',
|
||||
'4c69edb70454496688813de3cd6a27f8',
|
||||
'fed17385093446b78e8c2f286f683100',
|
||||
'38233cc7b14148fea33ea9998c19dc22',
|
||||
'70c3c5d7a1cc442eb998428893b00e94'
|
||||
);
|
||||
|
||||
// try {
|
||||
// $result = curlHelper("https://duanju.niurl.cn/api.php", "GET")['body'];
|
||||
// $list = json_decode($result, true);
|
||||
// $list = $list['data'];
|
||||
|
||||
// } catch (Exception $e) {
|
||||
// }
|
||||
try {
|
||||
$list1 = [];
|
||||
$result = curlHelper("https://kuoapp.com/duanju/get.php?day=".date('Y-m-d'), "GET")['body'];
|
||||
$res1 = json_decode($result, true);
|
||||
if (is_array($res1) && array_keys($res1) === range(0, count($res1) - 1)) {
|
||||
$list1 = $res1;
|
||||
}
|
||||
|
||||
$list2 = [];
|
||||
$result = curlHelper("https://kuoapp.com/duanju/get.php?day=".date('Y-m-d', strtotime('-1 day')), "GET")['body'];
|
||||
$res2 = json_decode($result, true);
|
||||
if (is_array($res2) && array_keys($res2) === range(0, count($res2) - 1)) {
|
||||
$list2 = $res2;
|
||||
}
|
||||
$list = array_merge($list1, $list2); // 合并两个数组
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
if (count($list) > 100) {
|
||||
$list = array_slice($list, 0, 100); // 如果超过100位,则截取前100位
|
||||
}
|
||||
$list = array_reverse($list);
|
||||
|
||||
|
||||
foreach ($list as $key => $value){
|
||||
// 如果资源不是今天或者昨天的 就跳过 只采集今天昨天的资源
|
||||
if($value['addtime'] != date('Y-m-d') && $value['addtime'] != date('Y-m-d', strtotime('-1 day'))){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//如已有此资源 跳过
|
||||
$value['name'] = str_replace(["\u0000", "\x00", "\0"], '', $value['name']);
|
||||
$detail = $this->model->where('title', $value['name'])->find();
|
||||
if(!empty($detail)){
|
||||
continue;
|
||||
}
|
||||
|
||||
//整理数据 按天创建夸克文件夹
|
||||
$dateString = $value['addtime']; // 哪一天的资源 如:2024-04-01
|
||||
$timestamp = strtotime($dateString); // 将日期转换为时间戳
|
||||
$newDateString = date('n月j日', $timestamp); // 夸克文件夹的名称 格式: 4月1日
|
||||
$month = date('n', $timestamp); //月份 格式:4
|
||||
|
||||
$DaysModel = new DaysModel();
|
||||
|
||||
$fids = $DaysModel->where(["time"=>$dateString])->find();
|
||||
if (!$fids){
|
||||
//去创建文件夹获取fid
|
||||
$urlData = array(
|
||||
'dir_init_lock' => false,
|
||||
'dir_path' => "",
|
||||
'file_name' => $newDateString,
|
||||
'pdir_fid' => $parameters[$month-1],
|
||||
);
|
||||
$urlHeader = array(
|
||||
'Accept: application/json, text/plain, */*',
|
||||
'Accept-Language: zh-CN,zh;q=0.9',
|
||||
'content-type: application/json;charset=UTF-8',
|
||||
'sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'sec-ch-ua-mobile: ?0',
|
||||
'sec-ch-ua-platform: "Windows"',
|
||||
'sec-fetch-dest: empty',
|
||||
'sec-fetch-mode: cors',
|
||||
'sec-fetch-site: same-site',
|
||||
'Referer: https://pan.quark.cn/',
|
||||
'Referrer-Policy: strict-origin-when-cross-origin',
|
||||
'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
||||
'cookie: '.Config('qfshop.quark_cookie'),
|
||||
);
|
||||
$quark = curlHelper("https://drive-pc.quark.cn/1/clouddrive/file?pr=ucpro&fr=pc&uc_param_str=", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
$quark = json_decode($quark, true);
|
||||
if($quark['status'] !== 200){
|
||||
continue;
|
||||
}
|
||||
|
||||
$fid = $quark['data']['fid'];
|
||||
|
||||
$DaysModel->insert([
|
||||
"fid" => $fid,
|
||||
"time" => $dateString,
|
||||
]);
|
||||
$fids = $DaysModel->where(["time"=>$dateString])->find();
|
||||
}
|
||||
//最终我要获取 $fids['fid'] 这个参数
|
||||
|
||||
$url = $value['url'];
|
||||
$substring = strstr($url, 's/');
|
||||
if ($substring !== false) {
|
||||
$pwd_id = substr($substring, 2); // 去除 's/' 部分
|
||||
} else {
|
||||
//资源地址格式有误
|
||||
continue;
|
||||
}
|
||||
$urlData = array(
|
||||
'cookie' => Config('qfshop.quark_cookie'),
|
||||
'url' => $url,
|
||||
'to_pdir_fid' => $fids['fid']??''
|
||||
);
|
||||
$res = curlHelper($this->url."/api/open/transfer", "POST", $urlData)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['code'] !== 200){
|
||||
continue;
|
||||
}
|
||||
|
||||
//添加资源到系统中
|
||||
$data["title"] = $value['name'];
|
||||
$data["url"] = $res['data']['share_url'];
|
||||
$addtime = time();
|
||||
if(!empty($value['addtime'])){
|
||||
$addtime = $value['addtime'].' '.date('H:i');
|
||||
$addtime = strtotime($addtime);
|
||||
}
|
||||
$data["update_time"] = $addtime;
|
||||
$data["create_time"] = $addtime;
|
||||
$data["source_category_id"] = 1;
|
||||
$this->model->insertGetId($data);
|
||||
$add_num++;
|
||||
}
|
||||
|
||||
return jok(date('Y-m-d H:i').' Added number of resources',$add_num);
|
||||
}
|
||||
|
||||
public function aaaa()
|
||||
{
|
||||
$dateString = date('Y-m-d');
|
||||
$timestamp = strtotime($dateString); // 将日期转换为时间戳
|
||||
$newDateString = date('n月j日', $timestamp); // 夸克文件夹的名称 格式: 6月1日
|
||||
$month = date('n', $timestamp); //月份 格式:6
|
||||
|
||||
$list = [];
|
||||
try {
|
||||
$list1 = [];
|
||||
$result = curlHelper("https://kuoapp.com/duanju/get.php?day=".date('Y-m-d'), "GET")['body'];
|
||||
$res1 = json_decode($result, true);
|
||||
if (is_array($res1) && array_keys($res1) === range(0, count($res1) - 1)) {
|
||||
$list1 = $res1;
|
||||
}
|
||||
|
||||
$list2 = [];
|
||||
$result = curlHelper("https://kuoapp.com/duanju/get.php?day=".date('Y-m-d', strtotime('-1 day')), "GET")['body'];
|
||||
$res2 = json_decode($result, true);
|
||||
if (is_array($res2) && array_keys($res2) === range(0, count($res2) - 1)) {
|
||||
$list2 = $res2;
|
||||
}
|
||||
$list = array_merge($list1, $list2); // 合并两个数组
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return jok('123456',date('H:i'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 在线观看接口 该接口仅用于微信自动回复
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Alone_online()
|
||||
{
|
||||
if(!Config('qfshop.mp4_online')){
|
||||
return jok('在线资源地址', []);
|
||||
}
|
||||
// 获取输入数据
|
||||
$searchdata = input('');
|
||||
if (empty($searchdata['alone_title'])) {
|
||||
return jerr("请输入要看的内容");
|
||||
}
|
||||
$title = $searchdata['alone_title'];
|
||||
|
||||
// 定义请求头
|
||||
$urlHeader = [
|
||||
'cookie: thinkphp_show_page_trace=0|0; pwmd5=9c2c9cc26c93ed2d7560cfc4ae4d4ac3; userid=312; usergroup=1; username=18339988501; usertime=2024-08-06+15%3A41%3A26; usersin=04e882c0b3f468fba62a5d1f03174aea',
|
||||
'Content-Type: application/json'
|
||||
];
|
||||
|
||||
// 查询参数
|
||||
$queryParams = [
|
||||
'page' => 1,
|
||||
'limit' => 1,
|
||||
'name' => $title,
|
||||
'type' => '',
|
||||
];
|
||||
|
||||
// 发送GET请求
|
||||
$res = curlHelper("https://vvc.qeduanju.cn/promote/list.html", "GET", json_encode([]), $urlHeader, $queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
|
||||
// 检查响应并处理数据
|
||||
if ($res && $res['code'] == 0 && $res['count'] > 0) {
|
||||
$data = [];
|
||||
$ids = [];
|
||||
|
||||
foreach ($res['data'] as $value) {
|
||||
$data[] = [
|
||||
'id' => $value['id'],
|
||||
'title' => $value['name']
|
||||
];
|
||||
$ids[] = $value['id'];
|
||||
}
|
||||
|
||||
// POST请求的数据
|
||||
$urlData = [
|
||||
"id" => $ids,
|
||||
"pzid" => 283
|
||||
];
|
||||
|
||||
// 发送POST请求
|
||||
$res2 = curlHelper("https://vvc.qeduanju.cn/promote/dwz.html", "POST", json_encode($urlData), $urlHeader, $queryParams)['body'];
|
||||
$res2 = json_decode($res2, true);
|
||||
|
||||
if ($res2 && $res2['code'] == 0) {
|
||||
$finalData = [];
|
||||
foreach ($res2['data'] as $value) {
|
||||
foreach ($data as &$item) {
|
||||
if ($item['id'] == $value['id']) {
|
||||
$finalData[] = [
|
||||
'title' => '【在线观看】'.$item['title'],
|
||||
'url' => $value['url']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
return jok('在线资源地址', $finalData);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有找到匹配数据,返回空数据
|
||||
return jok('在线资源地址', []);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\QfShop;
|
||||
use app\model\Source as SourceModel;
|
||||
use app\model\SourceCategory as SourceCategoryModel;
|
||||
|
||||
class Search extends QfShop
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$SourceModel = new SourceModel();
|
||||
$data = $SourceModel->getList(input(''));
|
||||
return jok('获取成功',$data);
|
||||
}
|
||||
|
||||
public function getDetail()
|
||||
{
|
||||
$SourceModel = new SourceModel();
|
||||
$data = $SourceModel->getDetail(input(''));
|
||||
return jok('获取成功',$data);
|
||||
}
|
||||
|
||||
public function getNew()
|
||||
{
|
||||
$SourceModel = new SourceModel();
|
||||
$data = input('');
|
||||
$data['page_size'] = $data['page_size']??20;
|
||||
$data = $SourceModel->getNew($data);
|
||||
return jok('获取成功',$data);
|
||||
}
|
||||
|
||||
public function getHot()
|
||||
{
|
||||
$SourceModel = new SourceModel();
|
||||
$data = $SourceModel->getHot(input(''));
|
||||
return jok('获取成功',$data);
|
||||
}
|
||||
|
||||
public function getCategory()
|
||||
{
|
||||
$SourceCategoryModel = new SourceCategoryModel();
|
||||
$data = $SourceCategoryModel->getList(input(''));
|
||||
return jok('获取成功',$data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use think\App;
|
||||
use app\api\QfShop;
|
||||
use think\facade\Cache;
|
||||
use Carbon\Carbon;
|
||||
use quarkPlugin\QuarkPlugin;
|
||||
use app\model\SourceCategory as SourceCategoryModel;
|
||||
|
||||
class Source extends QfShop
|
||||
{
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
}
|
||||
public function day()
|
||||
{
|
||||
// 当前日期
|
||||
$currentDate = Carbon::today()->toDateString();
|
||||
// 缓存键名
|
||||
$cacheKey = 'api_alone_date_' . $currentDate;
|
||||
|
||||
// 检查缓存中是否存在该键
|
||||
if (Cache::has($cacheKey)) {
|
||||
return jerr("该接口今天已经执行过,请1小时后再试!");
|
||||
}
|
||||
|
||||
Cache::set($cacheKey, time(), 2400);
|
||||
|
||||
|
||||
|
||||
$SourceCategoryModel = new SourceCategoryModel();
|
||||
$map[] = ['is_update', '=', 1];
|
||||
$data = $SourceCategoryModel->where($map)->column('source_category_id');
|
||||
$ids = implode(',', $data);
|
||||
|
||||
$quarkPlugin = new QuarkPlugin();
|
||||
$quarkPlugin->transferAll($ids,2);
|
||||
return jok('已提交任务,稍后查看结果');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use think\App;
|
||||
use app\api\QfShop;
|
||||
use app\model\User as Usermodel;
|
||||
use app\model\Ads as Adsmodel;
|
||||
use app\model\Feedback as FeedbackModel;
|
||||
use app\model\SourceCategory as SourceCategoryModel;
|
||||
|
||||
class Tool extends QfShop
|
||||
{
|
||||
/**
|
||||
* 系统配置参数
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
$data = [
|
||||
'app_name' => Config('qfshop.app_name'),
|
||||
'qcode' => getimgurl(Config('qfshop.qcode')),
|
||||
'logo' => getimgurl(Config('qfshop.logo')),
|
||||
'app_description' => Config('qfshop.app_description'),
|
||||
];
|
||||
return jok('获取成功',$data);
|
||||
}
|
||||
/**
|
||||
* 上传图片
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Upload()
|
||||
{
|
||||
// 获取当前登录的用户信息
|
||||
$userInfo = $this->getLoginUser();
|
||||
|
||||
try {
|
||||
$file = request()->file('file');
|
||||
} catch (\Exception $error) {
|
||||
return jerr('上传文件失败,请检查你的文件!');
|
||||
}
|
||||
$Usermodel = new Usermodel();
|
||||
$data = $Usermodel->Upload($file, $userInfo);
|
||||
return jok('上传成功',$data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据广告位关键词获取广告图片列表
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getAdsCode()
|
||||
{
|
||||
$Adsmodel = new Adsmodel();
|
||||
$data = $Adsmodel->getAdsCode(input(''));
|
||||
return jok('获取成功',$data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户反馈
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function feedback()
|
||||
{
|
||||
$data = input('');
|
||||
if (empty($data['content'])) {
|
||||
return jerr("请输入要看的内容");
|
||||
}
|
||||
$FeedbackModel = new FeedbackModel();
|
||||
$FeedbackModel->save(['content' => $data['content']]);
|
||||
return jok('已反馈');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取首页排行榜数据
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function ranking()
|
||||
{
|
||||
$channel = input('channel');
|
||||
$is_m = input('is_m')??0;
|
||||
|
||||
if (empty($channel)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 使用 ThinkPHP 提供的 runtime_path() 函数获取 runtime 目录路径
|
||||
$cacheDir = runtime_path('cache'); // runtime/cache 目录
|
||||
if (!is_dir($cacheDir)) {
|
||||
mkdir($cacheDir, 0755, true); // 确保缓存目录存在
|
||||
}
|
||||
|
||||
// 根据 channel 值生成缓存文件名
|
||||
$cacheFile = $cacheDir . "ranking_data_{$channel}.cache";
|
||||
$cacheTime = 12*3600; // 缓存时间为 12 小时
|
||||
|
||||
// 检查缓存文件是否存在且在缓存时间内
|
||||
if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $cacheTime) {
|
||||
// 从缓存中读取数据
|
||||
$data = json_decode(file_get_contents($cacheFile), true);
|
||||
} else {
|
||||
$data = [];
|
||||
if (!empty($channel)) {
|
||||
$queryParams = array(
|
||||
"area" => "全部",
|
||||
"year" => "全部",
|
||||
"channel" => $channel,
|
||||
"rank_type" => "最热",
|
||||
"cate" => "全部",
|
||||
"from" => "hot_page",
|
||||
"start" => 0,
|
||||
"hit" => Config('qfshop.ranking_num') ?? 1,
|
||||
);
|
||||
$res = curlHelper("https://biz.quark.cn/api/trending/ranking/getYingshiRanking", "GET", null, [], $queryParams)['body'];
|
||||
$res = json_decode($res, true);
|
||||
try {
|
||||
foreach ($res['data']['hits']['hit']['item'] as $key => $value) {
|
||||
$data[] = array(
|
||||
"title" => $value['title'],
|
||||
"src" => $value['src'],
|
||||
"ranking" => $value['ranking'],
|
||||
"hot_score" => $value['hot_score'],
|
||||
"desc" => $value['desc'],
|
||||
);
|
||||
}
|
||||
} catch (Exception $error) {
|
||||
$data = [];
|
||||
}
|
||||
|
||||
// 将数据缓存到文件中
|
||||
file_put_contents($cacheFile, json_encode($data));
|
||||
}
|
||||
}
|
||||
|
||||
if($is_m==1){
|
||||
$ranking_m_num = Config('qfshop.ranking_m_num') ?? 6;
|
||||
$data = array_slice($data, 0, $ranking_m_num);
|
||||
}
|
||||
|
||||
return jok('获取成功', $data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use think\App;
|
||||
use app\api\QfShop;
|
||||
|
||||
use EasyWeChat\Factory;
|
||||
use EasyWeChat\OfficialAccount\Application;
|
||||
|
||||
use app\model\Source as SourceModel;
|
||||
|
||||
class Wechat extends QfShop
|
||||
{
|
||||
/*
|
||||
微信公众平台配置如下:
|
||||
微信公众平台-基本配置-生成AppSecret并设置ip白名单
|
||||
启用服务器配置即可
|
||||
URL:你的域名/api/wechat/serve
|
||||
Token:自行生成
|
||||
EncodingAESKey:随机生成即可
|
||||
消息加解密方式:推荐即可
|
||||
*/
|
||||
private $config = [
|
||||
'app_id' => 'wx7d0373771cf5e395',//公众号appid
|
||||
'secret' => '3e9fefc1ccc573afb4141bf2e4e6ac3b',//公众号secret
|
||||
'token' => 'aDA3Ve61uNpn5xXKgPm49wtqL2ZlvDac', //Token 自行生成32字符串 英文或数字
|
||||
'aes_key' => 'r0HkOAEGKkaYdJLvaCy9ldtgzhMzDUJYPoLxUc62OMA' //微信公众平台生成后填写到这里
|
||||
];
|
||||
|
||||
public function serve()
|
||||
{
|
||||
// 创建一个微信公众账号实例,使用指定的配置
|
||||
$app = Factory::officialAccount($this->config);
|
||||
|
||||
// 设置消息处理回调函数
|
||||
$app->server->push(function ($message) {
|
||||
// 检查用户消息内容中是否包含“搜剧”关键字
|
||||
if (strpos($message['Content'], '搜') !== false) {
|
||||
|
||||
// 去除“搜剧”关键字和空格,提取用户输入的剧名
|
||||
$newString = str_replace(['搜剧', ' '], '', $message['Content']);
|
||||
$newString = str_replace(['搜', ' '], '', $message['Content']);
|
||||
|
||||
// 实例化资源模型,并搜索匹配的剧名
|
||||
$SourceModel = new SourceModel();
|
||||
$list = $SourceModel->where('title', 'like', '%' . $newString . '%')->limit(5)->select();
|
||||
|
||||
// 构建回复内容
|
||||
if (!$list->isEmpty()) {
|
||||
$content = "";
|
||||
foreach ($list as $item) {
|
||||
if ($content) {
|
||||
$content = $content."\n".$item['title']."\n".$item['url']."\n --------------------";
|
||||
} else {
|
||||
$content = $item['title']."\n".$item['url']."\n --------------------";
|
||||
}
|
||||
}
|
||||
// 添加操作步骤说明
|
||||
$content = $content."\n 步骤:点击上方链接-打开网盘-点立即查看-点右下角保存-打开文件-按文件名排序即可从第一集开始-自动-全集播放";
|
||||
} else {
|
||||
// 如果没有找到匹配的剧名,提示用户减少关键词尝试搜索
|
||||
$content = "未找到,减少关键词尝试搜索。";
|
||||
}
|
||||
|
||||
return $content; // 返回匹配结果或提示信息
|
||||
}
|
||||
|
||||
// 如果不匹配条件,返回空字符串或不做任何回复
|
||||
return '';
|
||||
});
|
||||
|
||||
// 开始处理微信服务器的请求并返回响应
|
||||
$response = $app->server->serve();
|
||||
$response->send(); // 发送响应
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
[2024-04-07T15:46:10.672053+08:00] EasyWeChat.DEBUG: Request received: {"method":"GET","uri":"https://pan.xinyuedh.com/api/wechat?s=%2Fapi%2Fwechat","content-type":null,"content":""}
|
||||
[2024-04-07T15:46:10.719415+08:00] EasyWeChat.DEBUG: Server response created: {"content":"success"}
|
||||
[2024-04-07T15:46:38.369913+08:00] EasyWeChat.DEBUG: Request received: {"method":"GET","uri":"https://pan.xinyuedh.com/api/wechat?s=%2Fapi%2Fwechat","content-type":null,"content":""}
|
||||
[2024-04-07T15:46:38.377289+08:00] EasyWeChat.DEBUG: Server response created: {"content":"success"}
|
||||
+973
@@ -0,0 +1,973 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 输出正常JSON
|
||||
*
|
||||
* @param string 提示信息
|
||||
* @param array 输出数据
|
||||
* @return json
|
||||
*/
|
||||
function jok($message = 'success', $data = null)
|
||||
{
|
||||
header("content-type:application/json;chartset=uft-8");
|
||||
if ($data) {
|
||||
echo json_encode(["code" => 200, "message" => $message, 'data' => $data]);
|
||||
} else {
|
||||
echo json_encode(["code" => 200, "message" => $message, 'data' => $data??'']);
|
||||
}
|
||||
die;
|
||||
}
|
||||
/**
|
||||
* 输出错误JSON
|
||||
*
|
||||
* @param string 错误信息
|
||||
* @param int 错误代码
|
||||
* @return json
|
||||
*/
|
||||
function jerr($message = 'error', $code = 500)
|
||||
{
|
||||
header("content-type:application/json;chartset=uft-8");
|
||||
echo json_encode(["code" => $code, "message" => $message]);
|
||||
die;
|
||||
}
|
||||
/**
|
||||
* 密码+盐 加密
|
||||
*
|
||||
* @param string 明文密码
|
||||
* @param string 盐
|
||||
* @return string
|
||||
*/
|
||||
function encodePassword($password, $salt)
|
||||
{
|
||||
return sha1($password . $salt . $password . $salt);
|
||||
}
|
||||
/**
|
||||
* 密码校验 6-16
|
||||
*
|
||||
* @param string 明文密码
|
||||
* @return boolean 是否校验通过
|
||||
*/
|
||||
function isValidPassword($password)
|
||||
{
|
||||
return preg_match('/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?!.*\s).{6,}/', $password);
|
||||
}
|
||||
/**
|
||||
* 获取随机字符
|
||||
*
|
||||
* @param int $len
|
||||
* @return void
|
||||
*/
|
||||
function getRandString($len)
|
||||
{
|
||||
$string = '';
|
||||
$randString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$string .= $randString[rand(0, strlen($randString) - 1)];
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
/**
|
||||
* 生成唯一会议编码
|
||||
* @param string $prefix 头部
|
||||
* @return string
|
||||
*/
|
||||
function get_order_no($prefix = 'QF')
|
||||
{
|
||||
$order_no = $prefix;
|
||||
$order_no .= mb_strtoupper(dechex(date('m')), 'utf-8');
|
||||
$order_no .= date('d') . mb_substr(time(), -5, null, 'utf-8');
|
||||
$order_no .= mb_substr(microtime(), 2, 5, 'utf-8');
|
||||
return $order_no;
|
||||
}
|
||||
/**
|
||||
* 获取随机字母
|
||||
*
|
||||
* @param int 长度
|
||||
* @return string
|
||||
*/
|
||||
function getRandChar($len)
|
||||
{
|
||||
$string = '';
|
||||
$randString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$string .= $randString[rand(0, strlen($randString) - 1)];
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
/**
|
||||
* 驼峰转下划线
|
||||
* @param $camelCaps
|
||||
* @param string $separator
|
||||
* @return string
|
||||
*/
|
||||
function uncamelize($camelCaps, $separator = '_')
|
||||
{
|
||||
return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
|
||||
}
|
||||
/**
|
||||
* 遍历类的方法
|
||||
*
|
||||
* @param string 指定的类名称
|
||||
* @return array
|
||||
*/
|
||||
function getClassMethods($class)
|
||||
{
|
||||
$array_result = [];
|
||||
$array_all = get_class_methods($class);
|
||||
if ($parent_class = get_parent_class($class)) {
|
||||
$array_parent = get_class_methods($parent_class);
|
||||
$array_result = array_diff($array_all, $array_parent);
|
||||
} else {
|
||||
$array_result = $array_all;
|
||||
}
|
||||
return $array_result;
|
||||
}
|
||||
/**
|
||||
* 获取包含协议和端口的域名
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getFullDomain()
|
||||
{
|
||||
// return ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? $_SERVER['REQUEST_SCHEME']) . "://" . $_SERVER['HTTP_HOST'];
|
||||
return "http://" . $_SERVER['HTTP_HOST'];
|
||||
}
|
||||
/**
|
||||
* 图片地址转绝对路径
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getimgurl($img)
|
||||
{
|
||||
$result = '';
|
||||
if($img){
|
||||
// $url = ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? $_SERVER['REQUEST_SCHEME']) . "://" . $_SERVER['HTTP_HOST'];
|
||||
$url = "http://" . $_SERVER['HTTP_HOST'];
|
||||
if(is_array($img)){
|
||||
$result = [];
|
||||
foreach ($img as $key => $value) {
|
||||
if(!preg_match("/^http(s)?:\\/\\/.+/", $value)){
|
||||
$result[] = $url.$value;
|
||||
}else{
|
||||
$result[] = $value;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(!preg_match("/^http(s)?:\\/\\/.+/", $img)){
|
||||
$result = $url.$img;
|
||||
}else{
|
||||
$result = $img;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换编辑器内容中的文件地址
|
||||
* @param string $content 编辑器内容
|
||||
* @return string
|
||||
*/
|
||||
function app_replace_content_file_url($content)
|
||||
{
|
||||
\phpQuery::newDocumentHTML($content);
|
||||
$pq = pq(null);
|
||||
$domain = request()->host();
|
||||
$images = $pq->find("img");
|
||||
if ($images->length) {
|
||||
foreach ($images as $img) {
|
||||
$img = pq($img);
|
||||
$imgSrc = $img->attr("src");
|
||||
if(!preg_match("/^http(s)?:\\/\\/.+/", $imgSrc)){
|
||||
$img->attr("src", getimgurl($imgSrc));
|
||||
}
|
||||
}
|
||||
}
|
||||
$links = $pq->find("a");
|
||||
if ($links->length) {
|
||||
foreach ($links as $link) {
|
||||
$link = pq($link);
|
||||
$href = $link->attr("href");
|
||||
if(!preg_match("/^http(s)?:\\/\\/.+/", $href)){
|
||||
$img->attr("href", getimgurl($imgSrc));
|
||||
}
|
||||
}
|
||||
}
|
||||
$content = $pq->htmlOuter();
|
||||
\phpQuery::$documents = null;
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端IP
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getClientIp()
|
||||
{
|
||||
foreach (array(
|
||||
'HTTP_CLIENT_IP',
|
||||
'HTTP_X_FORWARDED_FOR',
|
||||
'HTTP_X_FORWARDED',
|
||||
'HTTP_X_CLUSTER_CLIENT_IP',
|
||||
'HTTP_FORWARDED_FOR',
|
||||
'HTTP_FORWARDED',
|
||||
'REMOTE_ADDR'
|
||||
) as $key) {
|
||||
if (array_key_exists($key, $_SERVER)) {
|
||||
foreach (explode(',', $_SERVER[$key]) as $ip) {
|
||||
$ip = trim($ip);
|
||||
if ((bool) filter_var(
|
||||
$ip,
|
||||
FILTER_VALIDATE_IP,
|
||||
FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6
|
||||
// FILTER_FLAG_NO_PRIV_RANGE |
|
||||
// FILTER_FLAG_NO_RES_RANGE
|
||||
)) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取文本中间
|
||||
*
|
||||
* @param string 原始字符串
|
||||
* @param string 左边字符串
|
||||
* @param string 右边字符串
|
||||
* @return string
|
||||
*/
|
||||
function getSubstr($str, $leftStr, $rightStr)
|
||||
{
|
||||
$left = strpos($str, $leftStr);
|
||||
$right = strpos($str, $rightStr, $left);
|
||||
if ($left < 0 or $right < $left) return '';
|
||||
return substr($str, $left + strlen($leftStr), $right - $left - strlen($leftStr));
|
||||
}
|
||||
/**
|
||||
* 获取操作系统
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getOs()
|
||||
{
|
||||
if (empty($_SERVER['HTTP_USER_AGENT'])) {
|
||||
return 'Other';
|
||||
}
|
||||
$agent = strtolower($_SERVER['HTTP_USER_AGENT']);
|
||||
if (strpos($agent, 'windows nt')) {
|
||||
$platform = 'Windows';
|
||||
} elseif (strpos($agent, 'macintosh')) {
|
||||
$platform = 'MacOS';
|
||||
} elseif (strpos($agent, 'ipod')) {
|
||||
$platform = 'iPod';
|
||||
} elseif (strpos($agent, 'ipad')) {
|
||||
$platform = 'iPad';
|
||||
} elseif (strpos($agent, 'iphone')) {
|
||||
$platform = 'iPhone';
|
||||
} elseif (strpos($agent, 'android')) {
|
||||
$platform = 'Android';
|
||||
} elseif (strpos($agent, 'unix')) {
|
||||
$platform = 'Unix';
|
||||
} elseif (strpos($agent, 'linux')) {
|
||||
$platform = 'Linux';
|
||||
} else {
|
||||
$platform = 'Other';
|
||||
}
|
||||
return $platform;
|
||||
}
|
||||
/**
|
||||
* 获取浏览器
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function getBrowser()
|
||||
{
|
||||
if (empty($_SERVER['HTTP_USER_AGENT'])) {
|
||||
return 'Unknown';
|
||||
}
|
||||
$agent = $_SERVER["HTTP_USER_AGENT"];
|
||||
if (strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) //ie11判断
|
||||
{
|
||||
return "IE";
|
||||
} else if (strpos($agent, 'Firefox') !== false) {
|
||||
return "Firefox";
|
||||
} else if (strpos($agent, 'Chrome') !== false) {
|
||||
return "Chrome";
|
||||
} else if (strpos($agent, 'Opera') !== false) {
|
||||
return 'Opera';
|
||||
} else if ((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false) {
|
||||
return 'Safari';
|
||||
} else {
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 是否手机请求
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function isMobileRequest()
|
||||
{
|
||||
$_SERVER['ALL_HTTP'] = isset($_SERVER['ALL_HTTP']) ? $_SERVER['ALL_HTTP'] : '';
|
||||
$mobile_browser = '0';
|
||||
if (preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|iphone|uc|qq|wechat|micro|messenger|ipad|ipod|android|xoom)/i', strtolower($_SERVER['HTTP_USER_AGENT'])))
|
||||
$mobile_browser++;
|
||||
if ((isset($_SERVER['HTTP_ACCEPT'])) and (strpos(strtolower($_SERVER['HTTP_ACCEPT']), 'application/vnd.wap.xhtml+xml') !== false))
|
||||
$mobile_browser++;
|
||||
if (isset($_SERVER['HTTP_X_WAP_PROFILE']))
|
||||
$mobile_browser++;
|
||||
if (isset($_SERVER['HTTP_PROFILE']))
|
||||
$mobile_browser++;
|
||||
$mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'], 0, 4));
|
||||
$mobile_agents = array(
|
||||
'w3c ', 'acs-', 'alav', 'alca', 'amoi', 'audi', 'avan', 'benq', 'bird', 'blac',
|
||||
'blaz', 'brew', 'cell', 'cldc', 'cmd-', 'dang', 'doco', 'eric', 'hipt', 'inno',
|
||||
'ipaq', 'java', 'jigs', 'kddi', 'keji', 'leno', 'lg-c', 'lg-d', 'lg-g', 'lge-',
|
||||
'maui', 'maxo', 'midp', 'mits', 'mmef', 'mobi', 'mot-', 'moto', 'mwbp', 'nec-',
|
||||
'newt', 'noki', 'oper', 'palm', 'pana', 'pant', 'phil', 'play', 'port', 'prox',
|
||||
'qwap', 'sage', 'sams', 'sany', 'sch-', 'sec-', 'send', 'seri', 'sgh-', 'shar',
|
||||
'sie-', 'siem', 'smal', 'smar', 'sony', 'sph-', 'symb', 't-mo', 'teli', 'tim-',
|
||||
'tosh', 'tsm-', 'upg1', 'upsi', 'vk-v', 'voda', 'wap-', 'wapa', 'wapi', 'wapp',
|
||||
'wapr', 'webc', 'winw', 'winw', 'xda', 'xda-'
|
||||
);
|
||||
if (in_array($mobile_ua, $mobile_agents))
|
||||
$mobile_browser++;
|
||||
if (strpos(strtolower($_SERVER['ALL_HTTP']), 'operamini') !== false)
|
||||
$mobile_browser++;
|
||||
// Pre-final check to reset everything if the user is on Windows
|
||||
if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false)
|
||||
$mobile_browser = 0;
|
||||
// But WP7 is also Windows, with a slightly different characteristic
|
||||
if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows phone') !== false)
|
||||
$mobile_browser++;
|
||||
if ($mobile_browser > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* 身份证号验证
|
||||
* @param $id
|
||||
* @return bool
|
||||
*/
|
||||
function isIDCard($id)
|
||||
{
|
||||
$id = strtoupper($id);
|
||||
$regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/";
|
||||
$arr_split = array();
|
||||
if (!preg_match($regx, $id)) {
|
||||
return FALSE;
|
||||
}
|
||||
if (15 == strlen($id)) //检查15位
|
||||
{
|
||||
$regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/";
|
||||
@preg_match($regx, $id, $arr_split);
|
||||
//检查生日日期是否正确
|
||||
$dtm_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
|
||||
if (!strtotime($dtm_birth)) {
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
} else { //检查18位
|
||||
$regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/";
|
||||
@preg_match($regx, $id, $arr_split);
|
||||
$dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
|
||||
if (!strtotime($dtm_birth)) //检查生日日期是否正确
|
||||
{
|
||||
return FALSE;
|
||||
} else {
|
||||
//检验18位身份证的校验码是否正确。
|
||||
//校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。
|
||||
$arr_int = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
|
||||
$arr_ch = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
|
||||
$sign = 0;
|
||||
for ($i = 0; $i < 17; $i++) {
|
||||
$b = (int) $id[$i];
|
||||
$w = $arr_int[$i];
|
||||
$sign += $b * $w;
|
||||
}
|
||||
$n = $sign % 11;
|
||||
$val_num = $arr_ch[$n];
|
||||
if ($val_num != substr($id, 17, 1)) {
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 是否是整数
|
||||
*
|
||||
* @param string 输入内容
|
||||
* @return boolean
|
||||
*/
|
||||
function isInteger($input)
|
||||
{
|
||||
return (ctype_digit(strval($input)));
|
||||
}
|
||||
/**
|
||||
* 获取一个key摘要
|
||||
*
|
||||
* @param string 原始key
|
||||
* @return string
|
||||
*/
|
||||
function getTicket($key)
|
||||
{
|
||||
return sha1($key . (env('SYSTEM_SALT') ?? 'qfshop') . $key);
|
||||
}
|
||||
/**
|
||||
* 通用CURL请求函数
|
||||
*
|
||||
* @param string $url URL地址
|
||||
* @param string $method 请求方法, 支持GET/POST/PUT/DELETE/PATCH/TRACE/OPTIONS/HEAD 默认POST
|
||||
* @param mixed $data 请求数据包体
|
||||
* @param array $header 请求头 数组
|
||||
* @param array $queryParams 查询参数 数组
|
||||
* @param string $cookies 请求COOKIES字符串
|
||||
* @param int $timeout 请求超时时间,默认30秒
|
||||
* @return array 响应数组,包括header, body, detail, error
|
||||
*/
|
||||
function curlHelper($url, $method = 'POST', $data = null, $header = [], $queryParams = "", $cookies = "", $timeout = 60)
|
||||
{
|
||||
// 构建查询参数
|
||||
if (!empty($queryParams)) {
|
||||
$queryString = http_build_query($queryParams);
|
||||
$url .= '?' . $queryString;
|
||||
}
|
||||
|
||||
$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_HTTPHEADER, $header);
|
||||
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); // 设置超时时间
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); // 设置连接超时时间
|
||||
|
||||
// 根据请求方法设置选项
|
||||
switch (strtoupper($method)) {
|
||||
case "POST":
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
if ($data) {
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
break;
|
||||
case "PUT":
|
||||
case "DELETE":
|
||||
case "PATCH":
|
||||
case "TRACE":
|
||||
case "OPTIONS":
|
||||
case "HEAD":
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
|
||||
if ($data) {
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
break;
|
||||
case "GET":
|
||||
default:
|
||||
curl_setopt($ch, CURLOPT_HTTPGET, true);
|
||||
break;
|
||||
}
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if ($response === false) {
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
return ['error' => $error];
|
||||
}
|
||||
|
||||
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||
$output = [
|
||||
'header' => substr($response, 0, $headerSize),
|
||||
'body' => substr($response, $headerSize),
|
||||
'detail' => curl_getinfo($ch)
|
||||
];
|
||||
|
||||
curl_close($ch);
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟表单上传文件请求
|
||||
* @param $$url 提交地址
|
||||
* @param $data 提交数据
|
||||
* @param $cookies 如设置了Content-Type将被自动覆写为formdata
|
||||
* ex.
|
||||
* $data = ['file'=>new \CURLFile(realpath($file_dir)),appid"=>"1234"];
|
||||
* $result = curl_form($url,$data);
|
||||
* @return mixed
|
||||
*/
|
||||
function curlForm($url, $data = null, $header = [], $cookies = "")
|
||||
{
|
||||
$header[] = 'Content-Type: multipart/form-data';
|
||||
return curlHelper($url, "POST", $data, $header, $cookies);
|
||||
}
|
||||
/**
|
||||
* 多维数组合并(支持多数组)
|
||||
* @param arraylist arrayMergeMulti(['1'=>'1','2'=>'2','3'=>'3'],['4'=>'4','5'=>'5','6'=>'6'])
|
||||
* @return array
|
||||
*/
|
||||
function arrayMergeMulti()
|
||||
{
|
||||
//获取当前方法捕获到的所有参数数组
|
||||
$args = func_get_args();
|
||||
$array = [];
|
||||
foreach ($args as $arg) {
|
||||
if (is_array($arg)) {
|
||||
foreach ($arg as $k => $v) {
|
||||
if (is_array($v)) {
|
||||
$array[$k] = isset($array[$k]) ? $array[$k] : [];
|
||||
$array[$k] = arrayMergeMulti($array[$k], $v);
|
||||
} else {
|
||||
$array[$k] = $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
/**
|
||||
* 对查询结果集进行排序
|
||||
* @access public
|
||||
* @param array $list 查询结果
|
||||
* @param string $field 排序的字段名
|
||||
* @param array $sortBy 排序类型
|
||||
* asc正向排序 desc逆向排序 nat自然排序
|
||||
* @return array|bool
|
||||
*/
|
||||
function listSortBy($list, $field, $sortBy = 'asc')
|
||||
{
|
||||
if (is_array($list)) {
|
||||
$refer = $resultSet = [];
|
||||
foreach ($list as $i => $data) {
|
||||
$refer[$i] = &$data[$field];
|
||||
}
|
||||
switch ($sortBy) {
|
||||
case 'asc': // 正向排序
|
||||
asort($refer);
|
||||
break;
|
||||
case 'desc': // 逆向排序
|
||||
arsort($refer);
|
||||
break;
|
||||
case 'nat': // 自然排序
|
||||
natcasesort($refer);
|
||||
break;
|
||||
}
|
||||
foreach ($refer as $key => $val) {
|
||||
$resultSet[] = &$list[$key];
|
||||
}
|
||||
return $resultSet;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化字节大小
|
||||
* @param number $size 字节数
|
||||
* @param int $float 小数保留位数
|
||||
* @param string $delimiter 数字和单位分隔符
|
||||
* @return string 格式化后的带单位的大小
|
||||
*/
|
||||
function formatBytes($size, $float = 2, $delimiter = '')
|
||||
{
|
||||
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||
for ($i = 0; $size >= 1024 && $i < 5; $i++) $size /= 1024;
|
||||
|
||||
return round($size, $float) . $delimiter . $units[$i];
|
||||
}
|
||||
/**
|
||||
* 生成标准UUID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getUuid()
|
||||
{
|
||||
mt_srand((float) microtime() * 10000);
|
||||
$uuid = sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
|
||||
return $uuid;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断是否为空参数
|
||||
* @param mixed $parm
|
||||
* @return bool
|
||||
*/
|
||||
function is_empty_parm(&$parm)
|
||||
{
|
||||
return !(isset($parm) && '' !== $parm);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前账号openid
|
||||
* $openid wxapp_openid wechat_openid
|
||||
* @return string
|
||||
*/
|
||||
function get_client_openid($user_id, $openid)
|
||||
{
|
||||
return \think\facade\Db::name('user')->where('user_id', $user_id)->value($openid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 产生数字与字母混合随机字符串
|
||||
* @param int $len 数值长度,默认6位
|
||||
* @return string
|
||||
*/
|
||||
function get_randstr($len = 6)
|
||||
{
|
||||
$chars = [
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
||||
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
|
||||
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2',
|
||||
'3', '4', '5', '6', '7', '8', '9',
|
||||
];
|
||||
|
||||
$charsLen = count($chars) - 1;
|
||||
shuffle($chars);
|
||||
|
||||
$output = '';
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$output .= $chars[mt_rand(0, $charsLen)];
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* 产生随机数值
|
||||
* @param int $len 数值长度,默认8位
|
||||
* @return string
|
||||
*/
|
||||
function rand_number($len = 8)
|
||||
{
|
||||
$chars = str_repeat('123456789', 3);
|
||||
if ($len > 10) {
|
||||
$chars = str_repeat($chars, $len);
|
||||
}
|
||||
|
||||
$chars = str_shuffle($chars);
|
||||
return mb_substr($chars, 0, $len, 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能字符串模糊化
|
||||
* @param string $str 被模糊的字符串
|
||||
* @param int $len 模糊的长度
|
||||
* @return string
|
||||
*/
|
||||
function auto_hid_substr(string $str, $len = 3)
|
||||
{
|
||||
if (empty($str)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$sub_str = mb_substr($str, 0, 1, 'utf-8');
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$sub_str .= '*';
|
||||
}
|
||||
|
||||
if (mb_strlen($str, 'utf-8') <= 2) {
|
||||
$str = $sub_str;
|
||||
}
|
||||
|
||||
$sub_str .= mb_substr($str, -1, 1, 'utf-8');
|
||||
return $sub_str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多维数组,根据某个特定字段过滤重复值
|
||||
* @return array
|
||||
*/
|
||||
function assoc_unique($arr, $key) {
|
||||
$tmp_arr = array();
|
||||
foreach ($arr as $k => $v) {
|
||||
if (in_array($v[$key], $tmp_arr)) {//搜索$v[$key]是否在$tmp_arr数组中存在,若存在返回true
|
||||
unset($arr[$k]);
|
||||
} else {
|
||||
$tmp_arr[] = $v[$key];
|
||||
}
|
||||
}
|
||||
sort($arr); //sort函数对数组进行排序
|
||||
return $arr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function getDom($url)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
$html = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$dom = new DOMDocument();
|
||||
@$dom->loadHTML($html);
|
||||
|
||||
return $dom;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 过滤标点符号并提取词语
|
||||
*
|
||||
* @param array $result 分词结果
|
||||
* @return array 过滤后的词汇
|
||||
*/
|
||||
function filterAndExtractWords(array $result)
|
||||
{
|
||||
// 定义要过滤掉的符号,包括标点符号和其他符号
|
||||
$pattern = '/[\p{P}\p{S}]/u';
|
||||
|
||||
// 提取词语、过滤掉符号并删除空的词语
|
||||
$filteredWords = array();
|
||||
foreach ($result as $item) {
|
||||
$word = preg_replace($pattern, '', $item[0]);
|
||||
// 只保留非空的词汇
|
||||
if (!empty($word)) {
|
||||
$filteredWords[] = $word;
|
||||
}
|
||||
}
|
||||
|
||||
return $filteredWords;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 高亮显示关键词
|
||||
* @param string $title 原始标题
|
||||
* @param string $searchTitle 搜索标题
|
||||
* @return string 带有高亮的标题
|
||||
*/
|
||||
function highlightKeywords($title, $searchTitle)
|
||||
{
|
||||
// 使用正则表达式来高亮所有关键词
|
||||
foreach ($searchTitle as $keyword) {
|
||||
$title = preg_replace('/(' . preg_quote($keyword, '/') . ')/i', '<span>$1</span>', $title);
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是哪个网盘
|
||||
* @return array
|
||||
*/
|
||||
function determineIsType($url) {
|
||||
// 判断 $url 中包含的域名并返回对应的 is_type
|
||||
if (strpos($url, 'alipan.com') !== false) {
|
||||
return 1;
|
||||
} elseif (strpos($url, 'baidu.com') !== false) {
|
||||
return 2;
|
||||
} elseif (strpos($url, 'uc.cn') !== false) {
|
||||
return 3;
|
||||
} elseif (strpos($url, 'xunlei.com') !== false) {
|
||||
return 4;
|
||||
} else {
|
||||
// 默认值是夸克网盘,返回 0
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 网络资源搜索源一
|
||||
* @return array
|
||||
*/
|
||||
|
||||
function source1($title)
|
||||
{
|
||||
$d = [];
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
/**
|
||||
* 网络资源搜索源二(5条线路)
|
||||
* 每个线路只取第一个
|
||||
* @return array
|
||||
*/
|
||||
function source2($title)
|
||||
{
|
||||
$urlDefault = "http://s.kkkob.com"; //http://s.kkkob.com
|
||||
$url2 = [];
|
||||
$res = curlHelper($urlDefault."/v/api/getToken", "GET")['body'];
|
||||
$res = json_decode($res, true);
|
||||
$token = $res['token'] ?? '';
|
||||
if(empty($token)){
|
||||
return $url2;
|
||||
}
|
||||
|
||||
$urlData = array(
|
||||
'name' => $title,
|
||||
'token' => $token
|
||||
);
|
||||
$urlHeader = array('Content-Type: application/json');
|
||||
// 定义正则表达式模式
|
||||
$pattern = '/https:\/\/pan\.quark\.cn\/[^\s]*/';
|
||||
|
||||
//线路2
|
||||
$res = curlHelper($urlDefault."/v/api/getJuzi", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if (!empty($res['list'] ?? [])) {
|
||||
foreach ($res['list'] as $key => $value) {
|
||||
if(preg_match($pattern, $value['answer'], $matches)){
|
||||
// 匹配成功,$matches[0] 包含了匹配到的链接
|
||||
$link = $matches[0];
|
||||
$url2[] = [
|
||||
'title' => preg_replace('/\s*[\((]?(夸克)?[\))]?\s*/u', '', $value['question']),
|
||||
'url' => $link
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($url2)){
|
||||
return $url2;
|
||||
}
|
||||
|
||||
//线路4
|
||||
$res = curlHelper($urlDefault."/v/api/getXiaoyu", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if (!empty($res['list'] ?? [])) {
|
||||
foreach ($res['list'] as $key => $value) {
|
||||
if(preg_match($pattern, $value['answer'], $matches)){
|
||||
// 匹配成功,$matches[0] 包含了匹配到的链接
|
||||
$link = $matches[0];
|
||||
$url2[] = [
|
||||
'title' => preg_replace('/\s*[\((]?(夸克)?[\))]?\s*/u', '', $value['question']),
|
||||
'url' => $link
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// //线路1
|
||||
// $res = curlHelper($urlDefault."/v/api/search", "POST", json_encode($urlData), $urlHeader)['body'];
|
||||
// $res = json_decode($res, true);
|
||||
// if (!empty($res['list'] ?? [])) {
|
||||
// $item = $res['list'][0];
|
||||
// // 使用正则表达式进行匹配
|
||||
// if (preg_match($pattern, $item['answer'], $matches)) {
|
||||
// // 匹配成功,$matches[0] 包含了匹配到的链接
|
||||
// $link = $matches[0];
|
||||
// $url2[] = [
|
||||
// 'title' => '①'.preg_replace('/\s*[\((]?(夸克)?[\))]?\s*/u', '', $item['question']),
|
||||
// 'url' => $link
|
||||
// ];
|
||||
// }
|
||||
// }
|
||||
|
||||
return $url2;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 网络资源搜索源三
|
||||
* @return array
|
||||
*/
|
||||
function source3($title)
|
||||
{
|
||||
$url3 = [];
|
||||
$url = 'https://www.qileso.com/tag/quark?s='.$title;
|
||||
$dom = getDom($url);
|
||||
$finder = new DomXPath($dom);
|
||||
// 查询class值为list-group post-list mt-3的元素
|
||||
$nodes =$finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' list-group post-list mt-3 ')]//a");
|
||||
|
||||
if ($nodes->length > 0) {
|
||||
$firstNode =$nodes->item(0);
|
||||
$href = $firstNode->getAttribute('href');
|
||||
|
||||
$dom = getDom($href);
|
||||
$finder = new DomXPath($dom);
|
||||
|
||||
// 查询包含特定前缀的href属性的所有<a>标签
|
||||
$nodes =$finder->query("//@*[starts-with(., 'https://pan.quark.cn/s/')]");
|
||||
if ($nodes->length > 0) {
|
||||
$firstNode =$nodes->item(0);
|
||||
$value = $firstNode->value;
|
||||
|
||||
// 查询<title>元素
|
||||
$nodes =$finder->query("/html/head/title");
|
||||
|
||||
if ($nodes->length > 0) {
|
||||
$titleNode =$nodes->item(0);
|
||||
$titleText =$titleNode->textContent;
|
||||
// 去掉 " - 奇乐搜" 部分
|
||||
$title = preg_replace('/ - 奇乐搜|网盘|夸克/', '', $titleText);
|
||||
}
|
||||
|
||||
$url3[] = [
|
||||
'title' => '②'.$title,
|
||||
'url' => $value
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $url3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 网络资源搜索源四
|
||||
* @return array
|
||||
*/
|
||||
function source4($title)
|
||||
{
|
||||
$url = 'https://www.pansearch.me/search?keyword='.urlencode($title).'&pan=quark';
|
||||
$dom = getDom($url);
|
||||
$finder = new DomXPath($dom);
|
||||
|
||||
// 使用 XPath 查询选择具有特定类名的元素
|
||||
$nodes =$finder->query('//div[contains(concat(" ", normalize-space(@class), " "), " whitespace-pre-wrap ") and contains(concat(" ", normalize-space(@class), " "), " break-all ")]');
|
||||
|
||||
$results = [];
|
||||
foreach ($nodes as $node) {
|
||||
// 获取元素的内容,包括其子元素
|
||||
$content = $node->textContent;
|
||||
|
||||
// Initialize an associative array to store parsed data
|
||||
$parsedItem = [
|
||||
'title' => '',
|
||||
'url' => ''
|
||||
];
|
||||
|
||||
// Use regular expressions to extract the title and url
|
||||
if (preg_match('/名称:(.*?)\n\n描述:/s', $content, $titleMatch)) {
|
||||
$parsedItem['title'] = '「推荐」'.trim($titleMatch[1]);
|
||||
}
|
||||
|
||||
if (preg_match('/链接:(https:\/\/pan\.quark\.cn\/s\/[a-zA-Z0-9]+)/', $content, $urlMatch)) {
|
||||
$parsedItem['url'] = trim($urlMatch[1]);
|
||||
}
|
||||
|
||||
if ($parsedItem['title'] && $parsedItem['url']) {
|
||||
$results[] = $parsedItem;
|
||||
}
|
||||
|
||||
if (count($results) >= 3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
// 事件定义文件
|
||||
return [
|
||||
'bind' => [
|
||||
],
|
||||
|
||||
'listen' => [
|
||||
'AppInit' => [],
|
||||
'HttpRun' => [],
|
||||
'HttpEnd' => [],
|
||||
'LogLevel' => [],
|
||||
'LogWrite' => [],
|
||||
],
|
||||
|
||||
'subscribe' => [
|
||||
],
|
||||
];
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\index;
|
||||
|
||||
use think\App;
|
||||
use EasyWeChat\Factory;
|
||||
use app\model\Conf as ConfModel;
|
||||
use app\model\User as UserModel;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
abstract class QfShop
|
||||
{
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
// 初始化
|
||||
protected function initialize()
|
||||
{
|
||||
$this->confModel = new ConfModel();
|
||||
|
||||
$configs = $this->confModel->select()->toArray();
|
||||
$c = array_column($configs, 'conf_value', 'conf_key');
|
||||
config($c, 'qfshop');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// <?php
|
||||
// namespace app\index\controller;
|
||||
|
||||
// use app\index\QfShop;
|
||||
// use think\facade\View;
|
||||
|
||||
// class Error extends QfShop
|
||||
// {
|
||||
// public function __call($method, $args)
|
||||
// {
|
||||
// $error = $this->authorize();
|
||||
// if ($error) {
|
||||
// return $error;
|
||||
// }
|
||||
// View::assign('wechat', $this->wechat);
|
||||
// if (file_exists(app_path() . "/view/" . strtolower($this->request->controller()) . "/" . $method . ".html")) {
|
||||
// if (key_exists('callback', $args)) {
|
||||
// View::assign('callback', $args['callback']);
|
||||
// } else {
|
||||
// View::assign('callback', '/admin');
|
||||
// }
|
||||
// return View::fetch();
|
||||
// } else {
|
||||
// return 404;
|
||||
// }
|
||||
// }
|
||||
// public static function show($msg = null)
|
||||
// {
|
||||
// View::assign('msg', $msg);
|
||||
// return View::fetch("/error");
|
||||
// }
|
||||
// }
|
||||
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace app\index\controller;
|
||||
|
||||
use think\App;
|
||||
use think\facade\View;
|
||||
use think\facade\Request;
|
||||
use think\facade\Cache;
|
||||
use app\index\QfShop;
|
||||
use app\model\Source as SourceModel;
|
||||
use app\model\SourceCategory as SourceCategoryModel;
|
||||
|
||||
|
||||
class Index extends QfShop
|
||||
{
|
||||
|
||||
public function __construct(App $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->SourceModel = new SourceModel();
|
||||
$this->SourceCategoryModel = new SourceCategoryModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 首页
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$rankList = $this->SourceCategoryModel->field('name,image')->where([['status','=',0],['is_sys','=',1]])->order('sort desc')->select();
|
||||
$newList = [];
|
||||
|
||||
if(config("qfshop.ranking_type") == 0 && config("qfshop.home_new") == 0){
|
||||
//最新榜
|
||||
$map[] = ['status', '=', 1];
|
||||
$map[] = ['is_time', '=', 0];
|
||||
$map[] = ['is_delete', '=', 0];
|
||||
|
||||
$newList = $this->SourceModel->order(['create_time' => 'desc'])
|
||||
->field('title,create_time as time')
|
||||
->where($map)
|
||||
->limit(Config('qfshop.ranking_num') ?? 1)
|
||||
->select()->each(function($item,$key){
|
||||
$item['times'] = substr($item['time'], 5, 5);
|
||||
unset($item['time']);
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
View::assign('newList', $newList);
|
||||
View::assign('config', config("qfshop"));
|
||||
View::assign('rankList', $rankList);
|
||||
View::assign('fixed', 1);
|
||||
View::assign('category_id', 0);
|
||||
return View::fetch('/news/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 搜索列表
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
public function list($name,$page=1,$cate='')
|
||||
{
|
||||
$data['page_no'] = $page;
|
||||
$data['page_size'] = 40;
|
||||
$data['title'] = $name;
|
||||
$data['category_id'] = $cate;
|
||||
$list = $this->SourceModel->getList($data);
|
||||
|
||||
|
||||
$rankList = $this->SourceCategoryModel->field('name,image')->where([['status','=',0],['is_sys','=',1]])->order('sort desc')->select();
|
||||
|
||||
$category = $this->SourceCategoryModel->field('name,source_category_id as id')->where([['status','=',0]])->order('sort desc')->select();
|
||||
|
||||
|
||||
View::assign('rankList', $rankList);
|
||||
View::assign('category', $category);
|
||||
View::assign('list', $list);
|
||||
View::assign('config', config("qfshop"));
|
||||
View::assign('keyword', $data['title']);
|
||||
View::assign('page_size', $data['page_size']);
|
||||
View::assign('page_no', $data['page_no']);
|
||||
View::assign('category_id', $data['category_id']);
|
||||
return View::fetch('/news/list');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 详情
|
||||
* @param {*}
|
||||
* @return {*}
|
||||
*/
|
||||
public function detail($id)
|
||||
{
|
||||
if(empty($id)){
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
|
||||
$data['id'] = $id;
|
||||
$detail = $this->SourceModel->getDetail($data);
|
||||
|
||||
if(empty($detail)){
|
||||
return redirect('/');
|
||||
}
|
||||
|
||||
|
||||
$rankList = $this->SourceCategoryModel->field('name,image')->where([['status','=',0],['is_sys','=',1]])->order('sort desc')->select();
|
||||
|
||||
|
||||
View::assign('rankList', $rankList);
|
||||
View::assign('detail', $detail);
|
||||
View::assign('config', config("qfshop"));
|
||||
View::assign('category_id', 0);
|
||||
return View::fetch('/news/detail');
|
||||
}
|
||||
|
||||
|
||||
public function show()
|
||||
{
|
||||
$data = input('');
|
||||
$this->SourceModel = new SourceModel();
|
||||
|
||||
// 搜索条件
|
||||
$map = [];
|
||||
|
||||
$map[] = ['status', '=', 1];
|
||||
$map[] = ['is_time', '=', 0];
|
||||
|
||||
if(!empty($data['type'])){
|
||||
// 将 $data['type'] 转换为时间戳
|
||||
$dayStart = strtotime($data['type']);
|
||||
$dayEnd = $dayStart + 86400; // 86400 秒 = 24 小时
|
||||
|
||||
// 添加日期范围条件,只统计所选日期的记录
|
||||
$map[] = ['create_time', 'between', [$dayStart, $dayEnd]];
|
||||
View::assign('day', date('n月j日', $dayStart));
|
||||
|
||||
}else{
|
||||
// 获取今天的时间戳范围
|
||||
$todayStart = strtotime(date('Y-m-d'));
|
||||
$todayEnd = $todayStart + 86400; // 86400 秒 = 24 小时
|
||||
|
||||
// 添加日期范围条件,只统计今天的记录
|
||||
$map[] = ['create_time', 'between', [$todayStart, $todayEnd]];
|
||||
View::assign('day',date('n月j日'));
|
||||
}
|
||||
|
||||
|
||||
$result = $this->SourceModel->field('source_id as id,source_category_id,title,url,create_time as time,is_time')->where($map)->select()->each(function($item,$key){
|
||||
$item['times'] = substr($item['time'], 0, 10);
|
||||
unset($item['time']);
|
||||
return $item;
|
||||
})->toArray();
|
||||
|
||||
|
||||
View::assign('list', $result);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace app\index\controller;
|
||||
|
||||
use think\Response;
|
||||
use think\facade\Request;
|
||||
|
||||
use app\model\Source as SourceModel;
|
||||
|
||||
|
||||
class Sitemap
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
// 检查是否有缓存
|
||||
$sitemap = cache('sitemap');
|
||||
|
||||
if (!$sitemap) {
|
||||
$SourceModel = new SourceModel();
|
||||
|
||||
$map[] = ['status', '=', 1];
|
||||
$map[] = ['is_delete', '=', 0];
|
||||
$map[] = ['is_time', '=', 0];
|
||||
|
||||
$urls = $SourceModel->where($map)->field('source_id, update_time')->order('update_time', 'desc')->limit(10000)->select();
|
||||
|
||||
// 创建 XML 内容
|
||||
$xml = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
$xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
|
||||
|
||||
$xml .= '<url>';
|
||||
$xml .= '<loc>'.Request::domain().'</loc>'; // 网站 URL
|
||||
$xml .= '<lastmod>'.date('Y-m-d').'</lastmod>'; // 最后修改时间
|
||||
$xml .= '<changefreq>daily</changefreq>'; // 页面更新频率
|
||||
$xml .= '<priority>1.0</priority>'; // 优先级
|
||||
$xml .= '</url>';
|
||||
|
||||
|
||||
foreach ($urls as $url) {
|
||||
$xml .= '<url>';
|
||||
$xml .= '<loc>'.Request::domain().'/d/'.$url['source_id'].'.html</loc>';
|
||||
$xml .= '<lastmod>' . date('Y-m-d', strtotime($url['update_time'])) . '</lastmod>';
|
||||
$xml .= '<priority>0.8</priority>';
|
||||
$xml .= '</url>';
|
||||
}
|
||||
|
||||
$xml .= '</urlset>';
|
||||
|
||||
// 缓存 sitemap 1 小时 3600
|
||||
cache('sitemap', $xml, 86400);
|
||||
|
||||
$sitemap = $xml;
|
||||
}
|
||||
return Response::create($sitemap, 'xml')->header(['Content-Type' => 'application/xml']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
|
||||
use think\facade\Route;
|
||||
|
||||
|
||||
Route::get('s/<name>-<page?>-<cate?>','index/index/list',[],['name' => '.+', 'id' => '\d+', 'cate' => '\d+']);
|
||||
Route::get('d/:id','index/index/detail');
|
||||
Route::get('sitemap.xml', 'index/sitemap/index');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="footerBox">
|
||||
<div class="box">
|
||||
<p>{$config.footer_dec|raw}</p>
|
||||
<p>
|
||||
{$config.footer_copyright|raw}
|
||||
<a href="/sitemap.xml" target="_blank">网站地图</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,175 @@
|
||||
<script src="/static/index/js/vue.global.min.js"></script>
|
||||
<script src="/static/index/js/index.full.min.js"></script>
|
||||
<script src="/static/index/js/axios.min.js"></script>
|
||||
<script>
|
||||
const { createApp, ref, onMounted, onUnmounted } = Vue;
|
||||
const { ElButton, ElMessage } = ElementPlus;
|
||||
const app = createApp({
|
||||
setup() {
|
||||
// 定义响应式数据
|
||||
const elementOpacity = ref(0);
|
||||
const scrollThreshold = ref(150); // 动态设置的滚动阈值
|
||||
const keyword = ref('{$keyword??''}');
|
||||
const qcodeVisible = ref(false);
|
||||
const layerVisible = ref(false);
|
||||
const content = ref('');
|
||||
const load = ref(false)
|
||||
const drawer = ref(false)
|
||||
const rankList = ref([]);
|
||||
const rankDj = ref([]);
|
||||
const is_m = ref(0);
|
||||
const newList = ref([]);
|
||||
|
||||
|
||||
// 公共消息方法
|
||||
const showMessage = (message, type = 'info') => {
|
||||
ElMessage({
|
||||
message,
|
||||
type,
|
||||
plain: true,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// 滚动监听方法
|
||||
const handleScroll = () => {
|
||||
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
||||
elementOpacity.value = scrollTop >= scrollThreshold.value
|
||||
? Math.min((scrollTop - scrollThreshold.value) / 100, 1)
|
||||
: Math.max(1 - (scrollThreshold.value - scrollTop) / 100, 0);
|
||||
|
||||
const boxElement = document.querySelector('.listBox .screen .fixed .box');
|
||||
if (boxElement.style.display === 'block' && is_m.value) {
|
||||
boxElement.style.display = 'none'; // 隐藏元素
|
||||
}
|
||||
};
|
||||
|
||||
// 搜索按钮点击事件
|
||||
const searchBtn = () => {
|
||||
if (!keyword.value) {
|
||||
return showMessage('请输入你要搜索的内容~', 'error');
|
||||
}
|
||||
const currentUrl = window.location.href;
|
||||
const targetUrl = `/s/${keyword.value}.html`;
|
||||
if (currentUrl.includes('/s/') || currentUrl.includes('/d/')) {
|
||||
window.location.href = targetUrl;
|
||||
} else {
|
||||
window.open(targetUrl, '_blank');
|
||||
}
|
||||
};
|
||||
|
||||
// 保存按钮点击事件
|
||||
const saveBtn = async () => {
|
||||
if (!content.value) {
|
||||
return showMessage('请输入你想看的资源信息~', 'error');
|
||||
}
|
||||
if (load.value) return;
|
||||
|
||||
load.value = true;
|
||||
try {
|
||||
const response = await axios.post('/api/tool/feedback', { content: content.value });
|
||||
showMessage(response.data.message, response.data.code === 200 ? 'success' : 'error');
|
||||
if (response.data.code === 200) {
|
||||
layerVisible.value = false;
|
||||
content.value = '';
|
||||
}
|
||||
} finally {
|
||||
load.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const setnum = (num) => (num / 10000).toFixed(2) + 'W';
|
||||
|
||||
const goLink = (event,id) => {
|
||||
event.preventDefault();
|
||||
window.location.href = `/d/${id}.html`;
|
||||
}
|
||||
|
||||
const changeBtn = (e) => {
|
||||
const category_id = `{$category_id}`;
|
||||
if(category_id){
|
||||
window.location.href = `/s/${keyword.value}-${e}-${category_id}.html`;
|
||||
}else{
|
||||
window.location.href = `/s/${keyword.value}-${e}.html`;
|
||||
}
|
||||
};
|
||||
|
||||
const copyText = async(event,title,url,code) => {
|
||||
event.preventDefault();
|
||||
var text = '标题:'+title+'\n链接:'+url
|
||||
if (code) text += `\n提取码:${code}`;
|
||||
text += `\n由【${'{$config.app_name}'}${window.location.hostname}】供网盘分享链接`;
|
||||
|
||||
|
||||
try {
|
||||
// 优先使用 navigator.clipboard
|
||||
await navigator.clipboard.writeText(text);
|
||||
showMessage('复制成功', 'success');
|
||||
} catch (err) {
|
||||
// 如果 navigator.clipboard 失败,使用 document.execCommand 作为回退
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = text;
|
||||
textArea.style.position = 'fixed'; // 避免滚动
|
||||
textArea.style.opacity = 0;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
const successful = document.execCommand('copy');
|
||||
if (successful) {
|
||||
showMessage('复制成功', 'success');
|
||||
} else {
|
||||
throw new Error('复制失败');
|
||||
}
|
||||
} catch (err) {
|
||||
showMessage('复制失败,请手动复制', 'error');
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
}
|
||||
|
||||
const selectBtn = () => {
|
||||
const boxElement = document.querySelector('.listBox .screen .fixed .box');
|
||||
// 切换 display 属性,显示或隐藏
|
||||
if (boxElement.style.display === 'none' || boxElement.style.display === '') {
|
||||
boxElement.style.display = 'block'; // 显示
|
||||
} else {
|
||||
boxElement.style.display = 'none'; // 隐藏
|
||||
}
|
||||
}
|
||||
|
||||
const handleDeviceType = () => {
|
||||
const isMobile = window.matchMedia('(max-width: 768px)').matches;
|
||||
if (isMobile) {
|
||||
// 手机端的逻辑
|
||||
is_m.value = 1
|
||||
} else {
|
||||
// 电脑端的逻辑
|
||||
is_m.value = 0
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 组件挂载时添加滚动监听
|
||||
onMounted(() => {
|
||||
handleDeviceType();
|
||||
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
window.addEventListener('resize', handleDeviceType);
|
||||
});
|
||||
|
||||
// 组件卸载时移除滚动监听
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
window.removeEventListener('resize', handleDeviceType);
|
||||
});
|
||||
|
||||
// 返回数据和方法
|
||||
return { elementOpacity, scrollThreshold, keyword, searchBtn, rankList,newList, setnum, qcodeVisible, layerVisible, content, saveBtn, rankDj,goLink,changeBtn,copyText,drawer,selectBtn,is_m };
|
||||
}
|
||||
})
|
||||
.use(ElementPlus) // 使用 Element Plus
|
||||
.mount('#app'); // 挂载 Vue 实例
|
||||
</script>
|
||||
@@ -0,0 +1,71 @@
|
||||
<div class="headerBox">
|
||||
<div class="bg" {notempty name="fixed"}:style="{ opacity: elementOpacity }"{/notempty}></div>
|
||||
<div class="box">
|
||||
<a href="/" class="logoBox" {notempty name="fixed"}:style="{ opacity: elementOpacity }"{/notempty}>
|
||||
{notempty name="config.logo"}
|
||||
<img class="logo" src="{$config.logo}"></img>
|
||||
{/notempty}
|
||||
|
||||
{if condition="$config.app_name && $config.app_name_hide!=1"}
|
||||
<div class="title">{$config.app_name}</div>
|
||||
{/if}
|
||||
</a>
|
||||
<div class="search" {notempty name="fixed"}:style="{ opacity: elementOpacity }"{/notempty}>
|
||||
<input type="text" v-model="keyword" placeholder="输入关键字进行搜索" @keyup.enter="searchBtn" confirm-type="search" @confirm="searchBtn">
|
||||
<div class="btn" @click="searchBtn">
|
||||
<i class="iconfont icon-sousuo"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navs">
|
||||
{notempty name="config.qcode"}
|
||||
<div class="item" @click="qcodeVisible = true">加入群聊</div>
|
||||
{/notempty}
|
||||
{empty name="config.app_demand"}
|
||||
<div class="item" @click="layerVisible = true">提交需求</div>
|
||||
{/empty}
|
||||
<div class="btns" v-html="`{$config.app_links}`"></div>
|
||||
|
||||
<div class="iconfont icon-caidan" @click="drawer = true"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="headerKox"></div>
|
||||
|
||||
|
||||
<el-dialog
|
||||
v-model="qcodeVisible"
|
||||
width="300"
|
||||
>
|
||||
<img src="{$config.qcode}" style="width: 100%" />
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-model="layerVisible"
|
||||
width="300"
|
||||
>
|
||||
<div class="layerBox">
|
||||
<div class="vname">提交需求</div>
|
||||
<el-input
|
||||
v-model="content"
|
||||
placeholder="请输入你想看的资源信息~"
|
||||
type="textarea"
|
||||
resize='none'
|
||||
></el-input>
|
||||
<div class="vbtn" @click="saveBtn">提交</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="drawer"
|
||||
width="300"
|
||||
center
|
||||
>
|
||||
<div class="drawer">
|
||||
{notempty name="config.qcode"}
|
||||
<div class="item" @click="qcodeVisible = true">加入群聊</div>
|
||||
{/notempty}
|
||||
{empty name="config.app_demand"}
|
||||
<div class="item" @click="layerVisible = true">提交需求</div>
|
||||
{/empty}
|
||||
<div class="btns" v-html="`{$config.app_links}`"></div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
{notempty name="config.app_icon"}
|
||||
<link rel="icon" href="{$config.app_icon}" />
|
||||
{/notempty}
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no,maximum-scale=1.0">
|
||||
<title>{if condition="isset($detail) && $detail.title"}{$detail.title} - {$config.app_name}{else /}{$config.app_name}{notempty name="$config.app_title"} - {$config.app_title}{/notempty}{/if}</title>
|
||||
<meta name="keywords" content="{notempty name="detail"}{$detail.title},{/notempty}{$config.app_keywords}" />
|
||||
<meta name="description" content="{notempty name="detail"}{$detail.title} - {/notempty}{$config.app_description}" />
|
||||
<link rel="stylesheet" href="/static/index/css/index.min.css">
|
||||
<link rel="stylesheet" href="/static/index/css/app.css">
|
||||
<link rel="stylesheet" href="/static/index/css/m.css">
|
||||
|
||||
{$config.seo_statistics|raw}
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-color: {$config.home_color|default='#3e3e3e'};
|
||||
--theme-theme: {$config.home_theme|default='#133ab3'};
|
||||
--theme-background: {$config.home_background|default='#fafafa'};
|
||||
--theme-other_background: {$config.other_background|default='#ffffff'};
|
||||
}
|
||||
{$config.home_css}
|
||||
</style>
|
||||
@@ -0,0 +1,310 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr" lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#fff">
|
||||
<meta name="viewport" content="initial-scale=1, minimum-scale=1, width=device-width">
|
||||
<title>提示</title>
|
||||
<style>
|
||||
a {
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
body {
|
||||
--background-color: #fff;
|
||||
--error-code-color: var(--google-gray-700);
|
||||
--google-blue-100: rgb(210, 227, 252);
|
||||
--google-blue-300: rgb(138, 180, 248);
|
||||
--google-blue-600: rgb(26, 115, 232);
|
||||
--google-blue-700: rgb(25, 103, 210);
|
||||
--google-gray-100: rgb(241, 243, 244);
|
||||
--google-gray-300: rgb(218, 220, 224);
|
||||
--google-gray-500: rgb(154, 160, 166);
|
||||
--google-gray-50: rgb(248, 249, 250);
|
||||
--google-gray-600: rgb(128, 134, 139);
|
||||
--google-gray-700: rgb(95, 99, 104);
|
||||
--google-gray-800: rgb(60, 64, 67);
|
||||
--google-gray-900: rgb(32, 33, 36);
|
||||
--heading-color: var(--google-gray-900);
|
||||
--primary-button-fill-color-active: var(--google-blue-700);
|
||||
--primary-button-fill-color: var(--google-blue-600);
|
||||
--primary-button-text-color: #fff;
|
||||
--text-color: var(--google-gray-700);
|
||||
background: var(--background-color);
|
||||
color: var(--text-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
.icon {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
body.captive-portal,
|
||||
body.dark-mode-available,
|
||||
body.neterror,
|
||||
body.supervised-user-block,
|
||||
.offline body {
|
||||
--background-color: var(--google-gray-900);
|
||||
--error-code-color: var(--google-gray-500);
|
||||
--heading-color: var(--google-gray-500);
|
||||
--link-color: var(--google-blue-300);
|
||||
--primary-button-fill-color-active: rgb(129, 162, 208);
|
||||
--primary-button-fill-color: var(--google-blue-300);
|
||||
--primary-button-text-color: var(--google-gray-900);
|
||||
--text-color: var(--google-gray-500);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
button {
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
color: var(--primary-button-text-color);
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-size: .875em;
|
||||
margin: 0;
|
||||
padding: 8px 16px;
|
||||
transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
[dir='rtl'] button {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.ssl button {
|
||||
background: var(--primary-button-fill-color);
|
||||
}
|
||||
|
||||
button:active {
|
||||
background: var(--primary-button-fill-color-active);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
color: var(--heading-color);
|
||||
font-size: 1.6em;
|
||||
font-weight: normal;
|
||||
line-height: 1.25em;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 72px;
|
||||
margin: 0 0 40px;
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
box-sizing: border-box;
|
||||
font-size: 1em;
|
||||
line-height: 1.6em;
|
||||
margin: 14vh auto 0;
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#main-message>p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
margin-top: 51px;
|
||||
}
|
||||
|
||||
.nav-wrapper::after {
|
||||
clear: both;
|
||||
content: '';
|
||||
display: table;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.interstitial-wrapper {
|
||||
padding: 0 10%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
|
||||
button,
|
||||
[dir='rtl'] button {
|
||||
float: none;
|
||||
font-size: .825em;
|
||||
font-weight: 500;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
padding: 0 5%;
|
||||
}
|
||||
|
||||
|
||||
.nav-wrapper {
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 240px) and (max-width: 420px) and (min-height: 401px),
|
||||
(min-width: 421px) and (min-height: 240px) and (max-height: 560px) {
|
||||
body .nav-wrapper {
|
||||
background: var(--background-color);
|
||||
bottom: 0;
|
||||
box-shadow: 0 -22px 40px var(--background-color);
|
||||
left: 0;
|
||||
margin: 0 auto;
|
||||
max-width: 736px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
max-width: 736px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 420px) and (orientation: portrait),
|
||||
(max-height: 560px) {
|
||||
body {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
button,
|
||||
[dir='rtl'] button,
|
||||
button.small-link {
|
||||
font-family: Roboto-Regular, Helvetica;
|
||||
font-size: .933em;
|
||||
margin: 6px 0;
|
||||
transform: translatez(0);
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-bottom: 5.69vh;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
box-sizing: border-box;
|
||||
margin: 7vh auto 12px;
|
||||
padding: 0 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.interstitial-wrapper p {
|
||||
font-size: .95em;
|
||||
line-height: 1.61em;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 421px) and (min-height: 500px) and (max-height: 560px) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 10vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 400px) and (orientation:portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-bottom: 145px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 299px) {
|
||||
.nav-wrapper {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and (orientation: portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 7vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 10vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ssl .icon {
|
||||
background-image: -webkit-image-set(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAABAlBMVEUAAADcRTfcRDfdRET/gIDcRjr/ZmbjVTncRDfcRTfcRDfdRDzgSTncRDjeSDvcRTjbRDfbRDjeRzvcRjfbRjjcRTjcRTjcRTfdRTfcRDjdRTjcRTjbRDjbRTjbRTjbRTfcRjjdRDrcRjfbRTjZQzfcRDjZRDfZRzbWQzXXRDXXQzbXQzbWQjXYSDvWQjbbRDfOQDPSQTTUQjXCPDDNPzPJPjLGPTHVQjXMPzPRQTTWQjXLPzPDPDHYQzbAOzDTQTXHPTLIPjK8Oi++Oy/FPTHEPTHPQDTQQDTUQTXBPDDKPjK/OzC9Oi/////PQDPRQDS3OS66OS7TQTTEPDHXQjbMPjMBhLaWAAAAL3RSTlMA4tgPAhYFCcL98B4x9ie1+s49WICbqXNKZY3pjuqcgVdLZnL2qKg9zmXpjfontV8LANsAAAJrSURBVHhe7ZTnduIwFAY3ARIgBAg9vW1v173ROylby/u/yso2Fx3MNaxs9h/zAHM+Sfa8+M/s2LFjx+3tdjwH+/sHWxHVAerb8KSyANnUFkRXwLiK78llgJHJxRalwSMd11OGOeV4nsM9FO0dxhJdw4LrOJ6jYy46PoohqgEHatE9JViiFNWTPIElTpIRRXcQ4C6aJ3EJAS4TkUQXsMJFFE++CCsU8xFEBSAoiHsaQNIQ7yuQCFe3DiHUhftKIlzdKoRSFe0r8sXDAkSoumkIigYaIOkIfeWi56EESFm8r1w0fFIl4epWgBA9qOMpmirCfeWijtoa9WSx6taAELFBRl/vilS3BJRIbRk9/VFTsLrifUXRuNfXLU0y/7m6p0CKxqN+v6lJU/k3eJxu7Os5LWKDHi1tYstKG1zON1X3DGiRMR80Mx3fdCbc1+bQe3o2SJrYXcV0fFMxL9xXiz0987BBtux65qaCeF8lHCR3FabBTQ3xvk4M1yN5B/Mw2+urew8hTP1BM38Qnu5evK8gMw+7IcfH9E3ZlEBfMSO//Kf35+Cm6ua+rhbSYDeEa9CUyW3qK1HIjj5DBz8dWd0bWCd6Ult/uMPEr+BmbV/JHrVG/a9MsEybV5fsK50R3frmBFXtCtVXmt73H4PhQ4t9k9rkJ55tYXwZrO4rCEUfPHfUEcuaZC/umw97TfaVpslu2tCb2lRWnBlKFtf+huwrjaa6Pxv7RfgW7nubJPtKI/X0puQO4k/Pfe/ovtLY7KbxVwve0/sE3VeaLosIbkEDvt8Hoq/hKGwQYvoq5OMnoq/hLAbgc/FVn33PX7pAfE5QHR6fAAAAAElFTkSuQmCC) 1x,
|
||||
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAABTVBMVEUAAADcRDf/ZmbcRjrjVTn/gIDdRETdRDzZQzbXQzXWQzbXQjbWQzXZRDbbRDnWQjXWQzXYSDvbRTjcRTjbRTfcRjfcRTjcRTjdRjncRTfdRTndRTfdRDrbRTjcRDnbRDfbRDjbRjfcRjfbRTjcRTjdRTjbRjjcRTjcRDjcRjncRTncRTndRDnbRTjcRDfZQzbcRTfgSTncRDfcRjjZQzjcRTfVRDbcRDjcRDjWQzXeRzvbRDjXRDXXQzbXQzbbRDfeSDvWQjbVQjXIPjLOQDPXQjbCPDDNPzPUQTXRQTS5OS7QQDTUQjW3OS7SQTTPQDTFPDHJPjK2OC26OS7HPjHOPzPLPjLMPjPRQDTGPDHTQTTEPTHLPzPGPTG7Oi/HPTLKPjLTQTXYQza9Oi/MPzPFPTHDPDHBPDC/OzC+Oy+8Oi/AOzDWQjX////bRDd3undHAAAAQnRSTlMA2AUWCQIPHj39wvbO8DH64ifqqYFmtrVMc1lKS5x0nY6PWKqbjYDpZXWCZ1py8Jv9McJXV+KA9qioPc5l6Y36J7VmcHe8AAAFWUlEQVR4XuzWS4rCQBSG0euz56ISgiaEjHwgGhAhDnRF3/6HDY1Ia5WPjP4a3LOKY28555xzzjnnnHPOuSyzpPR7vb6lZAUrS8hgB7uBpaMEKC0Zhz3A/mCpaPjTWCK23GwtCcMjN8ehpWDN3doS8HPi7vRjejX/1CbX8qA1sdGZB+eRaW14sjGp8YQnk7EpVQQqE7peCFyupjMnYm4yGVGZ7q1EyTZbEEche2uUbLMlL5W6t4Zkm22Ikm02561c89aQbLNTPpgq3hqSbbbmo1r41rhW8NaAaLMzvjITvDUg2WzFlyrBWwOCzc6Jkm12QQcL3Vtlmy3opFC9VbbZJR0tNW+Vbbahs0b41rhc8FbVZqdEyTb724t5/bYNA3G4e+80NYI0gGFkvaR779KKZUWuFKe7nlIsT5X//2M5VMZiZB9DQj74xW8ffrwjP90Mb/07Vf5CbXYJg0BtO4toKS9vhYHGY1vDZg28FQY6tBZls8tYBehwNLTyt1nhrTDQaDQcWAux2SJWAxpOBpWMWSvm4q0w0Gg4nFQqFTd/m72HlYBYQJV+w83bZu9jRaDJYEB4osjJ02aFt8JASUBRq+PlarMrWBGI8lQajVanXA5kopUcvBUEGrCAWhSoXs3PZtewKhA/MMbTbcpEa7l4KwwURZSHANnVnGz2CVYGmg6oZ1u1XGy2hNWBCA8BogE1m7Zl+ShNVMrdW2Wg/v+Amr2eRYCcGLBZU2+FgcSBESDfdZxdwGbNvBUGihKgnk1OjPAEwS5gsybeCgNNdTQLyAtqtRCwWQNvhYH4ndjtNnlAnlet1uIQsFl9b4WBpgNyaUCEJ45DwGa1vRUGanU6nMcmB+ZSnlosES3nvm/tUpGm1tFPd5DDAyKFBJGpzRaxSjW5J0o8/MAQ4ZEyKua/b+0Np175blMERDuaECFBZGqzBaxY9iAjIMbDK01U0OVZxcplE6BIjLzFRixgQDwflCJaXcC+1ToKyOYHFvCOljPiNmvurTBRI+oQoGTk2Z1YQyIeiWhlEftWnx8Yf8RcyiMCEkyhic2u4xOWSw9MBBQENTQFI83a+iL2rdgpJ1rms45mByYzhbDNwt6qTtTlQC7r6FT/CLRQ02ZLWKc8OmK+LzooCykhKpl4q7p+7B/d0SjNggRbqGOzm1gPqL3PX3niZakOQsenf1PDWzWAxr+JBtEDQxnnJTISNmvurfBK75t45bORBNGSobcqb9DqBCjdQOl5E370xthbYaDRiIjRDxKQwJk9a+o2u431gYZERBo/kcBIfvJ/TrSt6K1b+kDUHMkra2V3j5zRlprNbmADILbQ65S/z2ggyY82zL0VXsdQnnLdhSOKQzWbLWADIMpDgOrd3q958QiigrG3wusYzmNbXmY4sh+tangrVJ2Dgy97X9v0CmILzzIHcj3ZPTL+h6DN7mhYR5nxHI4mtKNbLCAmaX9QDDKFO6C36hDttcdJQFGLeTWRIupocGOj62cBb9WqesLTFwfm000MQgqz9lDLW+Hve35HM9Fnqw9HetBkNsF6+Yaet8Jf0+xbka0XbYspSMIg+5D8/8psnqdYv3qso1vsS9Hy6SaGQ6AYHP9ngLdqllVpiIB8RygRQjGEdOsc4K26RGzk6YTxjhbDDdzXcfwC8Fbd8glPnR4Y62gBAM/a1WybfYVNyyUBiZFPXYCAH70GvFW7nFRHH7EgyI8uAd6qXZ7NAqoilG6ZKuBH184D3qpdAQlIWp0p9dE7wFv1q8Y6+njLoPl+9P4C4K0GRKSjgTyywvoAeKtBxVWU6YhorovcvA14q0HtouwU0Fw/+jzN8w/cQ/zg6ug2/QAAAABJRU5ErkJggg==) 2x);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body id="body" class="ssl extended-reporting-has-checkbox">
|
||||
<div class="interstitial-wrapper">
|
||||
<div id="main-content">
|
||||
<div class="icon" id="icon"></div>
|
||||
<div id="main-message">
|
||||
<h1>提示</h1>
|
||||
<p>{$msg}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-wrapper">
|
||||
<a href="javascript:history.go(-1);"><button id="primary-button">好的,我知道了</button></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
html {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: system-ui, PingFang SC, STHeiti, sans-serif;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: system-ui, PingFang SC, STHeiti, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/assets/uni.4906e6f8.css">
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title>心悦搜剧-免费分享百万级网盘资源,致力打造顶尖网盘搜索引擎,让您畅享资源无忧!</title>
|
||||
<meta name="keywords" content="心悦搜剧、短剧搜索、影视资源、在线短剧">
|
||||
<meta name="description" content="免费分享百万级网盘资源,致力打造顶尖网盘搜索引擎,让您畅享资源无忧!">
|
||||
<link rel="icon" href="/assets/logo-DQLPqAxx.png" />
|
||||
<script src="./static/config.js"></script>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
<script type="module" crossorigin src="/assets/index-CICgbd-2.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BLVVqZ0m.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
|
||||
<script>LA.init({id:"3HsdT1GaTQzE091Y",ck:"3HsdT1GaTQzE091Y",hashMode:true})</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h4>【{$day} | 短剧每日更新】</h4>
|
||||
{volist name="list" id="vo"}
|
||||
{$key+1}、{$vo.title}<br/>
|
||||
{/volist}
|
||||
<br/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,123 @@
|
||||
{include file="common/header"}
|
||||
</head>
|
||||
<body>
|
||||
<div class="headBg" style="background-image: url({$config.home_bg});"></div>
|
||||
<div id="app" v-cloak>
|
||||
{include file="common/head"}
|
||||
<div class="searchBox searchDetail">
|
||||
<div class="search">
|
||||
<input type="text" v-model="keyword" placeholder="输入关键字进行搜索" @keyup.enter="searchBtn" confirm-type="search" @confirm="searchBtn">
|
||||
<div class="btn" @click="searchBtn">
|
||||
<i class="iconfont icon-sousuo"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="listBox detailBox">
|
||||
<div class="left">
|
||||
<h3>详情</h3>
|
||||
<div class="box details">
|
||||
{notempty name="detail.vod_pic"}
|
||||
<div class="pic">
|
||||
<img src="{$detail.vod_pic}" />
|
||||
</div>
|
||||
{/notempty}
|
||||
<div class="title">{$detail.title}</div>
|
||||
<div class="cat">
|
||||
<div class="l">资源分类</div>
|
||||
<div class="r">
|
||||
{if condition="$detail.category && $detail.category.name"}
|
||||
{$detail.category.name}
|
||||
{else /}
|
||||
其它
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="cat">
|
||||
<div class="l">资源描述</div>
|
||||
<div class="r">
|
||||
{if condition="$detail.vod_content"}
|
||||
{$detail.vod_content}
|
||||
{else /}
|
||||
-
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="cat">
|
||||
<div class="l">更新时间</div>
|
||||
<div class="r">{$detail.times}</div>
|
||||
</div>
|
||||
<div class="cat">
|
||||
<div class="l">资源类型</div>
|
||||
<div class="r">
|
||||
<img src="/static/index/images/{$detail.is_type}.png" class="icon" />
|
||||
{if condition="$detail.is_type==1"}
|
||||
<span>阿里云盘</span>
|
||||
{elseif condition="$detail.is_type==2"/}
|
||||
<span>百度网盘</span>
|
||||
{elseif condition="$detail.is_type==3"/}
|
||||
<span>UC网盘</span>
|
||||
{elseif condition="$detail.is_type==4"/}
|
||||
<span>迅雷网盘</span>
|
||||
{else /}
|
||||
<span>夸克网盘</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="cat">
|
||||
<div class="l">资源地址</div>
|
||||
<div class="r">
|
||||
<a href="{$detail.url}" target="_blank">{$detail.url}</a>
|
||||
</div>
|
||||
</div>
|
||||
{notempty name="detail.code"}
|
||||
<div class="cat">
|
||||
<div class="l">提取码</div>
|
||||
<div class="r" style="color: #FF3F3D;">{$detail.code}</div>
|
||||
</div>
|
||||
{/notempty}
|
||||
<div class="btns">
|
||||
<div class="btn btnCol" @click.stop="copyText($event,'{$detail.title}','{$detail.url}','{$detail.code}')"><i class="iconfont icon-fenxiang1"></i>复制分享</div>
|
||||
<a href="{$detail.url}" target="_blank" class="btn"><i class="iconfont icon-yun_o"></i>立即访问</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<block v-for="(item,index) in rankList" :key="index">
|
||||
<div class="nav">
|
||||
<img :src="item.image" v-if="item.image">
|
||||
{{item.name}}
|
||||
</div>
|
||||
<div class="box" v-if="item.list && item.list.length>0">
|
||||
<div class="list">
|
||||
<a :href="'/s/'+vo.title+'.html'" v-for="(vo,i) in item.list" :key="i" class="item" v-show="i<5">
|
||||
<p>
|
||||
<span>{{i+1}}</span>
|
||||
{{vo.title}}
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</block>
|
||||
</div>
|
||||
</div>
|
||||
{include file="common/foot"}
|
||||
</div>
|
||||
{include file="common/footer"}
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
if(!app.is_m){
|
||||
app.rankList = JSON.parse('<?php echo json_encode($rankList, JSON_UNESCAPED_UNICODE); ?>');
|
||||
for (const item of app.rankList) {
|
||||
axios.get('/api/tool/ranking',{
|
||||
params: {
|
||||
channel: item.name,
|
||||
is_m: app.is_m
|
||||
}
|
||||
})
|
||||
.then(function (res) {
|
||||
item.list = res.data.data
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,113 @@
|
||||
{include file="common/header"}
|
||||
</head>
|
||||
<body>
|
||||
<div class="headBg" style="background-image: url({$config.home_bg});"></div>
|
||||
<div id="app" v-cloak>
|
||||
{include file="common/head"}
|
||||
<div class="homeBox searchBox">
|
||||
<div class="box">
|
||||
<div class="logoBox">
|
||||
{notempty name="config.logo"}
|
||||
<img class="logo" src="{$config.logo}"></img>
|
||||
{/notempty}
|
||||
{if condition="$config.app_name && $config.app_name_hide!=1"}
|
||||
<span class="title">{$config.app_name}</span>
|
||||
{/if}
|
||||
</div>
|
||||
{notempty name="config.app_subname"}
|
||||
<div class="subTitle">{$config.app_subname}</div>
|
||||
{/notempty}
|
||||
<div class="search">
|
||||
<input type="text" v-model="keyword" placeholder="输入关键字进行搜索" @keyup.enter="searchBtn" confirm-type="search" @confirm="searchBtn">
|
||||
<div class="btn" @click="searchBtn">
|
||||
<i class="iconfont icon-sousuo"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="home {if $config.ranking_type != 1}homeNO{/if}">
|
||||
<div class="block" v-if="newList.length>0">
|
||||
<div class="nav">
|
||||
{notempty name="config.home_new_img"}
|
||||
<img src="{$config.home_new_img}"></img>
|
||||
{/notempty}
|
||||
最新更新
|
||||
</div>
|
||||
<div class="content">
|
||||
{if $config.ranking_type == 1 }
|
||||
<div class="list">
|
||||
<a :href="'/s/'+vo.title+'.html'" target="_blank" class="item" v-for="(vo,i) in newList" :key="i">
|
||||
<div class="img">
|
||||
<img :src="vo.src" />
|
||||
<span>Loading...</span>
|
||||
</div>
|
||||
<p>{{vo.title}}</p>
|
||||
</a>
|
||||
</div>
|
||||
{else /}
|
||||
<div class="list">
|
||||
<a :href="'/s/'+vo.title+'.html'" target="_blank" class="item" v-for="(vo,i) in newList" :key="i">
|
||||
<p>
|
||||
<span>{{i+1}}</span>
|
||||
{{vo.title}}
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="block" v-for="(item,index) in rankList" :key="index">
|
||||
<div class="nav">
|
||||
<img :src="item.image" v-if="item.image">
|
||||
{{item.name}}
|
||||
</div>
|
||||
<div class="content">
|
||||
{if $config.ranking_type == 1 }
|
||||
<div class="list">
|
||||
<a :href="'/s/'+vo.title+'.html'" target="_blank" class="item" v-for="(vo,i) in item.list" :key="i">
|
||||
<div class="img">
|
||||
<img :src="vo.src" />
|
||||
<span>Loading...</span>
|
||||
</div>
|
||||
<p>{{vo.title}}</p>
|
||||
</a>
|
||||
</div>
|
||||
{else /}
|
||||
<div class="list">
|
||||
<a :href="'/s/'+vo.title+'.html'" target="_blank" class="item" v-for="(vo,i) in item.list" :key="i">
|
||||
<p>
|
||||
<span>{{i+1}}</span>
|
||||
{{vo.title}}
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{include file="common/foot"}
|
||||
</div>
|
||||
{include file="common/footer"}
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
app.newList = JSON.parse('<?php echo json_encode($newList, JSON_UNESCAPED_UNICODE); ?>');
|
||||
let num = '{$config.ranking_m_num}';
|
||||
if(app.is_m){
|
||||
app.newList = app.newList.slice(0, num);
|
||||
}
|
||||
app.rankList = JSON.parse('<?php echo json_encode($rankList, JSON_UNESCAPED_UNICODE); ?>');
|
||||
for (const item of app.rankList) {
|
||||
axios.get('/api/tool/ranking',{
|
||||
params: {
|
||||
channel: item.name,
|
||||
is_m: app.is_m
|
||||
}
|
||||
})
|
||||
.then(function (res) {
|
||||
item.list = res.data.data
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,121 @@
|
||||
{include file="common/header"}
|
||||
</head>
|
||||
<body>
|
||||
<div class="headBg" style="background-image: url({$config.home_bg});"></div>
|
||||
<div id="app" v-cloak>
|
||||
{include file="common/head"}
|
||||
<div class="searchBox searchList">
|
||||
<div class="search">
|
||||
<div class="select" @click="selectBtn">
|
||||
{if condition="$category_id == ''"}全部{/if}
|
||||
{foreach $category as $key=>$vo }
|
||||
{if condition='$category_id == $vo.id'}{$vo.name}{/if}
|
||||
{/foreach}
|
||||
<i class="iconfont icon-xiala" style="font-size: 3vw"></i>
|
||||
</div>
|
||||
<input type="text" v-model="keyword" placeholder="输入关键字进行搜索" @keyup.enter="searchBtn" confirm-type="search" @confirm="searchBtn">
|
||||
<div class="btn" @click="searchBtn">
|
||||
<i class="iconfont icon-sousuo"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="listBox">
|
||||
<div class="screen">
|
||||
<div class="fixed">
|
||||
<h3>筛选</h3>
|
||||
<div class="box">
|
||||
<a href="/s/{$keyword}.html" class="{eq name="category_id" value=""}active{/eq}">全部</a>
|
||||
{foreach $category as $key=>$vo }
|
||||
<a href="/s/{$keyword}-1-{$vo.id}.html" class="{if condition='$category_id == $vo.id'}active{/if}">{$vo.name}</a>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="left">
|
||||
<h3>为您找到【<span>{$keyword}</span>】相关资源<span> {$list.total_result} </span>条</h3>
|
||||
<div class="box">
|
||||
{if condition="$list.total_result>0"}
|
||||
<div class="list">
|
||||
{foreach $list.items as $key=>$vo }
|
||||
<a class="item" target="_blank" href="{$vo.url}">
|
||||
<div class="title">
|
||||
{$vo.name|raw}
|
||||
</div>
|
||||
<div class="type time">{$vo.times}</div>
|
||||
<div class="type">
|
||||
{if condition="$vo.is_type==1"}
|
||||
<span>来源:阿里云盘</span>
|
||||
{elseif condition="$vo.is_type==2"/}
|
||||
<span>来源:百度网盘</span>
|
||||
{elseif condition="$vo.is_type==3"/}
|
||||
<span>来源:UC网盘</span>
|
||||
{elseif condition="$vo.is_type==4"/}
|
||||
<span>来源:迅雷网盘</span>
|
||||
{else /}
|
||||
<span>来源:夸克网盘</span>
|
||||
{/if}
|
||||
{notempty name="vo.code"}
|
||||
<span>提取码:<span>{$vo.code}</span></span>
|
||||
{/notempty}
|
||||
</div>
|
||||
<div class="btns">
|
||||
<div class="btn" @click.stop="copyText($event,'{$vo.title}','{$vo.url}','{$vo.code}')"><i class="iconfont icon-fenxiang1"></i>复制分享</div>
|
||||
<div class="btn" @click.stop="goLink($event,'{$vo.id}')"><i class="iconfont icon-fangwen"></i>查看详情</div>
|
||||
<div class="btn">
|
||||
<img src="/static/index/images/{$vo.is_type}.png" class="icon" />
|
||||
立即访问
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
{/foreach}
|
||||
</div>
|
||||
<div class="page">
|
||||
{notempty name="list.total_result"}
|
||||
<el-pagination background layout="prev, pager, next" :pager-count="3" :default-current-page="{$page_no}" :default-page-size="{$page_size}" :total="{$list.total_result}" @change="changeBtn"></el-pagination>
|
||||
{/notempty}
|
||||
</div>
|
||||
{else /}
|
||||
<el-empty style="margin-top: 10%;" :image-size="200" image="{$config.search_bg??''}" description="{$config.search_tips|default='未找到,可换个关键词尝试哦~'}"></el-empty>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<block v-for="(item,index) in rankList" :key="index">
|
||||
<div class="nav">
|
||||
<img :src="item.image" v-if="item.image">
|
||||
{{item.name}}
|
||||
</div>
|
||||
<div class="box" v-if="item.list && item.list.length>0">
|
||||
<div class="list">
|
||||
<a :href="'/s/'+vo.title+'.html'" v-for="(vo,i) in item.list" :key="i" class="item" v-show="i<5">
|
||||
<p>
|
||||
<span>{{i+1}}</span>
|
||||
{{vo.title}}
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</block>
|
||||
</div>
|
||||
</div>
|
||||
{include file="common/foot"}
|
||||
</div>
|
||||
{include file="common/footer"}
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
// if(!app.is_m){
|
||||
app.rankList = JSON.parse('<?php echo json_encode($rankList, JSON_UNESCAPED_UNICODE); ?>');
|
||||
for (const item of app.rankList) {
|
||||
axios.get('/api/tool/ranking',{
|
||||
params: {
|
||||
channel: item.name,
|
||||
is_m: app.is_m
|
||||
}
|
||||
})
|
||||
.then(function (res) {
|
||||
item.list = res.data.data
|
||||
})
|
||||
}
|
||||
// }
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
// 全局中间件定义文件
|
||||
return [
|
||||
// 跨域请求支持
|
||||
\think\middleware\AllowCrossDomain::class,
|
||||
// 全局请求缓存
|
||||
// \think\middleware\CheckRequestCache::class,
|
||||
// 多语言加载
|
||||
// \think\middleware\LoadLangPack::class,
|
||||
// Session初始化
|
||||
\think\middleware\SessionInit::class
|
||||
];
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Access extends QfShop
|
||||
{
|
||||
/**
|
||||
* 创建一个新的授权
|
||||
*
|
||||
* @param [int] AdminID
|
||||
* @param [plat] 授权平台
|
||||
* @return 授权信息|false
|
||||
*/
|
||||
public function createAccess($access_admin, $access_plat)
|
||||
{
|
||||
//将该平台下所有授权记录标记为失效
|
||||
// $this->where([
|
||||
// "access_admin" => $access_admin,
|
||||
// "access_plat" => $access_plat
|
||||
// ])->update(['access_status' => 1]);
|
||||
//生成一个新的Access_token
|
||||
$access_token = sha1(time()) . rand(100000, 99999) . sha1(time());
|
||||
$access_id = $this->insertGetId([
|
||||
"access_admin" => $access_admin,
|
||||
"access_plat" => $access_plat,
|
||||
"access_token" => $access_token,
|
||||
"access_ip" => request()->ip(),
|
||||
"access_createtime" => time(),
|
||||
"access_updatetime" => time()
|
||||
]);
|
||||
$access = $this->where("access_id", $access_id)->find();
|
||||
return $access ?? false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Admin extends QfShop
|
||||
{
|
||||
/**
|
||||
* 用户登录
|
||||
*
|
||||
* @param string 帐号
|
||||
* @param string 密码
|
||||
* @return void
|
||||
*/
|
||||
public function login($admin_account, $admin_password)
|
||||
{
|
||||
$admin = $this->where([
|
||||
"admin_account" => $admin_account,
|
||||
])->find();
|
||||
if ($admin) {
|
||||
//判断密码是否正确
|
||||
$salt = $admin['admin_salt'];
|
||||
$password = $admin['admin_password'];
|
||||
if ($password != encodePassword($admin_password, $salt)) {
|
||||
return false;
|
||||
}
|
||||
return $admin->toArray() ?? false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getListByPage($maps, $order = null, $field = "*")
|
||||
{
|
||||
$resource = $this->view('admin', $field)->view('group', '*', 'group.group_id = admin.admin_group', 'left');
|
||||
foreach ($maps as $map) {
|
||||
switch (count($map)) {
|
||||
case 1:
|
||||
$resource = $resource->where($map[0]);
|
||||
break;
|
||||
case 2:
|
||||
$resource = $resource->where($map[0], $map[1]);
|
||||
break;
|
||||
case 3:
|
||||
$resource = $resource->where($map[0], $map[1], $map[2]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
if ($order) {
|
||||
$resource = $resource->order($order);
|
||||
}
|
||||
return $resource->paginate($this->per_page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*
|
||||
* @param string UID
|
||||
* @param string 密码
|
||||
* @return void
|
||||
*/
|
||||
public function motifyPassword($admin_id, $password)
|
||||
{
|
||||
$access = new Access();
|
||||
//将所有授权记录标记为失效
|
||||
$access->where('access_admin', $admin_id)->update(['access_status' => 1]);
|
||||
$salt = getRandString(4);
|
||||
$password = encodePassword($password, $salt);
|
||||
return $this->where([
|
||||
"admin_id" => $admin_id
|
||||
])->update([
|
||||
"admin_password" => $password,
|
||||
"admin_salt" => $salt,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过帐号获取用户信息
|
||||
*
|
||||
* @param string 帐号/手机号
|
||||
* @return void
|
||||
*/
|
||||
public function getAdminByAccount($admin_account)
|
||||
{
|
||||
$admin = $this->where([
|
||||
"admin_account" => $admin_account
|
||||
])->find();
|
||||
if ($admin) {
|
||||
return $admin->toArray() ?? false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* AccessToken获取用户信息
|
||||
*
|
||||
* @param string access_token
|
||||
* @return void
|
||||
*/
|
||||
public function getAdminByAccessToken($access_token)
|
||||
{
|
||||
$Access = new Access();
|
||||
$access = $Access->where([
|
||||
"access_token" => $access_token,
|
||||
"access_status" => 0,
|
||||
])->find();
|
||||
if ($access) {
|
||||
if (time() > $access['access_updatetime'] + 7200) {
|
||||
return false;
|
||||
}
|
||||
if ($access['access_updatetime'] - $access['access_createtime'] > 86400) {
|
||||
return false;
|
||||
}
|
||||
$Access->where([
|
||||
"access_id" => $access['access_id'],
|
||||
])->update([
|
||||
'access_updatetime' => time()
|
||||
]);
|
||||
$this->where("admin_id", $access['access_admin'])->update([
|
||||
'admin_updatetime' => time()
|
||||
]);
|
||||
$admin = $this->where("admin_id", $access['access_admin'])->find();
|
||||
return $admin->toArray() ?? false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class App extends QfShop
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Attach extends QfShop
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\facade\Db;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Auth extends QfShop
|
||||
{
|
||||
/**
|
||||
* 判断用户组是否获得某节点的授权
|
||||
*
|
||||
* @param int 用户组ID
|
||||
* @param int 节点ID
|
||||
* @return void
|
||||
*/
|
||||
public function auth($auth_group, $auth_node)
|
||||
{
|
||||
$auth = $this->where([
|
||||
"auth_group" => $auth_group,
|
||||
"auth_node" => $auth_node
|
||||
])->find();
|
||||
return $auth ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户组 获取管理后台菜单
|
||||
*
|
||||
* @param int 用户组ID
|
||||
* @return void
|
||||
*/
|
||||
public function getAdminMenuListByAdminId($group_id)
|
||||
{
|
||||
if ($group_id == 1) {
|
||||
//超级管理员组
|
||||
$list = Node::where([
|
||||
"node_pid" => 0,
|
||||
"node_show" => 1,
|
||||
])
|
||||
->order("node_order desc,node_id asc")
|
||||
->select();
|
||||
for ($i = 0; $i < count($list); $i++) {
|
||||
$list[$i]['subList'] = $this->getSubAdminListByPid($list[$i]['node_id'], $group_id);
|
||||
for ($j = 0; $j < count($list[$i]['subList']); $j++) {
|
||||
$list[$i]['subList'][$j]['subList'] = $this->getSubAdminListByPid($list[$i]['subList'][$j]['node_id'], $group_id);
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
} else {
|
||||
//其他组
|
||||
$list = Node::where([
|
||||
"node_pid" => 0,
|
||||
"node_show" => 1,
|
||||
])
|
||||
->order("node_order desc,node_id asc")
|
||||
->select();
|
||||
for ($i = 0; $i < count($list); $i++) {
|
||||
$list[$i]['subList'] = $this->getSubAdminListByPid($list[$i]['node_id'], 1);
|
||||
for ($j = 0; $j < count($list[$i]['subList']); $j++) {
|
||||
$list[$i]['subList'][$j]['subList'] = $this->getSubAdminListByPid($list[$i]['subList'][$j]['node_id'], 1);
|
||||
}
|
||||
}
|
||||
if($list){
|
||||
$list = $list->toArray();
|
||||
}
|
||||
$list2 = Node::alias("node")
|
||||
->view('node', '*')
|
||||
->view('auth', '*', 'node.node_id=auth.auth_node', 'left')
|
||||
->where([
|
||||
"node_module" => "qfadmin",
|
||||
"node_show" => 1,
|
||||
"auth_group" => $group_id
|
||||
])
|
||||
->order("node_order desc,node_id asc")
|
||||
->select()->toArray();
|
||||
|
||||
foreach ($list2 as $k => $v) {
|
||||
//一级
|
||||
foreach ($list as $key => $value) {
|
||||
if($v['node_id'] == $value['node_id']){
|
||||
$list[$key]['select'] = 1;
|
||||
}
|
||||
//2级
|
||||
foreach ($value['subList'] as $key2 => $value2) {
|
||||
if($v['node_id'] == $value2['node_id']){
|
||||
$list[$key]['subList'][$key2]['select'] = 1;
|
||||
}
|
||||
//3级
|
||||
foreach ($value2['subList'] as $key3 => $value3) {
|
||||
if($v['node_id'] == $value3['node_id']){
|
||||
$list[$key]['subList'][$key2]['subList'][$key3]['select'] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($list as $key => $value) {
|
||||
//一级
|
||||
if(empty($value['select'])){
|
||||
if(!empty($value['subList'])){
|
||||
foreach ($value['subList'] as $key2 => $value2) {
|
||||
//2级
|
||||
if(empty($value2['select'])){
|
||||
if(!empty($value2['subList'])){
|
||||
foreach ($value2['subList'] as $key3 => $value3) {
|
||||
//3级
|
||||
if(empty($value3['select'])){
|
||||
if(empty($value3['subList'])){
|
||||
unset($list[$key]['subList'][$key2]['subList'][$key3]);
|
||||
if(empty($list[$key]['subList'][$key2]['subList'])){
|
||||
unset($list[$key]['subList'][$key2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
unset($list[$key]['subList'][$key2]);
|
||||
if(empty($list[$key]['subList'])){
|
||||
unset($list[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
unset($list[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$list = array_values($list);
|
||||
foreach ($list as $key => $value) {
|
||||
if(!empty($value['subList'])){
|
||||
$list[$key]['subList'] = array_values($list[$key]['subList']);
|
||||
foreach ($value['subList'] as $key2 => $value2) {
|
||||
if(!empty($value2['subList'])){
|
||||
try {
|
||||
$list[$key]['subList'][$key2]['subList'] = array_values($list[$key]['subList'][$key2]['subList']);
|
||||
} catch (\Throwable $th) {
|
||||
//throw $th;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据节点ID 获取用户组的子菜单
|
||||
*
|
||||
* @param int 节点ID
|
||||
* @param int 用户组ID
|
||||
* @return void
|
||||
*/
|
||||
public function getSubAdminListByPid($node_id, $group_id = 1)
|
||||
{
|
||||
if ($group_id == 1) {
|
||||
//超级管理员组
|
||||
return Node::where([
|
||||
"node_pid" => $node_id,
|
||||
"node_show" => 1
|
||||
])
|
||||
->order("node_order desc,node_id asc")
|
||||
->select();
|
||||
} else {
|
||||
//其他组
|
||||
return Node::alias("node")
|
||||
->view('node', '*')
|
||||
->view('auth', '*', 'node.node_id=auth.auth_node', 'left')
|
||||
->where([
|
||||
"node_pid" => $node_id,
|
||||
"node_show" => 1,
|
||||
"auth_group" => $group_id
|
||||
])
|
||||
->order("node_order desc,node_id asc")
|
||||
->select();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 删除授权记录
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cleanAuth()
|
||||
{
|
||||
//清空auth表
|
||||
Db::execute("truncate table " . config('database.connections.mysql.prefix') . "auth");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Conf extends QfShop
|
||||
{
|
||||
/**
|
||||
* 更新配置
|
||||
*
|
||||
* @param string 配置key
|
||||
* @param string 配置值
|
||||
* @param int 整形配置
|
||||
* @param string 配置描述
|
||||
* @return void
|
||||
*/
|
||||
public function updateConf($key, $value, $int = 0, $desc = null)
|
||||
{
|
||||
$data = [];
|
||||
if ($desc) {
|
||||
$data['conf_desc'] = $desc;
|
||||
}
|
||||
$data['conf_value'] = $value;
|
||||
$this->where([
|
||||
"conf_key" => $key,
|
||||
"conf_readonly" => 0,
|
||||
])->update($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Days extends QfShop
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Feedback extends QfShop
|
||||
{
|
||||
/**
|
||||
* 主键
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 是否需要自动写入时间戳
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
/**
|
||||
* 只读属性
|
||||
* @var array
|
||||
*/
|
||||
protected $readonly = [
|
||||
'id',
|
||||
];
|
||||
|
||||
/**
|
||||
* 字段类型或者格式转换
|
||||
* @var array
|
||||
*/
|
||||
protected $type = [
|
||||
'id' => 'integer',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Group extends QfShop
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Log extends QfShop
|
||||
{
|
||||
/**
|
||||
* 主键
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'id';
|
||||
|
||||
/**
|
||||
* 是否需要自动写入时间戳
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
/**
|
||||
* 只读属性
|
||||
* @var array
|
||||
*/
|
||||
protected $readonly = [
|
||||
'id',
|
||||
];
|
||||
|
||||
/**
|
||||
* 字段类型或者格式转换
|
||||
* @var array
|
||||
*/
|
||||
protected $type = [
|
||||
'id' => 'integer',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Node extends QfShop
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
use think\helper\Str;
|
||||
use app\model\Token as TokenModel;
|
||||
|
||||
/**
|
||||
* QfShop 数据模型基类
|
||||
*/
|
||||
class QfShop extends Model
|
||||
{
|
||||
/**
|
||||
* 默认分页获取条数
|
||||
*
|
||||
* @var int 默认分页获取条数
|
||||
*/
|
||||
public $page_size = 40;
|
||||
public $per_page = 10;
|
||||
|
||||
/**
|
||||
* 翻页搜索器
|
||||
* @access public
|
||||
* @param object $query
|
||||
* @param mixed $value
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function searchPageAttr($query, $value, $data)
|
||||
{
|
||||
$pageNo = !empty($data['page_no']) ? $data['page_no'] : 1;
|
||||
$pageSize = !empty($data['page_size']) ? $data['page_size'] : $this->page_size;
|
||||
$query->page($pageNo, $pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 排序搜索器
|
||||
* @access public
|
||||
* @param object $query
|
||||
* @param mixed $value
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function searchOrderAttr($query, $value, $data)
|
||||
{
|
||||
$order = [];
|
||||
if (!empty($data['order_field']) || !empty($data['order_type'])) {
|
||||
$order[$data['order_field']] = $data['order_type'];
|
||||
} else {
|
||||
$order = $this->defaultOrder;
|
||||
}
|
||||
if (!empty($this->fixedOrder)) {
|
||||
// 固定排序必须在前,否则将导致自定义排序无法覆盖
|
||||
$order = array_merge($this->fixedOrder, $order);
|
||||
if (!empty($data['order_field']) && $this->isReverse) {
|
||||
$order = array_reverse($order);
|
||||
}
|
||||
}
|
||||
if (!empty($order)) {
|
||||
$query->order($order);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认排序
|
||||
* @access public
|
||||
* @param array $order 默认排序
|
||||
* @param array $fixed 固定排序
|
||||
* @param bool $reverse 是否调整顺序
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefaultOrder(array $order, $fixed = [], $reverse = false)
|
||||
{
|
||||
$this->defaultOrder = $order;
|
||||
$this->fixedOrder = $fixed;
|
||||
$this->isReverse = $reverse;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 模型验证器
|
||||
* @access public
|
||||
* @param array|object $data 验证数据
|
||||
* @param string|null $scene 场景名
|
||||
* @param bool $clean 是否清理规则键值不存在的$data
|
||||
* @param string $validate 验证器规则或类
|
||||
* @return bool
|
||||
*/
|
||||
public function validateData(array &$data, $scene = null, $clean = false, $validate = '')
|
||||
{
|
||||
try {
|
||||
// 确定规则来源
|
||||
if (empty($validate)) {
|
||||
$class = '\\app\\validate\\' . $this->getName();
|
||||
if ($scene) {
|
||||
$v = new $class();
|
||||
$v->extractScene($data, $scene, $clean, $this->getPk());
|
||||
} else {
|
||||
$v = validate($class);
|
||||
}
|
||||
} else {
|
||||
$v = validate($validate);
|
||||
if ($scene) {
|
||||
$v->extractScene($data, $scene, $clean, $this->getPk());
|
||||
}
|
||||
}
|
||||
|
||||
if ($clean) {
|
||||
$keys = $v->getRuleKey();
|
||||
foreach ($data as $key => $value) {
|
||||
if (!in_array($key, $keys, true)) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
unset($key, $value);
|
||||
}
|
||||
|
||||
$v->failException(true)->check($data);
|
||||
} catch (ValidateException $e) {
|
||||
return $this->setError($e->getMessage());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测是否存在相同值
|
||||
* @access public
|
||||
* @param array $map 查询条件
|
||||
* @return bool false:不存在
|
||||
*/
|
||||
public static function checkUnique(array $map)
|
||||
{
|
||||
if (empty($map)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$count = self::where($map)->count();
|
||||
if (is_numeric($count) && $count <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台使用分页获取数据
|
||||
*
|
||||
* @param array 筛选数组
|
||||
* @param string 排序方式
|
||||
* @param string 搜索字段
|
||||
* @return void
|
||||
*/
|
||||
public function getListByPage($maps, $order = null, $field = "*")
|
||||
{
|
||||
$resource = $this->field($field);
|
||||
foreach ($maps as $map) {
|
||||
switch (count($map)) {
|
||||
case 1:
|
||||
$resource = $resource->where($map[0]);
|
||||
break;
|
||||
case 2:
|
||||
$resource = $resource->where($map[0], $map[1]);
|
||||
break;
|
||||
case 3:
|
||||
$resource = $resource->where($map[0], $map[1], $map[2]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
if ($order) {
|
||||
$resource = $resource->order($order);
|
||||
}
|
||||
return $resource->paginate($this->per_page);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 替换数组中的驼峰键名为下划线
|
||||
* @access public
|
||||
* @param array $name 需要修改的键名
|
||||
* @param array &$data 源数据
|
||||
*/
|
||||
public static function keyToSnake(array $name, array &$data)
|
||||
{
|
||||
if (!is_array($name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($name as $value) {
|
||||
foreach ($data as &$item) {
|
||||
if (!array_key_exists($value, $item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$temp = $item[$value];
|
||||
unset($item[$value]);
|
||||
|
||||
$item[Str::snake($value)] = $temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数组键名驼峰转下划线
|
||||
* @access public
|
||||
* @param array $data 数据
|
||||
* @return array
|
||||
*/
|
||||
public static function snake(array $data)
|
||||
{
|
||||
if (empty($data)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($data as $itemKey => $item) {
|
||||
foreach ($item as $valueKey => $value) {
|
||||
$data[$itemKey][Str::snake($valueKey)] = $value;
|
||||
unset($data[$itemKey][$valueKey]);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
class Sms
|
||||
{
|
||||
/**
|
||||
* 发送通知短信
|
||||
*
|
||||
* @param string 手机号码
|
||||
* @param string 内容
|
||||
* @param string 签到二维码链接
|
||||
* @return void
|
||||
*/
|
||||
public function sendSmsNotice($smsData)
|
||||
{
|
||||
//短连接生成
|
||||
$baidu_token = config('qfshop.baidu_token');
|
||||
if (!$baidu_token) {
|
||||
jerr('请先在后台系统设置短链接相关参数!');
|
||||
}
|
||||
$urlData = [
|
||||
[
|
||||
'LongUrl' => $smsData['qrcodeUrl'],
|
||||
'TermOfValidity' => "1-year",
|
||||
]
|
||||
];
|
||||
$urlHeader = array(
|
||||
'Content-Type: application/json; charset=UTF-8',
|
||||
'Dwz-Token: '.$baidu_token,
|
||||
);
|
||||
$res = curlHelper("https://dwz.cn/api/v3/short-urls", "POST", json_encode($urlData,256), $urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['Code'] != 0){
|
||||
return false;
|
||||
}
|
||||
|
||||
$smsData['qrcodeurl'] = $res['ShortUrls'][0]['ShortUrl'];
|
||||
|
||||
$result = $this->sendSms($smsData);
|
||||
if($result){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 发送短信(百度)
|
||||
*
|
||||
* @param string 手机号码
|
||||
* @param string 内容
|
||||
* @return void
|
||||
*/
|
||||
private function sendSms($smsData)
|
||||
{
|
||||
//初始化短信相关配置
|
||||
$sms_sign = config('qfshop.sms_sign');
|
||||
$sms_tmpl = config('qfshop.sms_tmpl_1');
|
||||
$error = null;
|
||||
if (!($sms_sign && $sms_tmpl)) {
|
||||
$error = jerr('请先在后台系统设置短信相关参数!');
|
||||
}
|
||||
|
||||
require_once __DIR__ . "/../../extend/baidu/baidusmsv3.php";
|
||||
$config = array(
|
||||
'endPoint' => 'smsv3.bj.baidubce.com',
|
||||
'accessKey' => 'b71eab07ebcc4f09b3f770e43a9d126d',
|
||||
'secretAccessKey' => '3c6c8b3d85274baab4c38481996919ec',
|
||||
);
|
||||
$smsClient = new \Baidusmsv3($config);
|
||||
$message = array(
|
||||
'template' => $sms_tmpl, //短信模板ID
|
||||
'signatureId' => $sms_sign, //短信签名ID
|
||||
'mobile' => $smsData['mobile'],
|
||||
"contentVar" => array(
|
||||
'param1' => '“'.$smsData['title'].'“',
|
||||
'param2' => $smsData['time'],
|
||||
'param3' => $smsData['address'],
|
||||
'param4' => '青峰网络',
|
||||
'param5' => $smsData['qrcodeurl'],
|
||||
),
|
||||
);
|
||||
$result = $smsClient->sendMessage($message);
|
||||
if($result['code'] == 1000){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param string 手机号码
|
||||
* @return void
|
||||
*/
|
||||
public function sendSmsCode($mobile,$code)
|
||||
{
|
||||
//初始化短信相关配置
|
||||
$sms_sign = config('qfshop.sms_sign');
|
||||
$sms_tmpl = config('qfshop.sms_tmpl_2');
|
||||
$error = null;
|
||||
if (!($sms_sign && $sms_tmpl)) {
|
||||
$error = jerr('请先在后台系统设置短信相关参数!');
|
||||
}
|
||||
|
||||
require_once __DIR__ . "/../../extend/baidu/baidusmsv3.php";
|
||||
$config = array(
|
||||
'endPoint' => 'smsv3.bj.baidubce.com',
|
||||
'accessKey' => 'b71eab07ebcc4f09b3f770e43a9d126d',
|
||||
'secretAccessKey' => '3c6c8b3d85274baab4c38481996919ec',
|
||||
);
|
||||
$smsClient = new \Baidusmsv3($config);
|
||||
$message = array(
|
||||
'template' => $sms_tmpl, //短信模板ID
|
||||
'signatureId' => $sms_sign, //短信签名ID
|
||||
'mobile' => $mobile,
|
||||
"contentVar" => array(
|
||||
'code' => ''.$code,
|
||||
'time' => '5',
|
||||
),
|
||||
);
|
||||
$result = $smsClient->sendMessage($message);
|
||||
if($result['code'] == 1000){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
use Lizhichao\Word\VicWord;
|
||||
|
||||
class Source extends QfShop
|
||||
{
|
||||
/**
|
||||
* 主键
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'source_id';
|
||||
|
||||
/**
|
||||
* 是否需要自动写入时间戳
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
/**
|
||||
* 只读属性
|
||||
* @var array
|
||||
*/
|
||||
protected $readonly = [
|
||||
'source_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* 字段类型或者格式转换
|
||||
* @var array
|
||||
*/
|
||||
protected $type = [
|
||||
'source_id' => 'integer',
|
||||
'is_delete' => 'integer',
|
||||
'status' => 'integer',
|
||||
'time' => 'timestamp',
|
||||
];
|
||||
|
||||
/**
|
||||
* hasOne qf_source_category
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
public function category()
|
||||
{
|
||||
return $this
|
||||
->hasOne(SourceCategory::class, 'source_category_id', 'source_category_id')
|
||||
->joinType('left')
|
||||
->field('source_category_id,name');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 获取一个信息
|
||||
* @param {*} $code
|
||||
* @return {*}
|
||||
*/
|
||||
public function getDetail(array $data)
|
||||
{
|
||||
$map[] = ['status', '=', 1];
|
||||
$map[] = ['is_delete', '=', 0];
|
||||
$map[] = ['source_id', '=', $data['id']];
|
||||
$field = 'source_id as id,source_category_id,title,url,create_time as time,vod_content,vod_pic,is_type';
|
||||
$result = $this->with('category')->where($map)->field($field)->find();
|
||||
if(!is_null($result)){
|
||||
$result->inc('page_views')->update();
|
||||
$result['times'] = substr($result['time'], 0, 10);
|
||||
}
|
||||
unset($result['time']);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表
|
||||
* @access public
|
||||
* @param array $data 外部数据
|
||||
* @return array|false
|
||||
* @throws
|
||||
*/
|
||||
public function getList(array $data)
|
||||
{
|
||||
// 搜索条件
|
||||
$map = [];
|
||||
|
||||
//默认排序
|
||||
$order = ['source_id' => 'desc'];
|
||||
|
||||
//需要高亮的词 仅分词搜索使用
|
||||
$searchTitle = [];
|
||||
|
||||
$map[] = ['status', '=', 1];
|
||||
$map[] = ['is_time', '=', 0];
|
||||
$map[] = ['is_delete', '=', 0];
|
||||
|
||||
if(!empty($data['day']) && $data['day']==2){
|
||||
// 获取今天的时间戳范围
|
||||
$todayStart = strtotime(date('Y-m-d'));
|
||||
$todayEnd = $todayStart + 86400; // 86400 秒 = 24 小时
|
||||
// 获取昨天的时间戳范围
|
||||
$yesterdayStart = $todayStart - 86400;
|
||||
$yesterdayEnd = $todayStart;
|
||||
// 添加日期范围条件
|
||||
$map[] = ['create_time', 'between', [$yesterdayStart, $todayEnd]];
|
||||
|
||||
//记录站点更新日志
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
$ips = Log::where(['ip'=>$ip])->find();
|
||||
if(empty($ips)){
|
||||
Log::save(['name' => '访问记录','ip'=>$ip]);
|
||||
}else{
|
||||
Log::where('id', $ips['id'])->update(['update_time' => time()]);
|
||||
}
|
||||
}
|
||||
|
||||
if(!empty($data['is_time']) && $data['is_time']==1){
|
||||
unset($map[array_search(['is_time', '=', 0], $map)]);
|
||||
}
|
||||
|
||||
if(!empty($data['category_id'])){
|
||||
// 将逗号分隔的字符串转换为数组
|
||||
$categoryIds = explode(',', $data['category_id']);
|
||||
// 使用 in 查询
|
||||
$map[] = ['source_category_id', 'in', $categoryIds];
|
||||
}
|
||||
|
||||
if(!empty($data['type']) && $data['type']==2){
|
||||
$map[] = ['is_type', '=', 0];
|
||||
}
|
||||
|
||||
|
||||
// 如果存在 title,则进行分词
|
||||
if (!empty($data['title'])) {
|
||||
$search_type = config('qfshop.search_type')??1;
|
||||
|
||||
if($search_type == 0){
|
||||
$map[] = ['title|description', 'like', '%' . trim($data['title']) . '%'];
|
||||
$query = $this->where($map);
|
||||
}else{
|
||||
$fc = new VicWord();
|
||||
$keywords = $fc->getAutoWord($data['title']);
|
||||
$keywords = filterAndExtractWords($keywords);
|
||||
|
||||
// 如果分词后有关键词
|
||||
if (count($keywords) > 1) {
|
||||
if($search_type == 1){
|
||||
//分词同时满足才搜索的到!
|
||||
foreach ($keywords as $keyword) {
|
||||
$map[] = ['title|description', 'like', '%' . $keyword . '%'];
|
||||
}
|
||||
$query = $this->where($map);
|
||||
}else{
|
||||
// 分词只要满足其一就可以搜索到!
|
||||
$weightExpr = [];
|
||||
foreach ($keywords as $keyword) {
|
||||
$weightExpr[] = "IF(title LIKE '%{$keyword}%' OR description LIKE '%{$keyword}%', 1, 0)";
|
||||
$searchTitle[] = $keyword;
|
||||
}
|
||||
$weightExpr = implode(' + ', $weightExpr);
|
||||
|
||||
// 在查询中添加权重计算和排序
|
||||
$query = $this->alias('a')
|
||||
->field('a.*, (' . $weightExpr . ') as weight')->where($map)
|
||||
->where(function($query) use ($keywords) {
|
||||
foreach ($keywords as $keyword) {
|
||||
$query->whereOr('title', 'like', '%' . trim($keyword) . '%')
|
||||
->whereOr('description', 'like', '%' . trim($keyword) . '%');
|
||||
}
|
||||
});
|
||||
$order = ['weight' => 'desc', 'source_id' => 'desc'];
|
||||
}
|
||||
} else {
|
||||
// 如果没有关键词,仍然使用原来的 title 查询
|
||||
$map[] = ['title|description', 'like', '%' . trim($data['title']) . '%'];
|
||||
$query = $this->where($map);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// 构建查询
|
||||
$query = $this->where($map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(!empty($data['type']) && $data['type']==2){
|
||||
$order = ['source_id' => 'asc'];
|
||||
}
|
||||
|
||||
|
||||
$result['total_result'] = $query->count();
|
||||
if ($result['total_result'] <= 0) {
|
||||
$result['items'] = [];
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 获取分页数据
|
||||
$result['items'] = $query->order($order)
|
||||
->field('source_id as id, source_category_id, title, is_type, code, url, update_time as time, is_time')
|
||||
->with('category')
|
||||
->withSearch(['page', 'order'], $data)
|
||||
->select()->each(function($item) use ($searchTitle) {
|
||||
$item['name'] = highlightKeywords($item['title'], $searchTitle);
|
||||
$item['times'] = substr($item['time'], 0, 10);
|
||||
unset($item['time']);
|
||||
return $item;
|
||||
})
|
||||
->toArray();
|
||||
|
||||
// 如果 $data['is_time'] == 1,则更新 update_time 字段
|
||||
if (!empty($data['is_time']) && $data['is_time'] == 1) {
|
||||
|
||||
// 获取所有需要更新的ID
|
||||
$ids = [];
|
||||
foreach ($result['items'] as $item) {
|
||||
if ($item['is_time'] == 1) {
|
||||
$ids[] = $item['id'];
|
||||
}
|
||||
}
|
||||
|
||||
// 更新数据库中的 update_time 字段
|
||||
if (!empty($ids)) {
|
||||
$this->whereIn('source_id', $ids)->update(['update_time' => time()]);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取最新
|
||||
* @access public
|
||||
* @param array $data 外部数据
|
||||
* @return array|false
|
||||
* @throws
|
||||
*/
|
||||
public function getNew(array $data)
|
||||
{
|
||||
|
||||
// 搜索条件
|
||||
$map = [];
|
||||
|
||||
$map[] = ['status', '=', 1];
|
||||
$map[] = ['is_time', '=', 0];
|
||||
|
||||
$result['total_result'] = $this->where($map)->count();
|
||||
if ($result['total_result'] <= 0) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result['items'] = $this->setDefaultOrder(['create_time' => 'desc'])
|
||||
->field('title,create_time as time')
|
||||
->where($map)
|
||||
->withSearch(['page', 'order'], $data)
|
||||
->select()->each(function($item,$key){
|
||||
$item['times'] = substr($item['time'], 5, 5);
|
||||
unset($item['time']);
|
||||
return $item;
|
||||
})
|
||||
->toArray();
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取最热
|
||||
* @access public
|
||||
* @param array $data 外部数据
|
||||
* @return array|false
|
||||
* @throws
|
||||
*/
|
||||
public function getHot(array $data)
|
||||
{
|
||||
$urlData = array(
|
||||
'endDay' => date("Y-m-d", strtotime("-1 day")),
|
||||
'startDay' => date("Y-m-d", strtotime("-1 day"))
|
||||
);
|
||||
$urlHeader = array('Content-Type: application/json');
|
||||
|
||||
//线路2
|
||||
$res = curlHelper("https://sycsp-prd.matesec.net/api/sp/miniApp/seriesRankList", "POST", json_encode($urlData),$urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['code'] !== 200){
|
||||
return jerr($res['msg']);
|
||||
}
|
||||
if(empty($res['data']['seriesHeatRankList'])){
|
||||
$urlData = array(
|
||||
'endDay' => date("Y-m-d", strtotime("-2 day")),
|
||||
'startDay' => date("Y-m-d", strtotime("-2 day"))
|
||||
);
|
||||
$urlHeader = array('Content-Type: application/json');
|
||||
|
||||
//线路2
|
||||
$res = curlHelper("https://sycsp-prd.matesec.net/api/sp/miniApp/seriesRankList", "POST", json_encode($urlData),$urlHeader)['body'];
|
||||
$res = json_decode($res, true);
|
||||
if($res['code'] !== 200){
|
||||
return jerr($res['msg']);
|
||||
}
|
||||
}
|
||||
|
||||
$ranking = 1;
|
||||
$result = [];
|
||||
foreach ($res['data']['seriesHeatRankList'] as $value) {
|
||||
$result[] = [
|
||||
'ranking' => $ranking++,
|
||||
'title' => $value['seriesName']??'',
|
||||
'hot' => $value['heatCount']??0,
|
||||
'hots' => $value['heatCountDisplay']??'',
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class SourceCategory extends QfShop
|
||||
{
|
||||
/**
|
||||
* 获取列表
|
||||
* @access public
|
||||
* @param array $data 外部数据
|
||||
* @return array|false
|
||||
* @throws
|
||||
*/
|
||||
public function getList(array $data)
|
||||
{
|
||||
|
||||
// 搜索条件
|
||||
$map = [];
|
||||
$map[] = ['status', '=', 0];
|
||||
$result = $this->where($map)->order('sort', 'desc')->select();
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class SourceLog extends QfShop
|
||||
{
|
||||
/**
|
||||
* 主键
|
||||
* @var string
|
||||
*/
|
||||
protected $pk = 'source_log_id';
|
||||
|
||||
/**
|
||||
* 是否需要自动写入时间戳
|
||||
* @var bool
|
||||
*/
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
/**
|
||||
* 只读属性
|
||||
* @var array
|
||||
*/
|
||||
protected $readonly = [
|
||||
'source_log_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* 字段类型或者格式转换
|
||||
* @var array
|
||||
*/
|
||||
protected $type = [
|
||||
'source_log_id' => 'integer',
|
||||
'end_time' => 'timestamp',
|
||||
];
|
||||
|
||||
public function addLog($name="任务名称",$total_num=0)
|
||||
{
|
||||
try {
|
||||
$Log = [
|
||||
'name' => $name,
|
||||
'total_num' => $total_num,
|
||||
'create_time' => time(),
|
||||
'update_time' => time(),
|
||||
];
|
||||
$logId = $this->insertGetId($Log);
|
||||
return $logId;
|
||||
} catch (\Throwable $th) {
|
||||
//throw $th;
|
||||
}
|
||||
}
|
||||
|
||||
public function editLog($source_log_id,$total_num,$edit_name,$fail_dec='',$type=0)
|
||||
{
|
||||
try {
|
||||
$data = [];
|
||||
$data['total_num'] = $total_num;
|
||||
if(!empty($fail_dec)){
|
||||
$data['fail_dec'] = $fail_dec;
|
||||
}
|
||||
$data['update_time'] = time();
|
||||
if($type==3){
|
||||
$this->where('source_log_id', $source_log_id)
|
||||
->update(['end_time' => time()]);
|
||||
}else{
|
||||
if($type==1){
|
||||
$data['end_time'] = time();
|
||||
}
|
||||
$this->where('source_log_id', $source_log_id)
|
||||
->inc($edit_name)
|
||||
->update($data);
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
//throw $th;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class Token extends QfShop
|
||||
{
|
||||
/**
|
||||
* 创建更新一个新的授权
|
||||
*
|
||||
* @param [int] 用户ID
|
||||
* @param [plat] 授权平台
|
||||
* @return 授权信息|false
|
||||
*/
|
||||
public function createAccess($user_id, $platform)
|
||||
{
|
||||
$token = $this->where([
|
||||
"user_id" => $user_id,
|
||||
"platform" => $platform
|
||||
])->find();
|
||||
//生成一个新的Access_token
|
||||
$access_token = sha1(time()) . rand(100000, 99999) . sha1(time());
|
||||
$expires = time() + (30 * 24 * 60 * 60); // 30天
|
||||
if($token){
|
||||
//如果已有token 执行更新
|
||||
$token_id = $token['token_id'];
|
||||
$this->where('token_id',$token_id)->update([
|
||||
"token" => $access_token,
|
||||
"ip" => request()->ip(),
|
||||
"token_expires" => $expires,
|
||||
"create_time" => time(),
|
||||
]);
|
||||
}else{
|
||||
//如果没有token 执行新增
|
||||
$token_id = $this->insertGetId([
|
||||
"user_id" => $user_id,
|
||||
"platform" => $platform,
|
||||
"token" => $access_token,
|
||||
"ip" => request()->ip(),
|
||||
"token_expires" => $expires,
|
||||
"create_time" => time(),
|
||||
]);
|
||||
}
|
||||
$access = $this->where("token_id", $token_id)->find();
|
||||
return $access ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权校验
|
||||
*
|
||||
* @param string token
|
||||
* @return void
|
||||
* 校验成功 更新授权码过期时间
|
||||
*/
|
||||
public function getToken($access_token)
|
||||
{
|
||||
$token = $this->where([
|
||||
"token" => $access_token
|
||||
])->find();
|
||||
if ($token) {
|
||||
if (time() > $token['token_expires']) {
|
||||
return false;
|
||||
}
|
||||
$expires = time() + (30 * 24 * 60 * 60); // 30天
|
||||
$this->where([
|
||||
"token_id" => $token['token_id'],
|
||||
])->update([
|
||||
'token_expires' => $expires
|
||||
]);
|
||||
$user = User::field("user_id,status,mobile")->where(["user_id" => $token['user_id'],"is_delete" => 0])->find();
|
||||
if(!$user){
|
||||
return jerr("账号不存在");
|
||||
}
|
||||
if ($user['status'] == 0) {
|
||||
return jerr("你的账户被禁用");
|
||||
}
|
||||
return $user;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use app\model\QfShop;
|
||||
|
||||
class User extends QfShop
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
//验证码类
|
||||
class Validate
|
||||
{
|
||||
private $charset = 'abcdefghkmnprstuvwxyzABCDEFGHKMNPRSTUVWXYZ23456789'; //随机因子
|
||||
private $code; //验证码
|
||||
private $codelen = 4; //验证码长度
|
||||
private $width = 130; //宽度
|
||||
private $height = 50; //高度
|
||||
private $img; //图形资源句柄
|
||||
private $font; //指定的字体
|
||||
private $fontsize = 20; //指定字体大小
|
||||
private $fontcolor; //指定字体颜色
|
||||
|
||||
//构造方法初始化
|
||||
public function __construct()
|
||||
{
|
||||
$this->font = $_SERVER['DOCUMENT_ROOT'] . '/static/admin/css/fonts/code.ttc';
|
||||
}
|
||||
|
||||
//生成随机码
|
||||
private function createCode()
|
||||
{
|
||||
$_len = strlen($this->charset) - 1;
|
||||
for ($i = 0; $i < $this->codelen; $i++) {
|
||||
$this->code .= $this->charset[mt_rand(0, $_len)];
|
||||
}
|
||||
}
|
||||
|
||||
//生成背景
|
||||
private function createBg()
|
||||
{
|
||||
$this->img = imagecreatetruecolor($this->width, $this->height);
|
||||
$color = imagecolorallocate($this->img, mt_rand(157, 255), mt_rand(157, 255), mt_rand(157, 255));
|
||||
imagefilledrectangle($this->img, 0, $this->height, $this->width, 0, $color);
|
||||
}
|
||||
|
||||
//生成文字
|
||||
private function createFont()
|
||||
{
|
||||
$_x = $this->width / $this->codelen;
|
||||
for ($i = 0; $i < $this->codelen; $i++) {
|
||||
$this->fontcolor = imagecolorallocate($this->img, mt_rand(0, 156), mt_rand(0, 156), mt_rand(0, 156));
|
||||
imagettftext($this->img, $this->fontsize, mt_rand(-30, 30), $_x * $i + mt_rand(1, 5), $this->height / 1.4, $this->fontcolor, $this->font, $this->code[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
//生成线条、雪花
|
||||
private function createLine()
|
||||
{
|
||||
for ($i = 0; $i < 6; $i++) {
|
||||
$color = imagecolorallocate($this->img, mt_rand(0, 156), mt_rand(0, 156), mt_rand(0, 156));
|
||||
imageline($this->img, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $color);
|
||||
}
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$color = imagecolorallocate($this->img, mt_rand(200, 255), mt_rand(200, 255), mt_rand(200, 255));
|
||||
imagestring($this->img, mt_rand(1, 5), mt_rand(0, $this->width), mt_rand(0, $this->height), '*', $color);
|
||||
}
|
||||
}
|
||||
|
||||
//对外生成
|
||||
public function getImg()
|
||||
{
|
||||
$this->createBg();
|
||||
$this->createCode();
|
||||
$this->createLine();
|
||||
$this->createFont();
|
||||
imagepng($this->img);
|
||||
$image_data = ob_get_contents();
|
||||
ob_end_clean();
|
||||
imagedestroy($this->img);
|
||||
return "data:image/png;base64," . base64_encode($image_data);
|
||||
}
|
||||
|
||||
//获取验证码
|
||||
public function getCode()
|
||||
{
|
||||
return strtolower($this->code);
|
||||
}
|
||||
/**
|
||||
* 验证图形验证码
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function validateImgCode($token, $code)
|
||||
{
|
||||
if (!$token) {
|
||||
return jerr("TOKEN参数丢失");
|
||||
}
|
||||
if (!$code) {
|
||||
return jerr("请输入验证码");
|
||||
}
|
||||
$code = strtoupper($code);
|
||||
$token = $token;
|
||||
$_code = cache($token);
|
||||
if (!$_code) {
|
||||
return jerr("验证码已过期");
|
||||
}
|
||||
if ($code != $_code) {
|
||||
return jerr('验证码错误');
|
||||
}
|
||||
// 删除设置的缓存
|
||||
cache($token, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr" lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#fff">
|
||||
<meta name="viewport" content="initial-scale=1, minimum-scale=1, width=device-width">
|
||||
<title>系统错误</title>
|
||||
<style>
|
||||
a {
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
body {
|
||||
--background-color: #fff;
|
||||
--error-code-color: var(--google-gray-700);
|
||||
--google-blue-100: rgb(210, 227, 252);
|
||||
--google-blue-300: rgb(138, 180, 248);
|
||||
--google-blue-600: rgb(26, 115, 232);
|
||||
--google-blue-700: rgb(25, 103, 210);
|
||||
--google-gray-100: rgb(241, 243, 244);
|
||||
--google-gray-300: rgb(218, 220, 224);
|
||||
--google-gray-500: rgb(154, 160, 166);
|
||||
--google-gray-50: rgb(248, 249, 250);
|
||||
--google-gray-600: rgb(128, 134, 139);
|
||||
--google-gray-700: rgb(95, 99, 104);
|
||||
--google-gray-800: rgb(60, 64, 67);
|
||||
--google-gray-900: rgb(32, 33, 36);
|
||||
--heading-color: var(--google-gray-900);
|
||||
--primary-button-fill-color-active: var(--google-blue-700);
|
||||
--primary-button-fill-color: var(--google-blue-600);
|
||||
--primary-button-text-color: #fff;
|
||||
--text-color: var(--google-gray-700);
|
||||
background: var(--background-color);
|
||||
color: var(--text-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
.icon {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
body.captive-portal,
|
||||
body.dark-mode-available,
|
||||
body.neterror,
|
||||
body.supervised-user-block,
|
||||
.offline body {
|
||||
--background-color: var(--google-gray-900);
|
||||
--error-code-color: var(--google-gray-500);
|
||||
--heading-color: var(--google-gray-500);
|
||||
--link-color: var(--google-blue-300);
|
||||
--primary-button-fill-color-active: rgb(129, 162, 208);
|
||||
--primary-button-fill-color: var(--google-blue-300);
|
||||
--primary-button-text-color: var(--google-gray-900);
|
||||
--text-color: var(--google-gray-500);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
button {
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
color: var(--primary-button-text-color);
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-size: .875em;
|
||||
margin: 0;
|
||||
padding: 8px 16px;
|
||||
transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
[dir='rtl'] button {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.ssl button {
|
||||
background: var(--primary-button-fill-color);
|
||||
}
|
||||
|
||||
button:active {
|
||||
background: var(--primary-button-fill-color-active);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
color: var(--heading-color);
|
||||
font-size: 1.6em;
|
||||
font-weight: normal;
|
||||
line-height: 1.25em;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 72px;
|
||||
margin: 0 0 40px;
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
box-sizing: border-box;
|
||||
font-size: 1em;
|
||||
line-height: 1.6em;
|
||||
margin: 14vh auto 0;
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#main-message>p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
margin-top: 51px;
|
||||
}
|
||||
|
||||
.nav-wrapper::after {
|
||||
clear: both;
|
||||
content: '';
|
||||
display: table;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.interstitial-wrapper {
|
||||
padding: 0 10%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
|
||||
button,
|
||||
[dir='rtl'] button{
|
||||
float: none;
|
||||
font-size: .825em;
|
||||
font-weight: 500;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
padding: 0 5%;
|
||||
}
|
||||
|
||||
|
||||
.nav-wrapper {
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 240px) and (max-width: 420px) and (min-height: 401px),
|
||||
(min-width: 421px) and (min-height: 240px) and (max-height: 560px) {
|
||||
body .nav-wrapper {
|
||||
background: var(--background-color);
|
||||
bottom: 0;
|
||||
box-shadow: 0 -22px 40px var(--background-color);
|
||||
left: 0;
|
||||
margin: 0 auto;
|
||||
max-width: 736px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
max-width: 736px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 420px) and (orientation: portrait),
|
||||
(max-height: 560px) {
|
||||
body {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
button,
|
||||
[dir='rtl'] button,
|
||||
button.small-link {
|
||||
font-family: Roboto-Regular, Helvetica;
|
||||
font-size: .933em;
|
||||
margin: 6px 0;
|
||||
transform: translatez(0);
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-bottom: 5.69vh;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
box-sizing: border-box;
|
||||
margin: 7vh auto 12px;
|
||||
padding: 0 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.interstitial-wrapper p {
|
||||
font-size: .95em;
|
||||
line-height: 1.61em;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 421px) and (min-height: 500px) and (max-height: 560px) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 10vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 400px) and (orientation:portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-bottom: 145px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 299px) {
|
||||
.nav-wrapper {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and (orientation: portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 7vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 10vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ssl .icon {
|
||||
background-image: -webkit-image-set(url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAABAlBMVEUAAADcRTfcRDfdRET/gIDcRjr/ZmbjVTncRDfcRTfcRDfdRDzgSTncRDjeSDvcRTjbRDfbRDjeRzvcRjfbRjjcRTjcRTjcRTfdRTfcRDjdRTjcRTjbRDjbRTjbRTjbRTfcRjjdRDrcRjfbRTjZQzfcRDjZRDfZRzbWQzXXRDXXQzbXQzbWQjXYSDvWQjbbRDfOQDPSQTTUQjXCPDDNPzPJPjLGPTHVQjXMPzPRQTTWQjXLPzPDPDHYQzbAOzDTQTXHPTLIPjK8Oi++Oy/FPTHEPTHPQDTQQDTUQTXBPDDKPjK/OzC9Oi/////PQDPRQDS3OS66OS7TQTTEPDHXQjbMPjMBhLaWAAAAL3RSTlMA4tgPAhYFCcL98B4x9ie1+s49WICbqXNKZY3pjuqcgVdLZnL2qKg9zmXpjfontV8LANsAAAJrSURBVHhe7ZTnduIwFAY3ARIgBAg9vW1v173ROylby/u/yso2Fx3MNaxs9h/zAHM+Sfa8+M/s2LFjx+3tdjwH+/sHWxHVAerb8KSyANnUFkRXwLiK78llgJHJxRalwSMd11OGOeV4nsM9FO0dxhJdw4LrOJ6jYy46PoohqgEHatE9JViiFNWTPIElTpIRRXcQ4C6aJ3EJAS4TkUQXsMJFFE++CCsU8xFEBSAoiHsaQNIQ7yuQCFe3DiHUhftKIlzdKoRSFe0r8sXDAkSoumkIigYaIOkIfeWi56EESFm8r1w0fFIl4epWgBA9qOMpmirCfeWijtoa9WSx6taAELFBRl/vilS3BJRIbRk9/VFTsLrifUXRuNfXLU0y/7m6p0CKxqN+v6lJU/k3eJxu7Os5LWKDHi1tYstKG1zON1X3DGiRMR80Mx3fdCbc1+bQe3o2SJrYXcV0fFMxL9xXiz0987BBtux65qaCeF8lHCR3FabBTQ3xvk4M1yN5B/Mw2+urew8hTP1BM38Qnu5evK8gMw+7IcfH9E3ZlEBfMSO//Kf35+Cm6ua+rhbSYDeEa9CUyW3qK1HIjj5DBz8dWd0bWCd6Ult/uMPEr+BmbV/JHrVG/a9MsEybV5fsK50R3frmBFXtCtVXmt73H4PhQ4t9k9rkJ55tYXwZrO4rCEUfPHfUEcuaZC/umw97TfaVpslu2tCb2lRWnBlKFtf+huwrjaa6Pxv7RfgW7nubJPtKI/X0puQO4k/Pfe/ovtLY7KbxVwve0/sE3VeaLosIbkEDvt8Hoq/hKGwQYvoq5OMnoq/hLAbgc/FVn33PX7pAfE5QHR6fAAAAAElFTkSuQmCC) 1x,
|
||||
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAMAAADQmBKKAAABTVBMVEUAAADcRDf/ZmbcRjrjVTn/gIDdRETdRDzZQzbXQzXWQzbXQjbWQzXZRDbbRDnWQjXWQzXYSDvbRTjcRTjbRTfcRjfcRTjcRTjdRjncRTfdRTndRTfdRDrbRTjcRDnbRDfbRDjbRjfcRjfbRTjcRTjdRTjbRjjcRTjcRDjcRjncRTncRTndRDnbRTjcRDfZQzbcRTfgSTncRDfcRjjZQzjcRTfVRDbcRDjcRDjWQzXeRzvbRDjXRDXXQzbXQzbbRDfeSDvWQjbVQjXIPjLOQDPXQjbCPDDNPzPUQTXRQTS5OS7QQDTUQjW3OS7SQTTPQDTFPDHJPjK2OC26OS7HPjHOPzPLPjLMPjPRQDTGPDHTQTTEPTHLPzPGPTG7Oi/HPTLKPjLTQTXYQza9Oi/MPzPFPTHDPDHBPDC/OzC+Oy+8Oi/AOzDWQjX////bRDd3undHAAAAQnRSTlMA2AUWCQIPHj39wvbO8DH64ifqqYFmtrVMc1lKS5x0nY6PWKqbjYDpZXWCZ1py8Jv9McJXV+KA9qioPc5l6Y36J7VmcHe8AAAFWUlEQVR4XuzWS4rCQBSG0euz56ISgiaEjHwgGhAhDnRF3/6HDY1Ia5WPjP4a3LOKY28555xzzjnnnHPOuSyzpPR7vb6lZAUrS8hgB7uBpaMEKC0Zhz3A/mCpaPjTWCK23GwtCcMjN8ehpWDN3doS8HPi7vRjejX/1CbX8qA1sdGZB+eRaW14sjGp8YQnk7EpVQQqE7peCFyupjMnYm4yGVGZ7q1EyTZbEEche2uUbLMlL5W6t4Zkm22Ikm02561c89aQbLNTPpgq3hqSbbbmo1r41rhW8NaAaLMzvjITvDUg2WzFlyrBWwOCzc6Jkm12QQcL3Vtlmy3opFC9VbbZJR0tNW+Vbbahs0b41rhc8FbVZqdEyTb724t5/bYNA3G4e+80NYI0gGFkvaR779KKZUWuFKe7nlIsT5X//2M5VMZiZB9DQj74xW8ffrwjP90Mb/07Vf5CbXYJg0BtO4toKS9vhYHGY1vDZg28FQY6tBZls8tYBehwNLTyt1nhrTDQaDQcWAux2SJWAxpOBpWMWSvm4q0w0Gg4nFQqFTd/m72HlYBYQJV+w83bZu9jRaDJYEB4osjJ02aFt8JASUBRq+PlarMrWBGI8lQajVanXA5kopUcvBUEGrCAWhSoXs3PZtewKhA/MMbTbcpEa7l4KwwURZSHANnVnGz2CVYGmg6oZ1u1XGy2hNWBCA8BogE1m7Zl+ShNVMrdW2Wg/v+Amr2eRYCcGLBZU2+FgcSBESDfdZxdwGbNvBUGihKgnk1OjPAEwS5gsybeCgNNdTQLyAtqtRCwWQNvhYH4ndjtNnlAnlet1uIQsFl9b4WBpgNyaUCEJ45DwGa1vRUGanU6nMcmB+ZSnlosES3nvm/tUpGm1tFPd5DDAyKFBJGpzRaxSjW5J0o8/MAQ4ZEyKua/b+0Np175blMERDuaECFBZGqzBaxY9iAjIMbDK01U0OVZxcplE6BIjLzFRixgQDwflCJaXcC+1ToKyOYHFvCOljPiNmvurTBRI+oQoGTk2Z1YQyIeiWhlEftWnx8Yf8RcyiMCEkyhic2u4xOWSw9MBBQENTQFI83a+iL2rdgpJ1rms45mByYzhbDNwt6qTtTlQC7r6FT/CLRQ02ZLWKc8OmK+LzooCykhKpl4q7p+7B/d0SjNggRbqGOzm1gPqL3PX3niZakOQsenf1PDWzWAxr+JBtEDQxnnJTISNmvurfBK75t45bORBNGSobcqb9DqBCjdQOl5E370xthbYaDRiIjRDxKQwJk9a+o2u431gYZERBo/kcBIfvJ/TrSt6K1b+kDUHMkra2V3j5zRlprNbmADILbQ65S/z2ggyY82zL0VXsdQnnLdhSOKQzWbLWADIMpDgOrd3q958QiigrG3wusYzmNbXmY4sh+tangrVJ2Dgy97X9v0CmILzzIHcj3ZPTL+h6DN7mhYR5nxHI4mtKNbLCAmaX9QDDKFO6C36hDttcdJQFGLeTWRIupocGOj62cBb9WqesLTFwfm000MQgqz9lDLW+Hve35HM9Fnqw9HetBkNsF6+Yaet8Jf0+xbka0XbYspSMIg+5D8/8psnqdYv3qso1vsS9Hy6SaGQ6AYHP9ngLdqllVpiIB8RygRQjGEdOsc4K26RGzk6YTxjhbDDdzXcfwC8Fbd8glPnR4Y62gBAM/a1WybfYVNyyUBiZFPXYCAH70GvFW7nFRHH7EgyI8uAd6qXZ7NAqoilG6ZKuBH184D3qpdAQlIWp0p9dE7wFv1q8Y6+njLoPl+9P4C4K0GRKSjgTyywvoAeKtBxVWU6YhorovcvA14q0HtouwU0Fw/+jzN8w/cQ/zg6ug2/QAAAABJRU5ErkJggg==) 2x);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body id="body" class="ssl extended-reporting-has-checkbox">
|
||||
<div class="interstitial-wrapper">
|
||||
<div id="main-content">
|
||||
<div class="icon" id="icon"></div>
|
||||
<div id="main-message">
|
||||
<h1>系统发生错误:</h1>
|
||||
<p>虽然不知道错在哪,但是确实出了点小问题...</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-wrapper">
|
||||
<a href="javascript:history.go(-1);"><button id="primary-button">好的,我知道了</button></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
html {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: system-ui, PingFang SC, STHeiti, sans-serif;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: system-ui, PingFang SC, STHeiti, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,585 @@
|
||||
<?php
|
||||
/** @var array $traces */
|
||||
if (!function_exists('parse_padding')) {
|
||||
function parse_padding($source)
|
||||
{
|
||||
$length = strlen(strval(count($source['source']) + $source['first']));
|
||||
return 40 + ($length - 1) * 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('parse_class')) {
|
||||
function parse_class($name)
|
||||
{
|
||||
$names = explode('\\', $name);
|
||||
return '<abbr title="' . $name . '">' . end($names) . '</abbr>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('parse_file')) {
|
||||
function parse_file($file, $line)
|
||||
{
|
||||
return '<a class="toggle" title="' . "{$file} line {$line}" . '">' . basename($file) . " line {$line}" . '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('parse_args')) {
|
||||
function parse_args($args)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($args as $key => $item) {
|
||||
switch (true) {
|
||||
case is_object($item):
|
||||
$value = sprintf('<em>object</em>(%s)', parse_class(get_class($item)));
|
||||
break;
|
||||
case is_array($item):
|
||||
if (count($item) > 3) {
|
||||
$value = sprintf('[%s, ...]', parse_args(array_slice($item, 0, 3)));
|
||||
} else {
|
||||
$value = sprintf('[%s]', parse_args($item));
|
||||
}
|
||||
break;
|
||||
case is_string($item):
|
||||
if (strlen($item) > 20) {
|
||||
$value = sprintf(
|
||||
'\'<a class="toggle" title="%s">%s...</a>\'',
|
||||
htmlentities($item),
|
||||
htmlentities(substr($item, 0, 20))
|
||||
);
|
||||
} else {
|
||||
$value = sprintf("'%s'", htmlentities($item));
|
||||
}
|
||||
break;
|
||||
case is_int($item):
|
||||
case is_float($item):
|
||||
$value = $item;
|
||||
break;
|
||||
case is_null($item):
|
||||
$value = '<em>null</em>';
|
||||
break;
|
||||
case is_bool($item):
|
||||
$value = '<em>' . ($item ? 'true' : 'false') . '</em>';
|
||||
break;
|
||||
case is_resource($item):
|
||||
$value = '<em>resource</em>';
|
||||
break;
|
||||
default:
|
||||
$value = htmlentities(str_replace("\n", '', var_export(strval($item), true)));
|
||||
break;
|
||||
}
|
||||
|
||||
$result[] = is_int($key) ? $value : "'{$key}' => {$value}";
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
}
|
||||
}
|
||||
if (!function_exists('echo_value')) {
|
||||
function echo_value($val)
|
||||
{
|
||||
if (is_array($val) || is_object($val)) {
|
||||
echo htmlentities(json_encode($val, JSON_PRETTY_PRINT));
|
||||
} elseif (is_bool($val)) {
|
||||
echo $val ? 'true' : 'false';
|
||||
} elseif (is_scalar($val)) {
|
||||
echo htmlentities($val);
|
||||
} else {
|
||||
echo 'Resource';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>系统发生错误</title>
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
<style>
|
||||
/* Base */
|
||||
body {
|
||||
color: #333;
|
||||
font: 16px Verdana, "Helvetica Neue", helvetica, Arial, 'Microsoft YaHei', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 10px 0 0;
|
||||
font-size: 28px;
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #4288ce;
|
||||
font-weight: 400;
|
||||
padding: 6px 0;
|
||||
margin: 6px 0 0;
|
||||
font-size: 18px;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 12px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
abbr {
|
||||
cursor: help;
|
||||
text-decoration: underline;
|
||||
text-decoration-style: dotted;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #868686;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.line-error {
|
||||
background: #f8cbcb;
|
||||
}
|
||||
|
||||
.echo table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.echo pre {
|
||||
padding: 16px;
|
||||
overflow: auto;
|
||||
font-size: 85%;
|
||||
line-height: 1.45;
|
||||
background-color: #f7f7f7;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
|
||||
}
|
||||
|
||||
.echo pre>pre {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Exception Info */
|
||||
.exception {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.exception .message {
|
||||
padding: 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-bottom: 0 none;
|
||||
line-height: 18px;
|
||||
font-size: 16px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, Verdana, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception .code {
|
||||
float: left;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
margin-right: 12px;
|
||||
padding: 16px;
|
||||
border-radius: 4px;
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.exception .source-code {
|
||||
padding: 6px;
|
||||
border: 1px solid #ddd;
|
||||
|
||||
background: #f9f9f9;
|
||||
overflow-x: auto;
|
||||
|
||||
}
|
||||
|
||||
.exception .source-code pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.exception .source-code pre ol {
|
||||
margin: 0;
|
||||
color: #4288ce;
|
||||
display: inline-block;
|
||||
min-width: 100%;
|
||||
box-sizing: border-box;
|
||||
font-size: 14px;
|
||||
font-family: "Century Gothic", Consolas, "Liberation Mono", Courier, Verdana, serif;
|
||||
padding-left: <?php echo (isset($source) && !empty($source)) ? parse_padding($source) : 40; ?>px;
|
||||
}
|
||||
|
||||
.exception .source-code pre li {
|
||||
border-left: 1px solid #ddd;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.exception .source-code pre code {
|
||||
color: #333;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
border-left: 1px solid #fff;
|
||||
font-size: 14px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, Verdana, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception .trace {
|
||||
padding: 6px;
|
||||
border: 1px solid #ddd;
|
||||
border-top: 0 none;
|
||||
line-height: 16px;
|
||||
font-size: 14px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, Verdana, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception .trace h2:hover {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.exception .trace ol {
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.exception .trace ol li {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.exception div:last-child {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
/* Exception Variables */
|
||||
.exception-var table {
|
||||
width: 100%;
|
||||
margin: 12px 0;
|
||||
box-sizing: border-box;
|
||||
table-layout: fixed;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.exception-var table caption {
|
||||
text-align: left;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
.exception-var table caption small {
|
||||
font-weight: 300;
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.exception-var table tbody {
|
||||
font-size: 13px;
|
||||
font-family: Consolas, "Liberation Mono", Courier, "微软雅黑", serif;
|
||||
}
|
||||
|
||||
.exception-var table td {
|
||||
padding: 0 6px;
|
||||
vertical-align: top;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.exception-var table td:first-child {
|
||||
width: 28%;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.exception-var table td pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Copyright Info */
|
||||
.copyright {
|
||||
margin-top: 24px;
|
||||
padding: 12px 0;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
/* SPAN elements with the classes below are added by prettyprint. */
|
||||
pre.prettyprint .pln {
|
||||
color: #000
|
||||
}
|
||||
|
||||
/* plain text */
|
||||
pre.prettyprint .str {
|
||||
color: #080
|
||||
}
|
||||
|
||||
/* string content */
|
||||
pre.prettyprint .kwd {
|
||||
color: #008
|
||||
}
|
||||
|
||||
/* a keyword */
|
||||
pre.prettyprint .com {
|
||||
color: #800
|
||||
}
|
||||
|
||||
/* a comment */
|
||||
pre.prettyprint .typ {
|
||||
color: #606
|
||||
}
|
||||
|
||||
/* a type name */
|
||||
pre.prettyprint .lit {
|
||||
color: #066
|
||||
}
|
||||
|
||||
/* a literal value */
|
||||
/* punctuation, lisp open bracket, lisp close bracket */
|
||||
pre.prettyprint .pun,
|
||||
pre.prettyprint .opn,
|
||||
pre.prettyprint .clo {
|
||||
color: #660
|
||||
}
|
||||
|
||||
pre.prettyprint .tag {
|
||||
color: #008
|
||||
}
|
||||
|
||||
/* a markup tag name */
|
||||
pre.prettyprint .atn {
|
||||
color: #606
|
||||
}
|
||||
|
||||
/* a markup attribute name */
|
||||
pre.prettyprint .atv {
|
||||
color: #080
|
||||
}
|
||||
|
||||
/* a markup attribute value */
|
||||
pre.prettyprint .dec,
|
||||
pre.prettyprint .var {
|
||||
color: #606
|
||||
}
|
||||
|
||||
/* a declaration; a variable name */
|
||||
pre.prettyprint .fun {
|
||||
color: red
|
||||
}
|
||||
|
||||
/* a function name */
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php if (\think\facade\App::isDebug()) { ?>
|
||||
<?php foreach ($traces as $index => $trace) { ?>
|
||||
<div class="exception">
|
||||
<div class="message">
|
||||
<div class="info">
|
||||
<div>
|
||||
<h2><?php echo "#{$index} [{$trace['code']}]" . sprintf('%s in %s', parse_class($trace['name']), parse_file($trace['file'], $trace['line'])); ?></h2>
|
||||
</div>
|
||||
<div>
|
||||
<h1><?php echo nl2br(htmlentities($trace['message'])); ?></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php if (!empty($trace['source'])) { ?>
|
||||
<div class="source-code">
|
||||
<pre class="prettyprint lang-php"><ol start="<?php echo $trace['source']['first']; ?>"><?php foreach ((array) $trace['source']['source'] as $key => $value) { ?><li class="line-<?php echo "{$index}-";
|
||||
echo $key + $trace['source']['first'];
|
||||
echo $trace['line'] === $key + $trace['source']['first'] ? ' line-error' : ''; ?>"><code><?php echo htmlentities($value); ?></code></li><?php } ?></ol></pre>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="trace">
|
||||
<h2 data-expand="<?php echo 0 === $index ? '1' : '0'; ?>">Call Stack</h2>
|
||||
<ol>
|
||||
<li><?php echo sprintf('in %s', parse_file($trace['file'], $trace['line'])); ?></li>
|
||||
<?php foreach ((array) $trace['trace'] as $value) { ?>
|
||||
<li>
|
||||
<?php
|
||||
// Show Function
|
||||
if ($value['function']) {
|
||||
echo sprintf(
|
||||
'at %s%s%s(%s)',
|
||||
isset($value['class']) ? parse_class($value['class']) : '',
|
||||
isset($value['type']) ? $value['type'] : '',
|
||||
$value['function'],
|
||||
isset($value['args']) ? parse_args($value['args']) : ''
|
||||
);
|
||||
}
|
||||
|
||||
// Show line
|
||||
if (isset($value['file']) && isset($value['line'])) {
|
||||
echo sprintf(' in %s', parse_file($value['file'], $value['line']));
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
<?php } ?>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php } else { ?>
|
||||
<div class="exception">
|
||||
<div class="info">
|
||||
<h1><?php echo htmlentities($message); ?></h1>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (!empty($datas)) { ?>
|
||||
<div class="exception-var">
|
||||
<h2>Exception Datas</h2>
|
||||
<?php foreach ((array) $datas as $label => $value) { ?>
|
||||
<table>
|
||||
<?php if (empty($value)) { ?>
|
||||
<caption><?php echo $label; ?><small>empty</small></caption>
|
||||
<?php } else { ?>
|
||||
<caption><?php echo $label; ?></caption>
|
||||
<tbody>
|
||||
<?php foreach ((array) $value as $key => $val) { ?>
|
||||
<tr>
|
||||
<td><?php echo htmlentities($key); ?></td>
|
||||
<td><?php echo_value($val); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if (!empty($tables)) { ?>
|
||||
<div class="exception-var">
|
||||
<h2>Environment Variables</h2>
|
||||
<?php foreach ((array) $tables as $label => $value) { ?>
|
||||
<table>
|
||||
<?php if (empty($value)) { ?>
|
||||
<caption><?php echo $label; ?><small>empty</small></caption>
|
||||
<?php } else { ?>
|
||||
<caption><?php echo $label; ?></caption>
|
||||
<tbody>
|
||||
<?php foreach ((array) $value as $key => $val) { ?>
|
||||
<tr>
|
||||
<td><?php echo htmlentities($key); ?></td>
|
||||
<td><?php echo_value($val); ?></td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
<?php } ?>
|
||||
</table>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php if (\think\facade\App::isDebug()) { ?>
|
||||
<script>
|
||||
function $(selector, node) {
|
||||
var elements;
|
||||
|
||||
node = node || document;
|
||||
if (document.querySelectorAll) {
|
||||
elements = node.querySelectorAll(selector);
|
||||
} else {
|
||||
switch (selector.substr(0, 1)) {
|
||||
case '#':
|
||||
elements = [node.getElementById(selector.substr(1))];
|
||||
break;
|
||||
case '.':
|
||||
if (document.getElementsByClassName) {
|
||||
elements = node.getElementsByClassName(selector.substr(1));
|
||||
} else {
|
||||
elements = get_elements_by_class(selector.substr(1), node);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
elements = node.getElementsByTagName();
|
||||
}
|
||||
}
|
||||
return elements;
|
||||
|
||||
function get_elements_by_class(search_class, node, tag) {
|
||||
var elements = [],
|
||||
eles,
|
||||
pattern = new RegExp('(^|\\s)' + search_class + '(\\s|$)');
|
||||
|
||||
node = node || document;
|
||||
tag = tag || '*';
|
||||
|
||||
eles = node.getElementsByTagName(tag);
|
||||
for (var i = 0; i < eles.length; i++) {
|
||||
if (pattern.test(eles[i].className)) {
|
||||
elements.push(eles[i])
|
||||
}
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
$.getScript = function(src, func) {
|
||||
var script = document.createElement('script');
|
||||
|
||||
script.async = 'async';
|
||||
script.src = src;
|
||||
script.onload = func || function() {};
|
||||
|
||||
$('head')[0].appendChild(script);
|
||||
}
|
||||
|
||||
;
|
||||
(function() {
|
||||
var files = $('.toggle');
|
||||
var ol = $('ol', $('.prettyprint')[0]);
|
||||
var li = $('li', ol[0]);
|
||||
|
||||
// 短路径和长路径变换
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
files[i].ondblclick = function() {
|
||||
var title = this.title;
|
||||
|
||||
this.title = this.innerHTML;
|
||||
this.innerHTML = title;
|
||||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
var expand = function(dom, expand) {
|
||||
var ol = $('ol', dom.parentNode)[0];
|
||||
expand = undefined === expand ? dom.attributes['data-expand'].value === '0' : undefined;
|
||||
if (expand) {
|
||||
dom.attributes['data-expand'].value = '1';
|
||||
ol.style.display = 'none';
|
||||
dom.innerText = 'Call Stack (展开)';
|
||||
} else {
|
||||
dom.attributes['data-expand'].value = '0';
|
||||
ol.style.display = 'block';
|
||||
dom.innerText = 'Call Stack (折叠)';
|
||||
}
|
||||
};
|
||||
var traces = $('.trace');
|
||||
for (var i = 0; i < traces.length; i++) {
|
||||
var h2 = $('h2', traces[i])[0];
|
||||
expand(h2);
|
||||
h2.onclick = function() {
|
||||
expand(this);
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
$.getScript('//cdn.bootcss.com/prettify/r298/prettify.min.js', function() {
|
||||
prettyPrint();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<?php } ?>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,309 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr" lang="zh">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#fff">
|
||||
<meta name="viewport" content="initial-scale=1, minimum-scale=1, width=device-width">
|
||||
<title>系统操作成功</title>
|
||||
<style>
|
||||
a {
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
body {
|
||||
--background-color: #fff;
|
||||
--error-code-color: var(--google-gray-700);
|
||||
--google-blue-100: rgb(210, 227, 252);
|
||||
--google-blue-300: rgb(138, 180, 248);
|
||||
--google-blue-600: rgb(26, 115, 232);
|
||||
--google-blue-700: rgb(25, 103, 210);
|
||||
--google-gray-100: rgb(241, 243, 244);
|
||||
--google-gray-300: rgb(218, 220, 224);
|
||||
--google-gray-500: rgb(154, 160, 166);
|
||||
--google-gray-50: rgb(248, 249, 250);
|
||||
--google-gray-600: rgb(128, 134, 139);
|
||||
--google-gray-700: rgb(95, 99, 104);
|
||||
--google-gray-800: rgb(60, 64, 67);
|
||||
--google-gray-900: rgb(32, 33, 36);
|
||||
--heading-color: var(--google-gray-900);
|
||||
--primary-button-fill-color-active: var(--google-blue-700);
|
||||
--primary-button-fill-color: var(--google-blue-600);
|
||||
--primary-button-text-color: #fff;
|
||||
--text-color: var(--google-gray-700);
|
||||
background: var(--background-color);
|
||||
color: var(--text-color);
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
html {
|
||||
-webkit-text-size-adjust: 100%;
|
||||
font-size: 125%;
|
||||
}
|
||||
|
||||
.icon {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
body.captive-portal,
|
||||
body.dark-mode-available,
|
||||
body.neterror,
|
||||
body.supervised-user-block,
|
||||
.offline body {
|
||||
--background-color: var(--google-gray-900);
|
||||
--error-code-color: var(--google-gray-500);
|
||||
--heading-color: var(--google-gray-500);
|
||||
--link-color: var(--google-blue-300);
|
||||
--primary-button-fill-color-active: rgb(129, 162, 208);
|
||||
--primary-button-fill-color: var(--google-blue-300);
|
||||
--primary-button-text-color: var(--google-gray-900);
|
||||
--text-color: var(--google-gray-500);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
button {
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
color: var(--primary-button-text-color);
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-size: .875em;
|
||||
margin: 0;
|
||||
padding: 8px 16px;
|
||||
transition: box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
[dir='rtl'] button {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.ssl button {
|
||||
background: var(--primary-button-fill-color);
|
||||
}
|
||||
|
||||
button:active {
|
||||
background: var(--primary-button-fill-color-active);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
color: var(--heading-color);
|
||||
font-size: 1.6em;
|
||||
font-weight: normal;
|
||||
line-height: 1.25em;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.2em;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.icon {
|
||||
height: 72px;
|
||||
margin: 0 0 40px;
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
box-sizing: border-box;
|
||||
font-size: 1em;
|
||||
line-height: 1.6em;
|
||||
margin: 14vh auto 0;
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#main-message>p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
margin-top: 51px;
|
||||
}
|
||||
|
||||
.nav-wrapper::after {
|
||||
clear: both;
|
||||
content: '';
|
||||
display: table;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.interstitial-wrapper {
|
||||
padding: 0 10%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
|
||||
button,
|
||||
[dir='rtl'] button{
|
||||
float: none;
|
||||
font-size: .825em;
|
||||
font-weight: 500;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 16px 24px;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
padding: 0 5%;
|
||||
}
|
||||
|
||||
|
||||
.nav-wrapper {
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 240px) and (max-width: 420px) and (min-height: 401px),
|
||||
(min-width: 421px) and (min-height: 240px) and (max-height: 560px) {
|
||||
body .nav-wrapper {
|
||||
background: var(--background-color);
|
||||
bottom: 0;
|
||||
box-shadow: 0 -22px 40px var(--background-color);
|
||||
left: 0;
|
||||
margin: 0 auto;
|
||||
max-width: 736px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
max-width: 736px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 420px) and (orientation: portrait),
|
||||
(max-height: 560px) {
|
||||
body {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
button,
|
||||
[dir='rtl'] button,
|
||||
button.small-link {
|
||||
font-family: Roboto-Regular, Helvetica;
|
||||
font-size: .933em;
|
||||
margin: 6px 0;
|
||||
transform: translatez(0);
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-bottom: 5.69vh;
|
||||
}
|
||||
|
||||
.interstitial-wrapper {
|
||||
box-sizing: border-box;
|
||||
margin: 7vh auto 12px;
|
||||
padding: 0 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.interstitial-wrapper p {
|
||||
font-size: .95em;
|
||||
line-height: 1.61em;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 421px) and (min-height: 500px) and (max-height: 560px) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 10vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 400px) and (orientation:portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-bottom: 145px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 299px) {
|
||||
.nav-wrapper {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and (orientation: portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 7vh;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) {
|
||||
.interstitial-wrapper {
|
||||
margin-top: 10vh;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ssl .icon {
|
||||
background-image: -webkit-image-set(url(data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20%20style%3d%22fill%3agreen%3bstroke%3awhite%3b%22%20d%3D%22M12%2022C6.477%2022%202%2017.523%202%2012S6.477%202%2012%202s10%204.477%2010%2010-4.477%2010-10%2010zm-1.177-7.86l-2.765-2.767L7%2012.431l3.119%203.121a1%201%200%20001.414%200l5.952-5.95-1.062-1.062-5.6%205.6z%22%2F%3E%3C%2Fsvg%3E) 2x);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body id="body" class="ssl extended-reporting-has-checkbox">
|
||||
<div class="interstitial-wrapper">
|
||||
<div id="main-content">
|
||||
<div class="icon" id="icon"></div>
|
||||
<div id="main-message">
|
||||
<h1>系统操作成功:</h1>
|
||||
<p><?php echo $message ? $message : '虽然不知道你干啥了,但是确实操作成功了...'; ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-wrapper">
|
||||
<a href="<?php echo $url;?>"><button id="primary-button">好的,我知道了</button></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<style>
|
||||
html {
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: system-ui, PingFang SC, STHeiti, sans-serif;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: system-ui, PingFang SC, STHeiti, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
use app\ExceptionHandle;
|
||||
use app\Request;
|
||||
|
||||
// 容器Provider定义文件
|
||||
return [
|
||||
'think\Request' => Request::class,
|
||||
'think\exception\Handle' => ExceptionHandle::class,
|
||||
];
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\qfadmin;
|
||||
|
||||
use think\App;
|
||||
use think\facade\View;
|
||||
|
||||
use app\model\Admin as AdminModel;
|
||||
use app\model\Access as AccessModel;
|
||||
use app\model\Auth as AuthModel;
|
||||
use app\model\Node as NodeModel;
|
||||
use app\model\Group as GroupModel;
|
||||
use app\model\Conf as ConfModel;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
abstract class QfShop
|
||||
{
|
||||
/**
|
||||
* Request实例
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
protected $module;
|
||||
protected $controller;
|
||||
protected $action;
|
||||
|
||||
//模型
|
||||
protected $AdminModel;
|
||||
protected $accessModel;
|
||||
protected $authModel;
|
||||
protected $nodeModel;
|
||||
protected $groupModel;
|
||||
protected $confModel;
|
||||
|
||||
//主键key
|
||||
protected $pk = '';
|
||||
//表名称
|
||||
protected $table = '';
|
||||
//主键value
|
||||
protected $pk_value = '';
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
// 初始化
|
||||
protected function initialize()
|
||||
{
|
||||
$this->module = "qfadmin";
|
||||
$this->controller = $this->request->controller() ? $this->request->controller() : "Index";
|
||||
$this->action = strtolower($this->request->action()) ? strtolower($this->request->action()) : "index";
|
||||
View::assign('controller', strtolower($this->controller));
|
||||
View::assign('action', strtolower($this->action));
|
||||
|
||||
$this->table = strtolower($this->controller);
|
||||
$this->pk = $this->table . "_id";
|
||||
$this->pk_value = input($this->pk);
|
||||
|
||||
$this->adminModel = new AdminModel();
|
||||
$this->accessModel = new AccessModel();
|
||||
$this->authModel = new AuthModel();
|
||||
$this->nodeModel = new NodeModel();
|
||||
$this->groupModel = new GroupModel();
|
||||
$this->confModel = new ConfModel();
|
||||
|
||||
|
||||
$configs = $this->confModel->select()->toArray();
|
||||
$c = [];
|
||||
foreach ($configs as $config) {
|
||||
$c[$config['conf_key']] = $config['conf_value'];
|
||||
}
|
||||
config($c, 'yadmin');
|
||||
}
|
||||
/**
|
||||
* 后台简单的身份判断
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function access()
|
||||
{
|
||||
$callback = "/qfadmin";
|
||||
if (strtolower($this->controller) != "index") {
|
||||
$callback .= "/" . strtolower($this->controller);
|
||||
}
|
||||
if ($this->action != "index") {
|
||||
$callback .= "/" . $this->action;
|
||||
}
|
||||
$access_token = cookie('access_token');
|
||||
if (!$access_token) {
|
||||
return redirect('/qfadmin/admin/login/?callback=' . urlencode($callback));
|
||||
}
|
||||
View::assign("access_token", $access_token);
|
||||
$this->admin = $this->adminModel->getAdminByAccessToken($access_token);
|
||||
if (!$this->admin) {
|
||||
return redirect('/qfadmin/admin/login/?callback=' . urlencode($callback));
|
||||
}
|
||||
if ($this->admin['admin_status'] > 0) {
|
||||
return $this->error("抱歉,你的帐号已被禁用,暂时无法登录系统!");
|
||||
}
|
||||
cookie("access_token", $access_token);
|
||||
View::assign('adminInfo', $this->admin);
|
||||
$this->group = $this->groupModel->where('group_id', $this->admin['admin_group'])->find();
|
||||
if ($this->group) {
|
||||
if ($this->group['group_id'] != 1 && $this->group['group_status'] == 1) {
|
||||
return $this->error("抱歉,你所在的用户组已被禁用,暂时无法登录系统");
|
||||
} else {
|
||||
$menuList = $this->authModel->getAdminMenuListByAdminId($this->group['group_id']);
|
||||
View::assign('menuList', $menuList);
|
||||
|
||||
$node = $this->nodeModel->where(['node_module' => $this->module, 'node_controller' => strtolower($this->controller), 'node_action' => $this->action])->find();
|
||||
View::assign('node', $node);
|
||||
|
||||
if($node['node_pid']==0){
|
||||
View::assign('menu', 0);
|
||||
}else{
|
||||
$res = $this->nodeModel->where('node_id',$node['node_pid'])->find();
|
||||
View::assign('menu', $res['node_pid']);
|
||||
}
|
||||
$menuLists = [];
|
||||
foreach ($menuList as $key => $value) {
|
||||
if($value['node_id'] == $node['node_pid']){
|
||||
$menuLists = $value['subList'];
|
||||
}else{
|
||||
foreach ($value['subList'] as $k => $v) {
|
||||
if($v['node_id'] == $node['node_pid']){
|
||||
$menuLists = $value['subList'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
View::assign('menuLists', $menuLists);
|
||||
View::assign('action', $this->request->action());
|
||||
}
|
||||
} else {
|
||||
return $this->error("抱歉,没有查到你的用户组信息,暂时无法登录系统");
|
||||
}
|
||||
}
|
||||
protected function error($message)
|
||||
{
|
||||
echo $message;
|
||||
die;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace app\qfadmin\controller;
|
||||
|
||||
use app\qfadmin\QfShop;
|
||||
use think\facade\View;
|
||||
|
||||
class Error extends QfShop
|
||||
{
|
||||
/**
|
||||
* 监听所有请求 渲染对应控制器下方法的页面
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
// 判断是否是登录/注册/找回密码
|
||||
// 否则进行accesss授权验证 如错误 直接返回
|
||||
if (!(strtolower($this->controller) == "admin" && in_array(strtolower($this->action), ['login', 'resetpassword', 'reg']))) {
|
||||
$error = $this->access();
|
||||
if ($error) {
|
||||
return $error;
|
||||
}
|
||||
}else{
|
||||
cookie('access_token', null);
|
||||
}
|
||||
if (key_exists('callback', $args)) {
|
||||
View::assign('callback', $args['callback']);
|
||||
} else {
|
||||
View::assign('callback', '/qfadmin');
|
||||
}
|
||||
View::assign('datas', $args);
|
||||
return View::fetch();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-plus" size="small" @click="clickAdd" plain>添加</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-delete" size="small" @click="postMultDelete" plain>批量删除</el-button>
|
||||
</el-form-item>
|
||||
<div style="float:right">
|
||||
<el-form-item>
|
||||
<el-select placeholder="请选择状态" size="small" v-model="search.admin_status">
|
||||
<el-option value="" label="全部用户">
|
||||
</el-option>
|
||||
<el-option value="0" label="正常用户">
|
||||
</el-option>
|
||||
<el-option value="1" label="禁用用户">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="width:120px;">
|
||||
<el-select placeholder="筛选类别" size="small" v-model="search.filter">
|
||||
<el-option value="admin_id" label="用户ID">
|
||||
</el-option>
|
||||
<el-option value="admin_name" label="用户昵称">
|
||||
</el-option>
|
||||
<el-option value="admin_account" label="用户帐号">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="输入关键词搜索" size="small" v-model="search.keyword"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList_search" plain>搜索</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-table :data="dataList.data" @selection-change="changeSelection" v-loading="loading">
|
||||
<el-table-column type="selection" width="50">
|
||||
</el-table-column>
|
||||
<el-table-column prop="admin_id" label="ID" width="100">
|
||||
</el-table-column>
|
||||
<el-table-column prop="admin_account" label="帐号">
|
||||
</el-table-column>
|
||||
<el-table-column prop="admin_name" label="昵称">
|
||||
</el-table-column>
|
||||
<el-table-column prop="group_name" label="用户组">
|
||||
</el-table-column>
|
||||
<el-table-column prop="admin_ipreg" label="注册IP" width="150">
|
||||
</el-table-column>
|
||||
<el-table-column label="最后活跃" width="120">
|
||||
<template slot-scope="scope">
|
||||
{{time2string(scope.row.admin_updatetime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="注册时间" width="120">
|
||||
<template slot-scope="scope">
|
||||
{{time2string(scope.row.admin_createtime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="禁用" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.admin_status==1?true:false" active-color="#ff4949"
|
||||
@change="clickStatus(scope.row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="primary" @click="clickEdit(scope.row)" :underline="false">编辑</el-link>
|
||||
<el-link type="danger" @click="clickDelete(scope.row)" :underline="false">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
|
||||
<div class="page">
|
||||
<el-pagination @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100,200,500]" :page-size="10"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="changeCurrentPage"
|
||||
:current-page="dataList.current_page" :page-count="dataList.last_page" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- 添加框 -->
|
||||
<el-dialog title="添加用户" :visible.sync="dialogFormAdd" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formAdd" status-icon :rules="rules" ref="formAdd">
|
||||
<el-form-item label="帐号" :label-width="formLabelWidth" prop="admin_account">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.admin_account"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" :label-width="formLabelWidth" prop="admin_password">
|
||||
<el-input size="medium" show-password="true" autocomplete="off" v-model="formAdd.admin_password">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="昵称" :label-width="formLabelWidth" prop="admin_name">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.admin_name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" :label-width="formLabelWidth" prop="admin_email">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.admin_email"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="身份证" :label-width="formLabelWidth" prop="admin_idcard">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.admin_idcard"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="真实姓名" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.admin_truename"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户组" :label-width="formLabelWidth">
|
||||
<el-select size="medium" placeholder="请选择用户组" v-model="formAdd.admin_group">
|
||||
<el-option v-for="group_add in groupList" :value="group_add.group_id" :label="group_add.group_name">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postAdd">确认添加</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 修改框 -->
|
||||
<el-dialog title="修改用户" :visible.sync="dialogFormEdit" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formEdit" status-icon :rules="rules" ref="formEdit">
|
||||
<el-form-item label="帐号" :label-width="formLabelWidth" prop="admin_account">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.admin_account"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" :label-width="formLabelWidth" prop="new_password">
|
||||
<el-input size="medium" show-password="true" autocomplete="off" v-model="formEdit.new_password"
|
||||
placeholder="不修改请留空">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="昵称" :label-width="formLabelWidth" prop="admin_name">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.admin_name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" :label-width="formLabelWidth" prop="admin_email">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.admin_email"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="身份证" :label-width="formLabelWidth" prop="admin_idcard">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.admin_idcard"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="真实姓名" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.admin_truename"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="用户组" :label-width="formLabelWidth">
|
||||
<el-select size="medium" placeholder="请选择用户组" v-model="formEdit.admin_group">
|
||||
<el-option v-for="group_edit in groupList" :value="group_edit.group_id"
|
||||
:label="group_edit.group_name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postEdit">确认修改</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getList();
|
||||
return {
|
||||
search: {
|
||||
admin_status: "",
|
||||
keyword: "",
|
||||
filter: "admin_id"
|
||||
},
|
||||
formLabelWidth: '80px',
|
||||
dialogFormAdd: false,
|
||||
dialogFormEdit: false,
|
||||
loading: true,
|
||||
dataList: [],
|
||||
groupList: [],
|
||||
selectList: [],
|
||||
form: {
|
||||
page: 1,
|
||||
per_page: 10
|
||||
},
|
||||
formAdd: {
|
||||
admin_group: 1
|
||||
},
|
||||
formEdit: {
|
||||
admin_group: 1
|
||||
},
|
||||
rules: {
|
||||
admin_account: [
|
||||
{ required: true, message: '帐号必须填写', trigger: 'blur' },
|
||||
],
|
||||
admin_name: [
|
||||
{ required: true, message: '昵称必须填写', trigger: 'blur' },
|
||||
],
|
||||
admin_password: [
|
||||
{ required: true, message: '密码必须填写', trigger: 'blur' },
|
||||
// { required: true, pattern: /^(?=.*[a-z])(?=.*\d).{6,16}$/, message: '密码必须包含字母和数字(6-16位)', trigger: 'blur' },
|
||||
],
|
||||
new_password: [
|
||||
{ required: true, message: '密码必须填写', trigger: 'blur' },
|
||||
// { pattern: /^(?=.*[a-z])(?=.*\d).{6,16}$/, message: '密码必须包含字母和数字(6-16位)', trigger: 'blur' },
|
||||
],
|
||||
admin_email: [
|
||||
{ pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/, message: '邮箱格式不正确', trigger: 'blur' },
|
||||
],
|
||||
admin_idcard: [
|
||||
{ pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '身份证格式不正确', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getList_search() {
|
||||
this.form.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
time2string(timestamps) {
|
||||
var now = new Date(timestamps * 1000),
|
||||
y = now.getFullYear(),
|
||||
m = now.getMonth() + 1,
|
||||
d = now.getDate();
|
||||
// return y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d) + " " + now.toTimeString().substr(0, 8);
|
||||
return (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d) + " " + now.toTimeString().substr(0, 5);
|
||||
},
|
||||
handleSizeChange(per_page) {
|
||||
this.form.per_page = per_page;
|
||||
this.getList();
|
||||
},
|
||||
postMultDelete() {
|
||||
var that = this;
|
||||
if (that.selectList.length == 0) {
|
||||
that.$message.error('未选择任何用户!');
|
||||
return;
|
||||
}
|
||||
this.$confirm('即将删除选中的用户, 是否确认?', '批量删除', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/admin/delete', Object.assign({}, PostBase, {
|
||||
admin_id: that.selectList.join(",")
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
changeSelection(list) {
|
||||
var that = this;
|
||||
that.selectList = [];
|
||||
for (var index in list) {
|
||||
that.selectList.push(list[index].admin_id);
|
||||
}
|
||||
},
|
||||
postEdit() {
|
||||
var that = this;
|
||||
that.$refs['formEdit'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/admin/update', Object.assign({}, PostBase, that.formEdit))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormEdit = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
postAdd() {
|
||||
var that = this;
|
||||
that.$refs['formAdd'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/admin/add', Object.assign({}, PostBase, that.formAdd))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormAdd = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
clickAdd() {
|
||||
var that = this;
|
||||
that.formAdd = {
|
||||
admin_group: 1
|
||||
};
|
||||
axios.post('/admin/group/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
that.groupList = response.data.data;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dialogFormAdd = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickDelete(row) {
|
||||
var that = this;
|
||||
this.$confirm('即将删除这个用户, 是否确认?', '删除提醒', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/admin/delete', Object.assign({}, PostBase, {
|
||||
admin_id: row.admin_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
clickStatus(row) {
|
||||
var that = this;
|
||||
axios.post(row.admin_status ? '/admin/admin/enable' : '/admin/admin/disable', Object.assign({}, PostBase, {
|
||||
admin_id: row.admin_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickEdit(row) {
|
||||
var that = this;
|
||||
that.formEdit = row;
|
||||
axios.post('/admin/group/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.groupList = response.data.data;
|
||||
axios.post('/admin/admin/detail', Object.assign({}, PostBase, {
|
||||
admin_id: row.admin_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.formEdit = response.data.data;
|
||||
that.dialogFormEdit = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/admin/getList', Object.assign({}, PostBase, that.form, that.search))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,263 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>后台管理系统</title>
|
||||
<meta charset="UTF-8">
|
||||
<!-- import CSS -->
|
||||
<link rel="stylesheet" href="/static/admin/css/element.css">
|
||||
<link rel="stylesheet" href="/static/admin/css/YAdmin.css">
|
||||
<style>
|
||||
.login-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
min-width: 1280px;
|
||||
min-height: 800px;
|
||||
background: url(/static/admin/images/login_bg.jpg) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.login-container:before{
|
||||
content: " ";
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: url(/static/admin/images/login_bg_bottom.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
height: 170px;
|
||||
}
|
||||
.login-box img{
|
||||
width: 720px;
|
||||
}
|
||||
.login-border {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
top: -30px;
|
||||
right: 100px;
|
||||
}
|
||||
.login-main{
|
||||
background-color: #ffffff;
|
||||
padding: 35px 45px 15px 45px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.login-main .vadmin{
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #6881ec;
|
||||
line-height: 20px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
.login-logo {
|
||||
margin: 0 0 20px;
|
||||
}
|
||||
.login-logo p {
|
||||
color: #ffffff;
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.login-submit {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
.login-form {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.login-form .el-form-item__content {
|
||||
width: 270px;
|
||||
}
|
||||
.login-form .el-form-item {
|
||||
margin-bottom: 26px;
|
||||
}
|
||||
.login-form .el-input input {
|
||||
text-indent: 5px;
|
||||
border-color: #DCDCDC;
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.login-form .el-input .el-input__prefix i {
|
||||
padding: 0 5px;
|
||||
font-size: 16px !important;
|
||||
}
|
||||
.login-code {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.login-code-img {
|
||||
margin-top: 1px;
|
||||
width: 100px;
|
||||
height: 38px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app" v-cloak>
|
||||
<div id="app" v-cloak>
|
||||
<div class="login-container">
|
||||
<div class="login-box">
|
||||
<img src="/static/admin/images/login_bg_box.png">
|
||||
</div>
|
||||
<div class="login-border">
|
||||
<div class="login-logo">
|
||||
<p>后台登录</p>
|
||||
</div>
|
||||
<div class="login-main">
|
||||
<p class="vadmin">管理员登录</p>
|
||||
<el-form class="login-form" status-icon :rules="loginRules" ref="loginForm" :model="loginForm"
|
||||
label-width="0" size="default">
|
||||
<el-form-item prop="admin_account">
|
||||
<el-input @keyup.enter.native="handleLogin()" v-model="loginForm.admin_account"
|
||||
auto-complete="off" placeholder="请输入账号">
|
||||
<i slot="prefix" class="el-icon-user"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="admin_password">
|
||||
<el-input @keyup.enter.native="handleLogin()" v-model="loginForm.admin_password" show-password
|
||||
auto-complete="off" placeholder="请输入密码">
|
||||
<i slot="prefix" class="el-icon-key"></i>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="codeUrl" prop="admin_code">
|
||||
<el-row :span="34">
|
||||
<el-col :span="14">
|
||||
<el-input @keyup.enter.native="handleLogin()" v-model="loginForm.admin_code"
|
||||
auto-complete="off" placeholder="请输入验证码">
|
||||
<i slot="prefix" class="el-icon-mobile"></i>
|
||||
</el-input>
|
||||
</el-col>
|
||||
<el-col :span="10">
|
||||
<div class="login-code">
|
||||
<img :src="codeUrl" class="login-code-img" @click="getCaptcha" alt="" />
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :loading="loading" @click.native.prevent="handleLogin"
|
||||
class="login-submit">登 录
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/static/admin/js/vue-2.6.10.min.js"></script>
|
||||
<script src="/static/admin/js/axios.min.js"></script>
|
||||
<script src="/static/admin/js/element.js"></script>
|
||||
<script src="/static/admin/js/YAdmin.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
codeUrl: '',
|
||||
codeToken: '',
|
||||
loading: false,
|
||||
loginForm: {
|
||||
admin_account: '',
|
||||
admin_password: '',
|
||||
admin_code: '',
|
||||
},
|
||||
loginRules: {
|
||||
admin_account: [
|
||||
{ required: true, message: '请输入账号', trigger: 'blur' }
|
||||
],
|
||||
admin_password: [
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{ min: 6, message: '密码长度最少为6位', trigger: 'blur' }
|
||||
],
|
||||
admin_code: [
|
||||
{ required: true, message: '请输入验证码', trigger: 'blur' },
|
||||
{ min: 4, max: 4, message: '验证码长度为4位', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getCaptcha();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @description 正式登录
|
||||
*/
|
||||
handleLogin() {
|
||||
var that = this;
|
||||
this.$refs.loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
this.loginForm.token = this.codeToken
|
||||
axios.post('/admin/admin/login', Object.assign({}, PostBase, this.loginForm))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: '登录成功,正在跳转中',
|
||||
type: 'success'
|
||||
});
|
||||
setTimeout(function () {
|
||||
location.replace('/qfadmin');
|
||||
}, 1000)
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
that.loading = false
|
||||
that.getCaptcha();
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('登录失败,服务器内部错误');
|
||||
that.loading = false
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
onSubmit() {
|
||||
var that = this;
|
||||
axios.post('/admin/admin/login', Object.assign({}, PostBase, this.form))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: '登录成功,正在跳转中',
|
||||
type: 'success'
|
||||
});
|
||||
setTimeout(function () {
|
||||
location.replace('{$callback}');
|
||||
}, 1000)
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('登录失败,服务器内部错误');
|
||||
});
|
||||
},
|
||||
getCaptcha() {
|
||||
var that = this;
|
||||
axios.post('/admin/system/getCaptcha', Object.assign({}, PostBase))
|
||||
.then(function (res) {
|
||||
that.codeUrl = res.data.data.img
|
||||
that.codeToken = res.data.data.token
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('获取失败');
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
<el-card class="box-card" shadow="never">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>修改我的密码</span>
|
||||
</div>
|
||||
<div class="text item">
|
||||
<el-form :model="form" status-icon :rules="rules" ref="form" label-width="80px">
|
||||
<el-form-item label="原密码" prop="oldPassword">
|
||||
<el-input show-password v-model="form.oldPassword" placeholder="请输入原密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="newPassword">
|
||||
<el-input show-password password="password" v-model="form.newPassword" placeholder="请输入新密码">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="checkPassword">
|
||||
<el-input show-password v-model="form.checkPassword" placeholder="请确认新密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">修改密码</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-card>
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
oldPassword: "",
|
||||
newPassword: "",
|
||||
checkPassword: "",
|
||||
},
|
||||
rules: {
|
||||
oldPassword: [
|
||||
{ required: true, message: '原密码必须输入', trigger: 'blur' },
|
||||
],
|
||||
newPassword: [
|
||||
{ required: true, message: '必须输入', trigger: 'blur' },
|
||||
],
|
||||
checkPassword: [
|
||||
{ required: true, message: '必须输入', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
var that = this;
|
||||
that.$refs['form'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
if (that.form.newPassword != that.form.checkPassword) {
|
||||
that.$message.error('两次密码输入不一致,请确认');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/admin/motifypassword', Object.assign({}, PostBase, {
|
||||
oldPassword: that.form.oldPassword,
|
||||
newPassword: that.form.newPassword,
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
setTimeout(function () {
|
||||
location.href = "/qfadmin/admin/login";
|
||||
}, 2000);
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
<el-card class="box-card" shadow="never">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>修改我的资料</span>
|
||||
</div>
|
||||
<div class="text item">
|
||||
<el-form :model="form" status-icon :rules="rules" ref="form" label-width="80px">
|
||||
<el-form-item label="昵称" prop="admin_name">
|
||||
<el-input v-model="form.admin_name" placeholder="请输入你的昵称"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="姓名" prop="admin_truename">
|
||||
<el-input v-model="form.admin_truename" placeholder="请输入你的真实姓名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="admin_email">
|
||||
<el-input v-model="form.admin_email" placeholder="请输入你的邮箱"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="身份证" prop="admin_idcard">
|
||||
<el-input v-model="form.admin_idcard" placeholder="请输入你的身份证"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">更新资料</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-card>
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getData();
|
||||
return {
|
||||
form: {
|
||||
},
|
||||
rules: {
|
||||
admin_name: [
|
||||
{ required: true, message: '昵称必须填写', trigger: 'blur' },
|
||||
],
|
||||
admin_email: [
|
||||
{ pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/, message: '邮箱格式不正确', trigger: 'blur' },
|
||||
],
|
||||
admin_idcard: [
|
||||
{ pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '身份证格式不正确', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
var that = this;
|
||||
axios.post('/admin/admin/getmyinfo', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.form = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
onSubmit() {
|
||||
var that = this;
|
||||
that.$refs['form'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
if (that.form.newPassword != that.form.checkPassword) {
|
||||
that.$message.error('两次密码输入不一致,请确认');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/admin/updateMyInfo', Object.assign({}, PostBase, that.form))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,214 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-upload class="upload-demo" action="/admin/attach/uploadImage" :on-success="handleUploadSuccess"
|
||||
:file-list="fileList" :show-file-list="false" :before-upload="beforeUpload" :data="postData"
|
||||
v-loading.fullscreen.lock="fullscreenLoading">
|
||||
<el-button size="small" type="primary">上传图片</el-button>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-delete" size="small" @click="postMultDelete" plain>批量删除</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="dataList.data" @selection-change="changeSelection" v-loading="loading">
|
||||
<el-table-column type="selection" width="50">
|
||||
</el-table-column>
|
||||
<el-table-column prop="attach_id" label="ID" width="60">
|
||||
</el-table-column>
|
||||
<el-table-column label="文件预览" width="120">
|
||||
<template slot-scope="scope">
|
||||
<div style="display: flex;align-items: center;">
|
||||
<el-link :href="scope.row.attach_path" :underline="false" target="_blank">
|
||||
<el-image style="width: 80px; height: 80px;flex:none;margin-right: 10px;background-color: #f8f8f9;border-radius: 6px;"
|
||||
fit="contain" :src="scope.row.attach_path">
|
||||
</el-image>
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="attach_name" label="文件名称">
|
||||
</el-table-column>
|
||||
<el-table-column prop="attach_size" label="附件大小" width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="附件类型" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag size="medium" type="warning">{{scope.row.attach_type.toUpperCase()}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="danger" @click="clickDelete(scope.row)" :underline="false">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<div class="page">
|
||||
<el-pagination @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100,200,500]" :page-size="10"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="changeCurrentPage"
|
||||
:current-page="dataList.current_page" :page-count="dataList.last_page" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getList();
|
||||
return {
|
||||
fullscreenLoading: false,
|
||||
search: {
|
||||
keyword: "",
|
||||
filter: "attach_phone"
|
||||
},
|
||||
loading: true,
|
||||
dataList: [],
|
||||
selectList: [],
|
||||
fileList: [],
|
||||
form: {
|
||||
page: 1,
|
||||
per_page: 10,
|
||||
},
|
||||
postData: PostBase,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleUploadSuccess(res, file) {
|
||||
this.fullscreenLoading = false;
|
||||
if (res.code == CODE_SUCCESS) {
|
||||
this.$message({
|
||||
message: res.message,
|
||||
type: 'success'
|
||||
});
|
||||
this.getList();
|
||||
} else {
|
||||
this.$message.error(res.message);
|
||||
}
|
||||
},
|
||||
beforeUpload(file) {
|
||||
const isImage = file.type === 'image/jpeg' || file.type === 'image/png';
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
if (!isImage) {
|
||||
this.$message.error('上传图片只能是 JPG/PNG 格式!');
|
||||
}
|
||||
if (!isLt2M) {
|
||||
this.$message.error('上传头像图片大小不能超过 2MB!');
|
||||
}
|
||||
this.fullscreenLoading = true;
|
||||
return isImage && isLt2M;
|
||||
},
|
||||
handleSizeChange(per_page) {
|
||||
this.form.per_page = per_page;
|
||||
this.getList();
|
||||
},
|
||||
time2string(timestamps, formatStr = 'MM-dd hh:mm') {
|
||||
var now = new Date(timestamps * 1000),
|
||||
y = now.getFullYear(),
|
||||
m = now.getMonth() + 1,
|
||||
d = now.getDate();
|
||||
return y + "-" + (m < 10 ? "0" + m : m) + "-" + (d < 10 ? "0" + d : d) + " " + now.toTimeString().substr(0, 8);
|
||||
},
|
||||
postMultDelete() {
|
||||
var that = this;
|
||||
if (that.selectList.length == 0) {
|
||||
that.$message.error('未选择任何附件!');
|
||||
return;
|
||||
}
|
||||
this.$confirm('即将删除选中的附件, 是否确认?', '批量删除', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/attach/delete', Object.assign({}, PostBase, {
|
||||
attach_id: that.selectList.join(",")
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => { });
|
||||
},
|
||||
changeSelection(list) {
|
||||
var that = this;
|
||||
that.selectList = [];
|
||||
for (var index in list) {
|
||||
that.selectList.push(list[index].attach_id);
|
||||
}
|
||||
},
|
||||
clickAdd() {
|
||||
var that = this;
|
||||
that.formAdd = {};
|
||||
that.dialogFormAdd = true;
|
||||
},
|
||||
clickDelete(row) {
|
||||
var that = this;
|
||||
this.$confirm('即将删除这个附件, 是否确认?', '删除提醒', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/attach/delete', Object.assign({}, PostBase, {
|
||||
attach_id: row.attach_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => { });
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/attach/getList', Object.assign({}, PostBase, that.form, that.search))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,19 @@
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<Uploads ref="upload"></Uploads>
|
||||
<Goodslists ref="goodslist"></Goodslists>
|
||||
</div>
|
||||
</body>
|
||||
{include file="component/view"/}
|
||||
<script src="/static/admin/js/vue-2.6.10.min.js"></script>
|
||||
<script src="/static/admin/js/axios.min.js"></script>
|
||||
<script src="/static/admin/js/element.js"></script>
|
||||
<script src="/static/admin/js/YAdmin.js"></script>
|
||||
<script src="/static/admin/js/SkuForm.umd.js"></script>
|
||||
<script src="/static/admin/UEditor/vue-ueditor-wrap.min.js"></script>
|
||||
<script src="/static/admin/UEditor/ueditor.config.js"></script>
|
||||
<script src="/static/admin/UEditor/ueditor.all.js"></script>
|
||||
<script src="/static/admin/js/component.js"></script>
|
||||
<script src="/static/admin/js/Sortable.min.js"></script>
|
||||
<script src="/static/admin/js/vuedraggable.umd.min.js"></script>
|
||||
@@ -0,0 +1,67 @@
|
||||
<meta charset="UTF-8">
|
||||
<!-- import CSS -->
|
||||
<link rel="stylesheet" href="/static/admin/css/element.css">
|
||||
<link rel="stylesheet" href="/static/admin/css/YAdmin.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app" v-cloak>
|
||||
<el-container>
|
||||
<el-header>
|
||||
<el-col style="width: auto;">
|
||||
<el-menu class="el-menu-vertical" text-color="#333333" :default-active="'{if condition="$node.node_pid"}{$node.node_pid}{else}{$node.node_id}{/if}'" unique-opened
|
||||
style="border:none;" mode="horizontal" active-text-color="#333333">
|
||||
{volist name="menuList" id="item"}
|
||||
{if condition="count($item.subList)>0"}
|
||||
{if condition="count($item.subList[0]['subList'])>0"}
|
||||
<el-menu-item index="{$item.node_id}"
|
||||
onclick="location.href='/{$item['subList'][0]['subList'][0]['node_module']}/{$item['subList'][0]['subList'][0]['node_controller']}/{$item['subList'][0]['subList'][0]['node_action']}';"
|
||||
{if
|
||||
condition="$menu==$item.node_id"
|
||||
}class="is-active" {/if}>
|
||||
<i class="{$item.node_icon}"></i> {$item.node_title}
|
||||
</el-menu-item>
|
||||
{else}
|
||||
<el-menu-item index="{$item.node_id}"
|
||||
onclick="location.href='/{$item['subList'][0]['node_module']}/{$item['subList'][0]['node_controller']}/{$item['subList'][0]['node_action']}';" {if
|
||||
condition="$menu==$item.node_id"
|
||||
}class="is-active" {/if}>
|
||||
<i class="{$item.node_icon}"></i> {$item.node_title}
|
||||
</el-menu-item>
|
||||
{/if}
|
||||
{else}
|
||||
{if condition="count($item.subList)>0 || $item.node_controller=='index'"}
|
||||
<el-menu-item index="{$item.node_id}"
|
||||
onclick="location.href='/{$item.node_module}/{$item.node_controller}/{$item.node_action}';" {if
|
||||
condition="$menu==$item.node_id"
|
||||
}class="is-active" {/if}>
|
||||
<i class="{$item.node_icon}"></i> {$item.node_title}
|
||||
</el-menu-item>
|
||||
{/if}
|
||||
{/if}
|
||||
{/volist}
|
||||
</el-menu>
|
||||
</el-col>
|
||||
|
||||
<el-col style="width: 240px;float: right;">
|
||||
<span class="topArea">
|
||||
<el-link :underline="false" class="el-icon-full-screen menuicon" onclick="requestFullScreen()"></el-link>
|
||||
<!-- <el-link :underline="false" class="el-icon-brush menuicon"></el-link> -->
|
||||
<el-dropdown>
|
||||
<el-link :underline="false"> {$adminInfo['admin_name']}<i class="el-icon-arrow-down"></i></el-link>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item onclick="location.href='/qfadmin/admin/updatemyinfo';">修改资料
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item onclick="location.href='/qfadmin/admin/motifypassword';">修改密码
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item onclick="location.href='/qfadmin/system/clean';">清除缓存
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item onclick="logout()">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-header>
|
||||
<el-container class="body">
|
||||
{include file="common/menu"/}
|
||||
<el-main>
|
||||
@@ -0,0 +1,47 @@
|
||||
<meta charset="UTF-8">
|
||||
<!-- import CSS -->
|
||||
<link rel="stylesheet" href="/static/admin/css/element.css">
|
||||
<link rel="stylesheet" href="/static/admin/css/YAdmin.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app" v-cloak>
|
||||
<el-container>
|
||||
<el-header>
|
||||
<el-col style="width: auto;">
|
||||
<el-menu class="el-menu-vertical" text-color="#333333" unique-opened
|
||||
style="border:none;" mode="horizontal" active-text-color="#333333">
|
||||
<el-menu-item onclick="location.href='./index.html?meeting_id={$datas.meeting_id??''}'" {if
|
||||
condition="$action=='index'"
|
||||
}class="is-active" {/if}>
|
||||
<i class="el-icon-user-solid"></i> 客户管理
|
||||
</el-menu-item>
|
||||
<el-menu-item onclick="location.href='./team.html?meeting_id={$datas.meeting_id??''}'" {if
|
||||
condition="$action=='team'"
|
||||
}class="is-active" {/if}>
|
||||
<i class="el-icon-s-custom"></i> 团队管理
|
||||
</el-menu-item>
|
||||
<el-menu-item onclick="location.href='./valetor.html?meeting_id={$datas.meeting_id??''}'" {if
|
||||
condition="$action=='valetor'"
|
||||
}class="is-active" {/if}>
|
||||
<i class="el-icon-s-help"></i> 会务人员管理
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
|
||||
<el-col style="width: 240px;float: right;">
|
||||
<span class="topArea">
|
||||
<el-link :underline="false" class="el-icon-full-screen menuicon" onclick="requestFullScreen()"></el-link>
|
||||
<!-- <el-link :underline="false" class="el-icon-brush menuicon"></el-link> -->
|
||||
<el-dropdown>
|
||||
<el-link :underline="false"> {$adminInfo['admin_name']}<i class="el-icon-arrow-down"></i></el-link>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item onclick="logout()">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-header>
|
||||
<el-container class="body">
|
||||
{include file="common/menu"/}
|
||||
<el-main>
|
||||
@@ -0,0 +1,44 @@
|
||||
{if condition="$menuLists"}
|
||||
<el-aside width="160px">
|
||||
<a class="titlehome" href="/qfadmin" style="display: block;height: 62px;line-height: 62px;text-align: center;"><img src="/static/admin/images/logo.png" width="40px" style="vertical-align: middle;" /></a>
|
||||
<el-menu class="el-menu-vertical-demo" text-color="#333333" default-active="'{$node.node_pid}-{$node.node_id}'" :collapse="false" :default-openeds="['{$node.node_pid}']">
|
||||
{volist name="menuLists" id="item"}
|
||||
{if condition="count($item.subList)>0"}
|
||||
<el-submenu index="{$item.node_id}">
|
||||
<template slot="title">
|
||||
<i {if condition='$item.node_icon'}class="{$item.node_icon}"{else}class="el-icon-menu"{/if}></i> {$item.node_title}
|
||||
</template>
|
||||
{volist name="$item.subList" id="subItem"}
|
||||
<el-menu-item onclick="location.href='/{$subItem.node_module}/{$subItem.node_controller}/{$subItem.node_action}';"
|
||||
index="{$item.node_id}-{$subItem.node_id}" {if
|
||||
condition="$subItem.node_controller==strtolower($controller) && $subItem.node_action==strtolower($action)"
|
||||
}class="is-active" {/if}>{$subItem.node_title}</el-menu-item>
|
||||
{/volist}
|
||||
</el-submenu>
|
||||
{else}
|
||||
{if condition="$item.node_controller=='' && $item.node_action==''"}
|
||||
<el-menu-item index="{$item.node_id}" onclick="testalert('暂无该功能')">
|
||||
<i {if condition='$item.node_icon' }class="{$item.node_icon}" {else}class="el-icon-menu" {/if}></i>
|
||||
{$item.node_title}
|
||||
</el-menu-item>
|
||||
{else}
|
||||
<el-menu-item index="{$item.node_id}"
|
||||
onclick="location.href='/{$item.node_module}/{$item.node_controller}/{$item.node_action}';" {if
|
||||
condition="$item.node_controller==strtolower($controller) && $item.node_action==strtolower($action)"
|
||||
}class="is-active" {/if}>
|
||||
<i {if condition='$item.node_icon' }class="{$item.node_icon}" {else}class="el-icon-menu" {/if}></i>
|
||||
{$item.node_title}
|
||||
</el-menu-item>
|
||||
{/if}
|
||||
{/if}
|
||||
{/volist}
|
||||
<div style="height: 120px;"></div>
|
||||
</el-menu>
|
||||
<div class="version">资源管理系统<br> Version 1.0.0</div>
|
||||
</el-aside>
|
||||
{else}
|
||||
<div style="position: absolute;top: -72px;left: 0;width: 160px;background-color: #ffffff;box-shadow: 0 0 12px 0 rgb(47 75 168 / 6%);border-radius: 12px;">
|
||||
<a class="title" href="/admin" style="display: block;height: 62px;line-height: 62px;text-align: center;"><img
|
||||
src="/static/admin/images/logo.png" width="40px" style="vertical-align: middle;" /></a>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,152 @@
|
||||
<template id="Upload">
|
||||
<el-dialog title="图片库" :visible.sync="visible" :modal-append-to-body='false' append-to-body :close-on-click-modal="false"
|
||||
width="725px">
|
||||
<div class="upload-boxs">
|
||||
<el-upload class="upload-right" action="/admin/attach/uploadImage" :on-success="handleUploadSuccess"
|
||||
:file-list="fileList" :show-file-list="false" :before-upload="beforeUpload" :data="postData"
|
||||
v-loading.fullscreen.lock="fullscreenLoading">
|
||||
<el-button size="small" type="primary" icon="el-icon-upload">上传图片</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
<ul class="storage-list">
|
||||
<li :class="item.select?'active':''" v-for="(item, index) in dataList.data" :key="index" @click="select(index)">
|
||||
<el-image fit="contain" :src="item.attach_path"></el-image>
|
||||
<p>{{item.attach_name}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p v-if="dataList.data&&dataList.data.length==0" style="text-align: center;">暂无资源</p>
|
||||
<el-pagination @current-change="changeCurrentPage" layout="prev, pager, next" :current-page="dataList.current_page"
|
||||
:page-count="dataList.last_page" hide-on-single-page background>
|
||||
</el-pagination>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<div style="float: left; font-size: 13px;">
|
||||
<span v-if="multiple">
|
||||
当前已选 <span style="color: #F56C6C;">{{selectList.length+selected_num}}</span> 个,最多允许选择 <span
|
||||
style="color: #F56C6C;">{{total_num}}</span> 个资源
|
||||
</span>
|
||||
<span v-else>当前已选 <span style="color: #F56C6C;">{{selectList.length}}</span> 个资源</span>
|
||||
</div>
|
||||
<el-button @click="visible = false" size="small">取消</el-button>
|
||||
<el-button type="primary" @click="save" size="small">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
|
||||
<template id="Single">
|
||||
<div class="slectimg" v-if="multiple">
|
||||
<block v-if="value.length>0">
|
||||
<draggable v-model="value" chosenClass="chosen" forceFallback="true" animation="600" @start="onStart"
|
||||
@end="onEnd">
|
||||
<transition-group>
|
||||
<div class="imgs" v-for="(v, s) in value" :key="s" style="cursor: all-scroll;">
|
||||
<el-image fit="contain" :src="v" :preview-src-list="value" :z-index="s"></el-image>
|
||||
<!-- <el-image fit="contain" :src="v" ></el-image> -->
|
||||
<i class="close el-icon-error" @click="deles(s)"></i>
|
||||
</div>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</block>
|
||||
<div class="noimg" @click="selectimg()">
|
||||
<i class="el-icon-plus"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="slectimg" v-else>
|
||||
<div class="imgs" v-if="value.length>0">
|
||||
<el-image fit="contain" :src="value" :preview-src-list="[value]"></el-image>
|
||||
<i class="close el-icon-error" @click="deles()"></i>
|
||||
</div>
|
||||
<div class="noimg" v-else @click="selectimg()">
|
||||
<i class="el-icon-plus"></i>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="Ueditor">
|
||||
<Ueditors v-model="value" ref="Ueditor" :config="config"></Ueditors>
|
||||
</template>
|
||||
|
||||
|
||||
<template id="skuforms">
|
||||
<div>
|
||||
<div style="padding-bottom: 10px;">
|
||||
<el-input style="width: 120px;" v-if="inputVisible" v-model="inputValue" ref="saveTagInput" size="small"
|
||||
@keyup.enter.native="handleInputConfirm" placeholder="回车确定">
|
||||
</el-input>
|
||||
<el-button v-else class="button-new-tag" size="small" @click="showInput" style="width: 120px;">+添加规格组</el-button>
|
||||
</div>
|
||||
<sku-form :source-attribute="sourceAttribute" :attribute.sync="attribute" :structure="structure" :sku.sync="sku"
|
||||
ref="skuForm"></sku-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<template id="Goodslist">
|
||||
<el-dialog title="商品库" :before-close="handleClose" :visible.sync="visible" :modal-append-to-body='false' append-to-body
|
||||
:close-on-click-modal="false" width="900px">
|
||||
|
||||
<el-form :inline="true">
|
||||
<div style="float:right">
|
||||
<el-form-item style="width:100px; margin-bottom: 0;">
|
||||
<el-cascader v-model="search.classify" placeholder="商品分类" :options="categoryList" :props="cascaderProps"
|
||||
style="width: 100%;" filterable clearable size="small" :show-all-levels="false">
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom: 0;">
|
||||
<el-input placeholder="输入商品名称搜索" size="small" v-model="search.keyword" @keyup.enter.native="getList_search"
|
||||
clearable @clear="getList_search"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item style="margin-bottom: 0;">
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList_search" plain>搜索
|
||||
</el-button>
|
||||
<el-button icon="el-icon-refresh-left" size="small" @click="getList_search(0)" plain>重置</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<el-table :data="dataList.data" ref="multipleTable" @selection-change="changeSelection" row-key="goods_id" reserve-selection="true" style="min-height: 425px;" v-loading="loading">
|
||||
<el-table-column align="center" type="selection" reserve-selection="true" width="55"></el-table-column>
|
||||
|
||||
<el-table-column label="商品" prop="goods_id" min-width="380">
|
||||
<template slot-scope="scope">
|
||||
<el-image class="goods-image" style="width: 50px;height: 50px;" :src="scope.row.picture[0]" :preview-src-list="[scope.row.picture[0]]"
|
||||
fit="contain" lazy></el-image>
|
||||
|
||||
<div class="goods-info cs-ml">
|
||||
<p class="action" style="overflow:hidden;text-overflow:ellipsis;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;">
|
||||
<span :title="scope.row.goods_name" class="link">{{scope.row.goods_name}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="本店价" prop="goods_price">
|
||||
<template slot-scope="scope">
|
||||
<div class="action">
|
||||
<span class="goods-shop-price">{{scope.row.goods_price}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="库存" prop="stock_total">
|
||||
<template slot-scope="scope">
|
||||
<div class="action">
|
||||
<span>{{scope.row.stock_total}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<p style="padding-bottom: 10px;">
|
||||
<el-pagination hide-on-single-page="true" layout="prev, pager, next" background :current-page="form.page" @current-change="changeCurrentPage" :page-size="5" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</p>
|
||||
<p>
|
||||
<el-button @click="cancels" size="small">取消</el-button>
|
||||
<el-button type="primary" @click="save" size="small">确定</el-button>
|
||||
</p>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -0,0 +1,194 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
<el-card class="box-card" shadow="never">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane :label="item.name" :name="item.val" v-for="(item, index) in tabname" :key="index" v-if="item.show">
|
||||
<div class="base_form" style="padding-right: 220px;">
|
||||
<el-form ref="form" label-width="220px">
|
||||
<block v-for="(items, indexs) in form" :key="indexs">
|
||||
<el-form-item :label="items.conf_title?items.conf_title:items.conf_key" v-if="items.conf_type==item.val">
|
||||
<block v-if="items.conf_spec==1">
|
||||
<el-input type="textarea" :rows="4" v-model="items.conf_value"></el-input>
|
||||
</block>
|
||||
<block v-else-if="items.conf_spec==2">
|
||||
<el-radio v-model="items.conf_value" v-for="(val, key) in items.conf_content" :key="key" :label="val.value">{{val.name}}</el-radio>
|
||||
</block>
|
||||
<block v-else-if="items.conf_spec==3">
|
||||
<el-checkbox-group v-model="items.conf_value">
|
||||
<el-checkbox v-for="(val, key) in items.conf_content" :key="key" :label="val.value">{{val.name}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</block>
|
||||
<block v-else-if="items.conf_spec==4">
|
||||
<Single v-model="items.conf_value"/>
|
||||
</block>
|
||||
<block v-else-if="items.conf_spec==5">
|
||||
<Single v-model="items.conf_value" multiple="true" :selected_num="items.conf_value.length"/>
|
||||
</block>
|
||||
<block v-else-if="items.conf_spec==6">
|
||||
<Ueditor v-model="items.conf_value"></Ueditor>
|
||||
</block>
|
||||
<block v-else-if="items.conf_spec==7">
|
||||
<el-color-picker v-model="items.conf_value"></el-color-picker>
|
||||
</block>
|
||||
<block v-else>
|
||||
<el-input v-model="items.conf_value"></el-input>
|
||||
</block>
|
||||
<span class="f_tips">{{items.conf_desc}}<span v-if="items.conf_spec==5"> 最多上传10张</span></span>
|
||||
</el-form-item>
|
||||
</block>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit(item.val)">保存配置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
</el-card>
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getData();
|
||||
return {
|
||||
form: [],
|
||||
activeName: "0",
|
||||
tabname: [
|
||||
{
|
||||
name: '基础设置',
|
||||
val: '0',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: 'SEO设置',
|
||||
val: '9',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: '前端模版',
|
||||
val: '3',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: '搜索设置',
|
||||
val: '1',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: '微信设置',
|
||||
val: '8',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: '交易设置',
|
||||
val: '10',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: '售后设置',
|
||||
val: '11',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: '上传配置',
|
||||
val: '2',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
name: '其他配置',
|
||||
val: '4',
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getData() {
|
||||
var that = this;
|
||||
axios.post('/admin/conf/getBaseConfig', Object.assign({}, PostBase))
|
||||
.then(function (res) {
|
||||
if (res.data.code == 200) {
|
||||
for (let item of res.data.data) {
|
||||
if (item.conf_spec == 2) {
|
||||
for (let i = 0; i < item.conf_content.length; i++) {
|
||||
let d = item.conf_content[i].split("=>");
|
||||
item.conf_content[i] = {
|
||||
name: d[0].toString(),
|
||||
value: d[1].toString()
|
||||
}
|
||||
}
|
||||
}else if(item.conf_spec==3){
|
||||
for (let i = 0; i < item.conf_content.length; i++) {
|
||||
let d = item.conf_content[i].split("=>");
|
||||
item.conf_content[i] = {
|
||||
name: d[0].toString(),
|
||||
value: d[1].toString()
|
||||
}
|
||||
}
|
||||
if(item.conf_value){
|
||||
item.conf_value = item.conf_value.split(",");
|
||||
}else{
|
||||
item.conf_value = []
|
||||
}
|
||||
}else if (item.conf_spec == 5) {
|
||||
if(item.conf_value){
|
||||
item.conf_value = item.conf_value.split(",");
|
||||
for (let i = 0; i < item.conf_value.length; i++) {
|
||||
if (!item.conf_value[i]) {
|
||||
item.conf_value.splice(i, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
item.conf_value = []
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < that.tabname.length; i++) {
|
||||
if(that.tabname[i].val == item.conf_type){
|
||||
that.tabname[i].show = true
|
||||
}
|
||||
}
|
||||
}
|
||||
that.form = res.data.data;
|
||||
} else {
|
||||
that.$message.error(res.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
onSubmit(index) {
|
||||
var that = this;
|
||||
var postData = {};
|
||||
for (var i = 0; i < that.form.length; i++) {
|
||||
if(that.form[i].conf_type == index){
|
||||
postData[that.form[i].conf_key] = that.form[i].conf_value;
|
||||
}
|
||||
}
|
||||
axios.post('/admin/conf/updateBaseConfig', Object.assign({}, PostBase, postData))
|
||||
.then(function (res) {
|
||||
if (res.data.code == 200) {
|
||||
that.$message({
|
||||
message: res.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(res.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,468 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-plus" size="small" @click="clickAdd" plain>添加</el-button>
|
||||
</el-form-item>
|
||||
<div style="float:right">
|
||||
<el-form-item style="width:120px;">
|
||||
<el-select placeholder="筛选类别" size="small" v-model="search.filter">
|
||||
<el-option value="conf_id" label="参数ID">
|
||||
</el-option>
|
||||
<el-option value="conf_title" label="参数名称">
|
||||
</el-option>
|
||||
<el-option value="conf_key" label="参数字段">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="输入关键词搜索" size="small" v-model="search.keyword"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList_search" plain>搜索</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-table :data="dataList.data" @selection-change="changeSelection" v-loading="loading">
|
||||
<el-table-column prop="conf_id" label="ID" width="60">
|
||||
</el-table-column>
|
||||
<el-table-column prop="conf_type" label="所属分类" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-tag size="small" type="success" v-if="scope.row.conf_type==1">搜索设置</el-tag>
|
||||
<el-tag size="small" type="warning" v-else-if="scope.row.conf_type==2">上传配置</el-tag>
|
||||
<el-tag size="small" type="info" v-else-if="scope.row.conf_type==3">前端模版</el-tag>
|
||||
<el-tag size="small" type="danger" v-else-if="scope.row.conf_type==4">其他配置</el-tag>
|
||||
<el-tag size="small" type="success" v-else-if="scope.row.conf_type==5">微信支付配置</el-tag>
|
||||
<el-tag size="small" type="warning" v-else-if="scope.row.conf_type==6">支付宝支付配置</el-tag>
|
||||
<el-tag size="small" type="success" v-else-if="scope.row.conf_type==7">微信小程序配置</el-tag>
|
||||
<el-tag size="small" type="danger" v-else-if="scope.row.conf_type==8">微信公众号配置</el-tag>
|
||||
<el-tag size="small" type="danger" v-else-if="scope.row.conf_type==9">SEO设置</el-tag>
|
||||
<el-tag size="small" type="danger" v-else-if="scope.row.conf_type==10">交易设置</el-tag>
|
||||
<el-tag size="small" type="danger" v-else-if="scope.row.conf_type==11">售后设置</el-tag>
|
||||
<el-tag size="small" v-else>基础设置</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="conf_title" label="参数名称">
|
||||
</el-table-column>
|
||||
<el-table-column prop="conf_desc" label="参数描述">
|
||||
</el-table-column>
|
||||
<el-table-column prop="conf_key" label="参数字段">
|
||||
<template slot-scope="scope">
|
||||
<el-tooltip class="item" effect="dark" :content="scope.row.conf_title" placement="top">
|
||||
<el-link>{{scope.row.conf_key}}</el-link>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="conf_sort" label="排序" width="90">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="primary" @click="clickEdit(scope.row)" :underline="false">编辑</el-link>
|
||||
<el-link type="danger" @click="clickDelete(scope.row)" :underline="false" v-if="scope.row.conf_system==0">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<div class="page">
|
||||
<el-pagination @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100,200,500]" :page-size="10"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="changeCurrentPage"
|
||||
:current-page="dataList.current_page" :page-count="dataList.last_page" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- 添加框 -->
|
||||
<el-dialog title="添加配置" :visible.sync="dialogFormAdd" width="800px" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formAdd" status-icon :rules="rules" ref="formAdd">
|
||||
<el-form-item label="所属分类" :label-width="formLabelWidth" prop="conf_type">
|
||||
<el-select v-model="formAdd.conf_type" placeholder="请选择所属分类" size="medium">
|
||||
<el-option label="基础设置" value="0"></el-option>
|
||||
<el-option label="SEO设置" value="9"></el-option>
|
||||
<el-option label="搜索设置" value="1"></el-option>
|
||||
<el-option label="上传配置" value="2"></el-option>
|
||||
<el-option label="前端模版" value="3"></el-option>
|
||||
<el-option label="其他配置" value="4"></el-option>
|
||||
<el-option label="微信支付配置" value="5"></el-option>
|
||||
<el-option label="支付宝支付配置" value="6"></el-option>
|
||||
<el-option label="微信小程序配置" value="7"></el-option>
|
||||
<el-option label="微信公众号配置" value="8"></el-option>
|
||||
<el-option label="交易设置" value="10"></el-option>
|
||||
<el-option label="售后设置" value="11"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数名称" :label-width="formLabelWidth" prop="conf_title">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.conf_title"></el-input>
|
||||
<span style="color: #999;">参数名称,如:网站LOGO</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数字段" :label-width="formLabelWidth" prop="conf_key">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.conf_key"></el-input>
|
||||
<span style="color: #999;">参数字段,如:logo</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数描述" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.conf_desc"></el-input>
|
||||
<span style="color: #999;">参数描述,如:建议尺寸: 300*300</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段类型" :label-width="formLabelWidth">
|
||||
<el-radio-group v-model="formAdd.conf_spec" size="small">
|
||||
<el-radio-button label="0">文本框</el-radio-button>
|
||||
<el-radio-button label="1">多行文本框</el-radio-button>
|
||||
<el-radio-button label="2">单选框</el-radio-button>
|
||||
<el-radio-button label="3">多选框</el-radio-button>
|
||||
<el-radio-button label="4">单图</el-radio-button>
|
||||
<el-radio-button label="5">多图</el-radio-button>
|
||||
<el-radio-button label="6">富文本</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-input v-if="formAdd.conf_spec==2 || formAdd.conf_spec==3" type="textarea" v-model="formAdd.conf_content"
|
||||
:rows="4" placeholder="参数方式例如: 开启=>1 关闭=>0" style="margin-top: 10px;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="显示隐藏" :label-width="formLabelWidth">
|
||||
<el-switch size="medium" v-model="formAdd.conf_status"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" :label-width="formLabelWidth">
|
||||
<el-input-number v-model="formAdd.conf_sort" :min="0" :max="999" size="medium" style="width: 120px;" controls-position="right" />
|
||||
</el-form-item>
|
||||
<el-form-item label="系统参数" :label-width="formLabelWidth">
|
||||
<el-switch size="medium" v-model="formAdd.conf_system"></el-switch>
|
||||
<div style="color: #999;">开启后,添加的参数将无法删除</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postAdd">确认添加</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 修改框 -->
|
||||
<el-dialog title="修改配置" :visible.sync="dialogFormEdit" width="800px" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formEdit" status-icon :rules="rules" ref="formEdit">
|
||||
<el-form-item label="所属分类" :label-width="formLabelWidth" prop="conf_type">
|
||||
<el-select v-model="formEdit.conf_type" placeholder="请选择所属分类" size="medium">
|
||||
<el-option label="基础设置" value="0"></el-option>
|
||||
<el-option label="SEO设置" value="9"></el-option>
|
||||
<el-option label="搜索设置" value="1"></el-option>
|
||||
<el-option label="上传配置" value="2"></el-option>
|
||||
<el-option label="前端模版" value="3"></el-option>
|
||||
<el-option label="其他配置" value="4"></el-option>
|
||||
<el-option label="微信支付配置" value="5"></el-option>
|
||||
<el-option label="支付宝支付配置" value="6"></el-option>
|
||||
<el-option label="微信小程序配置" value="7"></el-option>
|
||||
<el-option label="微信公众号配置" value="8"></el-option>
|
||||
<el-option label="交易设置" value="10"></el-option>
|
||||
<el-option label="售后设置" value="11"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数名称" :label-width="formLabelWidth" prop="conf_title">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.conf_title"></el-input>
|
||||
<span style="color: #999;">参数名称,如:网站LOGO</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数字段" :label-width="formLabelWidth" prop="conf_key">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.conf_key"></el-input>
|
||||
<span style="color: #6881ec;">参数字段,切勿随意修改</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="参数描述" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.conf_desc"></el-input>
|
||||
<span style="color: #999;">参数描述,如:建议尺寸: 300*300</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="字段类型" :label-width="formLabelWidth">
|
||||
<el-radio-group v-model="formEdit.conf_spec" size="small">
|
||||
<el-radio-button label="0">文本框</el-radio-button>
|
||||
<el-radio-button label="1">多行文本框</el-radio-button>
|
||||
<el-radio-button label="2">单选框</el-radio-button>
|
||||
<el-radio-button label="3">多选框</el-radio-button>
|
||||
<el-radio-button label="4">单图</el-radio-button>
|
||||
<el-radio-button label="5">多图</el-radio-button>
|
||||
<el-radio-button label="6">富文本</el-radio-button>
|
||||
<el-radio-button label="7">颜色选择</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-input v-if="formEdit.conf_spec==2 || formEdit.conf_spec==3" type="textarea" v-model="formEdit.conf_content" :rows="4" placeholder="参数方式例如: 开启=>1 关闭=>0" style="margin-top: 10px;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="显示隐藏" :label-width="formLabelWidth">
|
||||
<el-switch size="medium" v-model="formEdit.conf_status"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" :label-width="formLabelWidth">
|
||||
<el-input-number v-model="formEdit.conf_sort" :min="0" :max="999" size="medium" style="width: 120px;"
|
||||
controls-position="right" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postEdit">确认修改</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getList();
|
||||
return {
|
||||
search: {
|
||||
keyword: "",
|
||||
filter: "conf_id"
|
||||
},
|
||||
formLabelWidth: '80px',
|
||||
dialogFormAdd: false,
|
||||
dialogFormEdit: false,
|
||||
loading: true,
|
||||
dataList: [],
|
||||
selectList: [],
|
||||
form: {
|
||||
page: 1,
|
||||
per_page: 10
|
||||
},
|
||||
formAdd: {
|
||||
conf_status: true,
|
||||
conf_spec: 0,
|
||||
conf_sort: 0,
|
||||
},
|
||||
formEdit: {},
|
||||
rules: {
|
||||
conf_title: [
|
||||
{ required: true, message: '参数名称必须填写', trigger: 'blur' },
|
||||
],
|
||||
conf_key: [
|
||||
{ required: true, message: '参数字段必须填写', trigger: 'blur' },
|
||||
],
|
||||
conf_type: [
|
||||
{ required: true, message: '所属分类必须填写', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getList_search() {
|
||||
this.form.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleSizeChange(per_page) {
|
||||
this.form.per_page = per_page;
|
||||
this.getList();
|
||||
},
|
||||
postMultDelete() {
|
||||
var that = this;
|
||||
if (that.selectList.length == 0) {
|
||||
that.$message.error('未选择任何配置!');
|
||||
return;
|
||||
}
|
||||
this.$confirm('即将删除选中的配置, 是否确认?', '批量删除', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/conf/delete', Object.assign({}, PostBase, {
|
||||
conf_id: that.selectList.join(",")
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
changeSelection(list) {
|
||||
var that = this;
|
||||
that.selectList = [];
|
||||
for (var index in list) {
|
||||
that.selectList.push(list[index].conf_id);
|
||||
}
|
||||
},
|
||||
postEdit() {
|
||||
var that = this;
|
||||
that.$refs['formEdit'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/conf/update', Object.assign({}, PostBase, that.formEdit))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormEdit = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
postAdd() {
|
||||
var that = this;
|
||||
that.$refs['formAdd'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/conf/add', Object.assign({}, PostBase, that.formAdd))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormAdd = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
clickAdd() {
|
||||
var that = this;
|
||||
that.formAdd = {
|
||||
conf_status: true,
|
||||
conf_spec: 0,
|
||||
conf_sort: 0,
|
||||
};
|
||||
axios.post('/admin/conf/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
that.groupList = response.data.data;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dialogFormAdd = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickDelete(row) {
|
||||
var that = this;
|
||||
this.$confirm('即将删除这个配置, 是否确认?', '删除提醒', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/conf/delete', Object.assign({}, PostBase, {
|
||||
conf_id: row.conf_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
clickStatus(row) {
|
||||
var that = this;
|
||||
axios.post(row.conf_status ? '/admin/conf/enable' : '/admin/conf/disable', Object.assign({}, PostBase, {
|
||||
conf_id: row.conf_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickEdit(row) {
|
||||
var that = this;
|
||||
that.formEdit = row;
|
||||
axios.post('/admin/conf/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.groupList = response.data.data;
|
||||
axios.post('/admin/conf/detail', Object.assign({}, PostBase, {
|
||||
conf_id: row.conf_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
response.data.data.conf_status = response.data.data.conf_status?true:false;
|
||||
response.data.data.conf_type = response.data.data.conf_type.toString();
|
||||
that.formEdit = response.data.data;
|
||||
that.dialogFormEdit = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/conf/getList', Object.assign({}, PostBase, that.form, that.search))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,408 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-plus" size="small" @click="clickAdd" plain>添加</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-delete" size="small" @click="postMultDelete" plain>批量删除</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="dataList" @selection-change="changeSelection" v-loading="loading">
|
||||
<el-table-column type="selection" width="50">
|
||||
</el-table-column>
|
||||
<el-table-column prop="group_id" label="组ID" width="100">
|
||||
</el-table-column>
|
||||
<el-table-column prop="group_name" label="组名称" width="200">
|
||||
</el-table-column>
|
||||
<el-table-column prop="group_desc" label="组描述">
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column label="禁用" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.group_status==1?true:false" active-color="#ff4949"
|
||||
@change="clickStatus(scope.row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="primary" @click="clickEdit(scope.row)" :underline="false">编辑</el-link>
|
||||
<el-link type="primary" @click="clickAuth(scope.row)" :underline="false">授权</el-link>
|
||||
<el-link type="danger" @click="clickDelete(scope.row)" :underline="false">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
|
||||
|
||||
<!-- 添加框 -->
|
||||
<el-dialog title="添加用户组" :visible.sync="dialogFormAdd" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formAdd" status-icon :rules="rules" ref="formAdd">
|
||||
<el-form-item label="组名称" :label-width="formLabelWidth" prop="group_name">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.group_name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="组描述" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.group_desc"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postAdd">确认添加</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 修改框 -->
|
||||
<el-dialog title="修改用户组" :visible.sync="dialogFormEdit" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formEdit" status-icon :rules="rules" ref="formEdit">
|
||||
<el-form-item label="组名称" :label-width="formLabelWidth" prop="group_name">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.group_name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="组描述" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.group_desc"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postEdit">确认修改</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 授权框 -->
|
||||
<el-dialog class="pub_dialog" title="用户组授权" :visible.sync="dialogFormAuth" :modal-append-to-body='false' append-to-body
|
||||
width="60%" :close-on-click-modal='false'>
|
||||
<div style="padding: 10px 30px;">
|
||||
<el-tree :data="nodeList" @check="currentChecked" show-checkbox node-key="node_id" :props="defaultProps" :default-checked-keys="defaultkeys"></el-tree>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postAuth">确认授权</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getList();
|
||||
return {
|
||||
checkAll: false,
|
||||
search: {
|
||||
group_status: "",
|
||||
keyword: "",
|
||||
filter: "group_id"
|
||||
},
|
||||
formLabelWidth: '80px',
|
||||
dialogFormAdd: false,
|
||||
dialogFormEdit: false,
|
||||
dialogFormAuth: false,
|
||||
loading: true,
|
||||
dataList: [],
|
||||
groupList: [],
|
||||
selectList: [],
|
||||
selectNodeList: [],
|
||||
selectedGroupId: 0,
|
||||
nodeList: [],
|
||||
defaultProps: {
|
||||
children: 'sub',
|
||||
label: 'node_title'
|
||||
},
|
||||
defaultkeys: [],
|
||||
form: {
|
||||
page: 1
|
||||
},
|
||||
formAdd: {},
|
||||
formEdit: {},
|
||||
rules: {
|
||||
group_name: [
|
||||
{ required: true, message: '组名称必须填写', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
postMultDelete() {
|
||||
var that = this;
|
||||
if (that.selectList.length == 0) {
|
||||
that.$message.error('未选择任何用户!');
|
||||
return;
|
||||
}
|
||||
this.$confirm('即将删除选中的用户, 是否确认?', '批量删除', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/group/delete', Object.assign({}, PostBase, {
|
||||
group_id: that.selectList.join(",")
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
changeSelection(list) {
|
||||
var that = this;
|
||||
that.selectList = [];
|
||||
for (var index in list) {
|
||||
that.selectList.push(list[index].group_id);
|
||||
}
|
||||
},
|
||||
postAuth() {
|
||||
var that = this;
|
||||
axios.post('/admin/group/authorize', Object.assign({}, PostBase, {
|
||||
node_ids: that.selectNodeList.join(','),
|
||||
group_id: that.selectedGroupId
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormAuth = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
postEdit() {
|
||||
var that = this;
|
||||
that.$refs['formEdit'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/group/update', Object.assign({}, PostBase, that.formEdit))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormEdit = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
postAdd() {
|
||||
var that = this;
|
||||
that.$refs['formAdd'].validate((valid) => {
|
||||
if (!valid) {
|
||||
that.$message.error('仔细检查检查,是不是有个地方写得不对?');
|
||||
return;
|
||||
}
|
||||
axios.post('/admin/group/add', Object.assign({}, PostBase, that.formAdd))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormAdd = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
},
|
||||
clickAdd() {
|
||||
var that = this;
|
||||
that.formAdd = {};
|
||||
axios.post('/admin/group/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
that.groupList = response.data.data;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dialogFormAdd = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickDelete(row) {
|
||||
var that = this;
|
||||
this.$confirm('即将删除这个用户, 是否确认?', '删除提醒', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/group/delete', Object.assign({}, PostBase, {
|
||||
group_id: row.group_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
clickStatus(row) {
|
||||
var that = this;
|
||||
axios.post(row.group_status ? '/admin/group/enable' : '/admin/group/disable', Object.assign({}, PostBase, {
|
||||
group_id: row.group_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickAuth(row) {
|
||||
var that = this;
|
||||
that.selectNodeList = [];
|
||||
that.selectedGroupId = row.group_id;
|
||||
axios.post('/admin/node/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.nodeList = response.data.data.data;
|
||||
that.dialogFormAuth = true;
|
||||
that.getAuthList(row);
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
getAuthList(row) {
|
||||
var that = this;
|
||||
that.defaultkeys = [];
|
||||
axios.post('/admin/group/getAuthorize', Object.assign({}, PostBase, {
|
||||
group_id: row.group_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.defaultkeys = [];
|
||||
for (var i in response.data.data) {
|
||||
that.defaultkeys.push(response.data.data[i].auth_node);
|
||||
}
|
||||
that.dialogFormAuth = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('设置选中状态失败');
|
||||
});
|
||||
},
|
||||
|
||||
currentChecked(nodeObj, SelectedObj) {
|
||||
this.selectNodeList = SelectedObj.checkedKeys
|
||||
},
|
||||
clickEdit(row) {
|
||||
var that = this;
|
||||
that.formEdit = row;
|
||||
axios.post('/admin/group/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.groupList = response.data.data;
|
||||
axios.post('/admin/group/detail', Object.assign({}, PostBase, {
|
||||
group_id: row.group_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.formEdit = response.data.data;
|
||||
that.dialogFormEdit = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/group/getList', Object.assign({}, PostBase, that.form, that.search))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>后台管理系统</title>
|
||||
{include file="common/header"/}
|
||||
<div class="homecontainer" style="height: 100%;display: flex;align-items: center;justify-content: center;">
|
||||
<div>
|
||||
<img src="/static/admin/images/logo@2x.png" alt="">
|
||||
<p style="color: #999999;">@资源管理系统</p>
|
||||
</div>
|
||||
</div>
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
data: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-table :data="dataList.data" v-loading="loading">
|
||||
<el-table-column prop="id" label="ID" align="center" width="100">
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="name">
|
||||
</el-table-column>
|
||||
<el-table-column prop="ip" label="IP">
|
||||
</el-table-column>
|
||||
<el-table-column prop="domain" label="address">
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="创建时间" align="center" width="200">
|
||||
</el-table-column>
|
||||
<el-table-column prop="update_time" label="最新时间" align="center" width="200">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<div class="page">
|
||||
<el-pagination @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100,200,500]" :page-size="10"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="changeCurrentPage"
|
||||
:current-page="dataList.current_page" :page-count="dataList.last_page" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
dataList: [],
|
||||
form: {
|
||||
page: 1,
|
||||
per_page: 10,
|
||||
order: 'id desc'
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(per_page) {
|
||||
this.form.per_page = per_page;
|
||||
this.getList();
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/log/getList', Object.assign({}, PostBase, that.form))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
for (let i = 0; i < that.dataList.data.length; i++) {
|
||||
if(!that.dataList.data[i].domain){
|
||||
that.getAdd(i)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
},
|
||||
getAdd(index){
|
||||
var that = this;
|
||||
axios.get('https://api.suyanw.cn/api/ipcha.php?ip='+that.dataList.data[index].ip)
|
||||
.then(function (res) {
|
||||
that.dataList.data[index].domain = res.data.text
|
||||
axios.post('/admin/log/setDomain', Object.assign({}, PostBase, {
|
||||
id: that.dataList.data[index].id,
|
||||
domain: that.dataList.data[index].domain,
|
||||
}))
|
||||
.then(function (response) {
|
||||
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,462 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-plus" size="small" @click="clickAdd" plain>添加</el-button>
|
||||
</el-form-item>
|
||||
<div style="float:right">
|
||||
<el-form-item style="width:120px;">
|
||||
<el-select placeholder="显示状态" size="small" v-model="search.node_show">
|
||||
<el-option value="" label="全部状态">
|
||||
</el-option>
|
||||
<el-option v-for="show in showList" :value="show.show_id" :label="show.show_title">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="width:120px;">
|
||||
<el-select placeholder="筛选类别" size="small" v-model="search.filter">
|
||||
<el-option value="node_id" label="节点ID">
|
||||
</el-option>
|
||||
<el-option value="node_title" label="节点名称">
|
||||
</el-option>
|
||||
<el-option value="node_desc" label="节点描述">
|
||||
</el-option>
|
||||
<el-option value="node_module" label="模块">
|
||||
</el-option>
|
||||
<el-option value="node_controller" label="控制器">
|
||||
</el-option>
|
||||
<el-option value="node_action" label="方法">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="输入关键词搜索" size="small" v-model="search.keyword"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList_search" plain>搜索</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-table :data="dataList" default-expand-all @selection-change="changeSelection" v-loading="loading" row-key="node_id" :tree-props="{children: 'sub', hasChildren: 'hasChildren'}">
|
||||
<el-table-column prop="node_id" label="ID" width="120">
|
||||
</el-table-column>
|
||||
<el-table-column prop="node_title" label="节点名称">
|
||||
<template slot-scope="scope">
|
||||
<i :class="scope.row.node_icon" style="font-size: 16px;"></i> {{scope.row.node_title}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="节点地址">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.node_module+"/"+scope.row.node_controller+"/"+scope.row.node_action}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="node_order" label="排序" width="">
|
||||
</el-table-column>
|
||||
<el-table-column label="隐藏" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.node_show==0?true:false" active-color="#ff4949"
|
||||
@change="clickShow(scope.row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="primary" @click="clickEdit(scope.row)" :underline="false">编辑</el-link>
|
||||
<el-link type="danger" @click="clickDelete(scope.row)" :underline="false">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- 添加框 -->
|
||||
<el-dialog title="添加节点" :visible.sync="dialogFormAdd" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formAdd" status-icon :rules="rules" ref="formAdd">
|
||||
<el-form-item label="节点名称" :label-width="formLabelWidth" prop="node_title">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.node_title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点描述" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.node_desc"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点图标" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.node_icon"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属模块" :label-width="formLabelWidth" prop="node_module">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.node_module"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="控制器" :label-width="formLabelWidth" prop="node_controller">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.node_controller"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="方法" :label-width="formLabelWidth" prop="node_action">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.node_action"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否显示" :label-width="formLabelWidth">
|
||||
<el-select placeholder="请选择是否显示到菜单" size="small" v-model="formAdd.node_show">
|
||||
<el-option v-for="show in showList" :value="show.show_id" :label="show.show_title">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="父级菜单" :label-width="formLabelWidth">
|
||||
<el-select placeholder="请选择菜单" size="small" v-model="formAdd.node_pid">
|
||||
<el-option v-for="parent in parentList" :value="parent.node_id" :label="parent.node_title">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="父级菜单" :label-width="formLabelWidth">
|
||||
<el-cascader :options="parentList" v-model="formAdd.node_pid" :props="props" :show-all-levels="false">
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="显示顺序" :label-width="formLabelWidth" prop="node_order">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.node_order"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postAdd">确认添加</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 修改框 -->
|
||||
<el-dialog title="修改节点" :visible.sync="dialogFormEdit" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formEdit" status-icon :rules="rules" ref="formEdit">
|
||||
<el-form-item label="节点名称" :label-width="formLabelWidth" prop="node_title">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.node_title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点描述" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.node_desc"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="节点图标" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.node_icon"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="所属模块" :label-width="formLabelWidth" prop="node_module">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.node_module"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="控制器" :label-width="formLabelWidth" prop="node_controller">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.node_controller"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="方法" :label-width="formLabelWidth" prop="node_action">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.node_action"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否显示" :label-width="formLabelWidth">
|
||||
<el-select placeholder="请选择是否显示到菜单" size="small" v-model="formEdit.node_show">
|
||||
<el-option v-for="show in showList" :value="show.show_id" :label="show.show_title">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="父级菜单" :label-width="formLabelWidth">
|
||||
<el-cascader :options="parentList" v-model="formEdit.node_pid" :props="props" :show-all-levels="false"></el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="显示顺序" :label-width="formLabelWidth" prop="node_order">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.node_order"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postEdit">确认修改</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getList();
|
||||
return {
|
||||
search: {
|
||||
node_show: "",
|
||||
keyword: "",
|
||||
filter: "node_id"
|
||||
},
|
||||
formLabelWidth: '80px',
|
||||
dialogFormAdd: false,
|
||||
dialogFormEdit: false,
|
||||
loading: true,
|
||||
dataList: [],
|
||||
parentList: [],
|
||||
props: {
|
||||
checkStrictly: true,
|
||||
emitPath: false,
|
||||
value: 'node_id',
|
||||
label: 'node_title',
|
||||
children: 'sub',
|
||||
},
|
||||
showList: [
|
||||
{
|
||||
show_id: 0,
|
||||
show_title: "隐藏"
|
||||
},
|
||||
{
|
||||
show_id: 1,
|
||||
show_title: "显示"
|
||||
}
|
||||
],
|
||||
selectList: [],
|
||||
formAdd: {
|
||||
node_readonly: 0,
|
||||
node_pid: 0,
|
||||
node_order: 1,
|
||||
node_show: 1,
|
||||
},
|
||||
formEdit: {
|
||||
node_readonly: 0,
|
||||
node_pid: 0,
|
||||
},
|
||||
rules: {
|
||||
node_title: [
|
||||
{ required: true, message: '节点名称必须填写', trigger: 'blur' },
|
||||
],
|
||||
node_controller: [
|
||||
// { required: true, pattern: /^[a-z]+$/, message: '控制器为有效小写字母', trigger: 'blur' },
|
||||
],
|
||||
node_module: [
|
||||
{ required: true, pattern: /^[a-z]+$/, message: '模块名为有效小写字母', trigger: 'blur' },
|
||||
],
|
||||
node_action: [
|
||||
{ required: true, pattern: /^[a-z]+$/, message: '方法名为有效小写字母', trigger: 'blur' },
|
||||
],
|
||||
node_order: [
|
||||
{ required: true, pattern: /^\d$/, message: '顺序为有效自然数', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getList_search() {
|
||||
this.form.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
postMultDelete() {
|
||||
var that = this;
|
||||
if (that.selectList.length == 0) {
|
||||
that.$message.error('未选择任何节点!');
|
||||
return;
|
||||
}
|
||||
this.$confirm('即将删除选中的节点, 是否确认?', '批量删除', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/node/delete', Object.assign({}, PostBase, {
|
||||
node_id: that.selectList.join(",")
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
changeSelection(list) {
|
||||
var that = this;
|
||||
that.selectList = [];
|
||||
for (var index in list) {
|
||||
that.selectList.push(list[index].node_id);
|
||||
}
|
||||
},
|
||||
postEdit() {
|
||||
var that = this;
|
||||
axios.post('/admin/node/update', Object.assign({}, PostBase, that.formEdit))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormEdit = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
postAdd() {
|
||||
var that = this;
|
||||
axios.post('/admin/node/add', Object.assign({}, PostBase, that.formAdd))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormAdd = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickAdd() {
|
||||
var that = this;
|
||||
that.formAdd = {
|
||||
node_readonly: 0,
|
||||
node_pid: 0,
|
||||
node_order: 1,
|
||||
node_show: 1,
|
||||
};
|
||||
axios.post('/admin/node/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
that.groupList = response.data.data;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dialogFormAdd = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickDelete(row) {
|
||||
var that = this;
|
||||
this.$confirm('即将删除这个节点, 是否确认?', '删除提醒', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/node/delete', Object.assign({}, PostBase, {
|
||||
node_id: row.node_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
clickShow(row) {
|
||||
var that = this;
|
||||
axios.post(row.node_show ? '/admin/node/hide_menu' : '/admin/node/show_menu', Object.assign({}, PostBase, {
|
||||
node_id: row.node_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickEdit(row) {
|
||||
var that = this;
|
||||
that.formEdit = row;
|
||||
axios.post('/admin/node/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.groupList = response.data.data;
|
||||
axios.post('/admin/node/detail', Object.assign({}, PostBase, {
|
||||
node_id: row.node_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
response.data.data.node_pid = response.data.data.node_pid==0?'0':response.data.data.node_pid
|
||||
that.formEdit = response.data.data;
|
||||
that.dialogFormEdit = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/node/getList', Object.assign({}, PostBase, that.form, that.search))
|
||||
.then(function (res) {
|
||||
that.loading = false;
|
||||
if (res.data.code == 200) {
|
||||
that.dataList = JSON.parse(JSON.stringify(res.data.data.data));
|
||||
that.parentList = [];
|
||||
that.parentList.push({
|
||||
node_id: "0",
|
||||
node_title: "顶级菜单",
|
||||
sub: [],
|
||||
});
|
||||
for (var i in res.data.data.data) {
|
||||
res.data.data.data[i].node_id = res.data.data.data[i].node_id
|
||||
that.parentList.push(res.data.data.data[i]);
|
||||
}
|
||||
for (let item of that.parentList) {
|
||||
if(item.sub.length>0){
|
||||
for (let items of item.sub) {
|
||||
items.sub = undefined
|
||||
}
|
||||
}else{
|
||||
item.sub = undefined
|
||||
}
|
||||
}
|
||||
} else {
|
||||
that.$message.error(res.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,324 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>资源分类</title>
|
||||
{include file="common/header"/}
|
||||
<el-form :inline="true">
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-plus" size="small" @click="clickAdd" plain>添加</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-warning-outline" size="small" @click="dayShow=true" plain>如何每日更新?</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-warning-outline" size="small" @click="allShow=true" plain>如何全部转存?</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="dataList" @selection-change="changeSelection" v-loading="loading">
|
||||
<el-table-column type="selection" width="50">
|
||||
</el-table-column>
|
||||
<el-table-column prop="source_category_id" label="ID" width="60">
|
||||
</el-table-column>
|
||||
<el-table-column label="分类名称">
|
||||
<template slot-scope="scope">
|
||||
<img :src="scope.row.image" style="width: 30px;height:30px;vertical-align: middle;" v-if="scope.row.image" />
|
||||
<span style="vertical-align: middle;margin-left: 5px">{{scope.row.name}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否每日更新" width="150" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.is_update==1?true:false"
|
||||
@change="clickStatus(scope.row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="是否前台展示" width="150" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.status==1?false:true"
|
||||
@change="clickStatus(scope.row)">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" label="排序" width="150" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-link type="primary" @click="s2Btn(scope.row)" :underline="false">一键转存</el-link>
|
||||
<el-link type="primary" @click="clickEdit(scope.row)" :underline="false">编辑</el-link>
|
||||
<el-link type="danger" @click="clickDelete(scope.row)" :underline="false">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<!-- 添加框 -->
|
||||
<el-dialog title="添加资源分类名称" :visible.sync="dialogFormAdd" width="500px" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formAdd" :rules="rules" ref="formAdd">
|
||||
|
||||
<el-form-item prop="name" label="分类名称" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formAdd.name"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="image" label="图标" :label-width="formLabelWidth">
|
||||
<Single v-model="formAdd.image"></Single>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sort" label="排序" :label-width="formLabelWidth">
|
||||
<el-input-number v-model="formAdd.sort" :min="0" :max="999" size="medium" style="width: 120px;"
|
||||
controls-position="right" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postAdd()">确认添加</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 修改框 -->
|
||||
<el-dialog title="修改资源分类信息" :visible.sync="dialogFormEdit" width="500px" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<el-form :model="formEdit" :rules="rules" ref="formEdit">
|
||||
<el-form-item prop="name" label="分类名称" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" v-model="formEdit.name" disabled ></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="image" label="图标" :label-width="formLabelWidth">
|
||||
<Single v-model="formEdit.image"></Single>
|
||||
</el-form-item>
|
||||
<el-form-item prop="sort" label="排序" :label-width="formLabelWidth">
|
||||
<el-input-number v-model="formEdit.sort" :min="0" :max="999" size="medium" style="width: 120px;"
|
||||
controls-position="right" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postEdit()">确认修改</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 每日更新 -->
|
||||
<el-dialog title="每日更新" :visible.sync="dayShow" width="500px" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<div style="margin-bottom: 20px;font-size:14px;color:#666;line-height: 2">
|
||||
<p>自动更新:<font color=orangered>转存当日及昨天的资源数据;</font></p>
|
||||
<font color=orangered>将此接口添加到计划任务中,计划任务每日执行一次即可;</font>
|
||||
<p>接口地址:{{domain}}/api/source/day</p>
|
||||
<p>Tips:添加计划任务后方可生效;名称重复的资源会跳过转存;</p>
|
||||
<p>宝塔任务类型:访问URL-GET</p>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 全部更新 -->
|
||||
<el-dialog title="全部转存" :visible.sync="allShow" width="500px" :modal-append-to-body='false' append-to-body :close-on-click-modal='false'>
|
||||
<div style="margin-bottom: 20px;font-size:14px;color:#666;line-height: 2">
|
||||
<p>全部转存:<font color=orangered>一键转存心悦搜索所有资源到自己的网盘及系统中</font></p>
|
||||
<font color=orangered>全部转存速度比较慢,提交后请耐心等待;名称重复的资源会跳过转存;</font>
|
||||
<p>全部转存需要按类别转存:见下方列表一键转存按钮</p>
|
||||
<p>Tips:心悦搜索:https://pan.xinyuedh.com;</p>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
this.getList();
|
||||
return {
|
||||
formLabelWidth: '80px',
|
||||
dialogFormAdd: false,
|
||||
dialogFormEdit: false,
|
||||
loading: true,
|
||||
dataList: [],
|
||||
selectList: [],
|
||||
formAdd: {
|
||||
image: '',
|
||||
sort: 0
|
||||
},
|
||||
formEdit: {
|
||||
},
|
||||
rules: {
|
||||
name: [ { required: true, message: '请输入分类名称', trigger: 'blur' }],
|
||||
},
|
||||
|
||||
allShow: false,
|
||||
dayShow: false,
|
||||
domain: window.location.protocol+'//'+window.location.host
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeSelection(list) {
|
||||
var that = this;
|
||||
that.selectList = [];
|
||||
for (var index in list) {
|
||||
that.selectList.push(list[index].source_category_id);
|
||||
}
|
||||
},
|
||||
postEdit() {
|
||||
var that = this;
|
||||
that.$refs["formEdit"].validate((valid) => {
|
||||
if (valid) {
|
||||
axios.post('/admin/source_category/update', Object.assign({}, PostBase, that.formEdit))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormEdit = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
postAdd() {
|
||||
var that = this;
|
||||
that.$refs['formAdd'].validate((valid) => {
|
||||
if (valid) {
|
||||
axios.post('/admin/source_category/add', Object.assign({}, PostBase, that.formAdd))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormAdd = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
clickAdd() {
|
||||
var that = this;
|
||||
that.formAdd = { sort: 0,image: '' };
|
||||
that.dialogFormAdd = true;
|
||||
},
|
||||
clickDelete(row) {
|
||||
var that = this;
|
||||
this.$confirm('即将删除这个分类, 是否确认?', '删除提醒', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/source_category/delete', Object.assign({}, PostBase, {
|
||||
source_category_id: row.source_category_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
clickStatus(row) {
|
||||
var that = this;
|
||||
axios.post(row.status ? '/admin/source_category/enable' : '/admin/source_category/disable', Object.assign({}, PostBase, {
|
||||
source_category_id: row.source_category_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
clickEdit(row) {
|
||||
var that = this;
|
||||
that.formEdit = row;
|
||||
axios.post('/admin/source_category/detail', Object.assign({}, PostBase, {
|
||||
source_category_id: row.source_category_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.formEdit = response.data.data;
|
||||
that.formEdit.image = that.formEdit.image||''
|
||||
that.dialogFormEdit = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/source_category/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
s2Btn(row){
|
||||
let that = this
|
||||
if(row.source_category_id!=1) return that.$message.error('当前版本仅支持短剧');
|
||||
this.$confirm('全部转存速度比较慢,提交后请耐心等待,该操作不可暂停, 是否继续?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/source/transferAll', Object.assign({}, PostBase,{
|
||||
source_category_id: row.source_category_id
|
||||
}))
|
||||
.then(function (res) {
|
||||
if (res.data.code == 200) {
|
||||
} else {
|
||||
that.$message.error(res.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
});
|
||||
that.$message({
|
||||
message: "已提交任务,稍后查看结果",
|
||||
type: 'success'
|
||||
});
|
||||
}).catch(() => {});
|
||||
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,116 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
<style>
|
||||
textarea{
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
{include file="common/header"/}
|
||||
<el-card class="box-card" shadow="never">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>目前仅支持夸克</span>
|
||||
</div>
|
||||
<div class="text item">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>设置夸克cookie</span>
|
||||
</div>
|
||||
<div style="font-size:14px;color:#666;">
|
||||
<el-form :model="form">
|
||||
<el-form-item>
|
||||
<el-input style="width: 100%;" v-model="form.cookie" placeholder="夸克云盘网页版的cookie"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<p>Tips:夸克云盘网页版的cookie,不懂如何获取请百度;填写并保存后才能使用下面功能</p>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-card>
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
cookie: '',
|
||||
},
|
||||
file: '',
|
||||
files: [],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getData();
|
||||
// this.getFile()
|
||||
},
|
||||
methods: {
|
||||
getData(){
|
||||
let that = this
|
||||
axios.post('/admin/conf/getBaseConfig', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == 200) {
|
||||
for (let item of response.data.data) {
|
||||
if(item.conf_key === 'quark_cookie'){
|
||||
that.form.cookie = item.conf_value
|
||||
}
|
||||
if(item.conf_key === 'quark_file'){
|
||||
that.file = item.conf_value
|
||||
}
|
||||
}
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
},
|
||||
onSubmit(){
|
||||
let that = this
|
||||
axios.post('/admin/conf/updateBaseConfig', Object.assign({}, PostBase, {
|
||||
quark_cookie: that.form.cookie
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == 200) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.getFile()
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
|
||||
getFile(){
|
||||
let that = this
|
||||
axios.post('/admin/source/getFiles', Object.assign({}, PostBase))
|
||||
.then(function (res) {
|
||||
if (res.data.code == 200) {
|
||||
that.files = res.data || []
|
||||
} else {
|
||||
that.$message.error(res.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-table :data="dataList.data" v-loading="loading">
|
||||
<el-table-column prop="id" label="ID" align="center" width="100">
|
||||
</el-table-column>
|
||||
<el-table-column prop="content" label="用户想要的资源描述">
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="提交时间" align="center" width="200">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<div class="page">
|
||||
<el-pagination @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100,200,500]" :page-size="10"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="changeCurrentPage"
|
||||
:current-page="dataList.current_page" :page-count="dataList.last_page" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
dataList: [],
|
||||
form: {
|
||||
page: 1,
|
||||
per_page: 10,
|
||||
order: 'id desc'
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(per_page) {
|
||||
this.form.per_page = per_page;
|
||||
this.getList();
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/feedback/getList', Object.assign({}, PostBase, that.form))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,476 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-form :inline="true" @submit.native.prevent>
|
||||
<el-form-item>
|
||||
<el-button icon="el-icon-plus" size="small" @click="clickAdd" plain>添加资源</el-button>
|
||||
<el-button icon="el-icon-document-copy" size="small" @click="getExport" plain>导出资源</el-button>
|
||||
<el-button icon="el-icon-plus" size="small" @click="ImportShow" plain>夸克导入专用</el-button>
|
||||
<el-button icon="el-icon-plus" size="small" @click="ImportBatch" plain>批量导入</el-button>
|
||||
</el-form-item>
|
||||
<div style="float:right">
|
||||
<el-form-item style="width:120px;">
|
||||
<el-select size="small" v-model="search.source_category_id" placeholder="筛选分类">
|
||||
<el-option v-for="item in category" :key="item.source_category_id" :label="item.name" :value="item.source_category_id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input placeholder="输入关键词搜索" size="small" v-model="search.keyword" @keyup.enter.native="getList_search"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="getList_search" plain>搜索
|
||||
</el-button>
|
||||
<el-button icon="el-icon-refresh-left" size="small" @click="getList_search(0)" plain>重置</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<el-table :data="dataList.data" v-loading="loading">
|
||||
<el-table-column prop="source_id" label="ID" width="80">
|
||||
</el-table-column>
|
||||
<el-table-column prop="title" label="资源名称">
|
||||
</el-table-column>
|
||||
<el-table-column prop="source_category_id_name" label="资源分类">
|
||||
</el-table-column>
|
||||
<el-table-column prop="url" label="资源地址" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="入库时间" align="center" width="200">
|
||||
</el-table-column>
|
||||
<el-table-column prop="update_time" label="更新时间" align="center" width="200">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div class="order-text">
|
||||
<p>
|
||||
<el-link type="success" @click="clickEdit(scope.row)" :underline="false">编辑</el-link>
|
||||
</p>
|
||||
<p>
|
||||
<el-link type="danger" @click="clickDelete(scope.row)" :underline="false">删除</el-link>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
|
||||
<div class="page">
|
||||
<el-pagination @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100,200,500]" :page-size="10"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="changeCurrentPage"
|
||||
:current-page="dataList.current_page" :page-count="dataList.last_page" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 添加框 -->
|
||||
<el-dialog title="添加资源" :visible.sync="dialogFormAdd" :modal-append-to-body='false' append-to-body
|
||||
:close-on-click-modal='false' width="680px">
|
||||
<el-form :model="formAdd" :rules="rules" ref="formAdd">
|
||||
<el-form-item prop="source_category_id" label="资源分类" :label-width="formLabelWidth">
|
||||
<el-select size="medium" v-model="formAdd.source_category_id" placeholder="请选择分类">
|
||||
<el-option v-for="item in category" :key="item.source_category_id" :label="item.name" :value="item.source_category_id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="title" label="资源名称" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" placeholder="请输入资源名称" v-model="formAdd.title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="url" label="资源地址" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" placeholder="请输入资源地址" v-model="formAdd.url"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词搜索" :label-width="formLabelWidth">
|
||||
<el-input type="textarea" :rows="5" size="medium" autocomplete="off" placeholder="一行一个名称" v-model="formAdd.description"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="资源介绍" :label-width="formLabelWidth">
|
||||
<el-input type="textarea" :rows="5" size="medium" autocomplete="off" placeholder="" v-model="formAdd.vod_content"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postAdd()">确认添加</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 修改框 -->
|
||||
<el-dialog title="修改资源" :visible.sync="dialogFormEdit" :modal-append-to-body='false' append-to-body
|
||||
:close-on-click-modal='false' width="680px">
|
||||
<el-form :model="formEdit" :rules="rules" ref="formEdit">
|
||||
<el-form-item prop="source_category_id" label="资源分类" :label-width="formLabelWidth">
|
||||
<el-select size="medium" v-model="formEdit.source_category_id" placeholder="请选择分类" clearable>
|
||||
<el-option v-for="item in category" :key="item.source_category_id" :label="item.name"
|
||||
:value="item.source_category_id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item prop="title" label="资源名称" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" placeholder="请输入资源名称" v-model="formEdit.title"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="url" label="资源地址" :label-width="formLabelWidth">
|
||||
<el-input size="medium" autocomplete="off" placeholder="请输入资源地址" v-model="formEdit.url"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="关键词搜索" :label-width="formLabelWidth">
|
||||
<el-input type="textarea" :rows="5" size="medium" autocomplete="off" placeholder="一行一个名称" v-model="formEdit.description"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="资源介绍" :label-width="formLabelWidth">
|
||||
<el-input type="textarea" :rows="5" size="medium" autocomplete="off" placeholder="" v-model="formEdit.vod_content"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="postEdit()">确认修改</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 夸克导入数据 -->
|
||||
<el-dialog title="导入资源" :visible.sync="dialogImport" :modal-append-to-body='false' append-to-body
|
||||
:close-on-click-modal='false' width="600px">
|
||||
<el-form :model="Importform">
|
||||
<el-form-item prop="source_category_id" label="资源分类" label-width="90px">
|
||||
<el-select size="medium" v-model="Importform.source_category_id" placeholder="请选择分类" clearable>
|
||||
<el-option v-for="item in category" :key="item.source_category_id" :label="item.name"
|
||||
:value="item.source_category_id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="" label-width="90px">
|
||||
<el-upload class="upload-demo" :data="Importform" name="file"
|
||||
ref="ImportUpload"
|
||||
drag
|
||||
:auto-upload="false"
|
||||
limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
:on-success="handleAvatarSuccess"
|
||||
action="/admin/source/imports"
|
||||
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
<span style="color: #999;">请导入夸克官方导出的csv文件</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="ImportPost()">提交</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 批量导入数据 -->
|
||||
<el-dialog title="导入资源" :visible.sync="dialogBatch" :modal-append-to-body='false' append-to-body
|
||||
:close-on-click-modal='false' width="790px">
|
||||
<el-form :model="Batchform">
|
||||
<el-form-item prop="type" label="选择方式" label-width="70px">
|
||||
<el-radio-group v-model="Batchform.type">
|
||||
<el-radio-button :label="1">直接导入</el-radio-button>
|
||||
<el-radio-button :label="2">转存分享导入</el-radio-button>
|
||||
</el-radio-group>
|
||||
<p style="color: #999;" v-if='Batchform.type==1'>直接导入:链接校验有效后直接入库;Tips:该功能不会检测是否重复;</p>
|
||||
<p style="color: #999;" v-else-if='Batchform.type==2'>将资源转存到自己网盘后分享入库(<font color=orangered>此功能仅支持夸克</font>)Tips:该功能不会检测是否重复;</p>
|
||||
<span style="color: #999;" v-if='Batchform.type==1'>支持<font color=orangered>夸克、阿里、UC</font>的网盘资源(一次最多可以上传500条资源)</span>
|
||||
<span style="color: #999;" v-else-if='Batchform.type==2'>目前仅支持<font color=orangered>夸克</font>的网盘资源(一次最多可以上传500条资源)</span>
|
||||
</el-form-item>
|
||||
<el-form-item prop="source_category_id" label="资源分类" label-width="70px" v-if="Batchform.type">
|
||||
<el-select size="medium" v-model="Batchform.source_category_id" placeholder="请选择分类" clearable>
|
||||
<el-option v-for="item in category" :key="item.source_category_id" :label="item.name"
|
||||
:value="item.source_category_id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="urls" label="资源分类" label-width="70px" v-if="Batchform.type">
|
||||
<el-input
|
||||
type="textarea"
|
||||
placeholder="资源示例:
|
||||
一条资源一行
|
||||
https://pan.quark.cn/s/xxxxxxxx
|
||||
https://www.alipan.com/s/xxxxxxxxx
|
||||
https://drive.uc.cn/s/xxxxxxxxxxx"
|
||||
v-model="Batchform.urls"
|
||||
rows="20"
|
||||
show-word-limit
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="BatchPost()">提交</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
search: {
|
||||
keyword: "",
|
||||
filter: "title",
|
||||
source_category_id: ''
|
||||
},
|
||||
formLabelWidth: '120px',
|
||||
dialogFormAdd: false,
|
||||
dialogFormEdit: false,
|
||||
loading: true,
|
||||
dataList: [],
|
||||
form: {
|
||||
page: 1,
|
||||
per_page: 10,
|
||||
order: 'create_time desc'
|
||||
},
|
||||
formAdd: {
|
||||
},
|
||||
formEdit: {
|
||||
},
|
||||
rules: {
|
||||
title: [{ required: true, message: '请输入资源名称', trigger: 'blur' }],
|
||||
url: [{ required: true, message: '请输入资源地址', trigger: 'blur' }],
|
||||
},
|
||||
dialogImport: false,
|
||||
Importform: {
|
||||
|
||||
},
|
||||
|
||||
category: [],
|
||||
|
||||
dialogBatch: false,
|
||||
Batchform: {},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getcategory();
|
||||
},
|
||||
methods: {
|
||||
getList_search(val) {
|
||||
if (val == 0) {
|
||||
this.search = {
|
||||
keyword: "",
|
||||
filter: "title",
|
||||
source_category_id: ''
|
||||
}
|
||||
}
|
||||
this.form.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleSizeChange(per_page) {
|
||||
this.form.per_page = per_page;
|
||||
this.getList();
|
||||
},
|
||||
postEdit() {
|
||||
var that = this;
|
||||
that.$refs["formEdit"].validate((valid) => {
|
||||
if (valid) {
|
||||
axios.post('/admin/source/update', Object.assign({}, PostBase, that.formEdit))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormEdit = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
postAdd() {
|
||||
var that = this;
|
||||
that.$refs['formAdd'].validate((valid) => {
|
||||
if (valid) {
|
||||
axios.post('/admin/source/add', Object.assign({}, PostBase, that.formAdd))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
that.dialogFormAdd = false;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
clickAdd() {
|
||||
var that = this;
|
||||
that.formAdd = { status: 1, share_image: '' };
|
||||
that.dialogFormAdd = true;
|
||||
},
|
||||
clickDelete(row) {
|
||||
var that = this;
|
||||
this.$confirm('删除后,资源将无法查看,是否继续删除?', '删除提醒', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/source/delete', Object.assign({}, PostBase, {
|
||||
source_id: row.source_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
that.getList();
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
clickEdit(row) {
|
||||
var that = this;
|
||||
that.formEdit = row;
|
||||
axios.post('/admin/source/detail', Object.assign({}, PostBase, {
|
||||
source_id: row.source_id
|
||||
}))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
response.data.data.source_category_id = response.data.data.source_category_id || undefined
|
||||
that.formEdit = response.data.data;
|
||||
that.dialogFormEdit = true;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getcategory(){
|
||||
var that = this;
|
||||
axios.post('/admin/source_category/getList', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.category = response.data.data;
|
||||
that.getList();
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/source/getList', Object.assign({}, PostBase, that.form, that.search))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
that.setcategory()
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
},
|
||||
setcategory(){
|
||||
for (let item of this.dataList.data) {
|
||||
for (let items of this.category) {
|
||||
if(item.source_category_id == items.source_category_id){
|
||||
item.source_category_id_name = items.name
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
//导入数据
|
||||
ImportShow() {
|
||||
this.Importform = {
|
||||
}
|
||||
this.dialogImport = true
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
this.$message.warning(`只能选择一个文件`);
|
||||
},
|
||||
handleAvatarSuccess(res, file) {
|
||||
if (res.code == 200) {
|
||||
this.getList();
|
||||
this.$message({
|
||||
message: res.message,
|
||||
type: 'success'
|
||||
});
|
||||
this.dialogImport = false;
|
||||
} else {
|
||||
this.$message.error(res.message);
|
||||
}
|
||||
this.$refs.ImportUpload.clearFiles();
|
||||
},
|
||||
ImportPost(){
|
||||
this.Importform = Object.assign(this.Importform, PostBase)
|
||||
this.$nextTick(() => {
|
||||
this.$refs.ImportUpload.submit();
|
||||
})
|
||||
},
|
||||
|
||||
//批量导入数据
|
||||
ImportBatch() {
|
||||
this.Batchform = {}
|
||||
this.dialogBatch = true
|
||||
},
|
||||
BatchPost(){
|
||||
var that = this;
|
||||
if(!that.Batchform.type) return that.$message.error('请选择导入方式');
|
||||
if(!that.Batchform.urls) return that.$message.error('请输入资源地址');
|
||||
axios.post('/admin/source/transfer', Object.assign({}, PostBase, that.Batchform))
|
||||
.then(function (res) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
that.$message({
|
||||
message: "已提交任务,稍后查看结果",
|
||||
type: 'success'
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
//数据导出
|
||||
getExport(){
|
||||
var that = this;
|
||||
var filters = Object.assign({}, PostBase, that.search);
|
||||
var url = '/admin/source/excel?';
|
||||
for (let key in filters) {
|
||||
url += key + "=" + filters[key] + "&";
|
||||
}
|
||||
window.open(url);
|
||||
that.$message.success('数据导出成功');
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
|
||||
<el-table :data="dataList.data" v-loading="loading">
|
||||
<el-table-column prop="name" label="任务名称">
|
||||
</el-table-column>
|
||||
<el-table-column prop="total_num" label="转存/导入总数" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="new_num" label="新增数" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="skip_num" label="重复跳过" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="fail_num" label="失败数" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column prop="fail_dec" label="最新错误信息" align="center">
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.end_time">已完成</el-tag>
|
||||
<el-tag type="danger" v-else>转存中</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="时间" align="center" width="240">
|
||||
<template slot-scope="scope">
|
||||
<p>任务开始:{{scope.row.create_time}}</p>
|
||||
<p v-if="scope.row.end_time">任务结束:{{scope.row.end_time}}</p>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
|
||||
<div class="page">
|
||||
<el-pagination @size-change="handleSizeChange" :page-sizes="[10, 20, 50, 100,200,500]" :page-size="10"
|
||||
layout="total, sizes, prev, pager, next, jumper" background @current-change="changeCurrentPage"
|
||||
:current-page="dataList.current_page" :page-count="dataList.last_page" :total="dataList.total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
dataList: [],
|
||||
form: {
|
||||
page: 1,
|
||||
per_page: 10,
|
||||
order: 'source_log_id desc'
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
handleSizeChange(per_page) {
|
||||
this.form.per_page = per_page;
|
||||
this.getList();
|
||||
},
|
||||
changeCurrentPage(page) {
|
||||
this.form.page = page;
|
||||
this.getList();
|
||||
},
|
||||
getList() {
|
||||
var that = this;
|
||||
that.loading = true;
|
||||
axios.post('/admin/source_log/getList', Object.assign({}, PostBase, that.form))
|
||||
.then(function (response) {
|
||||
that.loading = false;
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.dataList = response.data.data;
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.loading = false;
|
||||
that.$message.error('服务器内部错误');
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{$node.node_title}</title>
|
||||
{include file="common/header"/}
|
||||
<el-card class="box-card" shadow="never">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>系统数据清理</span>
|
||||
</div>
|
||||
<div class="text item">
|
||||
<!-- <el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>清理授权记录</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 20px;font-size:14px;color:#666;">
|
||||
用户组授权信息清理为
|
||||
<font color=orangered>不可逆操作</font>,请谨慎操作!<br> 清理完毕后,除超级管理用户组外,其他任何用户组将无法访问系统任何功能!
|
||||
<br> 建议仅在用户组权限混乱或出现其他账号安全问题时进行清理操作。
|
||||
<br> 清理成功后可重新对用户组进行权限授权,即可恢复正常使用。
|
||||
</div>
|
||||
<el-button type="danger" @click="clearAuth">清理授权</el-button>
|
||||
</el-card>
|
||||
<br> -->
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>清除缓存</span>
|
||||
</div>
|
||||
<div style="margin-bottom: 20px;font-size:14px;color:#666;">
|
||||
清除缓存
|
||||
<font color=orangered>不可逆操作</font>
|
||||
</div>
|
||||
<el-button type="danger" @click="clearLog">清除缓存</el-button>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-card>
|
||||
{include file="common/footer"/}
|
||||
<script>
|
||||
var app = new Vue({
|
||||
el: '#app',
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
clearLog() {
|
||||
var that = this;
|
||||
this.$confirm('即将清除缓存, 是否确认?', '删除日志', {
|
||||
confirmButtonText: '删除',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
axios.post('/admin/system/clean', Object.assign({}, PostBase))
|
||||
.then(function (response) {
|
||||
if (response.data.code == CODE_SUCCESS) {
|
||||
that.$message({
|
||||
message: response.data.message,
|
||||
type: 'success'
|
||||
});
|
||||
} else {
|
||||
that.$message.error(response.data.message);
|
||||
}
|
||||
})
|
||||
.catch(function (error) {
|
||||
that.$message.error('服务器内部错误');
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
// clearAuth() {
|
||||
// var that = this;
|
||||
// this.$confirm('即将删除授权信息, 是否确认?', '清空授权', {
|
||||
// confirmButtonText: '删除',
|
||||
// cancelButtonText: '取消',
|
||||
// type: 'warning'
|
||||
// }).then(() => {
|
||||
// axios.post('/admin/auth/clean', Object.assign({}, PostBase))
|
||||
// .then(function (response) {
|
||||
// if (response.data.code == CODE_SUCCESS) {
|
||||
// that.$message({
|
||||
// message: response.data.message,
|
||||
// type: 'success'
|
||||
// });
|
||||
// } else {
|
||||
// that.$message.error(response.data.message);
|
||||
// }
|
||||
// })
|
||||
// .catch(function (error) {
|
||||
// that.$message.error('服务器内部错误');
|
||||
// console.log(error);
|
||||
// });
|
||||
// }).catch(() => {
|
||||
// });
|
||||
// },
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
use app\AppService;
|
||||
|
||||
// 系统服务定义文件
|
||||
// 服务在完成全局初始化之后执行
|
||||
return [
|
||||
AppService::class,
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user