This commit is contained in:
全栈小学生 2025-05-23 14:40:12 +08:00
parent d98c2dacc1
commit 384e793c7e
81 changed files with 3763 additions and 1971 deletions

View File

@ -0,0 +1,125 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\adminapi\controller\addon;
use app\service\admin\upgrade\BackupRecordsService;
use core\base\BaseAdminController;
use think\Response;
class Backup extends BaseAdminController
{
/**
* 获取升级记录分页列表
* @return Response
*/
public function getRecords()
{
$data = $this->request->params([
[ "content", "" ],
]);
return success(( new BackupRecordsService() )->getPage($data));
}
/**
* 修改备注
* @return Response
*/
public function modifyRemark()
{
$data = $this->request->params([
[ "id", "" ],
[ 'remark', '' ]
]);
( new BackupRecordsService() )->modifyRemark($data);
return success('MODIFY_SUCCESS');
}
/**
* 恢复前检测文件是否存在
* @return Response
*/
public function checkDirExist()
{
$data = $this->request->params([
[ "id", 0 ],
]);
return success(( new BackupRecordsService() )->checkDirExist($data[ 'id' ]));
}
/**
* 检测目录权限
* @return Response
*/
public function checkPermission()
{
return success(( new BackupRecordsService() )->checkPermission());
}
/**
* 恢复备份
* @return Response
*/
public function restoreBackup()
{
$data = $this->request->params([
[ 'id', 0 ],
[ 'task', '' ]
]);
$res = ( new BackupRecordsService() )->restore($data);
return $res;
}
/**
* 删除升级记录
* @return Response
*/
public function deleteRecords()
{
$data = $this->request->params([
[ "ids", [] ],
]);
( new BackupRecordsService() )->del($data[ 'ids' ]);
return success('DELETE_SUCCESS');
}
/**
* 手动备份
* @return Response
*/
public function manualBackup()
{
$data = $this->request->params([
[ 'task', '' ]
]);
$res = ( new BackupRecordsService() )->manualBackup($data);
return $res;
}
/**
* 获取正在进行的恢复任务
* @return Response
*/
public function getRestoreTask()
{
return success(( new BackupRecordsService() )->getRestoreTask());
}
/**
* 获取正在进行的备份任务
* @return Response
*/
public function getBackupTask()
{
return success(( new BackupRecordsService() )->getBackupTask());
}
}

View File

@ -11,6 +11,7 @@
namespace app\adminapi\controller\addon; namespace app\adminapi\controller\addon;
use app\service\admin\upgrade\UpgradeRecordsService;
use app\service\admin\upgrade\UpgradeService; use app\service\admin\upgrade\UpgradeService;
use core\base\BaseAdminController; use core\base\BaseAdminController;
use think\Response; use think\Response;
@ -24,7 +25,10 @@ class Upgrade extends BaseAdminController
*/ */
public function upgrade($addon = '') public function upgrade($addon = '')
{ {
return success(data:( new UpgradeService() )->upgrade($addon)); $data = $this->request->params([
['is_need_backup', true]
]);
return success(data: ( new UpgradeService() )->upgrade($addon, $data));
} }
/** /**
@ -32,9 +36,9 @@ class Upgrade extends BaseAdminController
* @param $app_key * @param $app_key
* @return Response * @return Response
*/ */
public function execute($addon = '') public function execute()
{ {
return success(data:( new UpgradeService() )->execute()); return success(data: ( new UpgradeService() )->execute());
} }
/** /**
@ -44,7 +48,7 @@ class Upgrade extends BaseAdminController
*/ */
public function getUpgradeContent($addon = '') public function getUpgradeContent($addon = '')
{ {
return success(data:( new UpgradeService() )->getUpgradeContent($addon)); return success(data: ( new UpgradeService() )->getUpgradeContent($addon));
} }
/** /**
@ -53,7 +57,7 @@ class Upgrade extends BaseAdminController
*/ */
public function getUpgradeTask() public function getUpgradeTask()
{ {
return success(data:( new UpgradeService() )->getUpgradeTask()); return success(data: ( new UpgradeService() )->getUpgradeTask());
} }
/** /**
@ -63,7 +67,7 @@ class Upgrade extends BaseAdminController
*/ */
public function upgradePreCheck($addon = '') public function upgradePreCheck($addon = '')
{ {
return success(data:( new UpgradeService() )->upgradePreCheck($addon)); return success(data: ( new UpgradeService() )->upgradePreCheck($addon));
} }
/** /**
@ -72,6 +76,30 @@ class Upgrade extends BaseAdminController
*/ */
public function clearUpgradeTask() public function clearUpgradeTask()
{ {
return success(data:( new UpgradeService() )->clearUpgradeTask()); return success(data: ( new UpgradeService() )->clearUpgradeTask(0, 1));
}
public function operate($operate) {
return success(( new UpgradeService() )->operate($operate));
}
/**
* 获取升级记录分页列表
* @return Response
*/
public function getRecords()
{
$data = $this->request->params([
[ "name", "" ],
]);
return success(( new UpgradeRecordsService() )->getPage($data));
}
public function delRecords() {
$data = $this->request->params([
[ 'ids', '' ],
]);
( new UpgradeRecordsService() )->del($data['ids']);
return success('DELETE_SUCCESS');
} }
} }

View File

@ -29,7 +29,7 @@ class Config extends BaseAdminController
*/ */
public function getBottomList() public function getBottomList()
{ {
return success((new DiyConfigService())->getBottomList()); return success(( new DiyConfigService() )->getBottomList());
} }
/** /**
@ -41,7 +41,7 @@ class Config extends BaseAdminController
$params = $this->request->params([ $params = $this->request->params([
[ 'key', 'app' ], [ 'key', 'app' ],
]); ]);
return success((new DiyConfigService())->getBottomConfig($params[ 'key' ])); return success(( new DiyConfigService() )->getBottomConfig($params[ 'key' ]));
} }
/** /**
@ -54,7 +54,7 @@ class Config extends BaseAdminController
[ 'value', [] ], [ 'value', [] ],
[ 'key', 'app' ] [ 'key', 'app' ]
]); ]);
(new DiyConfigService())->setBottomConfig($data[ 'value' ], $data[ 'key' ]); ( new DiyConfigService() )->setBottomConfig($data[ 'value' ], $data[ 'key' ]);
return success(); return success();
} }

View File

@ -274,7 +274,7 @@ class Diy extends BaseAdminController
*/ */
public function getDiyTheme() public function getDiyTheme()
{ {
return success(( new DiyService() )->getDiyTheme()); return success(( new DiyService() )->getDiyTheme());
} }
/** /**
@ -291,7 +291,7 @@ class Diy extends BaseAdminController
[ 'new_theme', '' ], [ 'new_theme', '' ],
]); ]);
( new DiyService() )->setDiyTheme($data); ( new DiyService() )->setDiyTheme($data);
return success('ADD_SUCCESS'); return success('ADD_SUCCESS');
} }
/** /**
@ -303,7 +303,7 @@ class Diy extends BaseAdminController
$data = $this->request->params([ $data = $this->request->params([
[ 'addon', '' ], [ 'addon', '' ],
]); ]);
return success(( new DiyService() )->getDefaultThemeColor($data)); return success(( new DiyService() )->getDefaultThemeColor($data));
} }
/** /**

View File

@ -370,16 +370,4 @@ class DiyForm extends BaseAdminController
return success(( new DiyFormRecordsService() )->getFieldStatList($data)); return success(( new DiyFormRecordsService() )->getFieldStatList($data));
} }
/**
* 获取万能表单微信小程序二维码
* @return Response
*/
public function getQrcode()
{
$data = $this->request->params([
[ "form_id", '' ],
]);
return success(( new DiyFormService() )->getQrcode($data[ 'form_id' ]));
}
} }

View File

@ -152,6 +152,7 @@ class Member extends BaseAdminController
{ {
$data = $this->request->params([ $data = $this->request->params([
['keyword', ''], ['keyword', ''],
['member_ids', []],
]); ]);
return success((new MemberService())->getList($data)); return success((new MemberService())->getList($data));
} }

View File

@ -20,7 +20,7 @@ class Module extends BaseAdminController
{ {
public function authorize() public function authorize()
{ {
return success((new CoreAuthService())->getAuthInfo()); return success(( new CoreAuthService() )->getAuthInfo());
} }
/** /**
@ -29,11 +29,11 @@ class Module extends BaseAdminController
public function setAuthorize() public function setAuthorize()
{ {
$data = $this->request->params([ $data = $this->request->params([
['auth_code', ''], [ 'auth_code', '' ],
['auth_secret', ''] [ 'auth_secret', '' ]
]); ]);
$this->validate($data, 'app\validate\niucloud\Module.set'); $this->validate($data, 'app\validate\niucloud\Module.set');
return success("SUCCESS", (new NiucloudService())->setAuthorize($data)); return success("SUCCESS", ( new NiucloudService() )->setAuthorize($data));
} }
/** /**
@ -41,7 +41,7 @@ class Module extends BaseAdminController
*/ */
public function getAuthorize() public function getAuthorize()
{ {
return success((new NiucloudService())->getAuthorize()); return success(( new NiucloudService() )->getAuthorize());
} }
/** /**
@ -49,8 +49,9 @@ class Module extends BaseAdminController
* @return Response * @return Response
* @throws \GuzzleHttp\Exception\GuzzleException * @throws \GuzzleHttp\Exception\GuzzleException
*/ */
public function getFrameworkLastVersion() { public function getFrameworkLastVersion()
return success(data:(new NiucloudService())->getFrameworkLastVersion()); {
return success(data: ( new NiucloudService() )->getFrameworkLastVersion());
} }
/** /**
@ -58,15 +59,29 @@ class Module extends BaseAdminController
* @return Response * @return Response
* @throws \GuzzleHttp\Exception\GuzzleException * @throws \GuzzleHttp\Exception\GuzzleException
*/ */
public function getFrameworkVersionList() { public function getFrameworkVersionList()
return success(data:(new NiucloudService())->getFrameworkVersionList()); {
return success(data: ( new NiucloudService() )->getFrameworkVersionList());
} }
/** /**
* 申请体验 * 申请体验
* @return Response * @return Response
*/ */
public function applyExperience() { public function applyExperience()
return success((new NiucloudService())->applyExperience()); {
return success(( new NiucloudService() )->applyExperience());
}
/**
* 获取应用/插件的版本更新记录
* @return Response
*/
public function getAppVersionList()
{
$data = $this->request->params([
[ 'app_key', '' ],
]);
return success(data: ( new NiucloudService() )->getAppVersionList($data[ 'app_key' ]));
} }
} }

View File

@ -17,6 +17,13 @@ use core\base\BaseAdminController;
class PayRefund extends BaseAdminController class PayRefund extends BaseAdminController
{ {
/**
* @return \think\Response
*/
public function getStatus()
{
return success(RefundDict::getStatus());
}
/** /**
* 退款列表 * 退款列表
* @return \think\Response * @return \think\Response

View File

@ -23,7 +23,7 @@ class Config extends BaseAdminController
*/ */
public function getWebsite() public function getWebsite()
{ {
return success((new ConfigService())->getWebSite()); return success(( new ConfigService() )->getWebSite());
} }
/** /**
@ -51,14 +51,14 @@ class Config extends BaseAdminController
[ "front_end_icon", "" ], [ "front_end_icon", "" ],
[ "icon", "" ] [ "icon", "" ]
]); ]);
(new ConfigService())->setWebSite($data); ( new ConfigService() )->setWebSite($data);
$service_data = $this->request->params([ $service_data = $this->request->params([
[ "wechat_code", "" ], [ "wechat_code", "" ],
[ "enterprise_wechat", "" ], [ "enterprise_wechat", "" ],
[ "tel", "" ], [ "tel", "" ],
]); ]);
(new ConfigService())->setService($service_data); ( new ConfigService() )->setService($service_data);
return success(); return success();
} }
@ -69,7 +69,7 @@ class Config extends BaseAdminController
*/ */
public function getCopyright() public function getCopyright()
{ {
return success((new ConfigService())->getCopyright()); return success(( new ConfigService() )->getCopyright());
} }
/**设置版权信息 /**设置版权信息
@ -78,16 +78,16 @@ class Config extends BaseAdminController
public function setCopyright() public function setCopyright()
{ {
$data = $this->request->params([ $data = $this->request->params([
['icp', ''], [ 'icp', '' ],
['gov_record', ''], [ 'gov_record', '' ],
['gov_url', ''], [ 'gov_url', '' ],
['market_supervision_url', ''], [ 'market_supervision_url', '' ],
['logo', ''], [ 'logo', '' ],
['company_name', ''], [ 'company_name', '' ],
['copyright_link', ''], [ 'copyright_link', '' ],
['copyright_desc', ''], [ 'copyright_desc', '' ],
]); ]);
(new ConfigService())->setCopyright($data); ( new ConfigService() )->setCopyright($data);
return success(); return success();
} }
@ -97,7 +97,7 @@ class Config extends BaseAdminController
*/ */
public function getSceneDomain() public function getSceneDomain()
{ {
return success((new ConfigService())->getSceneDomain()); return success(( new ConfigService() )->getSceneDomain());
} }
/** /**
@ -106,7 +106,7 @@ class Config extends BaseAdminController
*/ */
public function getServiceInfo() public function getServiceInfo()
{ {
return success((new ConfigService())->getService()); return success(( new ConfigService() )->getService());
} }
/**设置版权信息 /**设置版权信息
@ -115,11 +115,11 @@ class Config extends BaseAdminController
public function setMap() public function setMap()
{ {
$data = $this->request->params([ $data = $this->request->params([
['key', ''], [ 'key', '' ],
[ 'is_open', 0 ], // 是否开启定位 [ 'is_open', 0 ], // 是否开启定位
[ 'valid_time', 0 ] // 定位有效期/分钟过期后将重新获取定位信息0为不过期 [ 'valid_time', 0 ] // 定位有效期/分钟过期后将重新获取定位信息0为不过期
]); ]);
(new ConfigService())->setMap($data); ( new ConfigService() )->setMap($data);
return success(); return success();
} }
@ -129,7 +129,7 @@ class Config extends BaseAdminController
*/ */
public function getMap() public function getMap()
{ {
return success((new ConfigService())->getMap()); return success(( new ConfigService() )->getMap());
} }
/** /**
@ -148,19 +148,21 @@ class Config extends BaseAdminController
* 获取开发者key * 获取开发者key
* @return Response * @return Response
*/ */
public function getDeveloperToken() { public function getDeveloperToken()
return success(data: (new ConfigService())->getDeveloperToken()); {
return success(data: ( new ConfigService() )->getDeveloperToken());
} }
/** /**
* 设置开发者key * 设置开发者key
* @return Response * @return Response
*/ */
public function setDeveloperToken() { public function setDeveloperToken()
{
$data = $this->request->params([ $data = $this->request->params([
['token', ''], [ 'token', '' ],
]); ]);
(new ConfigService())->setDeveloperToken($data); ( new ConfigService() )->setDeveloperToken($data);
return success(); return success();
} }
@ -168,7 +170,9 @@ class Config extends BaseAdminController
* 获取install.php配置 * 获取install.php配置
* @return Response * @return Response
*/ */
public function getInstallConfig() { public function getInstallConfig()
{
return success(config('install')); return success(config('install'));
} }
} }

View File

@ -91,4 +91,19 @@ class System extends BaseAdminController
{ {
return success(['app_debug' => env('app_debug', false)]); return success(['app_debug' => env('app_debug', false)]);
} }
/**
* 获取推广二维码
* @return Response
*/
public function getSpreadQrcode()
{
$params = $this->request->params([
['form_id', ''],
['folder',''],
['page',''],
['params',[]]
]);
return success((new SystemService())->getQrcode($params));
}
} }

View File

@ -24,7 +24,7 @@ class Verifier extends BaseAdminController
*/ */
public function lists() public function lists()
{ {
return success(data:(new VerifierService())->getPage()); return success(data: ( new VerifierService() )->getPage());
} }
/** /**
@ -33,7 +33,17 @@ class Verifier extends BaseAdminController
*/ */
public function select() public function select()
{ {
return success(data:(new VerifierService())->getList()); return success(data: ( new VerifierService() )->getList());
}
/**
* 获取核销员信息
* @param int $order_id
* @return Response
*/
public function detail($id)
{
return success(data: ( new VerifierService() )->getDetail($id));
} }
/** /**
@ -44,10 +54,24 @@ class Verifier extends BaseAdminController
public function add() public function add()
{ {
$data = $this->request->params([ $data = $this->request->params([
['member_id', 0], [ 'member_id', 0 ],
['verify_type', ''], [ 'verify_type', '' ],
]); ]);
return success(data:(new VerifierService())->add($data)); return success(data: ( new VerifierService() )->add($data));
}
/**
* 添加核销员
* @param int $order_id
* @return Response
*/
public function edit($id)
{
$data = $this->request->params([
[ 'verify_type', '' ],
]);
( new VerifierService() )->edit($id,$data);
return success('EDIT_SUCCESS');
} }
/** /**
@ -55,7 +79,7 @@ class Verifier extends BaseAdminController
*/ */
public function del(int $id) public function del(int $id)
{ {
return success('DELETE_SUCCESS', (new VerifierService())->del($id)); return success('DELETE_SUCCESS', ( new VerifierService() )->del($id));
} }
/** /**

View File

@ -24,13 +24,13 @@ class Verify extends BaseAdminController
public function lists() public function lists()
{ {
$data = $this->request->params([ $data = $this->request->params([
['relate_tag', 0], [ 'relate_tag', 0 ],
['type', ''], [ 'type', '' ],
['code', ''], [ 'code', '' ],
['verifier_member_id', ''], [ 'verifier_member_id', '' ],
['create_time', []] [ 'create_time', [] ]
]); ]);
return success((new VerifyService())->getPage($data)); return success(( new VerifyService() )->getPage($data));
} }
/** /**
@ -40,6 +40,6 @@ class Verify extends BaseAdminController
*/ */
public function detail(string $verify_code) public function detail(string $verify_code)
{ {
return success((new VerifyService())->getDetail($verify_code)); return success(( new VerifyService() )->getDetail($verify_code));
} }
} }

View File

