diff --git a/niucloud/app/adminapi/controller/diy/Diy.php b/niucloud/app/adminapi/controller/diy/Diy.php index b6f960fd9..5f0937475 100644 --- a/niucloud/app/adminapi/controller/diy/Diy.php +++ b/niucloud/app/adminapi/controller/diy/Diy.php @@ -270,7 +270,7 @@ class Diy extends BaseAdminController } /** - * 获取自定义主题配色 + * 获取主题风格列表 * @return Response */ public function getDiyTheme() @@ -279,30 +279,79 @@ class Diy extends BaseAdminController } /** - * 添加主题配色 + * 设置主题风格 * @return Response */ public function setDiyTheme() { $data = $this->request->params([ [ 'id', '' ], - [ 'key', '' ], - [ 'mode', '' ], - [ 'color_mark', '' ], - [ 'color_name', '' ], - [ 'diy_value', '' ], - [ 'value', '' ], + [ 'addon', '' ], + [ 'title', '' ], + [ 'theme', '' ], + [ 'new_theme', '' ], ]); ( new DiyService() )->setDiyTheme($data); return success('ADD_SUCCESS'); } /** - * 设置主题配色 + * 获取主题配色列表 * @return Response */ public function getDefaultThemeColor() { - return success(( new DiyService() )->getDefaultThemeColor()); + $data = $this->request->params([ + [ 'addon', '' ], + ]); + return success(( new DiyService() )->getDefaultThemeColor($data)); + } + + /** + * 添加自定义主题配色 + * @return Response + */ + public function addDiyTheme() + { + $data = $this->request->params([ + [ 'title', '' ], + [ 'default_theme', '' ], + [ 'theme', '' ], + [ 'new_theme', '' ], + [ 'addon', '' ] + ]); + $this->validate($data, 'app\validate\diy\DiyTheme.add'); + ( new DiyService() )->addDiyTheme($data); + return success('ADD_SUCCESS'); + } + + /** + * 编辑自定义主题配色 + * @param $id + * @return Response + */ + public function editDiyTheme($id) + { + $data = $this->request->params([ + [ 'title', '' ], + [ 'theme', '' ], + [ 'new_theme', '' ], + [ 'addon', '' ] + ]); + $data[ 'id' ] = $id; + $this->validate($data, 'app\validate\diy\DiyTheme.edit'); + ( new DiyService() )->editDiyTheme($id, $data); + return success('EDIT_SUCCESS'); + } + + /** + * 删除自定义主题配色 + * @param $id + * @return Response + */ + public function delDiyTheme(int $id) + { + ( new DiyService() )->delDiyTheme($id); + return success('DELETE_SUCCESS'); } } diff --git a/niucloud/app/adminapi/controller/diy/DiyForm.php b/niucloud/app/adminapi/controller/diy/DiyForm.php index 010d10bec..4e19b38a9 100644 --- a/niucloud/app/adminapi/controller/diy/DiyForm.php +++ b/niucloud/app/adminapi/controller/diy/DiyForm.php @@ -42,6 +42,21 @@ class DiyForm extends BaseAdminController return success(( new DiyFormService() )->getPage($data)); } + /** + * @notes 获取万能表单分页列表(用于弹框选择) + * @return Response + */ + public function select() + { + $data = $this->request->params([ + [ "title", "" ], + [ "type", "" ], + [ 'addon', '' ], + [ 'verify_form_ids', '' ] // 检测id集合是否存在,移除不存在的id,纠正数据准确性 + ]); + return success(( new DiyFormService() )->getSelectPage($data)); + } + /** * @notes 获取万能表单列表 * @return Response @@ -101,7 +116,7 @@ class DiyForm extends BaseAdminController [ "value", [] ], [ 'template', '' ], ]); - + $data[ 'form_id' ] = $id; $this->validate($data, 'app\validate\diy\DiyForm.edit'); ( new DiyFormService() )->edit($id, $data); return success('MODIFY_SUCCESS'); diff --git a/niucloud/app/adminapi/controller/member/CashOut.php b/niucloud/app/adminapi/controller/member/CashOut.php index 3c975765f..2179a4a59 100644 --- a/niucloud/app/adminapi/controller/member/CashOut.php +++ b/niucloud/app/adminapi/controller/member/CashOut.php @@ -120,4 +120,15 @@ class CashOut extends BaseAdminController (new MemberCashOutService())->checkTransferStatus($id); return success(); } + + /** + * 取消 + * @param $id + * @return void + */ + public function cancel($id){ + + (new MemberCashOutService())->cancel($id); + return success(); + } } diff --git a/niucloud/app/adminapi/controller/pay/Transfer.php b/niucloud/app/adminapi/controller/pay/Transfer.php new file mode 100644 index 000000000..3d25ec904 --- /dev/null +++ b/niucloud/app/adminapi/controller/pay/Transfer.php @@ -0,0 +1,54 @@ +getWechatTransferScene()); + } + + /** + * 设置场景id + * @param $scene + * @return void + */ + public function setSceneId($scene){ + $data = $this->request->params([ + ['scene_id', ''], + ]); + return success(data:(new TransferService())->setSceneId($scene, $data)); + } + + /** + * 设置业务转账场景配置 + * @param $type + * @return \think\Response + */ + public function setTradeScene($type){ + $data = $this->request->params([ + ['scene', ''], + ['infos', []], + ['perception', ''], + ]); + return success(data:(new TransferService())->setTradeScene($type, $data)); + } +} \ No newline at end of file diff --git a/niucloud/app/adminapi/controller/sys/System.php b/niucloud/app/adminapi/controller/sys/System.php index 50a0afcd4..b3ff539c4 100644 --- a/niucloud/app/adminapi/controller/sys/System.php +++ b/niucloud/app/adminapi/controller/sys/System.php @@ -50,14 +50,21 @@ class System extends BaseAdminController } /** - * 清理缓存,更新菜单 + * 清理表缓存 */ public function schemaCache() { - return success((new SystemService())->schemaCache()); } + /** + * 清理缓存 + */ + public function clearCache() + { + return success((new SystemService())->clearCache()); + } + /** * 校验消息队列是否正常运行 * @return Response diff --git a/niucloud/app/adminapi/controller/weapp/Config.php b/niucloud/app/adminapi/controller/weapp/Config.php index 65109cd1d..16aa77b71 100644 --- a/niucloud/app/adminapi/controller/weapp/Config.php +++ b/niucloud/app/adminapi/controller/weapp/Config.php @@ -48,4 +48,42 @@ class Config extends BaseAdminController return success('SET_SUCCESS'); } + /** + * 设置微信小程序域名 + * @return Response + */ + public function setDomain() { + $data = $this->request->params([ + ['requestdomain', ''], + ['wsrequestdomain', ''], + ['uploaddomain', ''], + ['downloaddomain', ''], + ['udpdomain', ''], + ['tcpdomain', ''] + ]); + (new WeappConfigService())->setDomain($data); + return success('SET_SUCCESS'); + } + + /** + * 获取微信小程序隐私协议 + * @return Response + */ + public function getPrivacySetting() { + return success((new WeappConfigService())->getPrivacySetting()); + } + + /** + * 设置微信小程序隐私协议 + * @return Response + */ + public function setPrivacySetting() { + $data = $this->request->params([ + ['setting_list', []], + ['owner_setting', []], + ['sdk_privacy_info_list', []] + ]); + (new WeappConfigService())->setPrivacySetting($data); + return success('SET_SUCCESS'); + } } diff --git a/niucloud/app/adminapi/route/diy.php b/niucloud/app/adminapi/route/diy.php index ec73ea2a0..3e41eb7de 100644 --- a/niucloud/app/adminapi/route/diy.php +++ b/niucloud/app/adminapi/route/diy.php @@ -93,6 +93,15 @@ Route::group('diy', function() { // 获取默认主题配色 Route::get('theme/color', 'diy.Diy/getDefaultThemeColor'); + // 添加自定义主题配色 + Route::post('theme/add', 'diy.Diy/addDiyTheme'); + + // 编辑自定义主题配色 + Route::put('theme/edit/:id', 'diy.Diy/editDiyTheme'); + + // 删除自定义主题配色 + Route::delete('theme/delete/:id', 'diy.Diy/delDiyTheme'); + /***************************************************** 配置相关 *****************************************************/ // 底部导航列表 @@ -112,6 +121,9 @@ Route::group('diy', function() { // 万能表单列表 Route::get('form/list', 'diy.DiyForm/lists'); + // 万能表单分页列表(用于弹框选择) + Route::get('form/select', 'diy.DiyForm/select'); + // 万能表单类型 Route::get('form/type', 'diy.DiyForm/getFormType'); diff --git a/niucloud/app/adminapi/route/member.php b/niucloud/app/adminapi/route/member.php index 12314df7f..59cfc3508 100644 --- a/niucloud/app/adminapi/route/member.php +++ b/niucloud/app/adminapi/route/member.php @@ -122,6 +122,8 @@ Route::group('member', function() { Route::put('cash_out/audit/:id/:action', 'member.CashOut/audit'); //会员提现备注 Route::put('cash_out/remark/:id', 'member.CashOut/remark'); + //取消会员提现 + Route::put('cash_out/cancel/:id', 'member.CashOut/cancel'); //校验会员提现转账状态 Route::put('cash_out/check/:id', 'member.CashOut/checkTransferStatus'); //转账方式 diff --git a/niucloud/app/adminapi/route/pay.php b/niucloud/app/adminapi/route/pay.php index ef9e7a9f8..208e897d4 100644 --- a/niucloud/app/adminapi/route/pay.php +++ b/niucloud/app/adminapi/route/pay.php @@ -59,6 +59,14 @@ Route::group('pay', function () { Route::get('type/list', 'pay.Pay/payTypeList'); //找朋友帮忙付支付信息 Route::get('friendspay/info/:trade_type/:trade_id/:channel', 'pay.Pay/friendspayInfo'); + + /***************************************************** 转账 *************************************************/ + //获取转账场景 + Route::get('transfer_scene', 'pay.Transfer/getWechatTransferScene'); + //设置场景id + Route::post('transfer_scene/set_scene_id/:scene', 'pay.Transfer/setSceneId'); + //设置业务场景配置 + Route::post('transfer_scene/set_trade_scene/:type', 'pay.Transfer/setTradeScene'); })->middleware([ AdminCheckToken::class, AdminCheckRole::class, diff --git a/niucloud/app/adminapi/route/sys.php b/niucloud/app/adminapi/route/sys.php index 9517dd6cf..ca2c05127 100644 --- a/niucloud/app/adminapi/route/sys.php +++ b/niucloud/app/adminapi/route/sys.php @@ -203,6 +203,7 @@ Route::group('sys', function() { /***************************************************** 清理缓存-刷新菜单 ****************************************************/ Route::post('schema/clear', 'sys.System/schemaCache'); + Route::post('cache/clear', 'sys.System/clearCache'); /***************************************************** 公共字典数据 ****************************************************/ Route::get('date/month', 'sys.Common/getMonth'); diff --git a/niucloud/app/adminapi/route/weapp.php b/niucloud/app/adminapi/route/weapp.php index 2a9a8b68b..2e233315b 100644 --- a/niucloud/app/adminapi/route/weapp.php +++ b/niucloud/app/adminapi/route/weapp.php @@ -24,6 +24,12 @@ Route::group('weapp', function() { Route::get('config', 'weapp.Config/get'); //设置微信配置 Route::put('config', 'weapp.Config/set'); + //设置微信域名 + Route::put('domain', 'weapp.Config/setDomain'); + // 设置微信隐私协议 + Route::put('privacysetting', 'weapp.Config/setPrivacySetting'); + // 获取微信隐私协议 + Route::get('privacysetting', 'weapp.Config/getPrivacySetting'); /***************************************************** 订阅消息 ****************************************************/ //同步订阅消息 @@ -41,6 +47,7 @@ Route::group('weapp', function() { Route::get('upload/:key', 'weapp.Version/uploadLog'); + /***************************************************** 小程序发货信息管理服务 ****************************************************/ // 查询小程序是否已开通发货信息管理服务 diff --git a/niucloud/app/api/controller/login/Login.php b/niucloud/app/api/controller/login/Login.php index 3883074bb..6da67c6bb 100644 --- a/niucloud/app/api/controller/login/Login.php +++ b/niucloud/app/api/controller/login/Login.php @@ -86,7 +86,8 @@ class Login extends BaseController [ 'mobile', '' ], [ 'nickname', '' ], [ 'headimg', '' ], - [ 'mobile', '' ] + [ 'mobile', '' ], + [ 'openid', '' ] ]); //校验登录注册配置 ( new ConfigService() )->checkLoginConfig(MemberLoginTypeDict::MOBILE); diff --git a/niucloud/app/api/controller/login/Register.php b/niucloud/app/api/controller/login/Register.php index ad76a1545..8231c1a1c 100644 --- a/niucloud/app/api/controller/login/Register.php +++ b/niucloud/app/api/controller/login/Register.php @@ -31,13 +31,14 @@ class Register extends BaseController [ 'username', '' ], [ 'password', '' ], [ 'mobile', '' ], + [ 'wx_openid', '' ] ]); //校验登录注册配置 ( new ConfigService() )->checkLoginConfig(MemberLoginTypeDict::USERNAME); //参数验证 $this->validate($data, 'app\validate\member\Member.account_register'); //验证码验证 - $result = ( new RegisterService() )->account($data[ 'username' ], $data[ 'password' ], $data[ 'mobile' ]); + $result = ( new RegisterService() )->account($data[ 'username' ], $data[ 'password' ], $data[ 'mobile' ], $data[ 'wx_openid' ]); return success($result); } diff --git a/niucloud/app/api/controller/member/MemberCashOut.php b/niucloud/app/api/controller/member/MemberCashOut.php index b0fc996db..176cd1389 100644 --- a/niucloud/app/api/controller/member/MemberCashOut.php +++ b/niucloud/app/api/controller/member/MemberCashOut.php @@ -27,12 +27,12 @@ class MemberCashOut extends BaseApiController public function lists() { $data = array_filter($this->request->params([ - [ 'status', '' ], - [ 'account_type', '' ] - ]), function($value){ + ['status', ''], + ['account_type', ''] + ]), function ($value) { return $value !== ''; }); - return success(( new MemberCashOutService() )->getPage($data)); + return success((new MemberCashOutService())->getPage($data)); } /** @@ -41,7 +41,7 @@ class MemberCashOut extends BaseApiController */ public function info($id) { - return success(( new MemberCashOutService() )->getInfo($id)); + return success((new MemberCashOutService())->getInfo($id)); } /** @@ -50,7 +50,7 @@ class MemberCashOut extends BaseApiController */ public function config() { - return success(( new MemberCashOutService() )->getCashOutConfig()); + return success((new MemberCashOutService())->getCashOutConfig()); } /** @@ -69,14 +69,14 @@ class MemberCashOut extends BaseApiController public function apply() { $data = $this->request->params([ - [ 'apply_money', 0 ], - [ 'account_type', MemberAccountTypeDict::MONEY ], - [ 'transfer_type', '' ], - [ 'account_id', 0 ], - [ 'transfer_payee', []] ,//收款方信息 + ['apply_money', 0], + ['account_type', MemberAccountTypeDict::MONEY], + ['transfer_type', ''], + ['account_id', 0], + ['transfer_payee', []],//收款方信息 ]); $this->validate($data, 'app\validate\member\CashOut.apply'); - return success(data:( new MemberCashOutService() )->apply($data)); + return success(data: (new MemberCashOutService())->apply($data)); } /** @@ -86,7 +86,20 @@ class MemberCashOut extends BaseApiController */ public function cancel($id) { - return success(data:( new MemberCashOutService() )->cancel($id)); + return success(data: (new MemberCashOutService())->cancel($id)); + } + + /** + * 开始转账 + * @param $id + * @return Response + */ + public function transfer($id) + { + $data = $this->request->params([ + ['open_id', 0], + ]); + return success(data: (new MemberCashOutService())->transfer($id, $data)); } } diff --git a/niucloud/app/api/controller/pay/Transfer.php b/niucloud/app/api/controller/pay/Transfer.php new file mode 100644 index 000000000..0e1ef5269 --- /dev/null +++ b/niucloud/app/api/controller/pay/Transfer.php @@ -0,0 +1,43 @@ +request->params([ +// ['openid', ''] +// ]); +// +// return success('SUCCESS',(new PayService())->pay($data['type'], $data['trade_type'], $data['trade_id'], $data['return_url'], $data['quit_url'], $data['buyer_id'], $data['voucher'], $data['openid'])); + } + + +} diff --git a/niucloud/app/api/controller/sys/Config.php b/niucloud/app/api/controller/sys/Config.php index 5ca44483e..afee728c6 100644 --- a/niucloud/app/api/controller/sys/Config.php +++ b/niucloud/app/api/controller/sys/Config.php @@ -80,6 +80,7 @@ class Config extends BaseApiController { $data = $this->request->params([ [ 'url', '' ], + [ 'openid', '' ] ]); $res = []; @@ -90,6 +91,12 @@ class Config extends BaseApiController $res[ 'login_config' ] = ( new MemberConfigService() )->getLoginConfig($data[ 'url' ]); $res[ 'theme_list' ] = ( new DiyService() )->getDiyTheme(); + // 查询是否已经存在该小程序用户, 如果存在则小程序端快捷登录时不再弹出授权弹框 + $res[ 'member_exist' ] = 0; + if (!empty($data[ 'openid' ])) { + $res[ 'member_exist' ] = ( new MemberService() )->getCount([ [ 'weapp_openid', '=', $data[ 'openid' ] ] ]) > 0 ? 1 : 0; + } + ( new MemberService() )->initMemberData(); if (isset($res[ 'site_info' ][ 'site_id' ]) && !empty($res[ 'site_info' ][ 'site_id' ])) { diff --git a/niucloud/app/api/route/file.php b/niucloud/app/api/route/file.php index d8f35fb04..9b5670415 100644 --- a/niucloud/app/api/route/file.php +++ b/niucloud/app/api/route/file.php @@ -41,4 +41,5 @@ Route::group('file', function() { Route::post('image/base64', 'upload.Upload/imageBase64'); })->middleware(ApiChannel::class) + ->middleware(ApiCheckToken::class, false) ->middleware(ApiLog::class); diff --git a/niucloud/app/api/route/member.php b/niucloud/app/api/route/member.php index b88ac5cbf..59a1e90c7 100644 --- a/niucloud/app/api/route/member.php +++ b/niucloud/app/api/route/member.php @@ -66,6 +66,8 @@ Route::group('member', function () { Route::post('cash_out/apply', 'member.MemberCashOut/apply'); //撤销提现申请 Route::put('cash_out/cancel/:id', 'member.MemberCashOut/cancel'); + // 提现转账 + Route::post('cash_out/transfer/:id', 'member.MemberCashOut/transfer'); // 提现账号列表 Route::get('cashout_account', 'member.CashOutAccount/lists'); // 提现账号详情 @@ -78,7 +80,6 @@ Route::group('member', function () { Route::put('cashout_account/:account_id', 'member.CashOutAccount/edit'); // 删除提现账号 Route::delete('cashout_account/:account_id', 'member.CashOutAccount/del'); - /***************************************************** 会员地址 **************************************************/ //会员收货地址列表 Route::get('address', 'member.Address/lists'); diff --git a/niucloud/app/api/route/pay.php b/niucloud/app/api/route/pay.php index 52c9821cf..5a9eb602a 100644 --- a/niucloud/app/api/route/pay.php +++ b/niucloud/app/api/route/pay.php @@ -40,6 +40,16 @@ Route::group('pay',function () { //支付关闭 Route::post('close', 'pay.Pay/close'); +})->middleware(ApiChannel::class) + ->middleware(ApiCheckToken::class, true)//表示验证登录 + ->middleware(ApiLog::class); + + +Route::group('transfer',function () { + //去支付 + Route::post('confirm/:transfer_no', 'pay.Pay/pay'); + + })->middleware(ApiChannel::class) ->middleware(ApiCheckToken::class, true)//表示验证登录 ->middleware(ApiLog::class); \ No newline at end of file diff --git a/niucloud/app/common.php b/niucloud/app/common.php index 914c9802e..7ce5de78c 100644 --- a/niucloud/app/common.php +++ b/niucloud/app/common.php @@ -560,8 +560,12 @@ function dir_copy(string $src = '', string $dst = '', &$files = [], $exclude_dir } else { // 排除文件 if (count($exclude_files) && in_array($file, $exclude_files)) continue; - copy($src . '/' . $file, $dst . '/' . $file); + $copyResult = copy($src . '/' . $file, $dst . '/' . $file); $files[] = $dst . '/' . $file; + if (!$copyResult) { + closedir($dir); + throw new \core\exception\CommonException("文件{$file}拷贝失败请检查是否有足够的权限"); + } } } } @@ -1018,3 +1022,53 @@ function get_last_time($time = null) } return $text; } + +/** + * 检查目录及其子目录的权限 + * @param string $dir 要检查的目录路径 + * @return void + */ +function checkDirPermissions($dir, $data = []) { + if (!is_dir($dir)) { + throw new \RuntimeException(sprintf('指定的路径 "%s" 不是一个有效的目录', $dir)); + } + + if (empty($data)) { + $data = [ + 'unreadable' => [], + 'not_writable' => [] + ]; + } + + try { + if (!is_readable($dir)) { + $data['unreadable'][] = $dir; + } + if (!is_writable($dir)) { + $data['not_writable'][] = $dir; + } + if (is_readable($dir)) { + $dh = opendir($dir); + while (($file = readdir($dh)) !== false) { + if ($file === '.' || $file === '..') { + continue; + } + $fullPath = $dir . DIRECTORY_SEPARATOR . $file; + // 判断是否为目录,如果是则递归调用 + if (is_dir($fullPath)) { + $data = checkDirPermissions($fullPath, $data); // 递归调用自身来检查子目录 + } else { + // 如果是文件,则检查其读写权限 + 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; + return $data; + } +} diff --git a/niucloud/app/dict/diy/ComponentDict.php b/niucloud/app/dict/diy/ComponentDict.php index 83e51c1d4..017b68f73 100644 --- a/niucloud/app/dict/diy/ComponentDict.php +++ b/niucloud/app/dict/diy/ComponentDict.php @@ -614,7 +614,8 @@ class ComponentDict ] ] ], - "offset" => 0 // 偏移量 + "offset" => 0, // 上下偏移量 + "lateralOffset" => 15 // 左右偏移量 ], ], 'HorzBlank' => [ diff --git a/niucloud/app/dict/diy/LinkDict.php b/niucloud/app/dict/diy/LinkDict.php index 0dbaed213..c7cdee482 100644 --- a/niucloud/app/dict/diy/LinkDict.php +++ b/niucloud/app/dict/diy/LinkDict.php @@ -28,136 +28,6 @@ class LinkDict */ public static function getLink($params = []) { - $system_links = [ - 'SYSTEM_LINK' => [ - 'title' => get_lang('dict_diy.system_link'), - 'addon_info' => [ - 'title' => '系统', - 'key' => 'app' - ], - 'child_list' => [ - [ - 'name' => 'INDEX', - 'title' => get_lang('dict_diy.system_link_index'), - 'url' => '/app/pages/index/index', - 'is_share' => 1, - 'action' => 'decorate' // 默认空,decorate 表示支持装修 - ], - ] - ], - 'MEMBER_LINK' => [ - 'title' => get_lang('dict_diy.member_link'), - 'addon_info' => [ - 'title' => '系统', - 'key' => 'app' - ], - 'child_list' => [ - [ - 'name' => 'MEMBER_CENTER', - 'title' => get_lang('dict_diy.member_index'), - 'url' => '/app/pages/member/index', - 'is_share' => 1, - 'action' => 'decorate' - ], - [ - 'name' => 'MEMBER_PERSONAL', - 'title' => get_lang('dict_diy.member_my_personal'), - 'url' => '/app/pages/member/personal', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_BALANCE', - 'title' => get_lang('dict_diy.member_my_balance'), - 'url' => '/app/pages/member/balance', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_POINT', - 'title' => get_lang('dict_diy.member_my_point'), - 'url' => '/app/pages/member/point', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_COMMISSION', - 'title' => get_lang('dict_diy.member_my_commission'), - 'url' => '/app/pages/member/commission', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_ADDRESS', - 'title' => get_lang('dict_diy.member_my_address'), - 'url' => '/app/pages/member/address', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_MY_LEVEL', - 'title' => get_lang('dict_diy.member_my_level'), - 'url' => '/app/pages/member/level', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_MY_SIGN_IN', - 'title' => get_lang('dict_diy.member_my_sign_in'), - 'url' => '/app/pages/member/sign_in', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_VERIFY_INDEX', - 'title' => get_lang('dict_diy.member_verify_index'), - 'url' => '/app/pages/verify/index', - 'is_share' => 0, - 'action' => '' - ], - [ - 'name' => 'MEMBER_CONTACT', - 'title' => get_lang('dict_diy.member_contact'), - 'url' => '/app/pages/member/contact', - 'is_share' => 0, - 'action' => '' - ], - ] - ], - 'DIY_PAGE' => [ - 'title' => get_lang('dict_diy.diy_page'), - 'addon_info' => [ - 'title' => '系统', - 'key' => 'app' - ], - 'child_list' => [] - ], - 'DIY_LINK' => [ - 'title' => get_lang('dict_diy.diy_link'), - 'addon_info' => [ - 'title' => '系统', - 'key' => 'app' - ], - 'child_list' => [] - ], - 'DIY_JUMP_OTHER_APPLET' => [ - 'title' => get_lang('dict_diy.diy_jump_other_applet'), - 'addon_info' => [ - 'title' => '系统', - 'key' => 'app' - ], - 'child_list' => [] - ], - 'DIY_MAKE_PHONE_CALL' => [ - 'title' => get_lang('dict_diy.diy_make_phone_call'), - 'addon_info' => [ - 'title' => '系统', - 'key' => 'app' - ], - 'child_list' => [] - ] - ]; - // 查询存在页面路由的应用插件列表 if (!empty($params[ 'query' ]) && $params[ 'query' ] == 'addon') { $system = [ @@ -170,8 +40,139 @@ class LinkDict $app = array_merge($system, $addons); return $app; } else { + $system_info = [ + 'title' => '系统', + 'key' => 'app' + ]; + $system_links = [ + 'SYSTEM_BASE_LINK' => [ + 'title' => '系统页面', + 'addon_info' => $system_info, + 'type' => 'folder', // 类型,folder 表示文件夹,link 表示链接 + 'child_list' => [ + [ + 'name' => 'SYSTEM_LINK', + 'title' => get_lang('dict_diy.system_link'), + 'child_list' => [ + [ + 'name' => 'INDEX', + 'title' => get_lang('dict_diy.system_link_index'), + 'url' => '/app/pages/index/index', + 'is_share' => 1, + 'action' => 'decorate' // 默认空,decorate 表示支持装修 + ], + ] + ], + [ + 'name' => 'MEMBER_LINK', + 'title' => get_lang('dict_diy.member_link'), + 'child_list' => [ + [ + 'name' => 'MEMBER_CENTER', + 'title' => get_lang('dict_diy.member_index'), + 'url' => '/app/pages/member/index', + 'is_share' => 1, + 'action' => 'decorate' + ], + [ + 'name' => 'MEMBER_PERSONAL', + 'title' => get_lang('dict_diy.member_my_personal'), + 'url' => '/app/pages/member/personal', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_BALANCE', + 'title' => get_lang('dict_diy.member_my_balance'), + 'url' => '/app/pages/member/balance', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_POINT', + 'title' => get_lang('dict_diy.member_my_point'), + 'url' => '/app/pages/member/point', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_COMMISSION', + 'title' => get_lang('dict_diy.member_my_commission'), + 'url' => '/app/pages/member/commission', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_ADDRESS', + 'title' => get_lang('dict_diy.member_my_address'), + 'url' => '/app/pages/member/address', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_MY_LEVEL', + 'title' => get_lang('dict_diy.member_my_level'), + 'url' => '/app/pages/member/level', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_MY_SIGN_IN', + 'title' => get_lang('dict_diy.member_my_sign_in'), + 'url' => '/app/pages/member/sign_in', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_VERIFY_INDEX', + 'title' => get_lang('dict_diy.member_verify_index'), + 'url' => '/app/pages/verify/index', + 'is_share' => 0, + 'action' => '' + ], + [ + 'name' => 'MEMBER_CONTACT', + 'title' => get_lang('dict_diy.member_contact'), + 'url' => '/app/pages/member/contact', + 'is_share' => 0, + 'action' => '' + ], + ] + ], + [ + 'name' => 'DIY_FORM_SELECT', + 'title' => get_lang('dict_diy.diy_form_select'), + 'component' => '/src/app/views/diy_form/components/form-select-content.vue' + ], + ] + ], + 'DIY_PAGE' => [ + 'title' => get_lang('dict_diy.diy_page'), + 'addon_info' => $system_info, + 'child_list' => [] + ], + 'OTHER_LINK' => [ + 'title' => '其他页面', + 'addon_info' => $system_info, + 'type' => 'folder', // 类型,folder 表示文件夹,link 表示链接 + 'child_list' => [ + [ + 'name' => 'DIY_LINK', + 'title' => get_lang('dict_diy.diy_link'), + ], + [ + 'name' => 'DIY_JUMP_OTHER_APPLET', + 'title' => get_lang('dict_diy.diy_jump_other_applet'), + ], + [ + 'name' => 'DIY_MAKE_PHONE_CALL', + 'title' => get_lang('dict_diy.diy_make_phone_call'), + ] + ] + ], + ]; return ( new DictLoader("UniappLink") )->load([ 'data' => $system_links, 'params' => $params ]); } } -} \ No newline at end of file +} diff --git a/niucloud/app/dict/diy/PagesDict.php b/niucloud/app/dict/diy/PagesDict.php index 144326249..e84b7558d 100644 --- a/niucloud/app/dict/diy/PagesDict.php +++ b/niucloud/app/dict/diy/PagesDict.php @@ -87,7 +87,21 @@ class PagesDict foreach ($link_list as $ck => $cv) { if ($cv[ 'addon_info' ][ 'key' ] == $v[ 'key' ]) { foreach ($cv[ 'child_list' ] as $tk => $tv) { - if ($tv[ 'url' ] == $v[ 'url' ]) { + if (isset($cv[ 'type' ]) && $cv[ 'type' ] == 'folder') { + if (!empty($tv[ 'child_list' ])) { + foreach ($tv[ 'child_list' ] as $child_k => $child_v) { + if ($child_v[ 'url' ] == $v[ 'url' ]) { + $link = [ + "parent" => $ck, + "name" => $child_v[ 'name' ], + "title" => $child_v[ 'title' ], + "url" => $child_v[ 'url' ] + ]; + break; + } + } + } + } else if ($tv[ 'url' ] == $v[ 'url' ]) { $link = [ "parent" => $ck, "name" => $tv[ 'name' ], diff --git a/niucloud/app/dict/diy_form/ComponentDict.php b/niucloud/app/dict/diy_form/ComponentDict.php index db3cc0580..37373a4a7 100644 --- a/niucloud/app/dict/diy_form/ComponentDict.php +++ b/niucloud/app/dict/diy_form/ComponentDict.php @@ -124,6 +124,7 @@ class ComponentDict 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 // 'detailComponent' => '/src/app/views/diy_form/components/detail-form-render.vue', // 用于详情展示,后台会返回默认,特殊组件可以重写组件 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -174,6 +175,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -225,6 +227,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -281,6 +284,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => [], // 默认值 存储数据类型不同,各组件自行处理 'value' => [], // 字段值 存储数据类型不同,各组件自行处理 ], @@ -369,6 +373,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => [], // 默认值 存储数据类型不同,各组件自行处理 'value' => [], // 字段值 存储数据类型不同,各组件自行处理 ], @@ -451,6 +456,7 @@ class ComponentDict // 'unique' => false, // 内容不可重复提交 true:是,false:否 // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // ], @@ -500,6 +506,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -550,6 +557,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -600,6 +608,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -650,6 +659,7 @@ class ComponentDict // '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' => '', // 字段值 存储数据类型不同,各组件自行处理 @@ -717,6 +727,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 'default' => [ // 默认值 存储数据类型不同,各组件自行处理 'date' => '', // 例:2024-12-27 'timestamp' => 0, // 例:1735290511 @@ -788,6 +799,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 // 默认值 存储数据类型不同,各组件自行处理 'default' => [ // todo 在做的过程中可能会再调整字段名称 @@ -882,6 +894,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 ], @@ -933,6 +946,7 @@ class ComponentDict 'unique' => false, // 内容不可重复提交 true:是,false:否 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 + 'cache' => false, // 开启本地数据缓存 true:开启,false:关闭 // 默认值 存储数据类型不同,各组件自行处理 'default' => [ 'start' => [ @@ -1025,6 +1039,7 @@ class ComponentDict // 'unique' => false, // 内容不可重复提交 true:是,false:否 // 'autofill' => false, // 自动填充上次填写的内容 true:开启,false:关闭 // 'privacyProtection' => false, // 隐私保护 true:开启,false:关闭,隐藏逻辑各组件自行处理 +// 'cache' => true, // 开启本地数据缓存 true:开启,false:关闭 // 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 // 'value' => '', // 字段值 存储数据类型不同,各组件自行处理 // ], @@ -1127,6 +1142,7 @@ class ComponentDict '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-image.vue', // 用于详情展示 'default' => '', // 默认值 存储数据类型不同,各组件自行处理 'value' => [], // 字段值 存储数据类型不同,各组件自行处理 @@ -1207,6 +1223,7 @@ class ComponentDict // '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' => '', // 字段值 存储数据类型不同,各组件自行处理 @@ -1263,6 +1280,7 @@ class ComponentDict // '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' => '', // 字段值 存储数据类型不同,各组件自行处理 diff --git a/niucloud/app/dict/diy_form/TemplateDict.php b/niucloud/app/dict/diy_form/TemplateDict.php index 6ee557cd6..f451e3f0e 100644 --- a/niucloud/app/dict/diy_form/TemplateDict.php +++ b/niucloud/app/dict/diy_form/TemplateDict.php @@ -1,6 +1,6 @@ false, "autofill" => false, "privacyProtection" => false, + 'cache' => true, "default" => "", "value" => "" ], @@ -230,6 +231,7 @@ class TemplateDict "unique" => true, "autofill" => false, "privacyProtection" => true, + 'cache' => true, "default" => "", "value" => "" ], @@ -279,6 +281,7 @@ class TemplateDict "unique" => true, "autofill" => false, "privacyProtection" => false, + 'cache' => true, "default" => "", "value" => "" ], @@ -328,6 +331,7 @@ class TemplateDict "unique" => false, "autofill" => false, "privacyProtection" => false, + 'cache' => true, "default" => "", "value" => "" ], @@ -377,13 +381,14 @@ class TemplateDict "unique" => false, "autofill" => false, "privacyProtection" => false, + 'cache' => false, "default" => [ - "date" => "2025-01-11", - "timestamp" => 1736564405.243 + "date" => "", + "timestamp" => 0 ], "value" => [ - "date" => "2025-01-11 11=>02", - "timestamp" => 1736564520 + "date" => "", + "timestamp" => 0 ] ], "placeholder" => "请选择日期", @@ -435,6 +440,7 @@ class TemplateDict "unique" => false, "autofill" => false, "privacyProtection" => false, + 'cache' => true, "default" => [], "value" => [] ], @@ -518,6 +524,7 @@ class TemplateDict "unique" => false, "autofill" => false, "privacyProtection" => false, + 'cache' => true, "default" => "", "value" => "" ], @@ -569,24 +576,25 @@ class TemplateDict "unique" => false, "autofill" => false, "privacyProtection" => false, + 'cache' => false, "default" => [ "start" => [ - "date" => "2025-01-11", - "timestamp" => 1736585705 + "date" => "", + "timestamp" => 0 ], "end" => [ - "date" => "2025-01-18", - "timestamp" => 1737190505 + "date" => "", + "timestamp" => 0 ] ], "value" => [ "start" => [ - "date" => "2025/01/11", - "timestamp" => 1736524800 + "date" => "", + "timestamp" => 0 ], "end" => [ - "date" => "2025/01/11", - "timestamp" => 1736524800 + "date" => "", + "timestamp" => 0 ] ] ], @@ -595,12 +603,12 @@ class TemplateDict "dateFormat" => "YYYY/MM/DD", "start" => [ "placeholder" => "请选择起始日期", - "dateWay" => "diy", + "dateWay" => "current", "defaultControl" => true ], "end" => [ "placeholder" => "请选择结束日期", - "dateWay" => "diy", + "dateWay" => "current", "defaultControl" => true ], "textColor" => "#303133", diff --git a/niucloud/app/dict/menu/admin.php b/niucloud/app/dict/menu/admin.php index b40ce9a28..e38b90e22 100644 --- a/niucloud/app/dict/menu/admin.php +++ b/niucloud/app/dict/menu/admin.php @@ -869,6 +869,20 @@ return [ 'status' => '1', 'is_show' => '1', ], + [ + 'menu_name' => '编辑站点用户', + 'menu_key' => 'edit_user', + 'menu_short_name' => '', + 'menu_type' => '2', + 'icon' => '', + 'api_url' => 'user/user/', + 'router_path' => '', + 'view_path' => '', + 'methods' => 'put', + 'sort' => '100', + 'status' => '1', + 'is_show' => '1', + ], [ 'menu_name' => '删除站点用户', 'menu_key' => 'delete_user', @@ -883,6 +897,20 @@ return [ 'status' => '1', 'is_show' => '1', ], + [ + 'menu_name' => '获取站点用户信息', + 'menu_key' => 'get_user_info', + 'menu_short_name' => '', + 'menu_type' => '2', + 'icon' => '', + 'api_url' => 'user/user/', + 'router_path' => '', + 'view_path' => '', + 'methods' => 'get', + 'sort' => '100', + 'status' => '1', + 'is_show' => '0', + ], [ 'menu_name' => '获取用户套餐权限', 'menu_key' => 'get_user_create_site_limit', @@ -1635,6 +1663,20 @@ 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 93fff7b2c..80254c232 100644 --- a/niucloud/app/dict/menu/site.php +++ b/niucloud/app/dict/menu/site.php @@ -2022,6 +2022,20 @@ return [ ], ], ], + [ + 'menu_name' => '转账场景', + 'menu_key' => 'transfer_scene_config', + 'menu_short_name' => '转账场景', + 'menu_type' => '1', + 'icon' => 'element Postcard', + 'api_url' => '', + 'router_path' => 'setting/transfer_scene', + 'view_path' => 'setting/transfer_scene', + 'methods' => 'get', + 'sort' => '59', + 'status' => '1', + 'is_show' => '1', + ], ], ], diff --git a/niucloud/app/dict/notice/notice.php b/niucloud/app/dict/notice/notice.php index 35acb421e..d269ea6d1 100644 --- a/niucloud/app/dict/notice/notice.php +++ b/niucloud/app/dict/notice/notice.php @@ -20,5 +20,18 @@ return [ 'variable' => [ 'code' => '验证码' ], - ] + ], + + //提示用户收款 +// 'member_transfer' => [ +// 'key' => 'member_transfer', +// 'receiver_type' => 1, +// 'name' => '提示用户收款', +// 'title' => '后台通过提现申请后,提示用户收款', +// 'async' => false, +// 'variable' => [ +// 'transfer_no' => '转账单号', +// +// ], +// ] ]; diff --git a/niucloud/app/dict/notice/sms.php b/niucloud/app/dict/notice/sms.php index 53c651307..80d137450 100644 --- a/niucloud/app/dict/notice/sms.php +++ b/niucloud/app/dict/notice/sms.php @@ -9,6 +9,10 @@ return [ ], 'recharge_success' => [ 'content' => '您充值金额¥{price}, 充值后金额¥{balance}', - ] + ], + +// 'member_transfer' => [ +// 'content' => '你的编号为{transfer_no}的提现申请已通过,您现在可以在提现中点击提现收款了', +// ] ]; \ No newline at end of file diff --git a/niucloud/app/dict/pay/TransferDict.php b/niucloud/app/dict/pay/TransferDict.php index 8126a5b73..0e98fa54d 100644 --- a/niucloud/app/dict/pay/TransferDict.php +++ b/niucloud/app/dict/pay/TransferDict.php @@ -29,7 +29,13 @@ class TransferDict public const SUCCESS = 'success';//转账成功 public const DEALING = 'dealing';//处理中 + public const WAIT = 'wait';//待转账 + + public const WAIT_USER = 'wait_user';//等待用户确认 + public const WAIT_USER_ING = 'wait_user_ing';//用户确认.转账中 + + public const FAIL_ING = 'fail_ing';//转账撤销中 public const FAIL = 'fail';//失败 @@ -57,6 +63,11 @@ class TransferDict 'key' => self::WECHAT, 'is_online' => true ],//微信 + self::WECHAT_CODE => [ + 'name' => get_lang('dict_transfer.type_wechat_code'), + 'key' => self::WECHAT_CODE, + 'is_online' => false + ],//微信收款码(线下转账) self::ALIPAY => [ 'name' => get_lang('dict_transfer.type_ali'), 'key' => self::ALIPAY, @@ -67,11 +78,6 @@ class TransferDict 'key' => self::BANK, 'is_online' => false ],//银行卡 - self::WECHAT_CODE => [ - 'name' => get_lang('dict_transfer.type_wechat_code'), - 'key' => self::WECHAT_CODE, - 'is_online' => false - ],//微信收款码(线下转账) ]; if ($is_all) { $list[self::OFFLINE] = [ @@ -96,12 +102,121 @@ class TransferDict */ public static function getStatus() { + return [ self::WAIT => get_lang('dict_transfer.status_wait'), self::DEALING => get_lang('dict_transfer.status_dealing'), + self::WAIT_USER => get_lang('dict_transfer.status_wait_user'), + self::WAIT_USER_ING => get_lang('dict_transfer.wait_user_ing'), self::SUCCESS => get_lang('dict_transfer.status_success'), self::FAIL => get_lang('dict_transfer.status_fail'), + + + self::FAIL_ING => get_lang('dict_transfer.status_fail_ing'), ]; } + + public const XJYX = 'xjyx'; + + public const QYPF = 'qypf'; + public const YJBC = 'yjbc'; + public const CGHK = 'cghk'; + public const ESHS = 'eshs'; + public const GYBZ = 'gybz'; + public const XZBT = 'xzbt'; + public const BXLP = 'bxlp'; + + /** + * 获取微信转账场景 + * @return void + */ + public static function getWechatTransferScene(){ + return [ + self::YJBC => [ + 'name' => '佣金报酬', + 'user_recv_perception' => [ + '劳务报酬', + '报销款', + '企业补贴', + '开工利是' + ], + 'transfer_scene_report_infos' => [ + '岗位类型', + '报酬说明' + ] + ], + self::XJYX => [ + 'name' => '现金营销', + 'user_recv_perception' => [ + '活动奖励', + '现金奖励', + ], + 'transfer_scene_report_infos' => [ + '活动名称', + '奖励说明' + ] + ], + self::QYPF => [ + 'name' => '企业赔付', + 'user_recv_perception' => [ + '退款', + '商家赔付', + ], + 'transfer_scene_report_infos' => [ + '赔付原因', + ] + ], + + self::CGHK => [ + 'name' => '采购货款', + 'user_recv_perception' => [ + '货款', + ], + 'transfer_scene_report_infos' => [ + '采购商品名称', + ] + ], + self::ESHS => [ + 'name' => '二手回收', + 'user_recv_perception' => [ + '二手回收货款', + ], + 'transfer_scene_report_infos' => [ + '回收商品名称', + ] + ], + self::GYBZ => [ + 'name' => '公益补助', + 'user_recv_perception' => [ + '公益补助金', + ], + 'transfer_scene_report_infos' => [ + '公益活动名称', + '公益活动备案编号' + ] + ], + self::XZBT => [ + 'name' => '行政补贴', + 'user_recv_perception' => [ + '行政补贴', + '行政奖励' + ], + 'transfer_scene_report_infos' => [ + '补贴类型', + ] + ], + self::BXLP => [ + 'name' => '保险理赔', + 'user_recv_perception' => [ + '保险理赔款', + ], + 'transfer_scene_report_infos' => [ + '保险产品备案编号', + '保险名称', + '保险操作单号' + ] + ], + ]; + } } \ No newline at end of file diff --git a/niucloud/app/dict/sys/CloudDict.php b/niucloud/app/dict/sys/CloudDict.php index 6d55988d9..f531a14ed 100644 --- a/niucloud/app/dict/sys/CloudDict.php +++ b/niucloud/app/dict/sys/CloudDict.php @@ -22,6 +22,8 @@ class CloudDict const APPLET_AUDITING = 2; + const APPLET_PUBLISHED = 3; + const APPLET_UPLOAD_FAIL = -1; const APPLET_AUDIT_FAIL = -2; @@ -33,6 +35,7 @@ class CloudDict self::APPLET_UPLOAD_FAIL => get_lang('dict_cloud_applet.upload_fail'), self::APPLET_AUDITING => get_lang('dict_cloud_applet.auditing'), self::APPLET_AUDIT_FAIL => get_lang('dict_cloud_applet.audit_fail'), + self::APPLET_PUBLISHED => get_lang('dict_cloud_applet.published'), ]; return $status_list[$status] ?? ''; } diff --git a/niucloud/app/dict/sys/ConfigKeyDict.php b/niucloud/app/dict/sys/ConfigKeyDict.php index e4a75174e..1558582f1 100644 --- a/niucloud/app/dict/sys/ConfigKeyDict.php +++ b/niucloud/app/dict/sys/ConfigKeyDict.php @@ -35,4 +35,6 @@ class ConfigKeyDict public const WEAPP_AUTHORIZATION_INFO = 'weapp_authorization_info'; public const WECHAT_AUTHORIZATION_INFO = 'wechat_authorization_info'; + + public const WECHAT_TRANSFER_SCENE_CONFIG = 'WECHAT_TRANSFER_SCENE_CONFIG';//微信转账场景配置 } diff --git a/niucloud/app/event.php b/niucloud/app/event.php index f43eb8e90..1520cda33 100644 --- a/niucloud/app/event.php +++ b/niucloud/app/event.php @@ -97,7 +97,7 @@ $system_event = [ //表单填表人统计导出 'app\listener\diy_form_export\DiyFormRecordsMemberExportTypeListener', //表单字段统计导出 -// 'app\listener\diy_form_export\DiyFormRecordsFieldsExportTypeListener', + 'app\listener\diy_form_export\DiyFormRecordsFieldsExportTypeListener', ], //导出数据源 'ExportData' => [ @@ -108,7 +108,7 @@ $system_event = [ //表单填表人统计导出 'app\listener\diy_form_export\DiyFormRecordsMemberExportDataListener', //表单字段统计导出 -// 'app\listener\diy_form_export\DiyFormRecordsFieldsExportDataListener', + 'app\listener\diy_form_export\DiyFormRecordsFieldsExportDataListener', ], //统计执行 'StatExecute' => [], @@ -123,7 +123,13 @@ $system_event = [ 'WeappAuthChangeAfter' => [ 'app\listener\system\WeappAuthChangeAfter' ], 'ShowApp' => [ 'app\listener\system\ShowAppListener' - ] + ], + //获取微信转账场景配置 + 'GetWechatTransferTradeScene' => [ + 'app\listener\transfer\TransferCashOutListener' + ], + //主题色 + 'ThemeColor' => [ 'app\listener\diy\ThemeColorListener' ], ], 'subscribe' => [ ], diff --git a/niucloud/app/install/source/database.sql b/niucloud/app/install/source/database.sql index 83eb6c3a1..7d785c7f2 100644 --- a/niucloud/app/install/source/database.sql +++ b/niucloud/app/install/source/database.sql @@ -227,13 +227,14 @@ CREATE TABLE `diy_theme` ( `title` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '标题', `type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '插件类型app,addon', `addon` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '所属应用,app:系统,shop:商城、o2o:上门服务', - `color_mark` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '颜色标识', - `color_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '颜色名称', `mode` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '模式,default:默认【跟随系统】,diy:自定义配色', - `value` TEXT DEFAULT NULL COMMENT '配色', - `diy_value` TEXT DEFAULT NULL COMMENT '自定义配色', - `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间', - `update_time` INT(11) NOT NULL DEFAULT 0 COMMENT '更新时间', + `theme_type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '配色类型,default:默认,diy:自定义', + `default_theme` text DEFAULT NULL COMMENT '当前色调的默认值', + `theme` text DEFAULT NULL COMMENT '当前色调', + `new_theme` text DEFAULT NULL COMMENT '新增颜色集合', + `is_selected` tinyint NOT NULL DEFAULT 0 COMMENT '已选色调,0:否,1.是', + `create_time` int NOT NULL DEFAULT 0 COMMENT '创建时间', + `update_time` int NOT NULL DEFAULT 0 COMMENT '更新时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='自定义主题配色表'; @@ -597,10 +598,24 @@ CREATE TABLE `pay_transfer` ( `batch_id` varchar(500) NOT NULL DEFAULT '' COMMENT '转账批次id', `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 '扩展信息', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '转账表' ROW_FORMAT = Dynamic; +DROP TABLE IF EXISTS `pay_transfer_scene`; +CREATE TABLE `pay_transfer_scene` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', + `site_id` INT(11) NOT NULL DEFAULT 0 COMMENT '站点id', + `type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '业务类型', + `scene` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '场景', + `infos` VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '转账报备背景', + `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间', + `perception` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '转账收款感知', + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '支付转账场景表' ROW_FORMAT = Dynamic; + DROP TABLE IF EXISTS `site`; CREATE TABLE `site` ( `site_id` int(11) NOT NULL AUTO_INCREMENT, diff --git a/niucloud/app/lang/zh-cn/api.php b/niucloud/app/lang/zh-cn/api.php index 0f4d760f1..11512d0c7 100644 --- a/niucloud/app/lang/zh-cn/api.php +++ b/niucloud/app/lang/zh-cn/api.php @@ -58,6 +58,7 @@ return [ 'ADDON_IS_INSTALLED_NOT_ALLOW_DEL' => '已安装的插件不允许删除', 'ADDON_ZIP_ERROR' => '插件压缩失败', 'PHP_SCRIPT_RUNNING_OUT_OF_MEMORY' => 'PHP脚本运行内存不足, 具体操作方法点击查看相关手册', + 'BEFORE_UPGRADING_NEED_UPGRADE_FRAMEWORK' => '升级插件前需要先升级框架', //登录注册重置账号.... 'LOGIN_SUCCESS' => '登录成功', @@ -177,15 +178,23 @@ return [ 'MEMBER_APPLY_CASHOUT' => '会员申请提现,扣除零钱', 'CASHOUT_MONEY_TOO_LITTLE' => '会员提现金额不能小于最低提现金额', 'CASHOUT_STATUS_NOT_IN_WAIT_TRANSFER' => '当前提现申请未处于待转账状态', + 'CASHOUT_STATUS_NOT_IN_CANCEL' => '只有进行中的提现才可以取消', 'CASHOUT_STATUS_NOT_IN_WAIT_AUDIT' => '当前提现申请未处于待审核状态', 'MEMBER_CASHOUT_TRANSFER' => '会员提现转账', 'CASH_OUT_ACCOUNT_NOT_EXIST' => '提现账户不存在', + 'CASH_OUT_WECHAT_ACCOUNT_NOT_ALLOW_ADMIN' => '在转账到微信零钱的提现场景下,提现操作应该由用户在客户端发起', 'CASH_OUT_ACCOUNT_NOT_FOUND_VALUE' => '转账到微信零钱缺少参数', //DIY 'PAGE_NOT_EXIST' => '页面不存在', - 'APP_COLOR_NOT_EXIST' => '系统配色不存在', + 'DIY_THEME_COLOR_NOT_EXIST' => '主题配色不存在', + 'DIY_THEME_DEFAULT_COLOR_CAN_NOT_DELETE' => '系统默认配色不能删除', + 'DIY_THEME_SELECTED_CAN_NOT_DELETE' => '主题配色已选中不能删除', + + //海报 + 'POSTER_NOT_EXIST' => '海报不存在', + 'POSTER_IN_USE_NOT_ALLOW_MODIFY' => '海报使用中禁止修改状态', //万能表单 'DIY_FORM_NOT_EXIST' => '表单不存在', @@ -230,6 +239,7 @@ return [ 'TREAT_PAYMENT_IS_OPEN' => '只有待支付时可以关闭', 'TRANFER_STATUS_NOT_IN_WAIT_TANSFER' => '当前转账未处于待转账状态', 'TRANSFER_ORDER_INVALID' => '无效的转账单据', + 'TRANSFER_IS_FAILING' => '单据正在撤销中,请等待片刻或稍后再试', 'TRANFER_CONFIG_ERROR' => '参数有误或未开通转账业务', 'IS_PAY_REMOVE_NOT_RESETTING' => '已支付和已取消的单据不可以重置', 'DOCUMENT_IS_PAY_REMOVE' => '当前单据已支付或已取消', @@ -243,6 +253,8 @@ return [ 'ONLY_OFFLINEPAY_CAN_AUDIT' => '只有线下支付的单据才可以审核', 'TRADE_NOT_EXIST' => '支付单据不存在', 'PAY_NOT_FOUND_TRADE' => '找不到可支付的交易', + + 'MERCHANT_TRANSFER_SCENARIOS_THAT_DO_NOT_EXIST' => '不存在的商户转账场景', //退款相关 'REFUND_NOT_EXIST' => '退款单据不存在', //订单相关 8*** @@ -265,6 +277,7 @@ return [ // 缓存相关 'CLEAR_MYSQL_CACHE_SUCCESS' => '数据表缓存清除成功', + 'CACHE_CLEAR_SUCCESS' => '缓存清除成功', //任务队列相关 'JOB_NOT_EXISTS' => '任务类不存在', @@ -323,6 +336,7 @@ return [ 'WEAPP_EXIST' => '该小程序已经授权给其他站点', 'WECHAT_EXIST' => '该公众号已经授权给其他站点', 'PLEASE_ADD_FIRST_SITE_GROUP' => '请先添加站点套餐', + 'NOT_YET_PRESENT_TEMPLATE_LIBRARY' => '平台尚未上传小程序到模板库', 'PRINTER_NOT_EXIST' => '打印机不存在' ]; diff --git a/niucloud/app/lang/zh-cn/dict.php b/niucloud/app/lang/zh-cn/dict.php index a5d229c98..e70c08cf0 100644 --- a/niucloud/app/lang/zh-cn/dict.php +++ b/niucloud/app/lang/zh-cn/dict.php @@ -233,7 +233,7 @@ return [ 'page_diy' => '微页面', 'component_type_basic' => '基础组件', - 'system_title' => '系统', + 'system_title' => '系统页面', 'system_link' => '启动页', 'system_link_index' => '首页', @@ -252,7 +252,9 @@ return [ 'diy_page' => '自定义页面', 'diy_link' => '自定义链接', 'diy_jump_other_applet' => '小程序跳转', - 'diy_make_phone_call' => '拨打电话' + 'diy_make_phone_call' => '拨打电话', + + 'diy_form_select' => '万能表单' ], // 自定义海报 'dict_diy_poster' => [ @@ -380,7 +382,8 @@ return [ 'upload_fail' => '上传失败', 'auditing' => '审核中', 'audit_success' => '审核通过', - 'audit_fail' => '审核失败' + 'audit_fail' => '审核失败', + 'published' => '已发布' ], 'dict_wechat_media' => [ 'type_image' => '图片', diff --git a/niucloud/app/lang/zh-cn/validate.php b/niucloud/app/lang/zh-cn/validate.php index b8301d2f3..6333feb04 100644 --- a/niucloud/app/lang/zh-cn/validate.php +++ b/niucloud/app/lang/zh-cn/validate.php @@ -165,6 +165,8 @@ return [ // 自定义 'validate_diy' => [ 'type_not_exist' => '不存在的页面模板', + 'theme_title_unique' => '色调名称必须是唯一的', + 'page_title_unique' => '表单名称必须是唯一的', ], // 会员提现账号 'validate_member_cash_out_account' => [ diff --git a/niucloud/app/listener/diy/ThemeColorListener.php b/niucloud/app/listener/diy/ThemeColorListener.php new file mode 100644 index 000000000..9f691c163 --- /dev/null +++ b/niucloud/app/listener/diy/ThemeColorListener.php @@ -0,0 +1,90 @@ + [ + [ + 'title' => '商务蓝', + 'name' => 'blue', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--primary-color' => "#007aff",//主色调 + '--primary-color-light' => "#ecf5ff",//主色调浅色(淡) + '--primary-color-light2' => "#FFF4ED",//主色调深色(深) + '--primary-help-color2' => "#007aff",//辅色调 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ] + ] + ], + // 主题颜色字段,前端展示用,字段中的value值颜色为添加自定义颜色的默认值,默认黑色风格 + 'theme_field' => [ + [ + 'title' => '页面背景色', + 'label' => "--page-bg-color", + 'value' => "#F6F6F6", + 'tip' => "页面背景色在uniapp中使用:var(--page-bg-color)", + ], + [ + 'title' => '主色调', + 'label' => "--primary-color", + 'value' => "rgba(51, 51, 51, 1)", + 'tip' => "主色调在uniapp中使用:var(--primary-color)", + ], + [ + 'title' => '主色调浅色(淡)', + 'label' => "--primary-color-light", + 'value' => "rgba(51, 51, 51, 0.1)", + 'tip' => "主色调浅色(淡)在uniapp中使用:var(--primary-color-light)", + ], + [ + 'title' => '主色调深色(深)', + 'label' => "--primary-color-light2", + 'value' => "rgba(51, 51, 51, 0.8)", + 'tip' => "主色调深色(深)在uniapp中使用:var(--primary-color-light2)", + ], + [ + 'title' => '辅色调', + 'label' => "--primary-help-color2", + 'value' => "rgba(51, 51, 51, 1)", + 'tip' => "辅色调在uniapp中使用:var(--primary-help-color2)", + ], + [ + 'title' => '灰色调', + 'label' => "--primary-color-dark", + 'value' => "#999999", + 'tip' => "灰色调在uniapp中使用:var(--primary-color-dark)", + ], + [ + 'title' => '禁用色', + 'label' => "--primary-color-disabled", + 'value' => "#CCCCCC", + 'tip' => "禁用色在uniapp中使用:var(--primary-color-disabled)", + ], + ] + ]; + } + } +} \ No newline at end of file diff --git a/niucloud/app/listener/diy_form_export/DiyFormRecordsFieldsExportDataListener.php b/niucloud/app/listener/diy_form_export/DiyFormRecordsFieldsExportDataListener.php new file mode 100644 index 000000000..05a2cd012 --- /dev/null +++ b/niucloud/app/listener/diy_form_export/DiyFormRecordsFieldsExportDataListener.php @@ -0,0 +1,121 @@ +getFieldsList($where, 'field_id, field_key, field_type, field_name'); + $simple_field_list = array_filter($field_list, function($v) { return !in_array($v[ 'field_type' ], [ 'FormRadio', 'FormCheckbox', 'FormDateScope', 'FormTimeScope', 'FormImage' ]); }); + $json_field_list = array_filter($field_list, function($v) { return in_array($v[ 'field_type' ], [ 'FormRadio', 'FormCheckbox', 'FormDateScope', 'FormTimeScope' ]); }); + + $records_field_model = new DiyFormRecordsFields(); + foreach ($simple_field_list as $k => &$v) { + $value_list = $records_field_model->field('form_id, field_key, field_type, field_name, field_value, count(*) as write_count')->where([ + [ 'site_id', '=', $site_id ], + [ 'field_key', '=', $v[ 'field_key' ] ], + [ 'field_type', '=', $v[ 'field_type' ] ] + ])->withSearch([ 'form_id' ], $where)->group('field_value')->append([ 'render_value' ])->select()->toArray(); + $total_count = $records_field_model->where([ + [ 'site_id', '=', $site_id ], + [ 'field_key', '=', $v[ 'field_key' ] ], + [ 'field_type', '=', $v[ 'field_type' ] ] + ])->withSearch([ 'form_id' ], $where)->count(); + if ($total_count > 0) { + $total_percent = 100; + foreach ($value_list as $k1 => &$v1) { + if ($k1 == count($value_list) - 1) { + $item_percent = $total_percent; + } else { + $item_percent = round($v1[ 'write_count' ] / $total_count * 100, 2); + } + $v1[ 'write_percent' ] = floatval($item_percent); + $total_percent = bcsub($total_percent, $item_percent, 2); + } + } + $data = array_merge($data, $value_list); + } + foreach ($json_field_list as $k => &$v) { + $field_list = $records_field_model->field('form_id, field_key, field_type, field_name, field_value')->where([ + [ 'site_id', '=', $site_id ], + [ 'field_key', '=', $v[ 'field_key' ] ], + [ 'field_type', '=', $v[ 'field_type' ] ] + ])->withSearch([ 'form_id' ], $where)->append([ 'render_value' ])->select()->toArray(); + + $total_count = 0; + $value_list = []; + foreach ($field_list as $k1 => &$v1) { + if ($v1[ 'field_type' ] != 'FormCheckbox') { + $key = $v1[ 'field_key' ] . '_' . $v1[ 'render_value' ]; + if (isset($value_list[ $key ])) { + $value_list[ $key ][ 'write_count' ] = $value_list[ $key ][ 'write_count' ] + 1; + $total_count++; + } else { + // 如果不存在,则初始化为1 + $value_list[ $key ] = $v1; + $value_list[ $key ][ 'write_count' ] = 1; + $total_count++; + } + } else { + $value_arr = explode(',', $v1[ 'render_value' ]); + foreach ($value_arr as $k2 => $v2) { + $key = $v1[ 'field_key' ] . '_' . $v2; + if (isset($value_list[ $key ])) { + $value_list[ $key ][ 'write_count' ] = $value_list[ $key ][ 'write_count' ] + 1; + $total_count++; + } else { + $value_list[ $key ] = $v1; + $value_list[ $key ][ 'render_value' ] = $v2; + $value_list[ $key ][ 'write_count' ] = 1; + $total_count++; + } + } + } + } + if ($total_count > 0) { + $value_list = array_values($value_list); + $total_percent = 100; + foreach ($value_list as $k1 => &$v1) { + if ($k1 == count($value_list) - 1) { + $item_percent = $total_percent; + } else { + $item_percent = round($v1[ 'write_count' ] / $total_count * 100, 2); + } + $v1[ 'write_percent' ] = floatval($item_percent); + $total_percent = bcsub($total_percent, $item_percent, 2); + } + } + $data = array_merge($data, $value_list); + } + foreach ($data as $k => &$v) { + $v[ 'render_value' ] = $v[ 'render_value' ] . "\t"; + } + $data = array_values($data); + } + return $data; + } +} \ No newline at end of file diff --git a/niucloud/app/listener/diy_form_export/DiyFormRecordsFieldsExportTypeListener.php b/niucloud/app/listener/diy_form_export/DiyFormRecordsFieldsExportTypeListener.php new file mode 100644 index 000000000..c19f47008 --- /dev/null +++ b/niucloud/app/listener/diy_form_export/DiyFormRecordsFieldsExportTypeListener.php @@ -0,0 +1,36 @@ + [ + 'name' => '表单字段统计列表', + 'column' => [ + 'field_name' => [ 'name' => '字段', 'merge_type' => 'column' ], + 'render_value' => [ 'name' => '选项值' ], + 'write_count' => [ 'name' => '小计' ], + 'write_percent' => [ 'name' => '比例' ], + ] + ] + ]; + } +} \ No newline at end of file diff --git a/niucloud/app/listener/member_export/MemberExportDataListener.php b/niucloud/app/listener/member_export/MemberExportDataListener.php index b8c8b78e0..58236e6b6 100644 --- a/niucloud/app/listener/member_export/MemberExportDataListener.php +++ b/niucloud/app/listener/member_export/MemberExportDataListener.php @@ -26,7 +26,7 @@ class MemberExportDataListener $data = []; if ($param['type'] == 'member') { $model = new Member(); - $field = 'member_id, member_no, mobile, nickname, birthday, member_level, point, balance, money, growth, commission, register_channel, status, create_time, last_visit_time'; + $field = 'member_id, member_no, mobile, nickname, sex, birthday, member_level, point, balance, money, growth, commission, register_channel, status, create_time, last_visit_time'; //查询导出数据 $search_model = $model->where([['site_id', '=', $param['site_id']]])->withSearch(['keyword','register_type', 'create_time', 'is_del', 'member_label', 'register_channel'], $param['where']) ->with(['memberLevelNameBind'])->field($field)->append(['register_channel_name', 'sex_name', 'status_name']); @@ -36,6 +36,7 @@ class MemberExportDataListener $data = $search_model->select()->toArray(); } foreach ($data as $key => $value) { + $data[$key]['member_no'] = $value['member_no']."\t"; $data[$key]['mobile'] = $value['mobile']."\t"; $data[$key]['create_time'] = !empty($value['create_time']) ? $value['create_time'] : ''; $data[$key]['last_visit_time'] = !empty($value['last_visit_time']) ? $value['last_visit_time'] : ''; diff --git a/niucloud/app/listener/member_export/MemberExportTypeListener.php b/niucloud/app/listener/member_export/MemberExportTypeListener.php index edf349c75..99579728b 100644 --- a/niucloud/app/listener/member_export/MemberExportTypeListener.php +++ b/niucloud/app/listener/member_export/MemberExportTypeListener.php @@ -25,6 +25,7 @@ class MemberExportTypeListener 'member' => [ 'name' => '会员列表', 'column' => [ + 'member_no' => [ 'name' => '会员编号'], 'nickname' => [ 'name' => '会员昵称'], 'mobile' => [ 'name' => '手机号'], 'member_level_name' => [ 'name' => '会员等级'], diff --git a/niucloud/app/listener/system/AddSiteAfterListener.php b/niucloud/app/listener/system/AddSiteAfterListener.php index cf41bb909..0d8421914 100644 --- a/niucloud/app/listener/system/AddSiteAfterListener.php +++ b/niucloud/app/listener/system/AddSiteAfterListener.php @@ -10,9 +10,9 @@ // +---------------------------------------------------------------------- namespace app\listener\system; -use app\model\sys\Poster; use app\model\sys\SysAttachment; use app\model\sys\SysAttachmentCategory; +use app\service\core\diy\CoreDiyService; use app\service\core\poster\CorePosterService; /** @@ -538,6 +538,8 @@ class AddSiteAfterListener 'is_default' => 1 ]); + // 创建默认主题风格颜色 + ( new CoreDiyService() )->initDefaultDiyTheme($site_id); return true; } } diff --git a/niucloud/app/listener/transfer/TransferCashOutListener.php b/niucloud/app/listener/transfer/TransferCashOutListener.php new file mode 100644 index 000000000..ab7f139a0 --- /dev/null +++ b/niucloud/app/listener/transfer/TransferCashOutListener.php @@ -0,0 +1,38 @@ +addPayLog($pay_info); + return [ + 'member_cash_out' => [ + 'name' => '佣金提现', + 'scene' => TransferDict::YJBC, + 'perception' => '劳务报酬', + 'infos' => [ + '岗位类型' => '业务顾问', + '报酬说明' => '佣金提现' + ] + ] + ]; + } +} \ No newline at end of file diff --git a/niucloud/app/model/diy/DiyTheme.php b/niucloud/app/model/diy/DiyTheme.php index c5672c574..73545998d 100644 --- a/niucloud/app/model/diy/DiyTheme.php +++ b/niucloud/app/model/diy/DiyTheme.php @@ -36,7 +36,7 @@ class DiyTheme extends BaseModel protected $name = 'diy_theme'; // 设置json类型字段 - protected $json = [ 'value', 'diy_value' ]; + protected $json = [ 'default_theme', 'theme', 'new_theme' ]; // 设置JSON数据返回数组 protected $jsonAssoc = true; diff --git a/niucloud/app/model/member/MemberCashOut.php b/niucloud/app/model/member/MemberCashOut.php index 8ce9aa552..d88a50491 100644 --- a/niucloud/app/model/member/MemberCashOut.php +++ b/niucloud/app/model/member/MemberCashOut.php @@ -73,7 +73,7 @@ class MemberCashOut extends BaseModel public function transfer() { return $this->hasOne(Transfer::class, 'transfer_no', 'transfer_no')->joinType('left') - ->withField('transfer_no, transfer_type, transfer_realname, transfer_mobile, transfer_bank, transfer_account, transfer_voucher, transfer_remark, transfer_fail_reason, transfer_status')->append(['transfer_status_name', 'transfer_type_name']); + ->withField('transfer_no, transfer_type, transfer_realname, transfer_mobile, transfer_bank, transfer_account, transfer_voucher, transfer_remark, transfer_fail_reason, transfer_status, package_info, extra')->append(['transfer_status_name', 'transfer_type_name']); } /** diff --git a/niucloud/app/model/pay/Transfer.php b/niucloud/app/model/pay/Transfer.php index 621a4cb7b..ed3b8825f 100644 --- a/niucloud/app/model/pay/Transfer.php +++ b/niucloud/app/model/pay/Transfer.php @@ -42,7 +42,7 @@ class Transfer extends BaseModel ]; // 设置json类型字段 - protected $json = [ 'transfer_payee' ]; + protected $json = [ 'transfer_payee', 'extra' ]; // 设置JSON数据返回数组 protected $jsonAssoc = true; diff --git a/niucloud/app/model/pay/TransferScene.php b/niucloud/app/model/pay/TransferScene.php new file mode 100644 index 000000000..9f27bb3f1 --- /dev/null +++ b/niucloud/app/model/pay/TransferScene.php @@ -0,0 +1,49 @@ + $v) { if (!empty($v[ 'child_list' ])) { foreach ($v[ 'child_list' ] as $ck => $cv) { - if (!empty($cv[ 'url' ])) { + if (!empty($cv[ 'child_list' ])) { + foreach ($cv[ 'child_list' ] as $ck2 => $cv2) { + $is_add = true; + + if (isset($where[ 'title' ]) && $where[ 'title' ] != '' && !str_contains($cv2[ 'title' ], $where[ 'title' ])) { + $is_add = false; + } + + if (!empty($where[ 'url' ]) && $where[ 'url' ] != $cv2[ 'url' ]) { + $is_add = false; + } + + if (!empty($v[ 'addon_info' ]) && !empty($where[ 'addon_name' ]) && $where[ 'addon_name' ] != $v[ 'addon_info' ][ 'key' ]) { + $is_add = false; + } + + $item = [ + 'addon_info' => $v[ 'addon_info' ] ?? '', + 'title' => $cv2[ 'title' ], + 'name' => $cv2[ 'name' ], + 'parent' => $k, + 'page' => $cv2[ 'url' ], + 'is_share' => $cv2[ 'is_share' ], + 'action' => $cv2[ 'action' ] ?? '', + 'sort' => ++$sort + ]; + + if ($is_add) { + $diy_route_list[] = $item; + } + } + + } else if (!empty($cv[ 'url' ])) { $is_add = true; - if (isset($where[ 'title' ]) && $where[ 'title' ] !='' && !str_contains($cv[ 'title' ], $where[ 'title' ])) { + if (isset($where[ 'title' ]) && $where[ 'title' ] != '' && !str_contains($cv[ 'title' ], $where[ 'title' ])) { $is_add = false; } @@ -181,7 +213,6 @@ class DiyRouteService extends BaseAdminService $link = LinkDict::getLink([ 'query' => 'addon' ]); - return $link; } diff --git a/niucloud/app/service/admin/diy/DiyService.php b/niucloud/app/service/admin/diy/DiyService.php index d0e911480..5b057c93e 100644 --- a/niucloud/app/service/admin/diy/DiyService.php +++ b/niucloud/app/service/admin/diy/DiyService.php @@ -821,33 +821,25 @@ 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']])->column('id,color_mark,color_name,diy_value,value,title,mode','addon'); - $defaultColor = ( new CoreDiyService() )->getDefaultColor(); + $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' => '系统', - 'mode' => 'diy', - 'title' => $theme_data['app']['title'] ?? '系统主色调', - 'color_mark' => $theme_data['app']['color_mark'] ?? $defaultColor['name'], - 'color_name' => $theme_data['app']['color_name'] ?? $defaultColor['title'], - 'value' => $theme_data['app']['value'] ?? $defaultColor['theme'], - 'diy_value' => $theme_data['app']['diy_value'] ?? '', + '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){ - $default_theme_data = array_values(array_filter(event('ThemeColor', [ 'key' => $value['key']])))[0] ?? []; + $addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value['key']])))[0] ?? []; $data[$value['key']]['id'] = $theme_data[$value['key']]['id'] ?? ''; $data[$value['key']]['icon'] = $value['icon'] ?? ''; - $data[$value['key']]['mode'] = $theme_data[$value['key']]['mode'] ?? 'diy'; $data[$value['key']]['addon_title'] = $value['title'] ?? ''; - $data[$value['key']]['title'] = $theme_data[$value['key']]['title'] ?? $value['title'].'主色调'; - $data[$value['key']]['color_mark'] = $theme_data[$value['key']]['color_mark'] ?? ($default_theme_data ? $default_theme_data[ 'name' ] : $defaultColor['name']); - $data[$value['key']]['color_name'] = $theme_data[$value['key']]['color_name'] ?? ($default_theme_data ? $default_theme_data[ 'title' ] : $defaultColor['title']); - $data[$value['key']]['value'] = $theme_data[$value['key']]['value'] ?? ($default_theme_data ? $default_theme_data[ 'theme' ] : $defaultColor['theme']); - $data[$value['key']]['diy_value'] = $theme_data[$value['key']]['diy_value'] ?? ''; + $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' ] : ''); } - if (count($site_addon[ 'apps' ]) > 1) { + if (count($site_addon[ 'apps' ]) > 1) {// 应用数量大于1时,展示系统主题色设置,只有一个应用时,不展示系统主题色设置 $data = array_merge($app_theme,$data); } @@ -861,9 +853,11 @@ class DiyService extends BaseAdminService */ public function setDiyTheme($data) { - $diy_theme_model = new (new DiyTheme()); - - $addon_data = (new addon())->where([['support_app', '=', $data['key']]])->select()->toArray(); + $diy_theme_model = new DiyTheme(); + $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_save_data = []; if (!empty($addon_data)){ foreach ($addon_data as $value){ @@ -871,11 +865,10 @@ class DiyService extends BaseAdminService 'site_id' => $this->site_id, 'type' => 'addon', 'addon' => $value['key'], - 'color_mark' => $data['color_mark'], - 'color_name' => $data['color_name'], - 'mode' => $data['mode'], - 'value' => $data['value'], - 'diy_value' => $data['diy_value'], + 'title' => $data['title'], + 'theme' => $data['theme'], + 'new_theme' => $data['new_theme'], + 'is_selected' => 1, 'update_time' => time(), ]; } @@ -884,25 +877,16 @@ 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(); - unset($data['key']); $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']], ['site_id', '=', $this->site_id]])->update($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); } } - }else{ - $data['site_id'] = $this->site_id; - $data['type'] = 'app'; - $data['addon'] = $data['key']; - $data['crete_time'] = time(); - unset($data['id'],$data['key']); - array_unshift($addon_save_data, $data); - foreach ($addon_save_data as $value){ - unset($value['update_time']); - $diy_theme_model->create($value); - } } Db::commit(); return true; @@ -916,9 +900,137 @@ class DiyService extends BaseAdminService * 获取默认主题配色 * @return array */ - public function getDefaultThemeColor() + public function getDefaultThemeColor($data) { - return ( new CoreDiyService() )->getDefaultThemeColor(); + $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'];//返回各个应用的主题颜色字段 + } + } + return $theme_list; + } + + /** + * 添加自定义主题配色 + * @param array $data + * @return bool + */ + public function addDiyTheme($data) + { + // 主应用添加自定义主题色时,主应用下的插件也同步添加自定义主题色 + $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){ + $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'], + 'theme_type' => 'diy', + 'create_time' => time(), + ]; + } + } + + Db::startTrans(); + try { + $data[ 'site_id' ] = $this->site_id; + $data[ 'type' ] = 'app'; + $data[ 'theme_type' ] = 'diy'; + $data[ 'create_time' ] = time(); + $diy_theme_model = new DiyTheme(); + $diy_theme_model->create($data); + if (!empty($addon_save_data)){ + $diy_theme_model->insertAll($addon_save_data); + } + Db::commit(); + return true; + } catch (Exception $e) { + Db::rollback(); + throw new AdminException($e->getMessage()); + } + } + + /** + * 编辑自定义主题配色 + * @param int $id + * @param array $data + * @return bool + */ + public function editDiyTheme(int $id, array $data) + { + $diy_theme_model = new DiyTheme(); + $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_save_data = []; + 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'], + 'update_time' => time(), + ]; + } + } + + Db::startTrans(); + try { + $data[ 'update_time' ] = time(); + $diy_theme_model->where([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ])->update($data); + if (!empty($addon_save_data)){ + $diy_theme_model->saveAll($addon_save_data); + } + Db::commit(); + return true; + } catch (Exception $e) { + Db::rollback(); + throw new AdminException($e->getMessage()); + } + } + + /** + * 删除自定义主题配色 + * @param int $id + * @return bool + */ + public function delDiyTheme(int $id) + { + $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(); + return $res; + } + + /** + * 检测自定义主题配色名称唯一性 + * @param array $data + * @return bool + */ + public function checkDiyThemeTitleUnique($data) + { + $where = [ + [ 'title', "=", $data[ 'title' ] ], + [ 'addon', "=", $data['addon'] ], + [ 'site_id', "=", $this->site_id ] + ]; + if (!empty($data[ 'id' ])) { + $where[] = [ 'id', "<>", $data[ 'id' ] ]; + } + $diy_theme_model = new DiyTheme(); + return $diy_theme_model->where($where)->count() > 0; } } diff --git a/niucloud/app/service/admin/diy_form/DiyFormRecordsService.php b/niucloud/app/service/admin/diy_form/DiyFormRecordsService.php index 2baeb268f..7731bc43e 100644 --- a/niucloud/app/service/admin/diy_form/DiyFormRecordsService.php +++ b/niucloud/app/service/admin/diy_form/DiyFormRecordsService.php @@ -52,21 +52,27 @@ class DiyFormRecordsService extends BaseAdminService public function getFieldStatList(array $where = []) { $field_list = ( new DiyFormService() )->getFieldsList($where, 'field_id, field_key, field_type, field_name'); + // 一般格式存储的表单字段列表,如单行文本、多行文本、数字、手机号、邮箱、身份证号 $simple_field_list = array_filter($field_list, function($v) { return !in_array($v[ 'field_type' ], [ 'FormRadio', 'FormCheckbox', 'FormDateScope', 'FormTimeScope', 'FormImage' ]); }); + // json格式存储的表单字段列表,如单选框、多选框、日期、日期范围、时间、时间范围 $json_field_list = array_filter($field_list, function($v) { return in_array($v[ 'field_type' ], [ 'FormRadio', 'FormCheckbox', 'FormDateScope', 'FormTimeScope' ]); }); + // 一般格式数据类型统计 $records_field_model = new DiyFormRecordsFields(); foreach ($simple_field_list as $k => &$v) { + // 按填写字段内容分组查询某个组件各字段内容填写次数 $value_list = $records_field_model->field('form_id, field_key, field_type, field_value, count(*) as write_count')->where([ [ 'site_id', '=', $this->site_id ], [ 'field_key', '=', $v[ 'field_key' ] ], [ 'field_type', '=', $v[ 'field_type' ] ] ])->withSearch([ 'form_id' ], $where)->group('field_value')->append([ 'render_value' ])->select()->toArray(); + // 查询某个组件填写总次数 $total_count = $records_field_model->where([ [ 'site_id', '=', $this->site_id ], [ 'field_key', '=', $v[ 'field_key' ] ], [ 'field_type', '=', $v[ 'field_type' ] ] ])->withSearch([ 'form_id' ], $where)->count(); + // 循环计算各字段内容填写占比 if ($total_count > 0) { $total_percent = 100; foreach ($value_list as $k1 => &$v1) { @@ -81,7 +87,9 @@ class DiyFormRecordsService extends BaseAdminService } $v[ 'value_list' ] = $value_list; } + // json格式数据类型统计 foreach ($json_field_list as $k => &$v) { + // 查询某个组件填写记录 $field_list = $records_field_model->field('form_id, field_key, field_type, field_value')->where([ [ 'site_id', '=', $this->site_id ], [ 'field_key', '=', $v[ 'field_key' ] ], @@ -91,7 +99,7 @@ class DiyFormRecordsService extends BaseAdminService $total_count = 0; $value_list = []; foreach ($field_list as $k1 => &$v1) { - if ($v1[ 'field_type' ] != 'FormCheckbox') { + if ($v1[ 'field_type' ] != 'FormCheckbox') {//非多选项组件的内容填写次数统计、总次数统计 $key = $v1[ 'field_key' ] . '_' . $v1[ 'render_value' ]; if (isset($value_list[ $key ])) { $value_list[ $key ][ 'write_count' ] = $value_list[ $key ][ 'write_count' ] + 1; @@ -104,7 +112,7 @@ class DiyFormRecordsService extends BaseAdminService } } else { $value_arr = explode(',', $v1[ 'render_value' ]); - foreach ($value_arr as $k2 => $v2) { + foreach ($value_arr as $k2 => $v2) {//多选项组件的每个选项选择次数统计、总次数统计 $key = $v1[ 'field_key' ] . '_' . $v2; if (isset($value_list[ $key ])) { $value_list[ $key ][ 'write_count' ] = $value_list[ $key ][ 'write_count' ] + 1; @@ -118,6 +126,7 @@ class DiyFormRecordsService extends BaseAdminService } } } + // 循环计算各字段内容填写占比 if ($total_count > 0) { $value_list = array_values($value_list); $total_percent = 100; @@ -133,6 +142,7 @@ class DiyFormRecordsService extends BaseAdminService } $v[ 'value_list' ] = $value_list; } + // 合并返回一般格式数据类型统计和json格式数据类型统计 return array_merge($simple_field_list, $json_field_list); } diff --git a/niucloud/app/service/admin/diy_form/DiyFormService.php b/niucloud/app/service/admin/diy_form/DiyFormService.php index 052973402..40261de66 100644 --- a/niucloud/app/service/admin/diy_form/DiyFormService.php +++ b/niucloud/app/service/admin/diy_form/DiyFormService.php @@ -55,7 +55,6 @@ class DiyFormService extends BaseAdminService */ public function getPage(array $where = []) { - $where[] = [ 'site_id', '=', $this->site_id ]; $field = 'form_id, page_title, title, type, status, addon, share, write_num, remark, update_time'; $order = "form_id desc"; @@ -63,6 +62,37 @@ class DiyFormService extends BaseAdminService return $this->pageQuery($search_model); } + /** + * 获取万能表单分页列表(用于弹框选择) + * @param array $where + * @return array + */ + public function getSelectPage(array $where = []) + { + $verify_form_ids = []; + // 检测id集合是否存在,移除不存在的id,纠正数据准确性 + if (!empty($where[ 'verify_form_ids' ])) { + $verify_form_ids = $this->model->where([ + [ 'form_id', 'in', $where[ 'verify_form_ids' ] ] + ])->field('form_id')->select()->toArray(); + + if (!empty($verify_form_ids)) { + $verify_form_ids = array_column($verify_form_ids, 'form_id'); + } + } + + $field = 'form_id, page_title, title, type, status, addon, share, write_num, remark, update_time'; + $order = "form_id desc"; + + $search_model = $this->model->where([ + [ 'site_id', '=', $this->site_id ], + [ 'status', '=', 1 ], + ])->withSearch([ "title", "type", 'addon' ], $where)->field($field)->order($order)->append([ 'type_name', 'addon_name' ]); + $list = $this->pageQuery($search_model); + $list[ 'verify_form_ids' ] = $verify_form_ids; + return $list; + } + /** * 获取万能表单列表 * @param array $where @@ -285,9 +315,15 @@ class DiyFormService extends BaseAdminService if ($status_count > 0) throw new AdminException('ON_STATUS_PROHIBIT_DELETE'); + foreach ($form_ids as $form_id) { + $result = event('BeforeFormDelete', [ 'form_id' => $form_id, 'site_id' => $this->site_id ])[ 0 ] ?? []; + if (!empty($result) && !$result[ 'allow_operate' ]) { + $form_info = $this->model->field('page_title')->where([ [ 'form_id', '=', $form_id ], [ 'site_id', '=', $this->site_id ] ])->findOrEmpty()->toArray(); + throw new AdminException($form_info[ 'page_title' ] . '已被使用,禁止删除'); + } + } + $form_fields_model = new DiyFormFields(); - $form_records_model = new DiyFormRecords(); - $form_records_fields_model = new DiyFormRecordsFields(); $form_submit_config_model = new DiyFormSubmitConfig(); $form_write_config_model = new DiyFormWriteConfig(); @@ -299,12 +335,6 @@ class DiyFormService extends BaseAdminService //删除万能表单字段表 $form_fields_model->where($where)->delete(); - //删除万能表单填写记录 - $form_records_model->where($where)->delete(); - - //删除万能表单填写字段 - $form_records_fields_model->where($where)->delete(); - //删除万能表单提交页配置 $form_submit_config_model->where($where)->delete(); @@ -412,11 +442,15 @@ class DiyFormService extends BaseAdminService } $componentType($form_component_list, 'diy_form'); - $diy_service = new DiyService(); - $diy_component_list = $diy_service->getComponentList(); - $componentType($diy_component_list, 'diy'); + $data = $form_component_list; - $data = array_merge($form_component_list, $diy_component_list); + if ($type == 'DIY_FORM') { + $diy_service = new DiyService(); + $diy_component_list = $diy_service->getComponentList(); + $componentType($diy_component_list, 'diy'); + + $data = array_merge($form_component_list, $diy_component_list); + } return $data; } @@ -521,6 +555,11 @@ class DiyFormService extends BaseAdminService */ public function modifyStatus($data) { + $result = event('BeforeFormDelete', [ 'form_id' => $data[ 'form_id' ], 'site_id' => $this->site_id ])[ 0 ] ?? []; + if (!empty($result) && !$result[ 'allow_operate' ] && $data[ 'status' ] == 0) { + $form_info = $this->model->field('page_title')->where([ [ 'form_id', '=', $data[ 'form_id' ] ], [ 'site_id', '=', $this->site_id ] ])->findOrEmpty()->toArray(); + throw new AdminException($form_info[ 'page_title' ] . '已被使用,不可禁用'); + } return $this->model->where([ [ 'form_id', '=', $data[ 'form_id' ] ], [ 'site_id', '=', $this->site_id ] @@ -633,4 +672,21 @@ class DiyFormService extends BaseAdminService ]; } + /** + * 检测表单名称唯一性 + * @param array $data + * @return bool + */ + public function checkPageTitleUnique($data) + { + $where = [ + [ 'page_title', "=", $data[ 'page_title' ] ], + [ 'site_id', "=", $this->site_id ] + ]; + if (!empty($data[ 'form_id' ])) { + $where[] = [ 'form_id', "<>", $data[ 'form_id' ] ]; + } + return $this->model->where($where)->count() > 0; + } + } diff --git a/niucloud/app/service/admin/member/MemberCashOutService.php b/niucloud/app/service/admin/member/MemberCashOutService.php index 211eb384d..3defe4e46 100644 --- a/niucloud/app/service/admin/member/MemberCashOutService.php +++ b/niucloud/app/service/admin/member/MemberCashOutService.php @@ -12,9 +12,11 @@ namespace app\service\admin\member; use app\dict\member\MemberCashOutDict; +use app\dict\pay\TransferDict; use app\model\member\MemberCashOut; use app\service\core\member\CoreMemberCashOutService; use core\base\BaseAdminService; +use core\exception\CommonException; /** * 会员提现服务层 @@ -79,6 +81,9 @@ class MemberCashOutService extends BaseAdminService */ public function transfer(int $id, array $data){ $core_member_cash_out_service = new CoreMemberCashOutService(); + $cash_out = $core_member_cash_out_service->find($this->site_id, $id); + if ($cash_out->isEmpty()) throw new CommonException('RECHARGE_LOG_NOT_EXIST'); + if ($cash_out['status'] != MemberCashOutDict::WAIT_TRANSFER && $cash_out['transfer_type'] == TransferDict::WECHAT) throw new CommonException('CASH_OUT_WECHAT_ACCOUNT_NOT_ALLOW_ADMIN'); return $core_member_cash_out_service->transfer($this->site_id, $id, $data); } @@ -118,4 +123,14 @@ class MemberCashOutService extends BaseAdminService return $core_member_cash_out_service->checkTransferStatus($this->site_id, $id); } + /** + * 取消体现 + * @param int $id + * @return mixed + */ + public function cancel(int $id){ + $core_member_cash_out_service = new CoreMemberCashOutService(); + return $core_member_cash_out_service->cancel($this->site_id, $id); + } + } \ No newline at end of file diff --git a/niucloud/app/service/admin/member/MemberService.php b/niucloud/app/service/admin/member/MemberService.php index f3f1cb37a..204a5f2f6 100644 --- a/niucloud/app/service/admin/member/MemberService.php +++ b/niucloud/app/service/admin/member/MemberService.php @@ -43,7 +43,6 @@ class MemberService extends BaseAdminService */ public function getPage(array $where = []) { - $field = 'member_id, member_no, site_id, username, mobile, password, register_channel, register_type, nickname, headimg, member_level, member_label, wx_openid, weapp_openid, wx_unionid, ali_openid, douyin_openid, login_ip, login_type, login_channel, login_count, login_time, create_time, last_visit_time, last_consum_time, sex, status, birthday, point, point_get, balance, balance_get, growth, growth_get, is_member, member_time, is_del, province_id, city_id, district_id, address, location, delete_time, money, money_get, commission, commission_get, commission_cash_outing'; $search_model = $this->model->where([['site_id', '=', $this->site_id]])->withSearch(['keyword','register_type', 'create_time', 'is_del', 'member_label', 'register_channel','member_level'],$where) ->field($field) diff --git a/niucloud/app/service/admin/pay/TransferService.php b/niucloud/app/service/admin/pay/TransferService.php new file mode 100644 index 000000000..c46f34ef9 --- /dev/null +++ b/niucloud/app/service/admin/pay/TransferService.php @@ -0,0 +1,76 @@ +model = new Pay(); + } + + public function getWechatTransferScene(){ + return (new CoreTransferSceneService())->getWechatTransferScene($this->site_id); + } + + /** + * 设置转账场景id + * @param $scene + * @param $data + * @return void + */ + public function setSceneId($scene, $data){ + $core_transfer_service = new CoreTransferSceneService(); + $config = $core_transfer_service->getWechatTransferSceneConfig($this->site_id) ?? []; + $scene_list = TransferDict::getWechatTransferScene(); + if(empty($scene_list[$scene])) throw new AdminException('MERCHANT_TRANSFER_SCENARIOS_THAT_DO_NOT_EXIST'); + $config[$scene] = $data['scene_id']; + $core_transfer_service->setWechatTransferSceneConfig($this->site_id, $config); + return true; + } + + /** + * 设置业务转账场景配置 + * @param $type + * @param $data + * @return void + */ + public function setTradeScene($type, $data){ + $core_transfer_service = new CoreTransferSceneService(); + $core_transfer_service->setTradeScene($this->site_id, $type, $data); + return true; + } +} diff --git a/niucloud/app/service/admin/site/SiteService.php b/niucloud/app/service/admin/site/SiteService.php index 1a5628c4e..623097798 100644 --- a/niucloud/app/service/admin/site/SiteService.php +++ b/niucloud/app/service/admin/site/SiteService.php @@ -246,12 +246,26 @@ class SiteService extends BaseAdminService $name = "\\$model"; $class = new $name(); if (in_array('site_id', $class->getTableFields())) { - $class->where([ [ 'site_id', '=', $site[ 'site_id' ] ] ])->delete(); + $class::destroy(function($query) use ($site){ + $query->where([ [ 'site_id', '=', $site[ 'site_id' ] ] ]); + }); +// $class->where([ [ 'site_id', '=', $site[ 'site_id' ] ] ])->delete(); } } catch (\Exception $e) { } } + //删除站点时同步删除该站点的所有管理员的关联信息 + $sys_userrole_model = new SysUserRole(); + $site_uids = $sys_userrole_model->where('site_id', $site_id)->field('site_id,uid')->select()->toArray(); + $del_res = $sys_userrole_model->where('site_id', $site_id)->field('site_id,uid')->delete(); + if ($del_res){ + //删除成功是清除对应的缓存 + foreach ($site_uids as $item){ + Cache::delete('user_role_'.$item['uid'].'_'.$site_id); + Cache::delete('user_role_list_' .$item['uid']); + } + } Cache::tag(self::$cache_tag_name . $site_id)->clear(); Db::commit(); return true; diff --git a/niucloud/app/service/admin/sys/PosterService.php b/niucloud/app/service/admin/sys/PosterService.php index 9783ce5fb..0de40981d 100644 --- a/niucloud/app/service/admin/sys/PosterService.php +++ b/niucloud/app/service/admin/sys/PosterService.php @@ -114,6 +114,12 @@ class PosterService extends BaseAdminService */ public function modifyStatus($data) { + $poster_info = $this->model->field('is_default')->where([ + [ 'id', '=', $data[ 'id' ] ], + [ 'site_id', '=', $this->site_id ] + ])->findOrEmpty()->toArray(); + if (empty($poster_info)) throw new AdminException('POSTER_NOT_EXIST'); + if ($poster_info[ 'is_default' ] == 1) throw new AdminException('POSTER_IN_USE_NOT_ALLOW_MODIFY'); return $this->model->where([ [ 'id', '=', $data[ 'id' ] ], [ 'site_id', '=', $this->site_id ] diff --git a/niucloud/app/service/admin/sys/SystemService.php b/niucloud/app/service/admin/sys/SystemService.php index 4cb79855e..51e674960 100644 --- a/niucloud/app/service/admin/sys/SystemService.php +++ b/niucloud/app/service/admin/sys/SystemService.php @@ -15,6 +15,7 @@ use app\job\sys\CheckJob; use app\service\core\site\CoreSiteService; use app\service\core\sys\CoreSysConfigService; use core\base\BaseAdminService; +use think\facade\Cache; use think\facade\Db; use Throwable; @@ -114,17 +115,26 @@ class SystemService extends BaseAdminService } /** - * 清理缓存 + * 清除表缓存 + * @return string */ public function schemaCache() { - if (is_dir(dirname($_SERVER[ 'DOCUMENT_ROOT' ]) . '/runtime/schema')) { rmdirs(dirname($_SERVER[ 'DOCUMENT_ROOT' ]) . '/runtime/schema'); } return 'CLEAR_MYSQL_CACHE_SUCCESS'; } + /** + * 清理缓存 + */ + public function clearCache() + { + Cache::clear(); + return 'CACHE_CLEAR_SUCCESS'; + } + /** *校验消息队列是否正常运行 * @return bool diff --git a/niucloud/app/service/admin/upgrade/UpgradeService.php b/niucloud/app/service/admin/upgrade/UpgradeService.php index 128f8c417..ce08e66f3 100644 --- a/niucloud/app/service/admin/upgrade/UpgradeService.php +++ b/niucloud/app/service/admin/upgrade/UpgradeService.php @@ -29,6 +29,7 @@ use core\exception\CommonException; use core\util\niucloud\BaseNiucloudClient; use think\facade\Cache; use think\facade\Db; +use function DI\string; /** * 框架及插件升级 @@ -81,13 +82,9 @@ class UpgradeService extends BaseAdminService $web_dir = $this->root_path . 'web' . DIRECTORY_SEPARATOR; $wap_dir = $this->root_path . 'uni-app' . DIRECTORY_SEPARATOR; - try { - 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'); - } catch (\Exception $e) { - throw new CommonException($e->getMessage()); - } + 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 = [ // 目录检测 @@ -109,6 +106,22 @@ class UpgradeService extends BaseAdminService $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]; + } + } + 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') @@ -127,6 +140,8 @@ class UpgradeService extends BaseAdminService public function upgrade(string $addon = '') { if ($this->upgrade_task) throw new CommonException('UPGRADE_TASK_EXIST'); + $upgrade_content = $this->getUpgradeContent($addon); + $upgrade = [ 'product_key' => BaseNiucloudClient::PRODUCT, 'framework_version' => config('version.version') @@ -137,6 +152,12 @@ class UpgradeService extends BaseAdminService } else { $upgrade['app_key'] = $addon; $upgrade['version'] = (new Addon())->where([ ['key', '=', $addon] ])->value('version'); + + // 判断框架版本是否低于插件支持版本 + $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); @@ -150,18 +171,19 @@ class UpgradeService extends BaseAdminService dir_mkdir($upgrade_dir); } - $upgrade_tsak = [ + $upgrade_task = [ 'key' => $key, 'upgrade' => $upgrade, + 'steps' => $this->steps, 'step' => 'requestUpgrade', 'executed' => ['requestUpgrade'], 'log' => [ $this->steps['requestUpgrade']['title'] ], 'params' => ['token' => $response['token'] ], - 'upgrade_content' => $this->getUpgradeContent($addon) + 'upgrade_content' => $upgrade_content ]; - Cache::set($this->cache_key, $upgrade_tsak); - return $upgrade_tsak; + Cache::set($this->cache_key, $upgrade_task); + return $upgrade_task; } catch (\Exception $e) { throw new CommonException($e->getMessage()); } @@ -174,7 +196,7 @@ class UpgradeService extends BaseAdminService public function execute() { if (!$this->upgrade_task) return true; - $steps = array_keys($this->steps); + $steps = isset($this->upgrade_task['steps']) ? array_keys($this->upgrade_task['steps']) : array_keys($this->steps); $index = array_search($this->upgrade_task['step'], $steps); $step = $steps[ $index + 1 ] ?? ''; $params = $this->upgrade_task['params'] ?? []; @@ -194,7 +216,8 @@ class UpgradeService extends BaseAdminService Cache::set($this->cache_key, $this->upgrade_task); } catch (\Exception $e) { $this->upgrade_task['step'] = $step; - $this->upgrade_task['error'] = $e->getMessage(); + $this->upgrade_task['error'][] = '升级失败,失败原因:' . $e->getMessage().$e->getFile().$e->getLine(); + Cache::set($this->cache_key, $this->upgrade_task); $this->upgradeErrorHandle(); } return true; @@ -481,20 +504,55 @@ class UpgradeService extends BaseAdminService * @return true|void */ public function upgradeErrorHandle() { + $steps = []; + $steps[$this->upgrade_task['step']] = []; + + 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; + Cache::set($this->cache_key, $this->upgrade_task); + } + + /** + * 恢复源码 + * @return void + */ + public function restoreCode() { try { - if (isset($this->upgrade_task['is_cover'])) { - $restore_service = (new RestoreService()); - $restore_service->restoreCode(); - $restore_service->restoreSql(); - } - $this->clearUpgradeTask(5); + (new RestoreService())->restoreCode(); return true; } catch (\Exception $e) { - $this->clearUpgradeTask(5); + $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; } } + /** + * 恢复数据库 + * @return void + */ + public function restoreSql() { + try { + (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(); + Cache::set($this->cache_key, $this->upgrade_task); + return true; + } + } + + public function restoreComplete() { + $this->clearUpgradeTask(5); + return true; + } + /** * 获取升级内容 * @param string $addon diff --git a/niucloud/app/service/admin/weapp/WeappConfigService.php b/niucloud/app/service/admin/weapp/WeappConfigService.php index fabc63983..f14d1e89e 100644 --- a/niucloud/app/service/admin/weapp/WeappConfigService.php +++ b/niucloud/app/service/admin/weapp/WeappConfigService.php @@ -14,8 +14,11 @@ namespace app\service\admin\weapp; use app\dict\common\CommonDict; use app\model\sys\SysConfig; use app\service\core\weapp\CoreWeappConfigService; +use app\service\core\wxoplatform\CoreOplatformService; use core\base\BaseAdminService; +use core\exception\CommonException; use think\Model; +use app\service\admin\wxoplatform\WeappVersionService; /** * 微信小程序设置 @@ -36,6 +39,23 @@ class WeappConfigService extends BaseAdminService $config_info[$k] = CommonDict::ENCRYPT_STR; } } + $config_info['domain'] = [ + 'requestdomain' => '', + 'wsrequestdomain' => '', + 'uploaddomain' => '', + 'downloaddomain' => '', + 'tcpdomain' => '', + 'udpdomain' => '' + ]; + if ($config_info[ 'is_authorization' ] == 1) { + try { + $domain = CoreOplatformService::getDomain($this->site_id); + foreach ($config_info[ 'domain' ] as $k => $v) { + $config_info[ 'domain' ][ $k ] = isset($domain[$k]) && is_array($domain[$k]) ? implode(';', $domain[$k]) : ''; + } + } catch (\Exception $e) { + } + } return array_merge($config_info, $this->getWeappStaticInfo()); } @@ -71,4 +91,39 @@ class WeappConfigService extends BaseAdminService 'upload_ip' => gethostbyname('oss.niucloud.com') ]; } + + /** + * 设置域名 + * @param $data + * @return void + */ + public function setDomain($data){ + foreach ($data as $k => $v) { + $data[$k] = empty($v) ? [] : explode(';', $v); + } + $result = CoreOplatformService::setDomain($this->site_id, $data); + if (isset($result['errcode']) && $result['errcode'] != 0) { + throw new CommonException($result['errmsg']); + } + } + + /** + * 获取隐私协议 + * @return array + */ + public function getPrivacySetting(){ + return CoreOplatformService::getPrivacySetting($this->site_id); + } + + /** + * 设置隐私协议 + * @return array + */ + public function setPrivacySetting($data){ + $data['privacy_ver'] = 1; + CoreOplatformService::setPrivacySetting($this->site_id, $data); + // 提交小程序 + (new WeappVersionService())->siteWeappCommit(); + } + } diff --git a/niucloud/app/service/admin/wxoplatform/OplatformServerService.php b/niucloud/app/service/admin/wxoplatform/OplatformServerService.php index 19a3fda1d..0f62cd78b 100644 --- a/niucloud/app/service/admin/wxoplatform/OplatformServerService.php +++ b/niucloud/app/service/admin/wxoplatform/OplatformServerService.php @@ -94,7 +94,7 @@ class OplatformServerService extends BaseAdminService private function weappAuditSuccess($message) { $site_id = CoreOplatformService::getSiteIdByAuthorizerAppid($message['ToUserName']); CoreOplatformService::releaseWeapp($site_id); - (new WeappVersion())->where(['site_id' => $site_id, 'status' => CloudDict::APPLET_AUDITING ])->update(['status' => CloudDict::APPLET_UPLOAD_SUCCESS ]); + (new WeappVersion())->where(['site_id' => $site_id, 'status' => CloudDict::APPLET_AUDITING ])->update(['status' => CloudDict::APPLET_PUBLISHED ]); // 发布后重新设置下域名 request()->siteId($site_id); diff --git a/niucloud/app/service/admin/wxoplatform/WeappVersionService.php b/niucloud/app/service/admin/wxoplatform/WeappVersionService.php index 0ff61c3f9..655f2d0cd 100644 --- a/niucloud/app/service/admin/wxoplatform/WeappVersionService.php +++ b/niucloud/app/service/admin/wxoplatform/WeappVersionService.php @@ -216,14 +216,14 @@ class WeappVersionService extends BaseAdminService */ public static function weappCommit($site_id, $site_group_id) { $version = (new WxOplatfromWeappVersion())->where([ ['site_group_id', '=', $site_group_id], ['template_id', '<>', '' ] ])->order('id desc')->findOrEmpty(); - if ($version->isEmpty()) return true; + if ($version->isEmpty()) throw new CommonException('NOT_YET_PRESENT_TEMPLATE_LIBRARY'); $is_exist = (new WeappVersion())->where(['site_id' => $site_id, 'status' => CloudDict::APPLET_AUDITING ])->findOrEmpty(); if (!$is_exist->isEmpty()) throw new CommonException('EXIST_AUDITING_VERSION'); $weapp_config = (new CoreWeappConfigService())->getWeappConfig($site_id); - CoreOplatformService::commitWeapp($site_id, [ + $commit_result = CoreOplatformService::commitWeapp($site_id, [ 'template_id' => $version['template_id'], 'user_version' => $version['user_version'], 'user_desc' => $version['user_desc'], @@ -236,8 +236,9 @@ class WeappVersionService extends BaseAdminService 'directCommit' => true ]) ]); - - (new WeappVersion())->where(['site_id' => $site_id, 'version' => $version['user_version'] ])->delete(); + if (isset($commit_result['errcode']) && $commit_result['errcode'] != 0) { + throw new CommonException($commit_result['errmsg']); + } $create_res = (new WeappVersion())->create([ 'site_id' => $site_id, diff --git a/niucloud/app/service/api/diy/DiyService.php b/niucloud/app/service/api/diy/DiyService.php index f45049daa..eb521c81b 100644 --- a/niucloud/app/service/api/diy/DiyService.php +++ b/niucloud/app/service/api/diy/DiyService.php @@ -160,26 +160,24 @@ class DiyService extends BaseApiService { $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]])->column('id,color_name,color_mark,value,diy_value,title','addon'); - $defaultColor = ( new CoreDiyService() )->getDefaultColor(); + $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'] = [ - 'color_name' => $theme_data['app']['color_name'] ?? $defaultColor['name'], - 'color_mark' => $theme_data['app']['color_mark'] ?? $defaultColor['title'], - 'value' => $theme_data['app']['value'] ?? $defaultColor['theme'], - 'diy_value' => $theme_data['app']['diy_value'] ?? '', + '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){ + foreach ($addon_list as $key => $value){ if (isset($value['support_app']) && empty($value['support_app']) && $value['type'] == 'addon'){ continue; } - $default_theme_data = array_values(array_filter(event('ThemeColor', [ 'key' => $value['key']])))[0] ?? []; - $data[$value['key']]['color_mark'] = $theme_data[$value['key']]['color_mark'] ?? ($default_theme_data ? $default_theme_data[ 'name' ] : $defaultColor['name']); - $data[$value['key']]['color_name'] = $theme_data[$value['key']]['color_name'] ?? ($default_theme_data ? $default_theme_data[ 'title' ] : $defaultColor['title']); - $data[$value['key']]['value'] = $theme_data[$value['key']]['value'] ?? ($default_theme_data ? $default_theme_data[ 'theme' ] : $defaultColor['theme']); - $data[$value['key']]['diy_value'] = $theme_data[$value['key']]['diy_value'] ?? ''; + $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'] ?? ''; } - if (count($site_addon[ 'apps' ]) > 1) { + if (count($site_addon[ 'apps' ]) > 1) {// 应用数量大于1时,展示系统主题色设置,只有一个应用时,不展示系统主题色设置 $data = array_merge($app_theme,$data); } return $data; diff --git a/niucloud/app/service/api/login/LoginService.php b/niucloud/app/service/api/login/LoginService.php index b1c2de714..1c2e446cd 100644 --- a/niucloud/app/service/api/login/LoginService.php +++ b/niucloud/app/service/api/login/LoginService.php @@ -118,7 +118,8 @@ class LoginService extends BaseApiService $data = array( 'mobile' => $params[ 'mobile' ], 'nickname' => $params[ 'nickname' ], - 'headimg' => $params[ 'headimg' ] + 'headimg' => $params[ 'headimg' ], + 'wx_openid' => $params[ 'openid' ] ); return ( new RegisterService() )->register($params[ 'mobile' ], $data, MemberRegisterTypeDict::MOBILE, false); } else { @@ -202,7 +203,7 @@ class LoginService extends BaseApiService //发送 if (!in_array($type, SmsDict::SCENE_TYPE)) throw new AuthException('MEMBER_MOBILE_CAPTCHA_ERROR'); $code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数,左侧补0 -// ( new NoticeService() )->send('member_verify_code', [ 'code' => $code, 'mobile' => $mobile ]); + ( new NoticeService() )->send('member_verify_code', [ 'code' => $code, 'mobile' => $mobile ]); //将验证码存入缓存 $key = md5(uniqid('', true)); $cache_tag_name = "mobile_key" . $mobile . $type; @@ -255,20 +256,21 @@ class LoginService extends BaseApiService if (!empty($open_id)) { Log::write('channel_1' . $this->channel); if (!empty($this->channel)) { - $openid_field = match($this->channel){ - 'wechat' => 'wx_openid', + $openid_field = match ( $this->channel ) { + 'wechat' => 'wx_openid', 'weapp' => 'weapp_openid', default => '' }; if (!empty($openid_field)) { if (!$member->isEmpty()) { if (empty($member->$openid_field)) { - //todo 定义当前第三方授权方没有退出登录功能,故这儿不做openid是否存在账号验证 -// $member_service = new MemberService(); -// $open_member = $member_service->findMemberInfo([$openid_field => $open_id, 'site_id' => $this->site_id]); - - $member->$openid_field = $open_id; - $member->save(); + $member_service = new MemberService(); + $open_member = $member_service->findMemberInfo([ $openid_field => $open_id, 'site_id' => $this->site_id ]); + // 检测openid是否存在账号验证 + if (empty($open_member)) { + $member->$openid_field = $open_id; + $member->save(); + } } else { if ($member->$openid_field != $open_id) { throw new AuthException('MEMBER_IS_BIND_AUTH'); diff --git a/niucloud/app/service/api/login/RegisterService.php b/niucloud/app/service/api/login/RegisterService.php index 579bcf975..8df6f9304 100644 --- a/niucloud/app/service/api/login/RegisterService.php +++ b/niucloud/app/service/api/login/RegisterService.php @@ -11,7 +11,6 @@ namespace app\service\api\login; -use app\dict\common\ChannelDict; use app\dict\member\MemberLoginTypeDict; use app\dict\member\MemberRegisterTypeDict; use app\job\member\SetMemberNoJob; @@ -111,7 +110,7 @@ class RegisterService extends BaseApiService * @param $mobile * @return array */ - public function account(string $username, string $password, $mobile) + public function account(string $username, string $password, $mobile, $wx_openid) { //todo 校验验证码 可以加try catch 后续 ( new CaptchaService() )->check(); @@ -130,6 +129,14 @@ class RegisterService extends BaseApiService 'username' => $username, 'password' => $password_hash, ); + if (!empty($wx_openid)) { + // 检测openid是否被使用 + $member_service = new MemberService(); + $member_info = $member_service->findMemberInfo([ 'wx_openid' => $wx_openid, 'site_id' => $this->site_id ]); + if (empty($member_info->toArray())) { + $data[ 'wx_openid' ] = $wx_openid; + } + } return $this->register($mobile, $data, MemberRegisterTypeDict::USERNAME); } @@ -181,7 +188,7 @@ class RegisterService extends BaseApiService $config = ( new MemberConfigService() )->getLoginConfig(); $is_bind_mobile = $config[ 'is_bind_mobile' ]; - $with_field = match($type){ + $with_field = match ( $type ) { MemberLoginTypeDict::USERNAME => 'username', MemberLoginTypeDict::MOBILE => 'mobile', MemberLoginTypeDict::WECHAT => 'wx_openid', diff --git a/niucloud/app/service/api/member/MemberCashOutService.php b/niucloud/app/service/api/member/MemberCashOutService.php index f5ae798c5..ccc533a54 100644 --- a/niucloud/app/service/api/member/MemberCashOutService.php +++ b/niucloud/app/service/api/member/MemberCashOutService.php @@ -81,15 +81,16 @@ class MemberCashOutService extends BaseApiService ])->findOrEmpty(); if($cash_out->isEmpty()) throw new ApiException('RECHARGE_LOG_NOT_EXIST'); - if($cash_out['status'] != MemberCashOutDict::WAIT_AUDIT) throw new CommonException('CASHOUT_STATUS_NOT_IN_WAIT_AUDIT'); - $cash_out->save( - - [ - 'cancel_time' => time(), - 'status' => MemberCashOutDict::CANCEL - ] - ); - (new CoreMemberCashOutService())->giveback($this->site_id, $cash_out); +// if($cash_out['status'] != MemberCashOutDict::WAIT_AUDIT) throw new CommonException('CASHOUT_STATUS_NOT_IN_WAIT_AUDIT'); + (new CoreMemberCashOutService())->cancel($this->site_id, $id); +// $cash_out->save( +// +// [ +// 'cancel_time' => time(), +// 'status' => MemberCashOutDict::CANCEL +// ] +// ); +// (new CoreMemberCashOutService())->giveback($this->site_id, $cash_out); return true; } @@ -101,4 +102,14 @@ class MemberCashOutService extends BaseApiService return (new CoreMemberConfigService())->getCashOutConfig($this->site_id); } + /** + * 提现转账(主要用于微信商家转账) + * @param int $id + * @return void + */ + public function transfer(int $id, array $data){ + $data['channel'] = $this->channel; + $result = (new CoreMemberCashOutService())->transfer($this->site_id, $id, $data); + return $result; + } } \ No newline at end of file diff --git a/niucloud/app/service/api/member/MemberConfigService.php b/niucloud/app/service/api/member/MemberConfigService.php index a9ecbd839..409a54c8e 100644 --- a/niucloud/app/service/api/member/MemberConfigService.php +++ b/niucloud/app/service/api/member/MemberConfigService.php @@ -35,9 +35,7 @@ class MemberConfigService extends BaseApiService // 检测公众号配置是否成功 $wechat_auth = ( new WechatAuthService() )->jssdkConfig($url); } catch (\Exception $e) { - $res[ 'is_auth_register' ] = 0; - $res[ 'is_force_access_user_info' ] = 0; - $res[ 'is_bind_mobile' ] = 0; + $res[ 'wechat_error' ] = $e->getMessage(); } } return $res; diff --git a/niucloud/app/service/api/member/MemberService.php b/niucloud/app/service/api/member/MemberService.php index 4c27afb90..b92f2cb22 100644 --- a/niucloud/app/service/api/member/MemberService.php +++ b/niucloud/app/service/api/member/MemberService.php @@ -63,6 +63,15 @@ class MemberService extends BaseApiService return $this->model->where([['member_id', '=', $this->member_id]])->with(['member_level_name_bind'])->field($field)->append(['sex_name'])->findOrEmpty()->toArray(); } + /** + * 检测会员信息是否存在 + * @return int + */ + public function getCount($condition) + { + return $this->model->where($condition)->count(); + } + /** * 会员中心信息 */ diff --git a/niucloud/app/service/api/pay/TransferService.php b/niucloud/app/service/api/pay/TransferService.php new file mode 100644 index 000000000..1502420b6 --- /dev/null +++ b/niucloud/app/service/api/pay/TransferService.php @@ -0,0 +1,69 @@ +core_pay_service = new CorePayService(); + } + + /** + * 去支付 + * @param string $type + * @param string $trade_type + * @param int $trade_id + * @param string $return_url + * @param string $quit_url + * @param string $buyer_id + * @return mixed + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function confirm(string $transfer_no, array $data = []){ + +// $member = (new CoreMemberService())->getInfoByMemberId($this->site_id, $this->member_id); +// switch ($this->channel) { +// case ChannelDict::WECHAT://公众号 +// $openid = $openid ? $openid : $member['wx_openid'] ?? ''; +// break; +// case ChannelDict::WEAPP://微信小程序 +// $openid = $openid ? $openid : $member['weapp_openid'] ?? ''; +// break; +// } + +// /**/return $this->core_pay_service->pay($this->site_id, $trade_type, $trade_id, $type, $this->channel, $openid, $return_url, $quit_url, $buyer_id, $voucher, $this->member_id); + } + + +} diff --git a/niucloud/app/service/api/weapp/WeappAuthService.php b/niucloud/app/service/api/weapp/WeappAuthService.php index 8cab07f4e..780393acc 100644 --- a/niucloud/app/service/api/weapp/WeappAuthService.php +++ b/niucloud/app/service/api/weapp/WeappAuthService.php @@ -107,6 +107,7 @@ class WeappAuthService extends BaseApiService $is_auth_register = $config[ 'is_auth_register' ]; $is_force_access_user_info = $config[ 'is_force_access_user_info' ]; $is_bind_mobile = $config[ 'is_bind_mobile' ]; + $is_mobile = $config[ 'is_mobile' ]; if ($member_info->isEmpty()) { @@ -147,6 +148,12 @@ class WeappAuthService extends BaseApiService } else { return [ 'openid' => $openid, 'unionid' => $unionid ]; // 将重要信息返回给前端保存 } + } else if($is_mobile) { + if (!empty($data[ 'mobile' ]) || !empty($data[ 'mobile_code' ])) { + return $this->register($openid, $data[ 'mobile' ], $data[ 'mobile_code' ], $unionid); + } else { + return [ 'openid' => $openid, 'unionid' => $unionid ]; // 将重要信息返回给前端保存 + } } } } else { diff --git a/niucloud/app/service/api/wechat/WechatAuthService.php b/niucloud/app/service/api/wechat/WechatAuthService.php index c6be98af2..b3599fd95 100644 --- a/niucloud/app/service/api/wechat/WechatAuthService.php +++ b/niucloud/app/service/api/wechat/WechatAuthService.php @@ -148,14 +148,16 @@ class WechatAuthService extends BaseApiService return $this->register($openid, '', $nickname, $avatar, $unionid); } + } else { + return [ 'openid' => $openid, 'unionid' => $unionid ]; // 将重要信息返回给前端保存 } } else { // 可能会更新用户和粉丝表 $login_service = new LoginService(); // 若用户头像为空,那么从微信获取头像和昵称,然后进行更新 if (empty($member_info->headimg)) { - $member_info->headimg = $avatar; - $member_info->nickname = $nickname; + if (!empty($avatar)) $member_info->headimg = $avatar; + if (!empty($nickname)) $member_info->nickname = $nickname; } return $login_service->login($member_info, MemberLoginTypeDict::WECHAT); } diff --git a/niucloud/app/service/core/addon/CoreAddonInstallService.php b/niucloud/app/service/core/addon/CoreAddonInstallService.php index de1b346a2..c4477b142 100644 --- a/niucloud/app/service/core/addon/CoreAddonInstallService.php +++ b/niucloud/app/service/core/addon/CoreAddonInstallService.php @@ -105,13 +105,9 @@ class CoreAddonInstallService extends CoreAddonBaseService $to_resource_dir = public_path() . 'addon' . DIRECTORY_SEPARATOR . $this->addon . DIRECTORY_SEPARATOR; - try { - if (!is_dir($this->root_path . 'admin' . DIRECTORY_SEPARATOR)) throw new CommonException('ADMIN_DIR_NOT_EXIST'); - if (!is_dir($this->root_path . 'web' . DIRECTORY_SEPARATOR)) throw new CommonException('WEB_DIR_NOT_EXIST'); - if (!is_dir($this->root_path . 'uni-app' . DIRECTORY_SEPARATOR)) throw new CommonException('UNIAPP_DIR_NOT_EXIST'); - } catch (\Exception $e) { - throw new CommonException($e->getMessage()); - } + if (!is_dir($this->root_path . 'admin' . DIRECTORY_SEPARATOR)) throw new CommonException('ADMIN_DIR_NOT_EXIST'); + if (!is_dir($this->root_path . 'web' . DIRECTORY_SEPARATOR)) throw new CommonException('WEB_DIR_NOT_EXIST'); + if (!is_dir($this->root_path . 'uni-app' . DIRECTORY_SEPARATOR)) throw new CommonException('UNIAPP_DIR_NOT_EXIST'); // 配置文件 $package_path = $this->install_addon_path . 'package' . DIRECTORY_SEPARATOR; @@ -141,6 +137,22 @@ class CoreAddonInstallService extends CoreAddonBaseService $data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $to_wap_dir), 'status' => is_dir($to_wap_dir) ? is_write($to_wap_dir) : mkdir($to_wap_dir, 0777, true)]; $data['dir']['is_write'][] = ['dir' => str_replace(project_path(), '', $to_resource_dir), 'status' => is_dir($to_resource_dir) ? is_write($to_resource_dir) : mkdir($to_resource_dir, 0777, true)]; + // 校验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['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') diff --git a/niucloud/app/service/core/addon/vm/vm/admin/api.vm b/niucloud/app/service/core/addon/vm/vm/admin/api.vm deleted file mode 100644 index 1c1b40b54..000000000 --- a/niucloud/app/service/core/addon/vm/vm/admin/api.vm +++ /dev/null @@ -1,7 +0,0 @@ - -import request from '@/utils/request' - -/***************************************************** hello world ****************************************************/ -export function getHelloWorld() { - return request.get(`{key}/hello_world`) -} \ No newline at end of file diff --git a/niucloud/app/service/core/addon/vm/vm/admin/lang.vm b/niucloud/app/service/core/addon/vm/vm/admin/lang.vm deleted file mode 100644 index 0967ef424..000000000 --- a/niucloud/app/service/core/addon/vm/vm/admin/lang.vm +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/niucloud/app/service/core/addon/vm/vm/admin/views.vm b/niucloud/app/service/core/addon/vm/vm/admin/views.vm deleted file mode 100644 index 2a193a403..000000000 --- a/niucloud/app/service/core/addon/vm/vm/admin/views.vm +++ /dev/null @@ -1,17 +0,0 @@ - - - - - diff --git a/niucloud/app/service/core/addon/vm/vm/package/uni-app-pages.vm b/niucloud/app/service/core/addon/vm/vm/package/uni-app-pages.vm deleted file mode 100644 index e315f636e..000000000 --- a/niucloud/app/service/core/addon/vm/vm/package/uni-app-pages.vm +++ /dev/null @@ -1,19 +0,0 @@ - <<middleware([ - AdminCheckToken::class, - AdminCheckRole::class, - AdminLog::class -]); \ No newline at end of file diff --git a/niucloud/app/service/core/addon/vm/vm/system/api_controller.vm b/niucloud/app/service/core/addon/vm/vm/system/api_controller.vm deleted file mode 100644 index d499c0990..000000000 --- a/niucloud/app/service/core/addon/vm/vm/system/api_controller.vm +++ /dev/null @@ -1,27 +0,0 @@ -middleware(ApiChannel::class) - ->middleware(ApiCheckToken::class, false) //false表示不验证登录 - ->middleware(ApiLog::class); - - - -Route::group('{key}', function() { - -})->middleware(ApiChannel::class) - ->middleware(ApiCheckToken::class, true) //表示验证登录 - ->middleware(ApiLog::class); - diff --git a/niucloud/app/service/core/addon/vm/vm/system/common.vm b/niucloud/app/service/core/addon/vm/vm/system/common.vm deleted file mode 100644 index 6dd355233..000000000 --- a/niucloud/app/service/core/addon/vm/vm/system/common.vm +++ /dev/null @@ -1,4 +0,0 @@ - [ - - ], - 'listen' => [ - - ], - 'subscribe' => [ - ], -]; \ No newline at end of file diff --git a/niucloud/app/service/core/addon/vm/vm/system/info.vm b/niucloud/app/service/core/addon/vm/vm/system/info.vm deleted file mode 100644 index 891188961..000000000 --- a/niucloud/app/service/core/addon/vm/vm/system/info.vm +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "{title}", - "desc": "{desc}", - "key": "{key}", - "version": "{version}", - "author": "{author}", - "type": "{type}", - "support_app": "{support_app}", - "compile":[], - "support_version": "{support_version}" -} diff --git a/niucloud/app/service/core/addon/vm/vm/system/menu.vm b/niucloud/app/service/core/addon/vm/vm/system/menu.vm deleted file mode 100644 index c25d0e295..000000000 --- a/niucloud/app/service/core/addon/vm/vm/system/menu.vm +++ /dev/null @@ -1,33 +0,0 @@ - '{title}', - 'menu_key' => '{key}', - 'menu_type' => 0, - 'icon' => '', - 'api_url' => '', - 'router_path' => '', - 'view_path' => '', - 'methods' => '', - 'sort' => 100, - 'status' => 1, - 'is_show' => 1, - 'children' => [ - [ - 'menu_name' => '{title}', - 'menu_key' => '{key}_hello_world', - 'menu_type' => 1, - 'icon' => '', - 'api_url' => '{key}/hello_world', - 'router_path' => '{key}/hello_world', - 'view_path' => 'hello_world/index', - 'methods' => 'get', - 'sort' => 100, - 'status' => 1, - 'is_show' => 1, - 'children' => [] - ], - ] - ] -]; diff --git a/niucloud/app/service/core/addon/vm/vm/uni-app/api.vm b/niucloud/app/service/core/addon/vm/vm/uni-app/api.vm deleted file mode 100644 index d6def9df1..000000000 --- a/niucloud/app/service/core/addon/vm/vm/uni-app/api.vm +++ /dev/null @@ -1,8 +0,0 @@ - -import request from '@/utils/request' - -/***************************************************** hello world ****************************************************/ -export function getHelloWorld() { - return request.get(`{key}/hello_world`) -} - diff --git a/niucloud/app/service/core/addon/vm/vm/uni-app/lang.vm b/niucloud/app/service/core/addon/vm/vm/uni-app/lang.vm deleted file mode 100644 index 311847daa..000000000 --- a/niucloud/app/service/core/addon/vm/vm/uni-app/lang.vm +++ /dev/null @@ -1,2 +0,0 @@ -{} - diff --git a/niucloud/app/service/core/addon/vm/vm/uni-app/views.vm b/niucloud/app/service/core/addon/vm/vm/uni-app/views.vm deleted file mode 100644 index 777b1a6e1..000000000 --- a/niucloud/app/service/core/addon/vm/vm/uni-app/views.vm +++ /dev/null @@ -1,18 +0,0 @@ - - - - diff --git a/niucloud/app/service/core/addon/vm/vm/web/api.vm b/niucloud/app/service/core/addon/vm/vm/web/api.vm deleted file mode 100644 index d2241dfe4..000000000 --- a/niucloud/app/service/core/addon/vm/vm/web/api.vm +++ /dev/null @@ -1,8 +0,0 @@ - -/** - * hello world - */ -export function getHelloWorld() { - return request.get('{key}/hello_world') -} - diff --git a/niucloud/app/service/core/addon/vm/vm/web/lang.vm b/niucloud/app/service/core/addon/vm/vm/web/lang.vm deleted file mode 100644 index 9e26dfeeb..000000000 --- a/niucloud/app/service/core/addon/vm/vm/web/lang.vm +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/niucloud/app/service/core/addon/vm/vm/web/lang_pages.vm b/niucloud/app/service/core/addon/vm/vm/web/lang_pages.vm deleted file mode 100644 index 93efa1d09..000000000 --- a/niucloud/app/service/core/addon/vm/vm/web/lang_pages.vm +++ /dev/null @@ -1,9 +0,0 @@ -{ - "pages": { - "{key}": { - "hello_world": { - "index": "hello_world" - } - } - } -} \ No newline at end of file diff --git a/niucloud/app/service/core/addon/vm/vm/web/routes.vm b/niucloud/app/service/core/addon/vm/vm/web/routes.vm deleted file mode 100644 index 46674b01a..000000000 --- a/niucloud/app/service/core/addon/vm/vm/web/routes.vm +++ /dev/null @@ -1,6 +0,0 @@ -export default [ - { - path: "/{key}/hello_world/index", - component: () => import('~/addon/{key}/pages/hello_world/index.vue') - } -] diff --git a/niucloud/app/service/core/addon/vm/vm/web/view.vm b/niucloud/app/service/core/addon/vm/vm/web/view.vm deleted file mode 100644 index af84acdc7..000000000 --- a/niucloud/app/service/core/addon/vm/vm/web/view.vm +++ /dev/null @@ -1,15 +0,0 @@ - - - - diff --git a/niucloud/app/service/core/diy/CoreDiyService.php b/niucloud/app/service/core/diy/CoreDiyService.php index db083cb57..ff512fee7 100644 --- a/niucloud/app/service/core/diy/CoreDiyService.php +++ b/niucloud/app/service/core/diy/CoreDiyService.php @@ -11,11 +11,10 @@ namespace app\service\core\diy; -use app\dict\sys\ConfigKeyDict; -use app\model\sys\SysConfig; -use app\service\core\sys\CoreConfigService; +use app\model\addon\Addon; +use app\model\diy\DiyTheme; +use app\service\core\site\CoreSiteService; use core\base\BaseCoreService; -use think\Model; /** * 自定义页面服务层 @@ -24,77 +23,79 @@ use think\Model; */ class CoreDiyService extends BaseCoreService { - /** - * 获取系统默认主题配色 - * @return array - */ - public function getDefaultColor() - { - return [ - 'title' => '商务蓝', - 'name' => 'blue', - 'theme' => [ - '--primary-color' => '#007aff', // 主色 - '--primary-help-color' => '#007aff', // 辅色 - '--price-text-color' => '#FF4142',// 价格颜色 - '--primary-color-dark' => '#398ade', // 灰色 - '--primary-color-disabled' => '#9acafc', // 禁用色 - '--primary-color-light' => '#ecf5ff', // 边框色(深) - '--primary-color-light2' => '#fff7f7', // 边框色(淡) - '--page-bg-color' => '#f6f6f6', // 页面背景色 - ], - ]; - } /** - * 获取默认主题配色 - * @return array + * 初始化默认自定义主题配色 + * @return true */ - public function getDefaultThemeColor() + public function initDefaultDiyTheme($site_id) { - return [ - [ - 'title' => '商务蓝', - 'name' => 'blue', - 'theme' => [ - '--primary-color' => '#007aff', // 主色 - '--primary-help-color' => '#007aff', // 辅色 - '--price-text-color' => '#FF4142',// 价格颜色 - '--primary-color-dark' => '#398ade', // 灰色 - '--primary-color-disabled' => '#9acafc', // 禁用色 - '--primary-color-light' => '#ecf5ff', // 边框色(深) - '--primary-color-light2' => '#fff7f7', // 边框色(淡) - '--page-bg-color' => '#f6f6f6', // 页面背景色 - ], - ], - [ - 'title' => '热情红', - 'name' => 'red', - 'theme' => [ - '--primary-color' => '#FF4142', // 主色 - '--primary-help-color' => '#FB7939', // 辅色 - '--price-text-color' => '#FF4142',// 价格颜色 - '--primary-color-dark' => '#F26F3E', // 灰色 - '--primary-color-disabled' => '#FFB397', // 禁用色 - '--primary-color-light' => '#FFEAEA', // 边框色(深) - '--primary-color-light2' => '#fff7f7', // 边框色(淡) - '--page-bg-color' => '#f6f6f6', // 页面背景色 - ], - ], - [ - 'title' => '活力橙', - 'name' => 'orange', - 'theme' => [ - '--primary-color' => '#FA6400', // 主色 - '--primary-help-color' => '#FA6400', // 辅色 - '--price-text-color' => '#FF2525',// 价格颜色 - '--primary-color-dark' => '#F48032', // 灰色 - '--primary-color-disabled' => '#FFC29A', // 禁用色 - '--primary-color-light' => '#FFF4ED', // 边框色(深) - '--primary-color-light2' => '#FFF4ED', // 边框色(淡) - '--page-bg-color' => '#f6f6f6', // 页面背景色 - ], - ] - ]; + $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) { + $data[] = [ + 'type' => 'app', + 'addon' => 'app', + 'site_id' => $site_id, + '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] ?? []; + if (empty($addon_theme)) continue; + + foreach ($addon_theme['theme_color'] as $k => $v){ + $data[] = [ + 'type' => 'app', + 'addon' => $value['key'], + 'site_id' => $site_id, + '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){ + $data[] = [ + 'type' => 'addon', + 'addon' => $v['key'], + 'site_id' => $site_id, + '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(), + ]; + } + } + } + } + $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 ]); + } + } + if (!empty($data)) { + $diy_theme_model->insertAll($data); + } + return true; } } diff --git a/niucloud/app/service/core/diy_form/CoreDiyFormRecordsService.php b/niucloud/app/service/core/diy_form/CoreDiyFormRecordsService.php index f757213b0..a66845a5f 100644 --- a/niucloud/app/service/core/diy_form/CoreDiyFormRecordsService.php +++ b/niucloud/app/service/core/diy_form/CoreDiyFormRecordsService.php @@ -167,7 +167,7 @@ class CoreDiyFormRecordsService extends BaseCoreService if (!empty($form_field_info)) { if ($form_field_info[ 'field_required' ] == 1 && empty($field_value)) { - throw new CommonException($component[ 'componentTitle' ] . '不能为空'); + throw new CommonException(($component[ 'field' ][ 'name' ] ?? $component[ 'componentTitle' ]) . '不能为空'); } else if (empty($check_field_value)) { // 过滤空数据 continue; @@ -181,7 +181,7 @@ class CoreDiyFormRecordsService extends BaseCoreService [ 'field_type', '=', $component[ 'componentName' ] ] ])->column('field_value'); if ($form_field_info[ 'field_unique' ] == 1 && in_array($field_value, $field_values)) { - throw new CommonException($component[ 'componentTitle' ] . '不能重复'); + throw new CommonException(($component[ 'field' ][ 'name' ] ?? $component[ 'componentTitle' ]) . '不能重复'); } } else if (empty($check_field_value)) { // 过滤空数据 diff --git a/niucloud/app/service/core/member/CoreMemberCashOutService.php b/niucloud/app/service/core/member/CoreMemberCashOutService.php index 7c442feb5..83cad2d73 100644 --- a/niucloud/app/service/core/member/CoreMemberCashOutService.php +++ b/niucloud/app/service/core/member/CoreMemberCashOutService.php @@ -132,12 +132,13 @@ class CoreMemberCashOutService extends BaseCoreService $cash_out_account = (new CoreMemberCashOutAccountService())->getInfo($data['account_id'], $site_id, $member_id); if (empty($cash_out_account)) throw new CommonException('CASH_OUT_ACCOUNT_NOT_EXIST'); } else { - $data_transfer_payee = $data['transfer_payee'] ?? []; - if (empty($data_transfer_payee)) throw new CommonException('CASH_OUT_ACCOUNT_NOT_FOUND_VALUE');//转账到微信零钱缺少参数 - $transfer_payee = [ - 'open_id' => $data_transfer_payee['open_id'] ?? '', - 'channel' => $data_transfer_payee['channel'] ?? '', - ]; +// $data_transfer_payee = $data['transfer_payee'] ?? []; +// if (empty($data_transfer_payee)) throw new CommonException('CASH_OUT_ACCOUNT_NOT_FOUND_VALUE');//转账到微信零钱缺少参数 +// $transfer_payee = [ +// 'open_id' => $data_transfer_payee['open_id'] ?? '', +// 'channel' => $data_transfer_payee['channel'] ?? '', +// ]; + $transfer_payee = []; } Db::startTrans(); @@ -204,6 +205,7 @@ class CoreMemberCashOutService extends BaseCoreService } /** + * 审核 * @param int $site_id * @param int $id * @param string $action @@ -240,14 +242,18 @@ class CoreMemberCashOutService extends BaseCoreService 'audit_time' => time(), 'status' => MemberCashOutDict::WAIT_TRANSFER ]); - $config = (new CoreMemberConfigService())->getCashOutConfig($site_id); - if ($config['is_auto_transfer']) { - try { - $this->transfer($site_id, $cash_out['id']); - } catch ( Throwable $e ) { +// $config = (new CoreMemberConfigService())->getCashOutConfig($site_id); +// if ($config['is_auto_transfer']) { +// try { + //会员提现需要在前端手动发起 +// if($cash_out['transfer_type'] != TransferDict::WECHAT){ +// $this->transfer($site_id, $cash_out['id']); +// } - } - } +// } catch ( Throwable $e ) { + +// } +// } return true; } @@ -288,16 +294,10 @@ class CoreMemberCashOutService extends BaseCoreService $transfer_type = $cash_out['transfer_type']; if ($transfer_type == TransferDict::WECHAT) {//如果是转账到微信钱包,则需要获取openid //根据转账方式和会员的授权信息来判断可以使用的转账方式 -// $member = (new CoreMemberService())->find($site_id, $cash_out['member_id']); -// if(!empty($member['wx_openid'])){ -// $data['openid'] = $member['wx_openid']; -// } else if(!empty($member['weapp_openid'])){ -// $data['openid'] = $member['wweapp_openid']; -// }else{ -// $data['openid'] = ''; -// } -// $data['openid'] = $member['wx_openid']; - $data['transfer_payee'] = $cash_out['transfer_payee'] ?? []; + $data['transfer_payee'] = [ + 'open_id' => $data['open_id'] ?? '', + 'channel' => $data['channel'] ?? '', + ]; } } else { $transfer_type = $cash_out['transfer_type']; @@ -305,7 +305,7 @@ class CoreMemberCashOutService extends BaseCoreService $result = (new CoreTransferService())->transfer($site_id, $transfer_no, $transfer_type, $data); Db::commit(); - return true; + return $result; // 提交事务 } catch (\Exception $e) { @@ -393,4 +393,27 @@ class CoreMemberCashOutService extends BaseCoreService ]); return true; } + + /** + * 取消提现 + * @param int $site_id + * @param int $id + * @return void + */ + public function cancel(int $site_id, int $id){ + $cash_out = $this->find($site_id, $id); + if ($cash_out->isEmpty()) throw new CommonException('RECHARGE_LOG_NOT_EXIST'); + if ($cash_out['status'] != MemberCashOutDict::WAIT_AUDIT && $cash_out['status'] != MemberCashOutDict::WAIT_TRANSFER && $cash_out['status'] != MemberCashOutDict::TRANSFER_ING) throw new CommonException('CASHOUT_STATUS_NOT_IN_CANCEL'); + if($cash_out['transfer_type'] == TransferDict::WECHAT){ + if($cash_out['status'] == MemberCashOutDict::TRANSFER_ING){ + $core_transfer_service = new CoreTransferService(); + $core_transfer_service->cancel($site_id, $cash_out['transfer_no']); + } + } + $cash_out->save([ + 'status' => MemberCashOutDict::CANCEL, + ]); + $this->giveback($site_id, $cash_out); + return true; + } } \ No newline at end of file diff --git a/niucloud/app/service/core/member/CoreMemberConfigService.php b/niucloud/app/service/core/member/CoreMemberConfigService.php index e495323ee..5f5a8baa4 100644 --- a/niucloud/app/service/core/member/CoreMemberConfigService.php +++ b/niucloud/app/service/core/member/CoreMemberConfigService.php @@ -170,9 +170,15 @@ class CoreMemberConfigService extends BaseCoreService //校验转账方式是否合法 $transfer_type_list = array_keys(TransferDict::getTransferType()); if (array_diff(array_diff($data[ 'transfer_type' ], $transfer_type_list), $transfer_type_list)) throw new CommonException('TRANSFER_TYPE_NOT_EXIST'); + foreach ($transfer_type_list as $key => $item) { + if (!in_array($item, $data[ 'transfer_type' ])) { + unset($transfer_type_list[ $key ]); + } + } + $transfer_type_list = array_values($transfer_type_list); $config = [ 'is_open' => $data[ 'is_open' ],//是否启用提现 - 'transfer_type' => $data[ 'transfer_type' ] ?? [],//提现方式 + 'transfer_type' => $transfer_type_list ?? [],//提现方式 'min' => $data[ 'min' ] ?? '',//最低提现金额 'is_auto_verify' => $data[ 'is_auto_verify' ] ?? 0, //是否自动审核 'is_auto_transfer' => $data[ 'is_auto_transfer' ] ?? 0, //是否自动转账 diff --git a/niucloud/app/service/core/niucloud/CoreCloudBuildService.php b/niucloud/app/service/core/niucloud/CoreCloudBuildService.php index 31c8b0c93..82c2b59cb 100644 --- a/niucloud/app/service/core/niucloud/CoreCloudBuildService.php +++ b/niucloud/app/service/core/niucloud/CoreCloudBuildService.php @@ -11,9 +11,11 @@ namespace app\service\core\niucloud; +use app\dict\addon\AddonDict; use app\model\addon\Addon; 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\CommonException; use core\util\niucloud\BaseNiucloudClient; @@ -33,6 +35,8 @@ class CoreCloudBuildService extends BaseCoreService protected $auth_code; + use WapTrait; + public function __construct() { parent::__construct(); @@ -69,15 +73,30 @@ class CoreCloudBuildService extends BaseCoreService ] ]; - $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)]; + clearstatcache(); - $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 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_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['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'), @@ -112,6 +131,7 @@ class CoreCloudBuildService extends BaseCoreService $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']); + $this->handleUniapp($package_dir . 'uni-app'); } // 拷贝admin端文件 $admin_is_compile = (new Addon())->where([ ['compile', 'like', '%admin%'] ])->field('id')->findOrEmpty(); @@ -155,6 +175,11 @@ class CoreCloudBuildService extends BaseCoreService return $this->build_task; } + 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) { $addons = get_site_addons(); @@ -255,15 +280,15 @@ class CoreCloudBuildService extends BaseCoreService $zip->extractTo($temp_dir . 'download'); $zip->close(); - if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'admin')) { - del_target_dir(public_path() .'admin', true); - } - if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'web')) { - del_target_dir(public_path() .'web', true); - } - if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'wap')) { - del_target_dir(public_path() .'wap', true); - } +// if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'admin')) { +// del_target_dir(public_path() .'admin', true); +// } +// if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'web')) { +// del_target_dir(public_path() .'web', true); +// } +// if (is_dir($temp_dir . 'download' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . 'wap')) { +// del_target_dir(public_path() .'wap', true); +// } dir_copy($temp_dir . 'download', root_path()); diff --git a/niucloud/app/service/core/pay/CorePayEventService.php b/niucloud/app/service/core/pay/CorePayEventService.php index d711d2d14..0474628aa 100644 --- a/niucloud/app/service/core/pay/CorePayEventService.php +++ b/niucloud/app/service/core/pay/CorePayEventService.php @@ -288,5 +288,14 @@ class CorePayEventService extends BaseCoreService } - + /** + * 转账取消 + * @param array $param + * @return array + * @throws Exception + */ + public function transferCancel(array $param) + { + return $this->app()->transferCancel($param); + } } diff --git a/niucloud/app/service/core/pay/CorePayService.php b/niucloud/app/service/core/pay/CorePayService.php index 97303b82e..8995ff374 100644 --- a/niucloud/app/service/core/pay/CorePayService.php +++ b/niucloud/app/service/core/pay/CorePayService.php @@ -22,6 +22,7 @@ use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; use think\facade\Db; +use think\facade\Log; use think\Model; use Throwable; @@ -485,6 +486,9 @@ class CorePayService extends BaseCoreService case 'refund': return ( new CoreRefundService() )->refundNotify($site_id, $out_trade_no, $type, $params); break; + case 'transfer': + return ( new CoreTransferService() )->transferNotify($site_id, $out_trade_no, $params); + break; } //找不到对应的业务 return true; @@ -492,6 +496,8 @@ class CorePayService extends BaseCoreService return false; } }; + + Log::write('业务'.$site_id.'_'.$channel.'_'.$type.'_'.$action); return $this->pay_event->init($site_id, $channel, $type)->notify($action, $callback); } diff --git a/niucloud/app/service/core/pay/CoreTransferSceneService.php b/niucloud/app/service/core/pay/CoreTransferSceneService.php new file mode 100644 index 000000000..448be7370 --- /dev/null +++ b/niucloud/app/service/core/pay/CoreTransferSceneService.php @@ -0,0 +1,221 @@ +model = new TransferScene(); + + } + /** + * 获取底部导航配置 + * @param int $site_id + * @param string $key + * @return array + */ + public function getWechatTransferSceneConfig(int $site_id) + { + $info = ( new CoreConfigService() )->getConfigValue($site_id, ConfigKeyDict::WECHAT_TRANSFER_SCENE_CONFIG) ?? []; + return $info; + } + + /** + * 设置微信转账场景导航 + * @param int $site_id + * @param array $data + * @param string $key + * @return SysConfig|bool|Model + */ + public function setWechatTransferSceneConfig(int $site_id, array $data) + { + return ( new CoreConfigService() )->setConfig($site_id, ConfigKeyDict::WECHAT_TRANSFER_SCENE_CONFIG, $data); + } + /** + * 获取转账场景 + * @param $site_id + * @return void + */ + public function getWechatTransferScene($site_id){ + $list = TransferDict::getWechatTransferScene(); + + $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']] = []; + $trade_scene_list[$trade_scene_item_item['scene']][$trade_scene_key] = $trade_scene_select_data; + + } + } + + 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] ?? []; + } + //然后根据支持的业务来完善业务场景备注 + + return $list; + } + + /** + * 通过业务设置转账场景的配置信息 + * @param $site_id + * @param $data + * @return void + */ + public function setTradeScene($site_id, $type, $data){ + //先判断是否存在 + $trade_scene = $this->model->where(['site_id' => $site_id, 'type' => $type])->findOrEmpty(); + $infos = $data['infos']; + $perception = $data['perception']; + $scene = $data['scene']; + $data = [ + 'infos' => $infos, + 'perception' => $perception, + 'scene' => $scene, + 'type' => $type, + 'site_id' => $site_id + ]; + if($trade_scene->isEmpty()){ + $this->model->create($data); + }else{ + $trade_scene->save($data); + } + return true; + } + + /** + * 通过业务获取转账场景的配置信息 + * @param $site_id + * @param $type + * @return array|mixed + */ + public function getSceneInfoByType($site_id, $type){ + $trade_scene_event_array = event('GetWechatTransferTradeScene', []); + $temp_list = []; + foreach($trade_scene_event_array as $trade_scene_item){ + $temp_list = array_merge($temp_list, $trade_scene_item); + } + $trade_scene = $this->model->where(['site_id' => $site_id, 'type' => $type])->findOrEmpty(); + + if($trade_scene->isEmpty()){ + $value = $temp_list[$type] ?? []; + }else{ + $value = $trade_scene->toArray(); + } + $config = $this->getWechatTransferSceneConfig($site_id); + $scene_id = $config[$value['scene']] ?? ''; + $value['scene_id'] = $scene_id; + return $value; + } +} diff --git a/niucloud/app/service/core/pay/CoreTransferService.php b/niucloud/app/service/core/pay/CoreTransferService.php index 88a7d8572..4ac21dcd5 100644 --- a/niucloud/app/service/core/pay/CoreTransferService.php +++ b/niucloud/app/service/core/pay/CoreTransferService.php @@ -14,10 +14,13 @@ namespace app\service\core\pay; use app\dict\pay\TransferDict; use app\model\pay\Pay; use app\model\pay\Transfer; +use app\model\pay\TransferScene; +use app\service\core\sys\CoreConfigService; use core\base\BaseCoreService; use core\exception\PayException; use Exception; use think\facade\Db; +use think\facade\Log; use think\Model; use Throwable; @@ -95,34 +98,61 @@ class CoreTransferService extends BaseCoreService $transfer->save($transfer_data); switch($transfer_type){ case TransferDict::WECHAT: - $out_batch_no = create_no(); +// $out_batch_no = create_no(); $transfer_account = $data['transfer_payee'] ?? []; - $transfer_account['out_batch_no'] = $out_batch_no; + $scene_data = (new CoreTransferSceneService())->getSceneInfoByType($site_id, $transfer['trade_type']); + //通过业务获取业务场景 + $temp_infos = $scene_data['infos'] ?? [];//转账场景信息 + if(!empty($temp_infos)){ + $transfer_scene_report_infos = []; + foreach($temp_infos as $key => $item){ + $transfer_scene_report_infos[] = [ + 'info_type' => $key, + 'info_content' => $item + ]; + } + } + $transfer_account['transfer_scene_report_infos'] = $transfer_scene_report_infos ?? [];// + $transfer_account['user_recv_perception'] = $scene_data['perception'];//收款感知 + $transfer_account['transfer_scene_id'] = $scene_data['scene_id']; +// $transfer_account['out_batch_no'] = $out_batch_no; break; } $params = []; + $return_result = []; if(TransferDict::getTransferType()[$transfer_type]['is_online']){ try { $result = $this->pay_event->init($site_id, 'transfer', $transfer_type)->transfer($transfer['money'], $transfer_no, $transfer_account, $transfer_realname, $transfer['remark']); // $params['batch_id'] = $result['batch_id']; // $params['out_batch_no'] = $result['out_batch_no']; //将返回的数据交给转账通知 - $update_data = [ - 'batch_id' => $result['batch_id'] ?? '' - ]; - if(!empty($out_batch_no)){ - $update_data['out_batch_no'] = $out_batch_no; + + if($transfer_type == TransferDict::WECHAT){ + $update_data = [ + 'out_batch_no' => $result['transfer_bill_no'] ?? '', + 'package_info' => $result['package_info'] ?? '', + 'extra' => $result['extra'] ?? [], + ]; + $transfer->save($update_data); + $return_result['status'] = $result['status']; + $return_result['package_info'] = $result['package_info']; + $return_result['extra'] = $result['extra'] ?? []; } - $transfer->save($update_data); + $this->transferNotify($site_id, $transfer_no, $result); - return true; +// return true; }catch( Throwable $e){ $this->fail($site_id, $transfer_no, ['reason' => get_lang($e->getMessage())]); throw new PayException($e->getMessage()); } + }else{ + $return_result = [ + 'status' => TransferDict::SUCCESS, + ]; + $this->success($site_id, $transfer_no, $params); } - $this->success($site_id, $transfer_no, $params); - return true; + + return $return_result; } /** * 通过转账单号查询转账 @@ -138,21 +168,34 @@ class CoreTransferService extends BaseCoreService return $this->model->where($where)->findOrEmpty(); } - public function transferNotify(int $site_id, string $transfer_no, $params){ - $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); + /** + * 转账回调 + * @param int $site_id + * @param string $transfer_no + * @param $params + * @return true + */ + public function transferNotify(int $site_id, string $transfer_no, $params){ + Log::write('transferNotify'.$transfer_no); + $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); - if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); + if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL, TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); $status = $params['status'] ?? TransferDict::DEALING; + Log::write('transferNotifyStatus'.$status); switch($status){ case TransferDict::SUCCESS: + Log::write('transferNotifyStatus1'.$status); $this->success($site_id, $transfer_no); break; - case TransferDict::DEALING: - $this->dealing($site_id, $transfer_no); - break; case TransferDict::FAIL: - $this->fail($site_id, $transfer_no); + $this->fail($site_id, $transfer_no, $params); + break; +// case TransferDict::DEALING: +// $this->dealing($site_id, $transfer_no); +// break; + default: + $this->dealing($site_id, $transfer_no, $status); break; } return true; @@ -167,15 +210,15 @@ class CoreTransferService extends BaseCoreService */ public function success(int $site_id, string $transfer_no, array $params = []){ $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); - + Log::write('transferNotifyStatus2'.$transfer['transfer_status']); if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); - if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); + if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); $trade_type = $transfer->trade_type; $data = [ 'transfer_time' => time(), 'transfer_status' => TransferDict::SUCCESS, - 'batch_id' => $params['batch_id'] ?? '', +// 'batch_id' => $params['batch_id'] ?? '', // 'out_batch_no' => $params['out_batch_no'] ?? '', // 'transfer_type' => $transfer_type, ]; @@ -183,6 +226,7 @@ class CoreTransferService extends BaseCoreService Db::startTrans(); try { $transfer->save($data); + Log::write('transferNotifyStatus3'.TransferDict::SUCCESS); $result = event('TransferSuccess', ['transfer_no' => $transfer_no, 'trade_type' => $trade_type, 'site_id' => $site_id]); if(!check_event_result($result)){ Db::rollback(); @@ -211,11 +255,11 @@ class CoreTransferService extends BaseCoreService $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); - if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); + if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING])) throw new PayException('TRANFER_STATUS_NOT_IN_WAIT_TANSFER'); $data = array( 'transfer_time' => time(), 'transfer_status' => TransferDict::FAIL, - 'transfer_fail_reason' => $params['reason'] + 'transfer_fail_reason' => $params['reason'] ?? '' ); //允许修改的值 @@ -228,7 +272,7 @@ class CoreTransferService extends BaseCoreService $transfer_no = $data['transfer_no']; $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); - if(!in_array($transfer['transfer_status'], [TransferDict::DEALING, TransferDict::WAIT, TransferDict::FAIL]) ) throw new PayException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验 + if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING]) ) throw new PayException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验 //查询第三方支付单据 $transfer_info = $this->pay_event->init($site_id, 'transfer', $transfer->transfer_type)->getTransfer($transfer_no, $transfer['out_batch_no'] ?? ''); @@ -238,12 +282,14 @@ class CoreTransferService extends BaseCoreService case TransferDict::SUCCESS: $this->success($site_id, $transfer_no); break; - case TransferDict::DEALING: - $this->dealing($site_id, $transfer_no); - break; + case TransferDict::FAIL: $this->fail($site_id, $transfer_no); break; +// case TransferDict::DEALING: + default: + $this->dealing($site_id, $transfer_no, $status); + break; } return $status; } @@ -255,15 +301,70 @@ class CoreTransferService extends BaseCoreService * @param $type * @return true */ - public function dealing(int $site_id, $transfer_no){ + public function dealing(int $site_id, $transfer_no, $status){ $this->model->where([ ['site_id', '=', $site_id], ['transfer_no', '=', $transfer_no] ])->update( [ - 'transfer_status' => TransferDict::DEALING, +// 'transfer_status' => TransferDict::DEALING, + 'transfer_status' => $status, ] ); return true; } + + /** + * 用户确认转账信息 + * @param int $site_id + * @param string $transfer_no + * @param string $channel + * @param array $data + * @return void + */ +// public function confirm(int $site_id, string $transfer_no, string $channel, array $data ){ +// $transfer_no = $data['transfer_no']; +// $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); +// if($transfer['transfer_type'] == TransferDict::WECHAT){ +// //todo 判断微信转账是否已经超时 +// +// //todo 判断转账的主体授权信息是否一致 +// $transfer_payee = $transfer['transfer_payee']; +// $transfer_open_id = $transfer_payee['open_id']; +// $open_id = $data['open_id']; +// +// } +// } + + /** + * 撤销转账 + * @param int $site_id + * @param string $transfer_no + * @return void + */ + public function cancel(int $site_id, string $transfer_no){ + + try { + $transfer_no = $transfer_no; + $transfer = $this->findTransferByTransferNo($site_id, $transfer_no); + if($transfer->isEmpty()) throw new PayException('TRANSFER_ORDER_INVALID'); + if(!in_array($transfer['transfer_status'], [TransferDict::WAIT, TransferDict::DEALING, TransferDict::FAIL,TransferDict::WAIT_USER, TransferDict::WAIT_USER_ING, TransferDict::FAIL_ING]) ) throw new PayException('TRANFER_IS_CHANGE');//只有待转账和转账中的订单可以校验 + + //查询第三方支付单据 + $result = $this->pay_event->init($site_id, 'transfer', $transfer->transfer_type)->transferCancel([ + 'transfer_no' => $transfer_no + ]); + $this->transferNotify($site_id, $transfer_no, $result); + if($result['status'] == TransferDict::FAIL_ING){//撤销中的话也要返回错误,不能让业务认为撤销成功了 + throw new PayException('TRANSFER_IS_FAILING'); + } + return true; + }catch( Throwable $e){ + + throw new PayException($e->getMessage()); + } + + } + + } diff --git a/niucloud/app/service/core/site/CoreSiteService.php b/niucloud/app/service/core/site/CoreSiteService.php index c51920a6c..d2f58bb6a 100644 --- a/niucloud/app/service/core/site/CoreSiteService.php +++ b/niucloud/app/service/core/site/CoreSiteService.php @@ -22,6 +22,7 @@ use core\exception\CommonException; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; +use think\facade\Cache; use think\Model; /** @@ -127,6 +128,8 @@ class CoreSiteService extends BaseCoreService 'status' => SiteDict::EXPIRE, ] ); + Cache::delete('site_info_cache' . $site_id); + Cache::tag(self::$cache_tag_name . $site_id)->clear(); return true; } diff --git a/niucloud/app/service/core/sys/CoreExportService.php b/niucloud/app/service/core/sys/CoreExportService.php index 2114fa8a9..07992292d 100644 --- a/niucloud/app/service/core/sys/CoreExportService.php +++ b/niucloud/app/service/core/sys/CoreExportService.php @@ -15,6 +15,7 @@ use app\dict\sys\ExportDict; use app\model\sys\SysExport; use core\base\BaseCoreService; use PhpOffice\PhpSpreadsheet\Spreadsheet; +use PhpOffice\PhpSpreadsheet\Style\Alignment; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use think\facade\Log; @@ -173,23 +174,67 @@ class CoreExportService extends BaseCoreService $i ++; } + // 设置单元格的文本居中 + $style_array = [ + 'alignment' => [ +// 'horizontal' => Alignment::HORIZONTAL_CENTER, + 'vertical' => Alignment::VERTICAL_CENTER, + ], + ]; + + $merge_params = []; //设置excel文件表头 foreach ($data_column as $k => $v) { $sheet->setCellValue($v['excel_column_name']. '1', $v['name']); + // 将样式应用到单元格 + $sheet->getStyle($v['excel_column_name']. '1')->applyFromArray($style_array); + $merge_params[$k] = [ + 'start_merge_row' => null,// 用于记录开始合并的行号 + 'previous_value' => null// 用于记录上一行的值 + ]; } $row = 2; // 从第二行开始填充数据,第一行是表头 foreach ($data as $item) { - foreach ($data_column as $k => $v) { $sheet->setCellValue($v['excel_column_name'] . $row, $item[$k]); + // 将样式应用到单元格 + $sheet->getStyle($v['excel_column_name'] . $row)->applyFromArray($style_array); + + // todo 合并行 + if (isset($v['merge_type']) && $v['merge_type'] == 'column') { + if ($item[$k] === $merge_params[$k]['previous_value']) { + // 如果当前值等于上一个值,说明需要合并 + if ($merge_params[$k]['start_merge_row'] === null) { + $merge_params[$k]['start_merge_row'] = $row - 1; + } + } else { + // 当值变化时,合并之前相同的单元格 + if ($merge_params[$k]['start_merge_row'] !== null) { + $sheet->mergeCells($v['excel_column_name'] . $merge_params[$k]['start_merge_row'] . ':' . $v['excel_column_name'] . ($row - 1)); + $merge_params[$k]['start_merge_row'] = null; + } + $merge_params[$k]['previous_value'] = $item[$k]; + } + } } $row++; // 移动到下一行 } + // 处理最后一组可能的合并 + foreach ($data_column as $k => $v) + { + // todo 合并行 + if (isset($v['merge_type']) && $v['merge_type'] == 'column') { + if ($merge_params[$k]['start_merge_row'] !== null) { + $sheet->mergeCells($v['excel_column_name'] . $merge_params[$k]['start_merge_row'] . ':' . $v['excel_column_name'] . ($row - 1)); + } + } + } + // 设置自动调整列宽 foreach ($data_column as $k => $v) { diff --git a/niucloud/app/service/core/wxoplatform/CoreOplatformService.php b/niucloud/app/service/core/wxoplatform/CoreOplatformService.php index a9d640cef..14ca40090 100644 --- a/niucloud/app/service/core/wxoplatform/CoreOplatformService.php +++ b/niucloud/app/service/core/wxoplatform/CoreOplatformService.php @@ -233,6 +233,20 @@ class CoreOplatformService extends BaseCoreService return $app->getClient()->get('/wxa/security/get_code_privacy_info')->toArray(); } + /** + * 获取隐私接口 + * @param $site_id + * @return array|mixed[] + */ + public static function getPrivacySetting($site_id) { + $app = CoreWeappService::app($site_id); + return $app->getClient()->post('/cgi-bin/component/getprivacysetting', [ + 'json' => [ + 'privacy_ver' => 1 + ] + ])->toArray(); + } + /** * 设置隐私协议 * @param $site_id @@ -272,7 +286,7 @@ class CoreOplatformService extends BaseCoreService */ public static function getDomain($site_id) { $app = CoreWeappService::app($site_id); - return $app->getClient()->post('/wxa/modify_domain', [ + return $app->getClient()->post('/wxa/modify_domain_directly', [ 'json' => [ 'action' => 'get', ] @@ -294,7 +308,7 @@ class CoreOplatformService extends BaseCoreService */ public static function setDomain($site_id, $data) { $app = CoreWeappService::app($site_id); - return $app->getClient()->post('/wxa/modify_domain', [ + return $app->getClient()->post('/wxa/modify_domain_directly', [ 'json' => [ 'action' => 'set', 'requestdomain' => $data['requestdomain'] ?? [], diff --git a/niucloud/app/upgrade/v101/Upgrade.php b/niucloud/app/upgrade/v101/Upgrade.php new file mode 100644 index 000000000..6f31229ff --- /dev/null +++ b/niucloud/app/upgrade/v101/Upgrade.php @@ -0,0 +1,444 @@ +handleDiyData(); + $this->handleDiyThemeData(); + $this->handleDiyFormData(); + } + + /** + * 处理自定义数据 + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + private function handleDiyData() + { + $diy_model = new Diy(); + $where = [ + [ 'value', '<>', '' ] + ]; + $field = 'id,site_id,name,title,template,value'; + $list = $diy_model->where($where)->field($field)->select()->toArray(); + + if (!empty($list)) { + foreach ($list as $k => $v) { + $diy_data = json_decode($v[ 'value' ], true); + + foreach ($diy_data[ 'value' ] as $ck => $cv) { + + // 浮动按钮 组件 + if ($cv[ 'componentName' ] == 'FloatBtn') { + + // 左右偏移量 + if (!isset($diy_data[ 'value' ][ $ck ][ 'lateralOffset' ])) { + $diy_data[ 'value' ][ $ck ][ 'lateralOffset' ] = 15; + } + + } + + // 商品列表 组件、积分商品 组件、商品推荐、新人专享、分销商品 + if (in_array($cv[ 'componentName' ], [ 'GoodsList', 'ShopExchangeGoods', 'ShopNewcomer', 'FenxiaoGoodsList' ])) { + // 图片圆角 + if (!isset($diy_data[ 'value' ][ $ck ][ 'imgElementRounded' ])) { + $diy_data[ 'value' ][ $ck ][ 'imgElementRounded' ] = 10; + } + } + + + // 多商品组 组件 + if ($cv[ 'componentName' ] == 'ManyGoodsList') { + + // 图片圆角 + if (!isset($diy_data[ 'value' ][ $ck ][ 'imgElementRounded' ])) { + $diy_data[ 'value' ][ $ck ][ 'imgElementRounded' ] = 0; + } + } + + // 会员信息 + if ($cv[ 'componentName' ] == 'ShopMemberInfo') { + + // 账户颜色 + if (!isset($diy_data[ 'value' ][ $ck ][ 'accountTextColor' ])) { + $diy_data[ 'value' ][ $ck ][ 'accountTextColor' ] = '#666666'; + } + } + + } + + $diy_data = json_encode($diy_data); + $diy_model->where([ [ 'id', '=', $v[ 'id' ] ] ])->update([ 'value' => $diy_data ]); + } + } + + } + + /** + * 处理主题风格数据 + */ + private function handleDiyThemeData() + { + $site_model = new Site(); + $diy_theme_model = new DiyTheme(); + $site_ids = $site_model->where([ [ 'site_id', '>', 0 ] ])->column('site_id'); + foreach ($site_ids as $site_id) { + // 删除原有所有主题风格颜色 + $diy_theme_model->where([ [ 'site_id', '=', $site_id ] ])->delete(); + // 创建默认主题风格颜色 + $this->initDefaultDiyTheme($site_id); + } + } + + /** + * 处理表单数据 + * @return void + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\DbException + * @throws \think\db\exception\ModelNotFoundException + */ + private function handleDiyFormData() + { + $diy_form_model = new DiyForm(); + $field = 'form_id,value'; + $list = $diy_form_model->where([ [ 'value', '<>', '' ] ])->field($field)->select()->toArray(); + + if (!empty($list)) { + foreach ($list as $k => $v) { + $diy_form_data = $v[ 'value' ]; + foreach ($diy_form_data[ 'value' ] as $ck => $cv) { + if ($cv[ 'componentType' ] == 'diy_form') { + if (in_array($cv[ 'componentName' ], [ 'FormDate', 'FormDateScope', 'FormTime', 'FormTimeScope' ])) { + $diy_form_data[ 'value' ][ $ck ][ 'cache' ] = false; + } else { + $diy_form_data[ 'value' ][ $ck ][ 'cache' ] = true; + } + + } + } + + $diy_form_model->where([ [ 'form_id', '=', $v[ 'form_id' ] ] ])->update([ 'value' => $diy_form_data ]); + + } + + } + + + } + + private function getAppTheme() + { + return [ + // 系统主题色 + 'theme_color' => [ + [ + 'title' => '商务蓝', + 'name' => 'blue', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--primary-color' => "#007aff",//主色调 + '--primary-color-light' => "#ecf5ff",//主色调浅色(淡) + '--primary-color-light2' => "#FFF4ED",//主色调深色(深) + '--primary-help-color2' => "#007aff",//辅色调 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ] + ] + ], + ]; + } + + private function getCmsTheme() + { + return [ + // 应用主题色 + 'theme_color' => [ + [ + 'title' => '商务蓝', + 'name' => 'blue', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#FF2525",//价格颜色 + '--primary-color' => "#007aff",//主色调 + '--primary-color-light' => "#ecf5ff",//主色调浅色(淡) + '--primary-color-light2' => "#FFF4ED",//主色调深色(深) + '--primary-help-color2' => "#007aff",//辅色调 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ] + ] + ], + ]; + } + + private function getO2oTheme() + { + return [ + 'theme_color' => [ + [ + 'title' => '活力橙', + 'name' => 'orange', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#FF2525",//价格颜色 + '--primary-color' => "#FA6400",//主色调 + '--primary-color-light' => "#FFF4ED",//主色调浅色(淡) + '--primary-color-light2' => "#FFF4ED",//主色调深色(深) + '--primary-help-color2' => "#fa6400",//辅色调 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ] + ], + ], + ]; + } + + private function getShopTheme() + { + return [ + 'theme_color' => [ + [ + 'title' => '热情红', + 'name' => 'red', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#FF4142",//价格颜色 + '--primary-color' => "#FF4142",//主色调 + '--primary-color-light' => "#FFEAEA",//主色调浅色(淡) + '--primary-color-light2' => "#FFF7F7",//主色调深色(深) + '--primary-help-color1' => "#FFB000",//辅色调1 + '--primary-help-color2' => "#FB7939",//辅色调2 + '--primary-help-color3' => "#F26F3E",//辅色调3 + '--primary-help-color4' => "#FFB397",//辅色调4 + '--primary-help-color5' => "#FFA029",//辅色调5 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ], + ], + ], + ]; + } + + private function getFenxiaoTheme() + { + return [ + 'theme_color' => [ + [ + 'title' => '热情红', + 'name' => 'red', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#FF4142",//价格颜色 + '--primary-color' => "#FF4142",//主色调 + '--primary-color-light' => "#FFEAEA",//主色调浅色(淡) + '--primary-color-light2' => "#FFF7F7",//主色调深色(深) + '--primary-help-color1' => "#FFB000",//辅色调1 + '--primary-help-color2' => "#FB7939",//辅色调2 + '--primary-help-color3' => "#F26F3E",//辅色调3 + '--primary-help-color4' => "#FFB397",//辅色调4 + '--primary-help-color5' => "#FFA029",//辅色调5 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ], + ], + ], + ]; + } + + private function getGiftcardTheme() + { + return [ + 'theme_color' => [ + [ + 'title' => '热情红', + 'name' => 'red', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#FF4142",//价格颜色 + '--primary-color' => "#FF4142",//主色调 + '--primary-color-light' => "#FFEAEA",//主色调浅色(淡) + '--primary-color-light2' => "#FFF7F7",//主色调深色(深) + '--primary-help-color1' => "#FFB000",//辅色调1 + '--primary-help-color2' => "#FB7939",//辅色调2 + '--primary-help-color3' => "#F26F3E",//辅色调3 + '--primary-help-color4' => "#FFB397",//辅色调4 + '--primary-help-color5' => "#FFA029",//辅色调5 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ], + ], + ], + ]; + } + + private function getSowCommunityTheme() + { + return [ + 'theme_color' => [ + [ + 'title' => '热情红', + 'name' => 'red', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#FF4142",//价格颜色 + '--primary-color' => "#FF4142",//主色调 + '--primary-color-light' => "#FFEAEA",//主色调浅色(淡) + '--primary-color-light2' => "#FFF7F7",//主色调深色(深) + '--primary-help-color2' => "#FFB000",//辅色调 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ], + ], + ], + ]; + } + + private function getTourismTheme() + { + return [ + 'theme_color' => [ + [ + 'title' => '活力橙', + 'name' => 'orange', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#F55246",//价格颜色 + '--primary-color' => "#FA6400",//主色调 + '--primary-color-light' => "#FFF4ED",//主色调浅色(淡) + '--primary-color-light2' => "#FFF4ED",//主色调深色(深) + '--primary-help-color2' => "#fa6400",//辅色调 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ], + ], + ], + ]; + } + + private function getVipcardTheme() + { + return [ + 'theme_color' => [ + [ + 'title' => '活力橙', + 'name' => 'orange', + 'theme' => [ + '--page-bg-color' => "#F6F6F6",//页面背景色 + '--price-text-color' => "#FF4142",//价格颜色 + '--primary-color' => "#FA6400",//主色调 + '--primary-color-light' => "#FFF4ED",//主色调浅色(淡) + '--primary-color-light2' => "#FFF4ED",//主色调深色(深) + '--primary-help-color2' => "#fa6400",//辅色调 + '--primary-color-dark' => "#999999",//灰色调 + '--primary-color-disabled' => "#CCCCCC",//禁用色 + ], + ], + ], + ]; + } + + + /** + * 初始化默认自定义主题配色 + * @return true + */ + private function initDefaultDiyTheme($site_id) + { + $site_addon = ( new CoreSiteService() )->getSiteCache($site_id); + $system_theme = $this->getAppTheme(); + 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' ], + 'theme_type' => 'default', + 'is_selected' => $k == 0 ? 1 : 0, + 'create_time' => time(), + ]; + } + foreach ($site_addon[ 'apps' ] as $value) { + $addon_theme = []; + if ($value[ 'key' ] == 'cms') { + $addon_theme = $this->getCmsTheme(); + } elseif ($value[ 'key' ] == 'o2o') { + $addon_theme = $this->getO2oTheme(); + } elseif ($value[ 'key' ] == 'shop') { + $addon_theme = $this->getShopTheme(); + } elseif ($value[ 'key' ] == 'shop_fenxiao') { + $addon_theme = $this->getFenxiaoTheme(); + } elseif ($value[ 'key' ] == 'shop_giftcard') { + $addon_theme = $this->getGiftcardTheme(); + } elseif ($value[ 'key' ] == 'sow_community') { + $addon_theme = $this->getSowCommunityTheme(); + } elseif ($value[ 'key' ] == 'tourism') { + $addon_theme = $this->getTourismTheme(); + } elseif ($value[ 'key' ] == 'vipcard') { + $addon_theme = $this->getVipcardTheme(); + } + + foreach ($addon_theme[ 'theme_color' ] as $k => $v) { + $data[] = [ + 'type' => 'app', + 'addon' => $value[ 'key' ], + 'site_id' => $site_id, + '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) { + $data[] = [ + 'type' => 'addon', + 'addon' => $v[ 'key' ], + 'site_id' => $site_id, + '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(), + ]; + } + } + } + } + $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 ]); + } + } + if (!empty($data)) { + $diy_theme_model->insertAll($data); + } + return true; + } + +} diff --git a/niucloud/app/upgrade/v101/upgrade.sql b/niucloud/app/upgrade/v101/upgrade.sql new file mode 100644 index 000000000..eff36f14e --- /dev/null +++ b/niucloud/app/upgrade/v101/upgrade.sql @@ -0,0 +1,34 @@ + +DROP TABLE IF EXISTS `diy_theme`; +CREATE TABLE `diy_theme` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `site_id` INT(11) NOT NULL DEFAULT 0 COMMENT '站点id', + `title` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '标题', + `type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '插件类型app,addon', + `addon` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '所属应用,app:系统,shop:商城、o2o:上门服务', + `mode` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '模式,default:默认【跟随系统】,diy:自定义配色', + `theme_type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '配色类型,default:默认,diy:自定义', + `default_theme` text DEFAULT NULL COMMENT '当前色调的默认值', + `theme` text DEFAULT NULL COMMENT '当前色调', + `new_theme` text DEFAULT NULL COMMENT '新增颜色集合', + `is_selected` tinyint NOT NULL DEFAULT 0 COMMENT '已选色调,0:否,1.是', + `create_time` int NOT NULL DEFAULT 0 COMMENT '创建时间', + `update_time` int NOT NULL DEFAULT 0 COMMENT '更新时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE utf8mb4_general_ci COMMENT='自定义主题配色表'; + +DROP TABLE IF EXISTS `pay_transfer_scene`; +CREATE TABLE `pay_transfer_scene` ( + `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键', + `site_id` INT(11) NOT NULL DEFAULT 0 COMMENT '站点id', + `type` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '业务类型', + `scene` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '场景', + `infos` VARCHAR(2000) NOT NULL DEFAULT '' COMMENT '转账报备背景', + `create_time` INT(11) NOT NULL DEFAULT 0 COMMENT '创建时间', + `perception` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '转账收款感知', + PRIMARY KEY (`id`) +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '支付转账场景表' ROW_FORMAT = Dynamic; + +ALTER TABLE `pay_transfer` ADD COLUMN `package_info` VARCHAR(1000) NOT NULL DEFAULT '' COMMENT '跳转领取页面的package信息'; + +ALTER TABLE `pay_transfer` ADD COLUMN `extra` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '扩展信息'; diff --git a/niucloud/app/validate/diy/DiyForm.php b/niucloud/app/validate/diy/DiyForm.php index a828a8ba3..b1a9394d8 100644 --- a/niucloud/app/validate/diy/DiyForm.php +++ b/niucloud/app/validate/diy/DiyForm.php @@ -11,6 +11,7 @@ namespace app\validate\diy; +use app\service\admin\diy_form\DiyFormService; use think\Validate; /** @@ -22,6 +23,7 @@ class DiyForm extends Validate { protected $rule = [ + 'page_title' => 'require|checkPageTitleUnique', 'title' => 'require', 'type' => 'require', 'value' => 'require', @@ -30,8 +32,13 @@ class DiyForm extends Validate protected $message = []; protected $scene = [ - "add" => [ 'title', 'type', 'value' ], - "edit" => [ 'title', 'value' ], + "add" => [ 'page_title', 'title', 'type', 'value' ], + "edit" => [ 'page_title', 'title', 'value' ], ]; + public function checkPageTitleUnique($value, $rule, $data) + { + return ( new DiyFormService() )->checkPageTitleUnique($data) ? get_lang("validate_diy.page_title_unique") : true; + } + } diff --git a/niucloud/app/validate/diy/DiyTheme.php b/niucloud/app/validate/diy/DiyTheme.php new file mode 100644 index 000000000..9df050eb8 --- /dev/null +++ b/niucloud/app/validate/diy/DiyTheme.php @@ -0,0 +1,43 @@ + 'require|checkDiyThemeTitleUnique', + 'theme' => 'require', + ]; + + protected $message = []; + + protected $scene = [ + "add" => ['title', 'theme'], + "edit" => ['title', 'theme'], + ]; + + public function checkDiyThemeTitleUnique($value, $rule, $data) + { + return ( new DiyService() )->checkDiyThemeTitleUnique($data) ? get_lang("validate_diy.theme_title_unique") : true; + } + + +} \ No newline at end of file diff --git a/niucloud/config/cache.php b/niucloud/config/cache.php index 34f9e1aa8..a40b31b41 100644 --- a/niucloud/config/cache.php +++ b/niucloud/config/cache.php @@ -24,6 +24,20 @@ return [ // 序列化机制 例如 ['serialize', 'unserialize'] 'serialize' => [], ], + 'jwt' => [ + // 驱动方式 + 'type' => 'File', + // 缓存保存目录 + 'path' => app()->getRuntimePath() . 'jwt' . DIRECTORY_SEPARATOR, + // 缓存前缀 + 'prefix' => '', + // 缓存有效期 0表示永久缓存 + 'expire' => 0, + // 缓存标签前缀 + 'tag_prefix' => 'tag:', + // 序列化机制 例如 ['serialize', 'unserialize'] + 'serialize' => [], + ], // 更多的缓存连接 // redis 'redis' => [ diff --git a/niucloud/config/version.php b/niucloud/config/version.php index 3a629d7be..fc44df460 100644 --- a/niucloud/config/version.php +++ b/niucloud/config/version.php @@ -1,6 +1,6 @@ '1.0.0', - 'code' => '202501170001' + 'version' => '1.0.1', + 'code' => '202503080001' ]; diff --git a/niucloud/core/dict/GrowthRule.php b/niucloud/core/dict/GrowthRule.php index 1a58d3145..59486e9fe 100644 --- a/niucloud/core/dict/GrowthRule.php +++ b/niucloud/core/dict/GrowthRule.php @@ -10,6 +10,8 @@ // +---------------------------------------------------------------------- namespace core\dict; +use app\service\core\addon\CoreAddonService; + class GrowthRule extends BaseDict { /** @@ -20,26 +22,35 @@ class GrowthRule extends BaseDict public function load(array $data = []) { $addons = $this->getLocalAddons(); - $account_change_type_files = []; + $system_change_type_file = $this->getDictPath() . "member" . DIRECTORY_SEPARATOR . "growth_rule.php"; + $core_addon_service = new CoreAddonService(); + $account_change_type_array = []; if (is_file($system_change_type_file)) { - $account_change_type_files[] = $system_change_type_file; + $account_change_type_datas = $this->loadFiles([$system_change_type_file]); + foreach ($account_change_type_datas as $account_change_type_data) { + foreach ($account_change_type_data as &$value) { + $value[ 'addon_name' ] = '系统'; + } + $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); + } } foreach ($addons as $v) { $addon_change_type_file = $this->getAddonDictPath($v) . "member" . DIRECTORY_SEPARATOR . "growth_rule.php"; if (is_file($addon_change_type_file)) { - $account_change_type_files[] = $addon_change_type_file; + $addon_info = $core_addon_service->getInfoByKey($v); + $account_change_type_datas = $this->loadFiles([$addon_change_type_file]); + foreach ($account_change_type_datas as $account_change_type_data) { + foreach ($account_change_type_data as &$value) { + $value[ 'addon_name' ] = $addon_info[ 'title' ]; + } + $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); + } } } - $account_change_type_datas = $this->loadFiles($account_change_type_files); - - $account_change_type_array = []; - foreach ($account_change_type_datas as $account_change_type_data) { - $account_change_type_array = empty($account_change_type_array) ? $account_change_type_data : array_merge2($account_change_type_array, $account_change_type_data); - } return $account_change_type_array; } } diff --git a/niucloud/core/pay/Alipay.php b/niucloud/core/pay/Alipay.php index 0368a3303..b699e508a 100644 --- a/niucloud/core/pay/Alipay.php +++ b/niucloud/core/pay/Alipay.php @@ -376,7 +376,15 @@ class Alipay extends BasePay } } } + /** + * 转账取消 + * @param array $params + * @return array + */ + public function transferCancel(array $params) + { + } public function fail() { return 'fail'; diff --git a/niucloud/core/pay/BasePay.php b/niucloud/core/pay/BasePay.php index 439d083f7..e9e7335e8 100644 --- a/niucloud/core/pay/BasePay.php +++ b/niucloud/core/pay/BasePay.php @@ -125,6 +125,13 @@ abstract class BasePay extends Storage */ abstract protected function getTransfer(string $transfer_no, $out_transfer_no = ''); + /** + * 取消转账 + * @param array $params + * @return mixed + */ + abstract protected function transferCancel(array $params); + /** * 初始化 * @param array $config diff --git a/niucloud/core/pay/Wechatpay.php b/niucloud/core/pay/Wechatpay.php index 41a704184..f69633677 100644 --- a/niucloud/core/pay/Wechatpay.php +++ b/niucloud/core/pay/Wechatpay.php @@ -9,6 +9,7 @@ use app\dict\pay\TransferDict; use core\exception\PayException; use Psr\Http\Message\MessageInterface; use Psr\Http\Message\ResponseInterface; +use think\facade\Log; use think\Response; use Throwable; use Yansongda\Artful\Exception\InvalidResponseException; @@ -16,6 +17,7 @@ use Yansongda\Pay\Exception\ContainerException; use Yansongda\Pay\Exception\InvalidParamsException; use Yansongda\Pay\Exception\ServiceNotFoundException; use Yansongda\Pay\Pay; +use Yansongda\Pay\Plugin\Wechat\V3\Marketing\MchTransfer\CancelPlugin; use Yansongda\Supports\Collection; @@ -229,51 +231,40 @@ class Wechatpay extends BasePay $to_data = $params['to_no'];//收款人数据 $channel = $to_data['channel'] ?? '';//渠道 $open_id = $to_data['open_id'] ?? '';//openid - + $transfer_scene_id = (string)$to_data['transfer_scene_id'] ?? '';//openid + $transfer_scene_report_infos = $to_data['transfer_scene_report_infos'] ?? [];//openid + $user_recv_perception = $to_data['user_recv_perception'] ?? '';//openid if(empty($this->config['mch_id']) || empty($this->config['mch_secret_key']) || empty($this->config['mch_secret_cert']) || empty($this->config['mch_public_cert_path'])){ throw new PayException('WECHAT_TRANSFER_CONFIG_NOT_EXIST'); } - //这儿的批次信息可能是这儿生成的,但依然需要记录 + $transfer_no = $params['transfer_no'] ?? ''; + $remark = $params['remark'] ?? ''; $order = [ - 'out_batch_no' => ($to_data['out_batch_no'] ?? '') . '',// - 'batch_name' => $params['remark'] ?? '', - 'batch_remark' => $params['remark'] ?? '', + '_action' => 'mch_transfer', // 微信官方老版本下线后,此部分可省略 + 'out_bill_no' => $transfer_no, + 'transfer_scene_id' => $transfer_scene_id, + 'openid' => $open_id, + // 'user_name' => '闫嵩达' // 明文传参即可,sdk 会自动加密 + 'transfer_amount' => (int)$params['money'], + 'transfer_remark' => $remark, + 'transfer_scene_report_infos' =>$transfer_scene_report_infos, + 'notify_url' => $this->config['notify_url'], + 'user_recv_perception' => $user_recv_perception ]; if($channel == ChannelDict::WEAPP){ $order['_type'] = 'mini'; } - $transfer_list = $params['transfer_list']; - //单笔转账 - if (empty($transfer_list)) { - $transfer_list = [ - [ - 'transfer_no' => $params['transfer_no'], - 'money' => (int)$params['money'], - 'remark' => $params['remark'], - 'openid' => $open_id - ] - ]; - } - $total_amount = 0; - $total_num = 0; - - foreach ($transfer_list as $k => $v) { - $item_transfer = [ - 'out_detail_no' => $params['transfer_no'], - 'transfer_amount' => (int)$v['money'], - 'transfer_remark' => $v['remark'], - 'openid' => $v['openid'], - ]; - $total_amount += (int)$v['money']; - $total_num++; - if (!empty($v['user_name'])) { - $item_transfer['user_name'] = $v['user_name'];// 明文传参即可,sdk 会自动加密 - } - $order['transfer_detail_list'][] = $item_transfer; - } - $order['total_amount'] = $total_amount; - $order['total_num'] = $total_num; + $tran_status_list = [ + 'PROCESSING' => TransferDict::DEALING, + 'ACCEPTED' => TransferDict::DEALING, + 'WAIT_USER_CONFIRM' => TransferDict::WAIT_USER,//等待收款用户确认 + 'TRANSFERING' => TransferDict::WAIT_USER_ING,//转账中 + 'FAIL' => TransferDict::FAIL, + 'SUCCESS' => TransferDict::SUCCESS, + 'CANCELING' => TransferDict::FAIL_ING, + 'CANCELLED' => TransferDict::FAIL, + ]; try { $result = $this->returnFormat(Pay::wechat()->transfer($order)); if (!empty($result['code'])) { @@ -287,15 +278,13 @@ class Wechatpay extends BasePay } throw new PayException($result['message']); } - - $tran_status_list = [ - 'PROCESSING' => TransferDict::DEALING, - 'ACCEPTED' => TransferDict::DEALING, - 'CLOSED' => TransferDict::FAIL, - 'FINISHED' => TransferDict::SUCCESS, - ]; - return ['batch_id' => $result['batch_id'], 'out_batch_no' => $result['out_batch_no'], 'status' => $tran_status_list[$result['batch_status']]]; + $result['mch_id'] = $this->config['mch_id']; + $result['appid'] = $channel == ChannelDict::WEAPP ? $this->config['mini_app_id'] : $this->config['mp_app_id']; + return ['out_bill_no' => $result['out_bill_no'], 'transfer_bill_no' => $result['transfer_bill_no'], 'status' => $tran_status_list[$result['state']], 'reason' => $result['fail_reason'] ?? '', 'package_info' => $result['package_info'] ?? [], 'extra' => $result]; } catch (\Exception $e) { +// if($e->getCode() == 9402){ +// return ['batch_id' => '', 'out_batch_no' => $order['out_batch_no'], 'status' => TransferDict::DEALING]; +// } if ($e instanceof InvalidResponseException) { throw new PayException($e->response->all()['message'] ?? ''); } @@ -374,7 +363,13 @@ class Wechatpay extends BasePay public function notify(string $action, callable $callback) { try { + Log::write('wechat_start'.$action); $result = $this->returnFormat(Pay::wechat()->callback()); + + Log::write('wechat_start_1'); + + Log::write($result); + Log::write('wechat_start_1'); if ($action == 'pay') {//支付 if ($result['event_type'] == 'TRANSACTION.SUCCESS') { $pay_trade_data = $result['resource']['ciphertext']; @@ -411,11 +406,43 @@ class Wechatpay extends BasePay return Pay::wechat()->success(); } } + }else if ($action == 'transfer') {//转账 + if ($result['event_type'] == 'MCHTRANSFER.BILL.FINISHED') { + $refund_trade_data = $result['resource']['ciphertext']; + $tran_status_list = [ + 'PROCESSING' => TransferDict::DEALING, + 'ACCEPTED' => TransferDict::DEALING, + + 'WAIT_USER_CONFIRM' => TransferDict::WAIT_USER,//等待收款用户确认 + 'TRANSFERING' => TransferDict::WAIT_USER_ING,//转账中 + 'FAIL' => TransferDict::FAIL, + 'SUCCESS' => TransferDict::SUCCESS, + 'CANCELING' => TransferDict::FAIL_ING, + 'CANCELLED' => TransferDict::FAIL, + ]; + $temp_params = [ +// 'out_bill_no' => $refund_trade_data['out_bill_no'], + 'mch_id' => $refund_trade_data['mch_id'], + 'out_bill_no' => $refund_trade_data['out_bill_no'] ?? '', + 'transfer_bill_no' => $refund_trade_data['transfer_bill_no'] ?? '', + 'status' => $tran_status_list[$refund_trade_data['state']], + 'reason' => $refund_trade_data['fail_reason'] ?? '', + ]; + Log::write('wechat_start_2'); + + Log::write($temp_params); + Log::write('wechat_start_2'); + $callback_result = $callback($refund_trade_data['out_bill_no'], $temp_params); + if (is_bool($callback_result) && $callback_result) { + return Pay::wechat()->success(); + } + } } return $this->fail(); } catch ( Throwable $e ) { // throw new PayException($e->getMessage()); + Log::write('wechat_error'.$e->getMessage().$e->getLine().$e->getFile()); return $this->fail($e->getMessage()); } } @@ -495,35 +522,93 @@ class Wechatpay extends BasePay public function getTransfer(string $transfer_no, $out_batch_no = '') { $order = [ - 'out_batch_no' => $out_batch_no, - 'out_detail_no' => $transfer_no, + 'out_bill_no' => $transfer_no, + 'transfer_bill_no' => $out_batch_no, '_action' => 'transfer', ]; + $tran_status_list = [ + 'PROCESSING' => TransferDict::DEALING, + 'ACCEPTED' => TransferDict::DEALING, + 'WAIT_USER_CONFIRM' => TransferDict::WAIT_USER,//等待收款用户确认 + 'TRANSFERING' => TransferDict::WAIT_USER_ING,//转账中 + 'FAIL' => TransferDict::FAIL, + 'SUCCESS' => TransferDict::SUCCESS, + 'CANCELING' => TransferDict::FAIL_ING, + 'CANCELLED' => TransferDict::FAIL, + ]; try { $result = Pay::wechat()->query($order); $result = $this->returnFormat($result); //微信转账状态 - $transfer_status_array = [ - 'INIT' => TransferDict::DEALING,//初始态。 系统转账校验中 - 'WAIT_PAY' => TransferDict::DEALING, - 'PROCESSING' => TransferDict::DEALING, - 'FAIL' => TransferDict::FAIL, - 'SUCCESS' => TransferDict::SUCCESS, - ]; +// $transfer_status_array = [ +// 'INIT' => TransferDict::DEALING,//初始态。 系统转账校验中 +// 'WAIT_PAY' => TransferDict::DEALING, +// 'PROCESSING' => TransferDict::DEALING, +// 'FAIL' => TransferDict::FAIL, +// 'SUCCESS' => TransferDict::SUCCESS, +// ]; return [ - 'status' => $transfer_status_array[$result['detail_status']], - 'transfer_no' => $transfer_no + 'status' => $tran_status_list[$result['state']], + 'transfer_no' => $transfer_no, + 'reason' => $result['fail_reason'] ?? '', + 'out_bill_no' => $result['out_bill_no'] ?? '', + 'transfer_bill_no' => $result['transfer_bill_no'] ?? '' ]; }catch(Throwable $e){ return [ 'status' => TransferDict::DEALING, - 'transfer_no' => $transfer_no + 'transfer_no' => $transfer_no, + 'reason' => $e->getMessage(), ]; } } + /** + * 转账取消 + * @param array $params + * @return array + */ + public function transferCancel(array $params) + { + if(empty($this->config['mch_id']) || empty($this->config['mch_secret_key']) || empty($this->config['mch_secret_cert']) || empty($this->config['mch_public_cert_path'])){ + throw new PayException('WECHAT_TRANSFER_CONFIG_NOT_EXIST'); + } + $transfer_no = $params['transfer_no'] ?? ''; + + $tran_status_list = [ + 'CANCELING' => TransferDict::FAIL_ING, + 'CANCELLED' => TransferDict::FAIL, + ]; + $order = [ + '_action' => 'cancel', // 微信官方老版本下线后,此部分可省略 + 'out_bill_no' => $transfer_no, + 'notify_url' => $this->config['notify_url'], + ]; + try { + + $allPlugins = Pay::wechat()->mergeCommonPlugins([CancelPlugin::class]); + + $result = Pay::wechat()->pay($allPlugins, $order); +// $result = $this->returnFormat(Pay::wechat()->transfer($order)); + if (!empty($result['code'])) { +// + if ($result['code'] == 'INVALID_REQUEST') { + throw new PayException(700010); + } + throw new PayException($result['message']); + } + + return ['out_bill_no' => $result['out_bill_no'], 'transfer_bill_no' => $result['transfer_bill_no'], 'status' => $tran_status_list[$result['state']]]; + } catch (\Exception $e) { + if ($e instanceof InvalidResponseException) { + throw new PayException($e->response->all()['message'] ?? ''); + } + throw new PayException($e->getMessage()); + } + + } public function fail($message = '') { $response = [ diff --git a/niucloud/core/util/TokenAuth.php b/niucloud/core/util/TokenAuth.php index ad10aea30..591acca76 100644 --- a/niucloud/core/util/TokenAuth.php +++ b/niucloud/core/util/TokenAuth.php @@ -47,7 +47,7 @@ class TokenAuth $params['jti'] = $id . "_" . $type; $token = JWT::encode($params, Env::get('app.app_key', 'niucloud456$%^')); - $cache_token = Cache::get("token_" . $params['jti']); + $cache_token = Cache::store("jwt")->get("token_" . $params['jti']) ?: Cache::get("token_" . $params['jti']); $cache_token_arr = $cache_token ?: []; // if(!empty($cache_token)) // { @@ -55,7 +55,7 @@ class TokenAuth // $cache_token_arr[] = $token; // } $cache_token_arr[] = $token; - Cache::tag("token")->set("token_" . $params['jti'], $cache_token_arr); + Cache::store("jwt")->tag("token")->set("token_" . $params['jti'], $cache_token_arr); return compact('token', 'params'); } @@ -74,7 +74,8 @@ class TokenAuth if (explode("_", $token_info['jti'])[1] != $type) { return []; } - if (!empty($token_info) && !in_array($token, Cache::get('token_' . $token_info['jti'], []))) { + $token_cache = Cache::store("jwt")->get("token_" . $token_info['jti']) ?: Cache::get("token_" . $token_info['jti'], []); + if (!empty($token_info) && !in_array($token, $token_cache)) { return []; } return $token_info; @@ -93,16 +94,16 @@ class TokenAuth public static function clearToken(int $id, string $type, ?string $token = '') { if (!empty($token)) { - $token_cache = Cache::get("token_" . $id . "_" . $type, []); + $token_cache = Cache::store("jwt")->get("token_" . $id . "_" . $type) ?: Cache::get("token_" . $id . "_" . $type, []); //todo 也可以通过修改过期时间来实现 if (!empty($token_cache)) { if (($key = array_search($token, $token_cache)) !== false) { array_splice($token_cache, $key, 1); } - Cache::set("token_" . $id . "_" . $type, $token_cache); + Cache::store("jwt")->set("token_" . $id . "_" . $type, $token_cache); } } else { - Cache::set("token_" . $id . "_" . $type, []); + Cache::store("jwt")->set("token_" . $id . "_" . $type, []); } return success(); }