first commit

This commit is contained in:
2025-06-25 10:53:11 +08:00
commit 9f374011ae
1240 changed files with 181139 additions and 0 deletions
+286
View File
@@ -0,0 +1,286 @@
<?php
/**
* @copyright Copyright (c) 2023-2024 美天智能科技
* @author 李志强
* @link http://www.meteteme.com
*/
declare(strict_types=1);
namespace app\base;
use think\App;
use think\exception\HttpResponseException;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Request;
use think\facade\Session;
use think\facade\View;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
$this->module = strtolower(app('http')->getName());
$this->controller = strtolower($this->request->controller());
$this->action = strtolower($this->request->action());
$this->uid = 0;
$this->did = 0;
$this->name = '';
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{
// 检测权限
$this->checkLogin();
$this->param = $this->request->param();
}
/**
*验证用户登录
*/
protected function checkLogin()
{
// 定义一个不需要登录验证的接口白名单
$whitelist = [
'business/supplier/sendintention',
// 其他不需要登录验证的接口可以继续添加到此数组
];
// 当前请求的路径
$currentPath = $this->module . '/' . $this->controller . '/' . $this->action;
// 检查当前路径是否在白名单中
if (in_array($currentPath, $whitelist)) {
return true;
}
if ($this->controller !== 'login' && $this->controller !== 'captcha') {
$session_admin = get_config('app.session_admin');
if (!Session::has($session_admin)) {
if ($this->request->isAjax()) {
return to_assign(404, '请先登录');
} else {
redirect('/home/login/index.html')->send();
exit;
}
} else {
$loginInfo = Session::get($session_admin);
$this->uid = $loginInfo['id'];
$this->did = $loginInfo['did'];
$params = [
'uid' => $this->uid,
'name' => $loginInfo['name'],
'thumb' => $loginInfo['thumb'],
'module' => $this->module,
'controller' => $this->controller,
'action' => $this->action,
'url' => $this->module . '/' . $this->controller . '/' . $this->action,
'version' => get_system_config('web', 'version')
];
View::assign('params', $params);
// 验证用户访问权限
if (($this->module == 'api') || ($this->module == 'home')) {
return true;
} else {
$reg_pwd = Db::name('Admin')->where(['id' => $this->uid])->value('reg_pwd');
if ($reg_pwd !== '') {
redirect('/home/user/edit_password.html')->send();
exit;
}
if (!$this->checkAuth()) {
if ($this->request->isAjax()) {
return to_assign(202, '你没有权限,请联系管理员或者人事部');
} else {
echo '<div style="text-align:center;color:red;margin-top:20%;">你没有权限,请联系管理员或者人事部</div>';
exit;
}
}
}
}
}
}
/**
* 验证用户访问权限
* @DateTime 2020-12-21
* @param string $controller 当前访问控制器
* @param string $action 当前访问方法
* @return [type]
*/
protected function checkAuth()
{
//Cache::delete('RulesSrc' . $uid);
$uid = $this->uid;
if (!Cache::get('RulesSrc' . $uid) || !Cache::get('RulesSrc0')) {
//用户所在权限组及所拥有的权限
// 执行查询
$groups = [];
$position_id = Db::name('Admin')->where('id', $uid)->value('position_id');
$groups = Db::name('PositionGroup')
->alias('a')
->join("AdminGroup g", "a.group_id=g.id", 'LEFT')
->where([['a.pid', '=', $position_id], ['g.status', '=', 1]])
->select()
->toArray();
//保存用户所属用户组设置的所有权限规则id
$ids = [];
foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
}
$ids = array_unique($ids);
//读取所有权限规则
$rules_all = Db::name('AdminRule')->field('src')->select()->toArray();
//读取用户组所有权限规则
$rules = Db::name('AdminRule')->where('id', 'in', $ids)->field('src')->select()->toArray();
//循环规则,判断结果。
$auth_list_all = [];
$auth_list = [];
foreach ($rules_all as $rule_all) {
$auth_list_all[] = strtolower($rule_all['src']);
}
foreach ($rules as $rule) {
$auth_list[] = strtolower($rule['src']);
}
//规则列表结果保存到Cache
Cache::tag('adminRules')->set('RulesSrc0', $auth_list_all, 36000);
Cache::tag('adminRules')->set('RulesSrc' . $uid, $auth_list, 36000);
} else {
$auth_list_all = Cache::get('RulesSrc0');
$auth_list = Cache::get('RulesSrc' . $uid);
}
$pathUrl = $this->module . '/' . $this->controller . '/' . $this->action;
// print_r
// print_r($auth_list);
if (!in_array($pathUrl, $auth_list)) {
return false;
} else {
return true;
}
}
//
// 以下为新增,为了使用旧版TP的 success error redirect 跳转 start
//
/**
* 操作成功跳转的快捷方法
* @access protected
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function success($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
{
if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
$url = $_SERVER["HTTP_REFERER"];
} elseif ($url) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
}
$result = [
'code' => 0,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
$type = $this->getResponseType();
if ($type == 'html') {
$response = view($this->app->config->get('app.dispatch_success_tmpl'), $result);
} else if ($type == 'json') {
$response = json($result);
}
throw new HttpResponseException($response);
}
/**
* 操作错误跳转的快捷方法
* @access protected
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function error($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
{
if (is_null($url)) {
$url = $this->request->isAjax() ? '' : 'javascript:history.back(-1);';
} elseif ($url) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : $this->app->route->buildUrl($url);
}
$result = [
'code' => 1,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
$type = $this->getResponseType();
if ($type == 'html') {
$response = view($this->app->config->get('app.dispatch_error_tmpl'), $result);
} else if ($type == 'json') {
$response = json($result);
}
throw new HttpResponseException($response);
}
/**
* 获取当前的response 输出类型
* @access protected
* @return string
*/
protected function getResponseType()
{
return $this->request->isJson() || $this->request->isAjax() ? 'json' : 'html';
}
//
// 以上为新增,为了使用旧版的 success error redirect 跳转 end
//
}
+232
View File
@@ -0,0 +1,232 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
{block name="meta"}
<link rel="mobile-prefetch" href="" />
{/block}
{block name="title"}
<title>{:get_system_config('web','admin_title')}</title>
{/block}
{block name="keywords"}
<meta name="keywords" content="{:get_system_config('web','keywords')}" />
<meta name="description" content="{:get_system_config('web','desc')}" />
{/block}
{block name="css"}
<link rel="stylesheet" href="{__METE__CSS__}/style.css">
<link rel="stylesheet" href="{__METE__}/gougu/css/gougu.css?v={$params.version}">
<link rel="stylesheet" href="{__METE__}/gougu/module/editormd/css/editormd.min.css">
<link rel="stylesheet" href="{__METE__}/gougu/module/editormd/css/editormd.preview.min.css">
<link rel="stylesheet" href="{__CSS__}/common.css?v={$params.version}">
<link rel="stylesheet" href="{__METE__CSS__}/font-awesome5.15.4.css">
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
rel="stylesheet"
/>
<link rel="stylesheet" href="{__METE__CSS__}/dhtmlxgantt.css">
<!-- <link rel="stylesheet" href="{__CSS__}/bs5.3.css">-->
{/block}
{block name="style"}{/block}
<script src="{__STATIC__}/jquery.min.js"></script>
<script>
const GOUGU_DEV = {
uid: '{$params.uid}',
name: '{$params.name}',
module: '{$params.module}',
controller: '{$params.controller}',
action: '{$params.action}',
version: '{$params.version}'
};
</script>
{block name="js"}{/block}
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
<div class="layui-header">
<div class="header-breadcrumb layui-layout-left">
{block name="breadcrumb"}
<span class="layui-breadcrumb">
<a href="https://project.meteteme.com" target="_blank">江苏美天科技</a>
<a><cite>工作台</cite></a>
</span>
{/block}
</div>
<ul class="layui-layout-right">
<li class="layui-nav-item">
<a href="javascript:;" id="add-new" title="新建内容">
<i class="layui-icon layui-icon-add-circle"></i>
</a>
</li>
<li class="layui-nav-item">
<a href="/home/message/inbox" id="notice" title="消息通知">
<i class="layui-icon layui-icon-notice"></i>
</a>
<div id="msgNum" class="msg-num" style="display:none;"><span>0</span></div>
</li>
<li class="layui-nav-item">
<a href="javascript:;" id="del-cache" title="清空缓存">
<i class="layui-icon layui-icon-fonts-clear"></i>
</a>
</li>
<li class="layui-nav-item">
<a href="javascript:;" id="refresh" title="刷新当前页">
<i class="layui-icon layui-icon-refresh"></i>
</a>
</li>
<li class="layui-nav-item">
<a href="javascript:;" id="loginout" title="{$params.name}-点击退出登录">
<img src="{$params.thumb}" class="layui-login-img"
onerror="javascript:this.src='{__IMG__}/icon.png';this.onerror=null;">
</a>
</li>
</ul>
</div>
<div class="layui-side">
{block name="side"}
<div class="side-memu">
<div class="side-memu-box">
<a class="item logo" href="/home/index">
<div class="gg-logo" title="{:get_system_config('web','admin_title')}">
<img src="{__IMG__}/icon.png" alt="{:get_system_config('web','admin_title')}" />
</div>
</a>
<a class="item {if condition=" $params.url eq 'home/index/index'"} active{/if}"
href="/home/index"><i class="iconfont icon-xueshuguanli"></i>
<div class="text">工作台</div>
</a>
{foreach name=":get_menus()" item="a"}
{gt name="$a.id" value="1"}
<a class="item {if condition='strpos($a.src,$params.module) nheq false'} active{/if}"
href="/{$a.src}"><i class="iconfont {$a.icon}"></i>
<div class="text">{$a.title}</div>
</a>
{/gt}
{/foreach}
<a class="item" href="/home/user/setting" title="设置"><i class="iconfont icon-shezhi"></i><div class="text">系统设置</div></a>
</div>
<div class="side-memu-footer">
</div>
</div>
{/block}
</div>
<div class="layui-body">
{block name="body"}
<div style="padding: 15px;">内容主体区域</div>
{/block}
</div>
{block name="footer"}{/block}
</div>
<script>
//右上角注销
$("#loginout").on("click", function () {
layer.confirm('确认注销登录吗?', { icon: 7, title: '警告' }, function (index) {
//注销
$.ajax({
url: "/home/login/login_out",
success: function (e) {
layer.msg(e.msg);
if (e.code == 0) {
setTimeout(function () {
location.href = "/home/login/index.html"
}, 1000)
}
}
})
layer.close(index);
});
});
//右上角消息
$("#msgNum").on('click', function () {
window.location.href = "/home/message/inbox";
return false;
})
//右上角刷新
$("#refresh").on('click', function () {
location.reload();
return false;
})
//右上角清除缓存
$("#del-cache").on('click', function (e) {
var that = $(this);
if (that.attr('class') === 'clearThis') {
layer.tips('正在努力清理中...', this);
return false;
}
layer.tips('正在清理系统缓存...', this);
that.attr('class', 'clearThis');
$.ajax({
url: "/api/index/cache_clear",
success: function (res) {
if (res.code == 1) {
setTimeout(function () {
that.attr('class', '');
layer.tips(res.msg, that);
}, 1000)
} else {
layer.tips(res.msg, that);
}
}
})
})
var intervalTime = 3000;
//获取消息
function getMsg() {
$.ajax({
url: "/home/index/index",
type: 'get',
success: function (e) {
intervalTime = 30000;
if (e.code == 0 && e.data != '') {
if (e.data.msg_num > 0) {
$('#msgNum').show().find('span').html(e.data.msg_num);
}
else {
$('#msgNum').hide().find('span').html(0);
}
}
}
})
}
//轮循获取消息,第一次页面加载完成3秒后,后期每30秒轮询一次
setTimeout(function () {
getMsg();
setInterval(function () {
getMsg();
}, 30000);
}, 3000)
</script>
<!-- 脚本 -->
{block name="script"}
<script>
const moduleInit = ['tool','admin'];
function gouguInit() {
console.log('加载完毕...');
}
</script>
{/block}
<!-- /脚本 -->
<script src="{__METE__}/layui/layui.js"></script>
<script src="{__METE__}/gougu/gouguInit.js"></script>
<script src="{__JS__}/clipboard.min.js"></script>
<script src="{__JS__}/dhtmlxgantt.js"></script>
<!-- 统计代码 -->
{block name="code"}{/block}
<!-- /统计代码 -->
</body>
</html>
+15
View File
@@ -0,0 +1,15 @@
<div class="sub-menu" style="width: 200px;">
<div class="sub-menu-content" style="width: 200px;">
<ul>
<li class="sub-menu-title {eq name='$params.action' value='inbox'} active{/eq}"><a href="/home/message/inbox"><i class="iconfont icon-yiyichuli"></i><span class="text">收件箱</span></a></li>
<li class="sub-menu-title {eq name='$params.action' value='sendbox'} active{/eq}"><a href="/home/message/sendbox"><i class="iconfont icon-tuiguangshezhi"></i><span class="text">发件箱</span></a></li>
<li class="sub-menu-title {eq name='$params.action' value='draft'} active{/eq}"><a href="/home/message/draft"><i class="iconfont icon-lunwenguanli"></i><span class="text">草稿箱</span></a></li>
<li class="sub-menu-title {eq name='$params.action' value='rubbish'} active{/eq}"><a href="/home/message/rubbish"><i class="iconfont icon-tiku"></i><span class="text">垃圾箱</span></a></li>
</ul>
</div>
<div class="menu-bar">
<div class="menu-bar-content">
<div class="line"></div>
</div>
</div>
</div>
+30
View File
@@ -0,0 +1,30 @@
<div class="sub-menu" style="width: 200px;">
<div class="sub-menu-content" style="width: 200px;">
<ul>
<li class="sub-menu-title"><a href="javascript:;"><i class="iconfont icon-zaijixueshengguanli"></i><span class="text">用户信息</span></a></li>
<li class="sub-menu-li {eq name='$params.action' value='edit_personal'} active{/eq}"><a href="/home/user/edit_personal"><span class="text">编辑个人信息</span></a></li>
<li class="sub-menu-li {eq name='$params.action' value='edit_password'} active{/eq}"><a href="/home/user/edit_password"><span class="text">修改登录密码</span></a></li>
{foreach name=":get_menus(1)" item="a"}
{notempty name="$a.src"}
<li class="sub-menu-title {if condition='strpos($a.src,$params.url) nheq false'} active{/if}"><a href="/{$a.src}"><i class="iconfont {$a.icon}"></i><span class="text">{$a.title}</span></a></li>
{else/}
<li class="sub-menu-title"><a href="javascript:;"><i class="iconfont {$a.icon}"></i><span class="text">{$a.title}</span></a></li>
{/notempty}
{notempty name="$a.list"}
{foreach name="$a.list" item="b"}
{notempty name="$b.src"}
<li class="sub-menu-li {if condition='strpos($b.src,$params.url) nheq false'} active{/if}"><a href="/{$b.src}"><span class="text">{$b.title}</span></a></li>
{else/}
<li class="sub-menu-li"><a href="javascript:;"><span class="text">{$b.title}</span></a></li>
{/notempty}
{/foreach}
{/notempty}
{/foreach}
</ul>
</div>
<div class="menu-bar">
<div class="menu-bar-content">
<div class="line"></div>
</div>
</div>
</div>