@ -42,6 +42,9 @@ Route::group('niucloud', function () {
// 获取框架版本更新记录 // 获取框架版本更新记录
Route::get('framework/version/list', 'niucloud.Module/getFrameworkVersionList'); Route::get('framework/version/list', 'niucloud.Module/getFrameworkVersionList');
// 获取应用/插件的版本更新记录
Route::get('app_version/list', 'niucloud.Module/getAppVersionList');
// 云编译 // 云编译
Route::post('build', 'niucloud.Cloud/build'); Route::post('build', 'niucloud.Cloud/build');
// 云编译 // 云编译

View File

@ -52,6 +52,7 @@ Route::group('pay', function () {
//退款列表 //退款列表
Route::get('refund', 'pay.PayRefund/pages'); Route::get('refund', 'pay.PayRefund/pages');
//退款详情 //退款详情
Route::get('refund/status', 'pay.PayRefund/getStatus');
Route::get('refund/:refund_no', 'pay.PayRefund/detail'); Route::get('refund/:refund_no', 'pay.PayRefund/detail');
//退款方式 //退款方式
Route::get('refund/type', 'pay.PayRefund/getRefundType'); Route::get('refund/type', 'pay.PayRefund/getRefundType');

View File

@ -23,6 +23,7 @@ Route::group('sys', function() {
//系统信息 //系统信息
Route::get('info', 'sys.System/info'); Route::get('info', 'sys.System/info');
Route::get('url', 'sys.System/url'); Route::get('url', 'sys.System/url');
Route::get('qrcode', 'sys.System/getSpreadQrcode');
/***************************************************** 用户组 ****************************************************/ /***************************************************** 用户组 ****************************************************/
//用户组列表 //用户组列表
Route::get('role', 'sys.Role/lists'); Route::get('role', 'sys.Role/lists');
@ -56,7 +57,7 @@ Route::group('sys', function() {
//授权用户菜单 //授权用户菜单
Route::get('authmenu', 'sys.Auth/authMenuList'); Route::get('authmenu', 'sys.Auth/authMenuList');
// 获取菜单信息 // 获取菜单信息
Route::get('menu/:app_type/info/:menu_key', 'sys.Menu/info'); Route::get('menu/info/:menu_key', 'sys.Menu/info');
// 初始化菜单 // 初始化菜单
Route::post('menu/refresh', 'sys.Menu/refreshMenu'); Route::post('menu/refresh', 'sys.Menu/refreshMenu');
@ -267,7 +268,6 @@ Route::group('sys', function() {
// 百度编辑器文件上传 // 百度编辑器文件上传
Route::post('ueditor', 'sys.Ueditor/upload'); Route::post('ueditor', 'sys.Ueditor/upload');
/***************************************************** 小票打印管理 ****************************************************/ /***************************************************** 小票打印管理 ****************************************************/
// 小票打印机分页列表 // 小票打印机分页列表

View File

@ -19,18 +19,59 @@ use think\facade\Route;
* 路由 * 路由
*/ */
Route::group('', function () { Route::group('', function () {
// 获取正在进行的升级任务 // 获取正在进行的升级任务
Route::get('upgrade/task', 'addon.Upgrade/getUpgradeTask'); Route::get('upgrade/task', 'addon.Upgrade/getUpgradeTask');
// 执行升级 // 执行升级
Route::post('upgrade/execute', 'addon.Upgrade/execute'); Route::post('upgrade/execute', 'addon.Upgrade/execute');
// 清除升级任务 // 清除升级任务
Route::post('upgrade/clear', 'addon.Upgrade/clearUpgradeTask'); Route::post('upgrade/clear', 'addon.Upgrade/clearUpgradeTask');
// 升级环境检测 // 升级环境检测
Route::get('upgrade/check/[:addon]', 'addon.Upgrade/upgradePreCheck'); Route::get('upgrade/check/[:addon]', 'addon.Upgrade/upgradePreCheck')->pattern(['addon' => '[\w|\,]+']);
// 升级 // 升级
Route::post('upgrade/[:addon]', 'addon.Upgrade/upgrade'); Route::post('upgrade/[:addon]', 'addon.Upgrade/upgrade')->pattern(['addon' => '[\w|\,]+']);
// 获取升级内容 // 获取升级内容
Route::get('upgrade/[:addon]', 'addon.Upgrade/getUpgradeContent'); Route::get('upgrade/[:addon]', 'addon.Upgrade/getUpgradeContent')->pattern(['addon' => '[\w|\,]+']);
Route::post('upgrade/operate/:operate', 'addon.Upgrade/operate');
// 升级记录分页列表
Route::get('upgrade/records', 'addon.Upgrade/getRecords');
// 删除升级记录
Route::delete('upgrade/records', 'addon.Upgrade/delRecords');
// 备份记录分页列表
Route::get('backup/records', 'addon.Backup/getRecords');
// 修改备注
Route::put('backup/remark', 'addon.Backup/modifyRemark');
// 恢复前检测文件是否存在,备份
Route::post('backup/check_dir', 'addon.Backup/checkDirExist');
// 检测目录权限
Route::post('backup/check_permission', 'addon.Backup/checkPermission');
// 恢复升级备份
Route::post('backup/restore', 'addon.Backup/restoreBackup');
// 删除升级记录
Route::post('backup/delete', 'addon.Backup/deleteRecords');
// 手动备份
Route::post('backup/manual', 'addon.Backup/manualBackup');
// 获取进行中的恢复
Route::get('backup/restore_task', 'addon.Backup/getRestoreTask');
// 获取进行中的备份
Route::get('backup/task', 'addon.Backup/getBackupTask');
})->middleware([ })->middleware([
AdminCheckToken::class, AdminCheckToken::class,
AdminCheckRole::class, AdminCheckRole::class,

View File

@ -28,6 +28,8 @@ Route::group('verify', function () {
/***************************************************** 核销员相关接口 ****************************************************/ /***************************************************** 核销员相关接口 ****************************************************/
// 添加核销员 // 添加核销员
Route::post('verifier', 'verify.Verifier/add'); Route::post('verifier', 'verify.Verifier/add');
Route::post('verifier/:id', 'verify.Verifier/edit');
Route::get('verifier/:id', 'verify.Verifier/detail');
// 获取核销员列表 // 获取核销员列表
Route::get('verifier', 'verify.Verifier/lists'); Route::get('verifier', 'verify.Verifier/lists');
// 获取核销员列表 // 获取核销员列表

View File

@ -22,53 +22,60 @@ class Verify extends BaseApiController
* 获取验证码 * 获取验证码
* @return Response * @return Response
*/ */
public function getVerifyCode(){ public function getVerifyCode()
{
$data = $this->request->params([ $data = $this->request->params([
['data', []], [ 'data', [] ],
['type', ''] [ 'type', '' ]
]); ]);
return success(data:(new VerifyService())->getVerifyCode($data['type'], $data['data'])); return success(data: ( new VerifyService() )->getVerifyCode($data[ 'type' ], $data[ 'data' ]));
} }
/** /**
* 获取核销码信息 * 获取核销码信息
* @return Response * @return Response
*/ */
public function getInfoByCode(){ public function getInfoByCode()
{
$data = $this->request->params([ $data = $this->request->params([
['code', ''], [ 'code', '' ],
]); ]);
return success(data:(new VerifyService())->getInfoByCode($data['code'])); return success(data: ( new VerifyService() )->getInfoByCode($data[ 'code' ]));
} }
/** /**
* 核销 * 核销
* @param $code * @param $code
* @return Response * @return Response
*/ */
public function verify($code){ public function verify($code)
return success(data:(new VerifyService())->verify($code)); {
return success(data: ( new VerifyService() )->verify($code));
} }
/** /**
* 校验是否是核销员 * 校验是否是核销员
* @return Response * @return Response
*/ */
public function checkVerifier(){ public function checkVerifier()
return success(data:(new VerifyService())->checkVerifier()); {
return success(data: ( new VerifyService() )->checkVerifier());
} }
/** /**
* 核销记录 * 核销记录
* @return void * @return void
*/ */
public function records(){ public function records()
{
$data = $this->request->params([ $data = $this->request->params([
['relate_tag', 0], [ 'relate_tag', 0 ],
['type', ''], [ 'type', '' ],
['code', ''], [ 'code', '' ],
['keyword', ''], [ 'keyword', '' ],
['create_time', []] [ 'create_time', [] ]
]); ]);
return success(data:(new VerifyService())->getRecordsPageByVerifier($data)); return success(data: ( new VerifyService() )->getRecordsPageByVerifier($data));
} }
/** /**
@ -76,8 +83,9 @@ class Verify extends BaseApiController
* @param $code * @param $code
* @return Response * @return Response
*/ */
public function detail(string|int $code){ public function detail(string|int $code)
return success(data:(new VerifyService())->getRecordsDetailByVerifier($code)); {
return success(data: ( new VerifyService() )->getRecordsDetailByVerifier($code));
} }
} }

View File

@ -554,7 +554,7 @@ function dir_copy(string $src = '', string $dst = '', &$files = [], $exclude_dir
if (is_dir($src . '/' . $file)) { if (is_dir($src . '/' . $file)) {
// 排除目录 // 排除目录
if (count($exclude_dirs) && in_array($file, $exclude_dirs)) continue; if (count($exclude_dirs) && in_array($file, $exclude_dirs)) continue;
dir_copy($src . '/' . $file, $dst . '/' . $file, $files); dir_copy($src . '/' . $file, $dst . '/' . $file, $files, $exclude_dirs, $exclude_files);
} else { } else {
// 排除文件 // 排除文件
if (count($exclude_files) && in_array($file, $exclude_files)) continue; if (count($exclude_files) && in_array($file, $exclude_files)) continue;
@ -1033,10 +1033,13 @@ function get_last_time($time = null)
/** /**
* 检查目录及其子目录的权限 * 检查目录及其子目录的权限
* @param string $dir 要检查的目录路径 * @param $dir 要检查的目录路径
* @return void * @param $data
* @param $exclude_dir 排除排除无需检测的的文件夹
* @return array|array[]|mixed
*/ */
function checkDirPermissions($dir, $data = []) { function checkDirPermissions($dir, $data = [], $exclude_dir = [])
{
if (!is_dir($dir)) { if (!is_dir($dir)) {
throw new \RuntimeException(sprintf('指定的路径 "%s" 不是一个有效的目录', $dir)); throw new \RuntimeException(sprintf('指定的路径 "%s" 不是一个有效的目录', $dir));
} }
@ -1050,33 +1053,83 @@ function checkDirPermissions($dir, $data = []) {
try { try {
if (!is_readable($dir)) { if (!is_readable($dir)) {
$data['unreadable'][] = $dir; $data[ 'unreadable' ][] = $dir;
} }
if (!is_writable($dir)) { if (!is_writable($dir)) {
$data['not_writable'][] = $dir; $data[ 'not_writable' ][] = $dir;
} }
if (is_readable($dir)) { if (is_readable($dir)) {
$dh = opendir($dir); $dh = opendir($dir);
while (($file = readdir($dh)) !== false) { while (( $file = readdir($dh) ) !== false) {
if ($file === '.' || $file === '..') { if ($file === '.' || $file === '..') {
continue; continue;
} }
$fullPath = $dir . DIRECTORY_SEPARATOR . $file; $fullPath = $dir . DIRECTORY_SEPARATOR . $file;
// 忽略指定目录
$is_exclude = false;
foreach ($exclude_dir as $k => $item) {
if (strpos($fullPath, $item)) {
$is_exclude = true;
break;
}
}
if ($is_exclude) continue;
// 判断是否为目录,如果是则递归调用 // 判断是否为目录,如果是则递归调用
if (is_dir($fullPath)) { if (is_dir($fullPath)) {
$data = checkDirPermissions($fullPath, $data); // 递归调用自身来检查子目录 $data = checkDirPermissions($fullPath, $data, $exclude_dir); // 递归调用自身来检查子目录
} else { } else {
// 如果是文件,则检查其读写权限 // 如果是文件,则检查其读写权限
if (!is_readable($fullPath)) $data['unreadable'][] = $fullPath; if (!is_readable($fullPath)) $data[ 'unreadable' ][] = $fullPath;
if (!is_writable($fullPath)) $data['not_writable'][] = $fullPath; if (!is_writable($fullPath)) $data[ 'not_writable' ][] = $fullPath;
} }
} }
closedir($dh); closedir($dh);
} }
return $data; return $data;
} catch (Exception $e) { } catch (Exception $e) {
$data['unreadable'][] = $dir; $data[ 'unreadable' ][] = $dir;
$data['not_writable'][] = $dir; $data[ 'not_writable' ][] = $dir;
return $data; return $data;
} }
} }
/**
* 下载网络图片
* @param $img_url 图片URL
* @param $file_name 本地保存位置
* @return bool
*/
function downloadImage($img_url, $file_name)
{
// 初始化 cURL 会话
$ch = curl_init($img_url);
// 打开本地文件以写入模式
$fp = fopen($file_name, 'wb');
// 设置 cURL 选项
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
// 跳过 SSL 验证
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
// 执行 cURL 会话
curl_exec($ch);
// 检查是否有错误发生
if (curl_errno($ch)) {
// echo 'Curl error: ' . curl_error($ch);
return false;
}
// 关闭 cURL 会话和文件句柄
curl_close($ch);
fclose($fp);
return true;
}

View File

@ -414,56 +414,57 @@ class ComponentDict
return $data; return $data;
} }
], ],
// 'FormWechatName' => [ // 'FormWechatName' => [
// 'title' => '微信名', // 'title' => '微信名',
// 'icon' => 'iconfont iconbiaotipc', // 'icon' => 'iconfont iconbiaotipc',
// 'path' => 'edit-form-wechat-name', // 编辑组件属性名称 // 'path' => 'edit-form-wechat-name', // 编辑组件属性名称
// 'uses' => 1, // 最大添加数量 // 'uses' => 1, // 最大添加数量
// 'sort' => 10007, // 'sort' => 10007,
// // 组件属性 // // 组件属性
// 'template' => [ // 'template' => [
// "textColor" => "#303133", // 文字颜色 // "textColor" => "#303133", // 文字颜色
// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始)
// 'pageEndBgColor' => '', // 底部背景颜色(结束) // 'pageEndBgColor' => '', // 底部背景颜色(结束)
// 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right // 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
// 'componentBgUrl' => '', // 组件背景图片 // 'componentBgUrl' => '', // 组件背景图片
// 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10 // 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10
// "componentStartBgColor" => '', // 组件背景颜色(开始) // "componentStartBgColor" => '', // 组件背景颜色(开始)
// "componentEndBgColor" => '', // 组件背景颜色(结束) // "componentEndBgColor" => '', // 组件背景颜色(结束)
// "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right // "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right
// "topRounded" => 0, // 组件上圆角 // "topRounded" => 0, // 组件上圆角
// "bottomRounded" => 0, // 组件下圆角 // "bottomRounded" => 0, // 组件下圆角
// "elementBgColor" => '', // 元素背景颜色 // "elementBgColor" => '', // 元素背景颜色
// "topElementRounded" => 0,// 元素上圆角 // "topElementRounded" => 0,// 元素上圆角
// "bottomElementRounded" => 0, // 元素下圆角 // "bottomElementRounded" => 0, // 元素下圆角
// "margin" => [ // "margin" => [
// "top" => 10, // 上边距 // "top" => 10, // 上边距
// "bottom" => 10, // 下边距 // "bottom" => 10, // 下边距
// "both" => 10 // 左右边距 // "both" => 10 // 左右边距
// ], // ],
// ], // ],
// 'value' => [ // 'value' => [
// // 表单的公共属性 // // 表单的公共属性
// 'field' => [ // 'field' => [
// 'name' => '微信名', // 字段名称 // 'name' => '微信名', // 字段名称
// // 字段说明,支持修改颜色、大小 // // 字段说明,支持修改颜色、大小
// 'remark' => [ // 'remark' => [
// 'text' => '', // 'text' => '',
// 'color' => '#999999', // 'color' => '#999999',
// "fontSize" => 14, // "fontSize" => 14,
// ], // ],
// 'required' => false, // 是否必填 truefalse // 'required' => false, // 是否必填 truefalse
// 'unique' => false, // 内容不可重复提交 truefalse // 'unique' => false, // 内容不可重复提交 truefalse
// 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭 // 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭
// 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理 // 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理
// 'cache' => true, // 开启本地数据缓存 true开启false关闭 // 'cache' => true, // 开启本地数据缓存 true开启false关闭
// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理
// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理
// ], // ],
// "fontSize" => 14, // 'placeholder' => '请输入', // 提示语
// "fontWeight" => "normal", // "fontSize" => 14,
// ] // "fontWeight" => "normal",
// ], // ]
// ],
'FormMobile' => [ 'FormMobile' => [
'title' => '手机号', 'title' => '手机号',
'icon' => 'iconfont icona-shoujipc30', 'icon' => 'iconfont icona-shoujipc30',
@ -617,74 +618,84 @@ class ComponentDict
"fontWeight" => "normal", "fontWeight" => "normal",
] ]
], ],
// 'FormTable' => [ // 'FormTable' => [
// 'title' => '表格', // 'title' => '表格',
// 'icon' => 'iconfont iconbiaotipc', // 'icon' => 'iconfont iconbiaotipc',
// 'path' => 'edit-form-table', // 编辑组件属性名称 // 'path' => 'edit-form-table', // 编辑组件属性名称
// 'uses' => 0, // 最大添加数量 // 'uses' => 0, // 最大添加数量
// 'sort' => 10011, // 'sort' => 10011,
// // 组件属性 // // 组件属性
// 'template' => [ // 'template' => [
// "textColor" => "#303133", // 文字颜色 // "textColor" => "#303133", // 文字颜色
// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始)
// 'pageEndBgColor' => '', // 底部背景颜色(结束) // 'pageEndBgColor' => '', // 底部背景颜色(结束)
// 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right // 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
// 'componentBgUrl' => '', // 组件背景图片 // 'componentBgUrl' => '', // 组件背景图片
// 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10 // 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10
// "componentStartBgColor" => '', // 组件背景颜色(开始) // "componentStartBgColor" => '', // 组件背景颜色(开始)
// "componentEndBgColor" => '', // 组件背景颜色(结束) // "componentEndBgColor" => '', // 组件背景颜色(结束)
// "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right // "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right
// "topRounded" => 0, // 组件上圆角 // "topRounded" => 0, // 组件上圆角
// "bottomRounded" => 0, // 组件下圆角 // "bottomRounded" => 0, // 组件下圆角
// "elementBgColor" => '', // 元素背景颜色 // "elementBgColor" => '', // 元素背景颜色
// "topElementRounded" => 0,// 元素上圆角 // "topElementRounded" => 0,// 元素上圆角
// "bottomElementRounded" => 0, // 元素下圆角 // "bottomElementRounded" => 0, // 元素下圆角
// "margin" => [ // "margin" => [
// "top" => 10, // 上边距 // "top" => 10, // 上边距
// "bottom" => 10, // 下边距 // "bottom" => 10, // 下边距
// "both" => 10 // 左右边距 // "both" => 10 // 左右边距
// ], // ],
// ], // ],
// 'value' => [ // 'value' => [
// // 表单的公共属性 // // 表单的公共属性
// 'field' => [ // 'field' => [
// 'name' => '表格', // 字段名称 // 'name' => '表格', // 字段名称
// // 字段说明,支持修改颜色、大小 // // 字段说明,支持修改颜色、大小
// 'remark' => [ // 'remark' => [
// 'text' => '', // 'text' => '',
// 'color' => '#999999', // 'color' => '#999999',
// "fontSize" => 14, // "fontSize" => 14,
// ], // ],
// 'required' => false, // 是否必填 truefalse // 'required' => false, // 是否必填 truefalse
// 'unique' => false, // 内容不可重复提交 truefalse // 'unique' => false, // 内容不可重复提交 truefalse
// 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭 // 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭
// 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理 // 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理
// 'cache' => true, // 开启本地数据缓存 true开启false关闭 // 'cache' => true, // 开启本地数据缓存 true开启false关闭
// 'detailComponent' => '/src/app/views/diy_form/components/detail-form-table.vue', // 用于详情展示 // 'detailComponent' => '/src/app/views/diy_form/components/detail-form-table.vue', // 用于详情展示
// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理
// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理
// ], // ],
// "fontSize" => 14, // "fontSize" => 14,
// "fontWeight" => "normal", // "fontWeight" => "normal",
// // 列设置 // // 列设置
// 'columnList' => [ // 'columnList' => [
// [ // [
// 'id' => '', // 唯一值,用于排序 // 'id' => '', // 唯一值,用于排序
// 'type' => 'text', // 类型text文本number数字radio单选项checkbox多选项todo不同类型结构也不一样这个组件要在前端处理 // 'type' => 'text', // 类型text文本number数字radio单选项checkbox多选项todo不同类型结构也不一样这个组件要在前端处理
// 'name' => '', // 字段名称 // 'name' => '', // 字段名称
// 'value' => '选项1' // 字段值 // 'value' => '选项1' // 字段值
// ], // ],
// ], // ],
// 'autoIncrementControl' => false, // 是否开启自增(展示按钮),添加多个 // 'autoIncrementControl' => false, // 是否开启自增(展示按钮),添加多个
// // 填写限制(开启自增才展示) // // 填写限制(开启自增才展示)
// 'writeLimit' => [ // 'writeLimit' => [
// 'default' => 2, // 默认展示 N 项 // 'default' => 2, // 默认展示 N 项
// 'min' => 0, // 最少填写 N 项 // 'min' => 0, // 最少填写 N 项
// 'max' => 0 // 最多填写 N 项 // 'max' => 0 // 最多填写 N 项
// ], // ],
// 'btnText' => '新增一组' // 'btnText' => '新增一组'
// ] // ],
// ], // // 渲染值
// 'render' => function($data) {
// // todo 处理业务数据
// return '';
// },
// // 转换类型
// 'convert' => function($data) {
// // todo 处理业务数据
// return $data;
// }
// ],
'FormDate' => [ 'FormDate' => [
'title' => '日期', 'title' => '日期',
'icon' => 'iconfont icona-riqipc30', 'icon' => 'iconfont icona-riqipc30',
@ -997,109 +1008,109 @@ class ComponentDict
return $data; return $data;
} }
], ],
// 'FormLocation' => [ // 'FormLocation' => [
// 'title' => '定位', // 'title' => '定位',
// 'icon' => 'iconfont iconbiaotipc', // 'icon' => 'iconfont iconbiaotipc',
// 'path' => 'edit-form-location', // 编辑组件属性名称 // 'path' => 'edit-form-location', // 编辑组件属性名称
// 'uses' => 1, // 最大添加数量 // 'uses' => 1, // 最大添加数量
// 'sort' => 10016, // 'sort' => 10016,
// // 组件属性 // // 组件属性
// 'template' => [ // 'template' => [
// "textColor" => "#303133", // 文字颜色 // "textColor" => "#303133", // 文字颜色
// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始)
// 'pageEndBgColor' => '', // 底部背景颜色(结束) // 'pageEndBgColor' => '', // 底部背景颜色(结束)
// 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right // 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
// 'componentBgUrl' => '', // 组件背景图片 // 'componentBgUrl' => '', // 组件背景图片
// 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10 // 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10
// "componentStartBgColor" => '', // 组件背景颜色(开始) // "componentStartBgColor" => '', // 组件背景颜色(开始)
// "componentEndBgColor" => '', // 组件背景颜色(结束) // "componentEndBgColor" => '', // 组件背景颜色(结束)
// "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right // "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right
// "topRounded" => 0, // 组件上圆角 // "topRounded" => 0, // 组件上圆角
// "bottomRounded" => 0, // 组件下圆角 // "bottomRounded" => 0, // 组件下圆角
// "elementBgColor" => '', // 元素背景颜色 // "elementBgColor" => '', // 元素背景颜色
// "topElementRounded" => 0,// 元素上圆角 // "topElementRounded" => 0,// 元素上圆角
// "bottomElementRounded" => 0, // 元素下圆角 // "bottomElementRounded" => 0, // 元素下圆角
// "margin" => [ // "margin" => [
// "top" => 10, // 上边距 // "top" => 10, // 上边距
// "bottom" => 10, // 下边距 // "bottom" => 10, // 下边距
// "both" => 10 // 左右边距 // "both" => 10 // 左右边距
// ], // ],
// ], // ],
// 'value' => [ // 'value' => [
// // 表单的公共属性 // // 表单的公共属性
// 'field' => [ // 'field' => [
// 'name' => '定位', // 字段名称 // 'name' => '定位', // 字段名称
// // 字段说明,支持修改颜色、大小 // // 字段说明,支持修改颜色、大小
// 'remark' => [ // 'remark' => [
// 'text' => '', // 'text' => '',
// 'color' => '#999999', // 'color' => '#999999',
// "fontSize" => 14, // "fontSize" => 14,
// ], // ],
// 'required' => false, // 是否必填 truefalse // 'required' => false, // 是否必填 truefalse
// 'unique' => false, // 内容不可重复提交 truefalse // 'unique' => false, // 内容不可重复提交 truefalse
// 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭 // 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭
// 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理 // 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理
// 'cache' => true, // 开启本地数据缓存 true开启false关闭 // 'cache' => true, // 开启本地数据缓存 true开启false关闭
// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理
// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理
// ], // ],
// 'placeholder' => '请输入', // 提示语 // 'placeholder' => '请输入', // 提示语
// "fontSize" => 14, // "fontSize" => 14,
// "fontWeight" => "normal", // "fontWeight" => "normal",
// 'mode' => 'authorized_wechat_location', // 获取方式authorized_wechat_location授权微信定位open_choose_location手动选择定位 // 'mode' => 'authorized_wechat_location', // 获取方式authorized_wechat_location授权微信定位open_choose_location手动选择定位
// ] // ]
// ], // ],
// 'FormAddress' => [ // 'FormAddress' => [
// 'title' => '地址', // 'title' => '地址',
// 'icon' => 'iconfont iconbiaotipc', // 'icon' => 'iconfont iconbiaotipc',
// 'path' => 'edit-form-address', // 编辑组件属性名称 // 'path' => 'edit-form-address', // 编辑组件属性名称
// 'uses' => 0, // 最大添加数量 // 'uses' => 0, // 最大添加数量
// 'sort' => 10017, // 'sort' => 10017,
// // 组件属性 // // 组件属性
// 'template' => [ // 'template' => [
// "textColor" => "#303133", // 文字颜色 // "textColor" => "#303133", // 文字颜色
// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始)
// 'pageEndBgColor' => '', // 底部背景颜色(结束) // 'pageEndBgColor' => '', // 底部背景颜色(结束)
// 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right // 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
// 'componentBgUrl' => '', // 组件背景图片 // 'componentBgUrl' => '', // 组件背景图片
// 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10 // 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10
// "componentStartBgColor" => '', // 组件背景颜色(开始) // "componentStartBgColor" => '', // 组件背景颜色(开始)
// "componentEndBgColor" => '', // 组件背景颜色(结束) // "componentEndBgColor" => '', // 组件背景颜色(结束)
// "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right // "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right
// "topRounded" => 0, // 组件上圆角 // "topRounded" => 0, // 组件上圆角
// "bottomRounded" => 0, // 组件下圆角 // "bottomRounded" => 0, // 组件下圆角
// "elementBgColor" => '', // 元素背景颜色 // "elementBgColor" => '', // 元素背景颜色
// "topElementRounded" => 0,// 元素上圆角 // "topElementRounded" => 0,// 元素上圆角
// "bottomElementRounded" => 0, // 元素下圆角 // "bottomElementRounded" => 0, // 元素下圆角
// "margin" => [ // "margin" => [
// "top" => 10, // 上边距 // "top" => 10, // 上边距
// "bottom" => 10, // 下边距 // "bottom" => 10, // 下边距
// "both" => 10 // 左右边距 // "both" => 10 // 左右边距
// ], // ],
// ], // ],
// 'value' => [ // 'value' => [
// // 表单的公共属性 // // 表单的公共属性
// 'field' => [ // 'field' => [
// 'name' => '地址', // 字段名称 // 'name' => '地址', // 字段名称
// // 字段说明,支持修改颜色、大小 // // 字段说明,支持修改颜色、大小
// 'remark' => [ // 'remark' => [
// 'text' => '', // 'text' => '',
// 'color' => '#999999', // 'color' => '#999999',
// "fontSize" => 14, // "fontSize" => 14,
// ], // ],
// 'required' => false, // 是否必填 truefalse // 'required' => false, // 是否必填 truefalse
// 'unique' => false, // 内容不可重复提交 truefalse // 'unique' => false, // 内容不可重复提交 truefalse
// 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭 // 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭
// 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理 // 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理
// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 todo 设置默认省/市/区/街道 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 todo 设置默认省/市/区/街道
// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理
// ], // ],
// 'placeholder' => '请输入', // 提示语 // 'placeholder' => '请输入', // 提示语
// "fontSize" => 14, // "fontSize" => 14,
// "fontWeight" => "normal", // "fontWeight" => "normal",
// 'addressFormat' => 'province/city/district/address', // 地址格式 // 'addressFormat' => 'province/city/district/address', // 地址格式
// ] // ]
// ], // ],
'FormImage' => [ 'FormImage' => [
'title' => '图片', 'title' => '图片',
'icon' => 'iconfont icona-tupianpc30', 'icon' => 'iconfont icona-tupianpc30',
@ -1181,115 +1192,115 @@ class ComponentDict
return $data; return $data;
} }
], ],
// 'FormVideo' => [ // 'FormVideo' => [
// 'title' => '视频', // 'title' => '视频',
// 'icon' => 'iconfont iconbiaotipc', // 'icon' => 'iconfont iconbiaotipc',
// 'path' => 'edit-form-video', // 编辑组件属性名称 // 'path' => 'edit-form-video', // 编辑组件属性名称
// 'uses' => 0, // 最大添加数量 // 'uses' => 0, // 最大添加数量
// 'sort' => 10019, // 'sort' => 10019,
// // 组件属性 // // 组件属性
// 'template' => [ // 'template' => [
// "textColor" => "#303133", // 文字颜色 // "textColor" => "#303133", // 文字颜色
// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始)
// 'pageEndBgColor' => '', // 底部背景颜色(结束) // 'pageEndBgColor' => '', // 底部背景颜色(结束)
// 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right // 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
// 'componentBgUrl' => '', // 组件背景图片 // 'componentBgUrl' => '', // 组件背景图片
// 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10 // 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10
// "componentStartBgColor" => '', // 组件背景颜色(开始) // "componentStartBgColor" => '', // 组件背景颜色(开始)
// "componentEndBgColor" => '', // 组件背景颜色(结束) // "componentEndBgColor" => '', // 组件背景颜色(结束)
// "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right // "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right
// "topRounded" => 0, // 组件上圆角 // "topRounded" => 0, // 组件上圆角
// "bottomRounded" => 0, // 组件下圆角 // "bottomRounded" => 0, // 组件下圆角
// "elementBgColor" => '', // 元素背景颜色 // "elementBgColor" => '', // 元素背景颜色
// "topElementRounded" => 0,// 元素上圆角 // "topElementRounded" => 0,// 元素上圆角
// "bottomElementRounded" => 0, // 元素下圆角 // "bottomElementRounded" => 0, // 元素下圆角
// "margin" => [ // "margin" => [
// "top" => 10, // 上边距 // "top" => 10, // 上边距
// "bottom" => 10, // 下边距 // "bottom" => 10, // 下边距
// "both" => 10 // 左右边距 // "both" => 10 // 左右边距
// ], // ],
// ], // ],
// 'value' => [ // 'value' => [
// // 表单的公共属性 // // 表单的公共属性
// 'field' => [ // 'field' => [
// 'name' => '视频', // 字段名称 // 'name' => '视频', // 字段名称
// // 字段说明,支持修改颜色、大小 // // 字段说明,支持修改颜色、大小
// 'remark' => [ // 'remark' => [
// 'text' => '', // 'text' => '',
// 'color' => '#999999', // 'color' => '#999999',
// "fontSize" => 14, // "fontSize" => 14,
// ], // ],
// 'required' => false, // 是否必填 truefalse // 'required' => false, // 是否必填 truefalse
// 'unique' => false, // 内容不可重复提交 truefalse // 'unique' => false, // 内容不可重复提交 truefalse
// 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭 // 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭
// 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理 // 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理
// 'cache' => true, // 开启本地数据缓存 true开启false关闭 // 'cache' => true, // 开启本地数据缓存 true开启false关闭
// 'detailComponent' => '/src/app/views/diy_form/components/detail-form-video.vue', // 用于详情展示 // 'detailComponent' => '/src/app/views/diy_form/components/detail-form-video.vue', // 用于详情展示
// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理
// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理
// ], // ],
// "fontSize" => 14, // "fontSize" => 14,
// "fontWeight" => "normal", // "fontWeight" => "normal",
// /** // /**
// * 上传方式 // * 上传方式
// * shoot_and_album拍摄和相册 // * shoot_and_album拍摄和相册
// * shoot_only只允许拍摄 // * shoot_only只允许拍摄
// */ // */
// 'uploadMode' => 'shoot_and_album', // 上传方式 // 'uploadMode' => 'shoot_and_album', // 上传方式
// ] // ]
// ], // ],
// 'FormFile' => [ // 'FormFile' => [
// 'title' => '文件', // 'title' => '文件',
// 'icon' => 'iconfont iconbiaotipc', // 'icon' => 'iconfont iconbiaotipc',
// 'path' => 'edit-form-file', // 编辑组件属性名称 // 'path' => 'edit-form-file', // 编辑组件属性名称
// 'uses' => 0, // 最大添加数量 // 'uses' => 0, // 最大添加数量
// 'sort' => 10020, // 'sort' => 10020,
// // 组件属性 // // 组件属性
// 'template' => [ // 'template' => [
// "textColor" => "#303133", // 文字颜色 // "textColor" => "#303133", // 文字颜色
// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始)
// 'pageEndBgColor' => '', // 底部背景颜色(结束) // 'pageEndBgColor' => '', // 底部背景颜色(结束)
// 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right // 'pageGradientAngle' => 'to bottom', // 渐变角度从上到下to bottom、从左到右to right
// 'componentBgUrl' => '', // 组件背景图片 // 'componentBgUrl' => '', // 组件背景图片
// 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10 // 'componentBgAlpha' => 2, // 组件背景图片的透明度0~10
// "componentStartBgColor" => '', // 组件背景颜色(开始) // "componentStartBgColor" => '', // 组件背景颜色(开始)
// "componentEndBgColor" => '', // 组件背景颜色(结束) // "componentEndBgColor" => '', // 组件背景颜色(结束)
// "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right // "componentGradientAngle" => 'to bottom', // 渐变角度上下to bottom、左右to right
// "topRounded" => 0, // 组件上圆角 // "topRounded" => 0, // 组件上圆角
// "bottomRounded" => 0, // 组件下圆角 // "bottomRounded" => 0, // 组件下圆角
// "elementBgColor" => '', // 元素背景颜色 // "elementBgColor" => '', // 元素背景颜色
// "topElementRounded" => 0,// 元素上圆角 // "topElementRounded" => 0,// 元素上圆角
// "bottomElementRounded" => 0, // 元素下圆角 // "bottomElementRounded" => 0, // 元素下圆角
// "margin" => [ // "margin" => [
// "top" => 10, // 上边距 // "top" => 10, // 上边距
// "bottom" => 10, // 下边距 // "bottom" => 10, // 下边距
// "both" => 10 // 左右边距 // "both" => 10 // 左右边距
// ], // ],
// ], // ],
// 'value' => [ // 'value' => [
// // 表单的公共属性 // // 表单的公共属性
// 'field' => [ // 'field' => [
// 'name' => '文件', // 字段名称 // 'name' => '文件', // 字段名称
// // 字段说明,支持修改颜色、大小 // // 字段说明,支持修改颜色、大小
// 'remark' => [ // 'remark' => [
// 'text' => '', // 'text' => '',
// 'color' => '#999999', // 'color' => '#999999',
// "fontSize" => 14, // "fontSize" => 14,
// ], // ],
// 'required' => false, // 是否必填 truefalse // 'required' => false, // 是否必填 truefalse
// 'unique' => false, // 内容不可重复提交 truefalse // 'unique' => false, // 内容不可重复提交 truefalse
// 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭 // 'autofill' => false, // 自动填充上次填写的内容 true开启false关闭
// 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理 // 'privacyProtection' => false, // 隐私保护 true开启false关闭隐藏逻辑各组件自行处理
// 'cache' => true, // 开启本地数据缓存 true开启false关闭 // 'cache' => true, // 开启本地数据缓存 true开启false关闭
// 'detailComponent' => '/src/app/views/diy_form/components/detail-form-file.vue', // 用于详情展示 // 'detailComponent' => '/src/app/views/diy_form/components/detail-form-file.vue', // 用于详情展示
// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理
// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理
// ], // ],
// "fontSize" => 14, // "fontSize" => 14,
// "fontWeight" => "normal", // "fontWeight" => "normal",
// 'limitUploadSize' => 30720, // 限制上传大小30MB // 'limitUploadSize' => 30720, // 限制上传大小30MB
// ] // ]
// ], // ],
], ],
], ],
]; ];

View File

@ -381,7 +381,7 @@ class TemplateDict
"unique" => false, "unique" => false,
"autofill" => false, "autofill" => false,
"privacyProtection" => false, "privacyProtection" => false,
'cache' => false, 'cache' => true,
"default" => [ "default" => [
"date" => "", "date" => "",
"timestamp" => 0 "timestamp" => 0
@ -576,7 +576,7 @@ class TemplateDict
"unique" => false, "unique" => false,
"autofill" => false, "autofill" => false,
"privacyProtection" => false, "privacyProtection" => false,
'cache' => false, 'cache' => true,
"default" => [ "default" => [
"start" => [ "start" => [
"date" => "", "date" => "",

View File

@ -1140,6 +1140,20 @@ return [
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
], ],
[
'menu_name' => '编辑核销员',
'menu_key' => 'edit_verifier',
'menu_short_name' => '编辑核销员',
'menu_type' => '2',
'icon' => '',
'api_url' => 'verify/verifier/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'post',
'sort' => '100',
'status' => '1',
'is_show' => '1',
],
[ [
'menu_name' => '删除核销员', 'menu_name' => '删除核销员',
'menu_key' => 'delete_verifier', 'menu_key' => 'delete_verifier',
@ -2437,122 +2451,6 @@ return [
], ],
], ],
], ],
[
'menu_name' => '小票打印',
'menu_key' => 'printer_management',
'menu_short_name' => '小票打印',
'menu_type' => '1',
'icon' => 'element FolderChecked',
'api_url' => 'printer',
'router_path' => 'printer/list',
'view_path' => 'printer/list',
'methods' => 'get',
'sort' => '30',
'status' => '1',
'is_show' => '1',
'children' => [
[
'menu_name' => '删除打印机',
'menu_key' => 'delete_printer',
'menu_short_name' => '删除打印机',
'menu_type' => '2',
'icon' => '',
'api_url' => 'printer/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => '100',
'status' => '1',
'is_show' => '1',
]
]
],
[
'menu_name' => '添加打印机',
'menu_key' => 'printer_add',
'menu_short_name' => '添加打印机',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer',
'router_path' => 'printer/add',
'view_path' => 'printer/edit',
'methods' => 'post',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
[
'menu_name' => '编辑打印机',
'menu_key' => 'printer_edit',
'menu_short_name' => '添加打印机',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer/<id>',
'router_path' => 'printer/edit',
'view_path' => 'printer/edit',
'methods' => 'put',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
[
'menu_name' => '小票打印模板',
'menu_key' => 'printer_template_management',
'menu_short_name' => '小票打印模板',
'menu_type' => '1',
'icon' => 'element FolderChecked',
'api_url' => 'printer/template',
'router_path' => 'printer/template/list',
'view_path' => 'printer/template_list',
'methods' => 'get',
'sort' => '96',
'status' => '1',
'is_show' => '0',
'children' => [
[
'menu_name' => '删除打印模板',
'menu_key' => 'delete_printer_template',
'menu_short_name' => '删除打印模板',
'menu_type' => '2',
'icon' => '',
'api_url' => 'printer/template/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => '100',
'status' => '1',
'is_show' => '1',
]
]
],
[
'menu_name' => '添加打印模板',
'menu_key' => 'printer_template_add',
'menu_short_name' => '添加打印模板',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer/template',
'router_path' => 'printer/template/add',
'view_path' => 'printer/template_edit',
'methods' => 'post',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
[
'menu_name' => '编辑打印模板',
'menu_key' => 'printer_template_edit',
'menu_short_name' => '编辑打印模板',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer/template/<id>',
'router_path' => 'printer/template/edit',
'view_path' => 'printer/template_edit',
'methods' => 'put',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
[ [
'menu_name' => '系统工具', 'menu_name' => '系统工具',
'menu_key' => 'setting_tool', 'menu_key' => 'setting_tool',
@ -2699,36 +2597,6 @@ return [
] ]
] ]
], ],
[
'menu_name' => '数据导出',
'menu_key' => 'setting_export',
'menu_short_name' => '数据导出',
'menu_type' => '1',
'icon' => 'element FolderChecked',
'api_url' => 'sys/export',
'router_path' => 'setting/export',
'view_path' => 'setting/export',
'methods' => 'get',
'sort' => '98',
'status' => '1',
'is_show' => '1',
'children' => [
[
'menu_name' => '删除报表',
'menu_key' => 'delete_export',
'menu_short_name' => '删除报表',
'menu_type' => '2',
'icon' => '',
'api_url' => 'sys/export/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => '100',
'status' => '1',
'is_show' => '1',
]
]
],
] ]
], ],
@ -2860,7 +2728,190 @@ return [
] ]
], ],
[ [
'menu_name' => '开发', 'menu_name' => '数据导出',
'menu_key' => 'setting_export',
'menu_short_name' => '数据导出',
'menu_type' => '0',
'icon' => 'element Files',
'api_url' => '',
'router_path' => '',
'view_path' => '',
'methods' => '',
'sort' => '0',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'setting_export',
'children' => [
[
'menu_name' => '数据导出列表',
'menu_key' => 'setting_export_list',
'menu_short_name' => '数据导出列表',
'menu_type' => '1',
'icon' => 'element FolderChecked',
'api_url' => 'sys/export',
'router_path' => 'setting/export',
'view_path' => 'setting/export',
'methods' => 'get',
'sort' => '98',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'setting_export',
'children' => [
[
'menu_name' => '删除报表',
'menu_key' => 'delete_export',
'menu_short_name' => '删除报表',
'menu_type' => '2',
'icon' => '',
'api_url' => 'sys/export/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => '100',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'setting_export',
]
]
],
]
],
[
'menu_name' => '打印管理',
'menu_key' => 'printer_management',
'menu_short_name' => '打印管理',
'menu_type' => '0',
'icon' => 'element Files',
'api_url' => '',
'router_path' => '',
'view_path' => '',
'methods' => '',
'sort' => '0',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'printer_management',
'children' => [
[
'menu_name' => '小票打印',
'menu_key' => 'printer_management_list',
'menu_short_name' => '小票打印',
'menu_type' => '1',
'icon' => 'element FolderChecked',
'api_url' => 'printer',
'router_path' => 'printer/list',
'view_path' => 'printer/list',
'methods' => 'get',
'sort' => '30',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'printer_management',
'children' => [
[
'menu_name' => '删除打印机',
'menu_key' => 'delete_printer',
'menu_short_name' => '删除打印机',
'menu_type' => '2',
'icon' => '',
'api_url' => 'printer/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => '100',
'status' => '1',
'is_show' => '1',
]
]
],
[
'menu_name' => '添加打印机',
'menu_key' => 'printer_add',
'menu_short_name' => '添加打印机',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer',
'router_path' => 'printer/add',
'view_path' => 'printer/edit',
'methods' => 'post',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
[
'menu_name' => '编辑打印机',
'menu_key' => 'printer_edit',
'menu_short_name' => '添加打印机',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer/<id>',
'router_path' => 'printer/edit',
'view_path' => 'printer/edit',
'methods' => 'put',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
[
'menu_name' => '小票打印模板',
'menu_key' => 'printer_template_management',
'menu_short_name' => '小票打印模板',
'menu_type' => '1',
'icon' => 'element FolderChecked',
'api_url' => 'printer/template',
'router_path' => 'printer/template/list',
'view_path' => 'printer/template_list',
'methods' => 'get',
'sort' => '96',
'status' => '1',
'is_show' => '0',
'children' => [
[
'menu_name' => '删除打印模板',
'menu_key' => 'delete_printer_template',
'menu_short_name' => '删除打印模板',
'menu_type' => '2',
'icon' => '',
'api_url' => 'printer/template/<id>',
'router_path' => '',
'view_path' => '',
'methods' => 'delete',
'sort' => '100',
'status' => '1',
'is_show' => '1',
]
]
],
[
'menu_name' => '添加打印模板',
'menu_key' => 'printer_template_add',
'menu_short_name' => '添加打印模板',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer/template',
'router_path' => 'printer/template/add',
'view_path' => 'printer/template_edit',
'methods' => 'post',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
[
'menu_name' => '编辑打印模板',
'menu_key' => 'printer_template_edit',
'menu_short_name' => '编辑打印模板',
'menu_type' => '1',
'icon' => '',
'api_url' => 'printer/template/<id>',
'router_path' => 'printer/template/edit',
'view_path' => 'printer/template_edit',
'methods' => 'put',
'sort' => '0',
'status' => '1',
'is_show' => '0',
],
]
],
[
'menu_name' => '开发管理',
'menu_key' => 'tool', 'menu_key' => 'tool',
'menu_short_name' => '开发', 'menu_short_name' => '开发',
'parent_key' => '', 'parent_key' => '',
@ -2984,7 +3035,7 @@ return [
'router_path' => 'tools/addon', 'router_path' => 'tools/addon',
'view_path' => 'tools/addon/index', 'view_path' => 'tools/addon/index',
'methods' => '', 'methods' => '',
'sort' => '110', 'sort' => '119',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
'children' => [ 'children' => [
@ -3028,7 +3079,21 @@ return [
'router_path' => 'tools/code', 'router_path' => 'tools/code',
'view_path' => 'tools/code/index', 'view_path' => 'tools/code/index',
'methods' => 'get', 'methods' => 'get',
'sort' => '100', 'sort' => '118',
'status' => '1',
'is_show' => '1',
],
[
'menu_name' => '更新缓存',
'menu_key' => 'update_cache',
'menu_short_name' => '更新缓存',
'menu_type' => '1',
'icon' => 'nc-iconfont nc-icon-qingliV6xx',
'api_url' => 'sys/schema/clear',
'router_path' => 'tools/update_cache',
'view_path' => 'tools/updatecache',
'methods' => 'post',
'sort' => '117',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
], ],
@ -3042,7 +3107,7 @@ return [
'router_path' => 'tools/code/edit', 'router_path' => 'tools/code/edit',
'view_path' => 'tools/code/edit', 'view_path' => 'tools/code/edit',
'methods' => '', 'methods' => '',
'sort' => '99', 'sort' => '100',
'status' => '1', 'status' => '1',
'is_show' => '0', 'is_show' => '0',
'children' => [ 'children' => [
@ -3114,7 +3179,7 @@ return [
'router_path' => 'tools/addon_edit', 'router_path' => 'tools/addon_edit',
'view_path' => 'tools/addon/edit', 'view_path' => 'tools/addon/edit',
'methods' => 'get', 'methods' => 'get',
'sort' => '90', 'sort' => '100',
'status' => '1', 'status' => '1',
'is_show' => '0', 'is_show' => '0',
'children' => [ 'children' => [
@ -3148,20 +3213,6 @@ return [
], ],
] ]
], ],
[
'menu_name' => '更新缓存',
'menu_key' => 'update_cache',
'menu_short_name' => '更新缓存',
'menu_type' => '1',
'icon' => 'nc-iconfont nc-icon-qingliV6xx',
'api_url' => 'sys/schema/clear',
'router_path' => 'tools/update_cache',
'view_path' => 'tools/updatecache',
'methods' => 'post',
'sort' => '98',
'status' => '1',
'is_show' => '1',
],
[ [
'menu_name' => '数据字典', 'menu_name' => '数据字典',
'menu_key' => 'sys_dict_dict_dict_list', 'menu_key' => 'sys_dict_dict_dict_list',
@ -3172,7 +3223,7 @@ return [
'router_path' => 'tools/list', 'router_path' => 'tools/list',
'view_path' => 'dict/list', 'view_path' => 'dict/list',
'methods' => 'get', 'methods' => 'get',
'sort' => '90', 'sort' => '106',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
'children' => [ 'children' => [
@ -3230,7 +3281,7 @@ return [
'router_path' => 'tools/detection', 'router_path' => 'tools/detection',
'view_path' => 'tools/detection', 'view_path' => 'tools/detection',
'methods' => '', 'methods' => '',
'sort' => '50', 'sort' => '105',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
], ],
@ -3244,7 +3295,7 @@ return [
'router_path' => 'tools/menu', 'router_path' => 'tools/menu',
'view_path' => 'auth/menu', 'view_path' => 'auth/menu',
'methods' => 'get', 'methods' => 'get',
'sort' => '48', 'sort' => '104',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
'children' => [ 'children' => [
@ -3316,7 +3367,7 @@ return [
'router_path' => 'tools/schedule', 'router_path' => 'tools/schedule',
'view_path' => 'tools/schedule', 'view_path' => 'tools/schedule',
'methods' => '', 'methods' => '',
'sort' => '40', 'sort' => '103',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
'children' => [ 'children' => [
@ -3388,7 +3439,7 @@ return [
'router_path' => 'tools/schedule_log', 'router_path' => 'tools/schedule_log',
'view_path' => 'tools/schedule_log', 'view_path' => 'tools/schedule_log',
'methods' => '', 'methods' => '',
'sort' => '40', 'sort' => '100',
'status' => '1', 'status' => '1',
'is_show' => '0' 'is_show' => '0'
], ],
@ -3402,24 +3453,10 @@ return [
'router_path' => 'tools/authorize', 'router_path' => 'tools/authorize',
'view_path' => 'app/authorize', 'view_path' => 'app/authorize',
'methods' => '', 'methods' => '',
'sort' => '30', 'sort' => '102',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
'children' => [ 'children' => [
[
'menu_name' => '系统升级',
'menu_key' => 'system_upgrade',
'menu_short_name' => '系统升级',
'menu_type' => '2',
'icon' => '',
'api_url' => 'upgrade',
'router_path' => '',
'view_path' => '',
'methods' => 'post',
'sort' => '100',
'status' => '1',
'is_show' => '1',
],
[ [
'menu_name' => '绑定授权信息', 'menu_name' => '绑定授权信息',
'menu_key' => 'bind_app_auth', 'menu_key' => 'bind_app_auth',
@ -3436,6 +3473,62 @@ return [
] ]
] ]
], ],
[
'menu_name' => '系统更新',
'menu_key' => 'system_upgrade',
'menu_short_name' => '系统更新',
'menu_type' => '1',
'icon' => 'iconfont iconxitonggengxin',
'api_url' => '',
'router_path' => 'tools/upgrade',
'view_path' => 'app/upgrade',
'methods' => '',
'sort' => '101',
'status' => '1',
'is_show' => '1',
],
[
'menu_name' => '升级记录',
'menu_key' => 'upgrade_records',
'menu_short_name' => '升级记录',
'menu_type' => '1',
'icon' => 'iconfont iconshengjijilu',
'api_url' => 'upgrade/records',
'router_path' => 'tools/upgrade_records',
'view_path' => 'tools/upgrade_records',
'methods' => 'post',
'sort' => '100',
'status' => '1',
'is_show' => '1',
],
[
'menu_name' => '备份记录',
'menu_key' => 'backup_records',
'menu_short_name' => '备份记录',
'menu_type' => '1',
'icon' => 'iconfont iconbeifenjiluV6xx',
'api_url' => 'backup/records',
'router_path' => 'tools/backup_records',
'view_path' => 'tools/backup_records',
'methods' => 'post',
'sort' => '99',
'status' => '1',
'is_show' => '1',
],
[
'menu_name' => '云编译',
'menu_key' => 'cloud_compile',
'menu_short_name' => '云编译',
'menu_type' => '1',
'icon' => 'iconfont iconyun2',
'api_url' => '',
'router_path' => 'tools/cloud_compile',
'view_path' => 'tools/cloud_compile',
'methods' => 'post',
'sort' => '98',
'status' => '1',
'is_show' => '1',
],
[ [
'menu_name' => '开发者key', 'menu_name' => '开发者key',
'menu_key' => 'developer_token', 'menu_key' => 'developer_token',
@ -3446,7 +3539,7 @@ return [
'router_path' => 'tools/developer_token', 'router_path' => 'tools/developer_token',
'view_path' => 'setting/developer_token', 'view_path' => 'setting/developer_token',
'methods' => 'get', 'methods' => 'get',
'sort' => '20', 'sort' => '97',
'status' => '1', 'status' => '1',
'is_show' => '1', 'is_show' => '1',
'children' => [ 'children' => [

View File

@ -12,6 +12,19 @@ return [
'class' => '', 'class' => '',
'function' => '' 'function' => ''
], ],
[
'key' => 'auto_clear_schedule_log',
'name' => '定时清理计划任务日志表',
'desc' => '',
'time' => [
'type' => 'day',
'day' => 1,
'hour' => 1,
'min' => 1
],
'class' => 'app\job\schedule\AutoClearScheduleLog',
'function' => ''
],
[ [
'key' => 'transfer_check_finish', 'key' => 'transfer_check_finish',
'name' => '检验在线转账是否处理完毕', 'name' => '检验在线转账是否处理完毕',
@ -22,5 +35,18 @@ return [
], ],
'class' => 'app\job\transfer\schedule\CheckFinish', 'class' => 'app\job\transfer\schedule\CheckFinish',
'function' => '' 'function' => ''
] ],
[
'key' => 'auto_clear_upgrade_records',
'name' => '定时清理升级/备份记录表',
'desc' => '',
'time' => [
'type' => 'day',
'day' => 1,
'hour' => 1,
'min' => 1
],
'class' => 'app\job\upgrade\AutoClearUpgradeRecords',
'function' => ''
],
]; ];

View File

@ -0,0 +1,34 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\dict\sys;
/**
* 备份记录字典
*/
class BackupDict
{
const STATUS_READY = 'ready'; //准备执行
const STATUS_COMPLETE = 'complete'; // 完成
const STATUS_FAIL = 'fail'; // 失败
public static function getStatus($status)
{
$status_list = [
self::STATUS_READY => get_lang('dict_backup.ready'),
self::STATUS_COMPLETE => get_lang('dict_backup.complete'),
self::STATUS_FAIL => get_lang('dict_backup.fail'),
];
return $status_list[ $status ] ?? '';
}
}

View File

@ -28,7 +28,9 @@ class CloudDict
const APPLET_AUDIT_FAIL = -2; const APPLET_AUDIT_FAIL = -2;
public static function getAppletUploadSatus($status) { const APPLET_AUDIT_UNDO = -3;
public static function getAppletUploadStatus($status) {
$status_list = [ $status_list = [
self::APPLET_UPLOADING => get_lang('dict_cloud_applet.uploading'), self::APPLET_UPLOADING => get_lang('dict_cloud_applet.uploading'),
self::APPLET_UPLOAD_SUCCESS => get_lang('dict_cloud_applet.upload_success'), self::APPLET_UPLOAD_SUCCESS => get_lang('dict_cloud_applet.upload_success'),
@ -36,6 +38,7 @@ class CloudDict
self::APPLET_AUDITING => get_lang('dict_cloud_applet.auditing'), self::APPLET_AUDITING => get_lang('dict_cloud_applet.auditing'),
self::APPLET_AUDIT_FAIL => get_lang('dict_cloud_applet.audit_fail'), self::APPLET_AUDIT_FAIL => get_lang('dict_cloud_applet.audit_fail'),
self::APPLET_PUBLISHED => get_lang('dict_cloud_applet.published'), self::APPLET_PUBLISHED => get_lang('dict_cloud_applet.published'),
self::APPLET_AUDIT_UNDO => get_lang('dict_cloud_applet.undo')
]; ];
return $status_list[$status] ?? ''; return $status_list[$status] ?? '';
} }

View File

@ -0,0 +1,40 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\dict\sys;
/**
* 升级记录字典
* Class UpgradeRecordsDict
* @package app\dict\sys
*
*/
class UpgradeDict
{
const STATUS_READY = 'ready'; //准备执行
const STATUS_COMPLETE = 'complete'; // 完成
const STATUS_FAIL = 'fail'; // 失败
const STATUS_CANCEL = 'cancel';
public static function getStatus($status)
{
$status_list = [
self::STATUS_READY => get_lang('dict_upgrade.ready'),
self::STATUS_COMPLETE => get_lang('dict_upgrade.complete'),
self::STATUS_FAIL => get_lang('dict_upgrade.fail'),
self::STATUS_CANCEL => get_lang('dict_upgrade.cancel'),
];
return $status_list[ $status ] ?? '';
}
}

View File

@ -153,7 +153,7 @@ CREATE TABLE `diy_form_submit_config` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id', `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`form_id` INT(11) NOT NULL DEFAULT 0 COMMENT '所属万能表单id', `form_id` INT(11) NOT NULL DEFAULT 0 COMMENT '所属万能表单id',
`submit_after_action` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '填表人提交后操作text文字信息voucher核销凭证', `submit_after_action` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '填表人提交后操作text文字信息voucher核销凭证',
`tips_type` VARCHAR(255) NOT NULL COMMENT '提示内容类型default默认提示diy自定义提示', `tips_type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '提示内容类型default默认提示diy自定义提示',
`tips_text` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '自定义提示内容', `tips_text` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '自定义提示内容',
`time_limit_type` VARCHAR(255) NOT NULL DEFAULT '0' COMMENT '核销凭证有效期限制类型no_limit不限制specify_time指定固定开始结束时间submission_time按提交时间设置有效期', `time_limit_type` VARCHAR(255) NOT NULL DEFAULT '0' COMMENT '核销凭证有效期限制类型no_limit不限制specify_time指定固定开始结束时间submission_time按提交时间设置有效期',
`time_limit_rule` TEXT DEFAULT NULL COMMENT '核销凭证时间限制规则json格式', `time_limit_rule` TEXT DEFAULT NULL COMMENT '核销凭证时间限制规则json格式',
@ -289,7 +289,7 @@ CREATE TABLE `generate_table` (
DROP TABLE IF EXISTS `jobs`; DROP TABLE IF EXISTS `jobs`;
CREATE TABLE `jobs` ( CREATE TABLE `jobs` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`queue` varchar(255) NOT NULL, `queue` varchar(255) NOT NULL DEFAULT '',
`payload` longtext NOT NULL, `payload` longtext NOT NULL,
`attempts` tinyint(4) UNSIGNED NOT NULL DEFAULT 0, `attempts` tinyint(4) UNSIGNED NOT NULL DEFAULT 0,
`reserve_time` int(11) UNSIGNED NULL DEFAULT 0, `reserve_time` int(11) UNSIGNED NULL DEFAULT 0,
@ -504,7 +504,7 @@ CREATE TABLE `pay` (
`trade_id` int(11) NOT NULL DEFAULT 0 COMMENT '业务id', `trade_id` int(11) NOT NULL DEFAULT 0 COMMENT '业务id',
`trade_no` varchar(255) NOT NULL DEFAULT '' COMMENT '交易单号', `trade_no` varchar(255) NOT NULL DEFAULT '' COMMENT '交易单号',
`body` varchar(1000) NOT NULL DEFAULT '' COMMENT '支付主体', `body` varchar(1000) NOT NULL DEFAULT '' COMMENT '支付主体',
`money` decimal(10, 2) NOT NULL COMMENT '支付金额', `money` decimal(10, 2) NOT NULL DEFAULT 0.00 COMMENT '支付金额',
`voucher` varchar(255) NOT NULL DEFAULT '' COMMENT '支付票据', `voucher` varchar(255) NOT NULL DEFAULT '' COMMENT '支付票据',
`status` int(11) NOT NULL DEFAULT 0 COMMENT '支付状态0.待支付 1. 支付中 2. 已支付 -1已取消', `status` int(11) NOT NULL DEFAULT 0 COMMENT '支付状态0.待支付 1. 支付中 2. 已支付 -1已取消',
`json` varchar(255) NOT NULL DEFAULT '' COMMENT '支付扩展用支付信息', `json` varchar(255) NOT NULL DEFAULT '' COMMENT '支付扩展用支付信息',
@ -700,6 +700,21 @@ CREATE TABLE `sys_attachment_category` (
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '附件分类表' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '附件分类表' ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `sys_backup_records`;
CREATE TABLE `sys_backup_records` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键id',
`version` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备份版本号',
`backup_key` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备份标识',
`content` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备份内容',
`status` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '状态',
`fail_reason` LONGTEXT DEFAULT NULL COMMENT '失败原因',
`remark` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '备注',
`create_time` INT NOT NULL DEFAULT 0 COMMENT '创建时间',
`complete_time` INT NOT NULL DEFAULT 0 COMMENT '完成时间',
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '备份记录表' ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `sys_config`; DROP TABLE IF EXISTS `sys_config`;
CREATE TABLE `sys_config` ( CREATE TABLE `sys_config` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
@ -966,6 +981,22 @@ CREATE TABLE `sys_schedule_log` (
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '计划任务执行记录' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '计划任务执行记录' ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `sys_upgrade_records`;
CREATE TABLE `sys_upgrade_records` (
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键id',
`upgrade_key` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '升级标识',
`app_key` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '插件标识',
`name` LONGTEXT DEFAULT NULL COMMENT '升级名称',
`content` TEXT DEFAULT NULL COMMENT '升级内容',
`prev_version` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '前一版本',
`current_version` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '当前版本',
`status` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '状态',
`fail_reason` LONGTEXT DEFAULT NULL COMMENT '失败原因',
`create_time` INT NOT NULL DEFAULT 0 COMMENT '创建时间',
`complete_time` INT NOT NULL DEFAULT 0 COMMENT '完成时间',
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '升级记录表' ROW_FORMAT = Dynamic;
DROP TABLE IF EXISTS `sys_user`; DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` ( CREATE TABLE `sys_user` (
`uid` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '系统用户ID', `uid` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '系统用户ID',
@ -974,13 +1005,13 @@ CREATE TABLE `sys_user` (
`password` varchar(100) NOT NULL DEFAULT '' COMMENT '用户密码', `password` varchar(100) NOT NULL DEFAULT '' COMMENT '用户密码',
`real_name` varchar(16) NOT NULL DEFAULT '' COMMENT '实际姓名', `real_name` varchar(16) NOT NULL DEFAULT '' COMMENT '实际姓名',
`last_ip` varchar(50) NOT NULL DEFAULT '' COMMENT '最后一次登录ip', `last_ip` varchar(50) NOT NULL DEFAULT '' COMMENT '最后一次登录ip',
`last_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后一次登录时间', `last_time` int(10) NOT NULL DEFAULT 0 COMMENT '最后一次登录时间',
`create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '添加时间', `create_time` int(10) NOT NULL DEFAULT 0 COMMENT '添加时间',
`login_count` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '登录次数', `login_count` int(10) NOT NULL DEFAULT 0 COMMENT '登录次数',
`is_del` tinyint(3) UNSIGNED NOT NULL DEFAULT 0, `is_del` tinyint(3) NOT NULL DEFAULT 0,
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间', `delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间', `update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
`status` tinyint(3) UNSIGNED NOT NULL DEFAULT 1 COMMENT '后台管理员状态 1有效0无效', `status` tinyint(3) NOT NULL DEFAULT 1 COMMENT '后台管理员状态 1有效0无效',
`role_ids` varchar(255) NOT NULL DEFAULT '' COMMENT '权限组', `role_ids` varchar(255) NOT NULL DEFAULT '' COMMENT '权限组',
`is_admin` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否是管理员', `is_admin` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否是管理员',
PRIMARY KEY (`uid`) USING BTREE, PRIMARY KEY (`uid`) USING BTREE,
@ -1045,9 +1076,9 @@ CREATE TABLE `web_adv` (
DROP TABLE IF EXISTS `web_friendly_link`; DROP TABLE IF EXISTS `web_friendly_link`;
CREATE TABLE `web_friendly_link` ( CREATE TABLE `web_friendly_link` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '索引id', `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '索引id',
`link_title` VARCHAR(100) NOT NULL COMMENT '标题', `link_title` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '标题',
`link_url` VARCHAR(100) NOT NULL COMMENT '链接', `link_url` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '链接',
`link_pic` VARCHAR(100) NOT NULL COMMENT '图片', `link_pic` VARCHAR(100) NOT NULL DEFAULT '' COMMENT '图片',
`sort` INT(11) NOT NULL DEFAULT 0 COMMENT '排序号', `sort` INT(11) NOT NULL DEFAULT 0 COMMENT '排序号',
`is_show` INT(11) NOT NULL DEFAULT 1 COMMENT '是否显示 1.是 2.否', `is_show` INT(11) NOT NULL DEFAULT 1 COMMENT '是否显示 1.是 2.否',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)

View File

@ -0,0 +1,47 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\schedule;
use app\model\sys\SysScheduleLog;
use core\base\BaseJob;
use think\facade\Log;
/**
* 队列异步调用定时任务
*/
class AutoClearScheduleLog extends BaseJob
{
/****执行成功的数据记录留存时间***/
const SUCCESS_SAVE_DAY = 3;
/***执行失败的数据记录留存时间***/
const ERROR_SAVE_DAY = 7;
public function doJob()
{
Log::write('AutoClearScheduleLog 定时清除schedule_log数据' . date('Y-m-d h:i:s'));
try {
( new SysScheduleLog() )->where([
[ 'execute_time', '<', time() - self::SUCCESS_SAVE_DAY * 86400 ],
[ 'status', '=', 'success' ],
])->delete();
( new SysScheduleLog() )->where([
[ 'execute_time', '<', time() - self::ERROR_SAVE_DAY * 86400 ],
[ 'status', '=', 'error' ],
])->delete();
return true;
} catch (\Exception $e) {
Log::write('AutoClearScheduleLog 定时清除schedule_log数据失败' . date('Y-m-d h:i:s') . $e->getMessage() . $e->getFile() . $e->getLine());
return false;
}
}
}

View File

@ -0,0 +1,54 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\upgrade;
use app\dict\sys\BackupDict;
use app\dict\sys\UpgradeDict;
use app\model\sys\SysUpgradeRecords;
use app\service\admin\upgrade\BackupRecordsService;
use core\base\BaseJob;
use think\facade\Log;
/**
* 队列异步调用定时任务
*/
class AutoClearUpgradeRecords extends BaseJob
{
const DAY = 7; // 清除7天前的数据
public function doJob()
{
Log::write('AutoClearUpgradeRecords 定时清除升级记录、备份记录数据' . date('Y-m-d h:i:s'));
try {
// 清除7天前的升级记录数据
( new SysUpgradeRecords() )->where([
[ 'create_time', '<', time() - self::DAY * 86400 ],
[ 'status', 'in', [ UpgradeDict::STATUS_READY, UpgradeDict::STATUS_FAIL ] ]
])->delete();
// 清除7天前的备份记录数据
$backup_records_service = new BackupRecordsService();
$backup_records = $backup_records_service->getList([
[ 'create_time', '<', time() - self::DAY * 86400 ],
[ 'status', 'in', [ BackupDict::STATUS_READY, BackupDict::STATUS_FAIL ] ]
], 'id');
$backup_records_service->del(array_column($backup_records, 'id'));
return true;
} catch (\Exception $e) {
Log::write('AutoClearScheduleLog 定时清除升级记录、备份记录数据失败' . date('Y-m-d h:i:s') . $e->getMessage() . $e->getFile() . $e->getLine());
return false;
}
}
}

View File

@ -0,0 +1,34 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\wxoplatform;
use app\service\admin\wxoplatform\WeappVersionService;
use core\base\BaseJob;
/**
* 队列异步调用支付定时未支付恢复
*/
class GetVersionUploadResult extends BaseJob
{
/**
* 消费
* @param $data
* @return true
*/
protected function doJob($task_key, $is_all)
{
WeappVersionService::getVersionUploadResult($task_key, $is_all);
return true;
}
}

View File

@ -0,0 +1,34 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\wxoplatform;
use app\service\admin\wxoplatform\WeappVersionService;
use core\base\BaseJob;
/**
* 队列异步调用支付定时未支付恢复
*/
class VersionUploadSuccess extends BaseJob
{
/**
* 消费
* @param $data
* @return true
*/
protected function doJob($task_key, $is_all)
{
WeappVersionService::uploadSuccess($task_key, $is_all);
return true;
}
}

View File

@ -36,19 +36,6 @@ return [
'real_name_require' => 'real_name is require', 'real_name_require' => 'real_name is require',
'password_require' => 'password is require', 'password_require' => 'password is require',
], ],
//站点
'validate_site' => [
'site_name_require' => 'site_name is require',
'site_name_max' => 'site_name is not exceed 120 points',
'keywords_require' => 'keywords is require',
'keywords_max' => 'site_name is not exceed 30 points',
'group_id_require' => 'group_id is require',
'group_id_number' => 'group_id must be a number',
'expire_time_number' => 'expire_time must be a number',
'group_name_require' => 'group_name is require',
'group_name_max' => 'group_name is not exceed 120 points',
'group_roles_require' => 'group_roles is require'
],
//附件 //附件
'validate_attachment' => [ 'validate_attachment' => [
'name_require' => 'name is require', 'name_require' => 'name is require',

View File

@ -37,6 +37,7 @@ return [
'SERVER_CROSS_REQUEST_FAIL' => '服务器跨域请求异常', 'SERVER_CROSS_REQUEST_FAIL' => '服务器跨域请求异常',
'ADDON_INSTALL_NOT_EXIST' => '未找到插件安装任务', 'ADDON_INSTALL_NOT_EXIST' => '未找到插件安装任务',
'ADDON_INSTALL_EXECUTED' => '插件安装任务已执行', 'ADDON_INSTALL_EXECUTED' => '插件安装任务已执行',
'ADDON_INSTALLING' => '插件安装中',
'INSTALL_CHECK_NOT_PASS' => '安装校验未通过', 'INSTALL_CHECK_NOT_PASS' => '安装校验未通过',
'ADDON_SQL_FAIL' => '插件sql执行失败', 'ADDON_SQL_FAIL' => '插件sql执行失败',
'ADDON_DIR_FAIL' => '插件文件操作失败', 'ADDON_DIR_FAIL' => '插件文件操作失败',
@ -56,6 +57,10 @@ return [
'ADDON_ZIP_ERROR' => '插件压缩失败', 'ADDON_ZIP_ERROR' => '插件压缩失败',
'PHP_SCRIPT_RUNNING_OUT_OF_MEMORY' => 'PHP脚本运行内存不足, 具体操作方法<a style="text-decoration: underline;" href="https://www.kancloud.cn/niushop/niushop_v6/3248604" target="blank">点击查看相关手册</a>', 'PHP_SCRIPT_RUNNING_OUT_OF_MEMORY' => 'PHP脚本运行内存不足, 具体操作方法<a style="text-decoration: underline;" href="https://www.kancloud.cn/niushop/niushop_v6/3248604" target="blank">点击查看相关手册</a>',
'BEFORE_UPGRADING_NEED_UPGRADE_FRAMEWORK' => '升级插件前需要先升级框架', 'BEFORE_UPGRADING_NEED_UPGRADE_FRAMEWORK' => '升级插件前需要先升级框架',
'UPGRADE_RECORD_NOT_EXIST' => '升级记录不存在',
'UPGRADE_BACKUP_CODE_NOT_FOUND' => '未找到备份的源码文件',
'UPGRADE_BACKUP_SQL_NOT_FOUND' => '未找到备份的数据库文件',
'NOT_EXIST_UPGRADE_CONTENT' => '没有获取到可以升级的内容',
//登录注册重置账号.... //登录注册重置账号....
'LOGIN_SUCCESS' => '登录成功', 'LOGIN_SUCCESS' => '登录成功',
@ -289,6 +294,8 @@ return [
'VERIFY_TYPE_ERROR' => '核销类型错误', 'VERIFY_TYPE_ERROR' => '核销类型错误',
'VERIFY_CODE_EXPIRED' => '当前核销码已核销或已失效', 'VERIFY_CODE_EXPIRED' => '当前核销码已核销或已失效',
'VERIFIER_NOT_EXIST' => '核销员不存在', 'VERIFIER_NOT_EXIST' => '核销员不存在',
'VERIFIER_EXIST'=>'核销员已存在',
'VERIFIER_NOT_AUTH' => '该核销员没有权限',
//签到相关 //签到相关
'SIGN_NOT_USE' => '签到未开启', 'SIGN_NOT_USE' => '签到未开启',
@ -312,7 +319,5 @@ return [
'DIRECTORY' => '目录', 'DIRECTORY' => '目录',
'WAS_NOT_CREATED' => '创建失败', 'WAS_NOT_CREATED' => '创建失败',
/********************************************************* 微信开放平台 **************************************/
'PRINTER_NOT_EXIST' => '打印机不存在' 'PRINTER_NOT_EXIST' => '打印机不存在'
]; ];

View File

@ -376,7 +376,6 @@ return [
'oct' => '10月', 'oct' => '10月',
'nov' => '11月', 'nov' => '11月',
'dec' => '12月', 'dec' => '12月',
], ],
'dict_site_layout' => [ 'dict_site_layout' => [
'default' => '默认' 'default' => '默认'
@ -387,7 +386,8 @@ return [
'upload_fail' => '上传失败', 'upload_fail' => '上传失败',
'auditing' => '审核中', 'auditing' => '审核中',
'audit_success' => '审核通过', 'audit_success' => '审核通过',
'audit_fail' => '审核失败' 'audit_fail' => '审核失败',
'published' => '已发布'
], ],
'dict_wechat_media' => [ 'dict_wechat_media' => [
'type_image' => '图片', 'type_image' => '图片',
@ -414,5 +414,16 @@ return [
// 打印机品牌 // 打印机品牌
'dict_printer' => [ 'dict_printer' => [
'yilianyun' => '易联云打印机' 'yilianyun' => '易联云打印机'
],
'dict_upgrade' => [
'ready' => '升级中',
'complete' => '完成',
'fail' => '失败',
'cancel' => '已取消'
],
'dict_backup' => [
'ready' => '准备执行',
'complete' => '完成',
'fail' => '失败'
] ]
]; ];

View File

@ -36,22 +36,6 @@ return [
'real_name_require' => '实际姓名必须填写', 'real_name_require' => '实际姓名必须填写',
'password_require' => '账号密码必须填写', 'password_require' => '账号密码必须填写',
], ],
//站点
'validate_site' => [
'site_name_require' => '网站名称必须填写',
'site_name_max' => '网站名称最多不能超过20个字符',
'keywords_require' => '关键字必须填写',
'keywords_max' => '关键字最多不能超过30个字符',
'group_id_require' => '站点分组必须填写',
'group_id_number' => '站点分组必须是整数',
'expire_time_number' => '到期时间必须是时间戳',
'group_name_require' => '站点分组名称必须填写',
'group_name_max' => '站点分组名称不能超过20字符',
'app_require' => '套餐主应用必须选择',
'front_end_name_require' => '前台名称必须填写',
'front_end_name_max' => '前台名称最多不能超过20个字符',
'site_domain_cannot_repeated' => '站点域名不能重复'
],
//附件 //附件
'validate_attachment' => [ 'validate_attachment' => [
'name_require' => '附件组名称必须填写', 'name_require' => '附件组名称必须填写',

View File

@ -37,13 +37,20 @@ class ShowAppListener
'key' => 'diy_form', 'key' => 'diy_form',
'url' => '/diy_form/list', 'url' => '/diy_form/list',
], ],
// [ [
// 'title' => '万能a表单', 'title' => '小票打印',
// 'desc' => '万能a表单', 'desc' => '支持打印机添加,便捷创建小票打印模板',
// 'icon' => 'static/resource/images/diy_form/icon.png', 'icon' => 'static/resource/images/tool/printer_icon.png',
// 'key' => 'diy_faorm', 'key' => 'printer_management',
// 'url' => '/diy_faorm/list', 'url' => '/printer/list',
// ] ],
[
'title' => '数据导出',
'desc' => '展示导出文件,支持删除与下载',
'icon' => 'static/resource/images/tool/export_icon.png',
'key' => 'setting_export',
'url' => '/setting/export',
],
], ],
// 营销 // 营销
'promotion' => [ 'promotion' => [

View File

@ -202,9 +202,16 @@ class Member extends BaseModel
*/ */
public function searchMemberLabelAttr(Query $query, $value, $data) public function searchMemberLabelAttr(Query $query, $value, $data)
{ {
if ($value) { if ($value) {
$query->whereLike('member_label', '%"' . $value . '"%'); if (is_array($value)) {
$temp_where = array_map(function($item) { return '%"' . $item . '"%'; }, $value);
} else {
$temp_where = [ '%"' . $value . '"%' ];
}
$query->where('member_label', 'like', $temp_where, 'or');
} }
} }
/** /**
@ -268,4 +275,5 @@ class Member extends BaseModel
{ {
return $this->hasOne(MemberLevel::class, 'level_id', 'member_level')->bind([ 'member_level_name' => 'level_name' ]); return $this->hasOne(MemberLevel::class, 'level_id', 'member_level')->bind([ 'member_level_name' => 'level_name' ]);
} }
} }

View File

@ -0,0 +1,112 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\model\sys;
use app\dict\sys\UpgradeDict;
use core\base\BaseModel;
/**
* 备份记录表模型
*/
class SysBackupRecords extends BaseModel
{
/**
* 数据表主键
* @var string
*
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'sys_backup_records';
protected $type = [
'create_time' => 'timestamp',
'complete_time' => 'timestamp'
];
// 设置json类型字段
protected $json = [ 'fail_reason' ];
// 设置JSON数据返回数组
protected $jsonAssoc = true;
/**
* 状态字段转化
* @param $value
* @param $data
* @return mixed
*/
public function getStatusNameAttr($value, $data)
{
if (empty($data[ 'status' ])) return '';
return UpgradeDict::getStatus($data[ 'status' ]);
}
/**
* 备份目录
* @param $value
* @param $data
* @return string
*/
public function getBackupDirAttr($value, $data)
{
if (empty($data[ 'backup_key' ])) return '';
return 'upgrade' . DIRECTORY_SEPARATOR . $data[ 'backup_key' ];
}
/**
* 备份源码目录
* @param $value
* @param $data
* @return string
*/
public function getBackupCodeDirAttr($value, $data)
{
if (empty($data[ 'backup_key' ])) return '';
$root_path = dirname(root_path()) . DIRECTORY_SEPARATOR;
$upgrade_dir = $root_path . 'upgrade' . DIRECTORY_SEPARATOR;
return $upgrade_dir . $data[ 'backup_key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
}
/**
* 备份数据库目录
* @param $value
* @param $data
* @return string
*/
public function getBackupSqlDirAttr($value, $data)
{
if (empty($data[ 'backup_key' ])) return '';
$root_path = dirname(root_path()) . DIRECTORY_SEPARATOR;
$upgrade_dir = $root_path . 'upgrade' . DIRECTORY_SEPARATOR;
return $upgrade_dir . $data[ 'backup_key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
}
/**
* 搜索器:备份内容
* @param $query
* @param $value
* @param $data
*/
public function searchContentAttr($query, $value, $data)
{
if ($value != '') {
$query->where("content", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
}
}
}

View File

@ -0,0 +1,130 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\model\sys;
use app\dict\sys\UpgradeDict;
use core\base\BaseModel;
/**
* 升级记录表模型
*/
class SysUpgradeRecords extends BaseModel
{
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'sys_upgrade_records';
protected $type = [
'create_time' => 'timestamp',
'complete_time' => 'timestamp'
];
// 设置json类型字段
protected $json = [ 'fail_reason' ];
// 设置JSON数据返回数组
protected $jsonAssoc = true;
/**
* 状态字段转化
* @param $value
* @param $data
* @return mixed
*/
public function getStatusNameAttr($value, $data)
{
if (empty($data[ 'status' ])) return '';
return UpgradeDict::getStatus($data[ 'status' ]);
}
/**
* 备份目录
* @param $value
* @param $data
* @return string
*/
public function getBackupDirAttr($value, $data)
{
if (empty($data[ 'upgrade_key' ])) return '';
return 'upgrade' . DIRECTORY_SEPARATOR . $data[ 'upgrade_key' ];
}
/**
* 备份源码目录
* @param $value
* @param $data
* @return string
*/
public function getBackupCodeDirAttr($value, $data)
{
if (empty($data[ 'upgrade_key' ])) return '';
$root_path = dirname(root_path()) . DIRECTORY_SEPARATOR;
$upgrade_dir = $root_path . 'upgrade' . DIRECTORY_SEPARATOR;
return $upgrade_dir . $data[ 'upgrade_key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
}
/**
* 备份数据库目录
* @param $value
* @param $data
* @return string
*/
public function getBackupSqlDirAttr($value, $data)
{
if (empty($data[ 'upgrade_key' ])) return '';
$root_path = dirname(root_path()) . DIRECTORY_SEPARATOR;
$upgrade_dir = $root_path . 'upgrade' . DIRECTORY_SEPARATOR;
return $upgrade_dir . $data[ 'upgrade_key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
}
/**
* 搜索器:升级名称
* @param $query
* @param $value
* @param $data
*/
public function searchNameAttr($query, $value, $data)
{
if ($value != '') {
$query->where("name", 'like', '%' . $this->handelSpecialCharacter($value) . '%');
}
}
/**
* 关联备份记录
* @return \think\model\relation\HasOne
*/
public function backupRecord()
{
return $this->hasOne(SysBackupRecords::class, 'backup_key', 'upgrade_key');
}
public function getContentAttr($value) {
if (!empty($value)) {
try {
return json_decode($value, true);
} catch (\Exception $e) {
}
}
return $value;
}
}

View File

@ -18,8 +18,6 @@ use think\db\Query;
/** /**
* 核销记录模型 * 核销记录模型
* Class Poster
* @package app\model\verify
*/ */
class Verify extends BaseModel class Verify extends BaseModel
{ {
@ -37,12 +35,13 @@ class Verify extends BaseModel
protected $name = 'verify'; protected $name = 'verify';
// 设置json类型字段 // 设置json类型字段
protected $json = [ 'data' , 'value']; protected $json = [ 'data', 'value' ];
// 设置JSON数据返回数组 // 设置JSON数据返回数组
protected $jsonAssoc = true; protected $jsonAssoc = true;
public function member() { public function member()
{
return $this->hasOne(Member::class, 'member_id', 'verifier_member_id'); return $this->hasOne(Member::class, 'member_id', 'verifier_member_id');
} }
@ -85,6 +84,7 @@ class Verify extends BaseModel
$query->where('relate_tag', '=', $value); $query->where('relate_tag', '=', $value);
} }
} }
/** /**
* 核销员 * 核销员
* @param $query * @param $query
@ -120,14 +120,14 @@ class Verify extends BaseModel
*/ */
public function searchCreateTimeAttr(Query $query, $value, $data) public function searchCreateTimeAttr(Query $query, $value, $data)
{ {
$start_time = empty($value[0]) ? 0 : strtotime($value[0]); $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]);
$end_time = empty($value[1]) ? 0 : strtotime($value[1]); $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]);
if ($start_time > 0 && $end_time > 0) { if ($start_time > 0 && $end_time > 0) {
$query->whereBetweenTime('create_time', $start_time, $end_time); $query->whereBetweenTime('create_time', $start_time, $end_time);
} else if ($start_time > 0 && $end_time == 0) { } else if ($start_time > 0 && $end_time == 0) {
$query->where([['create_time', '>=', $start_time]]); $query->where([ [ 'create_time', '>=', $start_time ] ]);
} else if ($start_time == 0 && $end_time > 0) { } else if ($start_time == 0 && $end_time > 0) {
$query->where([['create_time', '<=', $end_time]]); $query->where([ [ 'create_time', '<=', $end_time ] ]);
} }
} }
@ -136,10 +136,11 @@ class Verify extends BaseModel
* @param $value * @param $value
* @return void * @return void
*/ */
public function getTypeNameAttr($value, $data) { public function getTypeNameAttr($value, $data)
if (empty($data['type'])) {
if (empty($data[ 'type' ]))
return ''; return '';
return VerifyDict::getType()[$data['type']]['name'] ?? ''; return VerifyDict::getType()[ $data[ 'type' ] ][ 'name' ] ?? '';
} }
} }

View File

@ -35,6 +35,6 @@ class WeappVersion extends BaseModel
protected $name = 'weapp_version'; protected $name = 'weapp_version';
public function getStatusNameAttr($value, $data) { public function getStatusNameAttr($value, $data) {
if (isset($data['status'])) return CloudDict::getAppletUploadSatus($data['status']); if (isset($data['status'])) return CloudDict::getAppletUploadStatus($data['status']);
} }
} }

View File

@ -623,39 +623,6 @@ class DiyFormService extends BaseAdminService
return ( new DiyFormFields() )->where([ [ 'field_id', '>', 0 ] ])->withSearch([ 'form_id' ], $where)->field($field)->order($order)->select()->toArray(); return ( new DiyFormFields() )->where([ [ 'field_id', '>', 0 ] ])->withSearch([ 'form_id' ], $where)->field($field)->order($order)->select()->toArray();
} }
/**
* 获取万能表单微信小程序二维码
* @param $form_id
* @return array
*/
public function getQrcode($form_id)
{
if (empty($form_id)) {
throw new AdminException('缺少参考form_id');
}
$page = 'app/pages/index/diy_form';
$data = [
[
'key' => 'form_id',
'value' => $form_id
],
];
$dir = 'upload/diy_form_qrcode';
$path = '';
try {
$path = qrcode('', $page, $data, $dir, 'weapp');
} catch (\Exception $e) {
Log::write('万能表单微信小程序二维码生成error' . $e->getMessage() . $e->getFile() . $e->getLine());
}
return [
'path' => $path
];
}
/** /**
* 检测表单名称唯一性 * 检测表单名称唯一性
* @param array $data * @param array $data

View File

@ -1,5 +1,5 @@
<el-form-item :label="t('{LCASE_COLUMN_NAME}')" prop="{COLUMN_NAME}"> <el-form-item :label="t('{LCASE_COLUMN_NAME}')" prop="{COLUMN_NAME}">
<el-select class="" v-model="{LCASE_CLASS_NAME}Table.searchParam.{COLUMN_NAME}" clearable :placeholder="t('{LCASE_COLUMN_NAME}Placeholder')"> <el-select v-model="{LCASE_CLASS_NAME}Table.searchParam.{COLUMN_NAME}" clearable :placeholder="t('{LCASE_COLUMN_NAME}Placeholder')">
<el-option label="全部" value=""></el-option> <el-option label="全部" value=""></el-option>
</el-select> </el-select>

View File

@ -44,11 +44,11 @@ class MemberService extends BaseAdminService
public function getPage(array $where = []) public function getPage(array $where = [])
{ {
$field = 'member_id, member_no, username, mobile, password, register_channel, register_type, nickname, headimg, member_level, member_label, wx_openid, weapp_openid, wx_unionid, ali_openid, douyin_openid, login_ip, login_type, login_channel, login_count, login_time, create_time, last_visit_time, last_consum_time, sex, status, birthday, point, point_get, balance, balance_get, growth, growth_get, is_member, member_time, is_del, province_id, city_id, district_id, address, location, delete_time, money, money_get, commission, commission_get, commission_cash_outing'; $field = 'member_id, member_no, username, mobile, password, register_channel, register_type, nickname, headimg, member_level, member_label, wx_openid, weapp_openid, wx_unionid, ali_openid, douyin_openid, login_ip, login_type, login_channel, login_count, login_time, create_time, last_visit_time, last_consum_time, sex, status, birthday, point, point_get, balance, balance_get, growth, growth_get, is_member, member_time, is_del, province_id, city_id, district_id, address, location, delete_time, money, money_get, commission, commission_get, commission_cash_outing';
$search_model = $this->model->withSearch(['keyword','register_type', 'create_time', 'is_del', 'member_label', 'register_channel','member_level'],$where) $search_model = $this->model->withSearch([ 'keyword', 'register_type', 'create_time', 'is_del', 'member_label', 'register_channel', 'member_level' ], $where)
->field($field) ->field($field)
->order('member_id desc') ->order('member_id desc')
->with('member_level_name_bind') ->with('member_level_name_bind')
->append(['register_channel_name', 'register_type_name', 'sex_name', 'login_channel_name', 'login_type_name', 'status_name']); ->append([ 'register_channel_name', 'register_type_name', 'sex_name', 'login_channel_name', 'login_type_name', 'status_name' ]);
return $this->pageQuery($search_model, function ($item, $key) { return $this->pageQuery($search_model, function ($item, $key) {
$item = $this->makeUp($item); $item = $this->makeUp($item);
}); });
@ -65,8 +65,13 @@ class MemberService extends BaseAdminService
public function getList(array $where = []) public function getList(array $where = [])
{ {
$field = 'member_id, nickname, headimg'; $field = 'member_id, nickname, headimg';
return $this->model->withSearch(['keyword'],$where)->field($field)->order('member_id desc')->limit($this->getPageParam()['limit'] ?? 0)->select()->toArray(); $temp_where[] = [];
if (!empty($where[ 'member_ids' ])) {
$temp_where[] = [ 'member_id', 'in', implode(',', $where[ 'member_ids' ]) ];
}
return $this->model->where($temp_where)->withSearch([ 'keyword' ], $where)->field($field)->order('member_id desc')->limit($this->getPageParam()[ 'limit' ] ?? 0)->select()->toArray();
} }
/** /**
* 会员详情 * 会员详情
* @param int $member_id * @param int $member_id
@ -75,7 +80,7 @@ class MemberService extends BaseAdminService
public function getInfo(int $member_id) public function getInfo(int $member_id)
{ {
$field = 'member_id,member_no, username, mobile, password, register_channel, register_type, nickname, headimg, member_level, member_label, wx_openid, weapp_openid, wx_unionid, ali_openid, douyin_openid, login_ip, login_type, login_channel, login_count, login_time, create_time, last_visit_time, last_consum_time, sex, status, birthday, point, point_get, balance, balance_get, growth, growth_get, is_member, member_time, is_del, province_id, city_id, district_id, address, location, delete_time, money, money_get, commission, commission_get, commission_cash_outing'; $field = 'member_id,member_no, username, mobile, password, register_channel, register_type, nickname, headimg, member_level, member_label, wx_openid, weapp_openid, wx_unionid, ali_openid, douyin_openid, login_ip, login_type, login_channel, login_count, login_time, create_time, last_visit_time, last_consum_time, sex, status, birthday, point, point_get, balance, balance_get, growth, growth_get, is_member, member_time, is_del, province_id, city_id, district_id, address, location, delete_time, money, money_get, commission, commission_get, commission_cash_outing';
return $this->makeUp($this->model->where([['member_id', '=', $member_id]])->field($field)->with('member_level_name_bind')->append(['register_channel_name', 'register_type_name', 'sex_name', 'login_channel_name', 'login_type_name', 'status_name'])->findOrEmpty()->toArray()); return $this->makeUp($this->model->where([ [ 'member_id', '=', $member_id ] ])->field($field)->with('member_level_name_bind')->append([ 'register_channel_name', 'register_type_name', 'sex_name', 'login_channel_name', 'login_type_name', 'status_name' ])->findOrEmpty()->toArray());
} }
/** /**
@ -87,36 +92,36 @@ class MemberService extends BaseAdminService
{ {
//检测手机是否重复 //检测手机是否重复
if(!empty($data['mobile'])){ if (!empty($data[ 'mobile' ])) {
if(!$this->model->where([['mobile', '=', $data['mobile']]])->findOrEmpty()->isEmpty()) if (!$this->model->where([ [ 'mobile', '=', $data[ 'mobile' ] ] ])->findOrEmpty()->isEmpty())
throw new AdminException('MOBILE_IS_EXIST'); throw new AdminException('MOBILE_IS_EXIST');
} }
if($data['init_member_no'] != $data['member_no']){ if ($data[ 'init_member_no' ] != $data[ 'member_no' ]) {
if(!$this->model->where([['member_no', '=', $data['member_no']]])->findOrEmpty()->isEmpty()) if (!$this->model->where([ [ 'member_no', '=', $data[ 'member_no' ] ] ])->findOrEmpty()->isEmpty())
throw new AdminException('MEMBER_NO_IS_EXIST'); throw new AdminException('MEMBER_NO_IS_EXIST');
}else{ } else {
if(!$this->model->where([['member_no', '=', $data['member_no']]])->findOrEmpty()->isEmpty()){ if (!$this->model->where([ [ 'member_no', '=', $data[ 'member_no' ] ] ])->findOrEmpty()->isEmpty()) {
$data['member_no'] = $this->getMemberNo(); $data[ 'member_no' ] = $this->getMemberNo();
} }
} }
$data['username'] = $data['mobile']; $data[ 'username' ] = $data[ 'mobile' ];
if(!empty($data['username'])){ if (!empty($data[ 'username' ])) {
if(!$this->model->where([['username', '=', $data['username']]])->findOrEmpty()->isEmpty()) if (!$this->model->where([ [ 'username', '=', $data[ 'username' ] ] ])->findOrEmpty()->isEmpty())
throw new AdminException('MEMBER_IS_EXIST'); throw new AdminException('MEMBER_IS_EXIST');
} }
if (empty($data[ 'nickname' ]) && !empty($data['mobile'])) { if (empty($data[ 'nickname' ]) && !empty($data[ 'mobile' ])) {
$data[ 'nickname' ] = substr_replace($data['mobile'], '****', 3, 4); $data[ 'nickname' ] = substr_replace($data[ 'mobile' ], '****', 3, 4);
} }
$password_hash = create_password($data['password']); $password_hash = create_password($data[ 'password' ]);
$data['password'] = $password_hash; $data[ 'password' ] = $password_hash;
$data['register_type'] = MemberRegisterTypeDict::MANUAL; $data[ 'register_type' ] = MemberRegisterTypeDict::MANUAL;
$data['register_channel'] = MemberRegisterChannelDict::MANUAL; // todo 公共化渠道 $data[ 'register_channel' ] = MemberRegisterChannelDict::MANUAL; // todo 公共化渠道
$member = $this->model->create($data); $member = $this->model->create($data);
$data['member_id'] = $member->member_id; $data[ 'member_id' ] = $member->member_id;
event("MemberRegister", $data); event("MemberRegister", $data);
return $member->member_id; return $member->member_id;
} }
@ -130,10 +135,10 @@ class MemberService extends BaseAdminService
public function edit(int $member_id, array $data) public function edit(int $member_id, array $data)
{ {
$where = array( $where = array(
['member_id', '=', $member_id], [ 'member_id', '=', $member_id ],
); );
if(!empty($data['password'])){ if (!empty($data[ 'password' ])) {
$data['password'] = create_password($data['password']); $data[ 'password' ] = create_password($data[ 'password' ]);
} }
$this->model->where($where)->update($data); $this->model->where($where)->update($data);
return true; return true;
@ -147,17 +152,18 @@ class MemberService extends BaseAdminService
*/ */
public function modify(int $member_id, string $field, $data) public function modify(int $member_id, string $field, $data)
{ {
return (new CoreMemberService())->modify($member_id, $field, $data); return ( new CoreMemberService() )->modify($member_id, $field, $data);
} }
/** /**
* 组合整理数据 * 组合整理数据
* @param $data * @param $data
*/ */
public function makeUp($data){ public function makeUp($data)
{
//会员标签 //会员标签
if(!empty($data['member_label'])){ if (!empty($data[ 'member_label' ])) {
$data['member_label_array'] = (new MemberLabelService())->getMemberLabelListByLabelIds($data['member_label']); $data[ 'member_label_array' ] = ( new MemberLabelService() )->getMemberLabelListByLabelIds($data[ 'member_label' ]);
} }
return $data; return $data;
} }
@ -167,8 +173,9 @@ class MemberService extends BaseAdminService
* @return int * @return int
* @throws DbException * @throws DbException
*/ */
public function getCount(array $where = []){ public function getCount(array $where = [])
$where[] = ['is_del', '=', 0]; {
$where[] = [ 'is_del', '=', 0 ];
return $this->model->where($where)->count(); return $this->model->where($where)->count();
} }
@ -178,9 +185,10 @@ class MemberService extends BaseAdminService
* @param int $status * @param int $status
* @return true * @return true
*/ */
public function setStatus(array $member_ids, int $status){ public function setStatus(array $member_ids, int $status)
{
$where = array( $where = array(
['member_id', 'in', $member_ids], [ 'member_id', 'in', $member_ids ],
); );
$data = array( $data = array(
'status' => $status 'status' => $status
@ -196,7 +204,7 @@ class MemberService extends BaseAdminService
*/ */
public function getSum($field) public function getSum($field)
{ {
return $this->model->where([ ['member_id', '>', 0] ])->sum($field); return $this->model->where([ [ 'member_id', '>', 0 ] ])->sum($field);
} }
/** /**
@ -205,7 +213,7 @@ class MemberService extends BaseAdminService
*/ */
public function getMemberNo() public function getMemberNo()
{ {
return (new CoreMemberService())->createMemberNo(); return ( new CoreMemberService() )->createMemberNo();
} }
/** /**
@ -215,8 +223,8 @@ class MemberService extends BaseAdminService
*/ */
public function deleteMember(int $member_id) public function deleteMember(int $member_id)
{ {
$this->model->destroy(function($query) use($member_id){ $this->model->destroy(function ($query) use ($member_id) {
$query->where([['member_id', '=', $member_id]]); $query->where([ [ 'member_id', '=', $member_id ] ]);
}); });
return true; return true;
} }
@ -230,9 +238,9 @@ class MemberService extends BaseAdminService
{ {
$field = 'member_id, member_no, username, mobile, nickname, point, balance, money, growth, commission, register_channel, status, create_time, last_visit_time'; $field = 'member_id, member_no, username, mobile, nickname, point, balance, money, growth, commission, register_channel, status, create_time, last_visit_time';
//查询导出数据 //查询导出数据
$data = $this->model->withSearch(['keyword','register_type', 'create_time', 'is_del', 'member_label', 'register_channel'],$where)->field($field)->append(['register_channel_name', 'status_name'])->select()->toArray(); $data = $this->model->withSearch([ 'keyword', 'register_type', 'create_time', 'is_del', 'member_label', 'register_channel' ], $where)->field($field)->append([ 'register_channel_name', 'status_name' ])->select()->toArray();
//执行导出 //执行导出
(new ExportService())->exportData('member', $data); ( new ExportService() )->exportData('member', $data);
return true; return true;
} }
@ -240,32 +248,36 @@ class MemberService extends BaseAdminService
* 获取会员权益字典 * 获取会员权益字典
* @return mixed * @return mixed
*/ */
public function getMemberBenefitsDict() { public function getMemberBenefitsDict()
return (new DictLoader("MemberBenefits"))->load(); {
return ( new DictLoader("MemberBenefits") )->load();
} }
/** /**
* 获取会员礼包字典 * 获取会员礼包字典
* @return array|null * @return array|null
*/ */
public function getMemberGiftDict() { public function getMemberGiftDict()
return (new DictLoader("MemberGift"))->load(); {
return ( new DictLoader("MemberGift") )->load();
} }
/** /**
* 获取成长值规则字典 * 获取成长值规则字典
* @return array|null * @return array|null
*/ */
public function getGrowthRuleDict() { public function getGrowthRuleDict()
return (new DictLoader("GrowthRule"))->load(); {
return ( new DictLoader("GrowthRule") )->load();
} }
/** /**
* 获取积分规则字典 * 获取积分规则字典
* @return array|null * @return array|null
*/ */
public function getPointRuleDict() { public function getPointRuleDict()
return (new DictLoader("PointRule"))->load(); {
return ( new DictLoader("PointRule") )->load();
} }
/** /**
@ -273,8 +285,9 @@ class MemberService extends BaseAdminService
* @param array $benefits * @param array $benefits
* @return array|null * @return array|null
*/ */
public function getMemberBenefitsContent(array $benefits) { public function getMemberBenefitsContent(array $benefits)
return (new CoreMemberService())->getBenefitsContent($benefits); {
return ( new CoreMemberService() )->getBenefitsContent($benefits);
} }
/** /**
@ -282,7 +295,8 @@ class MemberService extends BaseAdminService
* @param array $benefits * @param array $benefits
* @return array|null * @return array|null
*/ */
public function getMemberGiftsContent(array $gifts) { public function getMemberGiftsContent(array $gifts)
return (new CoreMemberService())->getGiftContent($gifts); {
return ( new CoreMemberService() )->getGiftContent($gifts);
} }
} }

View File

@ -37,14 +37,15 @@ class NiucloudService extends BaseAdminService
* @param $data * @param $data
* @return \app\model\sys\SysConfig|bool|\think\Model * @return \app\model\sys\SysConfig|bool|\think\Model
*/ */
public function setAuthorize($data){ public function setAuthorize($data)
{
$data = [ $data = [
'auth_code' => $data['auth_code'], 'auth_code' => $data[ 'auth_code' ],
'auth_secret' => $data['auth_secret'] 'auth_secret' => $data[ 'auth_secret' ]
]; ];
$service = (new CoreAuthService($data['auth_code'], $data['auth_secret'])); $service = ( new CoreAuthService($data[ 'auth_code' ], $data[ 'auth_secret' ]) );
$auth_info = $service->getAuthInfo()['data'] ?? []; $auth_info = $service->getAuthInfo()[ 'data' ] ?? [];
if (empty($auth_info)) throw new CommonException('AUTH_NOT_EXISTS'); if (empty($auth_info)) throw new CommonException('AUTH_NOT_EXISTS');
$service->clearAccessToken(); $service->clearAccessToken();
return $this->core_config_service->setConfig(ConfigKeyDict::NIUCLOUD_CONFIG, $data); return $this->core_config_service->setConfig(ConfigKeyDict::NIUCLOUD_CONFIG, $data);
@ -54,34 +55,45 @@ class NiucloudService extends BaseAdminService
* 获取授权信息 * 获取授权信息
* @return mixed|string[] * @return mixed|string[]
*/ */
public function getAuthorize(){ public function getAuthorize()
{
$info = $this->core_config_service->getConfig(ConfigKeyDict::NIUCLOUD_CONFIG); $info = $this->core_config_service->getConfig(ConfigKeyDict::NIUCLOUD_CONFIG);
if(empty($info)) if (empty($info)) {
{
$info = []; $info = [];
$info['value'] = [ $info[ 'value' ] = [
'auth_code' => '', 'auth_code' => '',
'auth_secret' => '' 'auth_secret' => ''
]; ];
} }
return $info['value']; return $info[ 'value' ];
} }
/** /**
* 获取框架最新版本 * 获取框架最新版本
*/ */
public function getFrameworkLastVersion() { public function getFrameworkLastVersion()
return (new CoreModuleService())->getFrameworkLastVersion(); {
return ( new CoreModuleService() )->getFrameworkLastVersion();
} }
/** /**
* 获取框架版本更新记录 * 获取框架版本更新记录
*/ */
public function getFrameworkVersionList() { public function getFrameworkVersionList()
return (new CoreModuleService())->getFrameworkVersionList(); {
return ( new CoreModuleService() )->getFrameworkVersionList();
} }
public function applyExperience() { public function applyExperience()
return (new CoreModuleService())->applyExperience(); {
return ( new CoreModuleService() )->applyExperience();
}
/**
* 获取应用/插件的版本更新记录
*/
public function getAppVersionList($app_key)
{
return ( new CoreModuleService() )->getAppVersionList($app_key);
} }
} }

View File

@ -118,16 +118,12 @@ class ConfigService extends BaseAdminService
*/ */
public function getService() public function getService()
{ {
$info = ( new CoreConfigService() )->getConfig('SERVICE_INFO'); $info = ( new CoreConfigService() )->getConfig('SERVICE_INFO')[ 'value' ] ?? [];
if (empty($info)) { return [
$info = []; 'wechat_code' => $info[ 'wechat_code' ] ?? '',
$info[ 'value' ] = [ 'enterprise_wechat' => $info[ 'enterprise_wechat' ] ?? '',
'wechat_code' => '', 'tel' => $info[ 'tel' ] ?? ''
'enterprise_wechat' => '', ];
'tel' => '',
];
}
return $info[ 'value' ];
} }
/** /**
@ -171,7 +167,7 @@ class ConfigService extends BaseAdminService
if (empty($info)) { if (empty($info)) {
$info = []; $info = [];
$info[ 'value' ] = [ $info[ 'value' ] = [
'key' => 'IZQBZ-3UHEU-WTCVD-2464U-I5N4V-ZFFU3', 'key' => '',
'is_open' => 1, // 是否开启定位 'is_open' => 1, // 是否开启定位
'valid_time' => 5 // 定位有效期/分钟过期后将重新获取定位信息0为不过期 'valid_time' => 5 // 定位有效期/分钟过期后将重新获取定位信息0为不过期
]; ];

View File

@ -14,8 +14,10 @@ namespace app\service\admin\sys;
use app\job\sys\CheckJob; use app\job\sys\CheckJob;
use app\service\core\sys\CoreSysConfigService; use app\service\core\sys\CoreSysConfigService;
use core\base\BaseAdminService; use core\base\BaseAdminService;
use core\exception\AdminException;
use think\facade\Cache; use think\facade\Cache;
use think\facade\Db; use think\facade\Db;
use think\facade\Log;
use Throwable; use Throwable;
/** /**
@ -49,7 +51,7 @@ class SystemService extends BaseAdminService
*/ */
public function getUrl() public function getUrl()
{ {
return (new CoreSysConfigService())->getSceneDomain(); return ( new CoreSysConfigService() )->getSceneDomain();
} }
/** /**
@ -61,7 +63,7 @@ class SystemService extends BaseAdminService
$server = []; $server = [];
$server[] = [ "name" => get_lang('dict_setting.server_system'), "server" => PHP_OS ]; $server[] = [ "name" => get_lang('dict_setting.server_system'), "server" => PHP_OS ];
$server[] = [ "name" => get_lang('dict_setting.server_setting'), "server" => PHP_SAPI ]; $server[] = [ "name" => get_lang('dict_setting.server_setting'), "server" => PHP_SAPI ];
$server[] = [ "name" => get_lang('dict_setting.php_version'), "server" => PHP_VERSION]; $server[] = [ "name" => get_lang('dict_setting.php_version'), "server" => PHP_VERSION ];
//环境权限 //环境权限
$system_variables = []; $system_variables = [];
@ -104,7 +106,7 @@ class SystemService extends BaseAdminService
//获取环境版本 //获取环境版本
$server_version = []; $server_version = [];
$row = (array) Db::query("select VERSION() as verson"); $row = (array) Db::query("select VERSION() as verson");
$server_version[] = [ "name" => get_lang('dict_setting.php_version'), "demand" => get_lang('dict_setting.php_ask'), "server" => PHP_VERSION]; $server_version[] = [ "name" => get_lang('dict_setting.php_version'), "demand" => get_lang('dict_setting.php_ask'), "server" => PHP_VERSION ];
$server_version[] = [ "name" => get_lang('dict_setting.mysql_version'), "demand" => get_lang('dict_setting.mysql_ask'), "server" => $row[ 0 ][ 'verson' ] ]; $server_version[] = [ "name" => get_lang('dict_setting.mysql_version'), "demand" => get_lang('dict_setting.mysql_ask'), "server" => $row[ 0 ][ 'verson' ] ];
// 进程 // 进程
@ -144,7 +146,7 @@ class SystemService extends BaseAdminService
$file = root_path('runtime') . $secret . '.job'; $file = root_path('runtime') . $secret . '.job';
try { try {
CheckJob::dispatch([ 'file' => $file ]); CheckJob::dispatch([ 'file' => $file ]);
} catch ( Throwable $e) { } catch (Throwable $e) {
return false; return false;
} }
// $timeout = 0; // $timeout = 0;
@ -179,4 +181,37 @@ class SystemService extends BaseAdminService
} }
return false; return false;
} }
/**
* 获取二维码
* @param $data
* @return array
*/
public function getQrcode($data)
{
$page = $data[ 'page' ];//'app/pages/index/diy_form';
$qrcode_data = [];
foreach ($data[ 'params' ] as $item) {
$qrcode_data[] = [
'key' => $item[ 'column_name' ],
'value' => $item[ 'column_value' ]
];
}
$dir = 'upload/' . $data[ 'folder' ] . '_qrcode';
try {
// h5
//$h5_path = qrcode('', $page, $data, $dir);
// 微信小程序
$weapp_path = qrcode('', $page, $qrcode_data, $dir, 'weapp');
return [
'h5_path' => '',
'weapp_path' => $weapp_path
];
} catch (AdminException $e) {
Log::write('获取推广微信小程序二维码error' . $e->getMessage() . $e->getFile() . $e->getLine() . 'params:' . json_encode($data, 256));
throw new AdminException($e->getMessage() . $e->getFile() . $e->getLine() . 'params:' . json_encode($data, 256));
}
}
} }

View File

@ -0,0 +1,662 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\admin\upgrade;
use app\dict\sys\BackupDict;
use app\model\sys\SysBackupRecords;
use app\service\admin\sys\SystemService;
use core\base\BaseAdminService;
use core\exception\AdminException;
use core\exception\CommonException;
use core\util\DbBackup;
use think\facade\Cache;
use think\facade\Db;
/**
* 备份记录表服务层
*/
class BackupRecordsService extends BaseAdminService
{
protected $upgrade_dir;
protected $root_path;
protected $cache_key = 'backup'; // 手动备份
protected $cache_restore_key = 'restore'; // 恢复
public function __construct()
{
parent::__construct();
$this->model = new SysBackupRecords();
$this->root_path = dirname(root_path()) . DIRECTORY_SEPARATOR;
$this->upgrade_dir = $this->root_path . 'upgrade' . DIRECTORY_SEPARATOR;
}
/**
* 添加备份记录
* @param array $data
* @return mixed
*/
public function add(array $data)
{
$data[ 'status' ] = BackupDict::STATUS_READY;
$data[ 'create_time' ] = time();
$res = $this->model->create($data);
return $res->id;
}
/**
* 编辑备份记录
* @param array $condition
* @param array $data
* @return true
*/
public function edit($condition, array $data)
{
$this->model->where($condition)->update($data);
return true;
}
/**
* 修改备注
* @param $params
* @return true
*/
public function modifyRemark($params)
{
return $this->edit([
[ 'id', '=', $params[ 'id' ] ]
], [ 'remark' => $params[ 'remark' ] ]);
}
/**
* 执行完成,更新备份记录的状态
* @param $backup_key
* @return void
*/
public function complete($backup_key)
{
$this->model->where([
[ 'backup_key', '=', $backup_key ],
])->update([
'status' => BackupDict::STATUS_COMPLETE,
'complete_time' => time()
]);
}
/**
* 执行失败,更新备份记录的状态
* @param $backup_key
* @return void
*/
public function failed($backup_key)
{
$info = $this->getInfo([
[ 'backup_key', '=', $backup_key ]
], 'id,backup_key');
if (!empty($info)) {
$this->del($info[ 'id' ]);
}
}
/**
* 删除备份记录
* @param $ids
* @return true
*/
public function del($ids)
{
$list = $this->model->field('id,backup_key')->where([ [ 'id', 'in', $ids ] ])->select()->toArray();
if (empty($list)) {
throw new AdminException('UPGRADE_RECORD_NOT_EXIST');
}
try {
Db::startTrans();
foreach ($list as $k => $v) {
// 删除备份文件
$upgrade_dir = project_path() . 'upgrade' . DIRECTORY_SEPARATOR . $v[ 'backup_key' ] . DIRECTORY_SEPARATOR;
if (is_dir($upgrade_dir)) {
del_target_dir($upgrade_dir, true);
}
}
$this->model->where([ [ 'id', 'in', $ids ] ])->delete();
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
throw new CommonException($e->getMessage());
}
}
/**
* 恢复前检测文件是否存在
* @param $id
* @return void
*/
public function checkDirExist($id)
{
$field = 'id, version, backup_key';
$info = $this->model->where([
[ 'id', '=', $id ],
[ 'status', '=', BackupDict::STATUS_COMPLETE ]
])->field($field)->append([ 'backup_dir', 'backup_code_dir', 'backup_sql_dir' ])->findOrEmpty()->toArray();
if (empty($info)) {
throw new AdminException('UPGRADE_RECORD_NOT_EXIST');
}
// 检测源码目录是否存在
if (!is_dir($info[ 'backup_code_dir' ])) {
throw new AdminException('UPGRADE_BACKUP_CODE_NOT_FOUND');
}
// 检测数据库目录是否存在
if (!is_dir($info[ 'backup_sql_dir' ])) {
throw new AdminException('UPGRADE_BACKUP_SQL_NOT_FOUND');
}
}
/**
* 检测目录权限
* @return void
*/
public function checkPermission()
{
$niucloud_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR;
$admin_dir = $this->root_path . 'admin' . DIRECTORY_SEPARATOR;
$web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR;
$wap_dir = $this->root_path . 'uni-app' . DIRECTORY_SEPARATOR;
if (!is_dir($admin_dir)) throw new CommonException('ADMIN_DIR_NOT_EXIST');
if (!is_dir($web_dir)) throw new CommonException('WEB_DIR_NOT_EXIST');
if (!is_dir($wap_dir)) throw new CommonException('UNIAPP_DIR_NOT_EXIST');
$data = [
// 目录检测
'dir' => [
// 要求可读权限
'is_readable' => [],
// 要求可写权限
'is_write' => []
]
];
$data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $niucloud_dir), 'status' => is_readable($niucloud_dir) ];
$data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $admin_dir), 'status' => is_readable($admin_dir) ];
$data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $web_dir), 'status' => is_readable($web_dir) ];
$data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $wap_dir), 'status' => is_readable($wap_dir) ];
$data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $niucloud_dir), 'status' => is_write($niucloud_dir) ];
$data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $admin_dir), 'status' => is_write($admin_dir) ];
$data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $web_dir), 'status' => is_write($web_dir) ];
$data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $wap_dir), 'status' => is_write($wap_dir) ];
// 检测全部目录及文件是否可读可写,忽略指定目录
// 忽略指定目录admin
$exclude_admin_dir = [ 'dist', 'node_modules' ];
$check_res = checkDirPermissions(project_path() . 'admin', [], $exclude_admin_dir);
// 忽略指定目录uni-app
$exclude_uniapp_dir = [ 'dist', 'node_modules' ];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'uni-app', [], $exclude_uniapp_dir));
// 忽略指定目录web
$exclude_web_dir = [ '.nuxt', '.output', 'dist', 'node_modules' ];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'web', [], $exclude_web_dir));
// 忽略指定目录niucloud
$exclude_niucloud_dir = [
'public' . DIRECTORY_SEPARATOR . 'admin',
'public' . DIRECTORY_SEPARATOR . 'wap',
'public' . DIRECTORY_SEPARATOR . 'web',
'public' . DIRECTORY_SEPARATOR . 'upload',
'public' . DIRECTORY_SEPARATOR . 'file',
'runtime',
'vendor'
];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'niucloud', [], $exclude_niucloud_dir));
if (!empty($check_res[ 'unreadable' ])) {
foreach ($check_res[ 'unreadable' ] as $item) {
$data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $item), 'status' => false ];
}
}
if (!empty($check_res[ 'not_writable' ])) {
foreach ($check_res[ 'not_writable' ] as $item) {
$data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $item), 'status' => false ];
}
}
$check_res = array_merge(
array_column($data[ 'dir' ][ 'is_readable' ], 'status'),
array_column($data[ 'dir' ][ 'is_write' ], 'status')
);
// 是否通过校验
$data[ 'is_pass' ] = !in_array(false, $check_res);
return $data;
}
/**
* 备份恢复
* @param $data
* @return array
*/
public function restore($data)
{
$field = 'id, version, backup_key';
$info = $this->model->where([
[ 'id', '=', $data[ 'id' ] ],
[ 'status', '=', BackupDict::STATUS_COMPLETE ]
])->field($field)->append([ 'backup_dir', 'backup_code_dir', 'backup_sql_dir' ])->findOrEmpty()->toArray();
if (empty($info)) {
throw new AdminException('UPGRADE_RECORD_NOT_EXIST');
}
// 恢复源码备份
if (!is_dir($info[ 'backup_code_dir' ])) {
throw new AdminException('UPGRADE_BACKUP_CODE_NOT_FOUND');
}
// 恢复数据库备份
if (!is_dir($info[ 'backup_sql_dir' ])) {
throw new AdminException('UPGRADE_BACKUP_SQL_NOT_FOUND');
}
$res = [ 'code' => 1, 'data' => [], 'msg' => '' ];
$cache_data = Cache::get($this->cache_restore_key);
if (!empty($cache_data) && !empty($cache_data[ 'key' ])) {
$key = $cache_data[ 'key' ];
} else {
$key = uniqid();
}
try {
if ($data[ 'task' ] == '') {
$key = uniqid();
$res[ 'data' ] = [
'content' => '开始恢复备份',
'task' => 'backupCode'
];
$temp = [
'key' => $key,
'data' => [ $res[ 'data' ] ]
];
Cache::set($this->cache_key, null);
Cache::set($this->cache_restore_key, $temp);
// 添加恢复日志
$this->add([
'backup_key' => $key,
'content' => "自动备份",
'version' => $info[ 'version' ]
]);
} elseif ($data[ 'task' ] == 'backupCode') {
$res[ 'data' ] = [
'content' => '备份源码',
'task' => 'backupSql'
];
$temp = Cache::get($this->cache_restore_key);
$temp[ 'data' ][] = $res[ 'data' ];
Cache::set($this->cache_restore_key, $temp);
//备份源码
$this->backupCode($key);
} elseif ($data[ 'task' ] == 'backupSql') {
$backup_result = $this->backupSql($key);
if ($backup_result === true) {
//备份数据库
$res[ 'data' ] = [
'content' => '数据库备份完成',
'task' => 'restoreCode'
];
} else {
$res[ 'data' ] = [
'content' => '',
'task' => 'backupSql'
];
if ($backup_result % 5 == 0) {
$res[ 'data' ][ 'content' ] = $backup_result == 0 ? '数据库开始备份' : '数据库备份中已备份' . $backup_result . '%';
}
}
$temp = Cache::get($this->cache_restore_key);
$temp[ 'data' ][] = $res[ 'data' ];
Cache::set($this->cache_restore_key, $temp);
} elseif ($data[ 'task' ] == 'restoreCode') {
$res[ 'data' ] = [
'content' => '恢复源码备份',
'task' => 'restoreSql'
];
$temp = Cache::get($this->cache_restore_key);
$temp[ 'data' ][] = $res[ 'data' ];
Cache::set($this->cache_restore_key, $temp);
// 恢复源码备份
$root_path = dirname(root_path()) . DIRECTORY_SEPARATOR;
dir_copy($info[ 'backup_code_dir' ], rtrim($root_path, DIRECTORY_SEPARATOR));
} elseif ($data[ 'task' ] == 'restoreSql') {
// 恢复数据库备份
$db = new DbBackup($info[ 'backup_sql_dir' ]);
$restore_result = $db->restoreDatabase();
if ($restore_result === true) {
$res[ 'data' ] = [
'content' => '恢复数据库备份',
'task' => 'restoreData'
];
} else {
$res[ 'data' ] = [
'content' => '',
'task' => 'restoreSql'
];
}
$temp = Cache::get($this->cache_restore_key);
$temp[ 'data' ][] = $res[ 'data' ];
Cache::set($this->cache_restore_key, $temp);
} elseif ($data[ 'task' ] == 'restoreData') {
$res[ 'data' ] = [
'content' => '恢复数据',
'task' => 'restoreComplete'
];
$temp = Cache::get($this->cache_restore_key);
$temp[ 'data' ][] = $res[ 'data' ];
Cache::set($this->cache_restore_key, $temp);
// todo 恢复数据
} elseif ($data[ 'task' ] == 'restoreComplete') {
$res[ 'data' ] = [
'content' => '备份恢复完成',
'task' => 'end'
];
// 修改备份记录状态
$this->edit([
[ 'backup_key', '=', Cache::get($this->cache_restore_key)[ 'key' ] ],
], [
'status' => BackupDict::STATUS_COMPLETE,
'complete_time' => time()
]);
Cache::set($this->cache_restore_key, null);
( new SystemService() )->clearCache(); // 清除缓存
}
return $res;
} catch (\Exception $e) {
$res[ 'data' ] = [
'content' => '备份恢复失败,稍后请手动恢复,备份文件路径:' . $info[ 'backup_dir' ] . ',失败原因:' . $e->getMessage() . $e->getFile() . $e->getLine(),
'task' => 'fail'
];
$fail_reason = [
'Message' => '失败原因:' . $e->getMessage(),
'File' => '文件:' . $e->getFile(),
'Line' => '代码行号:' . $e->getLine(),
'Trace' => $e->getTrace()
];
// 修改备份记录状态
$this->edit([
[ 'backup_key', '=', Cache::get($this->cache_restore_key)[ 'key' ] ],
], [
'fail_reason' => $fail_reason,
'status' => BackupDict::STATUS_FAIL,
'complete_time' => time()
]);
Cache::set($this->cache_restore_key, null);
return $res;
}
}
/**
* 手动备份
* @param $data
* @return array
*/
public function manualBackup($data)
{
$res = [ 'code' => 1, 'data' => [], 'msg' => '' ];
$key = uniqid();
$cache_data = Cache::get($this->cache_key);
if ($cache_data) {
$key = $cache_data[ 'key' ];
}
try {
if ($data[ 'task' ] == '') {
$key = uniqid();
$res[ 'data' ] = [
'content' => '开始备份',
'task' => 'backupCode'
];
$temp = [
'key' => $key,
'data' => [ $res[ 'data' ] ]
];
Cache::set($this->cache_key, null);
Cache::set($this->cache_key, $temp);
// 添加备份日志
$this->add([
'backup_key' => $key,
'content' => "手动备份",
'version' => "v" . config('version.version'),
]);
} elseif ($data[ 'task' ] == 'backupCode') {
$res[ 'data' ] = [
'content' => '备份源码',
'task' => 'backupSql'
];
$temp = Cache::get($this->cache_key);
$temp[ 'data' ][] = $res[ 'data' ];
Cache::set($this->cache_key, $temp);
//备份源码
$this->backupCode($key);
} elseif ($data[ 'task' ] == 'backupSql') {
$backup_result = $this->backupSql($key);
if ($backup_result === true || $backup_result == 100) {
//备份数据库
$res[ 'data' ] = [
'content' => '数据库备份完成',
'task' => 'backComplete'
];
} else {
$res[ 'data' ] = [
'content' => $backup_result == 0 ? '数据库开始备份' : '数据库备份已备份' . $backup_result . '%',
'task' => 'backupSql'
];
}
$temp = Cache::get($this->cache_restore_key);
$temp[ 'data' ][] = $res[ 'data' ];
Cache::set($this->cache_restore_key, $temp);
} elseif ($data[ 'task' ] == 'backComplete') {
$res[ 'data' ] = [
'content' => '备份完成',
'task' => 'end'
];
// 修改备份记录状态
$this->complete(Cache::get($this->cache_key)[ 'key' ]);
Cache::set($this->cache_key, null);
}
return $res;
} catch (\Exception $e) {
$res[ 'data' ] = [
'content' => '备份失败,稍后请重新手动备份,失败原因:' . $e->getMessage() . $e->getFile() . $e->getLine(),
'task' => 'fail'
];
// 修改备份记录状态
$this->failed(Cache::get($this->cache_key)[ 'key' ]);
Cache::set($this->cache_key, null);
return $res;
}
}
/**
* 获取正在进行的恢复任务
* @return mixed|null
*/
public function getRestoreTask()
{
$task_data = Cache::get($this->cache_restore_key) ?? [];
return $task_data;
}
/**
* 获取正在进行的备份任务
* @return mixed|null
*/
public function getBackupTask()
{
$task_data = Cache::get($this->cache_key) ?? [];
return $task_data;
}
/**
* 获取备份记录信息
* @param array $condition
* @param $field
* @return array
*/
public function getInfo(array $condition, $field = 'id, version, backup_key, content, status, fail_reason, create_time, complete_time')
{
return $this->model->field($field)->where($condition)->findOrEmpty()->toArray();
}
/**
* 备份记录列表
* @param $condition
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getList($condition = [], $field = 'id, version, backup_key, content, status, fail_reason, create_time, complete_time')
{
$order = "id desc";
return $this->model->where($condition)->field($field)->order($order)->select()->toArray();
}
/**
* 备份记录分页列表
* @param array $where
* @return array
*/
public function getPage(array $where = [])
{
$field = 'id, version, backup_key, content, remark, complete_time';
$order = "id desc";
$search_model = $this->model->where([
[ 'status', '=', BackupDict::STATUS_COMPLETE ],
[ 'content|version', 'like', '%' . $where[ 'content' ] . '%' ]
])->append([ 'backup_dir' ])->field($field)->order($order);
return $this->pageQuery($search_model);
}
/**
* 备份代码
* @param $backup_key
* @return void
*/
public function backupCode($backup_key)
{
$backup_dir = $this->upgrade_dir . $backup_key . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
// 创建目录
dir_mkdir($backup_dir);
// 备份admin
dir_copy($this->root_path . 'admin', $backup_dir . 'admin', exclude_dirs: [ '.vscode', 'node_modules', 'dist' ]);
// 备份uni-app
dir_copy($this->root_path . 'uni-app', $backup_dir . 'uni-app', exclude_dirs: [ 'node_modules', 'dist' ]);
// 备份web
dir_copy($this->root_path . 'web', $backup_dir . 'web', exclude_dirs: [ 'node_modules', '.nuxt', '.output', 'dist' ]);
// 备份niucloud全部代码
$niucloud_dir = $backup_dir . 'niucloud' . DIRECTORY_SEPARATOR;
dir_copy($this->root_path . 'niucloud', $niucloud_dir, exclude_dirs: [ 'runtime', 'upload' ]);
return true;
}
/**
* 备份数据库
* @param $backup_key
* @return void
*/
public function backupSql($backup_key)
{
$backup_dir = $this->upgrade_dir . $backup_key . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
// 创建目录
dir_mkdir($backup_dir);
$prefix = config('database.connections.' . config('database.default'))[ 'prefix' ];
// 不需要备份的表
$not_need_backup = [
"{$prefix}sys_schedule_log",
"{$prefix}sys_user_log",
"{$prefix}jobs",
"{$prefix}jobs_failed",
"{$prefix}sys_upgrade_records",
"{$prefix}sys_backup_records"
];
$db = new DbBackup($backup_dir, 1024 * 1024 * 2, $not_need_backup, key: $backup_key);
$result = $db->backupDatabaseSegment();
if ($result === true) return true;
return $db->getBackupProgress();
}
}

