chore: 添加静态资源文件和版本配置文件

添加大量图片、字体、音频等静态资源文件,包括用户界面图片、模板文件和安装界面素材
添加系统版本配置文件(.version)和常量定义文件(.constant)
更新供应商依赖文件,包括Symfony VarDumper组件和相关许可证文件
添加验证码配置文件(captcha.php)和.gitignore规则
This commit is contained in:
2026-03-06 20:14:23 +08:00
commit c9a98f342c
4485 changed files with 490986 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\services\system\log;
use app\services\BaseServices;
/**
* Class ClearServices
* @package app\services\system\log
*/
class ClearServices extends BaseServices
{
/** 递归删除文件
* @param $dirName
* @param bool $subdir
*/
protected function delDirAndFile($dirName)
{
$list = glob($dirName . '*');
foreach ($list as $file) {
if (is_dir($file))
$this->delDirAndFile($file . DS);
else
@unlink($file);
}
@rmdir($dirName);
}
/**
* 删除日志
*/
public function deleteLog()
{
$root = app()->getRootPath() . 'runtime' . DS;
$this->delDirAndFile($root . 'admin' . DS . 'log' . DS);
$this->delDirAndFile($root . 'api' . DS . 'log' . DS);
$this->delDirAndFile($root . 'log' . DS);
}
/**
* 刷新数据缓存
*/
public function refresCache()
{
$root = app()->getRootPath() . 'runtime' . DS;
$adminRoute = $root . 'admin';
$apiRoute = $root . 'api';
$cacheRoute = $root . 'cache';
$cache = [];
if (is_dir($adminRoute))
$cache[$adminRoute] = scandir($adminRoute);
if (is_dir($apiRoute))
$cache[$apiRoute] = scandir($apiRoute);
if (is_dir($cacheRoute))
$cache[$cacheRoute] = scandir($cacheRoute);
foreach ($cache as $p => $list) {
foreach ($list as $file) {
if (!in_array($file, ['.', '..', 'log', 'schema', 'admin.php'])) {
$path = $p . DS . $file;
if (is_file($path)) {
@unlink($path);
} else {
$this->delDirAndFile($path . DS);
}
}
}
}
}
}

View File

