diff --git a/niucloud/app/adminapi/controller/addon/Backup.php b/niucloud/app/adminapi/controller/addon/Backup.php new file mode 100644 index 000000000..815c62d0d --- /dev/null +++ b/niucloud/app/adminapi/controller/addon/Backup.php @@ -0,0 +1,125 @@ +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()); + } +} diff --git a/niucloud/app/adminapi/controller/addon/Upgrade.php b/niucloud/app/adminapi/controller/addon/Upgrade.php index b374ebdd7..63295c584 100644 --- a/niucloud/app/adminapi/controller/addon/Upgrade.php +++ b/niucloud/app/adminapi/controller/addon/Upgrade.php @@ -11,6 +11,7 @@ namespace app\adminapi\controller\addon; +use app\service\admin\upgrade\UpgradeRecordsService; use app\service\admin\upgrade\UpgradeService; use core\base\BaseAdminController; use think\Response; @@ -24,7 +25,7 @@ class Upgrade extends BaseAdminController */ public function upgrade($addon = '') { - return success(data:( new UpgradeService() )->upgrade($addon)); + return success(data: ( new UpgradeService() )->upgrade($addon)); } /** @@ -32,9 +33,9 @@ class Upgrade extends BaseAdminController * @param $app_key * @return Response */ - public function execute($addon = '') + public function execute() { - return success(data:( new UpgradeService() )->execute()); + return success(data: ( new UpgradeService() )->execute()); } /** @@ -44,7 +45,7 @@ class Upgrade extends BaseAdminController */ public function getUpgradeContent($addon = '') { - return success(data:( new UpgradeService() )->getUpgradeContent($addon)); + return success(data: ( new UpgradeService() )->getUpgradeContent($addon)); } /** @@ -53,7 +54,7 @@ class Upgrade extends BaseAdminController */ public function getUpgradeTask() { - return success(data:( new UpgradeService() )->getUpgradeTask()); + return success(data: ( new UpgradeService() )->getUpgradeTask()); } /** @@ -63,7 +64,7 @@ class Upgrade extends BaseAdminController */ public function upgradePreCheck($addon = '') { - return success(data:( new UpgradeService() )->upgradePreCheck($addon)); + return success(data: ( new UpgradeService() )->upgradePreCheck($addon)); } /** @@ -72,6 +73,23 @@ class Upgrade extends BaseAdminController */ public function clearUpgradeTask() { - return success(data:( new UpgradeService() )->clearUpgradeTask()); + return success(data: ( new UpgradeService() )->clearUpgradeTask()); } + + 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)); + } + } diff --git a/niucloud/app/adminapi/controller/diy/Config.php b/niucloud/app/adminapi/controller/diy/Config.php index 744ae7a20..f00732f7d 100644 --- a/niucloud/app/adminapi/controller/diy/Config.php +++ b/niucloud/app/adminapi/controller/diy/Config.php @@ -29,7 +29,7 @@ class Config extends BaseAdminController */ 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([ [ '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', [] ], [ 'key', 'app' ] ]); - (new DiyConfigService())->setBottomConfig($data[ 'value' ], $data[ 'key' ]); + ( new DiyConfigService() )->setBottomConfig($data[ 'value' ], $data[ 'key' ]); return success(); } diff --git a/niucloud/app/adminapi/controller/diy/Diy.php b/niucloud/app/adminapi/controller/diy/Diy.php index 5f0937475..38e9c1f20 100644 --- a/niucloud/app/adminapi/controller/diy/Diy.php +++ b/niucloud/app/adminapi/controller/diy/Diy.php @@ -49,8 +49,7 @@ class Diy extends BaseAdminController */ public function getPageByCarouselSearch() { - $data = $this->request->params([]); - return success(( new DiyService() )->getPageByCarouselSearch($data)); + return success(( new DiyService() )->getPageByCarouselSearch()); } /** @@ -275,7 +274,7 @@ class Diy extends BaseAdminController */ public function getDiyTheme() { - return success(( new DiyService() )->getDiyTheme()); + return success(( new DiyService() )->getDiyTheme()); } /** @@ -292,7 +291,7 @@ class Diy extends BaseAdminController [ 'new_theme', '' ], ]); ( new DiyService() )->setDiyTheme($data); - return success('ADD_SUCCESS'); + return success('ADD_SUCCESS'); } /** @@ -304,7 +303,7 @@ class Diy extends BaseAdminController $data = $this->request->params([ [ 'addon', '' ], ]); - return success(( new DiyService() )->getDefaultThemeColor($data)); + return success(( new DiyService() )->getDefaultThemeColor($data)); } /** diff --git a/niucloud/app/adminapi/controller/diy/DiyForm.php b/niucloud/app/adminapi/controller/diy/DiyForm.php index 4e19b38a9..fe2d7372b 100644 --- a/niucloud/app/adminapi/controller/diy/DiyForm.php +++ b/niucloud/app/adminapi/controller/diy/DiyForm.php @@ -370,16 +370,4 @@ class DiyForm extends BaseAdminController 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' ])); - } - } diff --git a/niucloud/app/adminapi/controller/member/Member.php b/niucloud/app/adminapi/controller/member/Member.php index 9b6e4929f..8ab815f51 100644 --- a/niucloud/app/adminapi/controller/member/Member.php +++ b/niucloud/app/adminapi/controller/member/Member.php @@ -152,6 +152,7 @@ class Member extends BaseAdminController { $data = $this->request->params([ ['keyword', ''], + ['member_ids', []], ]); return success((new MemberService())->getList($data)); } diff --git a/niucloud/app/adminapi/controller/niucloud/Module.php b/niucloud/app/adminapi/controller/niucloud/Module.php index d2394df9e..e9ce3eaf2 100644 --- a/niucloud/app/adminapi/controller/niucloud/Module.php +++ b/niucloud/app/adminapi/controller/niucloud/Module.php @@ -20,7 +20,7 @@ class Module extends BaseAdminController { public function authorize() { - return success((new CoreAuthService())->getAuthInfo()); + return success(( new CoreAuthService() )->getAuthInfo()); } /** @@ -29,11 +29,11 @@ class Module extends BaseAdminController public function setAuthorize() { $data = $this->request->params([ - ['auth_code', ''], - ['auth_secret', ''] + [ 'auth_code', '' ], + [ 'auth_secret', '' ] ]); $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() { - return success((new NiucloudService())->getAuthorize()); + return success(( new NiucloudService() )->getAuthorize()); } /** @@ -49,8 +49,9 @@ class Module extends BaseAdminController * @return Response * @throws \GuzzleHttp\Exception\GuzzleException */ - public function getFrameworkLastVersion() { - return success(data:(new NiucloudService())->getFrameworkLastVersion()); + public function getFrameworkLastVersion() + { + return success(data: ( new NiucloudService() )->getFrameworkLastVersion()); } /** @@ -58,7 +59,20 @@ class Module extends BaseAdminController * @return Response * @throws \GuzzleHttp\Exception\GuzzleException */ - public function getFrameworkVersionList() { - return success(data:(new NiucloudService())->getFrameworkVersionList()); + public function getFrameworkVersionList() + { + return success(data: ( new NiucloudService() )->getFrameworkVersionList()); + } + + /** + * 获取应用/插件的版本更新记录 + * @return Response + */ + public function getAppVersionList() + { + $data = $this->request->params([ + [ 'app_key', '' ], + ]); + return success(data: ( new NiucloudService() )->getAppVersionList($data[ 'app_key' ])); } } diff --git a/niucloud/app/adminapi/controller/pay/PayRefund.php b/niucloud/app/adminapi/controller/pay/PayRefund.php index 2f96de55c..e7fa2367c 100644 --- a/niucloud/app/adminapi/controller/pay/PayRefund.php +++ b/niucloud/app/adminapi/controller/pay/PayRefund.php @@ -17,6 +17,13 @@ use core\base\BaseAdminController; class PayRefund extends BaseAdminController { + /** + * @return \think\Response + */ + public function getStatus() + { + return success(RefundDict::getStatus()); + } /** * 退款列表 * @return \think\Response diff --git a/niucloud/app/adminapi/controller/sys/Config.php b/niucloud/app/adminapi/controller/sys/Config.php index 9b4964d6f..a12ef8428 100644 --- a/niucloud/app/adminapi/controller/sys/Config.php +++ b/niucloud/app/adminapi/controller/sys/Config.php @@ -57,6 +57,8 @@ class Config extends BaseAdminController $service_data = $this->request->params([ [ "wechat_code", "" ], [ "enterprise_wechat", "" ], + [ "site_login_logo", "" ], + [ "site_login_bg_img", "" ], [ "tel", "" ], ]); ( new ConfigService() )->setService($service_data); diff --git a/niucloud/app/adminapi/controller/sys/System.php b/niucloud/app/adminapi/controller/sys/System.php index b3ff539c4..4cd249a46 100644 --- a/niucloud/app/adminapi/controller/sys/System.php +++ b/niucloud/app/adminapi/controller/sys/System.php @@ -91,4 +91,19 @@ class System extends BaseAdminController { 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)); + } } diff --git a/niucloud/app/adminapi/controller/verify/Verifier.php b/niucloud/app/adminapi/controller/verify/Verifier.php index 1ab65d5db..07dc84cab 100644 --- a/niucloud/app/adminapi/controller/verify/Verifier.php +++ b/niucloud/app/adminapi/controller/verify/Verifier.php @@ -24,7 +24,7 @@ class Verifier extends BaseAdminController */ 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() { - 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() { $data = $this->request->params([ - ['member_id', 0], - ['verify_type', ''], + [ 'member_id', 0 ], + [ '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) { - return success('DELETE_SUCCESS', (new VerifierService())->del($id)); + return success('DELETE_SUCCESS', ( new VerifierService() )->del($id)); } /** diff --git a/niucloud/app/adminapi/controller/verify/Verify.php b/niucloud/app/adminapi/controller/verify/Verify.php index 54e619ecc..5e62b2767 100644 --- a/niucloud/app/adminapi/controller/verify/Verify.php +++ b/niucloud/app/adminapi/controller/verify/Verify.php @@ -24,13 +24,13 @@ class Verify extends BaseAdminController public function lists() { $data = $this->request->params([ - ['relate_tag', 0], - ['type', ''], - ['code', ''], - ['verifier_member_id', ''], - ['create_time', []] + [ 'relate_tag', 0 ], + [ 'type', '' ], + [ 'code', '' ], + [ 'verifier_member_id', '' ], + [ '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) { - return success((new VerifyService())->getDetail($verify_code)); + return success(( new VerifyService() )->getDetail($verify_code)); } } diff --git a/niucloud/app/adminapi/controller/wxoplatform/WeappVersion.php b/niucloud/app/adminapi/controller/wxoplatform/WeappVersion.php index 8d7acc277..4078f2a46 100644 --- a/niucloud/app/adminapi/controller/wxoplatform/WeappVersion.php +++ b/niucloud/app/adminapi/controller/wxoplatform/WeappVersion.php @@ -22,10 +22,19 @@ class WeappVersion extends BaseAdminController * @return Response */ public function weappCommit() { - (new WeappVersionService())->add(); + $data = $this->request->params([ + ['site_group_id', ""] + ]); + $data['is_all'] = empty($data['site_group_id']) ? 1 : 0; + (new WeappVersionService())->add($data); return success(); } + + public function getSiteGroupCommitRecord() { + return success(data:(new WeappVersionService())->getSiteGroupCommitRecord()); + } + /** * 获取最后一次提交记录 * @return Response @@ -35,7 +44,10 @@ class WeappVersion extends BaseAdminController } public function commitRecord() { - return success(data:(new WeappVersionService())->getPage()); + $data = $this->request->params([ + ['site_group_id', ""] + ]); + return success(data:(new WeappVersionService())->getPage($data)); } /** diff --git a/niucloud/app/adminapi/route/niucloud.php b/niucloud/app/adminapi/route/niucloud.php index d7fda56cd..032b7f975 100644 --- a/niucloud/app/adminapi/route/niucloud.php +++ b/niucloud/app/adminapi/route/niucloud.php @@ -17,7 +17,7 @@ use think\facade\Route; /** * 应用插件相关路由 */ -Route::group('niucloud', function () { +Route::group('niucloud', function() { //设置 授权信息 Route::post('authinfo', 'niucloud.Module/setAuthorize'); //获取 授权设置 @@ -42,6 +42,9 @@ Route::group('niucloud', function () { // 获取框架版本更新记录 Route::get('framework/version/list', 'niucloud.Module/getFrameworkVersionList'); + // 获取应用/插件的版本更新记录 + Route::get('app_version/list', 'niucloud.Module/getAppVersionList'); + // 云编译 Route::post('build', 'niucloud.Cloud/build'); // 获取编译任务 diff --git a/niucloud/app/adminapi/route/pay.php b/niucloud/app/adminapi/route/pay.php index 208e897d4..8d7e9137b 100644 --- a/niucloud/app/adminapi/route/pay.php +++ b/niucloud/app/adminapi/route/pay.php @@ -43,6 +43,7 @@ Route::group('pay', function () { //退款列表 Route::get('refund', 'pay.PayRefund/pages'); //退款详情 + Route::get('refund/status', 'pay.PayRefund/getStatus'); Route::get('refund/:refund_no', 'pay.PayRefund/detail'); //退款方式 Route::get('refund/type', 'pay.PayRefund/getRefundType'); diff --git a/niucloud/app/adminapi/route/sys.php b/niucloud/app/adminapi/route/sys.php index ca2c05127..fd4956817 100644 --- a/niucloud/app/adminapi/route/sys.php +++ b/niucloud/app/adminapi/route/sys.php @@ -23,6 +23,7 @@ Route::group('sys', function() { //系统信息 Route::get('info', 'sys.System/info'); Route::get('url', 'sys.System/url'); + Route::get('qrcode', 'sys.System/getSpreadQrcode'); /***************************************************** 用户组 ****************************************************/ //用户组列表 Route::get('role', 'sys.Role/lists'); diff --git a/niucloud/app/adminapi/route/upgrade.php b/niucloud/app/adminapi/route/upgrade.php index 8f4f65f99..935f5e893 100644 --- a/niucloud/app/adminapi/route/upgrade.php +++ b/niucloud/app/adminapi/route/upgrade.php @@ -19,18 +19,56 @@ use think\facade\Route; * 路由 */ Route::group('', function () { + // 获取正在进行的升级任务 Route::get('upgrade/task', 'addon.Upgrade/getUpgradeTask'); + // 执行升级 Route::post('upgrade/execute', 'addon.Upgrade/execute'); + // 清除升级任务 Route::post('upgrade/clear', 'addon.Upgrade/clearUpgradeTask'); + // 升级环境检测 Route::get('upgrade/check/[:addon]', 'addon.Upgrade/upgradePreCheck'); + // 升级 Route::post('upgrade/[:addon]', 'addon.Upgrade/upgrade'); + // 获取升级内容 Route::get('upgrade/[:addon]', 'addon.Upgrade/getUpgradeContent'); + + Route::post('upgrade/operate/:operate', 'addon.Upgrade/operate'); + + // 升级记录分页列表 + Route::get('upgrade/records', 'addon.Upgrade/getRecords'); + + // 备份记录分页列表 + 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([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/adminapi/route/verify.php b/niucloud/app/adminapi/route/verify.php index c544621d1..9ebd6afb4 100644 --- a/niucloud/app/adminapi/route/verify.php +++ b/niucloud/app/adminapi/route/verify.php @@ -28,6 +28,8 @@ Route::group('verify', function () { /***************************************************** 核销员相关接口 ****************************************************/ // 添加核销员 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'); // 获取核销员列表 diff --git a/niucloud/app/adminapi/route/wxoplatform.php b/niucloud/app/adminapi/route/wxoplatform.php index 259edf100..62bf78bc2 100644 --- a/niucloud/app/adminapi/route/wxoplatform.php +++ b/niucloud/app/adminapi/route/wxoplatform.php @@ -38,6 +38,8 @@ Route::group('wxoplatform', function () { Route::get('weapp/commit', 'wxoplatform.WeappVersion/commitRecord'); // 站点小程序提交审核 Route::post('site/weapp/commit', 'wxoplatform.WeappVersion/siteWeappCommit'); + // 按站点套餐获取提交记录 + Route::get('sitegroup/commit', 'wxoplatform.WeappVersion/getSiteGroupCommitRecord'); })->middleware([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/api/controller/sys/Verify.php b/niucloud/app/api/controller/sys/Verify.php index 82c354854..6edc2248e 100644 --- a/niucloud/app/api/controller/sys/Verify.php +++ b/niucloud/app/api/controller/sys/Verify.php @@ -22,53 +22,60 @@ class Verify extends BaseApiController * 获取验证码 * @return Response */ - public function getVerifyCode(){ + public function getVerifyCode() + { $data = $this->request->params([ - ['data', []], - ['type', ''] + [ 'data', [] ], + [ 'type', '' ] ]); - return success(data:(new VerifyService())->getVerifyCode($data['type'], $data['data'])); + return success(data: ( new VerifyService() )->getVerifyCode($data[ 'type' ], $data[ 'data' ])); } /** * 获取核销码信息 * @return Response */ - public function getInfoByCode(){ + public function getInfoByCode() + { $data = $this->request->params([ - ['code', ''], + [ 'code', '' ], ]); - return success(data:(new VerifyService())->getInfoByCode($data['code'])); + return success(data: ( new VerifyService() )->getInfoByCode($data[ 'code' ])); } + /** * 核销 * @param $code * @return Response */ - public function verify($code){ - return success(data:(new VerifyService())->verify($code)); + public function verify($code) + { + return success(data: ( new VerifyService() )->verify($code)); } + /** * 校验是否是核销员 * @return Response */ - public function checkVerifier(){ - return success(data:(new VerifyService())->checkVerifier()); + public function checkVerifier() + { + return success(data: ( new VerifyService() )->checkVerifier()); } /** * 核销记录 * @return void */ - public function records(){ + public function records() + { $data = $this->request->params([ - ['relate_tag', 0], - ['type', ''], - ['code', ''], - ['keyword', ''], - ['create_time', []] + [ 'relate_tag', 0 ], + [ 'type', '' ], + [ 'code', '' ], + [ 'keyword', '' ], + [ '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 * @return Response */ - public function detail(string|int $code){ - return success(data:(new VerifyService())->getRecordsDetailByVerifier($code)); + public function detail(string|int $code) + { + return success(data: ( new VerifyService() )->getRecordsDetailByVerifier($code)); } } diff --git a/niucloud/app/common.php b/niucloud/app/common.php index 7ce5de78c..e6c5cf69d 100644 --- a/niucloud/app/common.php +++ b/niucloud/app/common.php @@ -556,7 +556,7 @@ function dir_copy(string $src = '', string $dst = '', &$files = [], $exclude_dir if (is_dir($src . '/' . $file)) { // 排除目录 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 { // 排除文件 if (count($exclude_files) && in_array($file, $exclude_files)) continue; @@ -1025,10 +1025,13 @@ function get_last_time($time = null) /** * 检查目录及其子目录的权限 - * @param string $dir 要检查的目录路径 - * @return void + * @param $dir 要检查的目录路径 + * @param $data + * @param $exclude_dir 排除排除无需检测的的文件夹 + * @return array|array[]|mixed */ -function checkDirPermissions($dir, $data = []) { +function checkDirPermissions($dir, $data = [], $exclude_dir = []) +{ if (!is_dir($dir)) { throw new \RuntimeException(sprintf('指定的路径 "%s" 不是一个有效的目录', $dir)); } @@ -1042,33 +1045,83 @@ function checkDirPermissions($dir, $data = []) { try { if (!is_readable($dir)) { - $data['unreadable'][] = $dir; + $data[ 'unreadable' ][] = $dir; } if (!is_writable($dir)) { - $data['not_writable'][] = $dir; + $data[ 'not_writable' ][] = $dir; } if (is_readable($dir)) { $dh = opendir($dir); - while (($file = readdir($dh)) !== false) { + while (( $file = readdir($dh) ) !== false) { if ($file === '.' || $file === '..') { continue; } $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)) { - $data = checkDirPermissions($fullPath, $data); // 递归调用自身来检查子目录 + $data = checkDirPermissions($fullPath, $data, $exclude_dir); // 递归调用自身来检查子目录 } else { // 如果是文件,则检查其读写权限 - if (!is_readable($fullPath)) $data['unreadable'][] = $fullPath; - if (!is_writable($fullPath)) $data['not_writable'][] = $fullPath; + if (!is_readable($fullPath)) $data[ 'unreadable' ][] = $fullPath; + if (!is_writable($fullPath)) $data[ 'not_writable' ][] = $fullPath; } } closedir($dh); } return $data; } catch (Exception $e) { - $data['unreadable'][] = $dir; - $data['not_writable'][] = $dir; + $data[ 'unreadable' ][] = $dir; + $data[ 'not_writable' ][] = $dir; 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; +} \ No newline at end of file diff --git a/niucloud/app/dict/diy_form/ComponentDict.php b/niucloud/app/dict/diy_form/ComponentDict.php index 37373a4a7..b55a8bfb1 100644 --- a/niucloud/app/dict/diy_form/ComponentDict.php +++ b/niucloud/app/dict/diy_form/ComponentDict.php @@ -414,56 +414,57 @@ class ComponentDict return $data; } ], - // 'FormWechatName' => [ - // 'title' => '微信名', - // 'icon' => 'iconfont iconbiaotipc', - // 'path' => 'edit-form-wechat-name', // 编辑组件属性名称 - // 'uses' => 1, // 最大添加数量 - // 'sort' => 10007, - // // 组件属性 - // 'template' => [ - // "textColor" => "#303133", // 文字颜色 - // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) - // 'pageEndBgColor' => '', // 底部背景颜色(结束) - // 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) - // 'componentBgUrl' => '', // 组件背景图片 - // 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 - // "componentStartBgColor" => '', // 组件背景颜色(开始) - // "componentEndBgColor" => '', // 组件背景颜色(结束) - // "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) - // "topRounded" => 0, // 组件上圆角 - // "bottomRounded" => 0, // 组件下圆角 - // "elementBgColor" => '', // 元素背景颜色 - // "topElementRounded" => 0,// 元素上圆角 - // "bottomElementRounded" => 0, // 元素下圆角 - // "margin" => [ - // "top" => 10, // 上边距 - // "bottom" => 10, // 下边距 - // "both" => 10 // 左右边距 - // ], - // ], - // 'value' => [ - // // 表单的公共属性 - // 'field' => [ - // 'name' => '微信名', // 字段名称 - // // 字段说明,支持修改颜色、大小 - // 'remark' => [ - // 'text' => '', - // 'color' => '#999999', - // "fontSize" => 14, - // ], - // 'required' => false, // 是否必填 true:是,false:否 - // 'unique' => false, // 内容不可重复提交 true:是,false:否 - // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 - // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 -// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 - // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 - // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 - // ], - // "fontSize" => 14, - // "fontWeight" => "normal", - // ] - // ], +// 'FormWechatName' => [ +// 'title' => '微信名', +// 'icon' => 'iconfont iconbiaotipc', +// 'path' => 'edit-form-wechat-name', // 编辑组件属性名称 +// 'uses' => 1, // 最大添加数量 +// 'sort' => 10007, +// // 组件属性 +// 'template' => [ +// "textColor" => "#303133", // 文字颜色 +// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) +// 'pageEndBgColor' => '', // 底部背景颜色(结束) +// 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) +// 'componentBgUrl' => '', // 组件背景图片 +// 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 +// "componentStartBgColor" => '', // 组件背景颜色(开始) +// "componentEndBgColor" => '', // 组件背景颜色(结束) +// "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) +// "topRounded" => 0, // 组件上圆角 +// "bottomRounded" => 0, // 组件下圆角 +// "elementBgColor" => '', // 元素背景颜色 +// "topElementRounded" => 0,// 元素上圆角 +// "bottomElementRounded" => 0, // 元素下圆角 +// "margin" => [ +// "top" => 10, // 上边距 +// "bottom" => 10, // 下边距 +// "both" => 10 // 左右边距 +// ], +// ], +// 'value' => [ +// // 表单的公共属性 +// 'field' => [ +// 'name' => '微信名', // 字段名称 +// // 字段说明,支持修改颜色、大小 +// 'remark' => [ +// 'text' => '', +// 'color' => '#999999', +// "fontSize" => 14, +// ], +// 'required' => false, // 是否必填 true:是,false:否 +// 'unique' => false, // 内容不可重复提交 true:是,false:否 +// 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 +// 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 +// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 +// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 +// ], +// 'placeholder' => '请输入', // 提示语 +// "fontSize" => 14, +// "fontWeight" => "normal", +// ] +// ], 'FormMobile' => [ 'title' => '手机号', 'icon' => 'iconfont icona-shoujipc30', @@ -617,74 +618,84 @@ class ComponentDict "fontWeight" => "normal", ] ], - // 'FormTable' => [ - // 'title' => '表格', - // 'icon' => 'iconfont iconbiaotipc', - // 'path' => 'edit-form-table', // 编辑组件属性名称 - // 'uses' => 0, // 最大添加数量 - // 'sort' => 10011, - // // 组件属性 - // 'template' => [ - // "textColor" => "#303133", // 文字颜色 - // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) - // 'pageEndBgColor' => '', // 底部背景颜色(结束) - // 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) - // 'componentBgUrl' => '', // 组件背景图片 - // 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 - // "componentStartBgColor" => '', // 组件背景颜色(开始) - // "componentEndBgColor" => '', // 组件背景颜色(结束) - // "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) - // "topRounded" => 0, // 组件上圆角 - // "bottomRounded" => 0, // 组件下圆角 - // "elementBgColor" => '', // 元素背景颜色 - // "topElementRounded" => 0,// 元素上圆角 - // "bottomElementRounded" => 0, // 元素下圆角 - // "margin" => [ - // "top" => 10, // 上边距 - // "bottom" => 10, // 下边距 - // "both" => 10 // 左右边距 - // ], - // ], - // 'value' => [ - // // 表单的公共属性 - // 'field' => [ - // 'name' => '表格', // 字段名称 - // // 字段说明,支持修改颜色、大小 - // 'remark' => [ - // 'text' => '', - // 'color' => '#999999', - // "fontSize" => 14, - // ], - // 'required' => false, // 是否必填 true:是,false:否 - // 'unique' => false, // 内容不可重复提交 true:是,false:否 - // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 - // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 -// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 - // 'detailComponent' => '/src/app/views/diy_form/components/detail-form-table.vue', // 用于详情展示 - // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 - // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 - // ], - // "fontSize" => 14, - // "fontWeight" => "normal", - // // 列设置 - // 'columnList' => [ - // [ - // 'id' => '', // 唯一值,用于排序 - // 'type' => 'text', // 类型,text:文本,number:数字,radio:单选项,checkbox:多选项,todo,不同类型,结构也不一样,这个组件要在前端处理 - // 'name' => '', // 字段名称 - // 'value' => '选项1' // 字段值 - // ], - // ], - // 'autoIncrementControl' => false, // 是否开启自增(展示按钮),添加多个 - // // 填写限制(开启自增才展示) - // 'writeLimit' => [ - // 'default' => 2, // 默认展示 N 项 - // 'min' => 0, // 最少填写 N 项 - // 'max' => 0 // 最多填写 N 项 - // ], - // 'btnText' => '新增一组' - // ] - // ], +// 'FormTable' => [ +// 'title' => '表格', +// 'icon' => 'iconfont iconbiaotipc', +// 'path' => 'edit-form-table', // 编辑组件属性名称 +// 'uses' => 0, // 最大添加数量 +// 'sort' => 10011, +// // 组件属性 +// 'template' => [ +// "textColor" => "#303133", // 文字颜色 +// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) +// 'pageEndBgColor' => '', // 底部背景颜色(结束) +// 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) +// 'componentBgUrl' => '', // 组件背景图片 +// 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 +// "componentStartBgColor" => '', // 组件背景颜色(开始) +// "componentEndBgColor" => '', // 组件背景颜色(结束) +// "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) +// "topRounded" => 0, // 组件上圆角 +// "bottomRounded" => 0, // 组件下圆角 +// "elementBgColor" => '', // 元素背景颜色 +// "topElementRounded" => 0,// 元素上圆角 +// "bottomElementRounded" => 0, // 元素下圆角 +// "margin" => [ +// "top" => 10, // 上边距 +// "bottom" => 10, // 下边距 +// "both" => 10 // 左右边距 +// ], +// ], +// 'value' => [ +// // 表单的公共属性 +// 'field' => [ +// 'name' => '表格', // 字段名称 +// // 字段说明,支持修改颜色、大小 +// 'remark' => [ +// 'text' => '', +// 'color' => '#999999', +// "fontSize" => 14, +// ], +// 'required' => false, // 是否必填 true:是,false:否 +// 'unique' => false, // 内容不可重复提交 true:是,false:否 +// 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 +// 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 +// 'detailComponent' => '/src/app/views/diy_form/components/detail-form-table.vue', // 用于详情展示 +// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 +// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 +// ], +// "fontSize" => 14, +// "fontWeight" => "normal", +// // 列设置 +// 'columnList' => [ +// [ +// 'id' => '', // 唯一值,用于排序 +// 'type' => 'text', // 类型,text:文本,number:数字,radio:单选项,checkbox:多选项,todo,不同类型,结构也不一样,这个组件要在前端处理 +// 'name' => '', // 字段名称 +// 'value' => '选项1' // 字段值 +// ], +// ], +// 'autoIncrementControl' => false, // 是否开启自增(展示按钮),添加多个 +// // 填写限制(开启自增才展示) +// 'writeLimit' => [ +// 'default' => 2, // 默认展示 N 项 +// 'min' => 0, // 最少填写 N 项 +// 'max' => 0 // 最多填写 N 项 +// ], +// 'btnText' => '新增一组' +// ], +// // 渲染值 +// 'render' => function($data) { +// // todo 处理业务数据 +// return ''; +// }, +// // 转换类型 +// 'convert' => function($data) { +// // todo 处理业务数据 +// return $data; +// } +// ], 'FormDate' => [ 'title' => '日期', 'icon' => 'iconfont icona-riqipc30', @@ -727,7 +738,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 - 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => [ // 默认值 存储数据类型不同,各组件自行处理 'date' => '', // 例:2024-12-27 'timestamp' => 0, // 例:1735290511 @@ -799,7 +810,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 - 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 // 默认值 存储数据类型不同,各组件自行处理 'default' => [ // todo 在做的过程中可能会再调整字段名称 @@ -894,7 +905,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 - 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -946,7 +957,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 - 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 // 默认值 存储数据类型不同,各组件自行处理 'default' => [ 'start' => [ @@ -997,109 +1008,109 @@ class ComponentDict return $data; } ], - // 'FormLocation' => [ - // 'title' => '定位', - // 'icon' => 'iconfont iconbiaotipc', - // 'path' => 'edit-form-location', // 编辑组件属性名称 - // 'uses' => 1, // 最大添加数量 - // 'sort' => 10016, - // // 组件属性 - // 'template' => [ - // "textColor" => "#303133", // 文字颜色 - // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) - // 'pageEndBgColor' => '', // 底部背景颜色(结束) - // 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) - // 'componentBgUrl' => '', // 组件背景图片 - // 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 - // "componentStartBgColor" => '', // 组件背景颜色(开始) - // "componentEndBgColor" => '', // 组件背景颜色(结束) - // "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) - // "topRounded" => 0, // 组件上圆角 - // "bottomRounded" => 0, // 组件下圆角 - // "elementBgColor" => '', // 元素背景颜色 - // "topElementRounded" => 0,// 元素上圆角 - // "bottomElementRounded" => 0, // 元素下圆角 - // "margin" => [ - // "top" => 10, // 上边距 - // "bottom" => 10, // 下边距 - // "both" => 10 // 左右边距 - // ], - // ], - // 'value' => [ - // // 表单的公共属性 - // 'field' => [ - // 'name' => '定位', // 字段名称 - // // 字段说明,支持修改颜色、大小 - // 'remark' => [ - // 'text' => '', - // 'color' => '#999999', - // "fontSize" => 14, - // ], - // 'required' => false, // 是否必填 true:是,false:否 - // 'unique' => false, // 内容不可重复提交 true:是,false:否 - // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 - // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 -// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 - // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 - // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 - // ], - // 'placeholder' => '请输入', // 提示语 - // "fontSize" => 14, - // "fontWeight" => "normal", - // 'mode' => 'authorized_wechat_location', // 获取方式,authorized_wechat_location:授权微信定位,open_choose_location:手动选择定位 - // ] - // ], - // 'FormAddress' => [ - // 'title' => '地址', - // 'icon' => 'iconfont iconbiaotipc', - // 'path' => 'edit-form-address', // 编辑组件属性名称 - // 'uses' => 0, // 最大添加数量 - // 'sort' => 10017, - // // 组件属性 - // 'template' => [ - // "textColor" => "#303133", // 文字颜色 - // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) - // 'pageEndBgColor' => '', // 底部背景颜色(结束) - // 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) - // 'componentBgUrl' => '', // 组件背景图片 - // 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 - // "componentStartBgColor" => '', // 组件背景颜色(开始) - // "componentEndBgColor" => '', // 组件背景颜色(结束) - // "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) - // "topRounded" => 0, // 组件上圆角 - // "bottomRounded" => 0, // 组件下圆角 - // "elementBgColor" => '', // 元素背景颜色 - // "topElementRounded" => 0,// 元素上圆角 - // "bottomElementRounded" => 0, // 元素下圆角 - // "margin" => [ - // "top" => 10, // 上边距 - // "bottom" => 10, // 下边距 - // "both" => 10 // 左右边距 - // ], - // ], - // 'value' => [ - // // 表单的公共属性 - // 'field' => [ - // 'name' => '地址', // 字段名称 - // // 字段说明,支持修改颜色、大小 - // 'remark' => [ - // 'text' => '', - // 'color' => '#999999', - // "fontSize" => 14, - // ], - // 'required' => false, // 是否必填 true:是,false:否 - // 'unique' => false, // 内容不可重复提交 true:是,false:否 - // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 - // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 - // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 todo 设置默认省/市/区/街道 - // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 - // ], - // 'placeholder' => '请输入', // 提示语 - // "fontSize" => 14, - // "fontWeight" => "normal", - // 'addressFormat' => 'province/city/district/address', // 地址格式 - // ] - // ], +// 'FormLocation' => [ +// 'title' => '定位', +// 'icon' => 'iconfont iconbiaotipc', +// 'path' => 'edit-form-location', // 编辑组件属性名称 +// 'uses' => 1, // 最大添加数量 +// 'sort' => 10016, +// // 组件属性 +// 'template' => [ +// "textColor" => "#303133", // 文字颜色 +// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) +// 'pageEndBgColor' => '', // 底部背景颜色(结束) +// 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) +// 'componentBgUrl' => '', // 组件背景图片 +// 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 +// "componentStartBgColor" => '', // 组件背景颜色(开始) +// "componentEndBgColor" => '', // 组件背景颜色(结束) +// "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) +// "topRounded" => 0, // 组件上圆角 +// "bottomRounded" => 0, // 组件下圆角 +// "elementBgColor" => '', // 元素背景颜色 +// "topElementRounded" => 0,// 元素上圆角 +// "bottomElementRounded" => 0, // 元素下圆角 +// "margin" => [ +// "top" => 10, // 上边距 +// "bottom" => 10, // 下边距 +// "both" => 10 // 左右边距 +// ], +// ], +// 'value' => [ +// // 表单的公共属性 +// 'field' => [ +// 'name' => '定位', // 字段名称 +// // 字段说明,支持修改颜色、大小 +// 'remark' => [ +// 'text' => '', +// 'color' => '#999999', +// "fontSize" => 14, +// ], +// 'required' => false, // 是否必填 true:是,false:否 +// 'unique' => false, // 内容不可重复提交 true:是,false:否 +// 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 +// 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 +// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 +// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 +// ], +// 'placeholder' => '请输入', // 提示语 +// "fontSize" => 14, +// "fontWeight" => "normal", +// 'mode' => 'authorized_wechat_location', // 获取方式,authorized_wechat_location:授权微信定位,open_choose_location:手动选择定位 +// ] +// ], +// 'FormAddress' => [ +// 'title' => '地址', +// 'icon' => 'iconfont iconbiaotipc', +// 'path' => 'edit-form-address', // 编辑组件属性名称 +// 'uses' => 0, // 最大添加数量 +// 'sort' => 10017, +// // 组件属性 +// 'template' => [ +// "textColor" => "#303133", // 文字颜色 +// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) +// 'pageEndBgColor' => '', // 底部背景颜色(结束) +// 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) +// 'componentBgUrl' => '', // 组件背景图片 +// 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 +// "componentStartBgColor" => '', // 组件背景颜色(开始) +// "componentEndBgColor" => '', // 组件背景颜色(结束) +// "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) +// "topRounded" => 0, // 组件上圆角 +// "bottomRounded" => 0, // 组件下圆角 +// "elementBgColor" => '', // 元素背景颜色 +// "topElementRounded" => 0,// 元素上圆角 +// "bottomElementRounded" => 0, // 元素下圆角 +// "margin" => [ +// "top" => 10, // 上边距 +// "bottom" => 10, // 下边距 +// "both" => 10 // 左右边距 +// ], +// ], +// 'value' => [ +// // 表单的公共属性 +// 'field' => [ +// 'name' => '地址', // 字段名称 +// // 字段说明,支持修改颜色、大小 +// 'remark' => [ +// 'text' => '', +// 'color' => '#999999', +// "fontSize" => 14, +// ], +// 'required' => false, // 是否必填 true:是,false:否 +// 'unique' => false, // 内容不可重复提交 true:是,false:否 +// 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 +// 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 todo 设置默认省/市/区/街道 +// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 +// ], +// 'placeholder' => '请输入', // 提示语 +// "fontSize" => 14, +// "fontWeight" => "normal", +// 'addressFormat' => 'province/city/district/address', // 地址格式 +// ] +// ], 'FormImage' => [ 'title' => '图片', 'icon' => 'iconfont icona-tupianpc30', @@ -1181,115 +1192,115 @@ class ComponentDict return $data; } ], - // 'FormVideo' => [ - // 'title' => '视频', - // 'icon' => 'iconfont iconbiaotipc', - // 'path' => 'edit-form-video', // 编辑组件属性名称 - // 'uses' => 0, // 最大添加数量 - // 'sort' => 10019, - // // 组件属性 - // 'template' => [ - // "textColor" => "#303133", // 文字颜色 - // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) - // 'pageEndBgColor' => '', // 底部背景颜色(结束) - // 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) - // 'componentBgUrl' => '', // 组件背景图片 - // 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 - // "componentStartBgColor" => '', // 组件背景颜色(开始) - // "componentEndBgColor" => '', // 组件背景颜色(结束) - // "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) - // "topRounded" => 0, // 组件上圆角 - // "bottomRounded" => 0, // 组件下圆角 - // "elementBgColor" => '', // 元素背景颜色 - // "topElementRounded" => 0,// 元素上圆角 - // "bottomElementRounded" => 0, // 元素下圆角 - // "margin" => [ - // "top" => 10, // 上边距 - // "bottom" => 10, // 下边距 - // "both" => 10 // 左右边距 - // ], - // ], - // 'value' => [ - // // 表单的公共属性 - // 'field' => [ - // 'name' => '视频', // 字段名称 - // // 字段说明,支持修改颜色、大小 - // 'remark' => [ - // 'text' => '', - // 'color' => '#999999', - // "fontSize" => 14, - // ], - // 'required' => false, // 是否必填 true:是,false:否 - // 'unique' => false, // 内容不可重复提交 true:是,false:否 - // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 - // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 -// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 - // 'detailComponent' => '/src/app/views/diy_form/components/detail-form-video.vue', // 用于详情展示 - // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 - // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 - // ], - // "fontSize" => 14, - // "fontWeight" => "normal", - // /** - // * 上传方式 - // * shoot_and_album:拍摄和相册 - // * shoot_only:只允许拍摄 - // */ - // 'uploadMode' => 'shoot_and_album', // 上传方式 - // ] - // ], - // 'FormFile' => [ - // 'title' => '文件', - // 'icon' => 'iconfont iconbiaotipc', - // 'path' => 'edit-form-file', // 编辑组件属性名称 - // 'uses' => 0, // 最大添加数量 - // 'sort' => 10020, - // // 组件属性 - // 'template' => [ - // "textColor" => "#303133", // 文字颜色 - // 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) - // 'pageEndBgColor' => '', // 底部背景颜色(结束) - // 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) - // 'componentBgUrl' => '', // 组件背景图片 - // 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 - // "componentStartBgColor" => '', // 组件背景颜色(开始) - // "componentEndBgColor" => '', // 组件背景颜色(结束) - // "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) - // "topRounded" => 0, // 组件上圆角 - // "bottomRounded" => 0, // 组件下圆角 - // "elementBgColor" => '', // 元素背景颜色 - // "topElementRounded" => 0,// 元素上圆角 - // "bottomElementRounded" => 0, // 元素下圆角 - // "margin" => [ - // "top" => 10, // 上边距 - // "bottom" => 10, // 下边距 - // "both" => 10 // 左右边距 - // ], - // ], - // 'value' => [ - // // 表单的公共属性 - // 'field' => [ - // 'name' => '文件', // 字段名称 - // // 字段说明,支持修改颜色、大小 - // 'remark' => [ - // 'text' => '', - // 'color' => '#999999', - // "fontSize" => 14, - // ], - // 'required' => false, // 是否必填 true:是,false:否 - // 'unique' => false, // 内容不可重复提交 true:是,false:否 - // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 - // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 -// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 - // 'detailComponent' => '/src/app/views/diy_form/components/detail-form-file.vue', // 用于详情展示 - // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 - // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 - // ], - // "fontSize" => 14, - // "fontWeight" => "normal", - // 'limitUploadSize' => 30720, // 限制上传大小,30MB - // ] - // ], +// 'FormVideo' => [ +// 'title' => '视频', +// 'icon' => 'iconfont iconbiaotipc', +// 'path' => 'edit-form-video', // 编辑组件属性名称 +// 'uses' => 0, // 最大添加数量 +// 'sort' => 10019, +// // 组件属性 +// 'template' => [ +// "textColor" => "#303133", // 文字颜色 +// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) +// 'pageEndBgColor' => '', // 底部背景颜色(结束) +// 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) +// 'componentBgUrl' => '', // 组件背景图片 +// 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 +// "componentStartBgColor" => '', // 组件背景颜色(开始) +// "componentEndBgColor" => '', // 组件背景颜色(结束) +// "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) +// "topRounded" => 0, // 组件上圆角 +// "bottomRounded" => 0, // 组件下圆角 +// "elementBgColor" => '', // 元素背景颜色 +// "topElementRounded" => 0,// 元素上圆角 +// "bottomElementRounded" => 0, // 元素下圆角 +// "margin" => [ +// "top" => 10, // 上边距 +// "bottom" => 10, // 下边距 +// "both" => 10 // 左右边距 +// ], +// ], +// 'value' => [ +// // 表单的公共属性 +// 'field' => [ +// 'name' => '视频', // 字段名称 +// // 字段说明,支持修改颜色、大小 +// 'remark' => [ +// 'text' => '', +// 'color' => '#999999', +// "fontSize" => 14, +// ], +// 'required' => false, // 是否必填 true:是,false:否 +// 'unique' => false, // 内容不可重复提交 true:是,false:否 +// 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 +// 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 +// 'detailComponent' => '/src/app/views/diy_form/components/detail-form-video.vue', // 用于详情展示 +// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 +// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 +// ], +// "fontSize" => 14, +// "fontWeight" => "normal", +// /** +// * 上传方式 +// * shoot_and_album:拍摄和相册 +// * shoot_only:只允许拍摄 +// */ +// 'uploadMode' => 'shoot_and_album', // 上传方式 +// ] +// ], +// 'FormFile' => [ +// 'title' => '文件', +// 'icon' => 'iconfont iconbiaotipc', +// 'path' => 'edit-form-file', // 编辑组件属性名称 +// 'uses' => 0, // 最大添加数量 +// 'sort' => 10020, +// // 组件属性 +// 'template' => [ +// "textColor" => "#303133", // 文字颜色 +// 'pageStartBgColor' => '#FFFFFF', // 底部背景颜色(开始) +// 'pageEndBgColor' => '', // 底部背景颜色(结束) +// 'pageGradientAngle' => 'to bottom', // 渐变角度,从上到下(to bottom)、从左到右(to right) +// 'componentBgUrl' => '', // 组件背景图片 +// 'componentBgAlpha' => 2, // 组件背景图片的透明度,0~10 +// "componentStartBgColor" => '', // 组件背景颜色(开始) +// "componentEndBgColor" => '', // 组件背景颜色(结束) +// "componentGradientAngle" => 'to bottom', // 渐变角度,上下(to bottom)、左右(to right) +// "topRounded" => 0, // 组件上圆角 +// "bottomRounded" => 0, // 组件下圆角 +// "elementBgColor" => '', // 元素背景颜色 +// "topElementRounded" => 0,// 元素上圆角 +// "bottomElementRounded" => 0, // 元素下圆角 +// "margin" => [ +// "top" => 10, // 上边距 +// "bottom" => 10, // 下边距 +// "both" => 10 // 左右边距 +// ], +// ], +// 'value' => [ +// // 表单的公共属性 +// 'field' => [ +// 'name' => '文件', // 字段名称 +// // 字段说明,支持修改颜色、大小 +// 'remark' => [ +// 'text' => '', +// 'color' => '#999999', +// "fontSize" => 14, +// ], +// 'required' => false, // 是否必填 true:是,false:否 +// 'unique' => false, // 内容不可重复提交 true:是,false:否 +// 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 +// 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 +// 'detailComponent' => '/src/app/views/diy_form/components/detail-form-file.vue', // 用于详情展示 +// 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 +// 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 +// ], +// "fontSize" => 14, +// "fontWeight" => "normal", +// 'limitUploadSize' => 30720, // 限制上传大小,30MB +// ] +// ], ], ], ]; diff --git a/niucloud/app/dict/diy_form/TemplateDict.php b/niucloud/app/dict/diy_form/TemplateDict.php index f451e3f0e..cc2cdf0ca 100644 --- a/niucloud/app/dict/diy_form/TemplateDict.php +++ b/niucloud/app/dict/diy_form/TemplateDict.php @@ -381,7 +381,7 @@ class TemplateDict "unique" => false, "autofill" => false, "privacyProtection" => false, - 'cache' => false, + 'cache' => true, "default" => [ "date" => "", "timestamp" => 0 @@ -576,7 +576,7 @@ class TemplateDict "unique" => false, "autofill" => false, "privacyProtection" => false, - 'cache' => false, + 'cache' => true, "default" => [ "start" => [ "date" => "", diff --git a/niucloud/app/dict/menu/admin.php b/niucloud/app/dict/menu/admin.php index e38b90e22..a83733718 100644 --- a/niucloud/app/dict/menu/admin.php +++ b/niucloud/app/dict/menu/admin.php @@ -1167,7 +1167,21 @@ return [ 'router_path' => 'tools/code', 'view_path' => 'tools/code/index', 'methods' => 'get', - 'sort' => '100', + 'sort' => '109', + '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' => '108', 'status' => '1', 'is_show' => '1', ], @@ -1181,7 +1195,7 @@ return [ 'router_path' => 'tools/code/edit', 'view_path' => 'tools/code/edit', 'methods' => '', - 'sort' => '99', + 'sort' => '100', 'status' => '1', 'is_show' => '0', 'children' => [ @@ -1253,7 +1267,7 @@ return [ 'router_path' => 'tools/addon_edit', 'view_path' => 'tools/addon/edit', 'methods' => 'get', - 'sort' => '90', + 'sort' => '100', 'status' => '1', 'is_show' => '0', 'children' => [ @@ -1297,7 +1311,7 @@ return [ 'router_path' => 'tools/list', 'view_path' => 'dict/list', 'methods' => 'get', - 'sort' => '90', + 'sort' => '107', 'status' => '1', 'is_show' => '1', 'children' => [ @@ -1355,7 +1369,7 @@ return [ 'router_path' => 'tools/detection', 'view_path' => 'tools/detection', 'methods' => '', - 'sort' => '50', + 'sort' => '106', 'status' => '1', 'is_show' => '1', ], @@ -1369,7 +1383,7 @@ return [ 'router_path' => 'tools/admin_menu', 'view_path' => 'auth/menu', 'methods' => 'get', - 'sort' => '49', + 'sort' => '105', 'status' => '1', 'is_show' => '1', 'children' => [ @@ -1441,7 +1455,7 @@ return [ 'router_path' => 'tools/site_menu', 'view_path' => 'auth/site_menu', 'methods' => 'get', - 'sort' => '48', + 'sort' => '104', 'status' => '1', 'is_show' => '1', 'children' => [ @@ -1513,7 +1527,7 @@ return [ 'router_path' => 'tools/schedule', 'view_path' => 'tools/schedule', 'methods' => '', - 'sort' => '40', + 'sort' => '103', 'status' => '1', 'is_show' => '1', 'children' => [ @@ -1585,7 +1599,7 @@ return [ 'router_path' => 'tools/schedule_log', 'view_path' => 'tools/schedule_log', 'methods' => '', - 'sort' => '40', + 'sort' => '100', 'status' => '1', 'is_show' => '0' ], @@ -1599,24 +1613,10 @@ return [ 'router_path' => 'tools/authorize', 'view_path' => 'app/authorize', 'methods' => '', - 'sort' => '30', + 'sort' => '102', 'status' => '1', 'is_show' => '1', '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_key' => 'bind_app_auth', @@ -1633,6 +1633,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_key' => 'developer_token', @@ -1643,7 +1699,7 @@ return [ 'router_path' => 'tools/developer_token', 'view_path' => 'setting/developer_token', 'methods' => 'get', - 'sort' => '20', + 'sort' => '97', 'status' => '1', 'is_show' => '1', 'children' => [ @@ -1663,20 +1719,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' => '100', - 'status' => '1', - 'is_show' => '1', - ] ], ], diff --git a/niucloud/app/dict/menu/site.php b/niucloud/app/dict/menu/site.php index 80254c232..183c16bca 100644 --- a/niucloud/app/dict/menu/site.php +++ b/niucloud/app/dict/menu/site.php @@ -936,6 +936,20 @@ return [ 'status' => '1', 'is_show' => '1', ], + [ + 'menu_name' => '编辑核销员', + 'menu_key' => 'edit_verifier', + 'menu_short_name' => '编辑核销员', + 'menu_type' => '2', + 'icon' => '', + 'api_url' => 'verify/verifier/', + 'router_path' => '', + 'view_path' => '', + 'methods' => 'post', + 'sort' => '100', + 'status' => '1', + 'is_show' => '1', + ], [ 'menu_name' => '删除核销员', 'menu_key' => 'delete_verifier', @@ -1102,7 +1116,7 @@ return [ 'methods' => 'get', 'sort' => '100', 'status' => '1', - 'is_show' => '1', + 'is_show' => '', 'children' => [ [ 'menu_name' => '保存', @@ -2217,122 +2231,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/', - '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/', - '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/', - '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/', - 'router_path' => 'printer/template/edit', - 'view_path' => 'printer/template_edit', - 'methods' => 'put', - 'sort' => '0', - 'status' => '1', - 'is_show' => '0', - ], [ 'menu_name' => '系统工具', 'menu_key' => 'setting_tool', @@ -2479,36 +2377,7 @@ 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/', - 'router_path' => '', - 'view_path' => '', - 'methods' => 'delete', - 'sort' => '100', - 'status' => '1', - 'is_show' => '1', - ] - ] - ], + ] ], @@ -2638,5 +2507,188 @@ return [ ], ], ] - ] + ], + [ + '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/', + '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/', + '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/', + '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/', + '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/', + 'router_path' => 'printer/template/edit', + 'view_path' => 'printer/template_edit', + 'methods' => 'put', + 'sort' => '0', + 'status' => '1', + 'is_show' => '0', + ], + ] + ], ]; diff --git a/niucloud/app/dict/schedule/schedule.php b/niucloud/app/dict/schedule/schedule.php index 63c71e46c..83640b879 100644 --- a/niucloud/app/dict/schedule/schedule.php +++ b/niucloud/app/dict/schedule/schedule.php @@ -25,7 +25,19 @@ return [ 'class' => 'app\job\schedule\SiteExpireClose', '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', 'name' => '检验在线转账是否处理完毕', @@ -37,6 +49,17 @@ return [ 'class' => 'app\job\transfer\schedule\CheckFinish', 'function' => '' ], + [ + 'key' => 'auto_clear_upgrade_records', + 'name' => '定时清理升级/备份记录表', + 'desc' => '', + 'time' => [ + 'type' => 'min', + 'min' => 1 + ], + 'class' => 'app\job\upgrade\AutoClearUpgradeRecords', + 'function' => '' + ], // [ // 'key' => 'site_stat', // 'name' => '站点统计', diff --git a/niucloud/app/dict/sys/BackupDict.php b/niucloud/app/dict/sys/BackupDict.php new file mode 100644 index 000000000..ab45262b8 --- /dev/null +++ b/niucloud/app/dict/sys/BackupDict.php @@ -0,0 +1,34 @@ + 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 ] ?? ''; + } +} diff --git a/niucloud/app/dict/sys/CloudDict.php b/niucloud/app/dict/sys/CloudDict.php index f531a14ed..86c74d0b0 100644 --- a/niucloud/app/dict/sys/CloudDict.php +++ b/niucloud/app/dict/sys/CloudDict.php @@ -28,7 +28,7 @@ class CloudDict const APPLET_AUDIT_FAIL = -2; - public static function getAppletUploadSatus($status) { + public static function getAppletUploadStatus($status) { $status_list = [ self::APPLET_UPLOADING => get_lang('dict_cloud_applet.uploading'), self::APPLET_UPLOAD_SUCCESS => get_lang('dict_cloud_applet.upload_success'), diff --git a/niucloud/app/dict/sys/UpgradeDict.php b/niucloud/app/dict/sys/UpgradeDict.php new file mode 100644 index 000000000..912fb5b98 --- /dev/null +++ b/niucloud/app/dict/sys/UpgradeDict.php @@ -0,0 +1,37 @@ + get_lang('dict_upgrade.ready'), + self::STATUS_COMPLETE => get_lang('dict_upgrade.complete'), + self::STATUS_FAIL => get_lang('dict_upgrade.fail'), + ]; + return $status_list[ $status ] ?? ''; + } +} diff --git a/niucloud/app/install/source/database.sql b/niucloud/app/install/source/database.sql index 7d785c7f2..e668ecbda 100644 --- a/niucloud/app/install/source/database.sql +++ b/niucloud/app/install/source/database.sql @@ -150,7 +150,7 @@ CREATE TABLE `diy_form_submit_config` ( `site_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:核销凭证', - `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 '自定义提示内容', `time_limit_type` VARCHAR(255) NOT NULL DEFAULT '0' COMMENT '核销凭证有效期限制类型,no_limit:不限制,specify_time:指定固定开始结束时间,submission_time:按提交时间设置有效期', `time_limit_rule` TEXT DEFAULT NULL COMMENT '核销凭证时间限制规则,json格式', @@ -290,7 +290,7 @@ CREATE TABLE `generate_table` ( DROP TABLE IF EXISTS `jobs`; CREATE TABLE `jobs` ( `id` int(11) NOT NULL AUTO_INCREMENT, - `queue` varchar(255) NOT NULL, + `queue` varchar(255) NOT NULL DEFAULT '', `payload` longtext NOT NULL, `attempts` tinyint(4) UNSIGNED NOT NULL DEFAULT 0, `reserve_time` int(11) UNSIGNED NULL DEFAULT 0, @@ -514,7 +514,7 @@ CREATE TABLE `pay` ( `trade_id` int(11) NOT NULL DEFAULT 0 COMMENT '业务id', `trade_no` varchar(255) 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 '支付票据', `status` int(11) NOT NULL DEFAULT 0 COMMENT '支付状态(0.待支付 1. 支付中 2. 已支付 -1已取消)', `json` varchar(255) NOT NULL DEFAULT '' COMMENT '支付扩展用支付信息', @@ -599,7 +599,7 @@ CREATE TABLE `pay_transfer` ( `transfer_payee` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '在线转账数据(json)', `out_batch_no` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '扩展数据,主要用于记录接收到线上打款的业务数据编号', `package_info` VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '跳转领取页面的package信息', - `extra` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '扩展信息', + `extra` VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '扩展信息', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '转账表' ROW_FORMAT = Dynamic; @@ -618,7 +618,7 @@ CREATE TABLE `pay_transfer_scene` ( DROP TABLE IF EXISTS `site`; CREATE TABLE `site` ( - `site_id` int(11) NOT NULL AUTO_INCREMENT, + `site_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `site_name` varchar(50) NOT NULL DEFAULT '' COMMENT '站点名称', `group_id` int(11) NOT NULL DEFAULT 0 COMMENT '分组ID(0:不限制)', `keywords` varchar(255) NOT NULL DEFAULT '' COMMENT '关键字', @@ -775,6 +775,22 @@ CREATE TABLE `sys_attachment_category` ( ) 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(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_config`; CREATE TABLE `sys_config` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', @@ -1053,6 +1069,24 @@ CREATE TABLE `sys_schedule_log` ( ) 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(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` VARCHAR(255) NOT NULL DEFAULT '' 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='升级记录表'; + + DROP TABLE IF EXISTS `sys_user`; CREATE TABLE `sys_user` ( `uid` smallint(5) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '系统用户ID', diff --git a/niucloud/app/job/schedule/AutoClearScheduleLog.php b/niucloud/app/job/schedule/AutoClearScheduleLog.php new file mode 100644 index 000000000..0c7c7128f --- /dev/null +++ b/niucloud/app/job/schedule/AutoClearScheduleLog.php @@ -0,0 +1,47 @@ +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; + } + + } +} diff --git a/niucloud/app/job/upgrade/AutoClearUpgradeRecords.php b/niucloud/app/job/upgrade/AutoClearUpgradeRecords.php new file mode 100644 index 000000000..14760efd0 --- /dev/null +++ b/niucloud/app/job/upgrade/AutoClearUpgradeRecords.php @@ -0,0 +1,54 @@ +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; + } + + } +} diff --git a/niucloud/app/job/wxoplatform/GetVersionUploadResult.php b/niucloud/app/job/wxoplatform/GetVersionUploadResult.php index fb79631e7..6cbc5739d 100644 --- a/niucloud/app/job/wxoplatform/GetVersionUploadResult.php +++ b/niucloud/app/job/wxoplatform/GetVersionUploadResult.php @@ -25,9 +25,9 @@ class GetVersionUploadResult extends BaseJob * @param $data * @return true */ - protected function doJob($task_key) + protected function doJob($task_key, $is_all) { - WeappVersionService::getVersionUploadResult($task_key); + WeappVersionService::getVersionUploadResult($task_key, $is_all); return true; } diff --git a/niucloud/app/job/wxoplatform/VersionUploadSuccess.php b/niucloud/app/job/wxoplatform/VersionUploadSuccess.php index ddc7fe650..673094db2 100644 --- a/niucloud/app/job/wxoplatform/VersionUploadSuccess.php +++ b/niucloud/app/job/wxoplatform/VersionUploadSuccess.php @@ -25,9 +25,9 @@ class VersionUploadSuccess extends BaseJob * @param $data * @return true */ - protected function doJob($task_key) + protected function doJob($task_key, $is_all) { - WeappVersionService::uploadSuccess($task_key); + WeappVersionService::uploadSuccess($task_key, $is_all); return true; } diff --git a/niucloud/app/lang/zh-cn/api.php b/niucloud/app/lang/zh-cn/api.php index 11512d0c7..f3286c45b 100644 --- a/niucloud/app/lang/zh-cn/api.php +++ b/niucloud/app/lang/zh-cn/api.php @@ -37,6 +37,7 @@ return [ 'SERVER_CROSS_REQUEST_FAIL' => '服务器跨域请求异常', 'ADDON_INSTALL_NOT_EXIST' => '未找到插件安装任务', 'ADDON_INSTALL_EXECUTED' => '插件安装任务已执行', + 'ADDON_INSTALLING' => '插件安装中', 'INSTALL_CHECK_NOT_PASS' => '安装校验未通过', 'SITE_INDEX_VIEW_PATH_NOT_EXIST' => '当前首页路径不存在', 'ADMIN_INDEX_VIEW_PATH_NOT_EXIST' => '当前首页路径不存在', @@ -59,6 +60,9 @@ return [ 'ADDON_ZIP_ERROR' => '插件压缩失败', 'PHP_SCRIPT_RUNNING_OUT_OF_MEMORY' => 'PHP脚本运行内存不足, 具体操作方法点击查看相关手册', 'BEFORE_UPGRADING_NEED_UPGRADE_FRAMEWORK' => '升级插件前需要先升级框架', + 'UPGRADE_RECORD_NOT_EXIST' => '升级记录不存在', + 'UPGRADE_BACKUP_CODE_NOT_FOUND' => '未找到备份的源码文件', + 'UPGRADE_BACKUP_SQL_NOT_FOUND' => '未找到备份的数据库文件', //登录注册重置账号.... 'LOGIN_SUCCESS' => '登录成功', @@ -308,6 +312,8 @@ return [ 'VERIFY_TYPE_ERROR' => '核销类型错误', 'VERIFY_CODE_EXPIRED' => '当前核销码已核销或已失效', 'VERIFIER_NOT_EXIST' => '核销员不存在', + 'VERIFIER_EXIST'=>'核销员已存在', + 'VERIFIER_NOT_AUTH' => '该核销员没有权限', //签到相关 'SIGN_NOT_USE' => '签到未开启', diff --git a/niucloud/app/lang/zh-cn/dict.php b/niucloud/app/lang/zh-cn/dict.php index e70c08cf0..8e9a1c283 100644 --- a/niucloud/app/lang/zh-cn/dict.php +++ b/niucloud/app/lang/zh-cn/dict.php @@ -410,5 +410,15 @@ return [ // 打印机品牌 'dict_printer' => [ 'yilianyun' => '易联云打印机' + ], + 'dict_upgrade' => [ + 'ready' => '准备执行', + 'complete' => '完成', + 'fail' => '失败' + ], + 'dict_backup' => [ + 'ready' => '准备执行', + 'complete' => '完成', + 'fail' => '失败' ] ]; diff --git a/niucloud/app/listener/system/ShowAppListener.php b/niucloud/app/listener/system/ShowAppListener.php index f67b65f3b..508272e14 100644 --- a/niucloud/app/listener/system/ShowAppListener.php +++ b/niucloud/app/listener/system/ShowAppListener.php @@ -37,13 +37,20 @@ class ShowAppListener 'key' => 'diy_form', 'url' => '/diy_form/list', ], -// [ -// 'title' => '万能a表单', -// 'desc' => '万能a表单', -// 'icon' => 'static/resource/images/diy_form/icon.png', -// 'key' => 'diy_faorm', -// 'url' => '/diy_faorm/list', -// ] + [ + 'title' => '小票打印', + 'desc' => '支持打印机添加,便捷创建小票打印模板', + 'icon' => 'static/resource/images/tool/printer_icon.png', + 'key' => 'printer_management', + 'url' => '/printer/list', + ], + [ + 'title' => '数据导出', + 'desc' => '展示导出文件,支持删除与下载', + 'icon' => 'static/resource/images/tool/export_icon.png', + 'key' => 'setting_export', + 'url' => '/setting/export', + ], ], // 营销 'promotion' => [ diff --git a/niucloud/app/model/member/Member.php b/niucloud/app/model/member/Member.php index 7b0cb364b..eaa90792c 100644 --- a/niucloud/app/model/member/Member.php +++ b/niucloud/app/model/member/Member.php @@ -202,9 +202,16 @@ class Member extends BaseModel */ public function searchMemberLabelAttr(Query $query, $value, $data) { + 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'); } + } /** diff --git a/niucloud/app/model/sys/SysBackupRecords.php b/niucloud/app/model/sys/SysBackupRecords.php new file mode 100644 index 000000000..d8f60b062 --- /dev/null +++ b/niucloud/app/model/sys/SysBackupRecords.php @@ -0,0 +1,112 @@ + '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) . '%'); + } + } +} diff --git a/niucloud/app/model/sys/SysUpgradeRecords.php b/niucloud/app/model/sys/SysUpgradeRecords.php new file mode 100644 index 000000000..312c1bfa7 --- /dev/null +++ b/niucloud/app/model/sys/SysUpgradeRecords.php @@ -0,0 +1,120 @@ + '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'); + } +} diff --git a/niucloud/app/model/sys/WxOplatfromWeappVersion.php b/niucloud/app/model/sys/WxOplatfromWeappVersion.php index 8bae91dac..402475e3b 100644 --- a/niucloud/app/model/sys/WxOplatfromWeappVersion.php +++ b/niucloud/app/model/sys/WxOplatfromWeappVersion.php @@ -46,6 +46,18 @@ class WxOplatfromWeappVersion extends BaseModel public function getStatusNameAttr($value, $data) { if (!isset($data['status'])) return ''; - return CloudDict::getAppletUploadSatus($data['status']); + return CloudDict::getAppletUploadStatus($data['status']); + } + + /** + * @param $query + * @param $value + * @param $data + * @return void + */ + public function searchSiteGroupIdAttr($query, $value, $data) { + if (!empty($value)) { + $query->where('site_group_id', '=', $value); + } } } diff --git a/niucloud/app/model/verify/Verify.php b/niucloud/app/model/verify/Verify.php index c6dd1a650..1f7b8ac78 100644 --- a/niucloud/app/model/verify/Verify.php +++ b/niucloud/app/model/verify/Verify.php @@ -18,8 +18,6 @@ use think\db\Query; /** * 核销记录模型 - * Class Poster - * @package app\model\verify */ class Verify extends BaseModel { @@ -37,12 +35,13 @@ class Verify extends BaseModel protected $name = 'verify'; // 设置json类型字段 - protected $json = [ 'data' , 'value']; + protected $json = [ 'data', 'value' ]; // 设置JSON数据返回数组 protected $jsonAssoc = true; - public function member() { + public function member() + { return $this->hasOne(Member::class, 'member_id', 'verifier_member_id'); } @@ -85,6 +84,7 @@ class Verify extends BaseModel $query->where('relate_tag', '=', $value); } } + /** * 核销员 * @param $query @@ -120,14 +120,14 @@ class Verify extends BaseModel */ public function searchCreateTimeAttr(Query $query, $value, $data) { - $start_time = empty($value[0]) ? 0 : strtotime($value[0]); - $end_time = empty($value[1]) ? 0 : strtotime($value[1]); + $start_time = empty($value[ 0 ]) ? 0 : strtotime($value[ 0 ]); + $end_time = empty($value[ 1 ]) ? 0 : strtotime($value[ 1 ]); if ($start_time > 0 && $end_time > 0) { $query->whereBetweenTime('create_time', $start_time, $end_time); } 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) { - $query->where([['create_time', '<=', $end_time]]); + $query->where([ [ 'create_time', '<=', $end_time ] ]); } } @@ -136,10 +136,11 @@ class Verify extends BaseModel * @param $value * @return void */ - public function getTypeNameAttr($value, $data) { - if (empty($data['type'])) + public function getTypeNameAttr($value, $data) + { + if (empty($data[ 'type' ])) return ''; - return VerifyDict::getType()[$data['type']]['name'] ?? ''; + return VerifyDict::getType()[ $data[ 'type' ] ][ 'name' ] ?? ''; } } diff --git a/niucloud/app/model/weapp/WeappVersion.php b/niucloud/app/model/weapp/WeappVersion.php index 73d169d72..b67da1df4 100644 --- a/niucloud/app/model/weapp/WeappVersion.php +++ b/niucloud/app/model/weapp/WeappVersion.php @@ -35,6 +35,6 @@ class WeappVersion extends BaseModel protected $name = 'weapp_version'; public function getStatusNameAttr($value, $data) { - if (isset($data['status'])) return CloudDict::getAppletUploadSatus($data['status']); + if (isset($data['status'])) return CloudDict::getAppletUploadStatus($data['status']); } } diff --git a/niucloud/app/service/admin/diy/DiyService.php b/niucloud/app/service/admin/diy/DiyService.php index 5b057c93e..133542e2b 100644 --- a/niucloud/app/service/admin/diy/DiyService.php +++ b/niucloud/app/service/admin/diy/DiyService.php @@ -21,7 +21,6 @@ use app\model\diy\Diy; use app\model\diy\DiyTheme; use app\service\admin\sys\SystemService; use app\service\core\diy\CoreDiyConfigService; -use app\service\core\diy\CoreDiyService; use app\service\core\site\CoreSiteService; use core\base\BaseAdminService; use core\exception\AdminException; @@ -66,9 +65,8 @@ class DiyService extends BaseAdminService * @param array $where * @return array */ - public function getPageByCarouselSearch(array $where = []) + public function getPageByCarouselSearch() { - $where[] = [ 'site_id', '=', $this->site_id ]; $field = 'id,site_id,title,page_title,name,template,type,mode,is_default,share,visit_count,create_time,update_time,value'; $order = "update_time desc"; $search_model = $this->model->whereOr([ @@ -821,26 +819,28 @@ class DiyService extends BaseAdminService public function getDiyTheme() { $site_addon = ( new CoreSiteService() )->getSiteCache($this->site_id); - $theme_data = ( new DiyTheme() )->where([['site_id', '=', $this->site_id], ['type', '=', 'app'], ['is_selected', '=', 1]])->column('id,title,theme','addon'); - $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app'])))[0] ?? []; - $app_theme['app'] = [ - 'id' => $theme_data['app']['id'] ?? '', + $theme_data = ( new DiyTheme() )->where([ [ 'site_id', '=', $this->site_id ], [ 'type', '=', 'app' ], [ 'is_selected', '=', 1 ] ])->column('id,title,theme', 'addon'); + $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app' ])))[ 0 ] ?? []; + $app_theme[ 'app' ] = [ + 'id' => $theme_data[ 'app' ][ 'id' ] ?? '', 'icon' => '', 'addon_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'] : '') + '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' ] : '' ) ]; $data = []; - foreach ($site_addon[ 'apps' ] as $value){ - $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value['key']])))[0] ?? []; - $data[$value['key']]['id'] = $theme_data[$value['key']]['id'] ?? ''; - $data[$value['key']]['icon'] = $value['icon'] ?? ''; - $data[$value['key']]['addon_title'] = $value['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' ] : ''); + foreach ($site_addon[ 'apps' ] as $value) { + $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'key' ] ])))[ 0 ] ?? []; + if (!empty($addon_theme) && !empty($addon_theme[ 'theme_color' ])) { + $data[ $value[ 'key' ] ][ 'id' ] = $theme_data[ $value[ 'key' ] ][ 'id' ] ?? ''; + $data[ $value[ 'key' ] ][ 'icon' ] = $value[ 'icon' ] ?? ''; + $data[ $value[ 'key' ] ][ 'addon_title' ] = $value[ 'title' ] ?? ''; + $data[ $value[ 'key' ] ][ 'title' ] = $theme_data[ $value[ 'key' ] ][ 'title' ] ?? $addon_theme[ 'theme_color' ][ 0 ][ 'title' ]; + $data[ $value[ 'key' ] ][ 'theme' ] = $theme_data[ $value[ 'key' ] ][ 'theme' ] ?? $addon_theme[ 'theme_color' ][ 0 ][ 'theme' ]; + } } - if (count($site_addon[ 'apps' ]) > 1) {// 应用数量大于1时,展示系统主题色设置,只有一个应用时,不展示系统主题色设置 - $data = array_merge($app_theme,$data); + if (empty($data) || count($site_addon[ 'apps' ]) > 1) {// 应用数量大于1时,展示系统主题色设置,只有一个应用时,不展示系统主题色设置 + $data = array_merge($app_theme, $data); } return $data; @@ -854,20 +854,20 @@ class DiyService extends BaseAdminService public function setDiyTheme($data) { $diy_theme_model = new DiyTheme(); - $diy_theme_count = $diy_theme_model->where([['id', '=', $data['id']], ['site_id', '=', $this->site_id]])->count(); + $diy_theme_count = $diy_theme_model->where([ [ 'id', '=', $data[ 'id' ] ], [ 'site_id', '=', $this->site_id ] ])->count(); if ($diy_theme_count == 0) throw new AdminException("DIY_THEME_COLOR_NOT_EXIST"); // 应用选择主题色(is_selected)发生变更时,主应用下的插件也同步发生变更 - $addon_data = (new addon())->field('key')->where([['support_app', '=', $data['addon']]])->select()->toArray(); + $addon_data = ( new addon() )->field('key')->where([ [ 'support_app', '=', $data[ 'addon' ] ] ])->select()->toArray(); $addon_save_data = []; - if (!empty($addon_data)){ - foreach ($addon_data as $value){ + if (!empty($addon_data)) { + foreach ($addon_data as $value) { $addon_save_data[] = [ 'site_id' => $this->site_id, 'type' => 'addon', - 'addon' => $value['key'], - 'title' => $data['title'], - 'theme' => $data['theme'], - 'new_theme' => $data['new_theme'], + 'addon' => $value[ 'key' ], + 'title' => $data[ 'title' ], + 'theme' => $data[ 'theme' ], + 'new_theme' => $data[ 'new_theme' ], 'is_selected' => 1, 'update_time' => time(), ]; @@ -876,15 +876,15 @@ class DiyService extends BaseAdminService try { Db::startTrans(); - if(!empty($data['id'])){ - $diy_theme_model->where([['addon', '=', $data['addon']], ['is_selected', '=', 1], ['site_id', '=', $this->site_id]])->update(['is_selected' => 0]); - $data['is_selected'] = 1; - $data['update_time'] = time(); - $diy_theme_model->where([['id', '=', $data['id']], ['site_id', '=', $this->site_id]])->update($data); - if (!empty($addon_save_data)){ - foreach ($addon_save_data as $value){ - $diy_theme_model->where([['addon', '=', $value['addon']], ['is_selected', '=', 1], ['site_id', '=', $this->site_id]])->update(['is_selected' => 0]); - $diy_theme_model->where([['addon', '=', $value['addon']], ['title', '=', $data['title']], ['site_id', '=', $this->site_id]])->update($value); + if (!empty($data[ 'id' ])) { + $diy_theme_model->where([ [ 'addon', '=', $data[ 'addon' ] ], [ 'is_selected', '=', 1 ], [ 'site_id', '=', $this->site_id ] ])->update([ 'is_selected' => 0 ]); + $data[ 'is_selected' ] = 1; + $data[ 'update_time' ] = time(); + $diy_theme_model->where([ [ 'id', '=', $data[ 'id' ] ], [ 'site_id', '=', $this->site_id ] ])->update($data); + if (!empty($addon_save_data)) { + foreach ($addon_save_data as $value) { + $diy_theme_model->where([ [ 'addon', '=', $value[ 'addon' ] ], [ 'is_selected', '=', 1 ], [ 'site_id', '=', $this->site_id ] ])->update([ 'is_selected' => 0 ]); + $diy_theme_model->where([ [ 'addon', '=', $value[ 'addon' ] ], [ 'title', '=', $data[ 'title' ] ], [ 'site_id', '=', $this->site_id ] ])->update($value); } } } @@ -902,11 +902,11 @@ class DiyService extends BaseAdminService */ public function getDefaultThemeColor($data) { - $theme_list = ( new DiyTheme() )->field('id,title,addon,default_theme,theme,new_theme,theme_type')->where([['site_id', '=', $this->site_id], ['addon', '=', $data['addon']]])->select()->toArray(); + $theme_list = ( new DiyTheme() )->field('id,title,addon,default_theme,theme,new_theme,theme_type')->where([ [ 'site_id', '=', $this->site_id ], [ 'addon', '=', $data[ 'addon' ] ] ])->select()->toArray(); foreach ($theme_list as &$value) { - $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value['addon'] ])))[0] ?? []; - if (!empty($addon_theme) && !empty($addon_theme['theme_field'])) { - $value['theme_field'] = $addon_theme['theme_field'];//返回各个应用的主题颜色字段 + $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'addon' ] ])))[ 0 ] ?? []; + if (!empty($addon_theme) && !empty($addon_theme[ 'theme_field' ])) { + $value[ 'theme_field' ] = $addon_theme[ 'theme_field' ];//返回各个应用的主题颜色字段 } } return $theme_list; @@ -920,18 +920,18 @@ class DiyService extends BaseAdminService public function addDiyTheme($data) { // 主应用添加自定义主题色时,主应用下的插件也同步添加自定义主题色 - $addon_data = (new addon())->field('key')->where([['support_app', '=', $data['addon']]])->select()->toArray(); + $addon_data = ( new addon() )->field('key')->where([ [ 'support_app', '=', $data[ 'addon' ] ] ])->select()->toArray(); $addon_save_data = []; - if (!empty($addon_data)){ - foreach ($addon_data as $value){ + if (!empty($addon_data)) { + foreach ($addon_data as $value) { $addon_save_data[] = [ 'site_id' => $this->site_id, 'type' => 'addon', - 'addon' => $value['key'], - 'title' => $data['title'], - 'default_theme' => $data['default_theme'], - 'theme' => $data['theme'], - 'new_theme' => $data['new_theme'], + 'addon' => $value[ 'key' ], + 'title' => $data[ 'title' ], + 'default_theme' => $data[ 'default_theme' ], + 'theme' => $data[ 'theme' ], + 'new_theme' => $data[ 'new_theme' ], 'theme_type' => 'diy', 'create_time' => time(), ]; @@ -946,7 +946,7 @@ class DiyService extends BaseAdminService $data[ 'create_time' ] = time(); $diy_theme_model = new DiyTheme(); $diy_theme_model->create($data); - if (!empty($addon_save_data)){ + if (!empty($addon_save_data)) { $diy_theme_model->insertAll($addon_save_data); } Db::commit(); @@ -969,15 +969,15 @@ class DiyService extends BaseAdminService $diy_theme_info = $diy_theme_model->field('title')->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->findOrEmpty()->toArray(); if (empty($diy_theme_info)) throw new AdminException("DIY_THEME_COLOR_NOT_EXIST"); // 主应用主题颜色发生改变时,主应用下的插件也同步更新主题颜色 - $addon_data = $diy_theme_model->field('id')->where([ [ 'title', '=', $diy_theme_info['title'] ], [ 'type', '=', 'addon' ], [ 'site_id', '=', $this->site_id ] ])->select()->toArray(); + $addon_data = $diy_theme_model->field('id')->where([ [ 'title', '=', $diy_theme_info[ 'title' ] ], [ 'type', '=', 'addon' ], [ 'site_id', '=', $this->site_id ] ])->select()->toArray(); $addon_save_data = []; - if (!empty($addon_data)){ - foreach ($addon_data as $value){ + if (!empty($addon_data)) { + foreach ($addon_data as $value) { $addon_save_data[] = [ - 'id' => $value['id'], - 'title' => $data['title'], - 'theme' => $data['theme'], - 'new_theme' => $data['new_theme'], + 'id' => $value[ 'id' ], + 'title' => $data[ 'title' ], + 'theme' => $data[ 'theme' ], + 'new_theme' => $data[ 'new_theme' ], 'update_time' => time(), ]; } @@ -987,7 +987,7 @@ class DiyService extends BaseAdminService try { $data[ 'update_time' ] = time(); $diy_theme_model->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->update($data); - if (!empty($addon_save_data)){ + if (!empty($addon_save_data)) { $diy_theme_model->saveAll($addon_save_data); } Db::commit(); @@ -1008,9 +1008,9 @@ class DiyService extends BaseAdminService $diy_theme_model = new DiyTheme(); $diy_theme_info = $diy_theme_model->field('title,theme_type,is_selected')->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->findOrEmpty()->toArray(); if (empty($diy_theme_info)) throw new AdminException("DIY_THEME_COLOR_NOT_EXIST"); - if ($diy_theme_info['theme_type'] == 'default') throw new AdminException("DIY_THEME_DEFAULT_COLOR_CAN_NOT_DELETE"); - if ($diy_theme_info['is_selected'] == 1) throw new AdminException("DIY_THEME_SELECTED_CAN_NOT_DELETE"); - $res = $diy_theme_model->where([ [ 'title', '=', $diy_theme_info['title'] ], [ 'site_id', '=', $this->site_id ] ])->delete(); + if ($diy_theme_info[ 'theme_type' ] == 'default') throw new AdminException("DIY_THEME_DEFAULT_COLOR_CAN_NOT_DELETE"); + if ($diy_theme_info[ 'is_selected' ] == 1) throw new AdminException("DIY_THEME_SELECTED_CAN_NOT_DELETE"); + $res = $diy_theme_model->where([ [ 'title', '=', $diy_theme_info[ 'title' ] ], [ 'site_id', '=', $this->site_id ] ])->delete(); return $res; } @@ -1023,7 +1023,7 @@ class DiyService extends BaseAdminService { $where = [ [ 'title', "=", $data[ 'title' ] ], - [ 'addon', "=", $data['addon'] ], + [ 'addon', "=", $data[ 'addon' ] ], [ 'site_id', "=", $this->site_id ] ]; if (!empty($data[ 'id' ])) { diff --git a/niucloud/app/service/admin/diy_form/DiyFormService.php b/niucloud/app/service/admin/diy_form/DiyFormService.php index 40261de66..5b3c26eb9 100644 --- a/niucloud/app/service/admin/diy_form/DiyFormService.php +++ b/niucloud/app/service/admin/diy_form/DiyFormService.php @@ -639,39 +639,6 @@ class DiyFormService extends BaseAdminService return ( new DiyFormFields() )->where([ [ 'site_id', '=', $this->site_id ] ])->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/' . $this->site_id . '/diy_form_qrcode'; - - $path = ''; - try { - $path = qrcode('', $page, $data, $this->site_id, $dir, 'weapp'); - } catch (\Exception $e) { - Log::write('万能表单微信小程序二维码生成error' . $e->getMessage() . $e->getFile() . $e->getLine()); - } - - return [ - 'path' => $path - ]; - } - /** * 检测表单名称唯一性 * @param array $data diff --git a/niucloud/app/service/admin/generator/vm/search/select2.vm b/niucloud/app/service/admin/generator/vm/search/select2.vm index 6e78d6fed..15cdc6c01 100644 --- a/niucloud/app/service/admin/generator/vm/search/select2.vm +++ b/niucloud/app/service/admin/generator/vm/search/select2.vm @@ -1,5 +1,5 @@ - + diff --git a/niucloud/app/service/admin/member/MemberService.php b/niucloud/app/service/admin/member/MemberService.php index 204a5f2f6..2bc718ecd 100644 --- a/niucloud/app/service/admin/member/MemberService.php +++ b/niucloud/app/service/admin/member/MemberService.php @@ -65,7 +65,11 @@ class MemberService extends BaseAdminService public function getList(array $where = []) { $field = 'member_id, nickname, headimg'; - return $this->model->where([['site_id', '=', $this->site_id]])->withSearch(['keyword'],$where)->field($field)->order('member_id desc')->limit($this->getPageParam()['limit'] ?? 0)->select()->toArray(); + $temp_where[] = ['site_id', '=', $this->site_id]; + 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(); } /** * 会员详情 diff --git a/niucloud/app/service/admin/niucloud/NiucloudService.php b/niucloud/app/service/admin/niucloud/NiucloudService.php index 9563a9c0e..d189a6b14 100644 --- a/niucloud/app/service/admin/niucloud/NiucloudService.php +++ b/niucloud/app/service/admin/niucloud/NiucloudService.php @@ -80,4 +80,11 @@ class NiucloudService extends BaseAdminService public function getFrameworkVersionList() { return (new CoreModuleService())->getFrameworkVersionList(); } + + /** + * 获取应用/插件的版本更新记录 + */ + public function getAppVersionList($app_key) { + return (new CoreModuleService())->getAppVersionList($app_key); + } } diff --git a/niucloud/app/service/admin/sys/ConfigService.php b/niucloud/app/service/admin/sys/ConfigService.php index c68a0f53a..4106c1b3b 100644 --- a/niucloud/app/service/admin/sys/ConfigService.php +++ b/niucloud/app/service/admin/sys/ConfigService.php @@ -11,13 +11,11 @@ namespace app\service\admin\sys; -use app\model\site\Site; use app\service\admin\site\SiteService; use app\service\core\channel\CoreH5Service; use app\service\core\sys\CoreConfigService; use app\service\core\sys\CoreSysConfigService; use core\base\BaseAdminService; -use core\exception\AdminException; /** * 配置服务层 @@ -70,7 +68,11 @@ class ConfigService extends BaseAdminService */ public function getWebSite() { - return ( new SiteService() )->getInfo($this->site_id); + $info = ( new SiteService() )->getInfo($this->site_id); + $service_info = $this->getService(); + $info['site_login_logo'] = $service_info[ 'site_login_logo' ]; + $info['site_login_bg_img'] = $service_info[ 'site_login_bg_img' ]; + return $info; } @@ -80,9 +82,7 @@ class ConfigService extends BaseAdminService */ public function setWebSite($data) { - return ( new SiteService() )->edit($this->site_id, $data); - } /** @@ -100,16 +100,14 @@ class ConfigService extends BaseAdminService */ public function getService() { - $info = ( new CoreConfigService() )->getConfig(0, 'SERVICE_INFO'); - if (empty($info)) { - $info = []; - $info[ 'value' ] = [ - 'wechat_code' => '', - 'enterprise_wechat' => '', - 'tel' => '', - ]; - } - return $info[ 'value' ]; + $info = ( new CoreConfigService() )->getConfig(0, 'SERVICE_INFO')[ 'value' ] ?? []; + return [ + 'wechat_code' => $info[ 'wechat_code' ] ?? '', + 'enterprise_wechat' => $info[ 'enterprise_wechat' ] ?? '', + 'site_login_logo' => $info[ 'site_login_logo' ] ?? '', + 'site_login_bg_img' => $info[ 'site_login_bg_img' ] ?? 'static/resource/images/site/login_bg.jpg', + 'tel' => $info[ 'tel' ] ?? '' + ]; } /** @@ -121,6 +119,8 @@ class ConfigService extends BaseAdminService { $data = [ "wechat_code" => $value[ 'wechat_code' ], + "site_login_logo" => $value[ 'site_login_logo' ], + "site_login_bg_img" => $value[ 'site_login_bg_img' ], "enterprise_wechat" => $value[ 'enterprise_wechat' ], "tel" => $value[ 'tel' ] ]; @@ -154,7 +154,7 @@ class ConfigService extends BaseAdminService if (empty($info)) { $info = []; $info[ 'value' ] = [ - 'key' => 'IZQBZ-3UHEU-WTCVD-2464U-I5N4V-ZFFU3', + 'key' => '', 'is_open' => 1, // 是否开启定位 'valid_time' => 5 // 定位有效期/分钟,过期后将重新获取定位信息,0为不过期 ]; diff --git a/niucloud/app/service/admin/sys/SystemService.php b/niucloud/app/service/admin/sys/SystemService.php index 51e674960..c0923d60c 100644 --- a/niucloud/app/service/admin/sys/SystemService.php +++ b/niucloud/app/service/admin/sys/SystemService.php @@ -12,11 +12,12 @@ namespace app\service\admin\sys; use app\job\sys\CheckJob; -use app\service\core\site\CoreSiteService; use app\service\core\sys\CoreSysConfigService; use core\base\BaseAdminService; +use core\exception\AdminException; use think\facade\Cache; use think\facade\Db; +use think\facade\Log; use Throwable; /** @@ -50,7 +51,7 @@ class SystemService extends BaseAdminService */ public function getUrl() { - return (new CoreSysConfigService())->getSceneDomain($this->site_id); + return ( new CoreSysConfigService() )->getSceneDomain($this->site_id); } /** @@ -62,7 +63,7 @@ class SystemService extends BaseAdminService $server = []; $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.php_version'), "server" => PHP_VERSION]; + $server[] = [ "name" => get_lang('dict_setting.php_version'), "server" => PHP_VERSION ]; //环境权限 $system_variables = []; @@ -105,7 +106,7 @@ class SystemService extends BaseAdminService //获取环境版本 $server_version = []; $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' ] ]; // 进程 @@ -145,7 +146,7 @@ class SystemService extends BaseAdminService $file = root_path('runtime') . $secret . '.job'; try { CheckJob::dispatch([ 'file' => $file ]); - } catch ( Throwable $e) { + } catch (Throwable $e) { return false; } // $timeout = 0; @@ -180,4 +181,37 @@ class SystemService extends BaseAdminService } 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/' . $this->site_id . '/' . $data[ 'folder' ] . '_qrcode'; + + try { + // h5 + //$h5_path = qrcode('', $page, $data, $this->site_id, $dir); + + // 微信小程序 + $weapp_path = qrcode('', $page, $qrcode_data, $this->site_id, $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)); + } + } } diff --git a/niucloud/app/service/admin/upgrade/BackupRecordsService.php b/niucloud/app/service/admin/upgrade/BackupRecordsService.php new file mode 100644 index 000000000..c3c10d4e6 --- /dev/null +++ b/niucloud/app/service/admin/upgrade/BackupRecordsService.php @@ -0,0 +1,650 @@ +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)) { + $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') { + + //备份数据库 + $res[ 'data' ] = [ + 'content' => '备份数据库', + 'task' => 'restoreCode' + ]; + + $temp = Cache::get($this->cache_restore_key); + $temp[ 'data' ][] = $res[ 'data' ]; + Cache::set($this->cache_restore_key, $temp); + + $this->backupSql($key); + + } 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') { + + $res[ 'data' ] = [ + 'content' => '恢复数据库备份', + 'task' => 'restoreData' + ]; + + $temp = Cache::get($this->cache_restore_key); + $temp[ 'data' ][] = $res[ 'data' ]; + Cache::set($this->cache_restore_key, $temp); + + // 恢复数据库备份 + $db = new DbBackup($info[ 'backup_sql_dir' ]); + $db->restoreDatabase(); + } 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); + + // 恢复数据 + $site_model = new Site(); + $site_model->where([ + [ 'site_id', '<>', 0 ], + [ 'app_type', '=', AppTypeDict::ADMIN ] + ])->update([ 'site_id' => 0 ]); + + } 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') { + + //备份数据库 + $res[ 'data' ] = [ + 'content' => '备份数据库', + 'task' => 'backComplete' + ]; + $temp = Cache::get($this->cache_key); + $temp[ 'data' ][] = $res[ 'data' ]; + Cache::set($this->cache_key, $temp); + + $this->backupSql($key); + + } 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); + + $db = new DbBackup($backup_dir, 1024 * 1024 * 2); + + $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->setExcludeTables($not_need_backup)->backupDatabaseSegment(); + + return true; + } + +} diff --git a/niucloud/app/service/admin/upgrade/BackupService.php b/niucloud/app/service/admin/upgrade/BackupService.php index bec22da32..df055d7aa 100644 --- a/niucloud/app/service/admin/upgrade/BackupService.php +++ b/niucloud/app/service/admin/upgrade/BackupService.php @@ -11,9 +11,8 @@ namespace app\service\admin\upgrade; -use app\dict\addon\AddonDict; -use app\service\admin\generator\GenerateService; use core\util\DbBackup; +use think\facade\Db; /** * 框架及插件升级备份 @@ -31,37 +30,20 @@ class BackupService extends UpgradeService // 创建目录 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' ]); - // 备份niucloud + // 备份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; - 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'); - } + + dir_copy($this->root_path . 'niucloud', $niucloud_dir, exclude_dirs: [ 'runtime', 'upload' ]); return true; } @@ -76,47 +58,21 @@ class BackupService extends UpgradeService // 创建目录 dir_mkdir($backup_dir); - $db = new DbBackup([ - 'path' => $backup_dir,//数据库备份路径 - 'part' => 1048576,//数据库备份卷大小 - 'compress' => 0,//数据库备份文件是否启用压缩 0不压缩 1 压缩 - 'level' => 9 //数据库备份文件压缩级别 1普通 4 一般 9最高 - ]); + $db = new DbBackup($backup_dir, 1024 * 1024 * 2); - $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(); + // 不需要备份的表 + $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->setExcludeTables($not_need_backup)->backupDatabaseSegment(); - if (!in_array($class->getTable(), $noot_need_backup)) { - $tables[] = $class->getTable(); - } - } catch (\Exception $e) { - } - } - } - - foreach ($tables as $table) { - $db->setFile()->backup($table); - } return true; } } diff --git a/niucloud/app/service/admin/upgrade/RestoreService.php b/niucloud/app/service/admin/upgrade/RestoreService.php index 963ae6f4c..2668b44b5 100644 --- a/niucloud/app/service/admin/upgrade/RestoreService.php +++ b/niucloud/app/service/admin/upgrade/RestoreService.php @@ -12,6 +12,8 @@ namespace app\service\admin\upgrade; +use app\dict\sys\AppTypeDict; +use app\model\site\Site; use core\util\DbBackup; /** @@ -24,8 +26,9 @@ 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; + 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); @@ -40,20 +43,20 @@ class RestoreService extends UpgradeService * 恢复数据库备份 * @return true */ - public function restoreSql() { - $backup_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR; + 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']); - } - } + $db = new DbBackup($backup_dir); + $db->restoreDatabase(); + + $site_model = new Site(); + $site_model->where([ + [ 'site_id', '<>', 0 ], + [ 'app_type', '=', AppTypeDict::ADMIN ] + ])->update([ 'site_id' => 0 ]); } return true; } + } diff --git a/niucloud/app/service/admin/upgrade/UpgradeRecordsService.php b/niucloud/app/service/admin/upgrade/UpgradeRecordsService.php new file mode 100644 index 000000000..023270716 --- /dev/null +++ b/niucloud/app/service/admin/upgrade/UpgradeRecordsService.php @@ -0,0 +1,116 @@ +model = new SysUpgradeRecords(); + } + + /** + * 添加升级记录 + * @param array $data + * @return mixed + */ + public function add(array $data) + { + $data[ 'create_time' ] = time(); + $res = $this->model->create($data); + // 关联备份记录 + ( 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) + { + $this->model->where([ [ 'upgrade_key', '=', $upgrade_key ] ])->delete(); + ( 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'; + $order = "id desc"; + $search_model = $this->model->where([ + [ 'status', '=', UpgradeDict::STATUS_COMPLETE ], + [ 'name|content|current_version', 'like', '%' . $where[ 'name' ] . '%' ] + ])->field($field)->order($order); + return $this->pageQuery($search_model); + } + +} diff --git a/niucloud/app/service/admin/upgrade/UpgradeService.php b/niucloud/app/service/admin/upgrade/UpgradeService.php index 7111ddc24..8bb1dfb30 100644 --- a/niucloud/app/service/admin/upgrade/UpgradeService.php +++ b/niucloud/app/service/admin/upgrade/UpgradeService.php @@ -12,6 +12,7 @@ namespace app\service\admin\upgrade; use app\dict\addon\AddonDict; +use app\dict\sys\UpgradeDict; use app\model\addon\Addon; use app\service\admin\install\InstallSystemService; use app\service\admin\sys\ConfigService; @@ -22,14 +23,16 @@ use app\service\core\addon\CoreDependService; use app\service\core\addon\WapTrait; use app\service\core\channel\CoreH5Service; use app\service\core\menu\CoreMenuService; +use app\service\core\niucloud\CoreCloudBuildService; use app\service\core\niucloud\CoreModuleService; use app\service\core\schedule\CoreScheduleInstallService; use core\base\BaseAdminService; +use core\exception\CloudBuildException; use core\exception\CommonException; use core\util\niucloud\BaseNiucloudClient; use think\facade\Cache; use think\facade\Db; -use function DI\string; +use think\facade\Log; /** * 框架及插件升级 @@ -51,15 +54,17 @@ class UpgradeService extends BaseAdminService protected $addon = ''; private $steps = [ - 'requestUpgrade' => ['step' => 'requestUpgrade', 'title' => '请求升级'], - 'downloadFile' => ['step' => 'downloadFile', 'title' => '下载更新文件'], - 'backupCode' => ['step' => 'backupCode', 'title' => '备份源码'], - 'backupSql' => ['step' => 'backupSql', 'title' => '备份数据库'], - 'coverCode' => ['step' => 'coverCode', 'title' => '合并更新文件'], - 'handleUniapp' => ['step' => 'handleUniapp', 'title' => '处理uniapp'], - 'refreshMenu' => ['step' => 'refreshMenu', 'title' => '刷新菜单'], - 'installSchedule' => ['step' => 'installSchedule', 'title' => '安装计划任务'], - 'upgradeComplete' => ['step' => 'upgradeComplete', 'title' => '升级完成'] + 'requestUpgrade' => [ 'step' => 'requestUpgrade', 'title' => '请求升级' ], + 'downloadFile' => [ 'step' => 'downloadFile', 'title' => '下载更新文件' ], + 'backupCode' => [ 'step' => 'backupCode', 'title' => '备份源码' ], + 'backupSql' => [ 'step' => 'backupSql', 'title' => '备份数据库' ], + 'coverCode' => [ 'step' => 'coverCode', 'title' => '合并更新文件' ], + 'handleUniapp' => [ 'step' => 'handleUniapp', 'title' => '处理uniapp' ], + 'refreshMenu' => [ 'step' => 'refreshMenu', 'title' => '刷新菜单' ], + 'installSchedule' => [ 'step' => 'installSchedule', 'title' => '安装计划任务' ], + 'cloudBuild' => [ 'step' => 'cloudBuild', 'title' => '开始云编译' ], + 'gteCloudBuildLog' => [ 'step' => 'gteCloudBuildLog', 'title' => '' ], + 'upgradeComplete' => [ 'step' => 'upgradeComplete', 'title' => '升级完成' ] ]; public function __construct() @@ -76,7 +81,8 @@ class UpgradeService extends BaseAdminService * @param string $addon * @return void */ - public function upgradePreCheck(string $addon = '') { + public function upgradePreCheck(string $addon = '') + { $niucloud_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR; $admin_dir = $this->root_path . 'admin' . DIRECTORY_SEPARATOR; $web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR; @@ -96,39 +102,61 @@ 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(), '', $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_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) ]; + $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) ]; - // 校验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'])) { - foreach ($check_res['unreadable'] as $item) { - $data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $item),'status' => false]; + // 忽略指定目录,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]; + 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') + array_column($data[ 'dir' ][ 'is_readable' ], '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; } @@ -137,31 +165,34 @@ class UpgradeService extends BaseAdminService * @param $addon * @return array */ - public function upgrade(string $addon = '') { + public function upgrade(string $addon = '') + { if ($this->upgrade_task) throw new CommonException('UPGRADE_TASK_EXIST'); $upgrade_content = $this->getUpgradeContent($addon); + $upgrade_title = '框架'; $upgrade = [ 'product_key' => BaseNiucloudClient::PRODUCT, 'framework_version' => config('version.version') ]; if (!$addon) { - $upgrade['app_key'] = AddonDict::FRAMEWORK_KEY; - $upgrade['version'] = config('version.version'); + $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' ] = $addon; + $upgrade[ 'version' ] = ( new Addon() )->where([ [ 'key', '=', $addon ] ])->value('version'); + $upgrade_title = ( new Addon() )->where([ [ 'key', '=', $addon ] ])->value('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'])) { + $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); - if (isset($response['code']) && $response['code'] == 0) throw new CommonException($response['msg']); + $response = ( new CoreAddonCloudService() )->upgradeAddon($upgrade); + if (isset($response[ 'code' ]) && $response[ 'code' ] == 0) throw new CommonException($response[ 'msg' ]); try { $key = uniqid(); @@ -176,12 +207,23 @@ class UpgradeService extends BaseAdminService 'upgrade' => $upgrade, 'steps' => $this->steps, 'step' => 'requestUpgrade', - 'executed' => ['requestUpgrade'], - 'log' => [ $this->steps['requestUpgrade']['title'] ], - 'params' => ['token' => $response['token'] ], + 'executed' => [ 'requestUpgrade' ], + 'log' => [ $this->steps[ 'requestUpgrade' ][ 'title' ] ], + 'params' => [ 'token' => $response[ 'token' ] ], 'upgrade_content' => $upgrade_content ]; + // 记录升级日志 + ( new UpgradeRecordsService() )->add([ + 'upgrade_key' => $upgrade_task[ 'key' ], + 'app_key' => $upgrade[ 'app_key' ], + 'name' => $upgrade_title, + 'content' => "{$upgrade_title} 升级 v{$upgrade_content['version']} 到 v{$upgrade_content['upgrade_version']}版本", + 'prev_version' => "v{$upgrade_content['version']}", + 'current_version' => "v{$upgrade_content['upgrade_version']}", + 'status' => UpgradeDict::STATUS_READY + ]); + Cache::set($this->cache_key, $upgrade_task); return $upgrade_task; } catch (\Exception $e) { @@ -193,33 +235,59 @@ class UpgradeService extends BaseAdminService * 执行升级 * @return true */ - public function execute() { + public function execute() + { if (!$this->upgrade_task) return true; - $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']; - $index = array_search($this->upgrade_task['step'], $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' ]; + $index = array_search($this->upgrade_task[ 'step' ], $steps); $step = $steps[ $index + 1 ] ?? ''; - $params = $this->upgrade_task['params'] ?? []; + $params = $this->upgrade_task[ 'params' ] ?? []; if ($step) { try { $res = $this->$step(...$params); if (is_array($res)) { - $this->upgrade_task['params'] = $res; + $this->upgrade_task[ 'params' ] = $res; } else { - $this->upgrade_task['step'] = $step; - $this->upgrade_task['params'] = []; - $this->upgrade_task['executed'][] = $step; - $this->upgrade_task['log'][] = $this->steps[$step]['title']; + $this->upgrade_task[ 'step' ] = $step; + $this->upgrade_task[ 'params' ] = []; + $this->upgrade_task[ 'executed' ][] = $step; + 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) { - $this->upgrade_task['step'] = $step; - $this->upgrade_task['error'][] = '升级失败,失败原因:' . $e->getMessage().$e->getFile().$e->getLine(); - Cache::set($this->cache_key, $this->upgrade_task); - $this->upgradeErrorHandle(); + $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); } return true; } else { @@ -235,12 +303,13 @@ class UpgradeService extends BaseAdminService * @param $step * @return true|null */ - public function downloadFile(string $token, string $dir = '', int $index = -1, $step = 0, $length = 0) { + public function downloadFile(string $token, string $dir = '', int $index = -1, $step = 0, $length = 0) + { 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; dir_mkdir($dir); } - $res = (new CoreAddonCloudService())->downloadUpgradeFile($token, $dir, $index, $step, $length); + $res = ( new CoreAddonCloudService() )->downloadUpgradeFile($token, $dir, $index, $step, $length); return $res; } @@ -248,8 +317,9 @@ class UpgradeService extends BaseAdminService * 备份源码 * @return true */ - public function backupCode() { - (new BackupService())->backupCode(); + public function backupCode() + { + ( new BackupService() )->backupCode(); return true; } @@ -257,8 +327,9 @@ class UpgradeService extends BaseAdminService * 备份数据库 * @return true */ - public function backupSql() { - (new BackupService())->backupSql(); + public function backupSql() + { + ( new BackupService() )->backupSql(); return true; } @@ -266,15 +337,16 @@ class UpgradeService extends BaseAdminService * 覆盖更新升级的代码 * @return void */ - public function coverCode($index = 0) { - $this->upgrade_task['is_cover'] = 1; - $addon = $this->upgrade_task['upgrade']['app_key']; + public function coverCode($index = 0) + { + $this->upgrade_task[ 'is_cover' ] = 1; + $addon = $this->upgrade_task[ 'upgrade' ][ 'app_key' ]; - $version_list = array_reverse($this->upgrade_task['upgrade_content']['version_list']); - $code_dir = $this->upgrade_dir .$this->upgrade_task['key'] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR; + $version_list = array_reverse($this->upgrade_task[ 'upgrade_content' ][ 'version_list' ]); + $code_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'download' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR; - $version_item = $version_list[$index]; - $version_no = $version_item['version_no']; + $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; @@ -294,20 +366,20 @@ class UpgradeService extends BaseAdminService // 覆盖文件 if (is_dir($code_dir . $version_no)) { // 忽略环境变量文件 - $exclude_files = ['.env.development', '.env.production', '.env', '.env.dev', '.env.product']; - dir_copy($code_dir . $version_no, $to_dir, exclude_files:$exclude_files); + $exclude_files = [ '.env.development', '.env.production', '.env', '.env.dev', '.env.product' ]; + dir_copy($code_dir . $version_no, $to_dir, exclude_files: $exclude_files); if ($addon != AddonDict::FRAMEWORK_KEY) { - (new CoreAddonInstallService($addon))->installDir(); + ( new CoreAddonInstallService($addon) )->installDir(); } } $upgrade_file_dir = 'v' . str_replace('.', '', $version_no); if ($addon == AddonDict::FRAMEWORK_KEY) { $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 { $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 @@ -317,10 +389,10 @@ class UpgradeService extends BaseAdminService // 执行升级方法 if (class_exists($class_path)) { - (new $class_path())->handle(); + ( new $class_path() )->handle(); } - $index ++; + $index++; if ($index < count($version_list)) { return compact('index'); } else { @@ -333,8 +405,9 @@ class UpgradeService extends BaseAdminService * @param string $version_no * @return void */ - public function installDepend(string $dir, array $change_files) { - $addon = $this->upgrade_task['upgrade']['app_key']; + public function installDepend(string $dir, array $change_files) + { + $addon = $this->upgrade_task[ 'upgrade' ][ 'app_key' ]; $depend_service = new CoreDependService(); if ($addon == AddonDict::FRAMEWORK_KEY) { @@ -353,7 +426,7 @@ class UpgradeService extends BaseAdminService $original = $depend_service->getComposerContent(); $new = $depend_service->jsonFileToArray($dir . $composer); 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); } @@ -362,7 +435,7 @@ class UpgradeService extends BaseAdminService $new = $depend_service->jsonFileToArray($dir . $admin_package); 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); } @@ -371,7 +444,7 @@ class UpgradeService extends BaseAdminService $new = $depend_service->jsonFileToArray($dir . $web_package); 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); } @@ -380,7 +453,7 @@ class UpgradeService extends BaseAdminService $new = $depend_service->jsonFileToArray($dir . $uniapp_package); 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); } @@ -391,12 +464,13 @@ class UpgradeService extends BaseAdminService * @param string $verson_no * @return true */ - 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']; - dir_copy($code_dir . 'uni-app', $this->root_path . 'uni-app', exclude_files:$exclude_files); + 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' ]; + dir_copy($code_dir . 'uni-app', $this->root_path . 'uni-app', exclude_files: $exclude_files); - $addon_list = (new CoreAddonService())->getInstallAddonList(); + $addon_list = ( new CoreAddonService() )->getInstallAddonList(); $depend_service = new CoreDependService(); if (!empty($addon_list)) { @@ -421,7 +495,7 @@ class UpgradeService extends BaseAdminService $new = $depend_service->jsonFileToArray($addon_uniapp_package); 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'; @@ -430,7 +504,7 @@ class UpgradeService extends BaseAdminService } } - $map = (new ConfigService())->getMap(); + $map = ( new ConfigService() )->getMap(); ( new CoreH5Service() )->mapKeyChange($map[ 'key' ]); return true; @@ -441,7 +515,8 @@ class UpgradeService extends BaseAdminService * @param string $sql_file * @return true */ - private function executeSql(string $sql_file) { + private function executeSql(string $sql_file) + { $sql_content = file_get_contents($sql_file); if (!empty($sql_content)) { @@ -462,11 +537,12 @@ class UpgradeService extends BaseAdminService * 刷新菜单 * @return void */ - public function refreshMenu() { - if ($this->upgrade_task['upgrade']['app_key'] == AddonDict::FRAMEWORK_KEY) { - (new InstallSystemService())->installMenu(); + public function refreshMenu() + { + if ($this->upgrade_task[ 'upgrade' ][ 'app_key' ] == AddonDict::FRAMEWORK_KEY) { + ( new InstallSystemService() )->installMenu(); } else { - (new CoreMenuService())->refreshAddonMenu($this->upgrade_task['upgrade']['app_key']); + ( new CoreMenuService() )->refreshAddonMenu($this->upgrade_task[ 'upgrade' ][ 'app_key' ]); } return true; } @@ -475,28 +551,79 @@ class UpgradeService extends BaseAdminService * 安装计划任务 * @return true */ - public function installSchedule() { - if ($this->upgrade_task['upgrade']['app_key'] == AddonDict::FRAMEWORK_KEY) { - (new CoreScheduleInstallService())->installSystemSchedule(); + public function installSchedule() + { + if ($this->upgrade_task[ 'upgrade' ][ 'app_key' ] == AddonDict::FRAMEWORK_KEY) { + ( new CoreScheduleInstallService() )->installSystemSchedule(); } else { - (new CoreScheduleInstallService())->installAddonSchedule($this->upgrade_task['upgrade']['app_key']); + ( new CoreScheduleInstallService() )->installAddonSchedule($this->upgrade_task[ 'upgrade' ][ 'app_key' ]); } 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 */ - public function upgradeComplete() { - $addon = $this->upgrade_task['upgrade']['app_key']; + public function upgradeComplete() + { + $addon = $this->upgrade_task[ 'upgrade' ][ 'app_key' ]; if ($addon != AddonDict::FRAMEWORK_KEY) { $core_addon_service = new CoreAddonService(); $install_data = $core_addon_service->getAddonConfig($addon); - $install_data['icon'] = 'addon/' . $addon . '/icon.png'; + $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; } @@ -504,30 +631,37 @@ class UpgradeService extends BaseAdminService * 升级出错之后的处理 * @return true|void */ - public function upgradeErrorHandle() { + public function upgradeErrorHandle($fail_reason = []) + { $steps = []; - $steps[$this->upgrade_task['step']] = []; + $steps[ $this->upgrade_task[ 'step' ] ] = []; - if (isset($this->upgrade_task['is_cover'])) { - $steps['restoreCode'] = ['step' => 'restoreCode', 'title' => '恢复源码备份']; - $steps['restoreSql'] = ['step' => 'restoreSql', 'title' => '恢复数据库备份']; + if (isset($this->upgrade_task[ 'is_cover' ])) { + $steps[ 'restoreCode' ] = [ 'step' => 'restoreCode', 'title' => '恢复源码备份' ]; + $steps[ 'restoreSql' ] = [ 'step' => 'restoreSql', 'title' => '恢复数据库备份' ]; } - $steps['restoreComplete'] = ['step' => 'restoreComplete', 'title' => '备份恢复完成']; - $this->upgrade_task['steps'] = $steps; + $steps[ 'restoreComplete' ] = [ 'step' => 'restoreComplete', 'title' => '备份恢复完成' ]; + $this->upgrade_task[ 'steps' ] = $steps; Cache::set($this->cache_key, $this->upgrade_task); + + Log::write('升级出错之后的处理:'.json_encode($fail_reason)); + + // 执行失败,更新升级记录状态,备份记录状态 + ( new UpgradeRecordsService() )->failed($this->upgrade_task[ 'key' ]); } /** * 恢复源码 * @return void */ - public function restoreCode() { + public function restoreCode() + { try { - (new RestoreService())->restoreCode(); + ( new RestoreService() )->restoreCode(); return true; } 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(); + $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(); Cache::set($this->cache_key, $this->upgrade_task); return true; } @@ -537,20 +671,22 @@ class UpgradeService extends BaseAdminService * 恢复数据库 * @return void */ - public function restoreSql() { + public function restoreSql() + { try { - (new RestoreService())->restoreSql(); + ( new RestoreService() )->restoreSql(); return true; } 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(); + $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(); Cache::set($this->cache_key, $this->upgrade_task); return true; } } - public function restoreComplete() { - $this->clearUpgradeTask(5); + public function restoreComplete() + { + $this->clearUpgradeTask(2); return true; } @@ -560,26 +696,28 @@ class UpgradeService extends BaseAdminService * @return array|\core\util\niucloud\Response|object|\Psr\Http\Message\ResponseInterface * @throws \GuzzleHttp\Exception\GuzzleException */ - public function getUpgradeContent(string $addon = '') { + public function getUpgradeContent(string $addon = '') + { $upgrade = [ 'product_key' => BaseNiucloudClient::PRODUCT ]; if (!$addon) { - $upgrade['app_key'] = AddonDict::FRAMEWORK_KEY; - $upgrade['version'] = config('version.version'); + $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' ] = $addon; + $upgrade[ 'version' ] = ( new Addon() )->where([ [ 'key', '=', $addon ] ])->value('version'); } - return (new CoreModuleService())->getUpgradeContent($upgrade)['data'] ?? []; + return ( new CoreModuleService() )->getUpgradeContent($upgrade)[ 'data' ] ?? []; } /** * 获取正在进行的升级任务 * @return mixed|null */ - public function getUpgradeTask() { + public function getUpgradeTask() + { return $this->upgrade_task; } @@ -587,7 +725,8 @@ class UpgradeService extends BaseAdminService * 清除升级任务 * @return true */ - public function clearUpgradeTask(int $delayed = 0) { + public function clearUpgradeTask(int $delayed = 0) + { if ($delayed) { Cache::set($this->cache_key, $this->upgrade_task, $delayed); } else { @@ -603,6 +742,32 @@ class UpgradeService extends BaseAdminService */ 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; + } } } diff --git a/niucloud/app/service/admin/verify/VerifierService.php b/niucloud/app/service/admin/verify/VerifierService.php index e779e0385..acf4594c3 100644 --- a/niucloud/app/service/admin/verify/VerifierService.php +++ b/niucloud/app/service/admin/verify/VerifierService.php @@ -77,6 +77,13 @@ class VerifierService extends BaseAdminService 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 @@ -88,7 +95,7 @@ class VerifierService extends BaseAdminService if ($member->isEmpty()) throw new CommonException('MEMBER_NOT_EXIST'); $model = $this->model->where([ ['site_id', '=', $this->site_id], ['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['site_id'] = $this->site_id; @@ -96,6 +103,16 @@ class VerifierService extends BaseAdminService return $res->id; } + /** + * 编辑核销员 + * @param array $data + * @return mixed + */ + public function edit($id, $data) + { + $this->model->where([ ['site_id', '=', $this->site_id], ['id', '=',$id] ])->update($data); + } + /** * 删除核销员 * @param int $id diff --git a/niucloud/app/service/admin/verify/VerifyService.php b/niucloud/app/service/admin/verify/VerifyService.php index a359216c9..d252ff407 100644 --- a/niucloud/app/service/admin/verify/VerifyService.php +++ b/niucloud/app/service/admin/verify/VerifyService.php @@ -33,11 +33,12 @@ class VerifyService extends BaseAdminService * @return array * @throws \think\db\exception\DbException */ - public function getPage(array $where = []) { - $search_model = $this->model->where([['site_id', '=', $this->site_id]])->withSearch(['code', 'type', 'create_time', 'verifier_member_id'], $where) - ->with(['member' => function($query){ + public function getPage(array $where = []) + { + $search_model = $this->model->where([ [ 'site_id', '=', $this->site_id ] ])->withSearch([ 'code', 'type', 'create_time', 'verifier_member_id' ], $where) + ->with([ 'member' => function($query) { $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); return $list; } @@ -47,16 +48,17 @@ class VerifyService extends BaseAdminService * @param string $verify_code * @return array */ - public function getDetail(string $verify_code) { + public function getDetail(string $verify_code) + { $info = $this->model->where([ - ['site_id', '=', $this->site_id], - ['code', '=', $verify_code] + [ 'site_id', '=', $this->site_id ], + [ 'code', '=', $verify_code ] ])->field('*') - ->with(['member' => function($query){ - $query->field('member_id, nickname, mobile, headimg'); - }])->append(['type_name'])->findOrEmpty()->toArray(); + ->with([ 'member' => function($query) { + $query->field('member_id, nickname, mobile, headimg'); + } ])->append([ 'type_name' ])->findOrEmpty()->toArray(); - $info['verify_info'] = event('VerifyInfo',$info); + $info[ 'verify_info' ] = event('VerifyInfo', $info); return $info; } diff --git a/niucloud/app/service/admin/weapp/WeappConfigService.php b/niucloud/app/service/admin/weapp/WeappConfigService.php index f14d1e89e..759688f83 100644 --- a/niucloud/app/service/admin/weapp/WeappConfigService.php +++ b/niucloud/app/service/admin/weapp/WeappConfigService.php @@ -123,7 +123,10 @@ class WeappConfigService extends BaseAdminService $data['privacy_ver'] = 1; CoreOplatformService::setPrivacySetting($this->site_id, $data); // 提交小程序 - (new WeappVersionService())->siteWeappCommit(); + try { + (new WeappVersionService())->siteWeappCommit(); + } catch (\Exception $e) { + } } } diff --git a/niucloud/app/service/admin/wxoplatform/WeappVersionService.php b/niucloud/app/service/admin/wxoplatform/WeappVersionService.php index 655f2d0cd..9a6a4fbf9 100644 --- a/niucloud/app/service/admin/wxoplatform/WeappVersionService.php +++ b/niucloud/app/service/admin/wxoplatform/WeappVersionService.php @@ -52,7 +52,7 @@ class WeappVersionService extends BaseAdminService $site_group = (new SiteGroup())->field("group_id, group_name, group_desc, create_time, update_time, app")->order('create_time asc')->select()->toArray(); if (empty($site_group)) throw new CommonException('PLEASE_ADD_FIRST_SITE_GROUP'); - $site_group_id = $data['site_group_id'] ?? $site_group[0]['group_id']; + $site_group_id = isset($data['site_group_id']) && !empty($data['site_group_id']) ? $data['site_group_id'] : $site_group[0]['group_id']; $base_url = $data['base_url'] ?? cache_remember('base_url', function (){ return (string)url('/', [], '', true); }); @@ -89,10 +89,29 @@ class WeappVersionService extends BaseAdminService ]); // 获取小程序版本提交结果 - GetVersionUploadResult::dispatch(['task_key' => $upload_res['key']], secs: 10); + GetVersionUploadResult::dispatch(['task_key' => $upload_res['key'], 'is_all' => $data['is_all'] ?? 1], secs: 10); return $res->id; } + /** + * 获取小程序提交记录 + * @return array + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + public function getSiteGroupCommitRecord($where = []) { + $field = 'group_id, group_name'; + $search_model = (new SiteGroup())->withSearch([ 'keywords' ], $where)->field($field)->order('create_time desc'); + $site_group = $this->pageQuery($search_model); + if (!empty($site_group['data'])) { + foreach ($site_group['data'] as $key => $item) { + $site_group['data'][$key]['commit_record'] = $this->model->where([ ['site_group_id', '=', $item['group_id'] ] ])->order('id desc')->field('id, user_version, user_desc, status, fail_reason, create_time, update_time, template_id')->append(['status_name'])->findOrEmpty()->toArray(); + } + } + return $site_group; + } + /** * 获取最后一次提交记录 * @return WxOplatfromWeappVersion|array|mixed|\think\Model @@ -106,10 +125,9 @@ class WeappVersionService extends BaseAdminService * @return array * @throws \think\db\exception\DbException */ - public function getPage() { - $search_model = $this->model->field('*')->append(['status_name']) - ->order('id desc') - ->with('site_group'); + public function getPage($data = []) { + $search_model = $this->model->field('*')->append(['status_name'])->withSearch([ 'site_group_id' ], $data) + ->order('id desc'); return $this->pageQuery($search_model); } @@ -118,21 +136,22 @@ class WeappVersionService extends BaseAdminService * @param string $task_key * @return void */ - public static function getVersionUploadResult(string $task_key) { + public static function getVersionUploadResult(string $task_key, $is_all = 1) { $build_log = (new CoreWeappCloudService())->getWeappCompileLog($task_key); if (isset($build_log['data']) && isset($build_log['data'][0]) && is_array($build_log['data'][0])) { $last = end($build_log['data'][0]); if ($last['code'] == 0) { (new WxOplatfromWeappVersion())->update(['status' => CloudDict::APPLET_UPLOAD_FAIL, 'fail_reason' => $last['msg'] ?? '', 'update_time' => time() ], ['task_key' => $task_key]); + VersionUploadSuccess::dispatch(['task_key' => $task_key, 'is_all' => $is_all]); return true; } if ($last['percent'] == 100) { (new WxOplatfromWeappVersion())->update(['status' => CloudDict::APPLET_UPLOAD_SUCCESS, 'update_time' => time() ], ['task_key' => $task_key]); - VersionUploadSuccess::dispatch(['task_key' => $task_key]); + VersionUploadSuccess::dispatch(['task_key' => $task_key, 'is_all' => $is_all]); return true; } - GetVersionUploadResult::dispatch(['task_key' => $task_key], secs: 10); + GetVersionUploadResult::dispatch(['task_key' => $task_key, 'is_all' => $is_all], secs: 10); } } @@ -141,7 +160,7 @@ class WeappVersionService extends BaseAdminService * @param $task * @return void */ - public static function uploadSuccess(string $task_key) { + public static function uploadSuccess(string $task_key, $is_all = 1) { $version = (new WxOplatfromWeappVersion())->where(['task_key' => $task_key])->findOrEmpty(); if ($version->isEmpty()) return true; @@ -176,7 +195,7 @@ class WeappVersionService extends BaseAdminService } $site_group = (new SiteGroup())->where([ ['group_id', '>', $version['site_group_id'] ] ])->order('group_id asc')->findOrEmpty(); - if (!$site_group->isEmpty()) { + if (!$site_group->isEmpty() && $is_all == 1) { WeappCommit::dispatch(['data' => ['site_group_id' => $site_group['group_id'], 'base_url' => Cache::get('base_url') ] ]); } } diff --git a/niucloud/app/service/api/diy/DiyService.php b/niucloud/app/service/api/diy/DiyService.php index eb521c81b..6619be485 100644 --- a/niucloud/app/service/api/diy/DiyService.php +++ b/niucloud/app/service/api/diy/DiyService.php @@ -13,10 +13,8 @@ namespace app\service\api\diy; use app\dict\diy\PagesDict; use app\dict\diy\TemplateDict; -use app\dict\sys\FileDict; use app\model\diy\Diy; use app\model\diy\DiyTheme; -use app\service\core\diy\CoreDiyService; use app\service\core\site\CoreSiteService; use core\base\BaseApiService; @@ -159,26 +157,28 @@ class DiyService extends BaseApiService public function getDiyTheme() { $site_addon = ( new CoreSiteService() )->getSiteCache($this->site_id); - $addon_list = array_merge($site_addon['apps'],$site_addon['site_addons']); - $theme_data = (new DiyTheme())->where([['site_id', '=', $this->site_id], ['is_selected', '=', 1]])->column('id,title,theme,new_theme','addon'); - $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app'])))[0] ?? []; - $app_theme['app'] = [ - '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'] : ''), - 'new_theme' => $theme_data['app']['new_theme'] ?? '', + $addon_list = array_merge($site_addon[ 'apps' ], $site_addon[ 'site_addons' ]); + $theme_data = ( new DiyTheme() )->where([ [ 'site_id', '=', $this->site_id ], [ 'is_selected', '=', 1 ] ])->column('id,title,theme,new_theme', 'addon'); + $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app' ])))[ 0 ] ?? []; + $app_theme[ 'app' ] = [ + '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' ] : '' ), + 'new_theme' => $theme_data[ 'app' ][ 'new_theme' ] ?? '', ]; $data = []; - foreach ($addon_list as $key => $value){ - if (isset($value['support_app']) && empty($value['support_app']) && $value['type'] == 'addon'){ + foreach ($addon_list as $key => $value) { + if (isset($value[ 'support_app' ]) && empty($value[ 'support_app' ]) && $value[ 'type' ] == 'addon') { continue; } - $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']]['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'] ?? ''; + $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'key' ] ])))[ 0 ] ?? []; + if (!empty($addon_theme) && !empty($addon_theme[ 'theme_color' ])) { + $data[ $value[ 'key' ] ][ 'title' ] = $theme_data[ $value[ 'key' ] ][ 'title' ] ?? $addon_theme[ 'theme_color' ][ 0 ][ 'title' ]; + $data[ $value[ 'key' ] ][ 'theme' ] = $theme_data[ $value[ 'key' ] ][ 'theme' ] ?? $addon_theme[ 'theme_color' ][ 0 ][ 'theme' ]; + $data[ $value[ 'key' ] ][ 'new_theme' ] = $theme_data[ $value[ 'key' ] ][ 'new_theme' ] ?? ''; + } } - if (count($site_addon[ 'apps' ]) > 1) {// 应用数量大于1时,展示系统主题色设置,只有一个应用时,不展示系统主题色设置 - $data = array_merge($app_theme,$data); + if (empty($data) || count($site_addon[ 'apps' ]) > 1) {// 应用数量大于1时,展示系统主题色设置,只有一个应用时,不展示系统主题色设置 + $data = array_merge($app_theme, $data); } return $data; } diff --git a/niucloud/app/service/api/sys/AreaService.php b/niucloud/app/service/api/sys/AreaService.php index 53aef545f..c559760fb 100644 --- a/niucloud/app/service/api/sys/AreaService.php +++ b/niucloud/app/service/api/sys/AreaService.php @@ -220,7 +220,7 @@ class AreaService extends BaseApiService 'formatted_addresses' => $address_data[ 'formatted_addresses' ] ]; } else { - throw new ApiException($res[ 'message' ]); + throw new ApiException('请检查地图配置:'.$res[ 'message' ]); } } else { diff --git a/niucloud/app/service/api/verify/VerifyService.php b/niucloud/app/service/api/verify/VerifyService.php index 360728289..5bb70473f 100644 --- a/niucloud/app/service/api/verify/VerifyService.php +++ b/niucloud/app/service/api/verify/VerifyService.php @@ -22,7 +22,6 @@ use core\base\BaseApiService; class VerifyService extends BaseApiService { - /** * 获取核销码(对应业务调用) * @param $type @@ -49,7 +48,7 @@ class VerifyService extends BaseApiService */ public function getInfoByCode($code) { - return ( new CoreVerifyService() )->getInfoByCode($this->site_id, $code); + return ( new CoreVerifyService() )->getInfoByCode($this->site_id, $this->member_id,$code); } /** diff --git a/niucloud/app/service/core/addon/CoreAddonCloudService.php b/niucloud/app/service/core/addon/CoreAddonCloudService.php index 58a68fdc5..ae064885b 100644 --- a/niucloud/app/service/core/addon/CoreAddonCloudService.php +++ b/niucloud/app/service/core/addon/CoreAddonCloudService.php @@ -35,7 +35,10 @@ class CoreAddonCloudService extends CoreCloudBaseService $package_dir = $temp_dir . 'package' . DIRECTORY_SEPARATOR; 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; // 拷贝composer文件 @@ -60,6 +63,19 @@ class CoreAddonCloudService extends CoreCloudBaseService $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) { // 将临时目录下文件生成压缩包 $zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip'; diff --git a/niucloud/app/service/core/addon/CoreAddonDevelopService.php b/niucloud/app/service/core/addon/CoreAddonDevelopService.php index 71f910090..90a9fe9e7 100644 --- a/niucloud/app/service/core/addon/CoreAddonDevelopService.php +++ b/niucloud/app/service/core/addon/CoreAddonDevelopService.php @@ -370,6 +370,7 @@ class CoreAddonDevelopService extends CoreAddonBaseService if (empty($image)) return true; if (check_file_is_remote($image)) { try { + downloadImage($image,$file); // 将云存储的图片下载到本地 (new CoreFetchService())->setRootPath($dir)->setRename($name)->image($image, 0, FileDict::LOCAL); } catch ( UploadFileException $e ) { return true; diff --git a/niucloud/app/service/core/diy/CoreDiyService.php b/niucloud/app/service/core/diy/CoreDiyService.php index ff512fee7..6e2f56e27 100644 --- a/niucloud/app/service/core/diy/CoreDiyService.php +++ b/niucloud/app/service/core/diy/CoreDiyService.php @@ -31,48 +31,48 @@ class CoreDiyService extends BaseCoreService public function initDefaultDiyTheme($site_id) { $site_addon = ( new CoreSiteService() )->getSiteCache($site_id); - $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app'])))[0] ?? []; - foreach ($system_theme['theme_color'] as $k => $v) { + $system_theme = array_values(array_filter(event('ThemeColor', [ 'key' => 'app' ])))[ 0 ] ?? []; + foreach ($system_theme[ 'theme_color' ] as $k => $v) { $data[] = [ 'type' => 'app', 'addon' => 'app', 'site_id' => $site_id, - 'title' => $v['title'], - 'theme' => $v['theme'], - 'default_theme' => $v['theme'], + 'title' => $v[ 'title' ], + 'theme' => $v[ 'theme' ], + 'default_theme' => $v[ 'theme' ], 'theme_type' => 'default', 'is_selected' => $k == 0 ? 1 : 0, 'create_time' => time(), ]; } - foreach ($site_addon[ 'apps' ] as $value){ - $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value['key'] ])))[0] ?? []; + foreach ($site_addon[ 'apps' ] as $value) { + $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'key' ] ])))[ 0 ] ?? []; if (empty($addon_theme)) continue; - foreach ($addon_theme['theme_color'] as $k => $v){ + foreach ($addon_theme[ 'theme_color' ] ?? [] as $k => $v) { $data[] = [ 'type' => 'app', - 'addon' => $value['key'], + 'addon' => $value[ 'key' ], 'site_id' => $site_id, - 'title' => $v['title'], - 'theme' => $v['theme'], - 'default_theme' => $v['theme'], + 'title' => $v[ 'title' ], + 'theme' => $v[ 'theme' ], + 'default_theme' => $v[ 'theme' ], 'theme_type' => 'default', 'is_selected' => $k == 0 ? 1 : 0, 'create_time' => time(), ]; } - $addon_data = (new addon())->field('key')->where([['support_app', '=', $value['key']]])->select()->toArray(); - if (!empty($addon_data)){ - foreach ($addon_data as $v){ - foreach ($addon_theme['theme_color'] as $theme_k => $theme_v){ + $addon_data = ( new addon() )->field('key')->where([ [ 'support_app', '=', $value[ 'key' ] ] ])->select()->toArray(); + if (!empty($addon_data)) { + foreach ($addon_data as $v) { + foreach ($addon_theme[ 'theme_color' ] as $theme_k => $theme_v) { $data[] = [ 'type' => 'addon', - 'addon' => $v['key'], + 'addon' => $v[ 'key' ], 'site_id' => $site_id, - 'title' => $theme_v['title'], - 'theme' => $theme_v['theme'], - 'default_theme' => $theme_v['theme'], + 'title' => $theme_v[ 'title' ], + 'theme' => $theme_v[ 'theme' ], + 'default_theme' => $theme_v[ 'theme' ], 'theme_type' => 'default', 'is_selected' => $theme_k == 0 ? 1 : 0, 'create_time' => time(), @@ -86,7 +86,7 @@ class CoreDiyService extends BaseCoreService $theme_count = $diy_theme_model->where([ [ 'site_id', "=", $site_id ], [ 'title', "=", $v[ 'title' ] ], - [ 'addon', "=", $v['addon'] ] + [ 'addon', "=", $v[ 'addon' ] ] ])->count(); // 如果已有该主题风格颜色则不再添加 if ($theme_count > 0) { diff --git a/niucloud/app/service/core/niucloud/CoreCloudBuildService.php b/niucloud/app/service/core/niucloud/CoreCloudBuildService.php index 82c2b59cb..305766f37 100644 --- a/niucloud/app/service/core/niucloud/CoreCloudBuildService.php +++ b/niucloud/app/service/core/niucloud/CoreCloudBuildService.php @@ -17,6 +17,7 @@ use app\service\core\addon\CoreAddonBaseService; use app\service\core\addon\CoreAddonDevelopDownloadService; use app\service\core\addon\WapTrait; use core\base\BaseCoreService; +use core\exception\CloudBuildException; use core\exception\CommonException; use core\util\niucloud\BaseNiucloudClient; use core\util\niucloud\CloudService; @@ -42,14 +43,15 @@ class CoreCloudBuildService extends BaseCoreService parent::__construct(); $this->root_path = project_path(); $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[] */ - public function buildPreCheck() { + public function buildPreCheck() + { $niucloud_dir = $this->root_path . 'niucloud' . DIRECTORY_SEPARATOR; $admin_dir = $this->root_path . 'admin' . DIRECTORY_SEPARATOR; $web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR; @@ -76,35 +78,35 @@ class CoreCloudBuildService extends BaseCoreService clearstatcache(); // 校验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(), '', $niucloud_dir . 'vendor'), 'status' => is_readable($niucloud_dir . '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(), '', $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(), '', $niucloud_dir . 'vendor'), 'status' => is_write($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(), '', $niucloud_dir . 'vendor'), 'status' => is_write($niucloud_dir . 'vendor') ]; // 校验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'])) { - foreach ($check_res['unreadable'] as $item) { - $data['dir']['is_readable'][] = ['dir' => str_replace(project_path(), '', $item),'status' => false]; + 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]; + 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') + array_column($data[ 'dir' ][ 'is_readable' ], '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; } @@ -113,10 +115,11 @@ class CoreCloudBuildService extends BaseCoreService * @param $addon * @return void */ - public function cloudBuild() { + public function cloudBuild() + { 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 $task_key = uniqid(); @@ -128,69 +131,71 @@ class CoreCloudBuildService extends BaseCoreService // 拷贝composer文件 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()) { - 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'); } // 拷贝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()) { - 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_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()) { - 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); $zip_file = $temp_dir . DIRECTORY_SEPARATOR . 'build.zip'; - (new CoreAddonDevelopDownloadService(''))->compressToZip($package_dir, $zip_file); + ( new CoreAddonDevelopDownloadService('') )->compressToZip($package_dir, $zip_file); $query = [ 'authorize_code' => $this->auth_code, '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' => [ [ - 'name' => 'file', + 'name' => 'file', 'contents' => fopen($zip_file, 'r'), 'filename' => 'build.zip' ] ], '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 = [ 'task_key' => $task_key, - 'timestamp' => $query['timestamp'] + 'timestamp' => $query[ 'timestamp' ] ]; Cache::set($this->cache_key, $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', ''); $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(); foreach ($addons as $addon) { - $custom_port = (new CoreAddonBaseService())->getAddonConfig($addon)['port'] ?? []; + $custom_port = ( new CoreAddonBaseService() )->getAddonConfig($addon)[ 'port' ] ?? []; if (!empty($custom_port)) { $addon_path = root_path() . 'addon' . DIRECTORY_SEPARATOR . $addon . DIRECTORY_SEPARATOR; 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'; + 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)); } } @@ -202,7 +207,8 @@ class CoreCloudBuildService extends BaseCoreService * 获取编译任务 * @return mixed */ - public function getBuildTask() { + public function getBuildTask() + { return $this->build_task; } @@ -210,19 +216,20 @@ class CoreCloudBuildService extends BaseCoreService * 获取编译执行日志 * @return void */ - public function getBuildLog() { + public function getBuildLog() + { if (!$this->build_task) return; $query = [ '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])) { - $last = end($build_log['data'][0]); - if ($last['percent'] == 100 && $last['code'] == 1) { - $build_log['data'][0] = $this->buildSuccess($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 ]); + if ($last[ 'percent' ] == 100 && $last[ 'code' ] == 1) { + $build_log[ 'data' ][ 0 ] = $this->buildSuccess($build_log[ 'data' ][ 0 ]); } } return $build_log; @@ -233,44 +240,45 @@ class CoreCloudBuildService extends BaseCoreService * @param array $log * @return array */ - public function buildSuccess(array $log) { + public function buildSuccess(array $log) + { try { $query = [ 'authorize_code' => $this->auth_code, - 'timestamp' => $this->build_task['timestamp'] + 'timestamp' => $this->build_task[ 'timestamp' ] ]; $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'])) { - $response = (new CloudService())->request('HEAD','cloud/build_download?' . http_build_query($query), [ - 'headers' => ['Range' => 'bytes=0-'] + if (!isset($this->build_task[ 'index' ])) { + $response = ( new CloudService() )->request('HEAD', 'cloud/build_download?' . http_build_query($query), [ + 'headers' => [ 'Range' => 'bytes=0-' ] ]); $length = $response->getHeader('Content-range'); - $length = (int)explode("/", $length[0])[1]; - $step = (int)ceil($length / $chunk_size); + $length = (int) explode("/", $length[ 0 ])[ 1 ]; + $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); } else { $zip_file = $temp_dir . 'download.zip'; $zip_resource = fopen($zip_file, 'a'); - if (($this->build_task['index'] + 1) <= $this->build_task['step']) { - $start = $this->build_task['index'] * $chunk_size; - $end = ($this->build_task['index'] + 1) * $chunk_size; - $end = min($end, $this->build_task['length']); + if (( $this->build_task[ 'index' ] + 1 ) <= $this->build_task[ 'step' ]) { + $start = $this->build_task[ 'index' ] * $chunk_size; + $end = ( $this->build_task[ 'index' ] + 1 ) * $chunk_size; + $end = min($end, $this->build_task[ 'length' ]); - $response = (new CloudService())->request('GET','cloud/build_download?' . http_build_query($query), [ - 'headers' => ['Range' => "bytes={$start}-{$end}"] + $response = ( new CloudService() )->request('GET', 'cloud/build_download?' . http_build_query($query), [ + 'headers' => [ 'Range' => "bytes={$start}-{$end}" ] ]); fwrite($zip_resource, $response->getBody()); fclose($zip_resource); - $this->build_task['index'] += 1; + $this->build_task[ 'index' ] += 1; 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 { // 解压文件 $zip = new \ZipArchive(); @@ -309,9 +317,10 @@ class CoreCloudBuildService extends BaseCoreService * 清除任务 * @return void */ - public function clearTask() { + public function clearTask() + { 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); Cache::set($this->cache_key, null); } diff --git a/niucloud/app/service/core/niucloud/CoreModuleService.php b/niucloud/app/service/core/niucloud/CoreModuleService.php index 19ce196bb..796286220 100644 --- a/niucloud/app/service/core/niucloud/CoreModuleService.php +++ b/niucloud/app/service/core/niucloud/CoreModuleService.php @@ -122,4 +122,14 @@ class CoreModuleService extends BaseNiucloudClient public function getFrameworkVersionList() { return $this->httpGet('store/framework/version', ['product_key' => self::PRODUCT])['data'] ?? 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; + } } diff --git a/niucloud/app/service/core/pay/CorePayService.php b/niucloud/app/service/core/pay/CorePayService.php index 8995ff374..025b549bf 100644 --- a/niucloud/app/service/core/pay/CorePayService.php +++ b/niucloud/app/service/core/pay/CorePayService.php @@ -277,7 +277,7 @@ class CorePayService extends BaseCoreService ] ); if (env('queue.state', true)) { - PayReturnTo::dispatch([ 'site_id' => $site_id, 'out_trade_no' => $out_trade_no ], secs: 15); + PayReturnTo::dispatch([ 'site_id' => $site_id, 'out_trade_no' => $out_trade_no ], secs: 60); } } return $pay_result; diff --git a/niucloud/app/service/core/pay/CoreTransferSceneService.php b/niucloud/app/service/core/pay/CoreTransferSceneService.php index 448be7370..1a1222dd8 100644 --- a/niucloud/app/service/core/pay/CoreTransferSceneService.php +++ b/niucloud/app/service/core/pay/CoreTransferSceneService.php @@ -71,78 +71,11 @@ class CoreTransferSceneService extends BaseCoreService $config = $this->getWechatTransferSceneConfig($site_id); //查询业务和场景的对应关系表 -// $trade_scene_event_array = [ -// 'shop_fenxiao' => [ -// 'name' => '分销', -// 'scene' => TransferDict::XJYX, -// 'perception' => '', -// 'infos' => [ -// '活动名称' => '分销佣金', -// '奖励说明' => '分销佣金奖励' -// ] -// ] -// ]; $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(['site_id' => $site_id])->column('*', 'type' ); $trade_scene_list = []; foreach($trade_scene_event_array as $trade_scene_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 = 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']] = []; @@ -153,14 +86,8 @@ class CoreTransferSceneService extends BaseCoreService foreach($list as $key => &$v){ $v['scene_id'] = $config[$key] ?? ''; -// $item_transfer_scene_report_infos = $v['transfer_scene_report_infos'] ?? []; $trade_scene_data = $trade_scene_list[$key] ?? []; $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] ?? []; } //然后根据支持的业务来完善业务场景备注 diff --git a/niucloud/app/service/core/site/CoreSiteService.php b/niucloud/app/service/core/site/CoreSiteService.php index d2f58bb6a..24ff7d86e 100644 --- a/niucloud/app/service/core/site/CoreSiteService.php +++ b/niucloud/app/service/core/site/CoreSiteService.php @@ -55,7 +55,6 @@ class CoreSiteService extends BaseCoreService [ 'site_id', '=', $site_id ], ]; $info = $this->model->where($where)->field('site_id, site_name, front_end_name, front_end_logo,front_end_icon, app_type, keywords, logo, icon, `desc`, status, latitude, longitude, province_id, city_id, district_id, address, full_address, phone, business_hours, create_time, expire_time, group_id, app, addons, site_domain')->append([ 'status_name' ])->findOrEmpty()->toArray(); -// dump($info);die; if (!empty($info)) { $site_addons = ( new CoreSiteService() )->getAddonKeysBySiteId((int) $site_id); $info[ 'apps' ] = ( new Addon() )->where([ [ 'key', 'in', $site_addons ], [ 'type', '=', AddonDict::APP ] ])->field('key,title,desc,icon,type,support_app')->select()->toArray(); @@ -161,7 +160,7 @@ class CoreSiteService extends BaseCoreService } //在查询站点所拥有的应用插件,两者结合 $site_addon_keys = is_array($site_info[ 'addons' ]) ? $site_info[ 'addons' ] : []; - return array_merge($group_addon_keys ?? [], $site_addon_keys); + return array_unique(array_merge($group_addon_keys ?? [], $site_addon_keys)); }, self::$cache_tag_name . $site_id ); diff --git a/niucloud/app/service/core/sys/CoreAttachmentService.php b/niucloud/app/service/core/sys/CoreAttachmentService.php index eecb43dff..abdd512e5 100644 --- a/niucloud/app/service/core/sys/CoreAttachmentService.php +++ b/niucloud/app/service/core/sys/CoreAttachmentService.php @@ -60,7 +60,7 @@ class CoreAttachmentService extends BaseCoreService ); $user = $this->model->where($where)->findOrEmpty(); if ($user->isEmpty()) - throw new AdminException('USER_NOT_EXIST'); + throw new AdminException('ATTACHMENT_NOE_EXIST'); return $user; } @@ -137,4 +137,4 @@ class CoreAttachmentService extends BaseCoreService $this->model->destroy($ids); return true; } -} \ No newline at end of file +} diff --git a/niucloud/app/service/core/verify/CoreVerifyService.php b/niucloud/app/service/core/verify/CoreVerifyService.php index e676afa3f..714a86038 100644 --- a/niucloud/app/service/core/verify/CoreVerifyService.php +++ b/niucloud/app/service/core/verify/CoreVerifyService.php @@ -36,22 +36,22 @@ class CoreVerifyService extends BaseCoreService { if (!array_key_exists($type, VerifyDict::getType())) throw new CommonException('VERIFY_TYPE_ERROR');//核销类型错误 //遇到错误直接抛出即可 - $result = array_filter(event('VerifyCreate', ['site_id' => $site_id, 'type' => $type, 'member_id' => $member_id, 'data' => $param]))[ 0 ] ?? []; + $result = array_filter(event('VerifyCreate', [ 'site_id' => $site_id, 'type' => $type, 'member_id' => $member_id, 'data' => $param ]))[ 0 ] ?? []; $data = []; - if(empty($result)){ + if (empty($result)) { $count = 1; - }else{ - $count = $result['count'] ?? 1; - $data = $result['data'] ?? []; - $body = $result['body'] ?? ''; - $relate_tag = $result['relate_tag'] ?? 0; - $expire_time = $result['expire_time'] ?? null; + } else { + $count = $result[ 'count' ] ?? 1; + $data = $result[ 'data' ] ?? []; + $body = $result[ 'body' ] ?? ''; + $relate_tag = $result[ 'relate_tag' ] ?? 0; + $expire_time = $result[ 'expire_time' ] ?? null; } $strData = json_encode($param); $value = [ 'site_id' => $site_id, 'type' => $type, - 'type_name' => VerifyDict::getType()[$type]['name'] ?? '', + 'type_name' => VerifyDict::getType()[ $type ][ 'name' ] ?? '', 'data' => $param, 'value' => $data, 'body' => $body ?? '', @@ -75,12 +75,25 @@ class CoreVerifyService extends BaseCoreService * @param string $verify_code * @return array */ - public function getInfoByCode($site_id, string $verify_code) + public function getInfoByCode($site_id, string $member_id, $verify_code) { //获取核销码数据 $value = $this->getCodeData($verify_code); //检测站点数据 - if($value['site_id'] != $site_id) throw new CommonException('VERIFY_CODE_EXPIRED');//核销码已过期 + if ($value[ 'site_id' ] != $site_id) throw new CommonException('VERIFY_CODE_EXPIRED');//核销码已过期 + $data = event('VerifyCheck', $value); + if (!empty($data)) { + $value = end($data); + } + + // 检测核销员身份,是否有核销权限 + $verifier = ( new Verifier() )->where([ [ 'member_id', '=', $member_id ], [ 'site_id', '=', $site_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; } @@ -93,20 +106,20 @@ class CoreVerifyService extends BaseCoreService //获取核销码数据 $value = $this->getCodeData($verify_code); //检测站点数据 - if($value['site_id'] != $site_id) throw new CommonException('VERIFY_CODE_EXPIRED');//核销码已过期 + if ($value[ 'site_id' ] != $site_id) throw new CommonException('VERIFY_CODE_EXPIRED');//核销码已过期 //检测核销员身份 $verifierModel = new Verifier(); - $verifier = $verifierModel->where([['site_id', '=', $value['site_id']], ['member_id', '=', $verify_member_id]])->findOrEmpty()->toArray(); + $verifier = $verifierModel->where([ [ 'site_id', '=', $value[ 'site_id' ] ], [ 'member_id', '=', $verify_member_id ] ])->findOrEmpty()->toArray(); if (empty($verifier)) throw new CommonException('VERIFIER_NOT_EXIST'); $verify_data = [ - 'site_id' => $value['site_id'], + 'site_id' => $value[ 'site_id' ], 'code' => $verify_code, - 'data' => $value['data'], - 'value' => $value['value'], - 'type' => $value['type'], - 'body' => $value['body'], - 'relate_tag' => $value['relate_tag'], + 'data' => $value[ 'data' ], + 'value' => $value[ 'value' ], + 'type' => $value[ 'type' ], + 'body' => $value[ 'body' ], + 'relate_tag' => $value[ 'relate_tag' ], 'create_time' => time(), 'verifier_member_id' => $verify_member_id, ]; @@ -117,7 +130,6 @@ class CoreVerifyService extends BaseCoreService //是核销码失效 $this->clearCode($verify_code); - return true; } @@ -155,4 +167,4 @@ class CoreVerifyService extends BaseCoreService return $code_cache; } -} \ No newline at end of file +} diff --git a/niucloud/app/service/core/weapp/CoreWeappDeliveryService.php b/niucloud/app/service/core/weapp/CoreWeappDeliveryService.php index a26371d08..e557e98f9 100644 --- a/niucloud/app/service/core/weapp/CoreWeappDeliveryService.php +++ b/niucloud/app/service/core/weapp/CoreWeappDeliveryService.php @@ -104,6 +104,9 @@ class CoreWeappDeliveryService extends BaseCoreService Log::write('发货信息录入接口,参数打印:' . json_encode($data)); + //微信订单录入有时差 延时3秒执行发货通知 + sleep(3); + $api = CoreWeappService::appApiClient($site_id); $result = $api->postJson('wxa/sec/order/upload_shipping_info', $data)->toArray(); @@ -152,6 +155,9 @@ class CoreWeappDeliveryService extends BaseCoreService Log::write('确认收货提醒接口,参数打印:' . json_encode($data)); + //微信订单录入有时差 延时3秒执行发货通知 + sleep(3); + $api = CoreWeappService::appApiClient($site_id); $result = $api->postJson('wxa/sec/order/notify_confirm_receive', $data)->toArray(); @@ -273,4 +279,4 @@ class CoreWeappDeliveryService extends BaseCoreService return $res; } -} \ No newline at end of file +} diff --git a/niucloud/app/service/core/weapp/CoreWeappService.php b/niucloud/app/service/core/weapp/CoreWeappService.php index f2e341670..5cecb69b7 100644 --- a/niucloud/app/service/core/weapp/CoreWeappService.php +++ b/niucloud/app/service/core/weapp/CoreWeappService.php @@ -111,7 +111,7 @@ class CoreWeappService extends BaseCoreService ]); if ($response->isFailed()) { // 出错了,处理异常 - throw new CommonException('WECHAT_MINI_PROGRAM_CODE_GENERATION_FAILED'); + throw new CommonException('微信小程序码生成失败:errcode:' . $response[ 'errcode' ] . 'errmsg:' . $response[ 'errmsg' ]); } $response->saveAs($filepath); return $filepath; diff --git a/niucloud/app/upgrade/v101/Upgrade.php b/niucloud/app/upgrade/v101/Upgrade.php index 5d102592d..a46f6cb53 100644 --- a/niucloud/app/upgrade/v101/Upgrade.php +++ b/niucloud/app/upgrade/v101/Upgrade.php @@ -425,20 +425,25 @@ class Upgrade } } } - if (!empty($data)) { - $diy_theme_model = new DiyTheme(); - foreach ($data as $k => &$v) { - $theme_count = $diy_theme_model->where([ - [ 'site_id', "=", $site_id ], - [ 'title', "=", $v[ 'title' ] ], - [ 'addon', "=", $v[ 'addon' ] ] - ])->count(); - // 如果已有该主题风格颜色则不再添加 - if ($theme_count > 0) { - unset($data[ $k ]); + + try { + if (!empty($data)) { + $diy_theme_model = new DiyTheme(); + foreach ($data as $k => &$v) { + $theme_count = $diy_theme_model->where([ + [ 'site_id', "=", $site_id ], + [ 'title', "=", $v[ 'title' ] ], + [ 'addon', "=", $v[ 'addon' ] ] + ])->count(); + // 如果已有该主题风格颜色则不再添加 + if ($theme_count > 0) { + unset($data[ $k ]); + } } + $diy_theme_model->insertAll($data); } - $diy_theme_model->insertAll($data); + } catch (\Exception $e) { + } return true; } diff --git a/niucloud/app/upgrade/v102/upgrade.sql b/niucloud/app/upgrade/v102/upgrade.sql new file mode 100644 index 000000000..5e1d78192 --- /dev/null +++ b/niucloud/app/upgrade/v102/upgrade.sql @@ -0,0 +1,40 @@ + +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` VARCHAR(255) NOT NULL DEFAULT '' 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:自定义提示'; diff --git a/niucloud/config/version.php b/niucloud/config/version.php index fc44df460..08a84dbb2 100644 --- a/niucloud/config/version.php +++ b/niucloud/config/version.php @@ -1,6 +1,6 @@ '1.0.1', - 'code' => '202503080001' + 'version' => '1.0.2', + 'code' => '202504180001' ]; diff --git a/niucloud/core/exception/CloudBuildException.php b/niucloud/core/exception/CloudBuildException.php new file mode 100644 index 000000000..ec447f5e1 --- /dev/null +++ b/niucloud/core/exception/CloudBuildException.php @@ -0,0 +1,18 @@ + 'refund', 'transaction_id' => $out_trade_no, 'out_refund_no' => $refund_no, - '' ]; $result = Pay::wechat()->query($order); if (empty($result)) diff --git a/niucloud/core/util/DbBackup.php b/niucloud/core/util/DbBackup.php index 5bad871b7..a5ffcd412 100644 --- a/niucloud/core/util/DbBackup.php +++ b/niucloud/core/util/DbBackup.php @@ -1,532 +1,147 @@ './backup/', - // 数据库备份卷大小 - 'part' => 20971520, - // 数据库备份文件是否启用压缩 0不压缩 1 压缩 - 'compress' => 0, - // 数据库备份文件压缩级别 1普通 4 一般 9最高 - 'level' => 9, - ); - - /** - * 数据库备份构造方法 - * @param array $file 备份或还原的文件信息 - * @param array $config 备份配置信息 - */ - public function __construct($config = []) + public function __construct($backupPath, $maxFileSize = 1024 * 1024, $excludeTables = []) { - $this->config = is_array($config) && !empty($config) ? array_merge($this->config, $config) : $this->config; - //初始化文件名 - $this->setFile(); - //初始化数据库连接参数 - $this->setDbConn(); - //检查文件是否可写 - if (!$this->checkPath($this->config['path'])) { - throw new \Exception("The current directory is not writable"); + $this->backupPath = $backupPath; + $this->maxFileSize = $maxFileSize; + $this->excludeTables = $excludeTables; + if (!is_dir($this->backupPath)) { + mkdir($this->backupPath, 0777, true); } + $this->currentFile = $this->backupPath . '/backup_' . $this->currentFileIndex . '.sql'; } - /** - * 设置脚本运行超时时间 - * 0表示不限制,支持连贯操作 - */ - public function setTimeout($time = null) - { - if (!is_null($time)) { - set_time_limit($time) || ini_set("max_execution_time", $time); - } + public function setExcludeTables($tables) { + $this->excludeTables = $tables; return $this; } - /** - * 设置数据库连接必备参数 - * @param array $dbconfig 数据库连接配置信息 - * @return object - */ - public function setDbConn($dbconfig = []) + public function backupDatabaseSegment($limit = 1000) { - if (empty($dbconfig)) { - $this->dbconfig = config('database.connections.'.config('database.default')); - } else { - $this->dbconfig = $dbconfig; - } - return $this; - } - - /** - * 设置备份文件名 - * - * @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; + $tables = $this->getAllTables(); + foreach ($tables as $table) { + if (in_array($table, $this->excludeTables)) { + continue; + } + if (!isset($this->tableOffset[$table])) { + $this->tableOffset[$table] = 0; + $this->backupTableStructure($table); + } + while (true) { + $data = Db::table($table)->limit($this->tableOffset[$table], $limit)->select()->toArray(); + if (empty($data)) { + break; + } + $this->backupTableData($table, $data); + $this->tableOffset[$table] += $limit; } } - return $this; } - /** - * 数据库表列表 - * - * @param null $table - * @param int $type - * @return array - */ - public function dataList($table = null, $type = 1) + private function backupTableStructure($table) { - 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}"); - } + $dropTableQuery = "DROP TABLE IF EXISTS `$table`;\n"; + $dropLength = strlen($dropTableQuery); + if ($this->currentFileSize + $dropLength > $this->maxFileSize) { + $this->startNewFile(); } + $fp = fopen($this->currentFile, 'a'); + fwrite($fp, $dropTableQuery); + $this->currentFileSize += $dropLength; - return array_map('array_change_key_case', $list); + $createTableQuery = $this->getTableCreateQuery($table); + $query = $createTableQuery . ";\n"; + $queryLength = strlen($query); + if ($this->currentFileSize + $queryLength > $this->maxFileSize) { + $this->startNewFile(); + $fp = fopen($this->currentFile, 'a'); + } + fwrite($fp, $query); + fclose($fp); + $this->currentFileSize += $queryLength; } - /** - * 数据库备份文件列表 - * - * @return array - */ - public function fileList() + private function backupTableData($table, $data) { - 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(); + $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 { - $info['part'] = $part; - $info['size'] = $file->getSize(); + $values[] = Db::getPdo()->quote($value); // 其他类型使用 quote 方法处理 } - $extension = strtoupper(pathinfo($file->getFilename(), PATHINFO_EXTENSION)); - $info['name'] = $name1; - $info['compress'] = $extension === 'SQL' ? '-' : $extension; - $info['time'] = strtotime("{$date} {$time}"); - $list["{$date} {$time}"] = $info; } + $valueSets[] = '(' . implode(', ', $values) . ')'; } - return $list; + $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; } - /** - * 获取文件名称 - * - * @param string $type - * @param int $time - * @return array|false|mixed|string - * @throws \Exception - */ - public function getFile($type = '', $time = 0) + private function getAllTables() { - // - if (!is_numeric($time)) { - throw new \Exception("{$time} Illegal data type"); + $tables = Db::query('SHOW TABLES'); + $tableNames = []; + foreach ($tables as $table) { + $tableNames[] = current($table); } - 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); + return $tableNames; + } + + private function getTableCreateQuery($tableName) + { + $result = Db::query("SHOW CREATE TABLE $tableName"); + return $result[0]['Create Table']; + } + + private function startNewFile() + { + $this->currentFileIndex++; + $this->currentFile = $this->backupPath . '/backup_' . $this->currentFileIndex . '.sql'; + $this->currentFileSize = 0; + } + + public function restoreDatabase() + { + $backupFiles = glob($this->backupPath . '/backup_*.sql'); + foreach ($backupFiles as $backupFile) { + $sql = file_get_contents($backupFile); + $queries = explode(";\n", $sql); + foreach ($queries as $query) { + if (trim($query) !== '') { + Db::execute($query); } - $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; - } - - /** - * 导入表 - * - * @param $start - * @param $time - * @return array|false|int - * @throws Exception - */ - public function import($start, $time) - { - //还原数据 - $this->file = $this->getFile('time', $time); - if ($this->config['compress']) { - $gz = gzopen($this->file[0], 'r'); - $size = 0; - } else { - $size = filesize($this->file[0]); - $gz = fopen($this->file[0], 'r'); - } - $sql = ''; - if ($start) { - $this->config['compress'] ? gzseek($gz, $start) : fseek($gz, $start); - } - for ($i = 0; $i < 1000; $i++) { - $sql .= $this->config['compress'] ? gzgets($gz) : fgets($gz); - if (preg_match('/.*;$/', trim($sql))) { - if (false !== Db::query($sql)) { - $start += strlen($sql); - } else { - return false; - } - $sql = ''; - } elseif ($this->config['compress'] ? gzeof($gz) : feof($gz)) { - return 0; } } - return array($start, $size); } - - /** - * 写入初始数据 - * - * @return boolean true - 写入成功,false - 写入失败 - */ - public function backupInit() - { - $sql = "-- -----------------------------\n"; - $sql .= "-- Think MySQL Data Transfer \n"; - $sql .= "-- \n"; - $sql .= "-- Host : ".$this->dbconfig['hostname']."\n"; - $sql .= "-- Port : ".$this->dbconfig['hostport']."\n"; - $sql .= "-- Database : ".$this->dbconfig['database']."\n"; - $sql .= "-- \n"; - $sql .= "-- Part : #{$this->file['part']}\n"; - $sql .= "-- Date : ".date("Y-m-d H:i:s")."\n"; - $sql .= "-- -----------------------------\n\n"; - $sql .= "SET FOREIGN_KEY_CHECKS = 0;\n\n"; - return $this->write($sql); - } - - /** - * 查询单条 - * @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) - { - // 备份表结构 - if (0 == $start) { - $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; - } - - /** - * 优化表 - * - * @param String $tables 表名 - * @return String $tables - */ - public function optimize($tables = null) - { - if ($tables) { - if (is_array($tables)) { - $tables = implode('`,`', $tables); - $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!"); - } - } - - /** - * 修复表 - * - * @param String $tables 表名 - * @return String $tables - */ - public function repair($tables = null) - { - if ($tables) { - if (is_array($tables)) { - $tables = implode('`,`', $tables); - $list = Db::query("REPAIR TABLE `{$tables}`"); - } else { - $list = Db::query("REPAIR TABLE `{$tables}`"); - } - 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!"); - } - } - - /** - * 写入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); - } - } - }