View File

@ -11,10 +11,6 @@
namespace app\service\admin\upgrade; namespace app\service\admin\upgrade;
use app\dict\addon\AddonDict;
use app\service\admin\generator\GenerateService;
use core\util\DbBackup;
/** /**
* 框架及插件升级备份 * 框架及插件升级备份
* @package app\service\core\upgrade * @package app\service\core\upgrade
@ -31,92 +27,21 @@ class BackupService extends UpgradeService
// 创建目录 // 创建目录
dir_mkdir($backup_dir); dir_mkdir($backup_dir);
// 备份admin // 备份admin
dir_copy($this->root_path . 'admin', $backup_dir . 'admin', exclude_dirs:[ '.vscode', 'node_modules', 'dist' ]); dir_copy($this->root_path . 'admin', $backup_dir . 'admin', exclude_dirs: [ '.vscode', 'node_modules', 'dist' ]);
// 备份uni-app // 备份uni-app
dir_copy($this->root_path . 'uni-app', $backup_dir . 'uni-app', exclude_dirs:[ 'node_modules', 'dist' ]); dir_copy($this->root_path . 'uni-app', $backup_dir . 'uni-app', exclude_dirs: [ 'node_modules', 'dist' ]);
// 备份web // 备份web
dir_copy($this->root_path . 'web', $backup_dir . 'web', exclude_dirs:[ 'node_modules', '.nuxt', '.output' ]); dir_copy($this->root_path . 'web', $backup_dir . 'web', exclude_dirs: [ 'node_modules', '.nuxt', '.output', 'dist' ]);
// 备份niucloud // 备份niucloud全部代码
$niucloud_dir = $backup_dir . 'niucloud' . DIRECTORY_SEPARATOR; $niucloud_dir = $backup_dir . 'niucloud' . DIRECTORY_SEPARATOR;
if ($this->upgrade_task[ 'upgrade' ][ 'app_key' ] == AddonDict::FRAMEWORK_KEY) {
dir_copy($this->root_path . 'niucloud', $niucloud_dir, exclude_dirs:[ 'addon', 'config', 'public', 'vendor', 'runtime' ]);
// 备份版本文件
$version_file = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'version.php';
$to_version_file = $niucloud_dir . 'config' . DIRECTORY_SEPARATOR . 'version.php';
file_copy($version_file, $to_version_file);
} else {
$addon = $this->upgrade_task[ 'upgrade' ][ 'app_key' ];
$addon_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR . 'addon' . DIRECTORY_SEPARATOR . $addon;
$to_addon_dir = $niucloud_dir . 'addon' . DIRECTORY_SEPARATOR . $addon;
dir_copy($addon_dir, $to_addon_dir);
}
// 备份前端文件
if (is_dir(public_path() . 'admin')) {
dir_copy(public_path() . 'admin', $niucloud_dir . 'public' . DIRECTORY_SEPARATOR . 'admin');
}
if (is_dir(public_path() . 'wap')) {
dir_copy(public_path() . 'wap', $niucloud_dir . 'public' . DIRECTORY_SEPARATOR . 'wap');
}
if (is_dir(public_path() . 'web')) {
dir_copy(public_path() . 'web', $niucloud_dir . 'public' . DIRECTORY_SEPARATOR . 'web');
}
return true; dir_copy($this->root_path . 'niucloud', $niucloud_dir, exclude_dirs: [ 'runtime', 'upload' ]);
}
/**
* 备份数据库
* @return void
*/
public function backupSql()
{
$backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
// 创建目录
dir_mkdir($backup_dir);
$db = new DbBackup([
'path' => $backup_dir,//数据库备份路径
'part' => 1048576,//数据库备份卷大小
'compress' => 0,//数据库备份文件是否启用压缩 0不压缩 1 压缩
'level' => 9 //数据库备份文件压缩级别 1普通 4 一般 9最高
]);
$tables = [];
$prefix = config('database.connections.' . config('database.default'))[ 'prefix' ];
if ($this->upgrade_task[ 'upgrade' ][ 'app_key' ] == AddonDict::FRAMEWORK_KEY) {
// 不需要备份的表
$noot_need_backup = [ "{$prefix}sys_schedule_log", "{$prefix}sys_user_log", "{$prefix}jobs", "{$prefix}jobs_failed" ];
$sys_models = ( new GenerateService() )->getModels([ 'addon' => 'system' ]);
foreach ($sys_models as $model) {
$name = "\\$model";
$class = new $name();
if (!in_array($class->getTable(), $noot_need_backup)) {
$tables[] = $class->getTable();
}
}
} else {
$addon_models = ( new GenerateService() )->getModels([ 'addon' => $this->upgrade_task[ 'upgrade' ][ 'app_key' ] ]);
foreach ($addon_models as $model) {
try {
// 不需要备份的表
$noot_need_backup = [ "{$prefix}shop_stat", "{$prefix}shop_goods_stat", "{$prefix}shop_goods_browse" ];
$name = "\\$model";
$class = new $name();
if (!in_array($class->getTable(), $noot_need_backup)) {
$tables[] = $class->getTable();
}
} catch (\Exception $e) {
}
}
}
foreach ($tables as $table) {
$db->setFile()->backup($table);
}
return true; return true;
} }
} }

