This commit is contained in:
全栈小学生 2026-03-20 15:59:18 +08:00
parent 1bc4217bef
commit 504b4c96a8
90 changed files with 1390 additions and 687 deletions

View File

@ -34,7 +34,7 @@ class Addon extends BaseAdminController
*/
public function init()
{
return success((new CoreAddonService())->getInitList());
return success(( new CoreAddonService() )->getInitList());
}
/**
@ -43,7 +43,7 @@ class Addon extends BaseAdminController
*/
public function getLocalAddonList()
{
return success((new CoreAddonService())->getLocalAddonList());
return success(( new CoreAddonService() )->getLocalAddonList());
}
/**
@ -53,7 +53,7 @@ class Addon extends BaseAdminController
*/
public function install($addon)
{
return success((new AddonService())->install($addon));
return success(( new AddonService() )->install($addon));
}
/**
@ -64,7 +64,7 @@ class Addon extends BaseAdminController
*/
public function cloudInstall($addon)
{
return success(data:(new AddonService())->cloudInstall($addon));
return success(data: ( new AddonService() )->cloudInstall($addon));
}
/**
@ -72,8 +72,9 @@ class Addon extends BaseAdminController
* @description 获取安装任务
* @return Response
*/
public function getInstallTask() {
return success(data:(new AddonService())->getInstallTask());
public function getInstallTask()
{
return success(data: ( new AddonService() )->getInstallTask());
}
/**
@ -82,8 +83,9 @@ class Addon extends BaseAdminController
* @param $addon
* @return mixed
*/
public function cloudInstallLog($addon) {
return success(data:(new AddonService())->cloudInstallLog($addon));
public function cloudInstallLog($addon)
{
return success(data: ( new AddonService() )->cloudInstallLog($addon));
}
/**
@ -94,7 +96,7 @@ class Addon extends BaseAdminController
*/
public function installCheck($addon)
{
return success(data:(new AddonService())->installCheck($addon));
return success(data: ( new AddonService() )->installCheck($addon));
}
/**
@ -105,7 +107,7 @@ class Addon extends BaseAdminController
*/
public function cancleInstall($addon)
{
return success(data:(new AddonService())->cancleInstall($addon));
return success(data: ( new AddonService() )->cancleInstall($addon));
}
/**
@ -115,7 +117,7 @@ class Addon extends BaseAdminController
*/
public function uninstall($addon)
{
(new AddonService())->uninstall($addon);
( new AddonService() )->uninstall($addon);
return success('ADDON_UNINSTALL_SUCCESS');
}
@ -127,7 +129,7 @@ class Addon extends BaseAdminController
*/
public function uninstallCheck($addon)
{
return success(data:(new AddonService())->uninstallCheck($addon));
return success(data: ( new AddonService() )->uninstallCheck($addon));
}
/**
@ -138,9 +140,9 @@ class Addon extends BaseAdminController
public function lists()
{
$data = $this->request->params([
['title', ''],
[ 'title', '' ],
]);
return success((new AddonService())->getPage($data));
return success(( new AddonService() )->getPage($data));
}
/**
@ -151,7 +153,7 @@ class Addon extends BaseAdminController
*/
public function info(int $id)
{
return success((new AddonService())->getInfo($id));
return success(( new AddonService() )->getInfo($id));
}
/**
@ -163,7 +165,7 @@ class Addon extends BaseAdminController
*/
public function setStatus(int $id, int $status)
{
(new AddonService())->setStatus($id, $status);
( new AddonService() )->setStatus($id, $status);
return success('SET_SUCCESS');
}
@ -173,11 +175,12 @@ class Addon extends BaseAdminController
* @param $addon
* @return Response
*/
public function download($addon){
public function download($addon)
{
$data = $this->request->params([
['version', '']
[ 'version', '' ]
]);
(new AddonService())->download($addon, $data['version']);
( new AddonService() )->download($addon, $data[ 'version' ]);
return success('DOWNLOAD_SUCCESS');
}
@ -186,8 +189,9 @@ class Addon extends BaseAdminController
* @description 查询已安装插件
* @return Response
*/
public function getInstallList(){
return success(data:(new AddonService())->getInstallList());
public function getInstallList()
{
return success(data: ( new AddonService() )->getInstallList());
}
/**
@ -196,7 +200,7 @@ class Addon extends BaseAdminController
*/
public function getAddonList()
{
return success((new CoreAddonService())->getInstallAddonList());
return success(( new CoreAddonService() )->getInstallAddonList());
}
/**
@ -204,7 +208,8 @@ class Addon extends BaseAdminController
* @description 插件类型
* @return Response
*/
public function getType(){
public function getType()
{
return success(AddonDict::getType());
}
@ -214,32 +219,23 @@ class Addon extends BaseAdminController
* @param $addon
* @return Response
*/
public function upgrade($addon = ''){
return success('DOWNLOAD_SUCCESS', (new AddonService())->upgrade($addon));
}
public function showApp()
public function upgrade($addon = '')
{
return success(data:(new AddonService())->getShowAppTools());
return success('DOWNLOAD_SUCCESS', ( new AddonService() )->upgrade($addon));
}
public function showMarketing()
{
return success(( new AddonService() )->getShowMarketingTools());
}
/**
* 统一展示 安装的插件 应用 营销工具等。。
* @return Response
*/
public function showCustomer()
{
return success((new AddonService())->showCustomer());
return success(( new AddonService() )->showCustomer());
}
public function getSpecialMenuList()
{
return success('SUCCESS', (new AddonService())->getSpecialMenuList());
return success('SUCCESS', ( new AddonService() )->getSpecialMenuList());
}
@ -249,7 +245,7 @@ class Addon extends BaseAdminController
*/
public function getIndexAddonLabelList()
{
return success((new CoreAddonService())->getIndexAddonLabelList());
return success(( new CoreAddonService() )->getIndexAddonLabelList());
}
/**
@ -260,9 +256,9 @@ class Addon extends BaseAdminController
public function getIndexAddonList()
{
$data = $this->request->params([
['label_id', ''],
[ 'label_id', '' ],
]);
return success((new CoreAddonService())->getIndexAddonList($data['label_id']));
return success(( new CoreAddonService() )->getIndexAddonList($data[ 'label_id' ]));
}
}

View File

@ -208,23 +208,6 @@ class NiuSms extends BaseAdminController
return success($data);
}
/**
* 忘记密码
* @description 忘记密码
* @param $username
* @return Response
*/
public function forgetPassword($username)
{
$params = $this->request->params([
['mobile', ''],
['code', ''],
['key', ''],
]);
$data = (new NiuSmsService())->forgetPassword($username, $params);
return success($data);
}
/**
* 签名列表
* @description 签名列表
@ -281,6 +264,15 @@ class NiuSms extends BaseAdminController
['signType', ""],
['imgUrl', ""],
['defaultSign', 0],
//新增字段
['bizLicenseUrl', ''],
['qccUrl', ''],
['tmnetUrl', ''],
['mobileIcpUrl', ''],
['telecomAppstoreUrl', ''],
['idcardFrontUrl', ''],
['idcardBackUrl', ''],
]);
(new NiuSmsService())->signCreate($username, $params);
return success("SUCCESS");

View File

@ -58,9 +58,9 @@ class Config extends BaseAdminController
[ "front_end_logo", "" ],
[ "front_end_icon", "" ],
[ "icon", "" ],
[ "meta_title", "" ],
[ "meta_desc", "" ],
[ "meta_keyword", "" ],
[ "meta_title", "" ], // Meta 标题
[ "meta_desc", "" ], // Meta 描述
[ "meta_keyword", "" ], // Meta 关键字
]);
( new ConfigService() )->setWebSite($data);

View File

@ -128,7 +128,6 @@ class Ueditor extends BaseAdminController
'title' => $upload_res['url'],
'original' => $upload_res['url'],
], 'json', 200);
break;
case 'video':
$upload_res = $upload_service->video($data['file']);
return Response::create([
@ -137,7 +136,6 @@ class Ueditor extends BaseAdminController
'title' => $upload_res['url'],
'original' => $upload_res['url'],
], 'json', 200);
break;
}
}
}

View File

@ -36,6 +36,8 @@ class User extends BaseAdminController
['realname', ''],
['role', ''],
['create_time', []],
['real_name', ''],
['last_time', []]
]);
$list = (new UserService())->getPage($data);
@ -129,6 +131,7 @@ class User extends BaseAdminController
['mobile', ''],
['real_name', ''],
['head_img', ''],
['role_ids', []],
]);
(new UserService())->edit($uid, $data);
return success();
@ -144,67 +147,4 @@ class User extends BaseAdminController
(new UserService())->del($uid);
return success("DELETE_SUCCESS");
}
/**
* 获取用户站点创建限制
* @description 获取用户站点创建限制
* @param $uid
* @return Response
*/
public function getUserCreateSiteLimit($uid){
return success(data:(new UserService())->getUserCreateSiteLimit($uid));
}
/**
* 获取用户站点创建限制
* @description 获取用户站点创建限制
* @param $id
* @return Response
*/
public function getUserCreateSiteLimitInfo($id){
return success(data:(new UserService())->getUserCreateSiteLimitInfo($id));
}
/**
* 添加用户站点创建限制
* @description 添加用户站点创建限制
* @param $uid
* @return Response
*/
public function addUserCreateSiteLimit($uid){
$data = $this->request->params([
['uid', 0],
['group_id', 0],
['num', 1],
['month', 1],
]);
(new UserService())->addUserCreateSiteLimit($data);
return success('SUCCESS');
}
/**
* 编辑用户站点创建限制
* @description 编辑用户站点创建限制
* @param $id
* @return Response
*/
public function editUserCreateSiteLimit($id){
$data = $this->request->params([
['num', 1],
['month', 1],
]);
(new UserService())->editUserCreateSiteLimit($id, $data);
return success('SUCCESS');
}
/**
* 删除用户站点创建限制
* @description 删除用户站点创建限制
* @param $id
* @return Response
*/
public function delUserCreateSiteLimit($id){
(new UserService())->delUserCreateSiteLimit($id);
return success('SUCCESS');
}
}

View File

@ -92,7 +92,5 @@ Route::group(function () {
Route::group(function () {
//获取已安装插件列表
Route::get('addon/list/install', 'addon.Addon/getInstallList');
Route::get('addon/list/showApp', 'addon.Addon/showApp');
Route::get('showMarketing', 'addon.Addon/showMarketing');
});

View File

@ -58,7 +58,6 @@ Route::group('notice', function () {
Route::post('login', 'notice.NiuSms/loginAccount');
Route::post('edit/:username', 'notice.NiuSms/editAccount');
Route::post('reset/password/:username', 'notice.NiuSms/resetPassword');
Route::post('forget/password/:username', 'notice.NiuSms/forgetPassword');
Route::get('send_list/:username', 'notice.NiuSms/accountSendList');
Route::get('info/:username', 'notice.NiuSms/accountInfo');
});

View File

@ -82,8 +82,6 @@ Route::group('sys', function() {
//地图设置
Route::put('config/map', 'sys.Config/setMap');
//地图设置
Route::get('config/map', 'sys.Config/getMap');
//登录注册设置
Route::get('config/login', 'login.Config/getConfig');
@ -343,6 +341,15 @@ Route::group('sys', function() {
AdminLog::class
]);
//系统环境(不效验登录状态)
Route::group('sys', function() {
//地图设置
Route::get('config/map', 'sys.Config/getMap');
})->middleware([
AdminCheckToken::class,
AdminLog::class
]);
//系统环境(不效验登录状态)
Route::group('sys', function() {
Route::get('web/website', 'sys.Config/getWebsite');

View File

@ -1,28 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\controller;
use core\base\BaseController;
use think\facade\App;
class Index extends BaseController
{
public function index()
{
return '<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} a{color:#2E5CD5;cursor: pointer;text-decoration: none} a:hover{text-decoration:underline; } body{ background: #fff; font-family: "Century Gothic","Microsoft yahei"; color: #333;font-size:18px;} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.6em; font-size: 42px }</style><div style="padding: 24px 48px;"> <h1>:) </h1><p> ThinkPHP V' . App::version() . '<br/><span style="font-size:30px;">16载初心不改 - 你值得信赖的PHP框架</span></p><span style="font-size:25px;">[ V6.0 版本由 <a href="https://www.yisu.com/" target="yisu">亿速云</a> 独家赞助发布 ]</span></div><script type="text/javascript" src="https://e.topthink.com/Public/static/client.js"></script><think id="ee9b1aa918103c4fc"></think>';
}
public function hello($name = 'ThinkPHP6')
{
return 'hello,' . $name;
}
}

View File

@ -68,4 +68,38 @@ class Upload extends BaseApiController
$base64_service = new Base64Service();
return success($base64_service->image($data['content']));
}
public function config()
{
return success([
'upload_max_filesize' => [
'unit' => 'KB',
'num'=>$this->convertPhpSizeToBytes(ini_get('upload_max_filesize'))/1024
],
]);
}
private function convertPhpSizeToBytes($size_str) {
// 去除字符串两端的空格,统一转为大写(方便判断单位)
$size_str = trim(strtoupper($size_str));
// 如果是空值或纯数字(无单位),默认单位为字节
if (!preg_match('/^(\d+(\.\d+)?)([BKMGTP]B?)?$/', $size_str, $matches)) {
return (int)$size_str;
}
// 提取数值和单位
$size = (float)$matches[1];
$unit = isset($matches[3]) ? $matches[3] : 'B'; // 默认单位为B
// 根据单位转换为字节
switch ($unit) {
case 'TB': case 'T': $size *= 1024;
case 'GB': case 'G': $size *= 1024;
case 'MB': case 'M': $size *= 1024;
case 'KB': case 'K': $size *= 1024;
case 'B': default: break; // 字节无需转换
}
return (int)$size;
}
}

View File

@ -46,7 +46,7 @@ class ApiCheckToken
if (!empty($token_info)) {
$request->memberId($token_info[ 'member_id' ]);
}
//校验会员和站点
//校验会员
( new AuthService() )->checkMember($request);
} catch (AuthException $e) {
//是否将登录错误抛出

View File

@ -32,6 +32,7 @@ Route::group('file', function() {
*/
Route::group('file', function() {
//上传图片
Route::get('config', 'upload.Upload/config');
Route::post('image', 'upload.Upload/image');
//上传视频
Route::post('video', 'upload.Upload/video');

View File

@ -17,7 +17,6 @@ use think\facade\Route;
//支付异步回调
Route::any('pay/notify/:channel/:type/:action', 'pay.Pay/notify')
->middleware(ApiChannel::class)
->middleware(ApiCheckToken::class)
->middleware(ApiLog::class);
/**
* 路由

View File

@ -1,7 +1,7 @@
<?php
declare (strict_types=1);
namespace app\command\Addon;
namespace app\command\addon;
use app\service\core\addon\CoreAddonInstallService;
use Exception;

View File

@ -1,7 +1,7 @@
<?php
declare (strict_types=1);
namespace app\command\Addon;
namespace app\command\addon;
use think\console\Command;
use think\console\Input;

View File

@ -9,7 +9,7 @@ use think\console\Command;
use think\console\Input;
use think\console\Output;
class refreshAreaCommand extends Command
class RefreshAreaCommand extends Command
{
protected function configure()
{

View File

@ -1,6 +1,9 @@
<?php
use Location\Coordinate;
use Location\Distance\Vincenty;
use think\Container;
use think\exception\InvalidArgumentException;
use think\Response;
use think\facade\Lang;
use think\facade\Queue;
@ -756,7 +759,11 @@ function cache_remember(string $name = null, $value = '', $tag = null, $options
if (is_null($tag)) {
Cache::set($name, $value, $options['expire'] ?? null);
} else {
Cache::tag($tag)->set($name, $value, $options['expire'] ?? null);
try {
Cache::tag($tag)->set($name, $value, $options['expire'] ?? null);
} catch (InvalidArgumentException $e) {
Cache::tag($tag)->set($name, $value, $options['expire'] ?? null);
}
}
return $value;
@ -897,7 +904,7 @@ function file_copy(string $source_file, string $to_file)
function qrcode($url, $page, $data, $dir = '', $channel = 'h5', $style = ['is_transparent' => true], $outfile = true)
{
if ($outfile) {
$dir = $dir ?: 'upload' . '/' . 'qrcode' ;//二维码默认存储位置
$dir = $dir ?: 'upload' . '/' . 'qrcode';//二维码默认存储位置
if (!is_dir($dir) && !mkdir($dir, 0777, true) && !is_dir($dir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
}
@ -954,7 +961,7 @@ function is_url($string)
* 获取站点插件
* @return array
*/
function get_install_addons() : array
function get_install_addons(): array
{
$addons = Cache::get("local_install_addons");
return is_null($addons) ? [] : $addons;
@ -1151,3 +1158,18 @@ function downloadImage($img_url, $file_name)
fclose($fp);
return true;
}
/**
* 获取地图两坐标点之间距离
* @param $lat1
* @param $lng1
* @param $lat2
* @param $lng2
* @return float
*/
function get_map_distance($lat1, $lng1, $lat2, $lng2)
{
$location = new Coordinate($lat1, $lng1);
$distance = ( new Vincenty() )->getDistance($location, new Coordinate((float) $lat2, (float) $lng2));
return round($distance/1000, 3);
}

View File

@ -37,52 +37,67 @@ class CommonActiveDict
self::IMPULSE_BUY => [
'name' => get_lang('common_active_short.impulse_buy_short'),
'active_name' => get_lang('common_active_short.impulse_buy_name'),
'bg_color' => "#FF7700"
'bg_color' => "#FF7700",
'jump_url'=>'/admin/shop_impulse_buy/list',/////
'is_need_params'=>1
],
self::GIFTCARD => [
'name' => get_lang('common_active_short.gift_card_short'),
'active_name' => get_lang('common_active_short.gift_card_name'),
'bg_color' => '#F00000'
'bg_color' => '#F00000',
'jump_url'=>'/admin/shop_giftcard/giftcard/list',/////
'is_need_params'=>1
],
self::DISCOUNT => [
'name' => get_lang('common_active_short.discount_short'),
'active_name' => get_lang('common_active_short.discount_name'),
'bg_color' => '#FFA322'
'bg_color' => '#FFA322',
'jump_url'=>'/admin/shop/marketing/discount/list',/////
'is_need_params'=>1
],
self::EXCHANGE => [
'name' => get_lang('common_active_short.exchange_short'),
'active_name' => get_lang('common_active_short.exchange_name'),
'bg_color' => '#00C441'
'bg_color' => '#00C441',
'jump_url'=>'/admin/shop/marketing/exchange/goods_list',/////
'is_need_params'=>1
],
self::MANJIANSONG => [
'name' => get_lang('common_active_short.manjiansong_short'),
'active_name' => get_lang('common_active_short.manjiansong_name'),
'bg_color' => '#249DE9'
'bg_color' => '#249DE9',
'jump_url'=>'/admin/shop/marketing/manjian/list',/////
'is_need_params'=>1
],
self::NEWCOMER_DISCOUNT => [
'name' => get_lang('common_active_short.newcomer_discount_short'),
'active_name' => get_lang('common_active_short.newcomer_discount_name'),
'bg_color' => '#BB27FF'
'bg_color' => '#BB27FF',
'jump_url'=>'/admin/shop/marketing/newcomer/config'
],
self::SECKILL => [
'name' => get_lang('common_active_short.seckill_short'),
'active_name' => get_lang('common_active_short.seckill_name'),
'bg_color' => '#F606CA'
'bg_color' => '#F606CA',
'jump_url'=>'/admin/seckill/active/list'
],
self::PINTUAN => [
'name' => get_lang('common_active_short.pintuan_short'),
'active_name' => get_lang('common_active_short.pintuan_name'),
'bg_color' => '#FF1C77'
'bg_color' => '#FF1C77',
'jump_url'=>'/admin/pintuan/active/list'
],
self::RELAY => [
'name' => get_lang('common_active_short.relay_short'),
'active_name' => get_lang('common_active_short.relay_name'),
'bg_color' => '#0EB108'
'bg_color' => '#0EB108',
'jump_url'=>'/admin/relay/active/list'
],
self::FRIEND_HELP => [
'name' => get_lang('common_active_short.friend_help_short'),
'active_name' => get_lang('common_active_short.friend_help_name'),
'bg_color' => '#F20C8A'
'bg_color' => '#F20C8A',
'jump_url'=>'/admin/friend_help/active/list'
],
];
return !empty($active) ? $data[$active] ?? [] : $data;

View File

@ -189,5 +189,17 @@ return [
//是否累增
'is_change_get' => 0,
],
],
MemberAccountTypeDict::GROWTH => [
//调整
'member_register' => [
//名称
'name' => get_lang('dict_member.account_point_member_register'),
//是否增加
'inc' => 1,
//是否减少
'dec' => 0,
],
]
];

View File

@ -1042,7 +1042,7 @@ return [
'children' => [
[
'menu_name' => '转账',
'menu_key' => 'cash_out_transfer',
'menu_key' => 'member_refund_transfer',
'menu_short_name' => '转账',
'menu_type' => '2',
'icon' => '',
@ -1115,7 +1115,7 @@ return [
'router_path' => 'marketing/verify/index',
'view_path' => '',
'methods' => 'get',
'sort' => '48',
'sort' => '30',
'status' => '1',
'is_show' => '1',
'children' => [
@ -1232,7 +1232,7 @@ return [
'router_path' => 'marketing/sign/config',
'view_path' => '',
'methods' => 'get',
'sort' => '30',
'sort' => '91',
'status' => '1',
'is_show' => '1',
'children' => [
@ -2812,7 +2812,7 @@ return [
'router_path' => '',
'view_path' => '',
'methods' => '',
'sort' => '0',
'sort' => '29',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'diy_form',
@ -2862,7 +2862,7 @@ return [
'router_path' => '',
'view_path' => '',
'methods' => '',
'sort' => '0',
'sort' => '27',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'setting_export',
@ -2912,7 +2912,7 @@ return [
'router_path' => '',
'view_path' => '',
'methods' => '',
'sort' => '0',
'sort' => '28',
'status' => '1',
'is_show' => '1',
'menu_attr' => 'printer_management',

View File

@ -141,12 +141,12 @@ class NoticeTypeDict
}
const PARAMS_TYPE_VALID_CODE = 'valid_code';
const PARAMS_TYPE_MOBILE_NUMBER = 'mobile_number';
const PARAMS_TYPE_OTHER_NUMBER = 'other_number';
const PARAMS_TYPE_AMOUNT = 'amount';
const PARAMS_TYPE_DATE = 'date';
const PARAMS_TYPE_CHINESE = 'chinese';
const PARAMS_TYPE_OTHERS = 'others';
const PARAMS_TYPE_INT_NUMBER = 'int_number';
public static function getApiParamsType()
{
return [
@ -159,20 +159,12 @@ class NoticeTypeDict
'max'=>6
],
[
'name' => '手机号',
'type' => self::PARAMS_TYPE_MOBILE_NUMBER,
'desc' => '1-15位纯数字',
'rule' => '/^\d$/',
'min'=>1,
'max'=>15
],
[
'name' => '其他号码',
'name' => '其他号码(手机号)',
'type' => self::PARAMS_TYPE_OTHER_NUMBER,
'desc' => '1-32位字母+数字组合',
'desc' => '1-20位字母+数字组合',
'rule'=>'/^[a-zA-Z0-9]$/',
'min'=>1,
'max'=>32
'max'=>20
],
[
'name' => '金额',
@ -189,18 +181,26 @@ class NoticeTypeDict
[
'name' => '中文',
'type' => self::PARAMS_TYPE_CHINESE,
'desc' => '1-32中文支持中文园括号()',
'rule' => '/^[\p{Han}()]$/u',
'desc' => '1-15中文支持中文圆括号()',
'rule' => '/^[\p{Han}]+$/u',
'min'=>1,
'max'=>32
'max'=>15
],
[
'name' => '纯数字',
'type' => self::PARAMS_TYPE_INT_NUMBER,
'desc' => ' 1-10个数字',
'rule' => '/^\d$/',
'min'=>1,
'max'=>10
],
[
'name' => '其他',
'type' => self::PARAMS_TYPE_OTHERS,
'desc' => ' 1-35个中文数字字母组合支持中文符号和空格',
'desc' => ' 1-30个中文数字字母组合,支持中文符号。',
'rule' => '/^[\p{Han}\p{N}\p{L}\p{P}\p{S}\s]$/u',
'min'=>1,
'max'=>35
'max'=>30
],
];
}

View File

@ -39,6 +39,10 @@ class PayChannelDict
'key' => $k,
'pay_type' => $pay_type
];
if (in_array($k,[ChannelDict::WEAPP,ChannelDict::WECHAT])){
unset($temp_pay_type[ PayDict::ALIPAY ]);
$list[ $k ][ 'pay_type' ] = $temp_pay_type;
}
// PC端暂不支持 帮付
if ($k == ChannelDict::PC) {
unset($temp_pay_type[ PayDict::FRIENDSPAY ]);

View File

@ -13,9 +13,10 @@ return [
],
'class' => 'app\job\schedule\AutoClearScheduleLog',
'function' => ''
], [
],
[
'key' => 'auto_clear_poster_qrcode',
'name' => '定时清理海报及二维码数据',
'name' => '定时清理一周前的海报及二维码数据',
'desc' => '',
'time' => [
'type' => 'day',
@ -26,6 +27,19 @@ return [
'class' => 'app\job\schedule\AutoClearPosterAndQrcode',
'function' => ''
],
[
'key' => 'auto_clear_system_log',
'name' => '定时清理一周前的业务日志',
'desc' => '',
'time' => [
'type' => 'day',
'day' => 1,
'hour' => 1,
'min' => 1
],
'class' => 'app\job\schedule\AutoClearLogFiles',
'function' => ''
],
[
'key' => 'transfer_check_finish',
'name' => '检验在线转账是否处理完毕',
@ -49,7 +63,7 @@ return [
],
'class' => 'app\job\upgrade\AutoClearUpgradeRecords',
'function' => ''
],[
], [
'key' => 'auto_clear_user_log',
'name' => '定时清理用户操作日志',
'desc' => '',
@ -61,5 +75,5 @@ return [
],
'class' => 'app\job\sys\ClearUserLog',
'function' => ''
]
],
];

View File

@ -103,7 +103,7 @@ class Index extends BaseInstall
$this->assign("name", $name);
$this->assign("verison", $verison);
$this->assign("dirs_list", $dirs_list);
if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir) {
if ($verison && $pdo && $curl && $openssl && $gd && $fileinfo && $is_dir && $imagick) {
$continue = true;
} else {
$continue = false;
@ -170,6 +170,15 @@ class Index extends BaseInstall
$conn = @mysqli_connect($dbhost, $dbuser, $dbpwd);
if ($conn) {
$sql_mode_result = mysqli_query($conn, "SELECT @@global.sql_mode");
$sql_mode = strtolower($sql_mode_result->fetch_array()[0] ?? '');
if (strpos($sql_mode, 'only_full_group_by') !== false) {
return fail([
"status" => -2,
"message" => "请将mysql配置sql_mode字段中的值“ONLY_FULL_GROUP_BY”去掉"
]);
}
if (empty($dbname)) {
$result = [
"status" => 1,
@ -390,6 +399,7 @@ class Index extends BaseInstall
$this->setSuccessLog([ '初始化', 'success' ]);
Cache::set('install_status', 2);//成功
// Cache::tag(MenuService::$cache_tag_name)->clear();
return success();
} catch (Exception $e) {
$this->setSuccessLog([ '安装失败' . $e->getMessage(), 'error' ]);

View File

@ -23,6 +23,7 @@ CREATE TABLE `activity_exchange_code`
`activity_id` INT(11) NOT NULL DEFAULT 0 COMMENT '活动ID',
`type` VARCHAR(20) NOT NULL DEFAULT '' COMMENT '类型 例seckill_goods-秒杀商品',
`type_id` INT(11) NOT NULL DEFAULT 0 COMMENT '类型对应id 秒杀商品id',
`type_item_id` int NOT NULL DEFAULT 0 COMMENT '规格id',
`expire_time` INT(11) NOT NULL DEFAULT 0 COMMENT '过期时间 0-不过期',
`member_id` INT(11) NOT NULL DEFAULT 0 COMMENT '领取会员',
`received_time` INT(11) NOT NULL DEFAULT 0 COMMENT '领取时间',
@ -366,6 +367,7 @@ CREATE TABLE `member`
`member_label` varchar(255) NOT NULL DEFAULT '' COMMENT '会员标签',
`wx_openid` varchar(255) NOT NULL DEFAULT '' COMMENT '微信用户openid',
`weapp_openid` varchar(255) NOT NULL DEFAULT '' COMMENT '微信小程序openid',
`wxapp_openid` varchar(255) NOT NULL DEFAULT '' COMMENT '微信移动应用openid',
`wx_unionid` varchar(255) NOT NULL DEFAULT '' COMMENT '微信unionid',
`ali_openid` varchar(255) NOT NULL DEFAULT '' COMMENT '支付宝账户id',
`douyin_openid` varchar(255) NOT NULL DEFAULT '' COMMENT '抖音小程序openid',
@ -4957,7 +4959,6 @@ DROP TABLE IF EXISTS `app_version`;
CREATE TABLE `app_version`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`site_id` INT(11) NOT NULL DEFAULT 0 COMMENT '站点id',
`version_code` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '版本号',
`version_name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '版本名称',
`version_desc` VARCHAR(1500) NOT NULL DEFAULT '' COMMENT '版本描述',
@ -4974,15 +4975,3 @@ CREATE TABLE `app_version`
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'app版本管理' ROW_FORMAT = Dynamic;
ALTER TABLE activity_exchange_code
CHANGE COLUMN activity_type activity_type VARCHAR(20) NOT NULL DEFAULT '' COMMENT '例seckill-秒杀活动';
ALTER TABLE activity_exchange_code
ADD COLUMN type_item_id INT(11) NOT NULL DEFAULT 0 COMMENT '规格id';
ALTER TABLE member
ADD COLUMN wxapp_openid VARCHAR(255) NOT NULL DEFAULT '' COMMENT '微信移动应用openid';
ALTER TABLE member
MODIFY wxapp_openid VARCHAR(255) NOT NULL DEFAULT '' COMMENT '微信移动应用openid' AFTER weapp_openid;

View File

@ -56,6 +56,12 @@
<div style='float:left' class="mysql-message" id='dbpwdsta'></div>
</td>
</tr>
<tr class="sql-mode-error" style="display: none">
<td></td>
<td>
<div class="message" style="color: red;">请将mysql配置sql_mode字段中的值“ONLY_FULL_GROUP_BY”去掉</div>
</td>
</tr>
<tr>
<td class="onetd"><span class="required">*</span>数据库名称:</td>
<td>
@ -224,7 +230,14 @@
type: "post",
dataType: 'json',
success: function(data){
inputBoxPointer('dbpwdsta').innerHTML = data.data.message;
if (data.data.status == -2) {
inputBoxPointer('dbpwdsta').innerHTML = '数据库连接成功'
$('.sql-mode-error .message').text(data.data.message)
$('.sql-mode-error').show()
} else {
$('.sql-mode-error').hide()
inputBoxPointer('dbpwdsta').innerHTML = data.data.message;
}
is_existdb = data.data.status;
message = data.data.message;
}

View File

@ -0,0 +1,163 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\job\schedule;
use core\base\BaseJob;
use think\facade\Log;
/**
* 队列异步调用定时任务 - 清理日志文件
*/
class AutoClearLogFiles extends BaseJob
{
public function doJob()
{
Log::write('AutoClearLogFiles 定时清理日志文件开始 ' . date('Y-m-d H:i:s'));
try {
// 定义需要清理的日志目录数组
$log_dirs = [
'log',
'adminapi/log',
'api/log'
];
// 遍历每个日志目录进行清理
foreach ($log_dirs as $dir) {
$abs_dir = runtime_path($dir);
// runtime_path补充根目录拼接方式
if (!is_dir($abs_dir)) {
$abs_dir = root_path() . $dir;
}
$this->clearDirectory($abs_dir);
}
Log::write('AutoClearLogFiles 定时清理日志文件完成 ' . date('Y-m-d H:i:s'));
return true;
} catch (\Exception $e) {
Log::write('AutoClearLogFiles 定时清除异常: ' . $e->getMessage() . ' 位置: ' . $e->getFile() . ':' . $e->getLine() . $e->getTraceAsString());
return false;
}
}
/**
* 清空指定目录下一周前的日志文件和空的子目录
*
* @param string $directory 目录路径
* @param bool $preserveDirectory 是否保留根目录(默认保留)
* @return bool 是否成功执行
*/
function clearDirectory(string $directory, bool $preserveDirectory = true): bool
{
// 规范化目录路径统一使用DIRECTORY_SEPARATOR
$directory = rtrim(realpath($directory), DIRECTORY_SEPARATOR);
Log::write('AutoClearLogFiles开始清理目录: ' . $directory);
// 检查目录是否存在
if (!is_dir($directory)) {
Log::write('AutoClearLogFiles目录不存在或不是有效目录: ' . $directory);
return false;
}
// 计算一周前的时间戳7天 = 7*24*60*60 = 604800秒
$one_week_ago = time() - 604800;
// 打开目录
$handle = opendir($directory);
if (!$handle) {
Log::write('AutoClearLogFiles无法打开目录: ' . $directory);
return false;
}
// 遍历目录内容
while (($entry = readdir($handle)) !== false) {
// 跳过当前目录和上级目录
if ($entry === '.' || $entry === '..') {
continue;
}
// 使用DIRECTORY_SEPARATOR确保路径分隔符正确
$path = $directory . DIRECTORY_SEPARATOR . $entry;
// 递归处理子目录
if (is_dir($path)) {
// 递归清理子目录(只删一周前文件,保留子目录本身)
if (!$this->clearDirectory($path, true)) {
Log::write('AutoClearLogFiles递归清理子目录失败: ' . $path);
closedir($handle);
return false;
}
// 检查子目录是否为空,若为空则删除
$isEmpty = true;
$sub_handle = opendir($path);
while (($sub_entry = readdir($sub_handle)) !== false) {
if ($sub_entry !== '.' && $sub_entry !== '..') {
$isEmpty = false;
break;
}
}
closedir($sub_handle);
if ($isEmpty && !$preserveDirectory) {
if (!rmdir($path)) {
Log::write('AutoClearLogFiles删除空目录失败: ' . $path);
} else {
Log::write('AutoClearLogFiles已删除空目录: ' . $path);
}
}
} else {
// 过滤日志文件(可选:只清理.log后缀的文件避免误删其他类型文件
$file_ext = pathinfo($path, PATHINFO_EXTENSION);
if ($file_ext !== 'log') {
Log::write('AutoClearLogFiles跳过非日志文件: ' . $path);
continue;
}
// 获取文件的最后修改时间
$file_time = filemtime($path);
// 校验:文件时间有效 且 早于/等于一周前
if ($file_time !== false && $file_time <= $one_week_ago) {
// 删除一周前的日志文件
if (!unlink($path)) {
Log::write('AutoClearLogFiles删除日志文件失败: ' . $path);
closedir($handle);
return false;
}
Log::write('AutoClearLogFiles已删除一周前的日志文件: ' . $path);
} else {
// 跳过近期日志文件
Log::write('AutoClearLogFiles跳过近期日志文件: ' . $path);
}
}
}
// 关闭目录句柄
closedir($handle);
// 根目录是否删除(默认保留,避免目录丢失)
if (!$preserveDirectory) {
Log::write('AutoClearLogFiles准备删除根目录: ' . $directory);
if (!rmdir($directory)) {
Log::write('AutoClearLogFiles删除根目录失败: ' . $directory);
return false;
}
Log::write('AutoClearLogFiles成功删除根目录: ' . $directory);
} else {
Log::write('AutoClearLogFiles保留根目录: ' . $directory);
}
return true;
}
}

View File

@ -24,16 +24,14 @@ class AutoClearPosterAndQrcode extends BaseJob
{
Log::write('AutoClearPosterAndQrcode 定时清除 二维码及海报数据开始' . date('Y-m-d H:i:s'));
try {
// 清理海报目录
$dir = 'upload/poster';
$dir = public_path($dir);
$res = $this->clearDirectory($dir);
// 清理二维码目录
$qrcode_dir = 'upload/qrcode';
$qrcode_dir = public_path($qrcode_dir);
$res = $this->clearDirectory($qrcode_dir);
$dirs = [
'upload/poster',
'upload/qrcode',
];
foreach ($dirs as $dir) {
$dir = public_path($dir);
$res = $this->clearDirectory($dir);
}
return true;
} catch (\Exception $e) {
Log::write('AutoClearPosterAndQrcode 定时清除异常: ' . $e->getMessage() . ' 位置: ' . $e->getFile() . ':' . $e->getLine() . $e->getTraceAsString());
@ -42,7 +40,7 @@ class AutoClearPosterAndQrcode extends BaseJob
}
/**
* 清空指定目录下所有文件和子目录
* 清空指定目录下一周前的文件和空的子目录
*
* @param string $directory 目录路径
* @param bool $preserveDirectory 是否保留根目录(默认保留)
@ -61,6 +59,9 @@ class AutoClearPosterAndQrcode extends BaseJob
return false;
}
// 计算一周前的时间戳7天 = 7*24*60*60 = 604800秒
$one_week_ago = time() - 604800;
// 打开目录
$handle = opendir($directory);
if (!$handle) {
@ -80,20 +81,47 @@ class AutoClearPosterAndQrcode extends BaseJob
// 递归处理子目录
if (is_dir($path)) {
// 递归清空子目录
if (!$this->clearDirectory($path, false)) {
// 递归清理子目录(只删一周前文件,保留子目录本身)
if (!$this->clearDirectory($path, true)) {
Log::write('AutoClearPosterAndQrcode递归清理子目录失败: ' . $path);
closedir($handle);
return false;
}
Log::write('AutoClearPosterAndQrcode已递归删除子目录: ' . $path);
// 子目录已经在递归调用中被删除,不需要再次删除
// 检查子目录是否为空,若为空则删除(可选逻辑,根据需求调整)
$isEmpty = true;
$sub_handle = opendir($path);
while (($sub_entry = readdir($sub_handle)) !== false) {
if ($sub_entry !== '.' && $sub_entry !== '..') {
$isEmpty = false;
break;
}
}
closedir($sub_handle);
if ($isEmpty && !$preserveDirectory) {
if (!rmdir($path)) {
Log::write('AutoClearPosterAndQrcode删除空目录失败: ' . $path);
} else {
Log::write('AutoClearPosterAndQrcode已删除空目录: ' . $path);
}
}
} else {
// 删除文件
if (!unlink($path)) {
Log::write('AutoClearPosterAndQrcode删除文件失败: ' . $path);
closedir($handle);
return false;
// 获取文件的创建/修改时间优先用修改时间filemtime更贴合业务
$file_time = filemtime($path);
// 校验:文件时间有效 且 早于一周前
if ($file_time !== false && $file_time <= $one_week_ago) {
// 删除一周前的文件
if (!unlink($path)) {
Log::write('AutoClearPosterAndQrcode删除文件失败: ' . $path);
closedir($handle);
return false;
}
Log::write('AutoClearPosterAndQrcode已删除一周前的文件: ' . $path);
} else {
// 跳过近期文件,记录日志(可选)
Log::write('AutoClearPosterAndQrcode跳过近期文件: ' . $path);
}
}
}
@ -101,7 +129,7 @@ class AutoClearPosterAndQrcode extends BaseJob
// 关闭目录句柄
closedir($handle);
// 是否删除根目录本身
// 根目录是否删除(默认保留,避免目录丢失)
if (!$preserveDirectory) {
Log::write('AutoClearPosterAndQrcode准备删除根目录: ' . $directory);
if (!rmdir($directory)) {
@ -115,6 +143,4 @@ class AutoClearPosterAndQrcode extends BaseJob
return true;
}
}

View File

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

View File

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

View File

@ -72,7 +72,7 @@ return [
'ATTACHMENT_GROUP_HAS_IMAGE' => '附件组中存在图片不允许删除',
'OSS_TYPE_NOT_EXIST' => '云存储类型不存在',
'URL_FILE_NOT_EXIST' => '获取不到网址指向的文件',
'PLEACE_SELECT_IMAGE' => '请选择要删除的图片',
'PLEASE_SELECT_IMAGE' => '请选择要删除的图片',
'UPLOAD_TYPE_ERROR' => '不是有效的上传类型',

View File

@ -67,6 +67,7 @@ return [
'CLOUD_BUILD_AUTH_CODE_NOT_FOUND' => '请先填写授权码',
'TASK_CYCLE_ERROR' => '任务周期填写错误',
'UPGRADE_TASK_EXIST' => '有正在执行的升级任务,可以展开正在升级的任务,也可以在开发>更新缓存中清除缓存重新开始升级',
'ZIP_ARCHIVE_NOT_EXIST' => '请先安装或启用zip扩展',
//登录注册重置账号....
'LOGIN_SUCCESS' => '登录成功',
@ -79,7 +80,6 @@ return [
'OLD_PASSWORD_ERROR' => '原始密码不正确',
'MOBILE_LOGIN_UNOPENED' => '手机号登录注册未开启',
'APP_TYPE_NOT_EXIST' => '无效的登录端口',
"USER_NOT_ALLOW_DEL" => "该用户是一些站点的管理员不允许删除",
"SUPER_ADMIN_NOT_ALLOW_DEL" => "超级管理员不允许删除",
//用户组权限
@ -112,7 +112,7 @@ return [
'ATTACHMENT_GROUP_HAS_IMAGE' => '附件组中存在图片不允许删除',
'OSS_TYPE_NOT_EXIST' => '云存储类型不存在',
'URL_FILE_NOT_EXIST' => '获取不到网址指向的文件',
'PLEACE_SELECT_IMAGE' => '请选择要删除的图片',
'PLEASE_SELECT_IMAGE' => '请选择要删除的图片',
'UPLOAD_TYPE_ERROR' => '不是有效的上传类型',
'OSS_FILE_URL_NOT_EXIST' => '远程资源文件地址不能为空',
'BASE_IMAGE_FILE_NOT_EXIST' => 'base图片资源不能为空',
@ -218,6 +218,7 @@ return [
'WEAPP_NOT_EXIST' => '微信小程序未配置完善',
'WEAPP_EMPOWER_NOT_EXIST' => '微信小程序授信信息不存在',
'WEAPP_EMPOWER_TEL_NOT_EXIST' => '微信小程序授信手机号不存在',
'CURR_SITE_IS_NOT_OPEN_SSL' => '微信小程序请求地址只支持https请先配置ssl',
'WECHAT_MINI_PROGRAM_CODE_GENERATION_FAILED' => '微信小程序码生成失败',
@ -329,8 +330,6 @@ return [
/********************************************************* 微信开放平台 **************************************/
'WECHAT_OPLATFORM_NOT_EXIST' => '未配置微信开放平台',
'WEAPP_EXIST' => '该小程序已经授权给其他站点',
'WECHAT_EXIST' => '该公众号已经授权给其他站点',
'NOT_YET_PRESENT_TEMPLATE_LIBRARY' => '平台尚未上传小程序到模板库',
'WEAPP_VERSION_NOT_EXIST' => '未获取到小程序版本提交记录',
'NOT_ALLOWED_CANCEL_AUDIT' => '只有审核中的才可以撤回',

View File

@ -25,8 +25,7 @@ class MemberLoginListener
public function handle(object $member)
{
// 新人专享活动
event("MemberLoginAfter", [ 'member_id' => $member[ 'member_id' ] ]);
return;
event("MemberLoginAfter", ['member_id' => $member['member_id']]);
}
}

View File

@ -20,6 +20,5 @@ class PayNotifyListener
{
public function handle($member)
{
return;
}
}

View File

@ -221,135 +221,82 @@ class AddonService extends BaseAdminService
return $this->model->where([ [ 'key', '=', $key ] ])->field('title, icon, key, desc, status, cover')->findOrEmpty()->toArray();
}
/**
* 查询应用列表todo 完善
* @return array
*/
public function getShowAppTools()
{
$list = [
'tool' => $this->getAllAddonAndTool()[ 'tool' ],
];
return $list;
}
/**
* 查询营销列表
* @return array
*/
public function getShowMarketingTools()
{
$all = $this->getAllAddonAndTool();
$list = [
'marketing' => $all[ 'marketing' ],
'addon' => $all[ 'addon' ],
];
return $list;
}
private function getMarketing()
{
$list = [
'marketing' => [
'title' => '营销活动',
'list' => []
]
];
$apps = event('ShowMarketing');
$keys = [];
foreach ($apps as $v) {
foreach ($v as $ck => $cv) {
if (!empty($cv)) {
foreach ($cv as $addon_k => $addon_v) {
if (in_array($addon_v[ 'key' ], $keys)) {
continue;
}
$list[ $ck ][ 'list' ][] = $addon_v;
$keys[] = $addon_v[ 'key' ];
}
}
}
}
return $list;
}
/**
* @return array[]
*/
public function showCustomer($is_sort=true)
public function showCustomer($is_sort = true)
{
$show_list = event('ShowCustomer', []);
$addon_type_list = MenuDict::getAddonChildMenu();
$return = [];
foreach ($show_list as $item) {
foreach ($addon_type_list as $key => $value) {
if (!isset($return[$key])) {
$return[$key] = [
'title' => $value['name'],
'sort' => $value['sort'],
if (!isset($return[ $key ])) {
$return[ $key ] = [
'title' => $value[ 'name' ],
'sort' => $value[ 'sort' ],
'list' => [],
];
}
$return[$key]['list'] = array_merge($return[$key]['list'], $item[$key] ?? []);
$return[ $key ][ 'list' ] = array_merge($return[ $key ][ 'list' ], $item[ $key ] ?? []);
}
}
//防止有未实现对应事件的插件额外做一次查询 未实现的直接放到 addon_tool 里面
$keys = [];
foreach ($return as $item) {
foreach ($item['list'] as $value) {
$keys[] = $value['key'];
foreach ($item[ 'list' ] as $value) {
$keys[] = $value[ 'key' ];
}
}
$addon_list = $this->getAddonList([]);
$menu_model = (new SysMenu());
$addon_list = $this->getAddonList();
$menu_model = ( new SysMenu() );
$addon_urls = $menu_model
->where([['addon', 'in', array_column($addon_list, 'key')], ['addon', 'not in', $keys], ['is_show', '=', 1], ['menu_type', '=', 1]])
->where([ [ 'addon', 'in', array_column($addon_list, 'key') ], [ 'addon', 'not in', $keys ], [ 'is_show', '=', 1 ], [ 'menu_type', '=', 1 ] ])
->order('id asc')
->group('addon')
->column('router_path', 'addon');
if (!empty($addon_list)) {
foreach ($addon_list as $k => $v) {
if (in_array($v['key'], $keys)) {
if (in_array($v[ 'key' ], $keys)) {
continue;
}
$url = $addon_urls[$v['key']] ?? '';
$return['addon_tool']['list'][] = [
'title' => $v['title'],
'desc' => $v['desc'],
'icon' => $v['icon'],
'key' => $v['key'],
$url = $addon_urls[ $v[ 'key' ] ] ?? '';
$return[ 'addon_tool' ][ 'list' ][] = [
'title' => $v[ 'title' ],
'desc' => $v[ 'desc' ],
'icon' => $v[ 'icon' ],
'key' => $v[ 'key' ],
'url' => $url ? '/' . $url : ''
];
}
}
if($is_sort){
if ($is_sort) {
usort($return, function (array $a, array $b) {
$sortA = isset($a['sort']) ? (int)$a['sort'] : 0;
$sortB = isset($b['sort']) ? (int)$b['sort'] : 0;
$sortA = isset($a[ 'sort' ]) ? (int) $a[ 'sort' ] : 0;
$sortB = isset($b[ 'sort' ]) ? (int) $b[ 'sort' ] : 0;
return $sortB <=> $sortA;
});
}
return $return;
}
//生成菜单数据
public function getSpecialMenuList()
{
$auth_menu_list = (new AuthService())->getAuthMenuList('all',1);
$auth_menu_list = ( new AuthService() )->getAuthMenuList('all', 1);
$auth_menu_list = array_column($auth_menu_list, null, 'menu_key');
$auth_menu_list = $auth_menu_list['addon']['children'] ?? [];
$auth_menu_list = $auth_menu_list[ 'addon' ][ 'children' ] ?? [];
$list = $this->showCustomer(false);//获取对应的需要展示的key
$addon_menu_list = MenuDict::getAddonChildMenu();
$menu_list = [];
foreach ($addon_menu_list as $item) {
$menu_key_list = array_column($list[$item['key']]['list'] ?? [], 'key');
$menu_key_list = array_column($list[ $item[ 'key' ] ][ 'list' ] ?? [], 'key');
$temp_menu = [
'app_type'=>'admin',
'menu_name' => $item['name'],
'menu_key' => $item['key'],
'menu_short_name' => $item['short_name'],
'app_type' => 'admin',
'menu_name' => $item[ 'name' ],
'menu_key' => $item[ 'key' ],
'menu_short_name' => $item[ 'short_name' ],
'parent_key' => 'addon',
'menu_type' => '0',
'icon' => 'iconfont iconzhuangxiu3',
@ -357,22 +304,24 @@ class AddonService extends BaseAdminService
'router_path' => 'app/index',
'view_path' => 'app/index',
'methods' => 'get',
'sort' => $item['sort'],
'sort' => $item[ 'sort' ],
'status' => '1',
'is_show' => '1',
];
$children = [];
foreach ($auth_menu_list as $datum_item) {
if (in_array($datum_item['menu_key'], $menu_key_list)) {
$children[] = $datum_item;
if (!empty($auth_menu_list)) {
foreach ($auth_menu_list as $datum_item) {
if (in_array($datum_item[ 'menu_key' ], $menu_key_list)) {
$children[] = $datum_item;
}
}
}
$temp_menu['children'] = $children;
$temp_menu[ 'children' ] = $children;
$menu_list[] = $temp_menu;
}
usort($menu_list, function (array $a, array $b) {
$sortA = isset($a['sort']) ? (int)$a['sort'] : 0;
$sortB = isset($b['sort']) ? (int)$b['sort'] : 0;
$sortA = isset($a[ 'sort' ]) ? (int) $a[ 'sort' ] : 0;
$sortB = isset($b[ 'sort' ]) ? (int) $b[ 'sort' ] : 0;
return $sortB <=> $sortA;
});
return [
@ -381,82 +330,4 @@ class AddonService extends BaseAdminService
];
}
private function getAllAddonAndTool()
{
$markting_list = $this->getMarketing() ?? [];
$markting = $markting_list[ 'marketing' ];
$marking_addon = $markting_list[ 'tool' ][ 'list' ] ?? [];
$list = [
'marketing' => $markting,
'addon' => [
'title' => '营销工具',
'list' => $marking_addon
],
'tool' => [
'title' => '系统工具',
'list' => []
]
];
$apps = event('ShowApp');
$keys = [];
foreach ($apps as $v) {
foreach ($v as $ck => $cv) {
if (!empty($cv)) {
foreach ($cv as $addon_k => $addon_v) {
if (in_array($addon_v[ 'key' ], $keys)) {
continue;
}
$list[ $ck ][ 'list' ][] = $addon_v;
$keys[] = $addon_v[ 'key' ];
}
}
}
}
$menu_model = ( new SysMenu() );
$site_addons = $this->getAddonList();
if (!empty($site_addons)) {
foreach ($site_addons as $k => $v) {
if ($v[ 'type' ] == 'app') {
unset($site_addons[ $k ]);
}
}
$addon_urls = $menu_model
->where([ [ 'addon', 'in', array_column($site_addons, 'key') ], [ 'is_show', '=', 1 ], [ 'menu_type', '=', 1 ] ])
->order('id asc')
->group('addon')
->column('router_path', 'addon');
foreach ($site_addons as $k => $v) {
$continue = true;
if (!empty($markting[ 'list' ])) {
foreach ($markting[ 'list' ] as $key => $val) {
if ($v[ 'key' ] == $val[ 'key' ]) {
unset($site_addons[ $k ]);
$continue = false;
}
}
}
if ($continue && !in_array($v[ 'key' ], $keys)) {
$url = $addon_urls[ $v[ 'key' ] ] ?? '';
$list[ 'addon' ][ 'list' ][] = [
'title' => $v[ 'title' ],
'desc' => $v[ 'desc' ],
'icon' => $v[ 'icon' ],
'key' => $v[ 'key' ],
'url' => $url ? '/' . $url : ''
];
}
}
}
return $list;
}
}

View File

@ -15,8 +15,10 @@ use app\Request;
use app\service\admin\sys\MenuService;
use app\service\admin\sys\RoleService;
use app\service\admin\user\UserService;
use app\service\core\niucloud\CoreAuthService;
use core\base\BaseAdminService;
use core\exception\AuthException;
use core\exception\CommonException;
use Exception;
/**
@ -35,10 +37,15 @@ class AuthService extends BaseAdminService
*/
public function checkRole(Request $request)
{
$this->checkAuthinfo($request);
$rule = strtolower(trim($request->rule()->getRule()));
$method = strtolower(trim($request->method()));
if($method != 'get'){
// throw new AuthException('演示站禁止操作');
}
$menu_service = new MenuService();
$all_menu_list = $menu_service->getAllApiList();
//先判断当前访问的接口是否收到权限的限制
@ -54,6 +61,33 @@ class AuthService extends BaseAdminService
}
public function checkAuthinfo(Request $request) {
$rule = strtolower(trim($request->rule()->getRule()));
$method = strtolower(trim($request->method()));
if ($method == 'get') return;
$ignore = ['niucloud/authinfo', 'upgrade', 'niucloud/build', 'sys/cache/clear'];
foreach ($ignore as $item) {
if (strpos($rule, $item) !== false) return;
}
$authinfo = (new CoreAuthService())->getAuthInfo()['data'] ?? [];;
if (empty($authinfo)) return;
if (!$this->isCheckDomain()) return;
$site_address = $authinfo['site_address'] ?? '';
$domain = request()->domain();
if (!empty($site_address) && strpos($domain, $site_address) !== false) return;
throw new CommonException("授权域名校验失败!请确保当前访问域名与授权码绑定的域名一致");
}
private function isCheckDomain() {
return !(request()->ip() == '127.0.0.1' || request()->host() == 'localhost');
}
/**
* 当前授权用户接口权限
* @return array

View File

@ -20,7 +20,6 @@ use app\service\core\sys\CoreConfigService;
use core\base\BaseAdminService;
use core\exception\AuthException;
use core\util\TokenAuth;
use Exception;
use Throwable;
/**
@ -41,7 +40,6 @@ class LoginService extends BaseAdminService
* 用户登录
* @param string $username
* @param string $password
* @param string $app_type
* @return array|bool
*/
public function login(string $username, string $password)
@ -88,8 +86,8 @@ class LoginService extends BaseAdminService
//查询权限以及菜单
$data = [
'token' => $token_info['token'],
'expires_time' => $token_info['params']['exp'],
'token' => $token_info[ 'token' ],
'expires_time' => $token_info[ 'params' ][ 'exp' ],
'userinfo' => [
'uid' => $userinfo->uid,
'username' => $userinfo->username,
@ -127,7 +125,6 @@ class LoginService extends BaseAdminService
/**
* 清理token
* @param int $uid
* @param string|null $type
* @param string|null $token
*/
public static function clearToken(int $uid, ?string $token = '')
@ -151,7 +148,6 @@ class LoginService extends BaseAdminService
$token_info = TokenAuth::parseToken($token, AppTypeDict::ADMIN);
} catch (Throwable $e) {
throw new AuthException('LOGIN_EXPIRE', 401);
}
if (!$token_info) {
throw new AuthException('MUST_LOGIN', 401);

View File

@ -60,24 +60,41 @@ class DiyService extends BaseAdminService
/**
* 获取自定义页面分页列表,轮播搜索组件用
* 查询微页面,数据排除存在轮播搜索组件的
* @param array $where
* @return array
* @throws DbException
*/
public function getPageByCarouselSearch()
{
$field = 'id,title,page_title,name,template,type,mode,is_default,share,visit_count,create_time,update_time,value';
$field = 'id,title,page_title,name,type,create_time,value';
$order = "update_time desc";
$search_model = $this->model->whereOr([
[
[ 'type', '=', 'DIY_PAGE' ],
[ 'value', 'not in', [ 'top_fixed', 'right_fixed', 'bottom_fixed', 'left_fixed', 'fixed' ] ]
],
[
[ 'type', '<>', 'DIY_PAGE' ],
[ 'is_default', '=', 0 ],
[ 'value', 'not in', [ 'top_fixed', 'right_fixed', 'bottom_fixed', 'left_fixed', 'fixed' ] ]
]
])->field($field)->order($order)->append([ 'type_name', 'type_page', 'addon_name' ]);
$search_model = $this->model
->whereOr([
[
[ 'type', '=', 'DIY_PAGE' ],
[ 'value', 'not like',
[
'%"position":"top_fixed"%',
'%"position":"right_fixed"%',
'%"position":"bottom_fixed"%',
'%"position":"left_fixed"%',
'%"position":"fixed"%'
]
]
],
[
[ 'type', '<>', 'DIY_PAGE' ],
[ 'is_default', '=', 0 ],
[ 'value', 'not like',
[
'%"position":"top_fixed"%',
'%"position":"right_fixed"%',
'%"position":"bottom_fixed"%',
'%"position":"left_fixed"%',
'%"position":"fixed"%'
]
]
]
])->field($field)->order($order)->append([ 'type_name', 'type_page', 'addon_name' ]);
return $this->pageQuery($search_model);
}

View File

@ -205,7 +205,7 @@ class GenerateService extends BaseAdminService
$table_id = $res->id;
$add_column_data = [];
$default_column = ['id', 'create_time', 'update_time'];
$default_column = ['id', 'create_time', 'update_time', 'delete_time'];
foreach ($fields as $k => $v){
$required = 0;
if ($v['notnull'] && !$v['primary'] && !in_array($v['name'], $default_column)) {

View File

@ -212,7 +212,7 @@ use app\adminapi\middleware\AdminLog;";
{
if(!empty($this->addonName))
{
$dir = $this->outDir . DIRECTORY_SEPARATOR.'addon'.DIRECTORY_SEPARATOR.'.$this->addonName.'.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'adminapi'.DIRECTORY_SEPARATOR.'route'.DIRECTORY_SEPARATOR;
$dir = $this->outDir . DIRECTORY_SEPARATOR.'addon'.DIRECTORY_SEPARATOR.$this->addonName.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'adminapi'.DIRECTORY_SEPARATOR.'route'.DIRECTORY_SEPARATOR;
}else{
$dir = $this->outDir . 'niucloud'.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'adminapi'.DIRECTORY_SEPARATOR.'route'.DIRECTORY_SEPARATOR;
}

View File

@ -106,7 +106,7 @@ class WebEditGenerator extends BaseGenerator
{
$content = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk']) {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk'] || $column['is_delete']) {
continue;
}
@ -435,7 +435,7 @@ class WebEditGenerator extends BaseGenerator
/**
* 获取文件生成到插件中
* @return void
* @return string
*/
public function getAddonObjectOutDir() {
$dir = $this->rootDir . DIRECTORY_SEPARATOR.'niucloud'.DIRECTORY_SEPARATOR.'addon'.DIRECTORY_SEPARATOR.$this->addonName.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'views'.DIRECTORY_SEPARATOR. $this->moduleName . DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR;
@ -492,7 +492,7 @@ class WebEditGenerator extends BaseGenerator
/**
* 调用字典方法
* @return void
* @return string
*/
public function getDictList()
{
@ -518,7 +518,7 @@ class WebEditGenerator extends BaseGenerator
/**
* 调用远程下拉方法
* @return void
* @return string
*/
public function getModelData()
{
@ -542,7 +542,7 @@ class WebEditGenerator extends BaseGenerator
/**
* 编辑远程下拉方法
* @return void
* @return string
*/
public function getEditWithApiPath()
{
@ -559,7 +559,7 @@ class WebEditGenerator extends BaseGenerator
/**
* 增加关联方法
* @return void
* @return string
*/
public function getWithApiPath()
{

View File

@ -156,7 +156,7 @@ class WebEditPageGenerator extends BaseGenerator
{
$content = '';
foreach ($this->tableColumn as $column) {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk']) {
if (!$column['is_insert'] || !$column['is_update'] || $column['is_pk'] || $column['is_delete']) {
continue;
}
@ -505,7 +505,7 @@ class WebEditPageGenerator extends BaseGenerator
/**
* 调用远程下拉方法
* @return void
* @return string
*/
public function getModelData()
{
@ -528,7 +528,7 @@ class WebEditPageGenerator extends BaseGenerator
/**
* 编辑远程下拉方法
* @return void
* @return string
*/
public function getEditWithApiPath()
{

View File

@ -539,7 +539,7 @@ class WebIndexGenerator extends BaseGenerator
/**
* 增加关联方法
* @return void
* @return string
*/
public function getWithApiPath()
{
@ -556,7 +556,7 @@ class WebIndexGenerator extends BaseGenerator
/**
* 调用远程下拉方法
* @return void
* @return string
*/
public function getModelData()
{

View File

@ -15,7 +15,6 @@ use app\model\member\MemberAddress;
use app\service\admin\sys\AreaService;
use app\service\core\member\CoreMemberAddressService;
use core\base\BaseAdminService;
use core\exception\AdminException;
/**

View File

@ -22,6 +22,7 @@ use core\exception\AdminException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
/**
* 会员服务层
@ -80,7 +81,11 @@ class MemberService extends BaseAdminService
public function getInfo(int $member_id)
{
$field = 'member_id,member_no, id_card,remark,username, mobile, password, register_channel, register_type, nickname, headimg, member_level, member_label, wx_openid, weapp_openid, wx_unionid, ali_openid, douyin_openid, login_ip, login_type, login_channel, login_count, login_time, create_time, last_visit_time, last_consum_time, sex, status, birthday, point, point_get, balance, balance_get, growth, growth_get, is_member, member_time, is_del, province_id, city_id, district_id, address, location, delete_time, money, money_get, commission, commission_get, commission_cash_outing';
return $this->makeUp($this->model->where([ [ 'member_id', '=', $member_id ] ])->field($field)->with('member_level_name_bind')->append([ 'register_channel_name', 'register_type_name', 'sex_name', 'login_channel_name', 'login_type_name', 'status_name' ])->findOrEmpty()->toArray());
$info = $this->makeUp($this->model->where([ [ 'member_id', '=', $member_id ] ])->field($field)->with('member_level_name_bind')->append([ 'register_channel_name', 'register_type_name', 'sex_name', 'login_channel_name', 'login_type_name', 'status_name' ])->findOrEmpty()->toArray());
if (empty($info[ 'member_level' ])) {
$info[ 'member_level' ] = '';
}
return $info;
}
/**
@ -149,6 +154,7 @@ class MemberService extends BaseAdminService
* @param int $member_id
* @param string $field
* @param $data
* @return Member
*/
public function modify(int $member_id, string $field, $data)
{
@ -168,6 +174,10 @@ class MemberService extends BaseAdminService
/**
* 组合整理数据
* @param $data
* @return mixed
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function makeUp($data)
{
@ -223,7 +233,16 @@ class MemberService extends BaseAdminService
*/
public function getMemberNo()
{
return ( new CoreMemberService() )->createMemberNo();
//开启事务,解决创建会员编码重复
try {
Db::startTrans();
$member_no = ( new CoreMemberService() )->createMemberNo();
Db::commit();
return $member_no;
} catch (AdminException $e) {
Db::rollback();
throw new AdminException("MEMBER_NO_CREATE_ERROR");
}
}
/**
@ -256,7 +275,7 @@ class MemberService extends BaseAdminService
/**
* 获取会员权益字典
* @return mixed
* @return array|null
*/
public function getMemberBenefitsDict()
{
@ -302,7 +321,7 @@ class MemberService extends BaseAdminService
/**
* 获取会员礼包内容
* @param array $benefits
* @param array $gifts
* @return array|null
*/
public function getMemberGiftsContent(array $gifts)

View File

@ -50,6 +50,7 @@ class MemberSignService extends BaseAdminService
/**
* 组合整理数据
* @param $data
* @return mixed
*/
public function makeUp($data)
{
@ -84,14 +85,14 @@ class MemberSignService extends BaseAdminService
*/
public function setSign(array $value)
{
if (empty($value[ 'sign_period' ])) throw new AdminException('SIGN_PERIOD_CANNOT_EMPTY');
if ($value[ 'sign_period' ] < 2 || $value[ 'sign_period' ] > 365) throw new AdminException('SIGN_PERIOD_BETWEEN_2_365_DAYS');
if (!empty($value[ 'continue_award' ])) {
foreach ($value[ 'continue_award' ] as $v) {
if ($v[ 'continue_sign' ] < 2 || $v[ 'continue_sign' ] > 365) throw new AdminException('CONTINUE_SIGN_BETWEEN_2_365_DAYS');
if ($v[ 'continue_sign' ] > $value[ 'sign_period' ]) throw new AdminException('CONTINUE_SIGN_CANNOT_GREATER_THAN_SIGN_PERIOD');
}
}
// if (empty($value[ 'sign_period' ])) throw new AdminException('SIGN_PERIOD_CANNOT_EMPTY');
// if ($value[ 'sign_period' ] < 2 || $value[ 'sign_period' ] > 365) throw new AdminException('SIGN_PERIOD_BETWEEN_2_365_DAYS');
// if (!empty($value[ 'continue_award' ])) {
// foreach ($value[ 'continue_award' ] as $v) {
// if ($v[ 'continue_sign' ] < 2 || $v[ 'continue_sign' ] > 365) throw new AdminException('CONTINUE_SIGN_BETWEEN_2_365_DAYS');
// if ($v[ 'continue_sign' ] > $value[ 'sign_period' ]) throw new AdminException('CONTINUE_SIGN_CANNOT_GREATER_THAN_SIGN_PERIOD');
// }
// }
$data = [
'is_use' => $value[ 'is_use' ], //是否开启
'sign_period' => $value[ 'sign_period' ], // 签到周期

View File

@ -17,6 +17,7 @@ use app\service\core\niucloud\CoreModuleService;
use app\service\core\sys\CoreConfigService;
use core\base\BaseAdminService;
use core\exception\CommonException;
use think\facade\Cache;
/**
* 消息管理服务层
@ -47,6 +48,7 @@ class NiucloudService extends BaseAdminService
$auth_info = $service->getAuthInfo()['data'] ?? [];
if (empty($auth_info)) throw new CommonException('AUTH_NOT_EXISTS');
$service->clearAccessToken();
Cache::set("authinfo", null);
return $this->core_config_service->setConfig(ConfigKeyDict::NIUCLOUD_CONFIG, $data);
}

View File

@ -233,10 +233,34 @@ class NiuSmsService extends BaseAdminService
*/
public function signCreate($username, $params)
{
if (!empty($params['imgUrl']) && strstr($params['imgUrl'], 'http') === false) {
$params['imgUrl'] = request()->domain() . '/' . $params['imgUrl'];
} else {
$params['imgUrl'] = $params['imgUrl'] ?? '';
$params['imgUrl'] = $this->formatImageUrl($params['imgUrl']);
$params['bizLicenseUrl'] = $this->formatImageUrl($params['bizLicenseUrl']);
$params['qccUrl'] = $this->formatImageUrl($params['qccUrl']);
$params['tmnetUrl'] = $this->formatImageUrl($params['tmnetUrl']);
$params['mobileIcpUrl'] = $this->formatImageUrl($params['mobileIcpUrl']);
$params['telecomAppstoreUrl'] = $this->formatImageUrl($params['telecomAppstoreUrl']);
$params['idcardFrontUrl'] = $this->formatImageUrl($params['idcardFrontUrl']);
$params['idcardBackUrl'] = $this->formatImageUrl($params['idcardBackUrl']);
if (empty($params['idcardFrontUrl'])) {
throw new ApiException('身份证正面不能为空');
}
if (empty($params['idcardBackUrl'])) {
throw new ApiException('身份证反面不能为空');
}
if (empty($params['bizLicenseUrl'])) {
throw new ApiException('营业执照');
}
if (in_array($params['signSource'], [4, 5]) && empty($params['telecomAppstoreUrl'])) {
throw new ApiException('应用商店/小程序页面开发者截图不能为空');
}
if (in_array($params['signSource'], [4, 5]) && empty($params['mobileIcpUrl'])) {
throw new ApiException('移动ICP截图不能为空');
}
if (in_array($params['signSource'], [3]) && empty($params['tmnetUrl'])) {
throw new ApiException('中国商标网截图不能为空');
}
if (in_array($params['signSource'], [1, 2]) && $params['signType'] == 1 && empty($params['qccUrl'])) {
throw new ApiException('企查查唯一性截图不能为空');
}
$res = $this->niu_service->signCreate($username, $params);
if (!empty($res['failList'])) {
@ -244,6 +268,21 @@ class NiuSmsService extends BaseAdminService
}
}
/**
* 格式化图片地址
* @param $url
* @return string
*/
private function formatImageUrl($url)
{
if (!empty($url) && strstr($url, 'http') === false) {
$url = request()->domain() . '/' . $url;
} else {
$url = $url ?? '';
}
return $url;
}
/**
* 签名创建
* @param $username

View File

@ -31,11 +31,15 @@ class RefundService extends BaseAdminService
/**
* 退款账户记录
* @param array $where
* @return mixed
* @return array
*/
public function getPage(array $where){
$field = 'id,refund_no,out_trade_no,type,channel,money,reason,status,create_time,refund_time,close_time,fail_reason,voucher,trade_type,trade_id,refund_type,main_type,main_id';
$search_model = $this->model->where([ [ 'id', '>', 0 ] ])->withSearch([ 'create_time', 'out_trade_no', 'refund_no', 'status' ], $where)->field($field)->append([ 'type_name', 'status_name' ])->order('create_time desc');
$search_model = $this->model->where([ [ 'id', '>', 0 ] ])
->withSearch([ 'create_time', 'out_trade_no', 'refund_no', 'status' ], $where)
->field($field)
->append([ 'type_name', 'status_name','trade_type_name' ])
->order('create_time desc');
return $this->pageQuery($search_model);
}

View File

@ -87,6 +87,9 @@ class ConfigService extends BaseAdminService
'front_end_logo' => '',
'front_end_icon' => '',
'icon' => '',
'meta_title' => '',
'meta_desc' => '',
'meta_keyword' => '',
];
}
return $info[ 'value' ];
@ -137,7 +140,6 @@ class ConfigService extends BaseAdminService
"enterprise_wechat" => $value[ 'enterprise_wechat' ],
"tel" => $value[ 'tel' ]
];
return $this->core_config_service->setConfig('SERVICE_INFO', $data);
}
@ -227,9 +229,9 @@ class ConfigService extends BaseAdminService
public function setLayout(array $data)
{
$config_service = new CoreConfigService();
$config = $config_service->getConfigValue( "LAYOUT_SETTING");
$config = $config_service->getConfigValue("LAYOUT_SETTING");
$config[ $data[ 'key' ] ] = $data[ 'value' ];
return ( new CoreConfigService() )->setConfig( "LAYOUT_SETTING", $config);
return ( new CoreConfigService() )->setConfig("LAYOUT_SETTING", $config);
}
/**
@ -238,7 +240,7 @@ class ConfigService extends BaseAdminService
*/
public function getThemeColor()
{
return ( new CoreConfigService() )->getConfigValue( "THEMECOLOR_SETTING");
return ( new CoreConfigService() )->getConfigValue("THEMECOLOR_SETTING");
}
/**

View File

@ -54,7 +54,7 @@ class PosterService extends BaseAdminService
* 获取自定义海报列表
* @param array $where
* @param string $field
* @return mixed
* @return array
*/
public function getList(array $where = [], $field = 'id, name, type, channel, value, status,is_default, create_time, update_time, addon')
{
@ -66,7 +66,7 @@ class PosterService extends BaseAdminService
* 获取自定义海报信息
* @param int $id
* @param string $field
* @return mixed
* @return array
*/
public function getInfo(int $id, $field = 'id, name, type, channel, value, status,is_default, create_time, update_time, addon')
{
@ -109,7 +109,7 @@ class PosterService extends BaseAdminService
/**
* 修改自定义海报启用状态
* @param $data
* @return mixed
* @return Poster
*/
public function modifyStatus($data)
{
@ -126,7 +126,7 @@ class PosterService extends BaseAdminService
/**
* 将自定义海报修改为默认海报
* @param $data
* @return mixed
* @return bool
*/
public function modifyDefault($data)
{
@ -137,7 +137,7 @@ class PosterService extends BaseAdminService
}
Db::startTrans();
$this->model->where([ [ 'type', '=', $info[ 'type' ] ] ])->update([ 'is_default' => 0 ]);
$this->model->where([ [ 'id', '=', $data[ 'id' ] ] ])->update([ 'is_default' => 1, 'update_time' => time() ]);
$this->model->where([ [ 'id', '=', $data[ 'id' ] ] ])->update([ 'is_default' => 1, 'status' => 1, 'update_time' => time() ]);
Db::commit();
return true;
} catch (Exception $e) {

View File

@ -249,8 +249,10 @@ class RoleService extends BaseAdminService
/**
* 角色状态修改
*/
public function modifyStatus(int $id, int $status)
public function modifyStatus($data)
{
$id = $data[ 'role_id' ];
$status = $data[ 'status' ];
$this->model->where([ [ 'role_id', '=', $id ] ])->update([ 'status' => $status ]);
return true;
}

View File

@ -127,24 +127,26 @@ class UpgradeService extends BaseAdminService
// 检测全部目录及文件是否可读可写,忽略指定目录
// 忽略指定目录admin
$exclude_admin_dir = [ 'dist', 'node_modules', '.git' ];
$exclude_admin_dir = [ 'dist', 'node_modules', '.git', '.user.ini' ];
$check_res = checkDirPermissions(project_path() . 'admin', [], $exclude_admin_dir);
// 忽略指定目录uni-app
$exclude_uniapp_dir = [ 'dist', 'node_modules', '.git' ];
$exclude_uniapp_dir = [ 'dist', 'node_modules', '.git', '.user.ini' ];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'uni-app', [], $exclude_uniapp_dir));
// 忽略指定目录web
$exclude_web_dir = [ '.nuxt', '.output', 'dist', 'node_modules', '.git' ];
$exclude_web_dir = [ '.nuxt', '.output', 'dist', 'node_modules', '.git', '.user.ini' ];
$check_res = array_merge2($check_res, checkDirPermissions(project_path() . 'web', [], $exclude_web_dir));
// 忽略指定目录niucloud
$exclude_niucloud_dir = [
'public' . DIRECTORY_SEPARATOR . 'admin',
'public' . DIRECTORY_SEPARATOR . 'admin' . DIRECTORY_SEPARATOR .'niucloud.ico',
'public' . DIRECTORY_SEPARATOR . 'wap',
'public' . DIRECTORY_SEPARATOR . 'web',
'public' . DIRECTORY_SEPARATOR . 'upload',
'public' . DIRECTORY_SEPARATOR . 'file',
'public' . DIRECTORY_SEPARATOR . 'favicon.ico',
'runtime',
'vendor',
'.user.ini',
@ -313,8 +315,6 @@ class UpgradeService extends BaseAdminService
}
if (!in_array($step, [ 'upgradeComplete', 'restoreComplete' ])) {
Cache::set($this->cache_key, $this->upgrade_task);
} else {
$this->clearUpgradeTask(2);
}
} catch (CloudBuildException $e) {
if (strpos($e->getMessage(), '队列') !== false) {
@ -466,7 +466,7 @@ class UpgradeService extends BaseAdminService
// 覆盖文件
if (is_dir($code_dir . $version_no)) {
// 忽略环境变量文件
$exclude_files = [ '.env.development', '.env.production', '.env', '.env.dev', '.env.product' ];
$exclude_files = [ '.env.development', '.env.production', '.env', '.env.dev', '.env.product', 'favicon.ico', 'niucloud.ico' ];
dir_copy($code_dir . $version_no, $to_dir, exclude_files: $exclude_files);
if ($addon != AddonDict::FRAMEWORK_KEY) {
( new CoreAddonInstallService($addon) )->installDir();
@ -629,15 +629,57 @@ class UpgradeService extends BaseAdminService
$sql_data = array_filter($this->getSqlQuery($sql_content));
if (!empty($sql_data)) {
try {
$default_collation = Db::query("SHOW VARIABLES LIKE 'collation_database'")[0]['Value'] ?? 'utf8mb4_general_ci';
} catch (\Exception $e) {
$default_collation = 'utf8mb4_general_ci';
}
foreach ($sql_data as $sql) {
$sql = $prefix ? $this->handleSqlPrefix($sql, $prefix) : $sql;
Db::query($sql);
// 处理成默认排序规则
$sql = preg_replace_callback(
'/\bCOLLATE\s*(=)?\s*[`"\']?([a-zA-Z0-9_]+)[`"\']?/i',
function ($matches) use ($default_collation) {
return "COLLATE " . $default_collation;
},
$sql
);
// 判断是否是新增字段
$pattern = '/^ALTER\s+TABLE\s+(`?)(\w+)\1\s+ADD(?:\s+COLUMN)?\s+(`?)(\w+)\3\s+/i';
if (preg_match($pattern, $sql, $matches)) {
if (!$this->columnExists($matches[2], $matches[4])) {
Db::query($sql);
}
}else{
Db::query($sql);
}
}
}
}
return true;
}
/**
* 判断数据表中某个字段是否存在
*
* @param string $table 表名(不带前缀)
* @param string $column 字段名
* @param string|null $database 指定数据库名(可选,默认当前连接的数据库)
* @return bool
*/
private function columnExists(string $table, string $column, ?string $database = null): bool
{
$db = env('database.database', '');
$count = Db::query(
"SELECT COUNT(*) AS cnt FROM information_schema.COLUMNS
WHERE table_schema = ? AND table_name = ? AND column_name = ?",
[$db, $table, $column]
);
return (int)$count[0]['cnt'] > 0;
}
/**
* 刷新菜单
* @return array|true
@ -703,20 +745,10 @@ class UpgradeService extends BaseAdminService
foreach ($log[ 'data' ][ 0 ] as $item) {
if ($item[ 'code' ] == 0) {
$this->upgrade_task[ 'step' ] = 'gteCloudBuildLog';
$this->upgrade_task[ 'error' ][] = $item[ 'msg' ];
// $this->upgrade_task[ 'error' ][] = $item[ 'msg' ];
$this->upgrade_task[ 'cloud_build_error' ] = $item[ 'msg' ];
Cache::set($this->cache_key, $this->upgrade_task);
$fail_reason = [
'Message' => '失败原因 云编译错误:' . $item[ 'msg' ],
'File' => '',
'Line' => '',
'Trace' => ''
];
( new CoreCloudBuildService() )->clearTask();
$this->upgradeErrorHandle($fail_reason);
return true;
}
if (!in_array($item[ 'action' ], $this->upgrade_task[ 'log' ])) {
@ -745,7 +777,13 @@ class UpgradeService extends BaseAdminService
}
// 执行完成,更新升级记录状态,备份记录状态
( new UpgradeRecordsService() )->complete($this->upgrade_task[ 'key' ]);
$this->clearUpgradeTask(2);
if (!isset($this->upgrade_task['cloud_build_error'])) {
$this->upgrade_task['step'] = 'upgradeComplete';
$this->clearUpgradeTask(2);
} else {
$this->upgrade_task['step'] = 'upgradeComplete';
Cache::set($this->cache_key, $this->upgrade_task);
}
return true;
}
@ -779,7 +817,7 @@ class UpgradeService extends BaseAdminService
if (!isset($this->upgrade_task['is_need_backup']) || $this->upgrade_task['is_need_backup']) {
$backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
} else {
$backup_dir = $this->upgrade_dir . $this->upgrade_task['upgrade_content']['last_backup'][ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
$backup_dir = $this->upgrade_dir . $this->upgrade_task['upgrade_content']['last_backup'][ 'backup_key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'code' . DIRECTORY_SEPARATOR;
}
try {
if (is_dir($backup_dir)) {
@ -802,7 +840,7 @@ class UpgradeService extends BaseAdminService
if (!isset($this->upgrade_task['is_need_backup']) || $this->upgrade_task['is_need_backup']) {
$backup_dir = $this->upgrade_dir . $this->upgrade_task[ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
} else {
$backup_dir = $this->upgrade_dir . $this->upgrade_task['upgrade_content']['last_backup'][ 'key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
$backup_dir = $this->upgrade_dir . $this->upgrade_task['upgrade_content']['last_backup'][ 'backup_key' ] . DIRECTORY_SEPARATOR . 'backup' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR;
}
try {
if (is_dir($backup_dir)) {
@ -826,7 +864,11 @@ class UpgradeService extends BaseAdminService
public function restoreComplete()
{
( new UpgradeRecordsService() )->failed($this->upgrade_task[ 'key' ], $this->upgrade_task['error']);
$error = $this->upgrade_task['error'] ?? [];
if (isset($this->upgrade_task['cloud_build_error'])) $error[] = $this->upgrade_task['cloud_build_error'];
( new UpgradeRecordsService() )->failed($this->upgrade_task[ 'key' ], $error);
$this->upgrade_task['step'] = 'restoreComplete';
Cache::set($this->cache_key, $this->upgrade_task);
$this->clearUpgradeTask(2);
return true;
}
@ -951,6 +993,15 @@ class UpgradeService extends BaseAdminService
];
$this->upgradeErrorHandle($fail_reason);
break;
case 'cloud_build_error_rollback':
$fail_reason = [
'Message' => '失败原因:云编译失败,错误原因:' . $this->upgrade_task['cloud_build_error'],
'File' => '',
'Line' => '',
'Trace' => ''
];
$this->upgradeErrorHandle($fail_reason);
break;
}
}
}

View File

@ -12,9 +12,7 @@
namespace app\service\admin\weapp;
use app\dict\sys\CloudDict;
use app\service\core\site\CoreSiteService;
use app\service\core\weapp\CoreWeappCloudService;
use app\service\core\weapp\CoreWeappConfigService;
use app\service\core\weapp\CoreWeappService;
use core\base\BaseAdminService;
use app\model\weapp\WeappVersion;

View File

@ -65,7 +65,7 @@ class WechatTemplateService extends BaseAdminService
//删除原来的消息模板
// (new CoreWechatTemplateService())->deletePrivateTemplate($wechat_template_id);
$template_loader = new TemplateLoader('wechat');
$template_loader->delete([ 'templateId' => $wechat_template_id ]);
$del_res = $template_loader->delete([ 'templateId' => $wechat_template_id ]);
//新的消息模板
// $res = (new CoreWechatTemplateService())->addTemplate($temp_key, $keyword_name_list);
$res = $template_loader->addTemplate([ 'shortId' => $temp_key, 'keyword_name_list' => $keyword_name_list ]);
@ -74,6 +74,9 @@ class WechatTemplateService extends BaseAdminService
//修改
$notice_service->modify($key, 'wechat_template_id', $res[ 'template_id' ]);
} else {
if (isset($res[ 'errcode' ]) && $res[ 'errcode' ] == 45026) {
throw new NoticeException('模板数量超出限制');
}
throw new NoticeException($res[ 'errmsg' ]);
}
return true;

View File

@ -167,9 +167,9 @@ class DiyService extends BaseApiService
];
$data = [];
foreach ($addon_list as $key => $value) {
if (isset($value[ 'support_app' ]) && empty($value[ 'support_app' ]) && $value[ 'type' ] == 'addon') {
continue;
}
// if (isset($value[ 'support_app' ]) && empty($value[ 'support_app' ]) && $value[ 'type' ] == 'addon') {
// continue;
// }
$addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'key' ] ])))[ 0 ] ?? [];
if (!empty($addon_theme) && !empty($addon_theme[ 'theme_color' ])) {
$data[ $value[ 'key' ] ][ 'title' ] = $theme_data[ $value[ 'key' ] ][ 'title' ] ?? $addon_theme[ 'theme_color' ][ 0 ][ 'title' ];

View File

@ -124,10 +124,10 @@ class AuthService extends BaseApiService
$mobile = $phone_info[ 'purePhoneNumber' ];
if (empty($mobile)) throw new ApiException('WECHAT_EMPOWER_NOT_EXIST');
$member_service = new MemberService();
// $member_service = new MemberService();
$mobile_member = $member_service->findMemberInfo([ 'mobile' => $mobile ]);
if (!$mobile_member->isEmpty()) throw new AuthException('MOBILE_IS_EXIST');
// $mobile_member = $member_service->findMemberInfo([ 'mobile' => $mobile ]);
// if (!$mobile_member->isEmpty()) throw new AuthException('MOBILE_IS_EXIST');
return [
'mobile' => $mobile

View File

@ -39,15 +39,16 @@ class ConfigService extends BaseApiService
*/
public function getCopyright()
{
return (new CoreSysConfigService())->getCopyright();
return ( new CoreSysConfigService() )->getCopyright();
}
/**
* 获取前端域名
* @return array|string[]
*/
public function getSceneDomain(){
return (new CoreSysConfigService())->getSceneDomain();
public function getSceneDomain()
{
return ( new CoreSysConfigService() )->getSceneDomain();
}
/**
@ -80,21 +81,26 @@ class ConfigService extends BaseApiService
'front_end_name' => '',
'front_end_logo' => '',
'icon' => '',
'meta_title' => '',
'meta_desc' => '',
'meta_keyword' => '',
];
}
$info['site_addons'] = (new CoreAddonService())->getInstallAddonList();
$info[ 'site_addons' ] = ( new CoreAddonService() )->getInstallAddonList();
return $info;
}
public function getMap(){
return (new CoreSysConfigService())->getMap();
public function getMap()
{
return ( new CoreSysConfigService() )->getMap();
}
public function getAppConfig() {
$config = (new CoreAppService())->getConfig();
if (!empty($config) && isset($config['wechat_app_secret'])) unset($config['wechat_app_secret']);
$weapp_config = (new CoreWeappConfigService())->getWeappConfig();
$config['weapp_original'] = $weapp_config['weapp_original'];
public function getAppConfig()
{
$config = ( new CoreAppService() )->getConfig();
if (!empty($config) && isset($config[ 'wechat_app_secret' ])) unset($config[ 'wechat_app_secret' ]);
$weapp_config = ( new CoreWeappConfigService() )->getWeappConfig();
$config[ 'weapp_original' ] = $weapp_config[ 'weapp_original' ];
return $config;
}

View File

@ -148,7 +148,7 @@ class WeappAuthService extends BaseApiService
} else {
return [ 'openid' => $openid, 'unionid' => $unionid ]; // 将重要信息返回给前端保存
}
} else if($is_mobile) {
} else if ($is_mobile) {
if (!empty($data[ 'mobile' ]) || !empty($data[ 'mobile_code' ])) {
return $this->register($openid, $data[ 'mobile' ], $data[ 'mobile_code' ], $unionid);
} else {
@ -175,6 +175,7 @@ class WeappAuthService extends BaseApiService
// }
}
}
if (empty($member_info->wx_unionid) && !empty($unionid)) $member_info->wx_unionid = $unionid;
return $login_service->login($member_info, MemberLoginTypeDict::WEAPP);
}
}

View File

@ -136,11 +136,14 @@ class WechatAuthService extends BaseApiService
return [ 'avatar' => $avatar, 'nickname' => $nickname, 'openid' => $openid, 'unionid' => $unionid ];
} else if ($is_force_access_user_info) {
// 开启强制获取会员信息时,必须获取到昵称和头像才能进行注册
if (!empty($nickname) && !empty($avatar)) {
// if (!empty($nickname) && !empty($avatar)) {
if (empty($nickname)){
$nickname = unique_random();
}
return $this->register($openid, '', $nickname, $avatar, $unionid); // 获取到昵称和头像,然后进行注册
} else {
return [ 'avatar' => $avatar, 'nickname' => $nickname, 'openid' => $openid, 'unionid' => $unionid ];
}
// } else {
// return [ 'avatar' => $avatar, 'nickname' => $nickname, 'openid' => $openid, 'unionid' => $unionid ];
// }
} else if ($is_bind_mobile) {
// 开启强制绑定手机号,必须获取手机号才能进行注册,由于公众号无法主动获取,所以不能注册
return [ 'openid' => $openid, 'unionid' => $unionid ];
@ -279,10 +282,10 @@ class WechatAuthService extends BaseApiService
public function updateOpenidByH5($wx_openid)
{
$member_service = new MemberService();
$member = $member_service->findMemberInfo([ 'wx_openid' => $wx_openid]);
$member = $member_service->findMemberInfo([ 'wx_openid' => $wx_openid ]);
if (!$member->isEmpty()) throw new AuthException('MEMBER_OPENID_EXIST');//openid已存在
$member_info = $member_service->findMemberInfo([ 'member_id' => $this->member_id]);
$member_info = $member_service->findMemberInfo([ 'member_id' => $this->member_id ]);
if ($member_info->isEmpty()) throw new AuthException('MEMBER_NOT_EXIST');//账号不存在
$member_service->editByFind($member_info, [ 'wx_openid' => $wx_openid ]);
return true;

View File

@ -173,7 +173,7 @@ class CoreAddonInstallService extends CoreAddonBaseService
}
if (!isset($install_data['support_version']) || empty($install_data['support_version'])) {
$data['addon_check'][] = [
'msg' => $install_data['title'] . '插件的info.json文件中未检测到匹配框架当前版本['. $framework_version_arr[0].'.'.$framework_version_arr[1] .'.*]的信息无法安装,<a style="text-decoration: underline;" href="https://www.kancloud.cn/niucloud/niucloud-admin-develop/3244512" target="blank">点击查看相关手册</a>',
'msg' => $install_data['title'] . '插件的info.json文件中未检测到匹配框架当前版本['. $framework_version_arr[0].'.'.$framework_version_arr[1] .'.*]的信息无法安装,<a style="text-decoration: underline;" href="https://doc.press.niucloud.com/php/saas-framework/use/installFAQ/pluginNotCompatible.html" target="blank">点击查看相关手册</a>',
'status' => false
];
continue;
@ -182,7 +182,7 @@ class CoreAddonInstallService extends CoreAddonBaseService
if ($framework_version_arr[0].$framework_version_arr[1] != $support_framework_arr[0].$support_framework_arr[1]) {
if ((float) "$support_framework_arr[0].$support_framework_arr[1]" < (float) "$framework_version_arr[0].$framework_version_arr[1]") {
$data['addon_check'][] = [
'msg' => $install_data['title'] . '插件的info.json文件中检测到支持的框架版本['. $install_data['support_version'] .']低于当前框架版本['. $framework_version_arr[0].'.'.$framework_version_arr[1] .'.*]无法安装,<a style="text-decoration: underline;" href="https://www.kancloud.cn/niucloud/niucloud-admin-develop/3244512" target="blank">点击查看相关手册</a>',
'msg' => $install_data['title'] . '插件的info.json文件中检测到支持的框架版本['. $install_data['support_version'] .']低于当前框架版本['. $framework_version_arr[0].'.'.$framework_version_arr[1] .'.*]无法安装,<a style="text-decoration: underline;" href="https://doc.press.niucloud.com/php/saas-framework/use/installFAQ/pluginNotCompatible.html" target="blank">点击查看相关手册</a>',
'status' => false
];
}

View File

@ -46,17 +46,20 @@ class CoreAddonService extends CoreAddonBaseService
public function getLocalAddonList()
{
$list = [];
$online_app_list = [];
$online_app_list = $online_apps = [];
$install_addon_list = $this->model->append(['status_name'])->column('title, icon, key, desc, status, author, version, install_time, update_time, cover', 'key');
try {
$niucloud_module_list = (new CoreModuleService())->getModuleList()['data'] ?? [];
foreach ($niucloud_module_list as $v) {
$data = array(
'app_id' => $v['app']['app_id'],
'title' => $v['app']['app_name'],
'desc' => $v['app']['app_desc'],
'key' => $v['app']['app_key'] ?? '',
'version' => $v['version'] ?? '',
'author' => $v['app']['app_name'],
'author' => $v['site_name'],
'author_phone' => $v['site_phone'],
'expire_time' => $v['expire_time'],
'type' => $v['app']['app_type'],
'support_app' => $v['app']['support_channel'] ?? [],
'is_download' => false,
@ -65,9 +68,15 @@ class CoreAddonService extends CoreAddonBaseService
'cover' => $v['app']['window_logo'][0],
);
$data['install_info'] = $install_addon_list[$v['app']['app_key']] ?? [];
//给安装的插件中为授权插件或应用的数据赋值过期时间
if (isset($install_addon_list[$v['app']['app_key']])) {
$install_addon_list[$v['app']['app_key']]['expire_time'] = $v['expire_time'];
}
$list[$v['app']['app_key']] = $data;
}
$online_app_list = array_column($list, 'key');
$online_apps = array_column($list, 'app_id', 'key');
} catch (Throwable $e) {
$error = $e->getMessage();
}
@ -81,8 +90,11 @@ class CoreAddonService extends CoreAddonBaseService
$key = $data['key'];
$data['install_info'] = $install_addon_list[$key] ?? [];
$data['is_download'] = true;
$data['is_local'] = in_array($data['key'], $online_app_list) ? false : true;
$data['is_local'] = !in_array($data['key'], $online_app_list);
$data['version'] = isset($list[$data['key']]) ? $list[$data['key']]['version'] : $data['version'];
$data['app_id'] = in_array($data['key'], $online_app_list) ? $online_apps[$data['key']] : 0;
$data['author_phone'] = '';
$data['expire_time'] = !isset($install_addon_list[$data['key']]) ? '长期有效' : ($install_addon_list[$data['key']]['expire_time'] ?? '');
$list[$key] = $data;
}
}

View File

@ -126,12 +126,12 @@ trait WapTrait
$content .= " </view>\n";
$content .= " </view>\n";
$content .= " </template>\n";
$content .= " <template v-if=\"diyStore.mode == '' && data.global && diyGroup.showCopyright.value && data.global.copyright && data.global.copyright.isShow\">\n";
$content .= " <template v-if=\"data.global && diyGroup.showCopyright.value && data.global.copyright && data.global.copyright.isShow\">\n";
$content .= " <copy-right :textColor=\"data.global.copyright.textColor\" />\n";
$content .= " </template>\n\n";
$content .= " <template v-if=\"diyStore.mode == '' && data.global && data.global.bottomTabBar && data.global.bottomTabBar.isShow\">\n";
$content .= " <view class=\"pt-[20rpx]\"></view>\n";
$content .= " <tabbar :addon=\"data.global.bottomTabBar.designNav.key\" />\n";
$content .= " <tabbar :addon=\"data.global.bottomTabBar.designNav?.key\" />\n";
$content .= " </template>\n";
$content .= " </view>\n";
$content .= "</template>\n";
@ -191,12 +191,20 @@ trait WapTrait
*/
public function installPageCode($compile_path, $addon = '')
{
if (!file_exists($this->geAddonPackagePath($this->addon) . 'uni-app-pages.php')) return;
if (is_array($addon)){
foreach ($addon as $item_addon){
if (!file_exists($this->geAddonPackagePath($item_addon) . 'uni-app-pages.php')) {
continue;
}
$uniapp_pages = require $this->geAddonPackagePath($item_addon) . 'uni-app-pages.php';
}
}else{
if (!file_exists($this->geAddonPackagePath($this->addon) . 'uni-app-pages.php')) return;
$uniapp_pages = require $this->geAddonPackagePath($this->addon) . 'uni-app-pages.php';
if (empty($uniapp_pages[ 'pages' ])) {
return;
$uniapp_pages = require $this->geAddonPackagePath($this->addon) . 'uni-app-pages.php';
if (empty($uniapp_pages[ 'pages' ])) {
return;
}
}
$pages = [];

View File

@ -55,27 +55,6 @@ class CoreAppService extends BaseCoreService
public function setConfig($data)
{
$info = (new CoreConfigService())->setConfig(ConfigKeyDict::APP, $data);
$this->appConfigChange($data);
return $info;
}
/**
* 地图key改变后变更 manifest.json
* @param string $map_key
* @return void
*/
public function appConfigChange($data) {
// $compile_path = project_path(). 'uni-app' . DIRECTORY_SEPARATOR;
// $this->mergeManifestJson($compile_path, [
// "h5" => [
// "sdkConfigs" => [
// "maps" => [
// "qqmap" => [
// "key" => $map_key
// ]
// ]
// ]
// ]
// ]);
}
}

View File

@ -64,7 +64,7 @@ class CoreDiyService extends BaseCoreService
$addon_theme = array_values(array_filter(event('ThemeColor', [ 'key' => $value[ 'key' ] ])))[ 0 ] ?? [];
if (empty($addon_theme)) continue;
foreach ($addon_theme[ 'theme_color' ] as $k => $v) {
foreach ($addon_theme[ 'theme_color' ] ?? [] as $k => $v) {
$data[] = [
'type' => 'app',
'addon' => $value[ 'key' ],

View File

@ -0,0 +1,99 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\core\map;
use app\service\core\sys\CoreConfigService;
use core\base\BaseCoreService;
use core\exception\CommonException;
/**
* 地图服务层
* Class CoreMapService
* @package app\service\core\map
*/
class CoreMapService extends BaseCoreService
{
//系统配置文件
public $core_config_service;
public function __construct()
{
parent::__construct();
$this->core_config_service = new CoreConfigService();
}
/**
* 获取规划路线
* @param $params
* @return array
*/
public function getPolyline($params)
{
$url = 'https://apis.map.qq.com/ws/direction/v1/driving/';
$map = $this->getMapConfig();
$get_data = [
'key' => $map[ 'key' ],
'from' => $params[ 'from' ],
'to' => $params[ 'to' ], // 是否返回周边POI列表1.返回0不返回(默认)
];
$url = $url . '?' . http_build_query($get_data);
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_TIMEOUT, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$res = curl_exec($curl);
$res = json_decode($res, true);
if ($res) {
curl_close($curl);
if ($res[ 'status' ] == 0) {
return $res['result'];
} else {
throw new CommonException('请检查地图配置:'.$res[ 'message' ]);
}
} else {
$error = curl_errno($curl);
curl_close($curl);
throw new CommonException($error);
}
}
/**
* 获取地图配置
* @return array|mixed
*/
public function getMapConfig()
{
$info = ( new CoreConfigService() )->getConfig('MAPKEY');
if (empty($info)) {
$info = [];
$info[ 'value' ] = [
'key' => 'IZQBZ-3UHEU-WTCVD-2464U-I5N4V-ZFFU3',
'is_open' => 1, // 是否开启定位
'valid_time' => 5 // 定位有效期/分钟过期后将重新获取定位信息0为不过期
];
}
$info[ 'value' ][ 'is_open' ] = $info[ 'value' ][ 'is_open' ] ?? 1;
$info[ 'value' ][ 'valid_time' ] = $info[ 'value' ][ 'valid_time' ] ?? 5;
return $info[ 'value' ];
}
}

View File

@ -37,10 +37,14 @@ class CoreMemberAccountService extends BaseCoreService
$member_info = $member_model->where([
[ 'member_id', '=', $member_id ],
])->field($account_type . ',' . $account_type . "_get" . ', username, mobile, nickname')->lock(true)->find();
if (empty($member_info)) throw new CommonException('MEMBER_NOT_EXIST');
if (empty($member_info)) {
Db::rollback();
throw new CommonException('MEMBER_NOT_EXIST');
}
$account_new_data = round((float) $member_info[ $account_type ] + (float) $account_data, 2);
if ($account_new_data < 0) {
Db::rollback();
throw new CommonException('ACCOUNT_INSUFFICIENT');
}

View File

@ -15,6 +15,7 @@ use core\util\niucloud\BaseNiucloudClient;
use core\util\niucloud\http\Response;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;
use think\facade\Cache;
/**
* 官网授权管理服务层
@ -28,10 +29,14 @@ class CoreAuthService extends BaseNiucloudClient
*/
public function getAuthInfo()
{
$cache = Cache::get("authinfo");
if (!empty($cache)) return $cache;
$auth_info = $this->httpGet('authinfo', ['code' => $this->code, 'secret' => $this->secret, 'product_key' => self::PRODUCT ]);
if(!empty($auth_info['data'])){
$auth_info['data']['address_type'] = true;
if($auth_info['data']['site_address'] != $_SERVER['HTTP_HOST']) $auth_info['data']['address_type'] = false;
Cache::set("authinfo", $auth_info, 7200);
}
return $auth_info;
}

View File

@ -136,18 +136,18 @@ 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' ]);
dir_copy($this->root_path . 'uni-app', $package_dir . 'uni-app', exclude_dirs: [ 'node_modules', 'unpackage', 'dist', '.git' ]);
$this->handleUniapp($package_dir . 'uni-app');
}
// 拷贝admin端文件
$admin_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%admin%' ] ])->field('id')->findOrEmpty();
if ($admin_is_compile->isEmpty()) {
dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs: [ 'node_modules', 'dist', '.vscode', '.idea' ]);
dir_copy($this->root_path . 'admin', $package_dir . 'admin', exclude_dirs: [ 'node_modules', 'dist', '.vscode', '.idea', '.git' ]);
}
// 拷贝web端文件
$web_is_compile = ( new Addon() )->where([ [ 'compile', 'like', '%web%' ] ])->field('id')->findOrEmpty();
if ($web_is_compile->isEmpty()) {
dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs: [ 'node_modules', '.output', '.nuxt' ]);
dir_copy($this->root_path . 'web', $package_dir . 'web', exclude_dirs: [ 'node_modules', '.output', '.nuxt', '.git' ]);
}
$this->handleCustomPort($package_dir);

View File

@ -15,6 +15,8 @@ namespace app\service\core\notice;
use app\job\notice\Notice;
use app\model\sys\SysNotice;
use core\base\BaseCoreService;
use core\exception\NoticeException;
use think\facade\Log;
/**
@ -36,16 +38,19 @@ class NoticeService extends BaseCoreService
* @return false|mixed
* @throws \Exception
*/
public static function send($key, $data){
public static function send($key, $data)
{
try {
$template = (new CoreNoticeService())->getInfo($key);
if(empty($template)) return false;
Log::write("消息发送");
Log::write($template);
if (empty($template)) return false;
return Notice::dispatch(['key' => $key, 'data' => $data, 'template' => $template], is_async:$template['async']);
return Notice::dispatch(['key' => $key, 'data' => $data, 'template' => $template], is_async: $template['async']);
}catch (\Exception $e){
throw new \Exception($e->getMessage());
} catch (\Exception $e) {
throw new NoticeException($e->getMessage());
}
}
}

View File

@ -150,6 +150,7 @@ class CorePayService extends BaseCoreService
* @param string $trade_type
* @param string $trade_id
* @param string $channel
* @param string $scene
* @return array
* @throws DataNotFoundException
* @throws DbException
@ -203,6 +204,8 @@ class CorePayService extends BaseCoreService
* @param string $return_url
* @param string $quit_url
* @param string $buyer_id
* @param string $voucher
* @param int $member_id
* @return mixed
* @throws DataNotFoundException
* @throws DbException
@ -263,7 +266,7 @@ class CorePayService extends BaseCoreService
]
);
if (env('queue.state', true)) {
PayReturnTo::dispatch([ 'out_trade_no' => $out_trade_no ], secs: 60);
PayReturnTo::dispatch([ 'out_trade_no' => $out_trade_no ], secs: 300);
}
}
return $pay_result;
@ -461,13 +464,10 @@ class CorePayService extends BaseCoreService
switch ($action) {
case 'pay'://支付结果通知
return $this->payNotify($out_trade_no, $type, $params);
break;
case 'refund':
return ( new CoreRefundService() )->refundNotify($out_trade_no, $type, $params);
break;
case 'transfer':
return ( new CoreTransferService() )->transferNotify($out_trade_no, $params);
break;
}
//找不到对应的业务
return true;
@ -563,7 +563,6 @@ class CorePayService extends BaseCoreService
Db::rollback();
throw new PayException($e->getMessage() . $e->getFile() . $e->getLine());
}
return true;
}
/**

View File

@ -13,17 +13,10 @@ namespace app\service\core\pay;
use app\dict\pay\TransferDict;
use app\dict\sys\ConfigKeyDict;
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;
/**
* 转账场景服务层
@ -41,7 +34,6 @@ class CoreTransferSceneService extends BaseCoreService
/**
* 获取底部导航配置
* @param string $key
* @return array
*/
public function getWechatTransferSceneConfig()
@ -53,7 +45,6 @@ class CoreTransferSceneService extends BaseCoreService
/**
* 设置微信转账场景导航
* @param array $data
* @param string $key
* @return SysConfig|bool|Model
*/
public function setWechatTransferSceneConfig(array $data)
@ -96,6 +87,7 @@ class CoreTransferSceneService extends BaseCoreService
/**
* 通过业务设置转账场景的配置信息
* @param $type
* @param $data
* @return void
*/

View File

@ -14,8 +14,6 @@ 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;

View File

@ -11,6 +11,7 @@
namespace app\service\core\sys;
use app\dict\sys\StorageDict;
use app\model\sys\SysAttachment;
use app\service\core\upload\CoreFileService;
use core\base\BaseCoreService;
@ -117,13 +118,29 @@ class CoreAttachmentService extends BaseCoreService
if(empty($list))
throw new UploadFileException('PLEACE_SELECT_IMAGE');
$ids = array_column($list, 'att_id');
$del_success_ids = [];
foreach($list as $v){
$file_driver = (new CoreFileService())->driver($v['storage_type']);
//读取上传附件的信息用于后续得校验和数据写入,删除失败直接通过
$file_driver->delete($v['path']);
try {
$file_driver = (new CoreFileService())->driver($v['storage_type']);
//读取上传附件的信息用于后续得校验和数据写入,删除失败直接通过
$file_driver->delete($v['path']);
} catch (\Exception $e) {
// 如果附件在云存储中删除失败后 尝试该资源是否是在平台云存储中
if ($v['storage_type'] != StorageDict::LOCAL) {
try {
$file_driver = (new CoreFileService())->driver(0, $v['storage_type']);
$file_driver->delete($v['path']);
} catch (\Exception $e) {
if (!empty($del_success_ids)) {
$this->model->destroy($del_success_ids);
}
throw new UploadFileException($e->getMessage());
}
}
}
$del_success_ids[] = $v['att_id'];
}
$this->model->destroy($ids);
$this->model->destroy($del_success_ids);
return true;
}
}

View File

@ -14,8 +14,10 @@ namespace app\service\core\sys;
use app\dict\sys\ExportDict;
use app\model\sys\SysExport;
use core\base\BaseCoreService;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use think\facade\Log;
@ -111,7 +113,7 @@ class CoreExportService extends BaseCoreService
$data_list = [];
foreach ($data_array as $v)
{
$data_list = empty($data_list) ? $v : array_merge($data_list, $v);
$data_list = array_merge($data_list, $v );
}
return $data_list;
}
@ -195,9 +197,17 @@ class CoreExportService extends BaseCoreService
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);
$cell_value = $item[$k] ?? '';
$cell_coordinate = $v['excel_column_name'] . $row;
// 步骤1获取单元格对象
$cell = $sheet->getCell($cell_coordinate);
// 步骤2强制单元格格式为纯文本核心
$cell->getStyle()->getNumberFormat()->setFormatCode(NumberFormat::FORMAT_TEXT);
// 步骤3显式赋值为字符串类型避免解析为公式核心
$cell->setValueExplicit($cell_value, DataType::TYPE_STRING);
// 将样式应用到单元格(原有逻辑保留)
$sheet->getStyle($cell_coordinate)->applyFromArray($style_array);
// todo 合并行
if (isset($v['merge_type']) && $v['merge_type'] == 'column') {

View File

@ -65,7 +65,7 @@ class CoreWeappCloudService extends CoreCloudBaseService
// 如果不存在编译版小程序
if ($compile_addon->isEmpty()) {
dir_copy($this->root_path . 'uni-app', $uni_dir, exclude_dirs: [ 'node_modules', 'unpackage', 'dist' ]);
dir_copy($this->root_path . 'uni-app', $uni_dir, exclude_dirs: [ 'node_modules', 'unpackage', 'dist', '.git' ]);
// $this->handleTabbar($uni_dir . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR);
// 替换env文件
$this->weappEnvReplace($uni_dir . DIRECTORY_SEPARATOR . '.env.production');
@ -90,7 +90,7 @@ class CoreWeappCloudService extends CoreCloudBaseService
'do' => 1,
'timestamp' => time()
];
$response = ( new CloudService() )->httpPost('cloud/weapp?' . http_build_query($query), [
$response = ( new CloudService(true) )->httpPost('cloud/weapp?' . http_build_query($query), [
'multipart' => [
[
'name' => 'file',
@ -189,7 +189,7 @@ class CoreWeappCloudService extends CoreCloudBaseService
$query = [
'authorize_code' => $this->auth_code,
];
$preview_url = ( new CloudService() )->getUrl('cloud/get_weapp_preview?' . http_build_query($query));
$preview_url = ( new CloudService(true) )->getUrl('cloud/get_weapp_preview?' . http_build_query($query));
try {
$path = runtime_path() . uniqid() . '.jpg';
@ -211,7 +211,7 @@ class CoreWeappCloudService extends CoreCloudBaseService
'authorize_code' => $this->auth_code,
'timestamp' => $timestamp
];
$build_log = ( new CloudService() )->httpGet('cloud/get_weapp_logs?' . http_build_query($query));
$build_log = ( new CloudService(true) )->httpGet('cloud/get_weapp_logs?' . http_build_query($query));
if (isset($build_log[ 'data' ]) && isset($build_log[ 'data' ][ 0 ]) && is_array($build_log[ 'data' ][ 0 ])) {
$last = end($build_log[ 'data' ][ 0 ]);

View File

@ -138,12 +138,13 @@ class CoreWechatServeService extends BaseCoreService
}
$scene = [ $sceneKey => $key ];
$param = [
'expire_seconds' => $expire_seconds, // 二维码的有效时间
'expire_seconds' => $expire_seconds,
'action_name' => $type,
'action_info' => [
'scene' => $scene
],
];
return $api->postJson('cgi-bin/qrcode/create', $param);
$response = $api->postJson('cgi-bin/qrcode/create', $param);
return json_decode($response->getContent(), true);
}
}

View File

@ -0,0 +1,85 @@
<?php
namespace app\upgrade\v158;
use app\model\diy\Diy;
use app\model\diy_form\DiyForm;
class Upgrade
{
public function handle()
{
$this->handleDiyData();
$this->handleDiyFormData();
}
/**
* 处理自定义数据
* @return void
* @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,value';
$list = $diy_model->where($where)->field($field)->select()->toArray();
$components_names = ['GoodsList','ManyGoodsList','ShopExchangeGoods','ShopGoodsRecommend','SingleRecommend','ShopNewcomer','ShopGoodsRanking','ShopGoodsHot'];
if (!empty($list)) {
foreach ($list as $k => $v) {
$diy_data = json_decode($v['value'], true);
$diy_data['global']['copyright']['textColor'] = '#ccc';
foreach ($diy_data['value'] as $k1=>$v1) {
if (in_array($v1['componentName'],$components_names)){
$diy_data['value'][$k1]['mode'] = 'aspectFill';
}
}
$diy_data = json_encode($diy_data);
$diy_model->where([['id', '=', $v['id']]])->update(['value' => $diy_data]);
}
}
}
/**
* 处理万能表单数据
* @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();
$where = [
['value', '<>', '']
];
$field = 'form_id,value';
$list = $diy_form_model->where($where)->field($field)->select()->toArray();
$components_names = ['GoodsList','ManyGoodsList','ShopExchangeGoods','ShopGoodsRecommend','SingleRecommend','ShopNewcomer','ShopGoodsRanking','ShopGoodsHot'];
if (!empty($list)) {
foreach ($list as $k => $v) {
$diy_data = $v['value'];
if (!isset($diy_data['global']['copyright']['textColor'])) {
$diy_data['global']['copyright']['textColor'] = '#ccc';
}
foreach ($diy_data['value'] as $k1=>$v1) {
if (in_array($v1['componentName'],$components_names)){
$diy_data['value'][$k1]['mode'] = 'aspectFill';
}
}
$diy_form_model->where([['form_id', '=', $v['form_id']]])->update(['value' => $diy_data]);
}
}
}
}

View File

@ -0,0 +1,2 @@
ALTER TABLE `verify`
CHANGE COLUMN `value` `value` TEXT DEFAULT NULL COMMENT '核销内容';

View File

@ -6,8 +6,8 @@ use core\dict\DictLoader;
$data = [
// 指令定义
'commands' => [
'addon:install' => 'app\command\Addon\Install',
'addon:uninstall' => 'app\command\Addon\Uninstall',
'addon:install' => 'app\command\addon\Install',
'addon:uninstall' => 'app\command\addon\Uninstall',
'menu:refresh' => 'app\command\Menu',
//消息队列 自定义命令
'queue:work' => 'app\command\queue\Queue',
@ -19,7 +19,7 @@ $data = [
'workerman' => 'app\command\workerman\Workerman',
//重置管理员密码
'reset:password' => 'app\command\Resetpassword',
'refresh:area' => 'app\command\refreshAreaCommand',
'refresh:area' => 'app\command\RefreshAreaCommand',
],
];
return (new DictLoader("Console"))->load($data);

View File

@ -1,5 +1,5 @@
<?php
return [
'version' => '1.5.7',
'code' => '202511120001'
'version' => '1.5.8',
'code' => '202603210001'
];

View File

@ -233,8 +233,12 @@ class Alipay extends BasePay
'out_trade_no' => $out_trade_no
];
} else {
//todo 这儿可以抛出错误
return false;
return [
'status' => RefundDict::FAIL,
'refund_no' => $refund_no,
'out_trade_no' => $out_trade_no,
'fail_reason' => $result['sub_msg'] ?? ''
];
}
}

View File

@ -130,13 +130,14 @@ class Wechatpay extends BasePay
public function app(array $params)
{
try {
return $this->returnFormat(Pay::wechat()->app([
$result = $this->returnFormat(Pay::wechat()->app([
'out_trade_no' => $params['out_trade_no'],
'description' => $params['body'],
'amount' => [
'total' => $params['money'],
],
]));
return ['orderInfo' => $result];
} catch (\Exception $e) {
if ($e instanceof InvalidResponseException) {
throw new PayException($e->response->all()['message'] ?? '');

View File

@ -49,7 +49,7 @@ class Niuyun extends BaseSms
*/
public function send(string $mobile, string $template_id, array $data = [])
{
Log::write("SEND_NY_SMS pre " . json_encode($data, 256));
Log::write("SEND_NY_SMS pre mobile: ".$mobile.' tem_id:'.$template_id . json_encode($data, 256));
if (empty($this->signature)) {
throw new CommonException('签名未配置');
}

View File

@ -17,6 +17,7 @@ use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use EasyWeChat\Kernel\Support\Collection;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;
use think\facade\Log;
class Weapp extends BaseTemplate
@ -42,12 +43,13 @@ class Weapp extends BaseTemplate
public function send(array $data)
{
$api = CoreWeappService::appApiClient();
$api->postJson('cgi-bin/message/subscribe/send', [
$res = $api->postJson('cgi-bin/message/subscribe/send', [
'template_id' => $data['template_id'], // 所需下发的订阅模板id
'touser' => $data['openid'], // 接收者(用户)的 openid
'page' => $data['page'], // 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,示例index?foo=bar。该字段不填则模板无跳转。
'data' => $data['data'],
]);
Log::write("发送小程序消息Response-" . json_encode($res->toArray(), 256));
}
/**
@ -60,11 +62,13 @@ class Weapp extends BaseTemplate
public function addTemplate(array $data)
{
$api = CoreWeappService::appApiClient();
return $api->postJson('wxaapi/newtmpl/addtemplate', [
$res = $api->postJson('wxaapi/newtmpl/addtemplate', [
'tid' => $data['tid'],
'kidList' => $data['kid_list'],
'sceneDesc' => $data['scene_desc'],
]);
Log::write("添加小程序模版Response-" . json_encode($res->toArray(), 256));
return $res;
}
/**
@ -77,9 +81,11 @@ class Weapp extends BaseTemplate
public function delete(array $data)
{
$api = CoreWeappService::appApiClient();
return $api->postJson('wxaapi/newtmpl/deltemplate', [
$res = $api->postJson('wxaapi/newtmpl/deltemplate', [
'priTmplId' => $data['template_id'],
]);
Log::write("删除小程序模版Response-" . json_encode($res->toArray(), 256));
return $res;
}
/**

View File

@ -0,0 +1,100 @@
<?php
namespace core\util\http;
use core\util\http\src\HasHttpRequests;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Message\ResponseInterface;
class HttpClient
{
use HasHttpRequests;
/**
*
* @var \think\facade\Request|\think\Request
*/
protected $request;
/**
*/
public function __construct()
{
}
/**
* @param string $url
* @param array $data
* @return array|Response|object|ResponseInterface
* @throws GuzzleException
*/
public function httpPost(string $url, array $data = [], array $options = [])
{
return $this->request($url, 'POST', array_merge([
'json' => $data,
'headers' => [
'Content-Type' => 'application/json;charset=utf-8'
]
], $options));
}
/**
* @param string $url
* @param array $data
* @return array|Response|object|ResponseInterface
* @throws GuzzleException
*/
public function httpPut(string $url, array $data = [], array $options = [])
{
return $this->request($url, 'PUT', array_merge([
'json' => $data,
'headers' => [
'Content-Type' => 'application/json;charset=utf-8'
]
], $options));
}
/**
* @param string $url
* @param string $method
* @param array $options
* @param bool $returnRaw
*
* @return ResponseInterface
* @throws GuzzleException
*/
public function request(string $url, string $method = 'GET', array $options = [], bool $returnRaw = false)
{
$response = $this->toRequest($url, $method, $options);
return $response;
}
/**
* @param string $url
* @param array $query
* @return array|object|Response|ResponseInterface
* @throws GuzzleException
*/
public function httpGet(string $url, array $query = [], array $options = [])
{
return $this->request($url, 'GET', array_merge([
'query' => $query,
], $options));
}
/**
* @param string $url
* @param array $data
* @param array $query
* @return array|Response|object|ResponseInterface
* @throws GuzzleException
*/
public function httpPostJson(string $url, array $data = [], array $query = [])
{
return $this->request($url, 'POST', ['query' => $query, 'json' => $data]);
}
}

View File

@ -0,0 +1,183 @@
<?php
namespace core\util\http\src;
use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\HandlerStack;
use Psr\Http\Message\ResponseInterface;
use function GuzzleHttp\choose_handler;
trait HasHttpRequests
{
/**
* curl的自定义选项
* @var array
*/
protected static array $defaults = [
'curl' => [
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
],
];
/**
* @var ClientInterface
*/
protected $httpClient;
/**
* @var array
*/
protected array $middlewares = [];
/**
* @var HandlerStack
*/
protected $handlerStack;
/**
* @param array $defaults
* @return void
*/
public static function setDefaultOptions(array $defaults = [])
{
self::$defaults = $defaults;
}
/**
* @return array
*/
public static function getDefaultOptions(): array
{
return self::$defaults;
}
/**
* @param callable $middleware
* @param string|null $name
* @return $this
*/
public function pushMiddleware(callable $middleware, string $name = null)
{
if (!is_null($name)) {
$this->middlewares[$name] = $middleware;
} else {
$this->middlewares[] = $middleware;
}
return $this;
}
/**
* @return array
*/
public function getMiddlewares(): array
{
return $this->middlewares;
}
/**
* @param $url
* @param string $method
* @param array $options
* @return ResponseInterface
* @throws GuzzleException
*/
public function toRequest($url, string $method = 'GET', array $options = [])
{
$method = strtoupper($method);
$options = array_merge(self::$defaults, $options, ['handler' => $this->getHandlerStack()]);
$options = $this->fixJsonIssue($options);
if (property_exists($this, 'baseUri') && !is_null($this->baseUri)) {
$options['base_uri'] = $this->baseUri;
}
$options['connect_timeout'] = 10;
$response = $this->getHttpClient()->request($method, $url, $options);
$response->getBody()->rewind();
return json_decode($response->getBody()->getContents(), true);
}
/**
* @return HandlerStack
*/
public function getHandlerStack(): HandlerStack
{
if ($this->handlerStack) {
return $this->handlerStack;
}
$this->handlerStack = HandlerStack::create($this->getGuzzleHandler());
foreach ($this->middlewares as $name => $middleware) {
$this->handlerStack->push($middleware, $name);
}
return $this->handlerStack;
}
/**
* @param HandlerStack $handlerStack
*
* @return $this
*/
public function setHandlerStack(HandlerStack $handlerStack)
{
$this->handlerStack = $handlerStack;
return $this;
}
/**
* @return callable
*/
protected function getGuzzleHandler()
{
return choose_handler();
}
/**
* @param array $options
* @return array
*/
protected function fixJsonIssue(array $options): array
{
if (isset($options['json']) && is_array($options['json'])) {
$options['headers'] = array_merge($options['headers'] ?? [], ['Content-Type' => 'application/json']);
if (empty($options['json'])) {
$options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_FORCE_OBJECT);
} else {
$options['body'] = \GuzzleHttp\json_encode($options['json'], JSON_UNESCAPED_UNICODE);
}
unset($options['json']);
}
return $options;
}
/**
* @return ClientInterface
*/
public function getHttpClient(): ClientInterface
{
if (!($this->httpClient instanceof ClientInterface)) {
$this->httpClient = new Client(['handler' => HandlerStack::create($this->getGuzzleHandler())]);
}
return $this->httpClient;
}
/**
* @param ClientInterface $httpClient
* @return $this
*/
public function setHttpClient(ClientInterface $httpClient)
{
$this->httpClient = $httpClient;
return $this;
}
}

View File

@ -30,6 +30,9 @@ class CloudService
$local_cloud_compile_config = (new CoreConfigService())->getConfig(0, 'LOCAL_CLOUD_COMPILE_CONFIG')['value'] ?? [];
if (!empty($local_cloud_compile_config) && isset($local_cloud_compile_config['isOpen']) && $local_cloud_compile_config['isOpen'] == 1){
$baseUri = $local_cloud_compile_config['baseUri'] ?? '';
if (empty($baseUri)){
throw new CommonException("已开启`第三方云编译`,但未配置云编译服务器地址,详情查看:平台端》云编译》第三方云编译");
}
}
if (!empty($local_cloud_compile)){

View File

@ -34,6 +34,7 @@ trait AccessToken
{
$this->access_token = '';
Cache::delete($this->access_token_cache);
if (file_exists(public_path() . 'access_token.txt')) unlink(file_exists(public_path() . 'access_token.txt'));
return $this;
}
/**
@ -55,6 +56,9 @@ trait AccessToken
if (empty($this->access_token)) {
$this->access_token = Cache::get($this->access_token_cache, '');
}
if (empty($this->access_token) && file_exists(public_path() . 'access_token.txt')) {
$this->access_token = file_get_contents(public_path() . 'access_token.txt');
}
return $this->access_token;
}
@ -67,7 +71,9 @@ trait AccessToken
{
$access_token_info = $this->httpGet('auth', ['code' => $this->code, 'secret' => $this->secret, 'token' => $this->createToken(), 'product_key' => self::PRODUCT, 'redirect_uri' => $this->getDomain(false)]);
if (isset($access_token_info['code']) && $access_token_info['code'] != 1) throw new NiucloudException($access_token_info['msg']);
$this->setAccessToken($access_token_info['data']['token']);
if (isset($access_token_info['data']['token']) && !empty($access_token_info['data']['token'])) {
$this->setAccessToken($access_token_info['data']['token']);
}
}
}

View File

@ -164,7 +164,10 @@ trait HasHttpRequests
public function getHttpClient(): ClientInterface
{
if (!($this->httpClient instanceof ClientInterface)) {
$this->httpClient = new Client(['handler' => HandlerStack::create($this->getGuzzleHandler())]);
$this->httpClient = new Client([
'handler' => HandlerStack::create($this->getGuzzleHandler()),
// 'proxy'=>''//调试放开
]);
}
return $this->httpClient;