@@ -0,0 +1,255 @@
<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\services\system\log;
use app\dao\system\log\SystemFileDao;
use app\services\BaseServices;
use crmeb\exceptions\AdminException;
use crmeb\services\CacheService;
use crmeb\services\FileService as FileClass;
use think\annotation\Inject;
/**
* 文件校验
* Class SystemFileServices
* @package app\services\system\log
* @mixin SystemFileDao
*/
class SystemFileServices extends BaseServices
{
/**
* @var SystemFileDao
*/
#[Inject]
protected SystemFileDao $dao;
/**
* 获取文件校验列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getFileList()
{
$rootPath = app()->getRootPath();
$key = 'system_file_app_crmeb_public';
$arr = CacheService::get(md5($key));
if (!$arr) {
$app = $this->getDir($rootPath . 'app');
$extend = $this->getDir($rootPath . 'crmeb');
$arr = array_merge($app, $extend);
CacheService::set(md5($key), $arr, 3600 * 24);
}
$fileAll = [];//本地文件
$cha = [];//不同的文件
$len = strlen($rootPath);
$fileKey = 'system_file_app_msyql';
$file = CacheService::get(md5($fileKey));
if (!$file) {
$file = $this->dao->getAll();//数据库中的文件
CacheService::set(md5($fileKey), $file, 3600 * 24);
}
if (empty($file)) {
foreach ($arr as $k => $v) {
$update_time = stat($v);
$fileAll[$k]['cthash'] = md5_file($v);
$fileAll[$k]['filename'] = substr($v, $len);
$fileAll[$k]['atime'] = $update_time['atime'];
$fileAll[$k]['mtime'] = $update_time['mtime'];
$fileAll[$k]['ctime'] = $update_time['ctime'];
}
$data_num = array_chunk($fileAll, 100);
$res = true;
$res = $this->transaction(function () use ($data_num, $res) {
foreach ($data_num as $k => $v) {
$res = $res && $this->dao->saveAll($v);
}
return $res;
});
if ($res) {
$cha = [];//不同的文件
} else {
$cha = $fileAll;
}
} else {
$file = array_combine(array_column($file, 'filename'), $file);
$insertData = [];
foreach ($arr as $ko => $vo) {
$update_time = stat($vo);
$cthash = md5_file($vo);
$fileName = substr($vo, $len);
$data = [
'filename' => $fileName,
'cthash' => $cthash,
'atime' => $update_time['atime'] ?? 0,
'mtime' => $update_time['mtime'] ?? 0,
'ctime' => $update_time['ctime'] ?? 0,
];
if (isset($file[$fileName])) {
$data ['type'] = $file[$fileName]['cthash'] != $cthash ? '已修改' : '新增的';
unset($file[$fileName]);
} else {//新增
$insertData[] = $data;
$data['type'] = '新增的';
}
$data['atime'] = (int)$data['atime'] ? date('Y-m-d H:i:s', (int)$data['atime']) : '';
$data['mtime'] = (int)$data['mtime'] ? date('Y-m-d H:i:s', (int)$data['mtime']) : '';
$data['ctime'] = (int)$data['ctime'] ? date('Y-m-d H:i:s', (int)$data['ctime']) : '';
$cha[] = $data;
}
if ($insertData) {
$this->dao->saveAll($insertData);
CacheService::delete(md5($fileKey));
}
foreach ($file as $k => $v) {
$cha[] = [
'filename' => $v['filename'],
'cthash' => $v['cthash'],
'atime' => (int)$v['atime'] ? date('Y-m-d H:i:s', (int)$v['atime']) : '',
'mtime' => (int)$v['mtime'] ? date('Y-m-d H:i:s', (int)$v['mtime']) : '',
'ctime' => (int)$v['ctime'] ? date('Y-m-d H:i:s', (int)$v['ctime']) : '',
'type' => '已删除',
];
}
}
$ctime = array_column($cha, 'ctime');
array_multisort($ctime, SORT_DESC, $cha);
return $cha;
}
/**
* 获取文件夹中的文件 包括子文件
* @param $dir
* @return array
*/
public function getDir($dir)
{
$data = [];
$this->searchDir($dir, $data);
return $data;
}
/**
* 获取文件夹中的文件 包括子文件 不能直接用 直接使用 $this->getDir()方法 P156
* @param $path
* @param $data
*/
public function searchDir($path, &$data)
{
if (is_dir($path) && !strpos($path, 'uploads')) {
$files = scandir($path);
foreach ($files as $file) {
if ($file != '.' && $file != '..') {
$this->searchDir($path . '/' . $file, $data);
}
}
}
if (is_file($path)) {
$data[] = $path;
}
}
/**
* 打开目录获取文件列表
* @return array
*/
public function opendir()
{
$fileAll = array('dir' => [], 'file' => []);
//根目录
$rootdir = app()->getRootPath();
// return $rootdir;
//当前目录
$request_dir = app('request')->param('dir');
//防止查看站点以外的目录
if (strpos($request_dir, $rootdir) === false) {
$request_dir = $rootdir;
}
//判断是否是返回上级
if (app('request')->param('superior') && !empty($request_dir)) {
if (strpos(dirname($request_dir), $rootdir) !== false) {
$dir = dirname($request_dir);
} else {
$dir = $rootdir;
}
} else {
$dir = !empty($request_dir) ? $request_dir : $rootdir;
$dir = rtrim($dir, DS) . DS . app('request')->param('filedir');
}
$list = scandir($dir);
foreach ($list as $key => $v) {
if ($v != '.' && $v != '..') {
if (is_dir($dir . DS . $v)) {
$fileAll['dir'][] = FileClass::listInfo($dir . DS . $v);
}
if (is_file($dir . DS . $v)) {
$fileAll['file'][] = FileClass::listInfo($dir . DS . $v);
}
}
}
//兼容windows
$uname = php_uname('s');
if (strstr($uname, 'Windows') !== false) {
$dir = ltrim($dir, '\\');
$rootdir = str_replace('\\', '\\\\', $rootdir);
}
$list = array_merge($fileAll['dir'], $fileAll['file']);
foreach ($list as $key => $value) {
$list[$key]['real_path'] = str_replace($rootdir, '', $value['pathname']);
$list[$key]['mtime'] = date('Y-m-d H:i:s', $value['mtime']);
}
return compact('dir', 'list');
}
/**
* 读取文件内容
* @param string $filepath 文件路径
* @return array
*/
public function openfile($filepath)
{
$content = FileClass::readFile($filepath);//防止页面内嵌textarea标签
$ext = FileClass::getExt($filepath);
$extarray = [
'js' => 'text/javascript'
, 'php' => 'text/x-php'
, 'html' => 'text/html'
, 'sql' => 'text/x-mysql'
, 'css' => 'text/x-scss'];
$mode = empty($extarray[$ext]) ? '' : $extarray[$ext];
return compact('content', 'mode', 'filepath');
}
/**
* 保存文件内容
* @param string $filepath 文件路径
* @param string $comment 文件内容
* @return bool
* @throws AdminException
*/
public function savefile($filepath, $comment)
{
//兼容windows
$uname = php_uname('s');
if (strstr($uname, 'Windows') !== false)
$filepath = ltrim(str_replace('/', DS, $filepath), '.');
if (!FileClass::isWritable($filepath)) {
throw new AdminException('没有权限');
}
return FileClass::writeFile($filepath, $comment);
}
}

View File

@@ -0,0 +1,91 @@
<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\services\system\log;
use app\dao\system\log\SystemLogDao;
use app\services\BaseServices;
use app\services\system\admin\SystemAdminServices;
use app\services\system\SystemMenusServices;
use think\annotation\Inject;
/**
* 系统日志
* Class SystemLogServices
* @package app\services\system\log
* @mixin SystemLogDao
*/
class SystemLogServices extends BaseServices
{
/**
* @var SystemLogDao
*/
#[Inject]
protected SystemLogDao $dao;
/**
* 记录访问日志
* @param int $adminId
* @param string $adminName
* @param string $module
* @param string $rule
* @param string $ip
* @param string $type
* @return bool
*/
public function recordAdminLog(int $adminId, string $adminName, string $module, string $rule, string $ip, string $type)
{
/** @var SystemMenusServices $service */
$service = app()->make(SystemMenusServices::class);
$data = [
'method' => $module,
'add_time' => time(),
'admin_name' => $adminName,
'path' => $rule,
'page' => $service->getVisitName($rule) ?: '未知',
'ip' => $ip,
'type' => $type
];
if ($type == 'store') {
$data['store_id'] = $adminId;
} else {
$data['admin_id'] = $adminId;
}
if ($this->dao->save($data)) {
return true;
} else {
return false;
}
}
/**
* 获取系统日志列表
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getLogList(array $where, int $level)
{
[$page, $limit] = $this->getPageValue();
if (!$where['admin_id']) {
/** @var SystemAdminServices $service */
$service = app()->make(SystemAdminServices::class);
$where['admin_id'] = $service->getAdminIds($level);
}
$list = $this->dao->getLogList($where, $page, $limit);
$count = $this->dao->count($where);
return compact('list', 'count');
}
}