View File

@ -11,50 +11,10 @@
namespace app\service\admin\upgrade; namespace app\service\admin\upgrade;
use core\util\DbBackup;
/** /**
* 框架及插件升级恢复备份 * 框架及插件升级恢复备份
* @package app\service\core\upgrade * @package app\service\core\upgrade
*/ */
class RestoreService extends UpgradeService class RestoreService extends UpgradeService
{ {
/**
* 恢复代码备份
* @return true
*/
public function restoreCode() {
$backup_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
if (is_dir($backup_dir)) {
// 删除前端文件
// if (is_dir(public_path() . 'admin')) del_target_dir(public_path() . 'admin', true);
// if (is_dir(public_path() . 'wap')) del_target_dir(public_path() . 'wap', true);
// if (is_dir(public_path() . 'web')) del_target_dir(public_path() . 'web', true);
dir_copy($backup_dir, rtrim($this->root_path, DIRECTORY_SEPARATOR));
}
return true;
}
/**
* 恢复数据库备份
* @return true
*/
public function restoreSql() {
$backup_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
if (is_dir($backup_dir)) {
$db = new DbBackup([
'path' => $backup_dir //数据库备份路径
]);
$file_list = $db->fileList();
if (!empty($file_list)) {
$db->setSqlMode();
foreach ($file_list as $file) {
$db->setFile($file)->import(0, $file['time']);
}
}
}
return true;
}
} }

View File

@ -0,0 +1,128 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\admin\upgrade;
use app\dict\sys\UpgradeDict;
use app\model\sys\SysUpgradeRecords;
use core\base\BaseAdminService;
use think\facade\Log;
/**
* 升级记录表服务层
*/
class UpgradeRecordsService extends BaseAdminService
{
public function __construct()
{
parent::__construct();
$this->model = new SysUpgradeRecords();
}
/**
* 添加升级记录
* @param array $data
* @return mixed
*/
public function add(array $data)
{
$data[ 'create_time' ] = time();
$res = $this->model->create($data);
// 关联备份记录
$is_need_backup = $data['is_need_backup'] ?? true;
if ($is_need_backup) {
( new BackupRecordsService() )->add([
'version' => $data[ 'current_version' ],
'backup_key' => $data[ 'upgrade_key' ],
'content' => '自动备份'
]);
}
return $res->id;
}
/**
* 编辑升级记录
* @param array $condition
* @param array $data
* @return true
*/
public function edit($condition, array $data)
{
$this->model->where($condition)->update($data);
return true;
}
/**
* 执行完成,更新升级记录状态,备份记录状态
* @param $upgrade_key
* @return void
*/
public function complete($upgrade_key)
{
// 记录升级日志
$this->edit([
[ 'upgrade_key', '=', $upgrade_key ]
], [
'status' => UpgradeDict::STATUS_COMPLETE,
'complete_time' => time()
]);
( new BackupRecordsService() )->complete($upgrade_key);
}
/**
* 执行失败,更新升级记录状态,备份记录状态
* @param $fail_reason
* @return void
*/
public function failed($upgrade_key, $fail_reason = [])
{
$this->model->where([ [ 'upgrade_key', '=', $upgrade_key ] ])->update(['status' => UpgradeDict::STATUS_FAIL, 'fail_reason' => $fail_reason ]);
( new BackupRecordsService() )->failed($upgrade_key);
}
/**
* 获取升级记录信息
* @param array $condition
* @param $field
* @return array
*/
public function getInfo(array $condition, $field = 'id, upgrade_key, app_key, name, content, prev_version, current_version, status, fail_reason, create_time, complete_time')
{
return $this->model->field($field)->where($condition)->findOrEmpty()->toArray();
}
/**
* 升级记录分页列表
* @param array $where
* @return array
*/
public function getPage(array $where = [])
{
$field = 'id, upgrade_key, app_key, name, content, prev_version, current_version, complete_time, create_time, status, fail_reason';
$order = "id desc";
$search_model = $this->model->where([
// [ 'status', '=', UpgradeDict::STATUS_COMPLETE ],
[ 'name|content|current_version', 'like', '%' . $where[ 'name' ] . '%' ]
])->field($field)->order($order)->append(['status_name']);
return $this->pageQuery($search_model);
}
/**
* 刪除升级记录
* @param $ids
* @return void
*/
public function del($ids) {
$this->model->where([['id', 'in', $ids]])->delete();
}
}

View File

@ -12,7 +12,10 @@
namespace app\service\admin\upgrade; namespace app\service\admin\upgrade;
use app\dict\addon\AddonDict; use app\dict\addon\AddonDict;
use app\dict\sys\BackupDict;
use app\dict\sys\UpgradeDict;
use app\model\addon\Addon; use app\model\addon\Addon;
use app\model\sys\SysBackupRecords;
use app\service\admin\install\InstallSystemService; use app\service\admin\install\InstallSystemService;
use app\service\admin\sys\ConfigService; use app\service\admin\sys\ConfigService;
use app\service\core\addon\CoreAddonCloudService; use app\service\core\addon\CoreAddonCloudService;
@ -22,13 +25,17 @@ use app\service\core\addon\CoreDependService;
use app\service\core\addon\WapTrait; use app\service\core\addon\WapTrait;
use app\service\core\channel\CoreH5Service; use app\service\core\channel\CoreH5Service;
use app\service\core\menu\CoreMenuService; use app\service\core\menu\CoreMenuService;
use app\service\core\niucloud\CoreCloudBuildService;
use app\service\core\niucloud\CoreModuleService; use app\service\core\niucloud\CoreModuleService;
use app\service\core\schedule\CoreScheduleInstallService; use app\service\core\schedule\CoreScheduleInstallService;
use core\base\BaseAdminService; use core\base\BaseAdminService;
use core\exception\CloudBuildException;
use core\exception\CommonException; use core\exception\CommonException;
use core\util\DbBackup;
use core\util\niucloud\BaseNiucloudClient; use core\util\niucloud\BaseNiucloudClient;
use think\facade\Cache; use think\facade\Cache;
use think\facade\Db; use think\facade\Db;
use think\facade\Log;
/** /**
* 框架及插件升级 * 框架及插件升级
@ -50,15 +57,17 @@ class UpgradeService extends BaseAdminService
protected $addon = ''; protected $addon = '';
private $steps = [ private $steps = [
'requestUpgrade' => ['step' => 'requestUpgrade', 'title' => '请求升级'], 'requestUpgrade' => [ 'step' => 'requestUpgrade', 'title' => '请求升级' ],
'downloadFile' => ['step' => 'downloadFile', 'title' => '下载更新文件'], 'downloadFile' => [ 'step' => 'downloadFile', 'title' => '' ],
'backupCode' => ['step' => 'backupCode', 'title' => '备份源码'], 'backupCode' => [ 'step' => 'backupCode', 'title' => '备份源码' ],
'backupSql' => ['step' => 'backupSql', 'title' => '备份数据库'], 'backupSql' => [ 'step' => 'backupSql', 'title' => '' ],
'coverCode' => ['step' => 'coverCode', 'title' => '合并更新文件'], 'coverCode' => [ 'step' => 'coverCode', 'title' => '合并更新文件' ],
'handleUniapp' => ['step' => 'handleUniapp', 'title' => '处理uniapp'], 'handleUniapp' => [ 'step' => 'handleUniapp', 'title' => '处理uniapp' ],
'refreshMenu' => ['step' => 'refreshMenu', 'title' => '刷新菜单'], 'refreshMenu' => [ 'step' => 'refreshMenu', 'title' => '刷新菜单' ],
'installSchedule' => ['step' => 'installSchedule', 'title' => '安装计划任务'], 'installSchedule' => [ 'step' => 'installSchedule', 'title' => '安装计划任务' ],
'upgradeComplete' => ['step' => 'upgradeComplete', 'title' => '升级完成'] 'cloudBuild' => [ 'step' => 'cloudBuild', 'title' => '开始云编译' ],
'gteCloudBuildLog' => [ 'step' => 'gteCloudBuildLog', 'title' => '' ],
'upgradeComplete' => [ 'step' => 'upgradeComplete', 'title' => '升级完成' ]
]; ];
public function __construct() public function __construct()
@ -68,6 +77,10 @@ class UpgradeService extends BaseAdminService
$this->root_path = dirname(root_path()) . DIRECTORY_SEPARATOR; $this->root_path = dirname(root_path()) . DIRECTORY_SEPARATOR;
$this->upgrade_dir = $this->root_path . 'upgrade' . DIRECTORY_SEPARATOR; $this->upgrade_dir = $this->root_path . 'upgrade' . DIRECTORY_SEPARATOR;
$this->upgrade_task = Cache::get($this->cache_key); $this->upgrade_task = Cache::get($this->cache_key);
if (!empty($this->upgrade_task) && !isset($this->upgrade_task[ 'upgrade_apps' ])) {
$this->upgrade_task[ 'upgrade_apps' ] = [ AddonDict::FRAMEWORK_KEY ];
}
} }
/** /**
@ -75,7 +88,8 @@ class UpgradeService extends BaseAdminService
* @param string $addon * @param string $addon
* @return void * @return void
*/ */
public function upgradePreCheck(string $addon = '') { public function upgradePreCheck(string $addon = '')
{
$niucloud_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR; $niucloud_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR;
$admin_dir = $this->root_path . 'admin' . DIRECTORY_SEPARATOR; $admin_dir = $this->root_path . 'admin' . DIRECTORY_SEPARATOR;
$web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR; $web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR;
@ -95,39 +109,62 @@ class UpgradeService extends BaseAdminService
] ]
]; ];
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $niucloud_dir), 'status' => is_readable($niucloud_dir)]; $data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $niucloud_dir), 'status' => is_readable($niucloud_dir) ];
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $admin_dir), 'status' => is_readable($admin_dir)]; $data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $admin_dir), 'status' => is_readable($admin_dir) ];
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $web_dir), 'status' => is_readable($web_dir)]; $data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $web_dir), 'status' => is_readable($web_dir) ];
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $wap_dir), 'status' => is_readable($wap_dir)]; $data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $wap_dir), 'status' => is_readable($wap_dir) ];
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $niucloud_dir), 'status' => is_write($niucloud_dir) ]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $niucloud_dir), 'status' => is_write($niucloud_dir) ];
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $admin_dir), 'status' => is_write($admin_dir) ]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $admin_dir), 'status' => is_write($admin_dir) ];
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $web_dir), 'status' => is_write($web_dir) ]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $web_dir), 'status' => is_write($web_dir) ];
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $wap_dir), 'status' => is_write($wap_dir) ]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $wap_dir), 'status' => is_write($wap_dir) ];
// 校验niucloud/public下 wap web admin 目录及文件是否可读可写 // 检测全部目录及文件是否可读可写,忽略指定目录
$check_res = checkDirPermissions(public_path() . 'wap');
$check_res = array_merge2($check_res, checkDirPermissions(public_path() . 'admin'));
$check_res = array_merge2($check_res, checkDirPermissions(public_path() . 'web'));
if (!empty($check_res['unreadable'])) { // 忽略指定目录admin
foreach ($check_res['unreadable'] as $item) { $exclude_admin_dir = [ 'dist', 'node_modules' ];
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $item),'status' => false]; $check_res = checkDirPermissions(project_path() . 'admin', [], $exclude_admin_dir);
// 忽略指定目录uni-app
$exclude_uniapp_dir = [ 'dist', 'node_modules' ];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'uni-app', [], $exclude_uniapp_dir));
// 忽略指定目录web
$exclude_web_dir = [ '.nuxt', '.output', 'dist', 'node_modules' ];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'web', [], $exclude_web_dir));
// 忽略指定目录niucloud
$exclude_niucloud_dir = [
'public' . DIRECTORY_SEPARATOR . 'admin',
'public' . DIRECTORY_SEPARATOR . 'wap',
'public' . DIRECTORY_SEPARATOR . 'web',
'public' . DIRECTORY_SEPARATOR . 'upload',
'public' . DIRECTORY_SEPARATOR . 'file',
'runtime',
'vendor',
'.user.ini'
];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'niucloud', [], $exclude_niucloud_dir));
if (!empty($check_res[ 'unreadable' ])) {
foreach ($check_res[ 'unreadable' ] as $item) {
$data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $item), 'status' => false ];
} }
} }
if (!empty($check_res['not_writable'])) { if (!empty($check_res[ 'not_writable' ])) {
foreach ($check_res['not_writable'] as $item) { foreach ($check_res[ 'not_writable' ] as $item) {
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $item),'status' => false]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $item), 'status' => false ];
} }
} }
$check_res = array_merge( $check_res = array_merge(
array_column($data['dir']['is_readable'], 'status'), array_column($data[ 'dir' ][ 'is_readable' ], 'status'),
array_column($data['dir']['is_write'], 'status') array_column($data[ 'dir' ][ 'is_write' ], 'status')
); );
// 是否通过校验 // 是否通过校验
$data['is_pass'] = !in_array(false, $check_res); $data[ 'is_pass' ] = !in_array(false, $check_res);
return $data; return $data;
} }
@ -136,31 +173,40 @@ class UpgradeService extends BaseAdminService
* @param $addon * @param $addon
* @return array * @return array
*/ */
public function upgrade(string $addon = '') { public function upgrade(string $addon = '', $data = [])
{
if ($this->upgrade_task) throw new CommonException('UPGRADE_TASK_EXIST'); if ($this->upgrade_task) throw new CommonException('UPGRADE_TASK_EXIST');
$upgrade_content = $this->getUpgradeContent($addon); $upgrade_content = $this->getUpgradeContent($addon);
if (empty($upgrade_content[ 'content' ])) throw new CommonException("NOT_EXIST_UPGRADE_CONTENT");
$upgrade = [ $upgrade = [
'product_key' => BaseNiucloudClient::PRODUCT, 'product_key' => BaseNiucloudClient::PRODUCT,
'framework_version' => config('version.version') 'framework_version' => config('version.version')
]; ];
if (!$addon) {
$upgrade['app_key'] = AddonDict::FRAMEWORK_KEY;
$upgrade['version'] = config('version.version');
} else {
$upgrade['app_key'] = $addon;
$upgrade['version'] = (new Addon())->where([ ['key', '=', $addon] ])->value('version');
// 判断框架版本是否低于插件支持版本 $upgrade[ 'app_key' ] = $upgrade_content[ 'content' ][ 0 ][ 'app' ][ 'app_key' ];
$last_version = $upgrade_content['version_list'][ count($upgrade_content['version_list']) - 1]; $upgrade[ 'version' ] = $upgrade_content[ 'content' ][ 0 ][ 'version' ];
if (str_replace('.', '', config('version.version')) < str_replace('.', '', $last_version['niucloud_version']['version_no'])) {
throw new CommonException('BEFORE_UPGRADING_NEED_UPGRADE_FRAMEWORK'); if (!$addon) {
} $upgrade_title = '框架';
// $upgrade[ 'app_key' ] = AddonDict::FRAMEWORK_KEY;
$upgrade[ 'version' ] = config('version.version');
} else {
// $upgrade[ 'app_key' ] = $addon;
// $upgrade[ 'version' ] = ( new Addon() )->where([ [ 'key', '=', $addon ] ])->value('version');
$upgrade_title = ( new Addon() )->where([ [ 'key', 'in', $addon ] ])->field('title')->select()->toArray();
$upgrade_title = implode(',', array_column($upgrade_title, 'title'));
//
// // 判断框架版本是否低于插件支持版本
// $last_version = $upgrade_content[ 'version_list' ][ count($upgrade_content[ 'version_list' ]) - 1 ];
// if (str_replace('.', '', config('version.version')) < str_replace('.', '', $last_version[ 'niucloud_version' ][ 'version_no' ])) {
// throw new CommonException('BEFORE_UPGRADING_NEED_UPGRADE_FRAMEWORK');
// }
} }
$response = (new CoreAddonCloudService())->upgradeAddon($upgrade); $response = ( new CoreAddonCloudService() )->upgradeAddon($upgrade);
if (isset($response['code']) && $response['code'] == 0) throw new CommonException($response['msg']); if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
try { try {
$key = uniqid(); $key = uniqid();
@ -170,17 +216,42 @@ class UpgradeService extends BaseAdminService
dir_mkdir($upgrade_dir); dir_mkdir($upgrade_dir);
} }
// 是否需要备份
$is_need_backup = $data[ 'is_need_backup' ] ?? true;
if (!$is_need_backup) {
unset($this->steps[ 'backupCode' ]);
unset($this->steps[ 'backupSql' ]);
}
$upgrade_task = [ $upgrade_task = [
'key' => $key, 'key' => $key,
'upgrade' => $upgrade, 'upgrade' => $upgrade,
'steps' => $this->steps, 'steps' => $this->steps,
'step' => 'requestUpgrade', 'step' => 'requestUpgrade',
'executed' => ['requestUpgrade'], 'executed' => [ 'requestUpgrade' ],
'log' => [ $this->steps['requestUpgrade']['title'] ], 'log' => [ $this->steps[ 'requestUpgrade' ][ 'title' ] ],
'params' => ['token' => $response['token'] ], 'params' => [ 'app_key' => $upgrade[ 'app_key' ], 'token' => $response[ 'token' ] ],
'upgrade_content' => $upgrade_content 'upgrade_content' => $upgrade_content,
'upgrade_apps' => $upgrade_content[ 'upgrade_apps' ],
'is_need_backup' => $is_need_backup
]; ];
foreach ($upgrade_content[ 'content' ] as $k => $v) {
unset($upgrade_content[ 'content' ][ $k ][ 'version_list' ]);
}
// 记录升级日志
( new UpgradeRecordsService() )->add([
'upgrade_key' => $upgrade_task[ 'key' ],
'app_key' => $upgrade[ 'app_key' ],
'name' => $upgrade_title,
'content' => json_encode($upgrade_content),
'prev_version' => "",
'current_version' => "",
'status' => UpgradeDict::STATUS_READY,
'is_need_backup' => $is_need_backup
]);
Cache::set($this->cache_key, $upgrade_task); Cache::set($this->cache_key, $upgrade_task);
return $upgrade_task; return $upgrade_task;
} catch (\Exception $e) { } catch (\Exception $e) {
@ -192,33 +263,59 @@ class UpgradeService extends BaseAdminService
* 执行升级 * 执行升级
* @return true * @return true
*/ */
public function execute() { public function execute()
{
if (!$this->upgrade_task) return true; if (!$this->upgrade_task) return true;
$steps = isset($this->upgrade_task['steps']) ? array_keys($this->upgrade_task['steps']) : array_keys($this->steps); $steps = isset($this->upgrade_task[ 'steps' ]) ? array_keys($this->upgrade_task[ 'steps' ]) : array_keys($this->steps);
if (isset($this->upgrade_task['steps'])) $this->steps = $this->upgrade_task['steps']; if (isset($this->upgrade_task[ 'steps' ])) $this->steps = $this->upgrade_task[ 'steps' ];
$index = array_search($this->upgrade_task['step'], $steps); $index = array_search($this->upgrade_task[ 'step' ], $steps);
$step = $steps[ $index + 1 ] ?? ''; $step = $steps[ $index + 1 ] ?? '';
$params = $this->upgrade_task['params'] ?? []; $params = $this->upgrade_task[ 'params' ] ?? [];
if ($step) { if ($step) {
try { try {
$res = $this->$step(...$params); $res = $this->$step(...$params);
if (is_array($res)) { if (is_array($res)) {
$this->upgrade_task['params'] = $res; $this->upgrade_task[ 'params' ] = $res;
} else { } else {
$this->upgrade_task['step'] = $step; $this->upgrade_task[ 'step' ] = $step;
$this->upgrade_task['params'] = []; $this->upgrade_task[ 'params' ] = [];
$this->upgrade_task['executed'][] = $step; $this->upgrade_task[ 'executed' ][] = $step;
$this->upgrade_task['log'][] = $this->steps[$step]['title']; if (!empty($this->steps[ $step ][ 'title' ])) {
$this->upgrade_task[ 'log' ][] = $this->steps[ $step ][ 'title' ];
}
} }
Cache::set($this->cache_key, $this->upgrade_task); if (!in_array($step, [ 'upgradeComplete', 'restoreComplete' ])) {
Cache::set($this->cache_key, $this->upgrade_task);
} else {
$this->clearUpgradeTask(2);
}
} catch (CloudBuildException $e) {
if (strpos($e->getMessage(), '队列') !== false) {
throw new CloudBuildException($e->getMessage());
}
$this->upgrade_task[ 'step' ] = $step;
$this->upgrade_task[ 'error' ][] = '升级失败,失败原因:' . $e->getMessage() . $e->getFile() . $e->getLine();
$fail_reason = [
'Message' => '失败原因:' . $e->getMessage(),
'File' => '文件:' . $e->getFile(),
'Line' => '代码行号:' . $e->getLine(),
'Trace' => $e->getTrace()
];
$this->upgradeErrorHandle($fail_reason);
} catch (\Exception $e) { } catch (\Exception $e) {
$this->upgrade_task['step'] = $step; $this->upgrade_task[ 'step' ] = $step;
$this->upgrade_task['error'][] = '升级失败,失败原因:' . $e->getMessage().$e->getFile().$e->getLine(); $this->upgrade_task[ 'error' ][] = '升级失败,失败原因:' . $e->getMessage() . $e->getFile() . $e->getLine();
Cache::set($this->cache_key, $this->upgrade_task); $fail_reason = [
$this->upgradeErrorHandle(); 'Message' => '失败原因:' . $e->getMessage(),
'File' => '文件:' . $e->getFile(),
'Line' => '代码行号:' . $e->getLine(),
'Trace' => $e->getTrace()
];
$this->upgradeErrorHandle($fail_reason);
} }
return true; return true;
} else { } else {
@ -234,12 +331,35 @@ class UpgradeService extends BaseAdminService
* @param $step * @param $step
* @return true|null * @return true|null
*/ */
public function downloadFile(string $token, string $dir = '', int $index = -1, $step = 0, $length = 0) { public function downloadFile(string $app_key, string $token, string $dir = '', int $index = -1, $step = 0, $length = 0)
{
if (!$dir) { if (!$dir) {
$dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR; $dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . $app_key . DIRECTORY_SEPARATOR;
dir_mkdir($dir); dir_mkdir($dir);
} }
$res = (new CoreAddonCloudService())->downloadUpgradeFile($token, $dir, $index, $step, $length); $res = ( new CoreAddonCloudService() )->downloadUpgradeFile($app_key, $token, $dir, $index, $step, $length);
if ($res === true) {
$index = array_search($app_key, $this->upgrade_task[ 'upgrade_apps' ]);
if ($app_key == AddonDict::FRAMEWORK_KEY) {
$this->upgrade_task[ 'log' ][] = "下载更新文件";
} else {
$this->upgrade_task[ 'log' ][] = "下载" . $this->upgrade_task[ 'upgrade_content' ][ 'content' ][ $index ][ 'app' ][ 'app_name' ] . "更新文件";
}
$index++;
if (isset($this->upgrade_task[ 'upgrade_apps' ][ $index ])) {
$upgrade = [
'product_key' => BaseNiucloudClient::PRODUCT,
'framework_version' => config('version.version'),
'app_key' => $this->upgrade_task[ 'upgrade_content' ][ 'content' ][ $index ][ 'app' ][ 'app_key' ],
'version' => $this->upgrade_task[ 'upgrade_content' ][ 'content' ][ $index ][ 'version' ]
];
$response = ( new CoreAddonCloudService() )->upgradeAddon($upgrade);
if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
return [ 'app_key' => $upgrade[ 'app_key' ], 'token' => $response[ 'token' ] ];
}
}
return $res; return $res;
} }
@ -247,8 +367,9 @@ class UpgradeService extends BaseAdminService
* 备份源码 * 备份源码
* @return true * @return true
*/ */
public function backupCode() { public function backupCode()
(new BackupService())->backupCode(); {
( new BackupService() )->backupCode();
return true; return true;
} }
@ -256,24 +377,52 @@ class UpgradeService extends BaseAdminService
* 备份数据库 * 备份数据库
* @return true * @return true
*/ */
public function backupSql() { public function backupSql($index = 0)
(new BackupService())->backupSql(); {
return true; $backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
// 创建目录
dir_mkdir($backup_dir);
$db = new DbBackup($backup_dir, 1024 * 1024 * 2, key: $this->upgrade_task[ 'key' ]);
$prefix = config('database.connections.' . config('database.default'))[ 'prefix' ];
// 不需要备份的表
$not_need_backup = [
"{$prefix}sys_schedule_log",
"{$prefix}sys_user_log",
"{$prefix}jobs",
"{$prefix}jobs_failed",
"{$prefix}sys_upgrade_records",
"{$prefix}sys_backup_records"
];
$result = $db->setExcludeTables($not_need_backup)->backupDatabaseSegment();
if ($db->getBackupProgress() == 100) {
$this->upgrade_task[ 'log' ][] = "数据库备份完成";
} else {
$this->upgrade_task[ 'log' ][] = $db->getBackupProgress() == 0 ? '数据库开始备份' : '数据库备份已备份' . $db->getBackupProgress() . '%';
}
if ($result === true) return true;
return [ 'index' => $result ];
} }
/** /**
* 覆盖更新升级的代码 * 覆盖更新升级的代码
* @return void * @return void
*/ */
public function coverCode($index = 0) { public function coverCode($index = 0, $addon = "")
$this->upgrade_task['is_cover'] = 1; {
$addon = $this->upgrade_task['upgrade']['app_key']; $this->upgrade_task[ 'is_cover' ] = 1;
if (empty($addon)) $addon = $this->upgrade_task[ 'upgrade_apps' ][ 0 ];
$version_list = array_reverse($this->upgrade_task['upgrade_content']['version_list']); $app_index = array_search($addon, $this->upgrade_task[ 'upgrade_apps' ]);
$code_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
$version_item = $version_list[$index]; $version_list = array_reverse($this->upgrade_task[ 'upgrade_content' ][ 'content' ][ $app_index ][ 'version_list' ]);
$version_no = $version_item['version_no']; $code_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
$version_item = $version_list[ $index ];
$version_no = $version_item[ 'version_no' ];
$to_dir = $addon == AddonDict::FRAMEWORK_KEY ? rtrim($this->root_path, DIRECTORY_SEPARATOR) : $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR . 'addon' . DIRECTORY_SEPARATOR . $addon; $to_dir = $addon == AddonDict::FRAMEWORK_KEY ? rtrim($this->root_path, DIRECTORY_SEPARATOR) : $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR . 'addon' . DIRECTORY_SEPARATOR . $addon;
@ -293,20 +442,20 @@ class UpgradeService extends BaseAdminService
// 覆盖文件 // 覆盖文件
if (is_dir($code_dir . $version_no)) { if (is_dir($code_dir . $version_no)) {
// 忽略环境变量文件 // 忽略环境变量文件
$exclude_files = ['.env.development', '.env.production', '.env', '.env.dev', '.env.product']; $exclude_files = [ '.env.development', '.env.production', '.env', '.env.dev', '.env.product' ];
dir_copy($code_dir . $version_no, $to_dir, exclude_files:$exclude_files); dir_copy($code_dir . $version_no, $to_dir, exclude_files: $exclude_files);
if ($addon != AddonDict::FRAMEWORK_KEY) { if ($addon != AddonDict::FRAMEWORK_KEY) {
(new CoreAddonInstallService($addon))->installDir(); ( new CoreAddonInstallService($addon) )->installDir();
} }
} }
$upgrade_file_dir = 'v' . str_replace('.', '', $version_no); $upgrade_file_dir = 'v' . str_replace('.', '', $version_no);
if ($addon == AddonDict::FRAMEWORK_KEY) { if ($addon == AddonDict::FRAMEWORK_KEY) {
$class_path = "\\app\\upgrade\\{$upgrade_file_dir}\\Upgrade"; $class_path = "\\app\\upgrade\\{$upgrade_file_dir}\\Upgrade";
$sql_file = root_path() . 'app' . DIRECTORY_SEPARATOR . 'upgrade' . DIRECTORY_SEPARATOR . $upgrade_file_dir . DIRECTORY_SEPARATOR . 'upgrade.sql'; $sql_file = root_path() . 'app' . DIRECTORY_SEPARATOR . 'upgrade' . DIRECTORY_SEPARATOR . $upgrade_file_dir . DIRECTORY_SEPARATOR . 'upgrade.sql';
} else { } else {
$class_path = "\\addon\\{$addon}\\app\\upgrade\\{$upgrade_file_dir}\\Upgrade"; $class_path = "\\addon\\{$addon}\\app\\upgrade\\{$upgrade_file_dir}\\Upgrade";
$sql_file = root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'upgrade' . DIRECTORY_SEPARATOR . $upgrade_file_dir . DIRECTORY_SEPARATOR . 'upgrade.sql'; $sql_file = root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'upgrade' . DIRECTORY_SEPARATOR . $upgrade_file_dir . DIRECTORY_SEPARATOR . 'upgrade.sql';
} }
// 执行升级sql // 执行升级sql
@ -316,13 +465,17 @@ class UpgradeService extends BaseAdminService
// 执行升级方法 // 执行升级方法
if (class_exists($class_path)) { if (class_exists($class_path)) {
(new $class_path())->handle(); ( new $class_path() )->handle();
} }
$index ++; $index++;
if ($index < count($version_list)) { if ($index < count($version_list)) {
return compact('index'); return compact('index', 'addon');
} else { } else {
$app_index++;
if (isset($this->upgrade_task[ 'upgrade_apps' ][ $app_index ])) {
return [ 'index' => 0, 'addon' => $this->upgrade_task[ 'upgrade_apps' ][ $app_index ] ];
}
return true; return true;
} }
} }
@ -332,8 +485,9 @@ class UpgradeService extends BaseAdminService
* @param string $version_no * @param string $version_no
* @return void * @return void
*/ */
public function installDepend(string $dir, array $change_files) { public function installDepend(string $dir, array $change_files)
$addon = $this->upgrade_task['upgrade']['app_key']; {
$addon = $this->upgrade_task[ 'upgrade' ][ 'app_key' ];
$depend_service = new CoreDependService(); $depend_service = new CoreDependService();
if ($addon == AddonDict::FRAMEWORK_KEY) { if ($addon == AddonDict::FRAMEWORK_KEY) {
@ -352,7 +506,7 @@ class UpgradeService extends BaseAdminService
$original = $depend_service->getComposerContent(); $original = $depend_service->getComposerContent();
$new = $depend_service->jsonFileToArray($dir . $composer); $new = $depend_service->jsonFileToArray($dir . $composer);
foreach ($new as $name => $value) { foreach ($new as $name => $value) {
$original[$name] = isset($original[$name]) && is_array($original[$name]) ? array_merge($original[$name], $new[$name]) : $new[$name]; $original[ $name ] = isset($original[ $name ]) && is_array($original[ $name ]) ? array_map('unserialize', array_unique(array_map('serialize', array_merge($original[ $name ], $new[ $name ])))) : $new[ $name ];
} }
$depend_service->writeArrayToJsonFile($original, $dir . $composer); $depend_service->writeArrayToJsonFile($original, $dir . $composer);
} }
@ -361,7 +515,7 @@ class UpgradeService extends BaseAdminService
$new = $depend_service->jsonFileToArray($dir . $admin_package); $new = $depend_service->jsonFileToArray($dir . $admin_package);
foreach ($new as $name => $value) { foreach ($new as $name => $value) {
$original[$name] = isset($original[$name]) && is_array($original[$name]) ? array_merge($original[$name], $new[$name]) : $new[$name]; $original[ $name ] = isset($original[ $name ]) && is_array($original[ $name ]) ? array_merge($original[ $name ], $new[ $name ]) : $new[ $name ];
} }
$depend_service->writeArrayToJsonFile($original, $dir . $admin_package); $depend_service->writeArrayToJsonFile($original, $dir . $admin_package);
} }
@ -370,7 +524,7 @@ class UpgradeService extends BaseAdminService
$new = $depend_service->jsonFileToArray($dir . $web_package); $new = $depend_service->jsonFileToArray($dir . $web_package);
foreach ($new as $name => $value) { foreach ($new as $name => $value) {
$original[$name] = isset($original[$name]) && is_array($original[$name]) ? array_merge($original[$name], $new[$name]) : $new[$name]; $original[ $name ] = isset($original[ $name ]) && is_array($original[ $name ]) ? array_merge($original[ $name ], $new[ $name ]) : $new[ $name ];
} }
$depend_service->writeArrayToJsonFile($original, $dir . $web_package); $depend_service->writeArrayToJsonFile($original, $dir . $web_package);
} }
@ -379,7 +533,7 @@ class UpgradeService extends BaseAdminService
$new = $depend_service->jsonFileToArray($dir . $uniapp_package); $new = $depend_service->jsonFileToArray($dir . $uniapp_package);
foreach ($new as $name => $value) { foreach ($new as $name => $value) {
$original[$name] = isset($original[$name]) && is_array($original[$name]) ? array_merge($original[$name], $new[$name]) : $new[$name]; $original[ $name ] = isset($original[ $name ]) && is_array($original[ $name ]) ? array_merge($original[ $name ], $new[ $name ]) : $new[ $name ];
} }
$depend_service->writeArrayToJsonFile($original, $dir . $uniapp_package); $depend_service->writeArrayToJsonFile($original, $dir . $uniapp_package);
} }
@ -390,12 +544,15 @@ class UpgradeService extends BaseAdminService
* @param string $verson_no * @param string $verson_no
* @return true * @return true
*/ */
public function handleUniapp() { public function handleUniapp()
$code_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR; {
$exclude_files = ['.env.development', '.env.production', 'manifest.json']; $key = end($this->upgrade_task[ 'upgrade_apps' ]);
dir_copy($code_dir . 'uni-app', $this->root_path . 'uni-app', exclude_files:$exclude_files);
$addon_list = (new CoreAddonService())->getInstallAddonList(); $code_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . $key . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
$exclude_files = [ '.env.development', '.env.production', 'manifest.json' ];
dir_copy($code_dir . 'uni-app', $this->root_path . 'uni-app', exclude_files: $exclude_files);
$addon_list = ( new CoreAddonService() )->getInstallAddonList();
$depend_service = new CoreDependService(); $depend_service = new CoreDependService();
if (!empty($addon_list)) { if (!empty($addon_list)) {
@ -420,7 +577,7 @@ class UpgradeService extends BaseAdminService
$new = $depend_service->jsonFileToArray($addon_uniapp_package); $new = $depend_service->jsonFileToArray($addon_uniapp_package);
foreach ($new as $name => $value) { foreach ($new as $name => $value) {
$original[$name] = isset($original[$name]) && is_array($original[$name]) ? array_merge($original[$name], $new[$name]) : $new[$name]; $original[ $name ] = isset($original[ $name ]) && is_array($original[ $name ]) ? array_merge($original[ $name ], $new[ $name ]) : $new[ $name ];
} }
$uniapp_package = $this->root_path . 'uni-app' . DIRECTORY_SEPARATOR . 'package.json'; $uniapp_package = $this->root_path . 'uni-app' . DIRECTORY_SEPARATOR . 'package.json';
@ -429,7 +586,7 @@ class UpgradeService extends BaseAdminService
} }
} }
$map = (new ConfigService())->getMap(); $map = ( new ConfigService() )->getMap();
( new CoreH5Service() )->mapKeyChange($map[ 'key' ]); ( new CoreH5Service() )->mapKeyChange($map[ 'key' ]);
return true; return true;
@ -440,7 +597,8 @@ class UpgradeService extends BaseAdminService
* @param string $sql_file * @param string $sql_file
* @return true * @return true
*/ */
private function executeSql(string $sql_file) { private function executeSql(string $sql_file)
{
$sql_content = file_get_contents($sql_file); $sql_content = file_get_contents($sql_file);
if (!empty($sql_content)) { if (!empty($sql_content)) {
@ -461,11 +619,20 @@ class UpgradeService extends BaseAdminService
* 刷新菜单 * 刷新菜单
* @return void * @return void
*/ */
public function refreshMenu() { public function refreshMenu($addon = "")
if ($this->upgrade_task['upgrade']['app_key'] == AddonDict::FRAMEWORK_KEY) { {
(new InstallSystemService())->installMenu(); if (empty($addon)) $addon = $this->upgrade_task[ 'upgrade_apps' ][ 0 ];
$app_index = array_search($addon, $this->upgrade_task[ 'upgrade_apps' ]);
if ($addon == AddonDict::FRAMEWORK_KEY) {
( new InstallSystemService() )->installMenu();
} else { } else {
(new CoreMenuService())->refreshAddonMenu($this->upgrade_task['upgrade']['app_key']); ( new CoreMenuService() )->refreshAddonMenu($addon);
}
$app_index++;
if (isset($this->upgrade_task[ 'upgrade_apps' ][ $app_index ])) {
return [ 'addon' => $this->upgrade_task[ 'upgrade_apps' ][ $app_index ] ];
} }
return true; return true;
} }
@ -474,28 +641,88 @@ class UpgradeService extends BaseAdminService
* 安装计划任务 * 安装计划任务
* @return true * @return true
*/ */
public function installSchedule() { public function installSchedule($addon = "")
if ($this->upgrade_task['upgrade']['app_key'] == AddonDict::FRAMEWORK_KEY) { {
(new CoreScheduleInstallService())->installSystemSchedule(); if (empty($addon)) $addon = $this->upgrade_task[ 'upgrade_apps' ][ 0 ];
$app_index = array_search($addon, $this->upgrade_task[ 'upgrade_apps' ]);
if ($addon == AddonDict::FRAMEWORK_KEY) {
( new CoreScheduleInstallService() )->installSystemSchedule();
} else { } else {
(new CoreScheduleInstallService())->installAddonSchedule($this->upgrade_task['upgrade']['app_key']); ( new CoreScheduleInstallService() )->installAddonSchedule($addon);
}
$app_index++;
if (isset($this->upgrade_task[ 'upgrade_apps' ][ $app_index ])) {
return [ 'addon' => $this->upgrade_task[ 'upgrade_apps' ][ $app_index ] ];
} }
return true; return true;
} }
/**
* 云编译
* @return void
*/
public function cloudBuild()
{
( new CoreCloudBuildService() )->cloudBuild();
}
/**
* 获取云编译日志
* @return void
*/
public function gteCloudBuildLog()
{
$log = ( new CoreCloudBuildService() )->getBuildLog();
if (empty($log)) return true;
foreach ($log[ 'data' ][ 0 ] as $item) {
if ($item[ 'code' ] == 0) {
$this->upgrade_task[ 'step' ] = 'gteCloudBuildLog';
$this->upgrade_task[ 'error' ][] = $item[ 'msg' ];
Cache::set($this->cache_key, $this->upgrade_task);
$fail_reason = [
'Message' => '失败原因 云编译错误:' . $item[ 'msg' ],
'File' => '',
'Line' => '',
'Trace' => ''
];
( new CoreCloudBuildService() )->clearTask();
$this->upgradeErrorHandle($fail_reason);
return true;
}
if (!in_array($item[ 'action' ], $this->upgrade_task[ 'log' ])) {
$this->upgrade_task[ 'log' ][] = $item[ 'action' ];
Cache::set($this->cache_key, $this->upgrade_task);
}
}
sleep(2);
return [];
}
/** /**
* 更新完成 * 更新完成
* @return void * @return void
*/ */
public function upgradeComplete() { public function upgradeComplete()
$addon = $this->upgrade_task['upgrade']['app_key']; {
if ($addon != AddonDict::FRAMEWORK_KEY) { foreach ($this->upgrade_task[ 'upgrade_apps' ] as $addon) {
$core_addon_service = new CoreAddonService(); if ($addon != AddonDict::FRAMEWORK_KEY) {
$install_data = $core_addon_service->getAddonConfig($addon); $core_addon_service = new CoreAddonService();
$install_data['icon'] = 'addon/' . $addon . '/icon.png'; $install_data = $core_addon_service->getAddonConfig($addon);
$core_addon_service->set($install_data); $install_data[ 'icon' ] = 'addon/' . $addon . '/icon.png';
$core_addon_service->set($install_data);
}
} }
$this->clearUpgradeTask(5); // 执行完成,更新升级记录状态,备份记录状态
( new UpgradeRecordsService() )->complete($this->upgrade_task[ 'key' ]);
$this->clearUpgradeTask(2);
return true; return true;
} }
@ -503,30 +730,41 @@ class UpgradeService extends BaseAdminService
* 升级出错之后的处理 * 升级出错之后的处理
* @return true|void * @return true|void
*/ */
public function upgradeErrorHandle() { public function upgradeErrorHandle($fail_reason = [])
{
$steps = []; $steps = [];
$steps[$this->upgrade_task['step']] = []; $steps[ $this->upgrade_task[ 'step' ] ] = [];
if (isset($this->upgrade_task['is_cover'])) { if (isset($this->upgrade_task[ 'is_cover' ])) {
$steps['restoreCode'] = ['step' => 'restoreCode', 'title' => '恢复源码备份']; $steps[ 'restoreCode' ] = [ 'step' => 'restoreCode', 'title' => '恢复源码备份' ];
$steps['restoreSql'] = ['step' => 'restoreSql', 'title' => '恢复数据库备份']; $steps[ 'restoreSql' ] = [ 'step' => 'restoreSql', 'title' => '恢复数据库备份' ];
} }
$steps['restoreComplete'] = ['step' => 'restoreComplete', 'title' => '备份恢复完成']; $steps[ 'restoreComplete' ] = [ 'step' => 'restoreComplete', 'title' => '备份恢复完成' ];
$this->upgrade_task['steps'] = $steps; $this->upgrade_task[ 'steps' ] = $steps;
$this->upgrade_task[ 'params' ] = [];
Cache::set($this->cache_key, $this->upgrade_task); Cache::set($this->cache_key, $this->upgrade_task);
Log::write('升级出错之后的处理:' . json_encode($fail_reason));
} }
/** /**
* 恢复源码 * 恢复源码
* @return void * @return void
*/ */
public function restoreCode() { public function restoreCode()
{
if ($this->upgrade_task[ 'is_need_backup' ]) {
$backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
} else {
$backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'upgrade_content' ][ 'last_backup' ][ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
}
try { try {
(new RestoreService())->restoreCode(); if (is_dir($backup_dir)) {
dir_copy($backup_dir, rtrim($this->root_path, DIRECTORY_SEPARATOR));
}
return true; return true;
} catch (\Exception $e) { } catch (\Exception $e) {
$backup_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR; $this->upgrade_task[ 'error' ][] = '源码备份恢复失败稍后请手动恢复,源码备份文件路径:' . $backup_dir . ',失败原因:' . $e->getMessage() . $e->getFile() . $e->getLine();
$this->upgrade_task['error'][] = '源码备份恢复失败稍后请手动恢复,源码备份文件路径:'. $backup_dir .',失败原因:' . $e->getMessage().$e->getFile().$e->getLine();
Cache::set($this->cache_key, $this->upgrade_task); Cache::set($this->cache_key, $this->upgrade_task);
return true; return true;
} }
@ -536,20 +774,32 @@ class UpgradeService extends BaseAdminService
* 恢复数据库 * 恢复数据库
* @return void * @return void
*/ */
public function restoreSql() { public function restoreSql($index = 0)
{
if ($this->upgrade_task[ 'is_need_backup' ]) {
$backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
} else {
$backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'upgrade_content' ][ 'last_backup' ][ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
}
try { try {
(new RestoreService())->restoreSql(); if (is_dir($backup_dir)) {
$db = new DbBackup($backup_dir, key: $this->upgrade_task[ 'key' ]);
$result = $db->restoreDatabase();
if ($result !== true) return [ 'index' => $result ];
}
return true; return true;
} catch (\Exception $e) { } catch (\Exception $e) {
$backup_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR; $this->upgrade_task[ 'error' ][] = '数据库备份恢复失败稍后请手动恢复,数据库备份文件路径:' . $backup_dir . ',失败原因:' . $e->getMessage() . $e->getFile() . $e->getLine();
$this->upgrade_task['error'][] = '数据库备份恢复失败稍后请手动恢复,数据库备份文件路径:'. $backup_dir .',失败原因:' . $e->getMessage().$e->getFile().$e->getLine();
Cache::set($this->cache_key, $this->upgrade_task); Cache::set($this->cache_key, $this->upgrade_task);
return true; return true;
} }
} }
public function restoreComplete() { public function restoreComplete()
$this->clearUpgradeTask(5); {
( new UpgradeRecordsService() )->failed($this->upgrade_task[ 'key' ], $this->upgrade_task[ 'error' ]);
$this->clearUpgradeTask(2);
return true; return true;
} }
@ -559,26 +809,56 @@ class UpgradeService extends BaseAdminService
* @return array|\core\util\niucloud\Response|object|\Psr\Http\Message\ResponseInterface * @return array|\core\util\niucloud\Response|object|\Psr\Http\Message\ResponseInterface
* @throws \GuzzleHttp\Exception\GuzzleException * @throws \GuzzleHttp\Exception\GuzzleException
*/ */
public function getUpgradeContent(string $addon = '') { public function getUpgradeContent(string $addon = '')
{
$content = [
'content' => [],
'upgrade_apps' => []
];
$upgrade = [ $upgrade = [
'product_key' => BaseNiucloudClient::PRODUCT 'product_key' => BaseNiucloudClient::PRODUCT
]; ];
$apps = [];
if (!$addon) { if (!$addon) {
$upgrade['app_key'] = AddonDict::FRAMEWORK_KEY; $upgrade[ 'app_key' ] = AddonDict::FRAMEWORK_KEY;
$upgrade['version'] = config('version.version'); $upgrade[ 'version' ] = config('version.version');
array_push($apps, $upgrade);
} else { } else {
$upgrade['app_key'] = $addon; $addons = array_filter(explode(',', $addon));
$upgrade['version'] = (new Addon())->where([ ['key', '=', $addon] ])->value('version'); foreach ($addons as $key) {
$info = ( new Addon() )->where([ [ 'key', '=', $key ] ])->field('version,type')->find();
$upgrade[ 'app_key' ] = $key;
$upgrade[ 'version' ] = $info[ 'version' ];
if ($info[ 'type' ] == 'app') {
array_unshift($apps, $upgrade);
} else {
array_push($apps, $upgrade);
}
}
} }
return (new CoreModuleService())->getUpgradeContent($upgrade)['data'] ?? []; foreach ($apps as $item) {
$upgrade_content = ( new CoreModuleService() )->getUpgradeContent($item)[ 'data' ] ?? [];
if (!empty($upgrade_content)) {
$content[ 'content' ][] = $upgrade_content;
$content[ 'upgrade_apps' ][] = $upgrade_content[ 'app' ][ 'app_key' ];
}
}
if (!empty($content[ 'content' ])) {
$content[ 'last_backup' ] = ( new SysBackupRecords() )->where([ [ 'status', '=', BackupDict::STATUS_COMPLETE ] ])->order('complete_time desc')->find();
}
return $content;
} }
/** /**
* 获取正在进行的升级任务 * 获取正在进行的升级任务
* @return mixed|null * @return mixed|null
*/ */
public function getUpgradeTask() { public function getUpgradeTask()
{
return $this->upgrade_task; return $this->upgrade_task;
} }
@ -586,12 +866,20 @@ class UpgradeService extends BaseAdminService
* 清除升级任务 * 清除升级任务
* @return true * @return true
*/ */
public function clearUpgradeTask(int $delayed = 0) { public function clearUpgradeTask(int $delayed = 0, int $is_active = 0)
{
// 主动取消升级
if ($is_active && $this->upgrade_task && !empty($this->upgrade_task[ 'key' ])) {
( new UpgradeRecordsService() )->edit([ [ 'upgrade_key', '=', $this->upgrade_task[ 'key' ] ], [ 'status', '=', UpgradeDict::STATUS_READY ] ], [ 'status' => UpgradeDict::STATUS_CANCEL ]);
}
if ($delayed) { if ($delayed) {
Cache::set($this->cache_key, $this->upgrade_task, $delayed); Cache::set($this->cache_key, $this->upgrade_task, $delayed);
} else { } else {
Cache::set($this->cache_key, null); Cache::set($this->cache_key, null);
} }
// 清除云编译的任务缓存
( new CoreCloudBuildService() )->clearTask();
return true; return true;
} }
@ -602,6 +890,32 @@ class UpgradeService extends BaseAdminService
*/ */
public function geAddonPackagePath(string $addon) public function geAddonPackagePath(string $addon)
{ {
return root_path() . 'addon' .DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR; return root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR . 'package' . DIRECTORY_SEPARATOR;
}
/**
* 用户操作
* @param $operate
* @return void
*/
public function operate($operate)
{
if (!$this->upgrade_task) return true;
switch ($operate) {
case 'local':
$this->upgrade_task[ 'step' ] = 'gteCloudBuildLog';
Cache::set($this->cache_key, $this->upgrade_task);
break;
case 'rollback':
$fail_reason = [
'Message' => '失败原因:一键云编译队列任务过多',
'File' => '',
'Line' => '',
'Trace' => ''
];
$this->upgradeErrorHandle($fail_reason);
break;
}
} }
} }

View File

@ -37,9 +37,9 @@ class VerifierService extends BaseAdminService
*/ */
public function getPage(array $where = []) public function getPage(array $where = [])
{ {
$search_model = $this->model->where([ ['id', '>', 0] ])->with(['member' => function($query){ $search_model = $this->model->where([ [ 'id', '>', 0 ] ])->with([ 'member' => function ($query) {
$query->field('member_id, nickname, mobile, headimg'); $query->field('member_id, nickname, mobile, headimg');
}])->field('*')->order('create_time desc'); } ])->field('*')->order('create_time desc');
return $this->pageQuery($search_model, function ($item, $key) { return $this->pageQuery($search_model, function ($item, $key) {
$item = $this->makeUp($item); $item = $this->makeUp($item);
}); });
@ -52,31 +52,39 @@ class VerifierService extends BaseAdminService
*/ */
public function getList(array $where = []) public function getList(array $where = [])
{ {
return $this->model->where([['id', '>', 0]])->with(['member' => function ($query) { return $this->model->where([ [ 'id', '>', 0 ] ])->with([ 'member' => function ($query) {
$query->field('member_id, nickname, mobile, headimg'); $query->field('member_id, nickname, mobile, headimg');
}])->field('*')->order('create_time desc')->select()->toArray(); } ])->field('*')->order('create_time desc')->select()->toArray();
} }
/** /**
* 组合整理数据 * 组合整理数据
* @param $data * @param $data
*/ */
public function makeUp($data){ public function makeUp($data)
{
//核销类型 //核销类型
if(!empty($data['verify_type'])){ if (!empty($data[ 'verify_type' ])) {
$type = VerifyDict::getType(); $type = VerifyDict::getType();
$type_array = []; $type_array = [];
foreach ($data['verify_type'] as $key => $value) { foreach ($data[ 'verify_type' ] as $key => $value) {
if (array_key_exists($value, $type)) { if (array_key_exists($value, $type)) {
$type_array[$key]['verify_type'] = $value; $type_array[ $key ][ 'verify_type' ] = $value;
$type_array[$key]['verify_type_name'] = $type[$value]['name']; $type_array[ $key ][ 'verify_type_name' ] = $type[ $value ][ 'name' ];
} }
} }
$data['verify_type_array'] = $type_array; $data[ 'verify_type_array' ] = $type_array;
} }
return $data; return $data;
} }
public function getDetail($id)
{
return $this->model->with([ 'member' => function ($query) {
$query->field('member_id, nickname, mobile, headimg');
} ])->field('')->findOrEmpty($id)->toArray();
}
/** /**
* 添加核销员 * 添加核销员
* @param array $data * @param array $data
@ -84,17 +92,27 @@ class VerifierService extends BaseAdminService
*/ */
public function add(array $data) public function add(array $data)
{ {
$member = (new Member())->where([ ['member_id', '=', $data['member_id'] ] ])->findOrEmpty(); $member = ( new Member() )->where([ [ 'member_id', '=', $data[ 'member_id' ] ] ])->findOrEmpty();
if ($member->isEmpty()) throw new CommonException('MEMBER_NOT_EXIST'); if ($member->isEmpty()) throw new CommonException('MEMBER_NOT_EXIST');
$model = $this->model->where([ ['member_id', '=', $data['member_id'] ] ])->findOrEmpty(); $model = $this->model->where([ [ 'member_id', '=', $data[ 'member_id' ] ] ])->findOrEmpty();
if (!$model->isEmpty()) return $model->id; if (!$model->isEmpty()) throw new CommonException('VERIFIER_EXIST');
$data['create_time'] = time(); $data[ 'create_time' ] = time();
$res = $this->model->create($data); $res = $this->model->create($data);
return $res->id; return $res->id;
} }
/**
* 编辑核销员
* @param array $data
* @return mixed
*/
public function edit($id, $data)
{
$this->model->where([ [ 'id', '=', $id ] ])->update($data);
}
/** /**
* 删除核销员 * 删除核销员
* @param int $id * @param int $id
@ -102,7 +120,7 @@ class VerifierService extends BaseAdminService
*/ */
public function del(int $id) public function del(int $id)
{ {
$res = $this->model->where([['id', '=', $id] ])->delete(); $res = $this->model->where([ [ 'id', '=', $id ] ])->delete();
return $res; return $res;
} }
} }

View File

@ -33,11 +33,12 @@ class VerifyService extends BaseAdminService
* @return array * @return array
* @throws \think\db\exception\DbException * @throws \think\db\exception\DbException
*/ */
public function getPage(array $where = []) { public function getPage(array $where = [])
$search_model = $this->model->where([['id', '>', 0]])->withSearch(['code', 'type', 'create_time', 'verifier_member_id'], $where) {
->with(['member' => function($query){ $search_model = $this->model->where([ [ 'id', '>', 0 ] ])->withSearch([ 'code', 'type', 'create_time', 'verifier_member_id' ], $where)
->with([ 'member' => function($query) {
$query->field('member_id, nickname, mobile, headimg'); $query->field('member_id, nickname, mobile, headimg');
}])->field('*')->order('create_time desc')->append(['type_name']); } ])->field('*')->order('create_time desc')->append([ 'type_name' ]);
$list = $this->pageQuery($search_model); $list = $this->pageQuery($search_model);
return $list; return $list;
} }
@ -47,15 +48,16 @@ class VerifyService extends BaseAdminService
* @param string $verify_code * @param string $verify_code
* @return array * @return array
*/ */
public function getDetail(string $verify_code) { public function getDetail(string $verify_code)
{
$info = $this->model->where([ $info = $this->model->where([
['code', '=', $verify_code] [ 'code', '=', $verify_code ]
])->field('*') ])->field('*')
->with(['member' => function($query){ ->with([ 'member' => function($query) {
$query->field('member_id, nickname, mobile, headimg'); $query->field('member_id, nickname, mobile, headimg');
}])->append(['type_name'])->findOrEmpty()->toArray(); } ])->append([ 'type_name' ])->findOrEmpty()->toArray();
$info['verify_info'] = event('VerifyInfo',$info); $info[ 'verify_info' ] = event('VerifyInfo', $info);
return $info; return $info;
} }

View File

@ -71,16 +71,15 @@ class DiyConfigService extends BaseApiService
// 检测当前站点是多应用还是单应用 // 检测当前站点是多应用还是单应用
if ($key == 'app') { if ($key == 'app') {
$apps = ( new CoreAddonService() )->getList([ [ 'type', '=', 'app' ] ]); $apps = ( new CoreAddonService() )->getList([ [ 'type', '=', 'app' ] ]);
$list = ( new CoreDiyConfigService() )->getBottomList(); $list = ( new CoreDiyConfigService() )->getBottomList();
$bottom_list_keys = array_column($list, 'key'); $bottom_list_keys = array_column($list, 'key');
// 排除没有底部导航的应用 // 排除没有底部导航的应用
foreach ($apps as $k => $v) { foreach ($apps as $k => $v) {
if (!in_array($v[ 'key' ], $bottom_list_keys)) { if (!in_array($v[ 'key' ], $bottom_list_keys)) {
unset($apps[ $k ]); unset($apps[ $k ]);
} }
} }
$apps = array_values($apps);
if (count($apps) == 1) { if (count($apps) == 1) {
$key = $apps[ 0 ][ 'key' ]; $key = $apps[ 0 ][ 'key' ];
} }

View File

@ -151,32 +151,32 @@ class DiyService extends BaseApiService
*/ */
public function getDiyTheme() public function getDiyTheme()
{ {
$addon_list = (new CoreAddonService())->getInstallAddonList(); $addon_list = ( new CoreAddonService() )->getInstallAddonList();
$apps=[]; $apps = [];
foreach ($addon_list as $k=>$v){ foreach ($addon_list as $k => $v) {
if($v['type']=='app'){ if ($v[ 'type' ] == 'app') {
$apps[]=$v; $apps[] = $v;
} }
} }
$theme_data = (new DiyTheme())->where([['is_selected', '=', 1]])->column('id,title,theme,new_theme','addon'); $theme_data = ( new DiyTheme() )->where([ [ 'is_selected', '=', 1 ] ])->column('id,title,theme,new_theme', 'addon');
$system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app'])))[0] ?? []; $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app' ])))[ 0 ] ?? [];
$app_theme['app'] = [ $app_theme[ 'app' ] = [
'title' => $theme_data['app']['title'] ?? (!empty($system_theme) ? $system_theme['theme_color'][0]['title'] : ''), 'title' => $theme_data[ 'app' ][ 'title' ] ?? ( !empty($system_theme) ? $system_theme[ 'theme_color' ][ 0 ][ 'title' ] : '' ),
'theme' => $theme_data['app']['theme'] ?? (!empty($system_theme) ? $system_theme['theme_color'][0]['theme'] : ''), 'theme' => $theme_data[ 'app' ][ 'theme' ] ?? ( !empty($system_theme) ? $system_theme[ 'theme_color' ][ 0 ][ 'theme' ] : '' ),
'new_theme' => $theme_data['app']['new_theme'] ?? '', 'new_theme' => $theme_data[ 'app' ][ 'new_theme' ] ?? '',
]; ];
$data = []; $data = [];
foreach ($addon_list as $key => $value){ foreach ($addon_list as $key => $value) {
if (isset($value['support_app']) && empty($value['support_app']) && $value['type'] == 'addon'){ if (isset($value[ 'support_app' ]) && empty($value[ 'support_app' ]) && $value[ 'type' ] == 'addon') {
continue; continue;
} }
$addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value['key']])))[0] ?? []; $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'key' ] ])))[ 0 ] ?? [];
$data[$value['key']]['title'] = $theme_data[$value['key']]['title'] ?? (!empty($addon_theme) ? $addon_theme['theme_color'][0][ 'title' ] : ''); $data[ $value[ 'key' ] ][ 'title' ] = $theme_data[ $value[ 'key' ] ][ 'title' ] ?? ( !empty($addon_theme) ? $addon_theme[ 'theme_color' ][ 0 ][ 'title' ] : '' );
$data[$value['key']]['theme'] = $theme_data[$value['key']]['theme'] ?? (!empty($addon_theme) ? $addon_theme['theme_color'][0][ 'theme' ] : ''); $data[ $value[ 'key' ] ][ 'theme' ] = $theme_data[ $value[ 'key' ] ][ 'theme' ] ?? ( !empty($addon_theme) ? $addon_theme[ 'theme_color' ][ 0 ][ 'theme' ] : '' );
$data[$value['key']]['new_theme'] = $theme_data[$value['key']]['new_theme'] ?? ''; $data[ $value[ 'key' ] ][ 'new_theme' ] = $theme_data[ $value[ 'key' ] ][ 'new_theme' ] ?? '';
} }
if (count($apps) > 1) {// 应用数量大于1时展示系统主题色设置只有一个应用时不展示系统主题色设置 if (count($apps) > 1) {// 应用数量大于1时展示系统主题色设置只有一个应用时不展示系统主题色设置
$data = array_merge($app_theme,$data); $data = array_merge($app_theme, $data);
} }
return $data; return $data;
} }

View File

@ -220,7 +220,7 @@ class AreaService extends BaseApiService
'formatted_addresses' => $address_data[ 'formatted_addresses' ] 'formatted_addresses' => $address_data[ 'formatted_addresses' ]
]; ];
} else { } else {
throw new ApiException($res[ 'message' ]); throw new ApiException('请检查地图配置:'.$res[ 'message' ]);
} }
} else { } else {

View File

@ -22,7 +22,6 @@ use core\base\BaseApiService;
class VerifyService extends BaseApiService class VerifyService extends BaseApiService
{ {
/** /**
* 获取核销码(对应业务调用) * 获取核销码(对应业务调用)
* @param $type * @param $type
@ -49,7 +48,7 @@ class VerifyService extends BaseApiService
*/ */
public function getInfoByCode($code) public function getInfoByCode($code)
{ {
return ( new CoreVerifyService() )->getInfoByCode($code); return ( new CoreVerifyService() )->getInfoByCode($this->member_id,$code);
} }
/** /**
@ -114,4 +113,4 @@ class VerifyService extends BaseApiService
])->field($field)->append([ 'type_name' ])->findOrEmpty()->toArray(); ])->field($field)->append([ 'type_name' ])->findOrEmpty()->toArray();
} }
} }

View File

@ -35,7 +35,10 @@ class CoreAddonCloudService extends CoreCloudBaseService
$package_dir = $temp_dir . 'package' . DIRECTORY_SEPARATOR; $package_dir = $temp_dir . 'package' . DIRECTORY_SEPARATOR;
dir_mkdir($package_dir); dir_mkdir($package_dir);
$compile = (new CoreAddonService())->getAddonConfig($addon)['compile'] ?? [];
$addon_config = (new CoreAddonService())->getAddonConfig($addon);
$compile = $addon_config['compile'] ?? [];
$custom_port = $addon_config['port']?? [];
$need_build = false; $need_build = false;
// 拷贝composer文件 // 拷贝composer文件
@ -60,6 +63,19 @@ class CoreAddonCloudService extends CoreCloudBaseService
$need_build = true; $need_build = true;
} }
// 自定义端口
if (!empty($custom_port)) {
$addon_path = $this->addonPath($addon);
foreach ($custom_port as $port) {
if (is_dir($addon_path . $port[ 'name' ])) {
dir_copy($addon_path . $port[ 'name' ], $package_dir . $port[ 'name' ]);
$json_path = $package_dir . $port[ 'name' ] . DIRECTORY_SEPARATOR . 'info.json';
file_put_contents($json_path, json_encode($port));
}
}
$need_build = true;
}
if ($need_build) { if ($need_build) {
// 将临时目录下文件生成压缩包 // 将临时目录下文件生成压缩包
$zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip'; $zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip';
@ -224,10 +240,6 @@ class CoreAddonCloudService extends CoreCloudBaseService
*/ */
public function downloadAddon(string $addon, string $version) { public function downloadAddon(string $addon, string $version) {
$action_token = (new CoreModuleService())->getActionToken('download', ['data' => ['app_key' => $addon, 'version' => $version, 'product_key' => BaseNiucloudClient::PRODUCT ]]); $action_token = (new CoreModuleService())->getActionToken('download', ['data' => ['app_key' => $addon, 'version' => $version, 'product_key' => BaseNiucloudClient::PRODUCT ]]);
if (isset($action_token['code']) && $action_token['code'] != 1) {
if ($action_token['code'] == 401) $action_token = (new CoreModuleService())->getActionToken('download', ['data' => ['app_key' => $addon, 'version' => $version, 'product_key' => BaseNiucloudClient::PRODUCT]]);
if ($action_token['code'] != 1) throw new CommonException($action_token['msg']);
}
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
@ -265,10 +277,6 @@ class CoreAddonCloudService extends CoreCloudBaseService
*/ */
public function upgradeAddon(array $data = []) { public function upgradeAddon(array $data = []) {
$action_token = (new CoreModuleService())->getActionToken('upgrade', ['data' => $data ]); $action_token = (new CoreModuleService())->getActionToken('upgrade', ['data' => $data ]);
if (isset($action_token['code']) && $action_token['code'] != 1) {
if ($action_token['code'] == 401) $action_token = (new CoreModuleService())->getActionToken('upgrade', ['data' => $data ]);
if ($action_token['code'] != 1) throw new CommonException($action_token['msg']);
}
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
@ -286,7 +294,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
* @param string $token * @param string $token
* @return void * @return void
*/ */
public function downloadUpgradeFile(string $token, string $dir = '', int $index = -1, $step = 0, $length = 0) { public function downloadUpgradeFile(string $app_key, string $token, string $dir = '', int $index = -1, $step = 0, $length = 0) {
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
'token' => $token 'token' => $token
@ -302,7 +310,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
$step = (int)ceil($length / $chunk_size); $step = (int)ceil($length / $chunk_size);
$index++; $index++;
return compact('token', 'dir', 'index', 'step', 'length'); return compact('app_key', 'token', 'dir', 'index', 'step', 'length');
} else { } else {
$zip_file = $dir . 'upgrade.zip'; $zip_file = $dir . 'upgrade.zip';
$zip_resource = fopen($zip_file, 'a'); $zip_resource = fopen($zip_file, 'a');
@ -319,7 +327,7 @@ class CoreAddonCloudService extends CoreCloudBaseService
fclose($zip_resource); fclose($zip_resource);
$index++; $index++;
return compact('token', 'dir', 'index', 'step', 'length'); return compact('app_key', 'token', 'dir', 'index', 'step', 'length');
} else { } else {
$zip = new \ZipArchive(); $zip = new \ZipArchive();
if ($zip->open($zip_file) === true) { if ($zip->open($zip_file) === true) {

View File

@ -366,6 +366,7 @@ class CoreAddonDevelopService extends CoreAddonBaseService
if (empty($image)) return true; if (empty($image)) return true;
if (check_file_is_remote($image)) { if (check_file_is_remote($image)) {
try { try {
downloadImage($image,$file); // 将云存储的图片下载到本地
(new CoreFetchService())->setRootPath($dir)->setRename($name)->image($image, 0, FileDict::LOCAL); (new CoreFetchService())->setRootPath($dir)->setRename($name)->image($image, 0, FileDict::LOCAL);
} catch ( UploadFileException $e ) { } catch ( UploadFileException $e ) {
return true; return true;

View File

@ -83,6 +83,7 @@ trait WapTrait
$addon_arr[] = $addon; // 追加新装插件 $addon_arr[] = $addon; // 追加新装插件
} }
$addon_arr = array_unique($addon_arr); $addon_arr = array_unique($addon_arr);
foreach ($addon_arr as $k => $v) { foreach ($addon_arr as $k => $v) {
$addon_path = $compile_path . str_replace('/', DIRECTORY_SEPARATOR, 'addon/' . $v . '/components/diy'); // 插件自定义组件根目录 $addon_path = $compile_path . str_replace('/', DIRECTORY_SEPARATOR, 'addon/' . $v . '/components/diy'); // 插件自定义组件根目录
$addon_file_arr = getFileMap($addon_path); $addon_file_arr = getFileMap($addon_path);

View File

@ -40,52 +40,52 @@ class CoreDiyService extends BaseCoreService
*/ */
public function initDefaultDiyTheme() public function initDefaultDiyTheme()
{ {
$addon_list = (new CoreAddonService())->getInstallAddonList(); $addon_list = ( new CoreAddonService() )->getInstallAddonList();
$apps=[]; $apps = [];
foreach ($addon_list as $k=>$v){ foreach ($addon_list as $k => $v) {
if($v['type']=='app'){ if ($v[ 'type' ] == 'app') {
$apps[]=$v; $apps[] = $v;
} }
} }
$system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app'])))[0] ?? []; $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app' ])))[ 0 ] ?? [];
foreach ($system_theme['theme_color'] as $k => $v) { foreach ($system_theme[ 'theme_color' ] as $k => $v) {
$data[] = [ $data[] = [
'type' => 'app', 'type' => 'app',
'addon' => 'app', 'addon' => 'app',
'title' => $v['title'], 'title' => $v[ 'title' ],
'theme' => $v['theme'], 'theme' => $v[ 'theme' ],
'default_theme' => $v['theme'], 'default_theme' => $v[ 'theme' ],
'theme_type' => 'default', 'theme_type' => 'default',
'is_selected' => $k == 0 ? 1 : 0, 'is_selected' => $k == 0 ? 1 : 0,
'create_time' => time(), 'create_time' => time(),
]; ];
} }
foreach ($apps as $value){ foreach ($apps as $value) {
$addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value['key'] ])))[0] ?? []; $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'key' ] ])))[ 0 ] ?? [];
if (empty($addon_theme)) continue; if (empty($addon_theme)) continue;
foreach ($addon_theme['theme_color'] as $k => $v){ foreach ($addon_theme[ 'theme_color' ] as $k => $v) {
$data[] = [ $data[] = [
'type' => 'app', 'type' => 'app',
'addon' => $value['key'], 'addon' => $value[ 'key' ],
'title' => $v['title'], 'title' => $v[ 'title' ],
'theme' => $v['theme'], 'theme' => $v[ 'theme' ],
'default_theme' => $v['theme'], 'default_theme' => $v[ 'theme' ],
'theme_type' => 'default', 'theme_type' => 'default',
'is_selected' => $k == 0 ? 1 : 0, 'is_selected' => $k == 0 ? 1 : 0,
'create_time' => time(), 'create_time' => time(),
]; ];
} }
$addon_data = (new addon())->field('key')->where([['support_app', '=', $value['key']]])->select()->toArray(); $addon_data = ( new addon() )->field('key')->where([ [ 'support_app', '=', $value[ 'key' ] ] ])->select()->toArray();
if (!empty($addon_data)){ if (!empty($addon_data)) {
foreach ($addon_data as $v){ foreach ($addon_data as $v) {
foreach ($addon_theme['theme_color'] as $theme_k => $theme_v){ foreach ($addon_theme[ 'theme_color' ] as $theme_k => $theme_v) {
$data[] = [ $data[] = [
'type' => 'addon', 'type' => 'addon',
'addon' => $v['key'], 'addon' => $v[ 'key' ],
'title' => $theme_v['title'], 'title' => $theme_v[ 'title' ],
'theme' => $theme_v['theme'], 'theme' => $theme_v[ 'theme' ],
'default_theme' => $theme_v['theme'], 'default_theme' => $theme_v[ 'theme' ],
'theme_type' => 'default', 'theme_type' => 'default',
'is_selected' => $theme_k == 0 ? 1 : 0, 'is_selected' => $theme_k == 0 ? 1 : 0,
'create_time' => time(), 'create_time' => time(),
@ -98,7 +98,7 @@ class CoreDiyService extends BaseCoreService
foreach ($data as $k => &$v) { foreach ($data as $k => &$v) {
$theme_count = $diy_theme_model->where([ $theme_count = $diy_theme_model->where([
[ 'title', "=", $v[ 'title' ] ], [ 'title', "=", $v[ 'title' ] ],
[ 'addon', "=", $v['addon'] ] [ 'addon', "=", $v[ 'addon' ] ]
])->count(); ])->count();
// 如果已有该主题风格颜色则不再添加 // 如果已有该主题风格颜色则不再添加
if ($theme_count > 0) { if ($theme_count > 0) {

View File

@ -90,10 +90,15 @@ class CoreMenuService extends BaseCoreService
$addon_admin_tree = $addon_loader->load(["addon" => $addon, "app_type" => "admin"]); $addon_admin_tree = $addon_loader->load(["addon" => $addon, "app_type" => "admin"]);
if (isset($addon_admin_tree['delete'])) unset($addon_admin_tree['delete']); if (isset($addon_admin_tree['delete'])) unset($addon_admin_tree['delete']);
$menu_list = [];
$admin_menu = $this->loadMenu($addon_admin_tree, "admin", $addon); if (!empty($addon_admin_tree)) {
$menu_list = array_merge($menu_list, $this->loadMenu($addon_admin_tree, "admin", $addon));
}
$this->deleteByAddon($addon, false); $this->deleteByAddon($addon, false);
$this->install($admin_menu); if(!empty($menu_list))
{
$this->install($menu_list);
}
return true; return true;

View File

@ -17,6 +17,7 @@ use app\service\core\addon\CoreAddonBaseService;
use app\service\core\addon\CoreAddonDevelopDownloadService; use app\service\core\addon\CoreAddonDevelopDownloadService;
use app\service\core\addon\WapTrait; use app\service\core\addon\WapTrait;
use core\base\BaseCoreService; use core\base\BaseCoreService;
use core\exception\CloudBuildException;
use core\exception\CommonException; use core\exception\CommonException;
use core\util\niucloud\BaseNiucloudClient; use core\util\niucloud\BaseNiucloudClient;
use core\util\niucloud\CloudService; use core\util\niucloud\CloudService;
@ -42,14 +43,15 @@ class CoreCloudBuildService extends BaseCoreService
parent::__construct(); parent::__construct();
$this->root_path = project_path(); $this->root_path = project_path();
$this->build_task = Cache::get($this->cache_key); $this->build_task = Cache::get($this->cache_key);
$this->auth_code = (new CoreNiucloudConfigService())->getNiucloudConfig()['auth_code'] ?? ''; $this->auth_code = ( new CoreNiucloudConfigService() )->getNiucloudConfig()[ 'auth_code' ] ?? '';
} }
/** /**
* 编译前环境检测 * 编译前环境检测
* @return array|array[] * @return array|array[]
*/ */
public function buildPreCheck() { public function buildPreCheck()
{
$niucloud_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR; $niucloud_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR;
$admin_dir = $this->root_path . 'admin' . DIRECTORY_SEPARATOR; $admin_dir = $this->root_path . 'admin' . DIRECTORY_SEPARATOR;
$web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR; $web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR;
@ -76,35 +78,35 @@ class CoreCloudBuildService extends BaseCoreService
clearstatcache(); clearstatcache();
// 校验niucloud/public niucloud/vendor 目录是否可读可写 // 校验niucloud/public niucloud/vendor 目录是否可读可写
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', public_path()), 'status' => is_readable(public_path())]; $data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', public_path()), 'status' => is_readable(public_path()) ];
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $niucloud_dir . 'vendor'), 'status' => is_readable($niucloud_dir . 'vendor')]; $data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $niucloud_dir . 'vendor'), 'status' => is_readable($niucloud_dir . 'vendor') ];
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', public_path()), 'status' => is_write(public_path())]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', public_path()), 'status' => is_write(public_path()) ];
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $niucloud_dir . 'vendor'), 'status' => is_write($niucloud_dir . 'vendor')]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $niucloud_dir . 'vendor'), 'status' => is_write($niucloud_dir . 'vendor') ];
// 校验niucloud/public下 wap web admin 目录及文件是否可读可写 // 校验niucloud/public下 wap web admin 目录及文件是否可读可写
$check_res = checkDirPermissions(public_path() . 'wap'); $check_res = checkDirPermissions(public_path() . 'wap');
$check_res = array_merge2($check_res, checkDirPermissions(public_path() . 'admin')); $check_res = array_merge2($check_res, checkDirPermissions(public_path() . 'admin'));
$check_res = array_merge2($check_res, checkDirPermissions(public_path() . 'web')); $check_res = array_merge2($check_res, checkDirPermissions(public_path() . 'web'));
if (!empty($check_res['unreadable'])) { if (!empty($check_res[ 'unreadable' ])) {
foreach ($check_res['unreadable'] as $item) { foreach ($check_res[ 'unreadable' ] as $item) {
$data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $item),'status' => false]; $data[ 'dir' ][ 'is_readable' ][] = [ 'dir' => str_replace(project_path(), '', $item), 'status' => false ];
} }
} }
if (!empty($check_res['not_writable'])) { if (!empty($check_res[ 'not_writable' ])) {
foreach ($check_res['not_writable'] as $item) { foreach ($check_res[ 'not_writable' ] as $item) {
$data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $item),'status' => false]; $data[ 'dir' ][ 'is_write' ][] = [ 'dir' => str_replace(project_path(), '', $item), 'status' => false ];
} }
} }
$check_res = array_merge( $check_res = array_merge(
array_column($data['dir']['is_readable'], 'status'), array_column($data[ 'dir' ][ 'is_readable' ], 'status'),
array_column($data['dir']['is_write'], 'status') array_column($data[ 'dir' ][ 'is_write' ], 'status')
); );
// 是否通过校验 // 是否通过校验
$data['is_pass'] = !in_array(false, $check_res); $data[ 'is_pass' ] = !in_array(false, $check_res);
return $data; return $data;
} }
@ -113,10 +115,11 @@ class CoreCloudBuildService extends BaseCoreService
* @param $addon * @param $addon
* @return void * @return void
*/ */
public function cloudBuild() { public function cloudBuild()
{
if ($this->build_task) throw new CommonException('CLOUD_BUILD_TASK_EXIST'); if ($this->build_task) throw new CommonException('CLOUD_BUILD_TASK_EXIST');
$action_token = (new CoreModuleService())->getActionToken('cloudbuild', ['data' => [ 'product_key' => BaseNiucloudClient::PRODUCT ]]); $action_token = ( new CoreModuleService() )->getActionToken('cloudbuild', [ 'data' => [ 'product_key' => BaseNiucloudClient::PRODUCT ] ]);
// 上传任务key // 上传任务key
$task_key = uniqid(); $task_key = uniqid();
@ -128,69 +131,71 @@ class CoreCloudBuildService extends BaseCoreService
// 拷贝composer文件 // 拷贝composer文件
file_put_contents($package_dir . 'composer.json', file_get_contents(root_path() . 'composer.json')); file_put_contents($package_dir . 'composer.json', file_get_contents(root_path() . 'composer.json'));
// 拷贝手机端文件 // 拷贝手机端文件
$wap_is_compile = (new Addon())->where([ ['compile', 'like', '%wap%'] ])->field('id')->findOrEmpty(); $wap_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%wap%' ] ])->field('id')->findOrEmpty();
if ($wap_is_compile->isEmpty()) { if ($wap_is_compile->isEmpty()) {
dir_copy($this->root_path . 'uni-app', $package_dir . 'uni-app', exclude_dirs:['node_modules', 'unpackage', 'dist']); dir_copy($this->root_path . 'uni-app', $package_dir . 'uni-app', exclude_dirs: [ 'node_modules', 'unpackage', 'dist' ]);
$this->handleUniapp($package_dir . 'uni-app'); $this->handleUniapp($package_dir . 'uni-app');
} }
// 拷贝admin端文件 // 拷贝admin端文件
$admin_is_compile = (new Addon())->where([ ['compile', 'like', '%admin%'] ])->field('id')->findOrEmpty(); $admin_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%admin%' ] ])->field('id')->findOrEmpty();
if ($admin_is_compile->isEmpty()) { if ($admin_is_compile->isEmpty()) {
dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs:['node_modules', 'dist', '.vscode', '.idea']); dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs: [ 'node_modules', 'dist', '.vscode', '.idea' ]);
} }
// 拷贝web端文件 // 拷贝web端文件
$web_is_compile = (new Addon())->where([ ['compile', 'like', '%web%'] ])->field('id')->findOrEmpty(); $web_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%web%' ] ])->field('id')->findOrEmpty();
if ($web_is_compile->isEmpty()) { if ($web_is_compile->isEmpty()) {
dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs:['node_modules', '.output', '.nuxt']); dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs: [ 'node_modules', '.output', '.nuxt' ]);
} }
$this->handleCustomPort($package_dir); $this->handleCustomPort($package_dir);
$zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip'; $zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip';
(new CoreAddonDevelopDownloadService(''))->compressToZip($package_dir, $zip_file); ( new CoreAddonDevelopDownloadService('') )->compressToZip($package_dir, $zip_file);
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
'timestamp' => time(), 'timestamp' => time(),
'token' => $action_token['data']['token'] ?? '' 'token' => $action_token[ 'data' ][ 'token' ] ?? ''
]; ];
$response = (new CloudService())->httpPost('cloud/build?' . http_build_query($query), [ $response = ( new CloudService() )->httpPost('cloud/build?' . http_build_query($query), [
'multipart' => [ 'multipart' => [
[ [
'name' => 'file', 'name' => 'file',
'contents' => fopen($zip_file, 'r'), 'contents' => fopen($zip_file, 'r'),
'filename' => 'build.zip' 'filename' => 'build.zip'
] ]
], ],
'timeout' => 300.0 'timeout' => 300.0
]); ]);
if (isset($response['code']) && $response['code'] == 0) throw new CommonException($response['msg']); if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CloudBuildException($response[ 'msg' ]);
$this->build_task = [ $this->build_task = [
'task_key' => $task_key, 'task_key' => $task_key,
'timestamp' => $query['timestamp'] 'timestamp' => $query[ 'timestamp' ]
]; ];
Cache::set($this->cache_key, $this->build_task); Cache::set($this->cache_key, $this->build_task);
return $this->build_task; return $this->build_task;
} }
private function handleUniapp(string $dir) { private function handleUniapp(string $dir)
{
$addon = ( new Addon() )->where([ [ 'status', '=', AddonDict::ON ] ])->value('key', ''); $addon = ( new Addon() )->where([ [ 'status', '=', AddonDict::ON ] ])->value('key', '');
$this->compileDiyComponentsCode($dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $addon); $this->compileDiyComponentsCode($dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR, $addon);
} }
private function handleCustomPort(string $package_dir) { private function handleCustomPort(string $package_dir)
{
$addons = get_site_addons(); $addons = get_site_addons();
foreach ($addons as $addon) { foreach ($addons as $addon) {
$custom_port = (new CoreAddonBaseService())->getAddonConfig($addon)['port'] ?? []; $custom_port = ( new CoreAddonBaseService() )->getAddonConfig($addon)[ 'port' ] ?? [];
if (!empty($custom_port)) { if (!empty($custom_port)) {
$addon_path = root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR; $addon_path = root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR;
foreach ($custom_port as $port) { foreach ($custom_port as $port) {
if (is_dir($addon_path . $port['name'])) { if (is_dir($addon_path . $port[ 'name' ])) {
dir_copy($addon_path . $port['name'], $package_dir . $port['name']); dir_copy($addon_path . $port[ 'name' ], $package_dir . $port[ 'name' ]);
$json_path = $package_dir . $port['name'] . DIRECTORY_SEPARATOR . 'info.json'; $json_path = $package_dir . $port[ 'name' ] . DIRECTORY_SEPARATOR . 'info.json';
file_put_contents($json_path, json_encode($port)); file_put_contents($json_path, json_encode($port));
} }
} }
@ -202,7 +207,8 @@ class CoreCloudBuildService extends BaseCoreService
* 安装时云编译 * 安装时云编译
* @return void * @return void
*/ */
public function installBuild() { public function installBuild()
{
if ($this->build_task) throw new CommonException('CLOUD_BUILD_TASK_EXIST'); if ($this->build_task) throw new CommonException('CLOUD_BUILD_TASK_EXIST');
// 上传任务key // 上传任务key
@ -215,50 +221,50 @@ class CoreCloudBuildService extends BaseCoreService
// 拷贝composer文件 // 拷贝composer文件
file_put_contents($package_dir . 'composer.json', file_get_contents(root_path() . 'composer.json')); file_put_contents($package_dir . 'composer.json', file_get_contents(root_path() . 'composer.json'));
// 拷贝手机端文件 // 拷贝手机端文件
$wap_is_compile = (new Addon())->where([ ['compile', 'like', '%wap%'] ])->field('id')->findOrEmpty(); $wap_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%wap%' ] ])->field('id')->findOrEmpty();
if ($wap_is_compile->isEmpty()) { if ($wap_is_compile->isEmpty()) {
dir_copy($this->root_path . 'uni-app', $package_dir . 'uni-app', exclude_dirs:['node_modules', 'unpackage', 'dist']); dir_copy($this->root_path . 'uni-app', $package_dir . 'uni-app', exclude_dirs: [ 'node_modules', 'unpackage', 'dist' ]);
} }
// 拷贝admin端文件 // 拷贝admin端文件
$admin_is_compile = (new Addon())->where([ ['compile', 'like', '%admin%'] ])->field('id')->findOrEmpty(); $admin_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%admin%' ] ])->field('id')->findOrEmpty();
if ($admin_is_compile->isEmpty()) { if ($admin_is_compile->isEmpty()) {
dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs:['node_modules', 'dist', '.vscode', '.idea']); dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs: [ 'node_modules', 'dist', '.vscode', '.idea' ]);
} }
// 拷贝web端文件 // 拷贝web端文件
$web_is_compile = (new Addon())->where([ ['compile', 'like', '%web%'] ])->field('id')->findOrEmpty(); $web_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%web%' ] ])->field('id')->findOrEmpty();
if ($web_is_compile->isEmpty()) { if ($web_is_compile->isEmpty()) {
dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs:['node_modules', '.output', '.nuxt']); dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs: [ 'node_modules', '.output', '.nuxt' ]);
} }
$this->handleCustomPort($package_dir); $this->handleCustomPort($package_dir);
$zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip'; $zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip';
(new CoreAddonDevelopDownloadService(''))->compressToZip($package_dir, $zip_file); ( new CoreAddonDevelopDownloadService('') )->compressToZip($package_dir, $zip_file);
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
'timestamp' => time() 'timestamp' => time()
]; ];
$versions = array_merge(['niucloud-admin' => config('version.version')], ((new Addon())->column('version', 'key'))); $versions = array_merge([ 'niucloud-admin' => config('version.version') ], ( ( new Addon() )->column('version', 'key') ));
ksort($versions); ksort($versions);
$query['version'] = md5(json_encode($versions) . BaseNiucloudClient::PRODUCT); $query[ 'version' ] = md5(json_encode($versions) . BaseNiucloudClient::PRODUCT);
$response = (new CloudService())->httpPost('cloud/install?' . http_build_query($query), [ $response = ( new CloudService() )->httpPost('cloud/install?' . http_build_query($query), [
'multipart' => [ 'multipart' => [
[ [
'name' => 'file', 'name' => 'file',
'contents' => fopen($zip_file, 'r'), 'contents' => fopen($zip_file, 'r'),
'filename' => 'build.zip' 'filename' => 'build.zip'
] ]
], ],
'timeout' => 300.0 'timeout' => 300.0
]); ]);
if (isset($response['code']) && $response['code'] == 0) throw new CommonException($response['msg']); if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
$this->build_task = [ $this->build_task = [
'task_key' => $task_key, 'task_key' => $task_key,
'timestamp' => $query['timestamp'], 'timestamp' => $query[ 'timestamp' ],
'version' => $query['version'] 'version' => $query[ 'version' ]
]; ];
Cache::set($this->cache_key, $this->build_task); Cache::set($this->cache_key, $this->build_task);
@ -269,7 +275,8 @@ class CoreCloudBuildService extends BaseCoreService
* 获取编译任务 * 获取编译任务
* @return mixed * @return mixed
*/ */
public function getBuildTask() { public function getBuildTask()
{
return $this->build_task; return $this->build_task;
} }
@ -277,19 +284,20 @@ class CoreCloudBuildService extends BaseCoreService
* 获取编译执行日志 * 获取编译执行日志
* @return void * @return void
*/ */
public function getBuildLog() { public function getBuildLog()
{
if (!$this->build_task) return; if (!$this->build_task) return;
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
'timestamp' => $this->build_task['timestamp'] 'timestamp' => $this->build_task[ 'timestamp' ]
]; ];
$build_log = (new CloudService())->httpGet('cloud/get_build_logs?' . http_build_query($query)); $build_log = ( new CloudService() )->httpGet('cloud/get_build_logs?' . http_build_query($query));
if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) { if (isset($build_log[ 'data' ]) && isset($build_log[ 'data' ][ 0 ]) && is_array($build_log[ 'data' ][ 0 ])) {
$last = end($build_log['data'][0]); $last = end($build_log[ 'data' ][ 0 ]);
if ($last['percent'] == 100 && $last['code'] == 1) { if ($last[ 'percent' ] == 100 && $last[ 'code' ] == 1) {
$build_log['data'][0] = $this->buildSuccess($build_log['data'][0]); $build_log[ 'data' ][ 0 ] = $this->buildSuccess($build_log[ 'data' ][ 0 ]);
} }
} }
return $build_log; return $build_log;
@ -300,45 +308,46 @@ class CoreCloudBuildService extends BaseCoreService
* @param array $log * @param array $log
* @return array * @return array
*/ */
public function buildSuccess(array $log) { public function buildSuccess(array $log)
{
try { try {
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
'timestamp' => $this->build_task['timestamp'] 'timestamp' => $this->build_task[ 'timestamp' ]
]; ];
if (isset($this->build_task['version'])) $query['version'] = $this->build_task['version']; if (isset($this->build_task[ 'version' ])) $query[ 'version' ] = $this->build_task[ 'version' ];
$chunk_size = 1 * 1024 * 1024; $chunk_size = 1 * 1024 * 1024;
$temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task['task_key'] . DIRECTORY_SEPARATOR; $temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task[ 'task_key' ] . DIRECTORY_SEPARATOR;
if (!isset($this->build_task['index'])) { if (!isset($this->build_task[ 'index' ])) {
$response = (new CloudService())->request('HEAD','cloud/build_download?' . http_build_query($query), [ $response = ( new CloudService() )->request('HEAD', 'cloud/build_download?' . http_build_query($query), [
'headers' => ['Range' => 'bytes=0-'] 'headers' => [ 'Range' => 'bytes=0-' ]
]); ]);
$length = $response->getHeader('Content-range'); $length = $response->getHeader('Content-range');
$length = (int)explode("/", $length[0])[1]; $length = (int) explode("/", $length[ 0 ])[ 1 ];
$step = (int)ceil($length / $chunk_size); $step = (int) ceil($length / $chunk_size);
$this->build_task = array_merge($this->build_task, ['step' => $step, 'index' => 0, 'length' => $length]); $this->build_task = array_merge($this->build_task, [ 'step' => $step, 'index' => 0, 'length' => $length ]);
Cache::set($this->cache_key, $this->build_task); Cache::set($this->cache_key, $this->build_task);
} else { } else {
$zip_file = $temp_dir . 'download.zip'; $zip_file = $temp_dir . 'download.zip';
$zip_resource = fopen($zip_file, 'a'); $zip_resource = fopen($zip_file, 'a');
if (($this->build_task['index'] + 1) <= $this->build_task['step']) { if (( $this->build_task[ 'index' ] + 1 ) <= $this->build_task[ 'step' ]) {
$start = $this->build_task['index'] * $chunk_size; $start = $this->build_task[ 'index' ] * $chunk_size;
$end = ($this->build_task['index'] + 1) * $chunk_size; $end = ( $this->build_task[ 'index' ] + 1 ) * $chunk_size;
$end = min($end, $this->build_task['length']); $end = min($end, $this->build_task[ 'length' ]);
$response = (new CloudService())->request('GET','cloud/build_download?' . http_build_query($query), [ $response = ( new CloudService() )->request('GET', 'cloud/build_download?' . http_build_query($query), [
'headers' => ['Range' => "bytes={$start}-{$end}"] 'headers' => [ 'Range' => "bytes={$start}-{$end}" ]
]); ]);
fwrite($zip_resource, $response->getBody()); fwrite($zip_resource, $response->getBody());
fclose($zip_resource); fclose($zip_resource);
$this->build_task['index'] += 1; $this->build_task[ 'index' ] += 1;
Cache::set($this->cache_key, $this->build_task); Cache::set($this->cache_key, $this->build_task);
$log[] = [ 'code' => 1, 'action' => '编译包下载中,已下载' . round($this->build_task['index'] / $this->build_task['step'] * 100) . '%', 'percent' => '100' ]; $log[] = [ 'code' => 1, 'action' => '编译包下载中,已下载' . round($this->build_task[ 'index' ] / $this->build_task[ 'step' ] * 100) . '%', 'percent' => '100' ];
} else { } else {
// 解压文件 // 解压文件
$zip = new \ZipArchive(); $zip = new \ZipArchive();
@ -377,9 +386,10 @@ class CoreCloudBuildService extends BaseCoreService
* 清除任务 * 清除任务
* @return void * @return void
*/ */
public function clearTask() { public function clearTask()
{
if (!$this->build_task) return; if (!$this->build_task) return;
$temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task['task_key'] . DIRECTORY_SEPARATOR;; $temp_dir = runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'cloud_build' . DIRECTORY_SEPARATOR . $this->build_task[ 'task_key' ] . DIRECTORY_SEPARATOR;;
@del_target_dir($temp_dir, true); @del_target_dir($temp_dir, true);
Cache::set($this->cache_key, null); Cache::set($this->cache_key, null);
} }

View File

@ -73,7 +73,6 @@ class CoreModuleService extends BaseNiucloudClient
} }
/** /**
* 操作token * 操作token
* @param $action * @param $action
@ -83,7 +82,7 @@ class CoreModuleService extends BaseNiucloudClient
*/ */
public function getActionToken($action, $data) public function getActionToken($action, $data)
{ {
return $this->httpGet('member_app_action/'.$action, $data); return $this->httpGet('member_app_action/' . $action, $data);
} }
/** /**
@ -92,7 +91,8 @@ class CoreModuleService extends BaseNiucloudClient
* @return array|\core\util\niucloud\Response|object|ResponseInterface * @return array|\core\util\niucloud\Response|object|ResponseInterface
* @throws GuzzleException * @throws GuzzleException
*/ */
public function getUpgradeContent($data) { public function getUpgradeContent($data)
{
return $this->httpGet('member_app_upgrade/content', $data); return $this->httpGet('member_app_upgrade/content', $data);
} }
@ -104,7 +104,7 @@ class CoreModuleService extends BaseNiucloudClient
*/ */
public function checkKey($key) public function checkKey($key)
{ {
return $this->httpGet('store/app_check/'.$key, ['product_key' => self::PRODUCT])['data'] ?? false; return $this->httpGet('store/app_check/' . $key, [ 'product_key' => self::PRODUCT ])[ 'data' ] ?? false;
} }
/** /**
@ -112,8 +112,9 @@ class CoreModuleService extends BaseNiucloudClient
* @return array|\core\util\niucloud\Response|object|ResponseInterface * @return array|\core\util\niucloud\Response|object|ResponseInterface
* @throws GuzzleException * @throws GuzzleException
*/ */
public function getFrameworkLastVersion() { public function getFrameworkLastVersion()
return $this->httpGet('store/framework/lastversion', ['product_key' => self::PRODUCT])['data'] ?? false; {
return $this->httpGet('store/framework/lastversion', [ 'product_key' => self::PRODUCT ])[ 'data' ] ?? false;
} }
/** /**
@ -121,24 +122,37 @@ class CoreModuleService extends BaseNiucloudClient
* @return false|mixed * @return false|mixed
* @throws GuzzleException * @throws GuzzleException
*/ */
public function getFrameworkVersionList() { public function getFrameworkVersionList()
return $this->httpGet('store/framework/version', ['product_key' => self::PRODUCT])['data'] ?? false; {
return $this->httpGet('store/framework/version', [ 'product_key' => self::PRODUCT ])[ 'data' ] ?? false;
} }
/** /**
* 申请体验 * 申请体验
* @return array|false|mixed
* @throws GuzzleException * @throws GuzzleException
*/ */
public function applyExperience() { public function applyExperience()
$data = $this->httpGet('apply/experience', ['product_key' => self::PRODUCT])['data'] ?? []; {
$data = $this->httpGet('apply/experience', [ 'product_key' => self::PRODUCT ])[ 'data' ] ?? [];
if (!empty($data)) { if (!empty($data)) {
(new CoreConfigService())->setConfig(ConfigKeyDict::NIUCLOUD_CONFIG, [ ( new CoreConfigService() )->setConfig(ConfigKeyDict::NIUCLOUD_CONFIG, [
'auth_code' => $data['auth_code'], 'auth_code' => $data[ 'auth_code' ],
'auth_secret' => $data['auth_secret'] 'auth_secret' => $data[ 'auth_secret' ]
]); ]);
return $data; return $data;
} else { } else {
return false; return false;
} }
} }
/**
* 获取应用/插件的版本更新记录
* @return false|mixed
* @throws GuzzleException
*/
public function getAppVersionList($app_key)
{
return $this->httpGet('store/app_version/list', [ 'product_key' => self::PRODUCT, 'app_key' => $app_key ])[ 'data' ] ?? false;
}
} }

View File

@ -169,9 +169,9 @@ class CorePayService extends BaseCoreService
//todo 校验场景控制支付方式 //todo 校验场景控制支付方式
$pay_type_list = ( new CorePayChannelService() )->getAllowPayTypeByChannel($channel, $pay[ 'trade_type' ]); $pay_type_list = ( new CorePayChannelService() )->getAllowPayTypeByChannel($channel, $pay[ 'trade_type' ]);
//找朋友帮忙付时不支持找朋友帮忙付 //找朋友帮忙付时不支持找朋友帮忙付
if(!empty($pay_type_list) && !empty($pay_type_list[PayDict::FRIENDSPAY]) && $scene == PaySceneDict::FRIENDSPAY){ if (!empty($pay_type_list) && !empty($pay_type_list[ PayDict::FRIENDSPAY ]) && $scene == PaySceneDict::FRIENDSPAY) {
$pay[ 'config' ] = $pay_type_list[PayDict::FRIENDSPAY]['config']; $pay[ 'config' ] = $pay_type_list[ PayDict::FRIENDSPAY ][ 'config' ];
unset($pay_type_list[PayDict::FRIENDSPAY]); unset($pay_type_list[ PayDict::FRIENDSPAY ]);
} }
$pay[ 'pay_type_list' ] = array_values($pay_type_list); $pay[ 'pay_type_list' ] = array_values($pay_type_list);
} }
@ -251,7 +251,7 @@ class CorePayService extends BaseCoreService
event('OfflinePayAfter', [ event('OfflinePayAfter', [
'trade_type' => $trade_type, 'trade_type' => $trade_type,
'trade_id' => $trade_id, 'trade_id' => $trade_id,
'out_trade_no' => $out_trade_no, 'out_trade_no' => $out_trade_no
]); ]);
} else { } else {
//将支付设置为支付中 //将支付设置为支付中
@ -263,7 +263,7 @@ class CorePayService extends BaseCoreService
] ]
); );
if (env('queue.state', true)) { if (env('queue.state', true)) {
PayReturnTo::dispatch([ 'out_trade_no' => $out_trade_no ], secs: 15); PayReturnTo::dispatch([ 'out_trade_no' => $out_trade_no ], secs: 60);
} }
} }
return $pay_result; return $pay_result;
@ -456,7 +456,7 @@ class CorePayService extends BaseCoreService
*/ */
public function notify(string $channel, string $type, string $action) public function notify(string $channel, string $type, string $action)
{ {
$callback = function($out_trade_no, $params) use ($type, $action) { $callback = function ($out_trade_no, $params) use ($type, $action) {
try { try {
switch ($action) { switch ($action) {
case 'pay'://支付结果通知 case 'pay'://支付结果通知
@ -476,7 +476,7 @@ class CorePayService extends BaseCoreService
} }
}; };
Log::write('业务'.'_'.$channel.'_'.$type.'_'.$action); Log::write('业务_' . $channel . '_' . $type . '_' . $action);
return $this->pay_event->init($channel, $type)->notify($action, $callback); return $this->pay_event->init($channel, $type)->notify($action, $callback);
} }

View File

@ -45,6 +45,13 @@ class CoreRefundService extends BaseCoreService
//通过交易流水号获取支付单据 //通过交易流水号获取支付单据
$pay = (new CorePayService())->findPayInfoByOutTradeNo($out_trade_no); $pay = (new CorePayService())->findPayInfoByOutTradeNo($out_trade_no);
if($pay->isEmpty()) throw new PayException('ALIPAY_TRANSACTION_NO_NOT_EXIST');//单据不存在 if($pay->isEmpty()) throw new PayException('ALIPAY_TRANSACTION_NO_NOT_EXIST');//单据不存在
//查询当前支付已存在的退狂单据,所有的退款总额不能超过支付单据的支付金额
$total_refund_money = $this->model->where([['out_trade_no', '=', $out_trade_no], ['status', '<>', RefundDict::FAIL]])->sum('money');
$comparison = bccomp(bcadd($total_refund_money, $money), $pay['money']);//浮点数直接进行比较会出现精度问题
if ($comparison > 0) throw new PayException('退款金额不能超过支付总额');//退款金额不能超过支付总额
//校验当前数据是否存在 //校验当前数据是否存在
//存在就修改,不存在就创建 //存在就修改,不存在就创建
$refund_no = create_no(); $refund_no = create_no();

View File

@ -71,78 +71,11 @@ class CoreTransferSceneService extends BaseCoreService
$config = $this->getWechatTransferSceneConfig(); $config = $this->getWechatTransferSceneConfig();
//查询业务和场景的对应关系表 //查询业务和场景的对应关系表
// $trade_scene_event_array = [
// 'shop_fenxiao' => [
// 'name' => '分销',
// 'scene' => TransferDict::XJYX,
// 'perception' => '',
// 'infos' => [
// '活动名称' => '分销佣金',
// '奖励说明' => '分销佣金奖励'
// ]
// ]
// ];
$trade_scene_event_array = event('GetWechatTransferTradeScene', []); $trade_scene_event_array = event('GetWechatTransferTradeScene', []);
// [
// 'xjyx' => [
// 'name' => '现金营销',
// 'scene_id' => 1001,
// 'user_recv_perception' => [//收款感知
// '活动奖励',
// '现金奖励',
// ],
// 'transfer_scene_report_infos' => [//报备背景信息
// '活动名称',
// '奖励说明'
// ],
// 'trade_scene_data' => [
// 'shop_fenxiao' => [
// 'name' => '分销',
// 'scene' => TransferDict::XJYX,
// 'infos' => [
// '活动名称' => '分销佣金',
// '奖励说明' => '分销佣金奖励'
// ],
// 'perception' => '活动奖励'
// ]
// ]
// ],
// 'qypf' => [
// 'name' => '企业赔付',
// 'scene_id' => 1002,
// 'user_recv_perception' => [
// '退款',
// '商家赔付',
// ],
// 'transfer_scene_report_infos' => [
// '赔付原因',
// ]
// ],
// 'yjbc' => [
// 'name' => '佣金报酬',
// 'scene_id' => 1005,
// 'user_recv_perception' => [
// '劳务报酬',
// '报销款',
// '企业补贴',
// '开工利是'
// ],
// 'transfer_scene_report_infos' => [
// '岗位类型',
// '报酬说明'
// ]
// ],
//
// ];
$trade_scene_column = ( new TransferScene() )->where([ [ 'id', '=', 0 ] ])->column('*', 'type'); $trade_scene_column = ( new TransferScene() )->where([ [ 'id', '=', 0 ] ])->column('*', 'type');
$trade_scene_list = []; $trade_scene_list = [];
foreach ($trade_scene_event_array as $trade_scene_item) { foreach ($trade_scene_event_array as $trade_scene_item) {
foreach ($trade_scene_item as $trade_scene_key => $trade_scene_item_item) { foreach ($trade_scene_item as $trade_scene_key => $trade_scene_item_item) {
// $trade_scene_select_data = $trade_scene_item_item;
// foreach($trade_scene_column as $trade_scene_column_item){
// if($trade_scene_column_item['type'] == )
// }
$trade_scene_select_data = $trade_scene_column[ $trade_scene_key ] ?? $trade_scene_item_item; $trade_scene_select_data = $trade_scene_column[ $trade_scene_key ] ?? $trade_scene_item_item;
$trade_scene_select_data = array_merge($trade_scene_item_item, $trade_scene_select_data); $trade_scene_select_data = array_merge($trade_scene_item_item, $trade_scene_select_data);
if (!isset($trade_scene_list[ $trade_scene_item_item[ 'scene' ] ])) $trade_scene_list[ $trade_scene_item_item[ 'scene' ] ] = []; if (!isset($trade_scene_list[ $trade_scene_item_item[ 'scene' ] ])) $trade_scene_list[ $trade_scene_item_item[ 'scene' ] ] = [];
@ -153,14 +86,8 @@ class CoreTransferSceneService extends BaseCoreService
foreach ($list as $key => &$v) { foreach ($list as $key => &$v) {
$v[ 'scene_id' ] = $config[ $key ] ?? ''; $v[ 'scene_id' ] = $config[ $key ] ?? '';
// $item_transfer_scene_report_infos = $v['transfer_scene_report_infos'] ?? [];
$trade_scene_data = $trade_scene_list[ $key ] ?? []; $trade_scene_data = $trade_scene_list[ $key ] ?? [];
$v[ 'trade_scene_data' ] = $trade_scene_data; $v[ 'trade_scene_data' ] = $trade_scene_data;
// foreach($item_transfer_scene_report_infos as $item_k => $item_v){
//
// }
// $trade_scene_list = $trade_scene_list[$key] ?? [];
} }
//然后根据支持的业务来完善业务场景备注 //然后根据支持的业务来完善业务场景备注

View File

@ -32,6 +32,7 @@ use Throwable;
class CoreTransferService extends BaseCoreService class CoreTransferService extends BaseCoreService
{ {
protected $pay_event; protected $pay_event;
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
@ -49,7 +50,8 @@ class CoreTransferService extends BaseCoreService
* @return string|null * @return string|null
* @throws Exception * @throws Exception
*/ */
public function create(string $main_type, int $main_id, float $money, string $trade_type, string $remark){ public function create(string $main_type, int $main_id, float $money, string $trade_type, string $remark)
{
$transfer_no = create_no(); $transfer_no = create_no();
$transfer_data = array( $transfer_data = array(
'money' => $money, 'money' => $money,
@ -72,77 +74,78 @@ class CoreTransferService extends BaseCoreService
* @param array $data * @param array $data
* @return true * @return true
*/ */
public function transfer(string $transfer_no, string $transfer_type, array $data){ public function transfer(string $transfer_no, string $transfer_type, array $data)
{
$transfer = $this->findTransferByTransferNo($transfer_no); $transfer = $this->findTransferByTransferNo($transfer_no);
if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID');
if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::FAIL])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); if (!in_array($transfer[ 'transfer_status' ], [ TransferDict::WAIT, TransferDict::FAIL ])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER');
$transfer_account = $data['transfer_account'] ?? ''; $transfer_account = $data[ 'transfer_account' ] ?? '';
$transfer_realname = $data['transfer_realname'] ?? ''; $transfer_realname = $data[ 'transfer_realname' ] ?? '';
$transfer_data = array( $transfer_data = array(
'transfer_type' => $transfer_type,//转账方式 'transfer_type' => $transfer_type,//转账方式
'transfer_realname' => $transfer_realname,//名称 'transfer_realname' => $transfer_realname,//名称
'transfer_mobile' => $data['transfer_mobile'] ?? '',//手机号 'transfer_mobile' => $data[ 'transfer_mobile' ] ?? '',//手机号
'transfer_bank' => $data['transfer_bank'] ?? '',//转账银行 'transfer_bank' => $data[ 'transfer_bank' ] ?? '',//转账银行
'transfer_account' => $transfer_account,//转账账号 'transfer_account' => $transfer_account,//转账账号
'openid' => $data['openid'] ?? '', 'openid' => $data[ 'openid' ] ?? '',
'transfer_voucher' => $data['transfer_voucher'] ?? '', 'transfer_voucher' => $data[ 'transfer_voucher' ] ?? '',
'transfer_remark' => $data['transfer_remark'] ?? '', 'transfer_remark' => $data[ 'transfer_remark' ] ?? '',
'transfer_payee' => $data['transfer_payee'] ?? [], 'transfer_payee' => $data[ 'transfer_payee' ] ?? [],
'transfer_payment_code' => $data['transfer_payment_code'] ?? '' 'transfer_payment_code' => $data[ 'transfer_payment_code' ] ?? ''
); );
$transfer->save($transfer_data); $transfer->save($transfer_data);
switch($transfer_type){ switch ($transfer_type) {
case TransferDict::WECHAT: case TransferDict::WECHAT:
// $out_batch_no = create_no(); // $out_batch_no = create_no();
$transfer_account = $data['transfer_payee'] ?? []; $transfer_account = $data[ 'transfer_payee' ] ?? [];
$scene_data = (new CoreTransferSceneService())->getSceneInfoByType($transfer['trade_type']); $scene_data = ( new CoreTransferSceneService() )->getSceneInfoByType($transfer[ 'trade_type' ]);
//通过业务获取业务场景 //通过业务获取业务场景
$temp_infos = $scene_data['infos'] ?? [];//转账场景信息 $temp_infos = $scene_data[ 'infos' ] ?? [];//转账场景信息
if(!empty($temp_infos)){ if (!empty($temp_infos)) {
$transfer_scene_report_infos = []; $transfer_scene_report_infos = [];
foreach($temp_infos as $key => $item){ foreach ($temp_infos as $key => $item) {
$transfer_scene_report_infos[] = [ $transfer_scene_report_infos[] = [
'info_type' => $key, 'info_type' => $key,
'info_content' => $item 'info_content' => $item
]; ];
} }
} }
$transfer_account['transfer_scene_report_infos'] = $transfer_scene_report_infos ?? [];// $transfer_account[ 'transfer_scene_report_infos' ] = $transfer_scene_report_infos ?? [];//
$transfer_account['user_recv_perception'] = $scene_data['perception'];//收款感知 $transfer_account[ 'user_recv_perception' ] = $scene_data[ 'perception' ];//收款感知
$transfer_account['transfer_scene_id'] = $scene_data['scene_id']; $transfer_account[ 'transfer_scene_id' ] = $scene_data[ 'scene_id' ];
// $transfer_account['out_batch_no'] = $out_batch_no; // $transfer_account['out_batch_no'] = $out_batch_no;
break; break;
} }
$params = []; $params = [];
$return_result = []; $return_result = [];
if(TransferDict::getTransferType()[$transfer_type]['is_online']){ if (TransferDict::getTransferType()[ $transfer_type ][ 'is_online' ]) {
try { try {
$result = $this->pay_event->init('transfer', $transfer_type)->transfer($transfer['money'], $transfer_no, $transfer_account, $transfer_realname, $transfer['remark']); $result = $this->pay_event->init('transfer', $transfer_type)->transfer($transfer[ 'money' ], $transfer_no, $transfer_account, $transfer_realname, $transfer[ 'remark' ]);
// $params['batch_id'] = $result['batch_id']; // $params['batch_id'] = $result['batch_id'];
// $params['out_batch_no'] = $result['out_batch_no']; // $params['out_batch_no'] = $result['out_batch_no'];
//将返回的数据交给转账通知 //将返回的数据交给转账通知
if($transfer_type == TransferDict::WECHAT){ if ($transfer_type == TransferDict::WECHAT) {
$update_data = [ $update_data = [
'out_batch_no' => $result['transfer_bill_no'] ?? '', 'out_batch_no' => $result[ 'transfer_bill_no' ] ?? '',
'package_info' => $result['package_info'] ?? '', 'package_info' => $result[ 'package_info' ] ?? '',
'extra' => $result['extra'] ?? [], 'extra' => $result[ 'extra' ] ?? [],
]; ];
$transfer->save($update_data); $transfer->save($update_data);
$return_result['status'] = $result['status']; $return_result[ 'status' ] = $result[ 'status' ];
$return_result['package_info'] = $result['package_info']; $return_result[ 'package_info' ] = $result[ 'package_info' ];
$return_result['extra'] = $result['extra'] ?? []; $return_result[ 'extra' ] = $result[ 'extra' ] ?? [];
} }
$this->transferNotify($transfer_no, $result); $this->transferNotify($transfer_no, $result);
// return true; // return true;
}catch( Throwable $e){ } catch (Throwable $e) {
$this->fail($transfer_no, ['reason' => get_lang($e->getMessage())]); $this->fail($transfer_no, [ 'reason' => get_lang($e->getMessage()) ]);
throw new PayException($e->getMessage()); throw new PayException($e->getMessage());
} }
}else{ } else {
$return_result = [ $return_result = [
'status' => TransferDict::SUCCESS, 'status' => TransferDict::SUCCESS,
]; ];
@ -151,14 +154,16 @@ class CoreTransferService extends BaseCoreService
return $return_result; return $return_result;
} }
/** /**
* 通过转账单号查询转账 * 通过转账单号查询转账
* @param string $transfer_no * @param string $transfer_no
* @return Pay|array|mixed|Model * @return Pay|array|mixed|Model
*/ */
public function findTransferByTransferNo(string $transfer_no){ public function findTransferByTransferNo(string $transfer_no)
{
$where = array( $where = array(
['transfer_no', '=', $transfer_no] [ 'transfer_no', '=', $transfer_no ]
); );
return $this->model->where($where)->findOrEmpty(); return $this->model->where($where)->findOrEmpty();
} }
@ -170,16 +175,17 @@ class CoreTransferService extends BaseCoreService
* @param $params * @param $params
* @return true * @return true
*/ */
public function transferNotify(string $transfer_no, $params){ public function transferNotify(string $transfer_no, $params)
Log::write('transferNotify'.$transfer_no); {
Log::write('transferNotify' . $transfer_no);
$transfer = $this->findTransferByTransferNo($transfer_no); $transfer = $this->findTransferByTransferNo($transfer_no);
if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID');
if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL, TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); if (!in_array($transfer[ 'transfer_status' ], [ TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL, TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING ])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER');
$status = $params['status'] ?? TransferDict::DEALING; $status = $params[ 'status' ] ?? TransferDict::DEALING;
Log::write('transferNotifyStatus'.$status); Log::write('transferNotifyStatus' . $status);
switch($status){ switch ($status) {
case TransferDict::SUCCESS: case TransferDict::SUCCESS:
Log::write('transferNotifyStatus1'.$status); Log::write('transferNotifyStatus1' . $status);
$this->success($transfer_no); $this->success($transfer_no);
break; break;
case TransferDict::FAIL: case TransferDict::FAIL:
@ -194,6 +200,7 @@ class CoreTransferService extends BaseCoreService
} }
return true; return true;
} }
/** /**
* 转账完成 * 转账完成
* @param string $transfer_no * @param string $transfer_no
@ -201,11 +208,12 @@ class CoreTransferService extends BaseCoreService
* @param array $params * @param array $params
* @return bool * @return bool
*/ */
public function success(string $transfer_no, array $params = []){ public function success(string $transfer_no, array $params = [])
{
$transfer = $this->findTransferByTransferNo($transfer_no); $transfer = $this->findTransferByTransferNo($transfer_no);
Log::write('transferNotifyStatus2'.$transfer['transfer_status']); Log::write('transferNotifyStatus2' . $transfer[ 'transfer_status' ]);
if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID');
if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); if (!in_array($transfer[ 'transfer_status' ], [ TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL, TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING ])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER');
$trade_type = $transfer->trade_type; $trade_type = $transfer->trade_type;
$data = [ $data = [
@ -219,16 +227,16 @@ class CoreTransferService extends BaseCoreService
Db::startTrans(); Db::startTrans();
try { try {
$transfer->save($data); $transfer->save($data);
Log::write('transferNotifyStatus3'.TransferDict::SUCCESS); Log::write('transferNotifyStatus3' . TransferDict::SUCCESS);
$result = event('TransferSuccess', ['transfer_no' => $transfer_no, 'trade_type' => $trade_type]); $result = event('TransferSuccess', [ 'transfer_no' => $transfer_no, 'trade_type' => $trade_type ]);
if(!check_event_result($result)){ if (!check_event_result($result)) {
Db::rollback(); Db::rollback();
return false; return false;
} }
// 提交事务 // 提交事务
Db::commit(); Db::commit();
return true; return true;
} catch ( Throwable $e) { } catch (Throwable $e) {
// 回滚事务 // 回滚事务
Db::rollback(); Db::rollback();
throw new PayException($e->getMessage()); throw new PayException($e->getMessage());
@ -243,15 +251,16 @@ class CoreTransferService extends BaseCoreService
* @param array $params * @param array $params
* @return true * @return true
*/ */
public function fail(string $transfer_no, array $params = []){ public function fail(string $transfer_no, array $params = [])
{
$transfer = $this->findTransferByTransferNo($transfer_no); $transfer = $this->findTransferByTransferNo($transfer_no);
if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID');
if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); if (!in_array($transfer[ 'transfer_status' ], [ TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL, TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING ])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER');
$data = array( $data = array(
'transfer_time' => time(), 'transfer_time' => time(),
'transfer_status' => TransferDict::FAIL, 'transfer_status' => TransferDict::FAIL,
'transfer_fail_reason' => $params['reason'] ?? '' 'transfer_fail_reason' => $params[ 'reason' ] ?? ''
); );
//允许修改的值 //允许修改的值
@ -260,17 +269,18 @@ class CoreTransferService extends BaseCoreService
} }
public function check(array $data){ public function check(array $data)
$transfer_no = $data['transfer_no']; {
$transfer_no = $data[ 'transfer_no' ];
$transfer = $this->findTransferByTransferNo($transfer_no); $transfer = $this->findTransferByTransferNo($transfer_no);
if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID');
if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING]) ) throw new PayException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验 if (!in_array($transfer[ 'transfer_status' ], [ TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL, TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING ])) throw new PayException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验
//查询第三方支付单据 //查询第三方支付单据
$transfer_info = $this->pay_event->init('transfer', $transfer->transfer_type)->getTransfer($transfer_no, $transfer['out_batch_no'] ?? ''); $transfer_info = $this->pay_event->init('transfer', $transfer->transfer_type)->getTransfer($transfer_no, $transfer[ 'out_batch_no' ] ?? '');
if(empty($transfer_info)) throw new PayException('TRANSFER_ORDER_INVALID');//查询不到转账信息 if (empty($transfer_info)) throw new PayException('TRANSFER_ORDER_INVALID');//查询不到转账信息
$status = $transfer_info['status']; $status = $transfer_info[ 'status' ];
switch($status){ switch ($status) {
case TransferDict::SUCCESS: case TransferDict::SUCCESS:
$this->success($transfer_no); $this->success($transfer_no);
break; break;
@ -292,9 +302,10 @@ class CoreTransferService extends BaseCoreService
* @param $type * @param $type
* @return true * @return true
*/ */
public function dealing($transfer_no, $status){ public function dealing($transfer_no, $status)
{
$this->model->where([ $this->model->where([
['transfer_no', '=', $transfer_no] [ 'transfer_no', '=', $transfer_no ]
])->update( ])->update(
[ [
// 'transfer_status' => TransferDict::DEALING, // 'transfer_status' => TransferDict::DEALING,
@ -330,29 +341,27 @@ class CoreTransferService extends BaseCoreService
* @param string $transfer_no * @param string $transfer_no
* @return void * @return void
*/ */
public function cancel(string $transfer_no){ public function cancel(string $transfer_no)
{
try { try {
$transfer_no = $transfer_no;
$transfer = $this->findTransferByTransferNo($transfer_no); $transfer = $this->findTransferByTransferNo($transfer_no);
if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); if ($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID');
if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING]) ) throw new PayException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验 if (!in_array($transfer[ 'transfer_status' ], [ TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL, TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING ])) throw new PayException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验
//查询第三方支付单据 //查询第三方支付单据
$result = $this->pay_event->init('transfer', $transfer->transfer_type)->transferCancel([ $result = $this->pay_event->init('transfer', $transfer->transfer_type)->transferCancel([
'transfer_no' => $transfer_no 'transfer_no' => $transfer_no
]); ]);
$this->transferNotify($transfer_no, $result); $this->transferNotify($transfer_no, $result);
if($result['status'] == TransferDict::FAIL_ING){//撤销中的话也要返回错误,不能让业务认为撤销成功了 if ($result[ 'status' ] == TransferDict::FAIL_ING) {//撤销中的话也要返回错误,不能让业务认为撤销成功了
throw new PayException('TRANSFER_IS_FAILING'); throw new PayException('TRANSFER_IS_FAILING');
} }
return true; return true;
}catch( Throwable $e){ } catch (Throwable $e) {
throw new PayException($e->getMessage()); throw new PayException($e->getMessage());
} }
} }
} }

View File

@ -35,21 +35,21 @@ class CoreVerifyService extends BaseCoreService
{ {
if (!array_key_exists($type, VerifyDict::getType())) throw new CommonException('VERIFY_TYPE_ERROR');//核销类型错误 if (!array_key_exists($type, VerifyDict::getType())) throw new CommonException('VERIFY_TYPE_ERROR');//核销类型错误
//遇到错误直接抛出即可 //遇到错误直接抛出即可
$result = array_filter(event('VerifyCreate', ['type' => $type, 'member_id' => $member_id, 'data' => $param]))[ 0 ] ?? []; $result = array_filter(event('VerifyCreate', [ 'type' => $type, 'member_id' => $member_id, 'data' => $param ]))[ 0 ] ?? [];
$data = []; $data = [];
if(empty($result)){ if (empty($result)) {
$count = 1; $count = 1;
}else{ } else {
$count = $result['count'] ?? 1; $count = $result[ 'count' ] ?? 1;
$data = $result['data'] ?? []; $data = $result[ 'data' ] ?? [];
$body = $result['body'] ?? ''; $body = $result[ 'body' ] ?? '';
$relate_tag = $result['relate_tag'] ?? 0; $relate_tag = $result[ 'relate_tag' ] ?? 0;
$expire_time = $result['expire_time'] ?? null; $expire_time = $result[ 'expire_time' ] ?? null;
} }
$strData = json_encode($param); $strData = json_encode($param);
$value = [ $value = [
'type' => $type, 'type' => $type,
'type_name' => VerifyDict::getType()[$type]['name'] ?? '', 'type_name' => VerifyDict::getType()[ $type ][ 'name' ] ?? '',
'data' => $param, 'data' => $param,
'value' => $data, 'value' => $data,
'body' => $body ?? '', 'body' => $body ?? '',
@ -72,10 +72,23 @@ class CoreVerifyService extends BaseCoreService
* @param string $verify_code * @param string $verify_code
* @return array * @return array
*/ */
public function getInfoByCode(string $verify_code) public function getInfoByCode(string $member_id, $verify_code)
{ {
//获取核销码数据 //获取核销码数据
$value = $this->getCodeData($verify_code); $value = $this->getCodeData($verify_code);
$data = event('VerifyCheck', $value);
if (!empty($data)) {
$value = end($data);
}
// 检测核销员身份,是否有核销权限
$verifier = ( new Verifier() )->where([ [ 'member_id', '=', $member_id ] ])->field('id,verify_type')->findOrEmpty()->toArray();
if (!empty($verifier)) {
if (!in_array($value[ 'type' ], $verifier[ 'verify_type' ])) {
throw new CommonException('VERIFIER_NOT_AUTH');
}
}
return $value; return $value;
} }
@ -89,16 +102,16 @@ class CoreVerifyService extends BaseCoreService
$value = $this->getCodeData($verify_code); $value = $this->getCodeData($verify_code);
//检测核销员身份 //检测核销员身份
$verifierModel = new Verifier(); $verifierModel = new Verifier();
$verifier = $verifierModel->where([['member_id', '=', $verify_member_id]])->findOrEmpty()->toArray(); $verifier = $verifierModel->where([ [ 'member_id', '=', $verify_member_id ] ])->findOrEmpty()->toArray();
if (empty($verifier)) throw new CommonException('VERIFIER_NOT_EXIST'); if (empty($verifier)) throw new CommonException('VERIFIER_NOT_EXIST');
$verify_data = [ $verify_data = [
'code' => $verify_code, 'code' => $verify_code,
'data' => $value['data'], 'data' => $value[ 'data' ],
'value' => $value['value'], 'value' => $value[ 'value' ],
'type' => $value['type'], 'type' => $value[ 'type' ],
'body' => $value['body'], 'body' => $value[ 'body' ],
'relate_tag' => $value['relate_tag'], 'relate_tag' => $value[ 'relate_tag' ],
'create_time' => time(), 'create_time' => time(),
'verifier_member_id' => $verify_member_id, 'verifier_member_id' => $verify_member_id,
]; ];
@ -109,7 +122,6 @@ class CoreVerifyService extends BaseCoreService
//是核销码失效 //是核销码失效
$this->clearCode($verify_code); $this->clearCode($verify_code);
return true; return true;
} }

View File

@ -14,6 +14,7 @@ namespace app\service\core\weapp;
use app\dict\sys\CloudDict; use app\dict\sys\CloudDict;
use app\model\addon\Addon; use app\model\addon\Addon;
use app\model\weapp\WeappVersion; use app\model\weapp\WeappVersion;
use app\service\api\diy\DiyConfigService;
use app\service\core\addon\CoreAddonDevelopDownloadService; use app\service\core\addon\CoreAddonDevelopDownloadService;
use app\service\core\addon\WapTrait; use app\service\core\addon\WapTrait;
use app\service\core\niucloud\CoreCloudBaseService; use app\service\core\niucloud\CoreCloudBaseService;
@ -44,15 +45,16 @@ class CoreWeappCloudService extends CoreCloudBaseService
* 上传小程序 * 上传小程序
* @param $addon * @param $addon
*/ */
public function uploadWeapp(array $data) { public function uploadWeapp(array $data)
{
if (!request()->isSsl()) throw new CommonException('CURR_SITE_IS_NOT_OPEN_SSL'); if (!request()->isSsl()) throw new CommonException('CURR_SITE_IS_NOT_OPEN_SSL');
$config = (new CoreWeappConfigService())->getWeappConfig(); $config = ( new CoreWeappConfigService() )->getWeappConfig();
if (empty($config['app_id'])) throw new CommonException('WEAPP_APPID_EMPTY'); if (empty($config[ 'app_id' ])) throw new CommonException('WEAPP_APPID_EMPTY');
if (empty($config['upload_private_key'])) throw new CommonException('UPLOAD_KEY_EMPTY'); if (empty($config[ 'upload_private_key' ])) throw new CommonException('UPLOAD_KEY_EMPTY');
if (!file_exists($config['upload_private_key'])) throw new CommonException('UPLOAD_KEY_NOT_EXIST'); if (!file_exists($config[ 'upload_private_key' ])) throw new CommonException('UPLOAD_KEY_NOT_EXIST');
$compile_addon = (new Addon())->where([ ['compile', 'like', "%weapp%"] ])->field('key')->findOrEmpty(); $compile_addon = ( new Addon() )->where([ [ 'compile', 'like', "%weapp%" ] ])->field('key')->findOrEmpty();
// 上传任务key // 上传任务key
$task_key = uniqid(); $task_key = uniqid();
// 此次上传任务临时目录 // 此次上传任务临时目录
@ -64,7 +66,8 @@ class CoreWeappCloudService extends CoreCloudBaseService
// 如果不存在编译版小程序 // 如果不存在编译版小程序
if ($compile_addon->isEmpty()) { if ($compile_addon->isEmpty()) {
dir_copy($this->root_path . 'uni-app', $uni_dir, exclude_dirs:['node_modules', 'unpackage', 'dist']); dir_copy($this->root_path . 'uni-app', $uni_dir, exclude_dirs: [ 'node_modules', 'unpackage', 'dist' ]);
// $this->handleTabbar($uni_dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR);
// 替换env文件 // 替换env文件
$this->weappEnvReplace($uni_dir . DIRECTORY_SEPARATOR . '.env.production'); $this->weappEnvReplace($uni_dir . DIRECTORY_SEPARATOR . '.env.production');
} else { } else {
@ -73,25 +76,25 @@ class CoreWeappCloudService extends CoreCloudBaseService
dir_copy($compile_dir, $uni_dir); dir_copy($compile_dir, $uni_dir);
$this->weappCompileReplace($uni_dir); $this->weappCompileReplace($uni_dir);
} }
file_put_contents($package_dir . 'private.key', file_get_contents($config['upload_private_key'])); file_put_contents($package_dir . 'private.key', file_get_contents($config[ 'upload_private_key' ]));
// 将临时目录下文件生成压缩包 // 将临时目录下文件生成压缩包
$zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'weapp.zip'; $zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'weapp.zip';
(new CoreAddonDevelopDownloadService(''))->compressToZip($package_dir, $zip_file); ( new CoreAddonDevelopDownloadService('') )->compressToZip($package_dir, $zip_file);
$query = [ $query = [
'compile' => $compile_addon->isEmpty() ? 0 : 1, 'compile' => $compile_addon->isEmpty() ? 0 : 1,
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
'appid' => $config['app_id'], 'appid' => $config[ 'app_id' ],
'version' => $data['version'] ?? '', 'version' => $data[ 'version' ] ?? '',
'desc' => $data['desc'] ?? '', 'desc' => $data[ 'desc' ] ?? '',
'do' => 1, 'do' => 1,
'timestamp' => time() 'timestamp' => time()
]; ];
$response = (new CloudService())->httpPost('cloud/weapp?' . http_build_query($query), [ $response = ( new CloudService() )->httpPost('cloud/weapp?' . http_build_query($query), [
'multipart' => [ 'multipart' => [
[ [
'name' => 'file', 'name' => 'file',
'contents' => fopen($zip_file, 'r'), 'contents' => fopen($zip_file, 'r'),
'filename' => 'weapp.zip' 'filename' => 'weapp.zip'
] ]
@ -101,9 +104,45 @@ class CoreWeappCloudService extends CoreCloudBaseService
// 删除临时文件 // 删除临时文件
del_target_dir(runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'weapp', true); del_target_dir(runtime_path() . 'backup' . DIRECTORY_SEPARATOR . 'weapp', true);
if (isset($response['code']) && $response['code'] == 0) throw new CommonException($response['msg']); if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]);
return ['key' => $query['timestamp'] ]; return [ 'key' => $query[ 'timestamp' ] ];
}
/**
* 处理底部导航
* @param $compile_path
* @return void
*/
public function handleTabbar($compile_path)
{
$bottomList = array_column(( new DiyConfigService() )->getBottomList(), null, 'key');
$tabbarList = [];
foreach ($bottomList as $app_item) {
array_push($tabbarList, ...$app_item[ 'value' ][ 'list' ]);
}
$tabbarList = array_map(function ($item) {
$link = array_filter(explode('/', $item[ 'link' ][ 'url' ]));
$item[ 'link' ] = $item[ 'link' ][ 'url' ];
$item[ 'component' ] = implode('-', $link);
$item[ 'name' ] = lcfirst(implode('', array_map(function ($str) {
return ucfirst($str);
}, $link)));
return $item;
}, $tabbarList);
$tabbarList = array_column($tabbarList, null, 'name');
if (isset($tabbarList[ 'appPagesIndexIndex' ])) unset($tabbarList[ 'appPagesIndexIndex' ]);
if (isset($tabbarList[ 'appPagesMemberIndex' ])) unset($tabbarList[ 'appPagesMemberIndex' ]);
// 处理vue文件
$tpl = str_replace('/', DIRECTORY_SEPARATOR, public_path() . 'static/tpl/tabbar.tpl');
$content = view($tpl, [ 'tabbarList' => $tabbarList ])->getContent();
file_put_contents(str_replace('/', DIRECTORY_SEPARATOR, $compile_path . 'app/pages/index/tabbar.vue'), $content);
// 处理tabbar.json
file_put_contents($compile_path . 'tabbar.json', json_encode(array_column($tabbarList, 'link'), JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
} }
/** /**
@ -111,10 +150,11 @@ class CoreWeappCloudService extends CoreCloudBaseService
* @param string $env_file * @param string $env_file
* @return void * @return void
*/ */
private function weappEnvReplace(string $env_file) { private function weappEnvReplace(string $env_file)
{
$env = file_get_contents($env_file); $env = file_get_contents($env_file);
$env = str_replace("VITE_APP_BASE_URL=''", "VITE_APP_BASE_URL='" . (string)url('/api/', [], '', true) . "'", $env); $env = str_replace("VITE_APP_BASE_URL=''", "VITE_APP_BASE_URL='" . (string) url('/api/', [], '', true) . "'", $env);
$env = str_replace("VITE_IMG_DOMAIN=''", "VITE_IMG_DOMAIN='" . (string)url('/', [], '', true) . "'", $env); $env = str_replace("VITE_IMG_DOMAIN=''", "VITE_IMG_DOMAIN='" . (string) url('/', [], '', true) . "'", $env);
file_put_contents($env_file, $env); file_put_contents($env_file, $env);
} }
@ -123,17 +163,18 @@ class CoreWeappCloudService extends CoreCloudBaseService
* @param string $vendor_file * @param string $vendor_file
* @return void * @return void
*/ */
private function weappCompileReplace(string $path) { private function weappCompileReplace(string $path)
{
// 替换request.js // 替换request.js
$request_file = $path . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'request.js'; $request_file = $path . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'request.js';
$content = file_get_contents($request_file); $content = file_get_contents($request_file);
$content = str_replace('{{$baseUrl}}', (string)url('/api/', [], '', true), $content); $content = str_replace('{{$baseUrl}}', (string) url('/api/', [], '', true), $content);
file_put_contents($request_file, $content); file_put_contents($request_file, $content);
// 替换common.js // 替换common.js
$common_file = $path . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'common.js'; $common_file = $path . DIRECTORY_SEPARATOR . 'utils' . DIRECTORY_SEPARATOR . 'common.js';
$content = file_get_contents($common_file); $content = file_get_contents($common_file);
$content = str_replace('{{$imgUrl}}', (string)url('/', [], '', true), $content); $content = str_replace('{{$imgUrl}}', (string) url('/', [], '', true), $content);
file_put_contents($common_file, $content); file_put_contents($common_file, $content);
} }
@ -141,11 +182,12 @@ class CoreWeappCloudService extends CoreCloudBaseService
* 获取微信小程序预览码 * 获取微信小程序预览码
* @return void * @return void
*/ */
public function getWeappPreviewImage() { public function getWeappPreviewImage()
{
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
]; ];
$preview_url = (new CloudService())->getUrl('cloud/get_weapp_preview?' . http_build_query($query)); $preview_url = ( new CloudService() )->getUrl('cloud/get_weapp_preview?' . http_build_query($query));
try { try {
$path = runtime_path() . uniqid() . '.jpg'; $path = runtime_path() . uniqid() . '.jpg';
@ -161,21 +203,22 @@ class CoreWeappCloudService extends CoreCloudBaseService
* @param string $timestamp * @param string $timestamp
* @return void * @return void
*/ */
public function getWeappCompileLog(string $timestamp) { public function getWeappCompileLog(string $timestamp)
{
$query = [ $query = [
'authorize_code' => $this->auth_code, 'authorize_code' => $this->auth_code,
'timestamp' => $timestamp 'timestamp' => $timestamp
]; ];
$build_log = (new CloudService())->httpGet('cloud/get_weapp_logs?' . http_build_query($query)); $build_log = ( new CloudService() )->httpGet('cloud/get_weapp_logs?' . http_build_query($query));
if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) { if (isset($build_log[ 'data' ]) && isset($build_log[ 'data' ][ 0 ]) && is_array($build_log[ 'data' ][ 0 ])) {
$last = end($build_log['data'][0]); $last = end($build_log[ 'data' ][ 0 ]);
if ($last['code'] == 0) { if ($last[ 'code' ] == 0) {
(new WeappVersion())->update(['status' => CloudDict::APPLET_UPLOAD_FAIL, 'fail_reason' => $last['msg'] ?? '', 'update_time' => time() ], ['task_key' => $timestamp]); ( new WeappVersion() )->update([ 'status' => CloudDict::APPLET_UPLOAD_FAIL, 'fail_reason' => $last[ 'msg' ] ?? '', 'update_time' => time() ], [ 'task_key' => $timestamp ]);
return $build_log; return $build_log;
} }
if ($last['percent'] == 100) { if ($last[ 'percent' ] == 100) {
(new WeappVersion())->update(['status' => CloudDict::APPLET_UPLOAD_SUCCESS, 'update_time' => time() ], ['task_key' => $timestamp]); ( new WeappVersion() )->update([ 'status' => CloudDict::APPLET_UPLOAD_SUCCESS, 'update_time' => time() ], [ 'task_key' => $timestamp ]);
} }
} }
return $build_log; return $build_log;

View File

@ -102,6 +102,9 @@ class CoreWeappDeliveryService extends BaseCoreService
Log::write('发货信息录入接口,参数打印:' . json_encode($data)); Log::write('发货信息录入接口,参数打印:' . json_encode($data));
//微信订单录入有时差 延时3秒执行发货通知
sleep(3);
$api = CoreWeappService::appApiClient(); $api = CoreWeappService::appApiClient();
$result = $api->postJson('wxa/sec/order/upload_shipping_info', $data)->toArray(); $result = $api->postJson('wxa/sec/order/upload_shipping_info', $data)->toArray();
@ -149,6 +152,9 @@ class CoreWeappDeliveryService extends BaseCoreService
Log::write('确认收货提醒接口,参数打印:' . json_encode($data)); Log::write('确认收货提醒接口,参数打印:' . json_encode($data));
//微信订单录入有时差 延时3秒执行发货通知
sleep(3);
$api = CoreWeappService::appApiClient(); $api = CoreWeappService::appApiClient();
$result = $api->postJson('wxa/sec/order/notify_confirm_receive', $data)->toArray(); $result = $api->postJson('wxa/sec/order/notify_confirm_receive', $data)->toArray();
@ -167,7 +173,7 @@ class CoreWeappDeliveryService extends BaseCoreService
* 1、如设置为空路径或小程序中不存在的路径,将仍然跳转平台默认的确认收货页面,不会进入你的小程序。 * 1、如设置为空路径或小程序中不存在的路径,将仍然跳转平台默认的确认收货页面,不会进入你的小程序。
* 2、平台会在路径后面增加支付单的 transaction_id、merchant_id、merchant_trade_no 作为query参数如果存在二级商户号则还会再增加 sub_merchant_id 参数,开发者可以在小程序中通过onLaunch等方式获取。 * 2、平台会在路径后面增加支付单的 transaction_id、merchant_id、merchant_trade_no 作为query参数如果存在二级商户号则还会再增加 sub_merchant_id 参数,开发者可以在小程序中通过onLaunch等方式获取。
* 3、如你需要在path中携带自定义的query参数请注意与上面的参数进行区分 * 3、如你需要在path中携带自定义的query参数请注意与上面的参数进行区分
* @param int $type * @param string $type
* @return mixed * @return mixed
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
@ -264,4 +270,4 @@ class CoreWeappDeliveryService extends BaseCoreService
return $res; return $res;
} }
} }

View File

@ -86,7 +86,7 @@ class CoreWeappService extends BaseCoreService
]); ]);
if ($response->isFailed()) { if ($response->isFailed()) {
// 出错了,处理异常 // 出错了,处理异常
throw new CommonException('WECHAT_MINI_PROGRAM_CODE_GENERATION_FAILED'); throw new CommonException('微信小程序码生成失败errcode:' . $response[ 'errcode' ] . 'errmsg:' . $response[ 'errmsg' ]);
} }
$response->saveAs($filepath); $response->saveAs($filepath);
return $filepath; return $filepath;

View File

@ -351,11 +351,11 @@ class Upgrade
*/ */
private function initDefaultDiyTheme() private function initDefaultDiyTheme()
{ {
$addon_list = (new CoreAddonService())->getInstallAddonList(); $addon_list = ( new CoreAddonService() )->getInstallAddonList();
$apps=[]; $apps = [];
foreach ($addon_list as $k=>$v){ foreach ($addon_list as $k => $v) {
if($v['type']=='app'){ if ($v[ 'type' ] == 'app') {
$apps[]=$v; $apps[] = $v;
} }
} }
$system_theme = $this->getAppTheme(); $system_theme = $this->getAppTheme();
@ -423,19 +423,22 @@ class Upgrade
} }
} }
} }
if (!empty($data)) { try {
$diy_theme_model = new DiyTheme(); if (!empty($data)) {
foreach ($data as $k => &$v) { $diy_theme_model = new DiyTheme();
$theme_count = $diy_theme_model->where([ foreach ($data as $k => &$v) {
[ 'title', "=", $v[ 'title' ] ], $theme_count = $diy_theme_model->where([
[ 'addon', "=", $v[ 'addon' ] ] [ 'title', "=", $v[ 'title' ] ],
])->count(); [ 'addon', "=", $v[ 'addon' ] ]
// 如果已有该主题风格颜色则不再添加 ])->count();
if ($theme_count > 0) { // 如果已有该主题风格颜色则不再添加
unset($data[ $k ]); if ($theme_count > 0) {
unset($data[ $k ]);
}
} }
$diy_theme_model->insertAll($data);
} }
$diy_theme_model->insertAll($data); } catch (\Exception $e) {
} }
return true; return true;
} }

View File

@ -0,0 +1,48 @@
ALTER TABLE `web_friendly_link` MODIFY COLUMN link_title VARCHAR (100) NOT NULL DEFAULT '' COMMENT '标题';
ALTER TABLE `web_friendly_link` MODIFY COLUMN link_url VARCHAR (100) NOT NULL DEFAULT '' COMMENT '链接';
ALTER TABLE `web_friendly_link` MODIFY COLUMN link_pic VARCHAR (100) NOT NULL DEFAULT '' COMMENT '图片';
ALTER TABLE `pay_transfer` CHANGE COLUMN `extra` `extra` VARCHAR (1000) NOT NULL DEFAULT '' COMMENT '扩展信息';
DROP TABLE IF EXISTS `sys_backup_records`;
CREATE TABLE `sys_backup_records`
(
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`version` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备份版本号',
`backup_key` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备份标识',
`content` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备份内容',
`status` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '状态',
`fail_reason` LONGTEXT DEFAULT NULL COMMENT '失败原因',
`remark` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '备注',
`create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
`complete_time` INT(11) NOT NULL DEFAULT 0 COMMENT '完成时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='备份记录表';
DROP TABLE IF EXISTS `sys_upgrade_records`;
CREATE TABLE `sys_upgrade_records`
(
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`upgrade_key` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '升级标识',
`app_key` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '插件标识',
`name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '升级名称',
`content` LONGTEXT DEFAULT NULL COMMENT '升级内容',
`prev_version` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '前一版本',
`current_version` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '当前版本',
`status` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '状态',
`fail_reason` LONGTEXT DEFAULT NULL COMMENT '失败原因',
`create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
`complete_time` INT(11) NOT NULL DEFAULT 0 COMMENT '完成时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='升级记录表';
ALTER TABLE `pay` MODIFY COLUMN `money` DECIMAL (10, 2) NOT NULL DEFAULT 0.00 COMMENT '支付金额';
ALTER TABLE `jobs` MODIFY COLUMN `queue` VARCHAR (255) NOT NULL DEFAULT '';
ALTER TABLE `diy_form_submit_config` MODIFY COLUMN `tips_type` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '提示内容类型default默认提示diy自定义提示';
ALTER TABLE `diy_theme` CHANGE COLUMN `title` `title` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '标题';

View File

@ -26,7 +26,7 @@ class CashOutConfig extends Validate
'rate' => 'between:0,100', //提现手续费比率 'rate' => 'between:0,100', //提现手续费比率
'is_auto_verify' => 'in:0,1', //是否自动审核 'is_auto_verify' => 'in:0,1', //是否自动审核
'is_auto_transfer' => 'in:0,1', //是否自动转账 'is_auto_transfer' => 'in:0,1', //是否自动转账
'transfer_type' => 'require', 'transfer_type' => 'requireIf:is_open,1',
]; ];
protected $message = [ protected $message = [
@ -41,4 +41,4 @@ class CashOutConfig extends Validate
protected $scene = [ protected $scene = [
'set' => ['is_open', 'min', 'rate', 'is_auto_verify', 'is_auto_transfer', 'transfer_type'], 'set' => ['is_open', 'min', 'rate', 'is_auto_verify', 'is_auto_transfer', 'transfer_type'],
]; ];
} }

View File

@ -1,6 +1,6 @@
<?php <?php
return [ return [
'version' => '1.5.2', 'version' => '1.5.3',
'code' => '2025031402' 'code' => '2025052201'
]; ];

View File

@ -1 +0,0 @@
// | 官方网址https://www.niucloud.com

View File

@ -0,0 +1,18 @@
<?php
namespace core\exception;
use RuntimeException;
use Throwable;
/**
* 平台管理端错误异常处理类
*/
class CloudBuildException extends RuntimeException
{
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

View File

@ -493,7 +493,6 @@ class Wechatpay extends BasePay
'_action' => 'refund', '_action' => 'refund',
'transaction_id' => $out_trade_no, 'transaction_id' => $out_trade_no,
'out_refund_no' => $refund_no, 'out_refund_no' => $refund_no,
''
]; ];
$result = Pay::wechat()->query($order); $result = Pay::wechat()->query($order);
if (empty($result)) if (empty($result))

View File

@ -1,532 +1,216 @@
<?php <?php
namespace core\util; namespace core\util;
use think\facade\Cache;
use think\facade\Db; use think\facade\Db;
class DbBackup class DbBackup
{ {
/** private $key;
* 文件指针 private $backupPath;
* @var resource private $maxFileSize;
*/ private $currentFileIndex = 1;
private $fp; private $currentFile;
/** private $currentFileSize = 0;
* 备份文件信息 part - 卷号name - 文件名 private $tableOffset = [];
* @var array private $tables = [];
*/ private $excludeTables = [];
private $file; private $totalTables;
/** private $processedTables = 0;
* 当前打开文件大小 private $restoreIndex = 0;
* @var integer
*/
private $size = 0;
/** private $startime = 0;
* 数据库配置
* @var integer
*/
private $dbconfig = array();
/**
* 备份配置
* @var integer
*/
private $config = array(
// 数据库备份路径
'path' => './backup/',
// 数据库备份卷大小
'part' => 20971520,
// 数据库备份文件是否启用压缩 0不压缩 1 压缩
'compress' => 0,
// 数据库备份文件压缩级别 1普通 4 一般 9最高
'level' => 9,
);
/** private $maxExecuteTime = 10;
* 数据库备份构造方法
* @param array $file 备份或还原的文件信息 public function __construct($backupPath, $maxFileSize = 1024 * 1024, $excludeTables = [], $key = '')
* @param array $config 备份配置信息
*/
public function __construct($config = [])
{ {
$this->config = is_array($config) && !empty($config) ? array_merge($this->config, $config) : $this->config; $this->key = $key;
//初始化文件名 $cache = $this->getCache();
$this->setFile(); $this->backupPath = $backupPath;
//初始化数据库连接参数 $this->maxFileSize = $maxFileSize;
$this->setDbConn(); $this->excludeTables = $excludeTables;
//检查文件是否可写 if (!is_dir($this->backupPath)) {
if (!$this->checkPath($this->config['path'])) { mkdir($this->backupPath, 0777, true);
throw new \Exception("The current directory is not writable");
} }
$this->currentFileIndex = $cache['currentFileIndex'] ?? 0;
$this->currentFile = $this->backupPath . '/backup_' . $this->currentFileIndex . '.sql';
$this->tables = $cache['tables'] ?? [];
$this->totalTables = count($this->getAllTables());
$this->processedTables = $cache['processedTables'] ?? 0;
$this->tableOffset = $cache['tableOffset'] ?? [];
$this->currentFileSize = $cache['currentFileSize'] ?? 0;
$this->restoreIndex = $cache['restoreIndex'] ?? 0;
$this->startime = time();
} }
/** private function getCache() {
* 设置脚本运行超时时间 $cache = Cache::get('db_backup_' . $this->key, []);
* 0表示不限制,支持连贯操作 return $cache;
*/ }
public function setTimeout($time = null)
{ private function setCache() {
if (!is_null($time)) { $cache = [
set_time_limit($time) || ini_set("max_execution_time", $time); 'currentFileIndex' => $this->currentFileIndex,
} 'processedTables' => $this->processedTables,
'tableOffset' => $this->tableOffset,
'currentFileSize' => $this->currentFileSize,
'restoreIndex' => $this->restoreIndex,
'tables' => $this->tables
];
Cache::set('db_backup_' . $this->key, $cache, 3600);
}
public function setExcludeTables($tables) {
$this->tables = [];
$this->excludeTables = $tables;
$this->totalTables = count($this->getAllTables());
return $this; return $this;
} }
/** public function backupDatabaseSegment($limit = 1000)
* 设置数据库连接必备参数
* @param array $dbconfig 数据库连接配置信息
* @return object
*/
public function setDbConn($dbconfig = [])
{ {
if (empty($dbconfig)) { $tables = array_slice($this->getAllTables(), $this->processedTables);
$this->dbconfig = config('database.connections.'.config('database.default')); if (!empty($tables)) {
} else { foreach ($tables as $table) {
$this->dbconfig = $dbconfig; if (!isset($this->tableOffset[$table])) {
} $this->tableOffset[$table] = 0;
return $this; $this->backupTableStructure($table);
}
/**
* 设置备份文件名
*
* @param Array $file 文件名字
* @return object
*/
public function setFile($file = null)
{
if (is_null($file)) {
$this->file = ['name' => date('Ymd-His'), 'part' => 1];
} else {
if (!array_key_exists("name", $file) && !array_key_exists("part", $file)) {
$this->file = $file['1'];
} else {
$this->file = $file;
}
}
return $this;
}
/**
* 数据库表列表
*
* @param null $table
* @param int $type
* @return array
*/
public function dataList($table = null, $type = 1)
{
if (is_null($table)) {
$list = Db::query("SHOW TABLE STATUS");
} else {
if ($type) {
$list = Db::query("SHOW FULL COLUMNS FROM {$table}");
} else {
$list = Db::query("show columns from {$table}");
}
}
return array_map('array_change_key_case', $list);
}
/**
* 数据库备份文件列表
*
* @return array
*/
public function fileList()
{
if (!is_dir($this->config['path'])) {
mkdir($this->config['path'], 0755, true);
}
$path = realpath($this->config['path']);
$flag = \FilesystemIterator::KEY_AS_FILENAME;
$glob = new \FilesystemIterator($path, $flag);
$list = array();
foreach ($glob as $name => $file) {
if (preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql(?:\\.gz)?$/', $name)) {
$name1 = $name;
$name = sscanf($name, '%4s%2s%2s-%2s%2s%2s-%d');
$date = "{$name[0]}-{$name[1]}-{$name[2]}";
$time = "{$name[3]}:{$name[4]}:{$name[5]}";
$part = $name[6];
if (isset($list["{$date} {$time}"])) {
$info = $list["{$date} {$time}"];
$info['part'] = max($info['part'], $part);
$info['size'] = $info['size'] + $file->getSize();
} else {
$info['part'] = $part;
$info['size'] = $file->getSize();
} }
$extension = strtoupper(pathinfo($file->getFilename(), PATHINFO_EXTENSION));
$info['name'] = $name1; while (true) {
$info['compress'] = $extension === 'SQL' ? '-' : $extension; $data = Db::table($table)->limit($this->tableOffset[$table], $limit)->select()->toArray();
$info['time'] = strtotime("{$date} {$time}"); if (empty($data)) {
$list["{$date} {$time}"] = $info; break;
}
$this->backupTableData($table, $data);
$this->tableOffset[$table] += $limit;
if (time() - $this->startime > $this->maxExecuteTime) {
$this->setCache();
return $this->processedTables;
}
}
if (time() - $this->startime > $this->maxExecuteTime) {
$this->setCache();
return $this->processedTables;
}
$this->processedTables++;
} }
} }
return $list;
}
/**
* 获取文件名称
*
* @param string $type
* @param int $time
* @return array|false|mixed|string
* @throws \Exception
*/
public function getFile($type = '', $time = 0)
{
//
if (!is_numeric($time)) {
throw new \Exception("{$time} Illegal data type");
}
switch ($type) {
case 'time':
$name = date('Ymd-His', $time).'-*.sql*';
$path = realpath($this->config['path']).DIRECTORY_SEPARATOR.$name;
return glob($path);
break;
case 'timeverif':
$name = date('Ymd-His', $time).'-*.sql*';
$path = realpath($this->config['path']).DIRECTORY_SEPARATOR.$name;
$files = glob($path);
$list = array();
foreach ($files as $name) {
$basename = basename($name);
$match = sscanf($basename, '%4s%2s%2s-%2s%2s%2s-%d');
$gz = preg_match('/^\\d{8,8}-\\d{6,6}-\\d+\\.sql.gz$/', $basename);
$list[$match[6]] = array($match[6], $name, $gz);
}
$last = end($list);
if (count($list) === $last[0]) {
return $list;
} else {
throw new \Exception("File {$files['0']} may be damaged, please check again");
}
break;
case 'pathname':
return "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql";
break;
case 'filename':
return "{$this->file['name']}-{$this->file['part']}.sql";
break;
case 'filepath':
return $this->config['path'];
break;
default:
$arr = array(
'pathname' => "{$this->config['path']}{$this->file['name']}-{$this->file['part']}.sql",
'filename' => "{$this->file['name']}-{$this->file['part']}.sql",
'filepath' => $this->config['path'], 'file' => $this->file
);
return $arr;
}
}
/**
* 删除备份文件
*
* @param $time
* @return mixed
* @throws \Exception
*/
public function delFile($time)
{
if ($time) {
$file = $this->getFile('time', $time);
array_map("unlink", $file);
$file = $this->getFile('time', $time);
if (count($file)) {
throw new \Exception("File ".implode('##', $file)." deleted failed");
} else {
return $time;
}
} else {
throw new \Exception("{$time} Time parameter is incorrect");
}
}
/**
* 下载备份
*
* @param string $time
* @param integer $part
* @return array|mixed|string
*/
public function downloadFile($time, $part = 0)
{
$file = $this->getFile('time', $time);
$fileName = $file[$part];
if (file_exists($fileName)) {
ob_end_clean();
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Length: '.filesize($fileName));
header('Content-Disposition: attachment; filename='.basename($fileName));
readfile($fileName);
} else {
throw new \Exception("{$time} File is abnormal");
}
}
public function setSqlMode() {
Db::query("SET sql_mode = '';");
return true; return true;
} }
/** public function getBackupProgress() {
* 导入表 return round($this->processedTables / $this->totalTables * 100);
* }
* @param $start
* @param $time private function backupTableStructure($table)
* @return array|false|int
* @throws Exception
*/
public function import($start, $time)
{ {
//还原数据 $dropTableQuery = "DROP TABLE IF EXISTS `$table`;\n";
$this->file = $this->getFile('time', $time); $dropLength = strlen($dropTableQuery);
if ($this->config['compress']) { if ($this->currentFileSize + $dropLength > $this->maxFileSize) {
$gz = gzopen($this->file[0], 'r'); $this->startNewFile();
$size = 0;
} else {
$size = filesize($this->file[0]);
$gz = fopen($this->file[0], 'r');
} }
$sql = ''; $fp = fopen($this->currentFile, 'a');
if ($start) { fwrite($fp, $dropTableQuery);
$this->config['compress'] ? gzseek($gz, $start) : fseek($gz, $start); $this->currentFileSize += $dropLength;
$createTableQuery = $this->getTableCreateQuery($table);
$query = $createTableQuery . ";\n";
$queryLength = strlen($query);
if ($this->currentFileSize + $queryLength > $this->maxFileSize) {
$this->startNewFile();
$fp = fopen($this->currentFile, 'a');
} }
for ($i = 0; $i < 1000; $i++) { fwrite($fp, $query);
$sql .= $this->config['compress'] ? gzgets($gz) : fgets($gz); fclose($fp);
if (preg_match('/.*;$/', trim($sql))) { $this->currentFileSize += $queryLength;
if (false !== Db::query($sql)) { }
$start += strlen($sql);
private function backupTableData($table, $data)
{
$columns = implode(', ', array_map(function ($column){
return "`{$column}`";
}, array_keys($data[0])));
$valueSets = [];
foreach ($data as $row) {
$values = [];
foreach ($row as $value) {
if (is_int($value)) {
$values[] = (string)$value; // 整数类型直接转换为字符串
} elseif (is_float($value)) {
$values[] = (string)$value; // 浮点数类型直接转换为字符串
} elseif (is_bool($value)) {
$values[] = $value ? '1' : '0'; // 布尔类型转换为 1 或 0
} elseif (is_null($value)) {
$values[] = 'NULL'; // 空值使用 NULL
} else { } else {
return false; $values[] = Db::getPdo()->quote($value); // 其他类型使用 quote 方法处理
} }
$sql = '';
} elseif ($this->config['compress'] ? gzeof($gz) : feof($gz)) {
return 0;
} }
$valueSets[] = '(' . implode(', ', $values) . ')';
} }
return array($start, $size); $insertQuery = "INSERT INTO `$table` ($columns) VALUES\n" . implode(",\n", $valueSets) . ";\n";
$queryLength = strlen($insertQuery);
if ($this->currentFileSize + $queryLength > $this->maxFileSize) {
$this->startNewFile();
}
$fp = fopen($this->currentFile, 'a');
fwrite($fp, $insertQuery);
fclose($fp);
$this->currentFileSize += $queryLength;
} }
/** private function getAllTables()
* 写入初始数据
*
* @return boolean true - 写入成功false - 写入失败
*/
public function backupInit()
{ {
$sql = "-- -----------------------------\n"; if (!empty($this->tables)) return $this->tables;
$sql .= "-- Think MySQL Data Transfer \n";
$sql .= "-- \n"; $tables = Db::query('SHOW TABLES');
$sql .= "-- Host : ".$this->dbconfig['hostname']."\n"; $this->tables = [];
$sql .= "-- Port : ".$this->dbconfig['hostport']."\n"; foreach ($tables as $table) {
$sql .= "-- Database : ".$this->dbconfig['database']."\n"; $table_name = current($table);
$sql .= "-- \n"; if (in_array($table_name, $this->excludeTables)) {
$sql .= "-- Part : #{$this->file['part']}\n"; continue;
$sql .= "-- Date : ".date("Y-m-d H:i:s")."\n"; }
$sql .= "-- -----------------------------\n\n"; $this->tables[] = $table_name;
$sql .= "SET FOREIGN_KEY_CHECKS = 0;\n\n"; }
return $this->write($sql); return $this->tables;
} }
/** private function getTableCreateQuery($tableName)
* 查询单条
* @param $sql
* @return array|mixed
*/
public function selectOne($sql) {
$result = Db::query($sql);
return $result[0] ?? [];
}
/**
* 备份表结构
*
* @param string $table 表名
* @param integer $start 起始行数
* @return boolean false - 备份失败
*/
public function backup($table, $start = 0)
{ {
// 备份表结构 $result = Db::query("SHOW CREATE TABLE $tableName");
if (0 == $start) { return $result[0]['Create Table'];
$result = $this->selectOne("SHOW CREATE TABLE `{$table}`");
$sql = "\n";
$sql .= "-- -----------------------------\n";
$sql .= "-- Table structure for `{$table}`\n";
$sql .= "-- -----------------------------\n";
$sql .= "DROP TABLE IF EXISTS `{$table}`;\n";
$sql .= trim($result['Create Table']).";\n\n";
if (false === $this->write($sql)) {
return false;
}
}
//数据总数
$result = $this->selectOne("SELECT COUNT(*) AS count FROM `{$table}`");
$count = $result['count'];
//备份表数据
if ($count) {
//写入数据注释
if (0 == $start) {
$sql = "-- -----------------------------\n";
$sql .= "-- Records of `{$table}`\n";
$sql .= "-- -----------------------------\n";
$this->write($sql);
}
//备份数据记录
$result = Db::query("SELECT * FROM `{$table}` LIMIT {$start}, 1000");
$sql = "INSERT INTO `{$table}` VALUES\n";
foreach ($result as $index => $row) {
$row = array_map(function ($item){
return is_string($item) ? addslashes($item) : $item;
}, $row);
$sql .= "('".str_replace(array("\r", "\n"), array('\\r', '\\n'),
implode("', '", $row))."')";
$sql .= $index < (count($result) - 1) ? ",\n" : ";\n";
}
if (false === $this->write($sql)) {
return false;
}
//还有更多数据
if ($count > $start + 1000) {
return $this->backup($table, $start + 1000);
}
}
//备份下一表
return true;
} }
/** private function startNewFile()
* 优化表
*
* @param String $tables 表名
* @return String $tables
*/
public function optimize($tables = null)
{ {
if ($tables) { $this->currentFileIndex++;
if (is_array($tables)) { $this->currentFile = $this->backupPath . '/backup_' . $this->currentFileIndex . '.sql';
$tables = implode('`,`', $tables); $this->currentFileSize = 0;
$list = db ::select("OPTIMIZE TABLE `{$tables}`");
} else {
$list = Db::query("OPTIMIZE TABLE `{$tables}`");
}
if ($list) {
return $tables;
} else {
throw new \Exception("data sheet'{$tables}'Repair mistakes please try again!");
}
} else {
throw new \Exception("Please specify the table to be repaired!");
}
} }
/** public function restoreDatabase()
* 修复表
*
* @param String $tables 表名
* @return String $tables
*/
public function repair($tables = null)
{ {
if ($tables) { $backupFiles = glob($this->backupPath . '/backup_*.sql');
if (is_array($tables)) { natsort($backupFiles);
$tables = implode('`,`', $tables); $backupFiles = array_values($backupFiles);
$list = Db::query("REPAIR TABLE `{$tables}`");
} else { if ($this->restoreIndex >= count($backupFiles)) return true;
$list = Db::query("REPAIR TABLE `{$tables}`"); $backupFile = $backupFiles[$this->restoreIndex];
$sql = file_get_contents($backupFile);
$queries = explode(";\n", $sql);
foreach ($queries as $query) {
if (trim($query) !== '') {
Db::execute($query);
} }
if ($list) {
return $list;
} else {
throw new \Exception("data sheet'{$tables}'Repair mistakes please try again!");
}
} else {
throw new \Exception("Please specify the table to be repaired!");
} }
$this->restoreIndex++;
$this->setCache();
return $this->restoreIndex;
} }
/**
* 写入SQL语句
*
* @param string $sql 要写入的SQL语句
* @return boolean true - 写入成功false - 写入失败!
*/
private function write($sql)
{
$size = strlen($sql);
//由于压缩原因无法计算出压缩后的长度这里假设压缩率为50%
//一般情况压缩率都会高于50%
$size = $this->config['compress'] ? $size / 2 : $size;
$this->open($size);
return $this->config['compress'] ? @gzwrite($this->fp, $sql) : @fwrite($this->fp, $sql);
}
/**
* 打开一个卷,用于写入数据
*
* @param integer $size 写入数据的大小
*/
private function open($size)
{
if ($this->fp) {
$this->size += $size;
if ($this->size > $this->config['part']) {
$this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp);
$this->fp = null;
$this->file['part']++;
session('backup_file', $this->file);
$this->backupInit();
}
} else {
$backuppath = $this->config['path'];
$filename = "{$backuppath}{$this->file['name']}-{$this->file['part']}.sql";
if ($this->config['compress']) {
$filename = "{$filename}.gz";
$this->fp = @gzopen($filename, "a{$this->config['level']}");
} else {
$this->fp = @fopen($filename, 'a');
}
$this->size = filesize($filename) + $size;
}
}
/**
* 检查目录是否可写
*
* @param string $path 目录
* @return boolean
*/
protected function checkPath($path)
{
if (is_dir($path)) {
return true;
}
if (mkdir($path, 0755, true)) {
return true;
} else {
return false;
}
}
/**
* 析构方法,用于关闭文件资源
*/
public function __destruct()
{
if ($this->fp) {
$this->config['compress'] ? @gzclose($this->fp) : @fclose($this->fp);
}
}
} }