初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

261
app/Controller.php Executable file
View File

@@ -0,0 +1,261 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app;
use think\App;
use think\facade\View;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use think\Validate;
use liliuwei\think\Jump;
use think\facade\Route;
use think\facade\Config;
use think\facade\Env;
/**
* 控制器基础类
*/
abstract class Controller
{
use Jump;
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct()
{
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{
}
/**
* 加载模板输出
* @access protected
* @param string $template 模板文件名
* @param array $vars 模板输出变量
* @param array $config 模板参数
* @return mixed
*/
protected function fetch($template = '', $vars = [], $config = [])
{
if (!empty($config)) {
$config_view = Config::get('view');
$config_view[ 'tpl_replace_string' ] = array_merge($config_view[ 'tpl_replace_string' ], $config);
Config::set($config_view, 'view');
}
return View::fetch($template, $vars);
}
/**
* 渲染内容输出
* @access protected
* @param string $content 模板内容
* @param array $vars 模板输出变量
* @param array $config 模板参数
* @return mixed
*/
protected function display($content = '', $vars = [], $config = [])
{
return View::display($content, $vars, $config);
}
/**
* 模板变量赋值
* @access protected
* @param mixed $name 要显示的模板变量
* @param mixed $value 变量的值
* @return $this
*/
protected function assign($name, $value = '')
{
View::assign($name, $value);
return $this;
}
/**
* 操作成功跳转的快捷方法
* @access protected
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function success($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
{
if (is_null($url) && isset($_SERVER[ "HTTP_REFERER" ])) {
$url = $_SERVER[ "HTTP_REFERER" ];
} elseif ($url) {
$url = ( strpos($url, '://') || 0 === strpos($url, '/') ) ? $url : $this->app->route->buildUrl($url);
}
$result = [
'code' => 1,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
$type = 'html';
// 把跳转模板的渲染下沉,这样在 response_send 行为里通过getData()获得的数据是一致性的格式
if ('html' == strtolower($type)) {
$type = 'view';
$response = Response::create(config('jump.dispatch_success_tmpl'), $type)->assign($result)->header($header);
} else {
$response = Response::create($result, $type)->header($header);
}
throw new HttpResponseException($response);
}
/**
* 操作错误跳转的快捷方法
* @access protected
* @param mixed $msg 提示信息
* @param string $url 跳转的URL地址
* @param mixed $data 返回的数据
* @param integer $wait 跳转等待时间
* @param array $header 发送的Header信息
* @return void
*/
protected function error($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
{
if (is_null($url)) {
$url = 'javascript:history.back(-1);';
} elseif ($url) {
$url = ( strpos($url, '://') || 0 === strpos($url, '/') ) ? $url : $this->app->route->buildUrl($url);
}
$result = [
'code' => 0,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
$type = 'html';
if ('html' == strtolower($type)) {
$type = 'view';
$response = Response::create(config('jump.dispatch_error_tmpl'), $type)->assign($result)->header($header);
} else {
$response = Response::create($result, $type)->header($header);
}
throw new HttpResponseException($response);
}
/**
* 返回封装后的API数据到客户端
* @access protected
* @param mixed $data 要返回的数据
* @param integer $code 返回的code
* @param mixed $msg 提示信息
* @param string $type 返回数据格式
* @param array $header 发送的Header信息
* @return void
*/
protected function result($data, $code = 0, $msg = '', $type = '', array $header = [])
{
$result = [
'code' => $code,
'msg' => $msg,
'time' => time(),
'data' => $data,
];
$type = 'html';
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
/**
* URL重定向
* @access protected
* @param string $url 跳转的URL表达式
* @param integer $code http code
* @param array $with 隐式传参
* @return void
*/
protected function redirect($url, $code = 302, $with = [])
{
$response = Response::create($url, 'redirect');
$response->code($code)->with($with);
throw new HttpResponseException($response);
}
/**
* @param array $data 验证数据
* @param 验证类 $validate
* @param 验证场景 $scene
*/
public function validate(array $data, $validate, $scene = '')
{
try {
$class = new $validate;
if (!empty($scene)) {
$res = $class->scene($scene)->check($data);
} else {
$res = $class->check($data);
}
if (!$res) {
return error(-1, $class->getError());
} else
return success(1);
} catch (\Exception $e) {
return error(-1, $e->getMessage());
}
}
}

88
app/ExceptionHandle.php Executable file
View File

@@ -0,0 +1,88 @@
<?php
namespace app;
use app\exception\ApiException;
use app\exception\BaseException;
use extend\exception\OrderException;
use extend\exception\StockException;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\facade\View;
use think\Response;
use think\template\exception\TemplateNotFoundException;
use Throwable;
/**
* 应用异常处理类
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
];
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception) : void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}
/**
* @param \think\Request $request
* @param Throwable $e
* @return Response
* @throws \Exception
*/
public function render($request, Throwable $e) : Response
{
if ($e instanceof HttpException) {
return view(app()->getRootPath() . 'public/error/error.html');
} elseif ($e instanceof ApiException || $e instanceof OrderException) {
//针对api异常处理
$data = [
'code' => $e->getCode(),
'message' => $e->getMessage(),
'timestamp' => time()
];
return Response::create($data, 'json', 200);
} elseif ($e instanceof StockException) {
//针对api异常处理
$data = [
'code' => $e->getCode(),
'message' => $e->getMessage(),
'timestamp' => time()
];
return Response::create($data, 'json', 200);
} elseif (!env('app_debug') && ( $request->isPost() || $request->isAjax() ) && !( $e instanceof HttpResponseException )) {
$data = [
'code' => -1,
'message' => "系统异常:" . $e->getMessage(),
'timestamp' => time()
];
return Response::create($data, 'json', 200);
}
// 其他错误交给系统处理
return parent::render($request, $e);
}
}

107
app/Request.php Executable file
View File

@@ -0,0 +1,107 @@
<?php
namespace app;
// 应用请求对象类
class Request extends \think\Request
{
/**
* 站点id
* @var int
*/
protected $site_id = 0;
/**
* 当前访问插件
* @var string
*/
protected $addon;
/**
* 当前访问应用(模块)
* @var string
*/
protected $module;
/**
* 解析url
* @var unknown
*/
protected $parseUrl;
protected $filter = [ 'filterEmoji', 'removeXss' ,'filterSpaces'];
/**
* 站点id
* @param number $siteid
*/
public function siteid($siteid = 1)
{
return 1;
}
/**
* 当前访问插件
* @param string $addon
* @return string
*/
public function addon($addon = '')
{
if (!empty($addon)) {
$GLOBALS[ "REQUEST_ADDON" ] = $addon;
}
if (isset($GLOBALS[ "REQUEST_ADDON" ])) {
return str_replace('shop.html', '', $GLOBALS[ "REQUEST_ADDON" ]);
}
}
/**
* 当前访问模块
* @param string $module
*/
public function module($module = '')
{
$module = str_replace('.html', '', $module);
if (!empty($module)) {
$GLOBALS[ "REQUEST_MODULE" ] = $module;
}
return $GLOBALS[ "REQUEST_MODULE" ] ?? '';
}
/**
* 判断当前是否是微信浏览器
*/
public function isWeixin()
{
if (strpos($_SERVER[ 'HTTP_USER_AGENT' ], 'MicroMessenger') !== false) {
return 1;
}
return 0;
}
/**
* 当前登录用户id
* @return mixed|number
*/
public function uid($app_module)
{
$uid = session($app_module . "." . "uid");
if (!empty($uid)) {
return $uid;
} else {
return 0;
}
}
/**
* 解析url
*/
public function parseUrl()
{
$addon = $this->addon() ? $this->addon() . '://' : '';
return $addon . $this->module() . '/' . $this->controller() . '/' . $this->action();
}
}

40
app/api/controller/Addon.php Executable file
View File

@@ -0,0 +1,40 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
*/
namespace app\api\controller;
use app\model\system\Addon as AddonModel;
/**
* 插件管理
* @author Administrator
*
*/
class Addon extends BaseApi
{
/**
* 列表信息
*/
public function lists()
{
$addon = new AddonModel();
$list = $addon->getAddonList();
return $this->response($list);
}
public function addonIsExit()
{
$addon_model = new AddonModel();
$res = $addon_model->addonIsExist();
return $this->response($this->success($res));
}
}

67
app/api/controller/Address.php Executable file
View File

@@ -0,0 +1,67 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
*/
namespace app\api\controller;
use app\model\system\Address as AddressModel;
/**
* 地址管理
* @author Administrator
*
*/
class Address extends BaseApi
{
/**
* 基础信息
*/
public function info()
{
$id = $this->params['id'];
$address = new AddressModel();
$info = $address->getAreaInfo($id);
return $this->response($info);
}
/**
* 列表信息
*/
public function lists()
{
$pid = $this->params['pid'] ?? 0;
$address = new AddressModel();
$list = $address->getAreas($pid);
return $this->response($list);
}
/**
* 树状结构信息
*/
public function tree()
{
$id = $this->params['id'];
$address = new AddressModel();
$tree = $address->getAreas($id);
return $this->response($tree);
}
/**
* 解析地址
*/
public function analysesAddress()
{
$address = input('address', '');
$address_model = new AddressModel();
return $this->response($address_model->analysesAddress($address));
}
}

60
app/api/controller/Adv.php Executable file
View File

@@ -0,0 +1,60 @@
<?php
/**
* Adv.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 山西牛酷信息科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\web\AdvPosition as AdvPositionModel;
use app\model\web\Adv as AdvModel;
class Adv extends BaseApi
{
/**
* 详情信息
*/
public function detail()
{
$keyword = $this->params['keyword'] ?? '';
//广告位
$adv_position_model = new AdvPositionModel();
$adv_position_info = $adv_position_model->getAdvPositionInfo([
[ 'keyword', '=', $keyword ],
[ 'site_id', '=', $this->site_id ],
[ 'state', '=', 1 ],
])[ 'data' ];
//广告图
$adv_list = [];
if (!empty($adv_position_info)) {
$adv_model = new AdvModel();
$adv_list = $adv_model->getAdvList(
[
[ 'ap_id', '=', $adv_position_info[ 'ap_id' ] ],
[ 'state', '=', 1 ],
],
$field = 'adv_id, adv_title, ap_id, adv_url, adv_image, slide_sort, price, background'
)[ 'data' ];
}
$res = [
'adv_position' => $adv_position_info,
'adv_list' => $adv_list,
];
return $this->response($this->success($res));
}
}

95
app/api/controller/Article.php Executable file
View File

@@ -0,0 +1,95 @@
<?php
namespace app\api\controller;
use app\model\article\Article as ArticleModel;
use app\model\article\ArticleCategory as ArticleCategoryModel;
/**
* 文章接口
* Class Goodsbrand
* @package app\api\controller
*/
class Article extends BaseApi
{
public function info()
{
$article_id = $this->params['article_id'] ?? 0;
if (empty($article_id)) {
return $this->response($this->error('', '缺少参数article_id'));
}
$article_model = new ArticleModel();
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'article_id', '=', $article_id ],
[ 'status', '=', 1 ]
];
$field = 'article_id, article_title, article_abstract, category_id, cover_img, article_content, is_show_release_time, is_show_read_num, is_show_dianzan_num, read_num, dianzan_num, create_time, initial_read_num, initial_dianzan_num';
$res = $article_model->getArticleDetailInfo($condition, $field, 2);
if (empty($res[ 'data' ])) {
return $this->response($this->error('', '文章不存在'));
}
return $this->response($res);
}
public function page()
{
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$article_id_arr = $this->params['article_id_arr'] ?? '';
$category_id = $this->params['category_id'] ?? '';
$condition = [
[ 'pn.site_id', '=', $this->site_id ],
[ 'pn.status', '=', 1 ],
];
if (!empty($article_id_arr)) {
$condition[] = [ 'pn.article_id', 'in', $article_id_arr ];
}
if (!empty($category_id)) {
$condition[] = [ 'pn.category_id', '=', $category_id ];
}
$order_by = 'pn.sort desc,pn.create_time desc';
$article_model = new ArticleModel();
$list = $article_model->getArticlePageList($condition, $page, $page_size, $order_by);
return $this->response($list);
}
public function lists()
{
$num = $this->params['num'] ?? 0;
$article_id_arr = $this->params['article_id_arr'] ?? '';
$condition = [
[ 'pn.site_id', '=', $this->site_id ],
[ 'pn.status', '=', 1 ],
];
if (!empty($article_id_arr)) {
$condition[] = [ 'article_id', 'in', $article_id_arr ];
}
$order_by = 'pn.sort desc,pn.create_time desc';
$alias = 'pn';
$join = [
[
'article_category png',
'png.category_id = pn.category_id',
'left'
]
];
$field = 'pn.*,png.category_name';
$article_model = new ArticleModel();
$list = $article_model->getArticleList($condition, $field, $order_by, $num, $alias, $join);
return $this->response($list);
}
/**
* 获取文章分类
* @return false|string
*/
public function category()
{
$article_category_model = new ArticleCategoryModel();
$res = $article_category_model->getArticleCategoryList([ [ 'site_id', '=', $this->site_id ] ], 'category_id,category_name,article_num', 'sort desc');
return $this->response($res);
}
}

350
app/api/controller/BaseApi.php Executable file
View File

@@ -0,0 +1,350 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\api\controller;
use app\exception\ApiException;
use app\model\shop\Shop;
use app\model\system\Api;
use Exception;
use think\facade\Cache;
use addon\store\model\Config as StoreConfig;
use app\model\store\Store;
use think\Response;
class BaseApi
{
public $lang;
public $params;
public $token;
protected $member_id = 0;
protected $site_id;
protected $app_module = 'shop';
public $app_type;
private $refresh_token;
/**
* 所选门店id
* @var
*/
protected $store_id = 0; // 门店id
/**
* 门店数据
* @var
*/
protected $store_data = [
'config' => [
'store_business' => 'shop'
]
];
public function __construct()
{
if ($_SERVER[ 'REQUEST_METHOD' ] == 'OPTIONS') {
exit;
}
//获取参数
$this->site_id = request()->siteid();
$this->params = input();
$this->params[ 'site_id' ] = $this->site_id;
$shop_model = new Shop();
$shop_status = $shop_model->getShopStatus($this->site_id, 'shop');
//默认APP类型处理
if (!isset($this->params[ 'app_type' ])) $this->params[ 'app_type' ] = 'h5';
if ($this->params[ 'app_type' ] == 'pc') {
if (!$shop_status[ 'data' ][ 'value' ][ 'shop_pc_status' ]) throw new ApiException(-3, '网站已关闭!');
} else if ($this->params[ 'app_type' ] == 'weapp') {
if (!$shop_status[ 'data' ][ 'value' ][ 'shop_weapp_status' ]) throw new ApiException(-3, '网站已关闭!');
} else if ($this->params[ 'app_type' ] == 'h5' || $this->params[ 'app_type' ] == 'wechat') {
if (!$shop_status[ 'data' ][ 'value' ][ 'shop_h5_status' ]) throw new ApiException(-3, '网站已关闭!');
}
$this->store_id = $this->params[ 'store_id' ] ?? 0;
}
/**
* 初始化门店数据
*/
protected function initStoreData()
{
$store_model = new Store();
$default_store = $store_model->getDefaultStore($this->site_id)[ 'data' ];
$this->store_data[ 'default_store' ] = $default_store ? $default_store[ 'store_id' ] : 0;
$this->store_id = $this->store_id ? : $this->store_data[ 'default_store' ];
if (addon_is_exit('store', $this->site_id)) {
$this->store_data[ 'config' ] = (new StoreConfig())->getStoreBusinessConfig($this->site_id)[ 'data' ][ 'value' ];
if ($this->store_id == $this->store_data[ 'default_store' ]) $this->store_data[ 'store_info' ] = $default_store;
else $this->store_data[ 'store_info' ] = $store_model->getStoreInfo([['site_id', '=', $this->site_id], ['store_id', '=', $this->store_id]])[ 'data' ];
// 禁止用户切换门店
if ($this->store_data[ 'config' ][ 'is_allow_change' ] == 0) {
if (empty($this->store_data[ 'store_info' ]) || $this->store_data[ 'store_info' ][ 'status' ] == 0) {
throw new ApiException(-3, '门店已关闭!');
}
if (empty($this->store_data[ 'store_info' ]) || $this->store_data[ 'store_info' ][ 'is_frozen' ] == 1) {
throw new ApiException(-3, '门店已停业!');
}
}
}
}
/**
* 检测token(使用私钥检测)
*/
protected function checkToken() : array
{
if (empty($this->params[ 'token' ])) return $this->error('', 'TOKEN_NOT_EXIST');
$key = 'site' . $this->site_id;
$api_model = new Api();
$api_config = $api_model->getApiConfig()[ 'data' ];
if ($api_config[ 'is_use' ] && isset($api_config[ 'value' ][ 'private_key' ]) && !empty($api_config[ 'value' ][ 'private_key' ])) {
$key = $api_config[ 'value' ][ 'private_key' ] . $key;
}
$decrypt = decrypt($this->params[ 'token' ], $key);
if (empty($decrypt)) return $this->error('', 'TOKEN_ERROR');
$data = json_decode($decrypt, true);
if (empty($data[ 'member_id' ])) return $this->error('', 'TOKEN_ERROR');
if ($data[ 'expire_time' ] < time()) {
if ($data[ 'expire_time' ] != 0) {
return $this->error('', 'TOKEN_EXPIRE');
}
} else if (($data[ 'expire_time' ] - time()) < 300 && !Cache::get('member_token' . $data[ 'member_id' ])) {
$this->refresh_token = $this->createToken($data[ 'member_id' ]);
Cache::set('member_token' . $data[ 'member_id' ], $this->refresh_token, 360);
}
$this->member_id = $data[ 'member_id' ];
return success(0, '', $data);
}
/**
* 创建token
* @param
* @return string
*/
protected function createToken($member_id)
{
$api_model = new Api();
$config_result = $api_model->getApiConfig();
$config = $config_result[ 'data' ];
# $expire_time 有效时间 0为永久 单位s
if ($config) {
$expire_time = round($config[ 'value' ][ 'long_time' ] * 3600);
} else {
$expire_time = 0;
}
$key = 'site' . $this->site_id;
$api_model = new Api();
$api_config = $api_model->getApiConfig()[ 'data' ];
if ($api_config[ 'is_use' ] && isset($api_config[ 'value' ][ 'private_key' ]) && !empty($api_config[ 'value' ][ 'private_key' ])) {
$key = $api_config[ 'value' ][ 'private_key' ] . $key;
}
$data = [
'member_id' => $member_id,
'create_time' => time(),
'expire_time' => empty($expire_time) ? 0 : time() + $expire_time
];
return encrypt(json_encode($data), $key);
}
/**
* 返回数据
* @param $data
* @return false|string
*/
public function response($data)
{
$data[ 'timestamp' ] = time();
if (!empty($this->refresh_token)) $data[ 'refreshtoken' ] = $this->refresh_token;
return Response::create($data, 'json', 200);
}
/**
* 操作成功返回值函数
* @param string $data
* @param string $code_var
* @return array
*/
public function success($data = '', $code_var = 'SUCCESS')
{
$lang_array = $this->getLang();
$code_array = $this->getCode();
$lang_var = $lang_array[ $code_var ] ?? $code_var;
$code_var = $code_array[ $code_var ] ?? $code_array[ 'SUCCESS' ];
return success($code_var, $lang_var, $data);
}
/**
* 操作失败返回值函数
* @param string $data
* @param string $code_var
* @return array
*/
public function error($data = '', $code_var = 'ERROR')
{
$lang_array = $this->getLang();
$code_array = $this->getCode();
$lang_var = $lang_array[ $code_var ] ?? $code_var;
$code_var = $code_array[ $code_var ] ?? $code_array[ 'ERROR' ];
return error($code_var, $lang_var, $data);
}
/**
* 获取语言包数组
* @return Ambigous <multitype:, unknown>
*/
private function getLang()
{
$default_lang = config('lang.default_lang');
$addon = request()->addon();
$addon = $addon ?? '';
$cache_common = Cache::get('lang_app/api/lang/' . $default_lang);
if (empty($cache_common)) {
$cache_common = include 'app/api/lang/' . $default_lang . '.php';
Cache::tag('lang')->set('lang_app/api/lang/' . $default_lang, $cache_common);
}
if (!empty($addon)) {
try {
$addon_lang_file = 'addon/' . $addon . '/api/lang/' . $default_lang . '.php';
if(is_file($addon_lang_file)){
$addon_cache_common = include $addon_lang_file;
if (!empty($addon_cache_common)) {
$cache_common = array_merge($cache_common, $addon_cache_common);
Cache::tag('lang')->set('lang_app/api/lang/' . $addon . '_' . $default_lang, $addon_cache_common);
}
}
} catch (Exception $e) {
}
}
return $cache_common;
}
/**
* 获取code编码
* @return Ambigous <multitype:, unknown>
*/
private function getCode()
{
$addon = request()->addon();
$addon = $addon ?? '';
$cache_common = Cache::get('lang_code_app/api/lang');
if (!empty($addon)) {
$addon_cache_common = Cache::get('lang_code_app/api/lang/' . $addon);
if (!empty($addon_cache_common)) {
$cache_common = array_merge($cache_common, $addon_cache_common);
}
}
if (empty($cache_common)) {
$cache_common = include 'app/api/lang/code.php';
Cache::tag('lang_code')->set('lang_code_app/api/lang', $cache_common);
if (!empty($addon)) {
try {
$addon_cache_common = include 'addon/' . $addon . '/api/lang/code.php';
if (!empty($addon_cache_common)) {
Cache::tag('lang_code')->set('lang_code_app/api/lang/' . $addon, $addon_cache_common);
$cache_common = array_merge($cache_common, $addon_cache_common);
}
} catch (Exception $e) {
}
}
}
$lang_path = $this->lang ?? '';
if (!empty($lang_path)) {
$cache_path = Cache::get('lang_code_' . $lang_path);
if (empty($cache_path)) {
$cache_path = include $lang_path . '/code.php';
Cache::tag('lang')->set('lang_code_' . $lang_path, $cache_path);
}
$lang = array_merge($cache_common, $cache_path);
} else {
$lang = $cache_common;
}
return $lang;
}
/**
* @param array $data 验证数据
* @param 验证类 $validate
* @param 验证场景 $scene
*/
public function validate(array $data, $validate, $scene = '')
{
try {
$class = new $validate;
if (!empty($scene)) {
$res = $class->scene($scene)->check($data);
} else {
$res = $class->check($data);
}
if (!$res) {
return error(-1, $class->getError());
} else
return success(1);
} catch (ValidateException $e) {
return error(-1, $e->getError());
} catch (Exception $e) {
return error(-1, $e->getMessage());
}
}
public function checkSign(): array
{
$sign = $this->params['sign'] ?? '';
if(empty($sign)){
return error(-1,'非法请求');
}
$time = $this->params['time'] ?? '';
if(empty($time) || !is_numeric($time) || $time<time()-10 || $time > time() + 10){
return error(-1,'time参数有误');
}
$api_model = new Api();
$api_config = $api_model->getApiConfig()[ 'data' ];
$key = 'site' . $this->site_id;
if (!empty($api_config[ 'value' ][ 'private_key' ])) {
$key = $api_config[ 'value' ][ 'private_key' ] . $key;
}
$key = preg_replace("/[^A-Za-z0-9]/", '', $key);
if($sign == md5( 'key='.$key.'&time='.$time)){
return success(0, '');
}
return $this->error(-1,'验签失败');
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
/**
* 订单创建
*/
class BaseOrderCreateApi extends BaseApi
{
/**
* 公共参数
* @return array
*/
public function getCommonParam()
{
return [
'site_id' => $this->site_id,
'store_id' => $this->params['store_id'] ?? 0,
'member_id' => $this->member_id,
'order_from' => $this->params['app_type'],
'order_from_name' => $this->params['app_type_name'],
'sale_channel' => 'all,online',
];
}
/**
* 获取发票参数
* @return array
*/
public function getInvoiceParam()
{
return [
'is_invoice' => $this->params['is_invoice'] ?? 0,
'invoice_type' => $this->params['invoice_type'] ?? 0,
'invoice_title' => $this->params['invoice_title'] ?? '',
'taxpayer_number' => $this->params['taxpayer_number'] ?? '',
'invoice_content' => $this->params['invoice_content'] ?? '',
'invoice_full_address' => $this->params['invoice_full_address'] ?? '',
'is_tax_invoice' => $this->params['is_tax_invoice'] ?? 0,
'invoice_email' => $this->params['invoice_email'] ?? '',
'invoice_title_type' => $this->params['invoice_title_type'] ?? 0,
];
}
/**
* 获取配送相关参数
* @return array
*/
public function getDeliveryParam()
{
if(isset($this->params['delivery']) && !is_string($this->params['delivery'])) $this->params['delivery'] = '';
if(!empty($this->params['member_address']) && is_array($this->params['member_address'])){
$this->params['member_address'] = json_encode($this->params['member_address']);
};
$data = [
//运费相关
'delivery' => isset($this->params['delivery']) && !empty($this->params['delivery']) ? json_decode($this->params['delivery'], true) : [],
'member_address' => isset($this->params['member_address']) && !empty($this->params['member_address']) ? json_decode($this->params['member_address'], true) : [],
'latitude' => $this->params['latitude'] ?? '',
'longitude' => $this->params['longitude'] ?? '',
];
return $data;
}
/**
* 传入参数
* @return array
*/
public function getInputParam()
{
return [
//留言
'buyer_message' => $this->params[ 'buyer_message' ] ?? '',
//自定义表单
'form_data' => isset($this->params[ 'form_data' ]) && !empty($this->params[ 'form_data' ]) ? json_decode($this->params[ 'form_data' ], true) : [],
];
}
}

49
app/api/controller/Captcha.php Executable file
View File

@@ -0,0 +1,49 @@
<?php
namespace app\api\controller;
use think\captcha\facade\Captcha as ThinkCaptcha;
use think\facade\Cache;
class Captcha extends BaseApi
{
/**
* 验证码
*/
public function captcha()
{
if (isset($this->params[ 'captcha_id' ]) && !empty($this->params[ 'captcha_id' ])) {
Cache::delete($this->params[ 'captcha_id' ]);
}
$captcha_data = ThinkCaptcha::create(null, true);
$captcha_id = md5(uniqid(null, true));
// 验证码10分钟有效
Cache::set($captcha_id, $captcha_data[ 'code' ], 600);
return $this->response($this->success([ 'id' => $captcha_id, 'img' => $captcha_data[ 'img' ] ]));
}
/**
* 检测验证码
* @param boolean $snapchat 阅后即焚
*/
public function checkCaptcha($snapchat = true) : array
{
if (!isset($this->params[ 'captcha_id' ]) || empty($this->params[ 'captcha_id' ])) {
return $this->error('', 'REQUEST_CAPTCHA_ID');
}
if (!isset($this->params[ 'captcha_code' ]) || empty($this->params[ 'captcha_code' ])) {
return $this->error('', 'REQUEST_CAPTCHA_CODE');
}
if ($snapchat) $captcha_data = Cache::pull($this->params[ 'captcha_id' ]);
else $captcha_data = Cache::get($this->params[ 'captcha_id' ]);
if (empty($captcha_data)) return $this->error('', 'CAPTCHA_FAILURE');
if ($this->params[ 'captcha_code' ] != $captcha_data) return $this->error('', 'CAPTCHA_ERROR');
return $this->success();
}
}

286
app/api/controller/Cart.php Executable file
View File

@@ -0,0 +1,286 @@
<?php
namespace app\api\controller;
use app\model\goods\Cart as CartModel;
use app\model\goods\Goods;
class Cart extends BaseApi
{
/**
* 添加信息
*/
public function add()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$sku_id = $this->params['sku_id'] ?? 0;
$num = $this->params['num'] ?? 0;
$form_data = $this->params[ 'form_data' ] ?? '';
if (empty($sku_id)) {
return $this->response($this->error('', 'REQUEST_SKU_ID'));
}
if (empty($num)) {
return $this->response($this->error('', 'REQUEST_NUM'));
}
$cart = new CartModel();
$data = [
'site_id' => $this->site_id,
'member_id' => $this->member_id,
'sku_id' => $sku_id,
'num' => $num,
'form_data' => $form_data
];
$res = $cart->addCart($data);
return $this->response($res);
}
/**
* 编辑信息
*/
public function edit()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$cart_id = $this->params['cart_id'] ?? 0;
$num = $this->params['num'] ?? 0;
$form_data = $this->params[ 'form_data' ] ?? '';
if (empty($cart_id)) {
return $this->response($this->error('', 'REQUEST_CART_ID'));
}
if (empty($num)) {
return $this->response($this->error('', 'REQUEST_NUM'));
}
$cart = new CartModel();
$data = [
'cart_id' => $cart_id,
'member_id' => $this->member_id,
'num' => $num,
'form_data' => $form_data
];
$res = $cart->editCart($data);
return $this->response($res);
}
/**
* 删除信息
*/
public function delete()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$cart_id = $this->params['cart_id'] ?? 0;
if (empty($cart_id)) {
return $this->response($this->error('', 'REQUEST_CART_ID'));
}
$cart = new CartModel();
$data = [
'cart_id' => $cart_id,
'member_id' => $this->member_id,
];
$res = $cart->deleteCart($data);
return $this->response($res);
}
/**
* 清空购物车
*/
public function clear()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$cart = new CartModel();
$data = [
'member_id' => $this->member_id,
];
$res = $cart->clearCart($data);
return $this->response($res);
}
/**
* 商品购物车列表
*/
public function goodsLists()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$this->initStoreData();
$goods = new Goods();
$condition = [
[ 'ngc.site_id', '=', $this->site_id ],
[ 'ngc.member_id', '=', $this->member_id ],
[ 'ngs.is_delete', '=', 0 ]
];
$field = 'ngc.cart_id, ngc.site_id, ngc.member_id, ngc.sku_id, ngc.num, ngs.sku_name,ngs.goods_id,
ngs.sku_no, ngs.sku_spec_format,ngs.price,ngs.market_price, ngs.goods_spec_format,
ngs.discount_price, ngs.promotion_type, ngs.start_time, ngs.end_time, ngs.stock, ngs.sale_channel,
ngs.sku_image, ngs.sku_images, ngs.goods_state, ngs.goods_stock_alarm, ngs.is_virtual, ngs.goods_name, ngs.is_consume_discount, ngs.discount_config, ngs.member_price, ngs.discount_method,
ngs.virtual_indate, ngs.is_free_shipping, ngs.shipping_template, ngs.unit, ngs.introduction,ngs.sku_spec_format, ngs.keywords, ngs.max_buy, ngs.min_buy, ns.site_name, ngs.is_limit, ngs.limit_type';
$join = [
[ 'goods_cart ngc', 'ngc.sku_id = ngs.sku_id', 'inner' ],
[ 'site ns', 'ns.site_id = ngs.site_id', 'left' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'ngs.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'left' ];
$field .= ',IFNULL(sgs.status, 0) as store_goods_status';
$field = str_replace('ngs.price', 'IFNULL(IF(ngs.is_unify_price = 1,ngs.price,sgs.price), ngs.price) as price', $field);
$field = str_replace('ngs.discount_price', 'IFNULL(IF(ngs.is_unify_price = 1,ngs.discount_price,sgs.price), ngs.discount_price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('ngs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
}
}
$list = $goods->getGoodsSkuList($condition, $field, 'ngc.cart_id desc', null, 'ngs', $join);
//库存转换处理
$list['data'] = $goods->goodsStockTransform($list['data'], $this->store_id, $this->store_data[ 'config' ][ 'store_business' ]);
if (!empty($list[ 'data' ])) {
// 销售渠道设置为线上销售时门店商品状态为1
foreach ($list[ 'data' ] as $k => $v) {
$store_goods_status = 1;
if ($v[ 'sale_channel' ] == 'offline') {
$store_goods_status = 0;
}
$list[ 'data' ][ $k ][ 'store_goods_status' ] = $store_goods_status;
}
$list[ 'data' ] = $goods->getGoodsListMemberPrice($list[ 'data' ], $this->member_id);
}
return $this->response($list);
}
/**
* 获取购物车数量
* @return string
*/
public function count()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$this->initStoreData();
$cart = new CartModel();
$condition = [
[ 'gc.member_id', '=', $this->member_id ],
[ 'gc.site_id', '=', $this->site_id ],
[ 'gs.goods_state', '=', 1 ],
[ 'gs.is_delete', '=', 0 ]
];
$join = [
[ 'goods_sku gs', 'gc.sku_id = gs.sku_id', 'inner' ]
];
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'sgs.status = 1 and gs.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'right' ];
}
$count = $cart->getCartSum($condition, 'gc.num', 'gc', $join);
return $this->response($count);
}
/**
* 购物车关联列表
* @return false|string
*/
public function lists()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$this->initStoreData();
$goods = new Goods();
$condition = [
[ 'ngc.site_id', '=', $this->site_id ],
[ 'ngc.member_id', '=', $this->member_id ],
[ 'ngs.is_delete', '=', 0 ]
];
$field = 'ngc.cart_id,ngc.sku_id,ngs.goods_id,ngs.discount_price,ngc.num, ngs.is_consume_discount,ngs.discount_method,ngs.member_price,ngs.discount_config,ngs.price,ngs.stock,ngs.max_buy,ngs.min_buy,ngs.goods_name';
$join = [
[ 'goods_cart ngc', 'ngc.sku_id = ngs.sku_id', 'inner' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'sgs.status = 1 and ngs.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'right' ];
$field = str_replace('ngs.discount_price', 'IFNULL(IF(ngs.is_unify_price = 1,ngs.discount_price,sgs.price), ngs.discount_price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('ngs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
}
}
$list = $goods->getGoodsSkuList($condition, $field, 'ngc.cart_id desc', null, 'ngs', $join);
if (!empty($list[ 'data' ])) {
//获取会员价
$list[ 'data' ] = $goods->getGoodsListMemberPrice($list[ 'data' ], $this->member_id);
foreach ($list[ 'data' ] as $k => $v) {
if (!empty($v[ 'member_price' ]) && $v[ 'member_price' ] < $v[ 'discount_price' ]) {
$list[ 'data' ][ $k ][ 'discount_price' ] = $v[ 'member_price' ];
}
$list[ 'data' ][ $k ][ 'total_money' ] = $list[ 'data' ][ $k ][ 'discount_price' ] * $v[ 'num' ];
}
}
return $this->response($list);
}
/**
* 获取会员购物车中商品数量
* @return false|string
*/
public function goodsNum()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$goods_id = $this->params[ 'goods_id' ] ?? 0;
$condition = [
[ 'gc.member_id', '=', $this->member_id ],
[ 'gc.site_id', '=', $this->site_id ],
[ 'gs.goods_id', '=', $goods_id ]
];
$join = [
[
'goods_sku gs',
'gc.sku_id = gs.sku_id',
'left'
]
];
$cart = new CartModel();
$data = $cart->getCartSum($condition, 'gc.num', 'gc', $join);
return $this->response($data);
}
public function editCartSku()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$cart_id = $this->params[ 'cart_id' ] ?? 0;
$num = $this->params[ 'num' ] ?? 0;
$sku_id = $this->params[ 'sku_id' ] ?? 0;
if (empty($cart_id)) return $this->response($this->error('', 'REQUEST_CART_ID'));
if (empty($num)) return $this->response($this->error('', 'REQUEST_NUM'));
if (empty($sku_id)) return $this->response($this->error('', 'REQUEST_SKU_ID'));
$cart = new CartModel();
$data = [
'cart_id' => $cart_id,
'site_id' => $this->site_id,
'member_id' => $this->member_id,
'num' => $num,
'sku_id' => $sku_id
];
$res = $cart->editCartSku($data);
return $this->response($res);
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\cart\CartCalculate as CartCalculateModel;
/**
* 购物车计算
* @author Administrator
*
*/
class Cartcalculate extends BaseApi
{
/**
* 购物车计算
*/
public function calculate()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$this->initStoreData();
$sku_ids = isset($this->params[ 'sku_ids' ]) ? json_decode($this->params[ 'sku_ids' ], true) : [];
$data = [
'sku_ids' => $sku_ids,
'site_id' => $this->site_id,//站点id
'member_id' => $this->member_id,
'order_from' => $this->params[ 'app_type' ],
'order_from_name' => $this->params[ 'app_type_name' ],
'store_id' => $this->store_id,
'store_data' => $this->store_data
];
$cart_calculate_model = new CartCalculateModel();
$res = $cart_calculate_model->calculate($data);
return $this->response($this->success($res));
}
}

206
app/api/controller/Config.php Executable file
View File

@@ -0,0 +1,206 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
*/
namespace app\api\controller;
use app\model\express\Config as ExpressConfig;
use app\model\system\Api;
use app\model\system\Promotion as PromotionModel;
use app\model\system\Servicer;
use app\model\system\Site as SiteModel;
use app\model\web\Config as ConfigModel;
use app\model\web\DiyView as DiyViewModel;
class Config extends BaseApi
{
/**
* 详情信息
*/
public function defaultimg()
{
$upload_config_model = new ConfigModel();
$res = $upload_config_model->getDefaultImg($this->site_id, 'shop');
if (!empty($res[ 'data' ][ 'value' ])) {
return $this->response($this->success($res[ 'data' ][ 'value' ]));
} else {
return $this->response($this->error());
}
}
/**
* 版权信息
*/
public function copyright()
{
$config_model = new ConfigModel();
$res = $config_model->getCopyright($this->site_id, 'shop');
return $this->response($this->success($res[ 'data' ][ 'value' ]));
}
/**
* 获取当前时间戳
* @return false|string
*/
public function time()
{
$time = time();
return $this->response($this->success($time));
}
/**
* 获取验证码配置
*/
public function getCaptchaConfig()
{
$config_model = new ConfigModel();
$info = $config_model->getCaptchaConfig();
return $this->response($this->success($info[ 'data' ][ 'value' ]));
}
/**
* 客服配置
*/
public function servicer()
{
$servicer_model = new Servicer();
$result = $servicer_model->getServicerConfig()[ 'data' ] ?? [];
return $this->response($this->success($result[ 'value' ] ?? []));
}
/**
* 系统初始化配置信息
* @return false|string
*/
public function init()
{
$diy_view = new DiyViewModel();
$diy_style = $diy_view->getStyleConfig($this->site_id)[ 'data' ][ 'value' ];
// 底部导航
$diy_bottom_nav = $diy_view->getBottomNavConfig($this->site_id)[ 'data' ][ 'value' ];
// 插件存在性
$addon = new \app\model\system\Addon();
$addon_is_exist = $addon->addonIsExist();
// 默认图
$config_model = new ConfigModel();
$default_img = $config_model->getDefaultImg($this->site_id, 'shop')[ 'data' ][ 'value' ];
// 版权信息
$copyright = $config_model->getCopyright($this->site_id, 'shop')[ 'data' ][ 'value' ];
$map_config = $config_model->getMapConfig($this->site_id, 'shop')[ 'data' ][ 'value' ];
$website_model = new SiteModel();
$site_info = $website_model->getSiteInfo([ [ 'site_id', '=', $this->site_id ] ], 'site_id,site_domain,site_name,logo,seo_title,seo_keywords,seo_description,site_tel,logo_square')[ 'data' ];
$servicer_model = new Servicer();
$servicer_info = $servicer_model->getServicerConfig()[ 'data' ][ 'value' ] ?? [];
$this->initStoreData();
//微信配置状态
$wechat_config_status = 0;
if(addon_is_exit('wechat')){
$config_model = new \addon\wechat\model\Config();
$config_info = $config_model->getWechatConfig($this->site_id)['data']['value'];
if (!empty($config_info[ 'appid' ]) && !empty($config_info[ 'appsecret' ])) {
$wechat_config_status = 1;
}
}
$res = [
'style_theme' => $diy_style,
'diy_bottom_nav' => $diy_bottom_nav,
'addon_is_exist' => $addon_is_exist,
'default_img' => $default_img,
'copyright' => $copyright,
'site_info' => $site_info,
'servicer' => $servicer_info,
'store_config' => $this->store_data[ 'config' ],
'map_config' => $map_config,
'wechat_config_status' => $wechat_config_status,
];
if (!empty($this->store_data[ 'store_info' ])) {
$res[ 'store_info' ] = $this->store_data[ 'store_info' ];
}
return $this->response($this->success($res));
}
/**
* 获取pc首页商品分类配置
* @return false|string
*/
public function categoryconfig()
{
$config_model = new ConfigModel();
$config_info = $config_model->getCategoryConfig($this->site_id);
return $this->response($this->success($config_info[ 'data' ][ 'value' ]));
}
/**
*配送方式配置信息(启用的)
* @return false|string
*/
public function enabledExpressType()
{
$express_type = ( new ExpressConfig() )->getEnabledExpressType($this->site_id);
return $this->response($this->success($express_type));
}
/**
* 获取活动专区页面配置
* @return false|string
*/
public function promotionZoneConfig()
{
$name = $this->params['name'] ?? ''; // 活动名称标识
if (empty($name)) {
return $this->response($this->error([], '缺少必填参数name'));
}
$promotion_model = new PromotionModel();
$res = $promotion_model->getPromotionZoneConfig($name, $this->site_id)[ 'data' ][ 'value' ];
return $this->response($this->success($res));
}
public function getApiConfig()
{
$api_model = new Api();
$config_result = $api_model->getApiConfig();
$api_config = $config_result[ "data" ];
$key = 'site' . $this->site_id;
if (!empty($api_config[ 'value' ][ 'private_key' ])) {
$key = $api_config[ 'value' ][ 'private_key' ] . $key;
}
$key = preg_replace("/[^A-Za-z0-9]/", '', $key);
$res = [
'time'=>time(),
'key'=>$key
];
return $this->response($this->success($res));
}
public function geMapConfig()
{
$map_model = new \app\model\map\QqMap();
$res = [
'key'=>$map_model->getKey()
];
return $this->response($this->success($res));
}
}

84
app/api/controller/Diyview.php Executable file
View File

@@ -0,0 +1,84 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\api\controller;
use app\model\web\DiyView as DiyViewModel;
/**
* 自定义模板
* @package app\api\controller
*/
class Diyview extends BaseApi
{
/**
* 基础信息
*/
public function info()
{
$id = $this->params['id'] ?? 0;
$name = $this->params['name'] ?? '';
if (empty($id) && empty($name)) {
return $this->response($this->error('', 'REQUEST_DIY_ID_NAME'));
}
$this->initStoreData();
// 如果是连锁运营模式,则进入门店页面
if ($name == 'DIY_VIEW_INDEX' && $this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$name = 'DIY_STORE';
}
$diy_view = new DiyViewModel();
$condition = [
[ 'site_id', '=', $this->site_id ]
];
if (!empty($id)) {
$condition[] = [ 'id', '=', $id ];
} elseif (!empty($name)) {
$condition[] = [ 'name', '=', $name ];
$condition[] = [ 'is_default', '=', 1 ];
}
$info = $diy_view->getDiyViewInfoInApi($condition);
//去除访问站点
/* if (!empty($info[ 'data' ])) {
$diy_view->modifyClick([ [ 'id', '=', $info[ 'data' ][ 'id' ] ], [ 'site_id', '=', $this->site_id ] ]);
}*/
return $this->response($info);
}
/**
* 平台端底部导航
* @return string
*/
public function bottomNav()
{
$diy_view = new DiyViewModel();
$info = $diy_view->getBottomNavConfig($this->site_id);
return $this->response($info);
}
/**
* 风格
*/
public function style()
{
$diy_view = new DiyViewModel();
$res = $diy_view->getStyleConfig($this->site_id);
return $this->response($res);
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
*/
namespace app\api\controller;
use app\model\member\Member as MemberModel;
use app\model\member\Register as RegisterModel;
use app\model\message\Message;
use think\facade\Cache;
class Findpassword extends BaseApi
{
/**
* 手机号找回密码
*/
public function mobile()
{
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if (!$exist) {
return $this->response($this->error('', '手机号不存在'));
} else {
$key = $this->params[ 'key' ];
$verify_data = Cache::get($key);
if (!empty($verify_data) && $verify_data[ 'mobile' ] == $this->params[ 'mobile' ] && $verify_data[ 'code' ] == $this->params[ 'code' ]) {
$member_model = new MemberModel();
$res = $member_model->resetMemberPassword($this->params[ 'password' ], [['mobile', '=', $this->params[ 'mobile' ]]]);
} else {
$res = $this->error('', '手机动态码不正确');
}
return $this->response($res);
}
}
/**
* 短信验证码
*/
public function mobileCode()
{
// 校验验证码
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha();
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
$mobile = $this->params[ 'mobile' ];//注册手机号
$register = new RegisterModel();
$exist = $register->mobileExist($mobile, $this->site_id);
if (!$exist) {
return $this->response($this->error('', '手机号不存在'));
} else {
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage(['type' => 'code', 'mobile' => $mobile, 'site_id' => $this->site_id, 'code' => $code, 'support_type' => ['sms'], 'keywords' => 'FIND_PASSWORD']);
if ($res[ 'code' ] >= 0) {
//将验证码存入缓存
$key = 'find_mobile_code_' . md5(uniqid(null, true));
Cache::tag('find_mobile_code')->set($key, ['mobile' => $mobile, 'code' => $code], 600);
return $this->response($this->success(['key' => $key]));
} else {
return $this->response($res);
}
}
}
}

56
app/api/controller/Game.php Executable file
View File

@@ -0,0 +1,56 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
*/
namespace app\api\controller;
use app\model\games\Games;
use app\model\games\Record;
/**
* 小游戏
* @author Administrator
*
*/
class Game extends BaseApi
{
/**
* 会员中奖纪录分页列表信息
*/
public function recordPage()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$id = $this->params['id'] ?? 0;
$condition = [
[ 'game_id', '=', $id ],
[ 'is_winning', '=', 1 ],
[ 'member_id', '=', $this->member_id ]
];
$field = 'member_nick_name,points,is_winning,award_name,award_type,relate_id,relate_name,point,balance,create_time';
$record = new Record();
$list = $record->getGamesDrawRecordPageList($condition, $page, $page_size, 'create_time desc', $field);
return $this->response($list);
}
/**
* 最新一条正在进行的活动
* @return false|string
*/
public function newestGame()
{
$res = ( new Games() )->getFirstInfo([ [ 'site_id', '=', $this->site_id ], [ 'status', '=', 1 ] ], 'game_id,game_type', 'game_id desc');
return $this->response($res);
}
}

132
app/api/controller/Goods.php Executable file
View File

@@ -0,0 +1,132 @@
<?php
namespace app\api\controller;
use app\model\goods\Goods as GoodsModel;
use app\model\goods\GoodsService;
use app\model\order\OrderCommon;
use app\model\system\Poster;
use app\model\goods\Config as GoodsConfigModel;
use app\model\web\Config as ConfigModel;
class Goods extends BaseApi
{
/**
* 修改商品点击量
* @return string
*/
public function modifyclicks()
{
$sku_id = $this->params['sku_id'] ?? 0;
if (empty($sku_id)) {
return $this->response($this->error('', 'REQUEST_SKU_ID'));
}
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$goods_model = new GoodsModel();
$res = $goods_model->modifyClick($sku_id, $this->site_id);
return $this->response($res);
}
/**
* 获取商品海报
*/
public function poster()
{
$this->checkToken();
$promotion_type = 'null';
$qrcode_param = json_decode($this->params[ 'qrcode_param' ], true);
$qrcode_param[ 'source_member' ] = $this->member_id;
$poster = new Poster();
$res = $poster->goods($this->params[ 'app_type' ], $this->params[ 'page' ], $qrcode_param, $promotion_type, $this->site_id, $this->store_id);
return $this->response($res);
}
/**
* 售后保障
* @return false|string
*/
public function aftersale()
{
$goods_config_model = new GoodsConfigModel();
$res = $goods_config_model->getAfterSaleConfig($this->site_id);
return $this->response($res);
}
/**
* 获取热门搜索关键词
*/
public function hotSearchWords()
{
$config_model = new ConfigModel();
$info = $config_model->getHotSearchWords($this->site_id, $this->app_module);
return $this->response($this->success($info[ 'data' ][ 'value' ]));
}
/**
* 获取默认搜索关键词
*/
public function defaultSearchWords()
{
$config_model = new ConfigModel();
$info = $config_model->getDefaultSearchWords($this->site_id, $this->app_module);
return $this->response($this->success($info[ 'data' ][ 'value' ]));
}
/**
* 商品服务
* @return false|string
*/
public function service()
{
$goods_service = new GoodsService();
$data = $goods_service->getServiceList([ [ 'site_id', '=', $this->site_id ] ], 'service_name,desc,icon');
foreach ($data[ 'data' ] as $key => $val) {
$data[ 'data' ][ $key ][ 'icon' ] = json_decode($val[ 'icon' ], true);
}
return $this->response($data);
}
/**
* 商品弹幕
* @return false|string
*/
public function goodsBarrage()
{
$goods_id = $this->params['goods_id'] ?? 0;
$order = new OrderCommon();
$field = 'm.headimg as img, m.nickname as title';
$join = [
[
'member m',
'm.member_id=og.member_id',
'left'
],
[
'order o',
'o.order_id=og.order_id',
'left'
]
];
$data = $order->getOrderGoodsPageList([ [ 'og.site_id', '=', $this->site_id ], [ 'og.goods_id', '=', $goods_id ], [ 'o.pay_status', '=', 1 ] ], 1, 20, 'og.order_goods_id desc', $field, 'og', $join, 'o.member_id');
return $this->response($data);
}
/**
* 小程序分享图
* @return false|string
*/
public function shareImg()
{
$qrcode_param = json_decode($this->params[ 'qrcode_param' ] ?? '{}', true);
$poster = new Poster();
$res = $poster->shareImg($this->params[ 'page' ] ?? '', $qrcode_param, $this->site_id, $this->store_id);
return $this->response($res);
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace app\api\controller;
use app\model\goods\GoodsBrand as GoodsBrandModel;
/**
* 商品品牌接口
* Class Goodsbrand
* @package app\api\controller
*/
class Goodsbrand extends BaseApi
{
public function page()
{
$page = $this->params[ 'page' ] ?? 1;
$page_size = $this->params[ 'page_size' ] ?? PAGE_LIST_ROWS;
$brand_id_arr = $this->params[ 'brand_id_arr' ] ?? '';
$goods_brand_model = new GoodsBrandModel();
$condition = [
[ 'site_id', '=', $this->site_id ]
];
if (!empty($brand_id_arr)) {
$condition[] = [ 'brand_id', 'in', $brand_id_arr ];
}
$list = $goods_brand_model->getBrandPageList($condition, $page, $page_size, 'sort desc,create_time desc', 'brand_id,brand_name,brand_initial,image_url, banner, brand_desc');
return $this->response($list);
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace app\api\controller;
use app\model\goods\GoodsBrowse as GoodsBrowseModel;
use app\model\goods\Goods as GoodsModel;
/**
* 商品浏览历史
* @package app\api\controller
*/
class Goodsbrowse extends BaseApi
{
/**
* 添加信息
*/
public function add()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$goods_id = $this->params['goods_id'] ?? 0;
$sku_id = $this->params['sku_id'] ?? 0;
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
if (empty($sku_id)) {
return $this->response($this->error('', 'REQUEST_SKU_ID'));
}
$goods_browse_model = new GoodsBrowseModel();
$data = [
'member_id' => $token[ 'data' ][ 'member_id' ],
'goods_id' => $goods_id,
'sku_id' => $sku_id,
'site_id' => $this->site_id,
'app_module' => $this->params[ 'app_type' ]
];
$res = $goods_browse_model->addBrowse($data);
return $this->response($res);
}
/**
* 删除信息
*/
public function delete()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? '';
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$goods_browse_model = new GoodsBrowseModel();
$res = $goods_browse_model->deleteBrowse($id, $token[ 'data' ][ 'member_id' ]);
return $this->response($res);
}
/**
* 分页列表
*/
public function page()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$this->initStoreData();
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$goods_browse_model = new GoodsBrowseModel();
$condition = [
[ 'ngb.member_id', '=', $token[ 'data' ][ 'member_id' ] ]
];
$alias = 'ngb';
$field = 'ngb.id,ngb.member_id,ngb.browse_time,ngb.sku_id,ngs.sku_image,ngs.discount_price,ngs.sku_name,ng.goods_id,ng.goods_name,ng.goods_image,(ngs.sale_num + ngs.virtual_sale) as sale_num,ngs.is_free_shipping,ngs.promotion_type,ngs.member_price,ngs.price,ngs.market_price,ngs.is_virtual,ng.goods_image,ng.sale_show,ng.market_price_show,ngs.unit';
$join = [
[
'goods ng',
'ngb.goods_id = ng.goods_id',
'inner'
],
[
'goods_sku ngs',
'ngb.sku_id = ngs.sku_id',
'inner'
]
];
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'ngs.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'left' ];
$field = str_replace('ngs.price', 'IFNULL(IF(ngs.is_unify_price = 1,ngs.price,sgs.price), ngs.price) as price', $field);
$field = str_replace('ngs.discount_price', 'IFNULL(IF(ngs.is_unify_price = 1,ngs.discount_price,sgs.price), ngs.discount_price) as discount_price', $field);
}
$res = $goods_browse_model->getBrowsePageList($condition, $page, $page_size, 'ngb.browse_time desc', $field, $alias, $join);
$goods = new GoodsModel();
if (!empty($res[ 'data' ][ 'list' ])) {
foreach ($res[ 'data' ][ 'list' ] as $k => $v) {
$res[ 'data' ][ 'list' ][ $k ][ 'sale_num' ] = numberFormat($res[ 'data' ][ 'list' ][ $k ][ 'sale_num' ]);
if ($token[ 'code' ] >= 0) {
// 是否参与会员等级折扣
$goods_member_price = $goods->getGoodsPrice($v[ 'sku_id' ], $this->member_id)[ 'data' ];
if (!empty($goods_member_price[ 'member_price' ])) {
$res[ 'data' ][ 'list' ][ $k ][ 'member_price' ] = $goods_member_price[ 'price' ];
} else {
unset($res[ 'data' ][ 'list' ][ $k ][ 'member_price' ]);
}
} else {
unset($res[ 'data' ][ 'list' ][ $k ][ 'member_price' ]);
}
}
}
return $this->response($res);
}
}

View File

@@ -0,0 +1,81 @@
<?php
namespace app\api\controller;
use app\model\goods\GoodsCategory as GoodsCategoryModel;
/**
* 商品分类
* Class Goodscategory
* @package app\api\controller
*/
class Goodscategory extends BaseApi
{
/**
* 树状结构信息
*/
public function tree()
{
$level = $this->params['level'] ?? 3;// 分类等级 1 2 3
$goods_category_model = new GoodsCategoryModel();
$condition = [
[ 'is_show', '=', 0 ],
[ 'level', '<=', $level ],
[ 'site_id', '=', $this->site_id ]
];
$field = 'category_id,category_name,short_name,pid,level,image,category_id_1,category_id_2,category_id_3,image_adv,link_url,is_recommend,icon';
$order = 'sort asc,category_id desc';
$list = $goods_category_model->getCategoryTree($condition, $field, $order);
return $this->response($list);
}
public function info()
{
$category_id = $this->params[ 'category_id' ] ?? 0;
if(empty($category_id))
{
return $this->response($this->error([], '缺少必须字段category_id'));
}
$goods_category_model = new GoodsCategoryModel();
$res = $goods_category_model->getCategoryInfo([ [ 'category_id', '=', $category_id ], [ 'site_id', '=', $this->site_id ] ]);
if (!empty($res[ 'data' ])) {
$category_ids = [ $res[ 'data' ][ 'category_id_1' ], $res[ 'data' ][ 'category_id_2' ], $res[ 'data' ][ 'category_id_3' ] ];
$category_list = $goods_category_model->getCategoryList([
[ 'site_id', '=', $this->site_id ],
[ 'is_show', '=', 0 ],
[ 'category_id', 'in', $category_ids ]
], 'category_id,category_name')[ 'data' ];
$res[ 'data' ][ 'category_full_name' ] = implode('$_SPLIT_$', array_column($category_list, 'category_name'));
$child_list = $goods_category_model->getCategoryList([ [ 'pid', '=', $category_id ], [ 'site_id', '=', $this->site_id ], [ 'is_show', '=', 0 ] ], 'category_id,category_name,short_name,pid,level,is_show,sort,image,attr_class_id,attr_class_name,category_id_1,category_id_2,category_id_3,commission_rate,image_adv,is_recommend,icon', 'sort asc,category_id desc')[ 'data' ];
if (empty($child_list)) {
// 查询上级商品分类
$child_list = $goods_category_model->getCategoryList([['pid', '=', $res['data']['pid']], ['site_id', '=', $this->site_id], ['is_show', '=', 0]], 'category_id,category_name,short_name,pid,level,is_show,sort,image,attr_class_id,attr_class_name,category_id_1,category_id_2,category_id_3,commission_rate,image_adv,is_recommend,icon', 'sort asc,category_id desc')['data'];
}
$res[ 'data' ][ 'child_list' ] = $child_list;
}
return $this->response($res);
}
/**
* 分类列表
* @return false|string
*/
public function lists()
{
$level = $this->params['level'] ?? 1;// 分类等级 1 2 3
$goods_category_model = new GoodsCategoryModel();
$condition = [
[ 'is_show', '=', 0 ],
[ 'level', '<=', $level ],
[ 'site_id', '=', $this->site_id ]
];
$field = 'category_id,category_name,short_name,pid,level,image,category_id_1,category_id_2,category_id_3,image_adv,link_url,is_recommend,icon';
$order = 'sort asc,category_id desc';
$res = $goods_category_model->getCategoryList($condition, $field, $order);
return $this->response($res);
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace app\api\controller;
use app\model\goods\GoodsCollect as GoodsCollectModel;
use app\model\goods\Goods as GoodsModel;
/**
* 商品收藏
* @author Administrator
*
*/
class Goodscollect extends BaseApi
{
/**
* 添加信息
*/
public function add()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$goods_id = $this->params['goods_id'] ?? 0;
$sku_id = $this->params['sku_id'] ?? 0;
$sku_name = $this->params['sku_name'] ?? '';
$sku_price = $this->params['sku_price'] ?? '';
$sku_image = $this->params['sku_image'] ?? '';
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
if (empty($sku_id)) {
return $this->response($this->error('', 'REQUEST_SKU_ID'));
}
$goods_collect_model = new GoodsCollectModel();
$data = [
'member_id' => $token[ 'data' ][ 'member_id' ],
'goods_id' => $goods_id,
'sku_id' => $sku_id,
'sku_name' => $sku_name,
'sku_price' => $sku_price,
'sku_image' => $sku_image,
'site_id' => $this->site_id
];
$res = $goods_collect_model->addCollect($data);
return $this->response($res);
}
/**
* 删除信息
*/
public function delete()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$goods_id = $this->params['goods_id'] ?? 0;
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
$goods_collect_model = new GoodsCollectModel();
$res = $goods_collect_model->deleteCollect($token[ 'data' ][ 'member_id' ], $goods_id);
return $this->response($res);
}
/**
* 分页列表信息
*/
public function page()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$this->initStoreData();
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$goods_collect_model = new GoodsModel();
$condition = [
[ 'gc.member_id', '=', $token[ 'data' ][ 'member_id' ] ],
[ ' g.is_delete', '=', 0 ]
];
$join = [
[ 'goods_collect gc', 'gc.goods_id = g.goods_id', 'inner' ],
[ 'goods_sku sku', 'g.sku_id = sku.sku_id', 'inner' ]
];
$field = 'gc.collect_id, gc.member_id, gc.goods_id, gc.sku_id,sku.sku_name, gc.sku_price, gc.sku_image,g.goods_name,g.is_free_shipping,sku.promotion_type,sku.member_price,sku.discount_price,g.sale_num,g.price,g.market_price,g.is_virtual, g.goods_image';
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'g.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'left' ];
$field = str_replace('sku.price', 'IFNULL(IF(sku.is_unify_price = 1,sku.price,sgs.price), sku.price) as price', $field);
$field = str_replace('sku.discount_price', 'IFNULL(IF(sku.is_unify_price = 1,sku.discount_price,sgs.price), sku.discount_price) as discount_price', $field);
}
$list = $goods_collect_model->getGoodsPageList($condition, $page, $page_size, 'gc.create_time desc', $field, 'g', $join);
return $this->response($list);
}
/**
* 检测用户是否收藏商品
* @param int $id
* @return false|string
*/
public function iscollect($id = 0)
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$goods_id = $this->params['goods_id'] ?? 0;
if (!empty($id)) {
$goods_id = $id;
}
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
$goods_collect_model = new GoodsCollectModel();
$res = $goods_collect_model->getIsCollect($goods_id, $token[ 'data' ][ 'member_id' ]);
return $this->response($res);
}
}

View File

@@ -0,0 +1,221 @@
<?php
/**
* Goodsevaluate.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\goods\GoodsEvaluate as GoodsEvaluateModel;
use app\model\order\Config as ConfigModel;
/**
* 商品评价
* Class Goodsevaluate
* @package app\api\controller
*/
class Goodsevaluate extends BaseApi
{
/**
* 添加信息·第一次评价
*/
public function add()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? 0;
$order_no = $this->params['order_no'] ?? 0;
$member_name = $this->params['member_name'] ?? '';
$member_headimg = $this->params['member_headimg'] ?? '';
$is_anonymous = $this->params['is_anonymous'] ?? 0;
$goods_evaluate = $this->params['goods_evaluate'] ?? '';
if (empty($order_id)) {
return $this->response($this->error('', 'REQUEST_ORDER_ID'));
}
if (empty($goods_evaluate)) {
return $this->response($this->error('', 'REQUEST_GOODS_EVALUATE'));
}
$goods_evaluate = json_decode($goods_evaluate, true);
$data = [
'order_id' => $order_id,
'order_no' => $order_no,
'member_name' => $member_name,
'member_id' => $token[ 'data' ][ 'member_id' ],
'is_anonymous' => $is_anonymous,
'member_headimg' => $member_headimg,
'goods_evaluate' => $goods_evaluate,
];
$goods_evaluate_model = new GoodsEvaluateModel();
$res = $goods_evaluate_model->addEvaluate($data, $this->site_id);
return $this->response($res);
}
/**
* 追评
* @return string
*/
public function again()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? 0;
$goods_evaluate = $this->params['goods_evaluate'] ?? '';
if (empty($order_id)) {
return $this->response($this->error('', 'REQUEST_ORDER_ID'));
}
if (empty($goods_evaluate)) {
return $this->response($this->error('', 'REQUEST_GOODS_EVALUATE'));
}
$goods_evaluate = json_decode($goods_evaluate, true);
$data = [
'order_id' => $order_id,
'goods_evaluate' => $goods_evaluate
];
$goods_evaluate_model = new GoodsEvaluateModel();
$res = $goods_evaluate_model->evaluateAgain($data, $this->site_id);
return $this->response($res);
}
/**
* 基础信息
* @param int $id
* @return false|string
*/
public function firstinfo($id = 0)
{
$goods_id = $this->params['goods_id'] ?? 0;
if (!empty($id)) {
$goods_id = $id;
}
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
$goods_evaluate_model = new GoodsEvaluateModel();
$condition = [
[ 'is_show', '=', 1 ],
[ 'is_audit', '=', 1 ],
[ 'goods_id', '=', $goods_id ]
];
$field = 'evaluate_id,content,images,explain_first,member_name,member_headimg,is_anonymous,again_content,again_images,again_explain,create_time,again_time,scores';
$order = 'create_time desc';
$info = $goods_evaluate_model->getSecondEvaluateInfo($condition, $field, $order);
return $this->response($info);
}
/**
* 列表信息
*/
public function page()
{
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$goods_id = $this->params['goods_id'] ?? 0;
$explain_type = empty($this->params[ 'explain_type' ]) ? '' : $this->params[ 'explain_type' ];
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
$goods_evaluate_model = new GoodsEvaluateModel();
if (!empty($explain_type)) {
$condition[] = [ 'explain_type', '=', $explain_type ];
}
$condition[] = [ 'is_show', '=', 1 ];
$condition[] = [ 'is_audit', '=', 1 ];
$condition[] = [ 'goods_id', '=', $goods_id ];
// $condition = [
// [ 'is_show', '=', 1 ],
// [ 'is_audit', '=', 1 ],
// [ 'goods_id', '=', $goods_id ]
// ];
$list = $goods_evaluate_model->getEvaluatePageList($condition, $page, $page_size);
return $this->response($list);
}
/**
* 获取评价 1好 2中 3差
*/
public function getGoodsEvaluate()
{
$goods_id = $this->params['goods_id'] ?? 0;
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
$goods_evaluate_model = new GoodsEvaluateModel();
$condition[] = [ 'is_show', '=', 1 ];
$condition[] = [ 'is_audit', '=', 1 ];
$condition[] = [ 'goods_id', '=', $goods_id ];
$list = $goods_evaluate_model->getEvaluateList($condition);
$haoping = 0;
$zhongping = 0;
$chaping = 0;
if (!empty($list[ 'data' ])) {
foreach ($list[ 'data' ] as $k => $v) {
if ($v[ 'explain_type' ] == 1) {
$haoping += 1;
} else if ($v[ 'explain_type' ] == 2) {
$zhongping += 1;
} else {
$chaping += 1;
}
}
}
$data = [
'total' => count($list[ 'data' ]),
'haoping' => $haoping,
'zhongping' => $zhongping,
'chaping' => $chaping
];
return $this->response($this->success($data));
}
/**
* 评价设置
* @return false|string
*/
public function config()
{
$config_model = new ConfigModel();
//订单评价设置
$res = $order_evaluate_config = $config_model->getOrderEvaluateConfig($this->site_id, $this->app_module);
return $this->response($this->success($res[ 'data' ][ 'value' ]));
}
/**
* 评论数量
* @param int $id
* @return false|string
*/
public function count($id = 0)
{
$goods_id = $this->params[ 'goods_id' ] ?? 0;
if (!empty($id)) {
$goods_id = $id;
}
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_GOODS_ID'));
}
$goods_evaluate_model = new GoodsEvaluateModel();
$condition[] = [ 'is_show', '=', 1 ];
$condition[] = [ 'is_audit', '=', 1 ];
$condition[] = [ 'goods_id', '=', $goods_id ];
$count = $goods_evaluate_model->getEvaluateCount($condition);
return $this->response($count);
}
}

861
app/api/controller/Goodssku.php Executable file
View File

@@ -0,0 +1,861 @@
<?php
/**
* Goodssku.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use addon\coupon\model\CouponType;
use addon\coupon\dict\CouponDict;
use app\model\express\Config as ExpressConfig;
use app\model\goods\Goods;
use app\model\goods\GoodsApi;
use app\model\goods\GoodsCategory as GoodsCategoryModel;
use app\model\goods\GoodsService;
use app\model\system\SplitWord;
use app\model\web\Config as ConfigModel;
use extend\BaiDuApi;
use extend\WordSplit;
use think\facade\Db;
/**
* 商品sku
* @author Administrator
*
*/
class Goodssku extends BaseApi
{
public function __construct()
{
parent::__construct();
$this->initStoreData();
}
/**
* 【PC端在用】基础信息
* @return false|string
*/
public function info()
{
$sku_id = $this->params['sku_id'] ?? 0;
if (empty($sku_id)) {
return $this->response($this->error('', 'REQUEST_SKU_ID'));
}
$goods = new Goods();
$field = 'gs.goods_id,gs.sku_id,g.goods_image,g.goods_name,g.keywords,gs.sku_name,gs.sku_spec_format,gs.price,gs.market_price,gs.discount_price,gs.promotion_type
,gs.start_time,gs.end_time,gs.stock,gs.sku_image,gs.sku_images,gs.goods_spec_format,gs.unit,gs.max_buy,gs.min_buy,gs.is_limit,gs.limit_type';
$info = $goods->getGoodsSkuDetail($sku_id, $this->site_id, $field);
if (empty($info[ 'data' ])) return $this->response($this->error());
$token = $this->checkToken();
if ($token[ 'code' ] >= 0) {
// 是否参与会员等级折扣
$goods_member_price = $goods->getGoodsPrice($sku_id, $this->member_id)[ 'data' ];
if (!empty($goods_member_price[ 'member_price' ])) {
$info[ 'data' ][ 'member_price' ] = $goods_member_price[ 'member_price' ];
}
if ($info[ 'data' ][ 'is_limit' ] && $info[ 'data' ][ 'limit_type' ] == 2 && $info[ 'data' ][ 'max_buy' ] > 0) $res[ 'goods_sku_detail' ][ 'purchased_num' ] = $goods->getGoodsPurchasedNum($info[ 'data' ][ 'goods_id' ], $this->member_id);
}
// 查询当前商品参与的营销活动信息
$goods_promotion = event('GoodsPromotion', [ 'goods_id' => $info[ 'data' ][ 'goods_id' ], 'sku_id' => $info[ 'data' ][ 'sku_id' ] ]);
$info[ 'data' ][ 'goods_promotion' ] = $goods_promotion;
//判断是否参与预售
$is_join_presale = event('IsJoinPresale', [ 'sku_id' => $sku_id ], true);
if (!empty($is_join_presale) && $is_join_presale[ 'code' ] == 0) {
$info[ 'data' ] = array_merge($info[ 'data' ], $is_join_presale[ 'data' ]);
}
//库存转换
$info['data'] = $goods->goodsStockTransform([$info['data']], $this->store_id, $this->store_data['config']['store_business'])[0];
return $this->response($info);
}
/**
* 商品详情
* @return false|string
*/
public function detail()
{
$sku_id = $this->params['sku_id'] ?? 0;
$goods_id = $this->params['goods_id'] ?? 0;
if (empty($sku_id) && empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$this->checkToken();
$detail = ( new GoodsApi() )->getGoodsSkuDetail($this->site_id, $sku_id, $goods_id, $this->member_id, $this->store_id, $this->store_data, 'all,online');
return $this->response($detail);
}
/**
* 查询商品SKU集合
* @return false|string
*/
public function goodsSku()
{
$goods_id = $this->params['goods_id'] ?? 0;
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$token = $this->checkToken();
$list = ( new GoodsApi() )->getGoodsSkuList($this->site_id, $goods_id, $this->member_id, $this->store_id, $this->store_data);
return $this->response($list);
}
/**
* 商品详情,商品分类用
* @return false|string
*/
public function getInfoForCategory()
{
$sku_id = $this->params['sku_id'] ?? 0;
if (empty($sku_id)) {
return $this->response($this->error('', 'REQUEST_SKU_ID'));
}
$goods = new Goods();
$condition = [
[ 'gs.sku_id', '=', $sku_id ],
[ 'gs.site_id', '=', $this->site_id ]
];
$field = 'gs.goods_id,gs.sku_id,gs.goods_name,gs.is_limit,gs.limit_type,gs.sku_name,gs.sku_spec_format,gs.price,gs.discount_price,gs.stock,gs.sku_image,gs.goods_spec_format,gs.unit,gs.max_buy,gs.min_buy,gs.goods_state,g.stock_show';
$join = [
[ 'goods g', 'g.goods_id = gs.goods_id', 'inner' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'gs.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'left' ];
$field = str_replace('gs.price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as price', $field);
$field = str_replace('gs.discount_price', 'IFNULL(IF(g.is_unify_price = 1,gs.discount_price,sgs.price), gs.discount_price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('gs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
}
}
$goods_sku_detail = $goods->getGoodsSkuInfo($condition, $field, 'gs', $join);
//库存转换
$goods_sku_detail['data'] = $goods->goodsStockTransform([$goods_sku_detail['data']], $this->store_id, $this->store_data['config']['store_business'])[0];
$token = $this->checkToken();
if ($token[ 'code' ] >= 0) {
// 是否参与会员等级折扣
$goods_member_price = $goods->getGoodsPrice($sku_id, $this->member_id, $this->store_id)[ 'data' ];
if (!empty($goods_member_price[ 'member_price' ])) {
$goods_sku_detail[ 'data' ][ 'member_price' ] = $goods_member_price[ 'member_price' ];
}
if ($goods_sku_detail[ 'data' ][ 'max_buy' ] > 0) $goods_sku_detail[ 'data' ][ 'purchased_num' ] = $goods->getGoodsPurchasedNum($goods_sku_detail[ 'data' ][ 'goods_id' ], $this->member_id);
}
return $this->response($goods_sku_detail);
}
/**
* 查询商品SKU集合商品分类用
* @return false|string
*/
public function goodsSkuByCategory()
{
$goods_id = $this->params['goods_id'] ?? 0;
if (empty($goods_id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$goods = new Goods();
$condition = [
[ 'gs.goods_id', '=', $goods_id ],
[ 'gs.site_id', '=', $this->site_id ]
];
$field = 'gs.sku_id,gs.sku_name,gs.sku_spec_format,gs.price,gs.discount_price,gs.promotion_type,gs.end_time,gs.stock,gs.sku_image,gs.goods_spec_format';
$join = [
[ 'goods g', 'g.goods_id = gs.goods_id', 'inner' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'gs.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'left' ];
$field = str_replace('gs.price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as price', $field);
$field = str_replace('gs.discount_price', 'IFNULL(IF(g.is_unify_price = 1,gs.discount_price,sgs.price), gs.discount_price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('gs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
}
}
$list = $goods->getGoodsSkuList($condition, $field, 'gs.sku_id asc', null, 'gs', $join);
//库存转换
$list['data'] = $goods->goodsStockTransform($list['data'], $this->store_id, $this->store_data['config']['store_business']);
$token = $this->checkToken();
foreach ($list[ 'data' ] as $k => $v) {
if ($token[ 'code' ] >= 0) {
// 是否参与会员等级折扣
$goods_member_price = $goods->getGoodsPrice($v[ 'sku_id' ], $this->member_id, $this->store_id)[ 'data' ];
if (!empty($goods_member_price[ 'member_price' ])) {
$list[ 'data' ][ $k ][ 'member_price' ] = $goods_member_price[ 'member_price' ];
}
}
}
return $this->response($list);
}
/**
* 列表信息
*/
public function page()
{
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$goods_id_arr = $this->params['goods_id_arr'] ?? '';//goods_id数组
$keyword = isset($this->params[ 'keyword' ]) ? trim($this->params[ 'keyword' ]) : '';//关键词
$category_id = $this->params['category_id'] ?? 0;//分类
$brand_id = $this->params[ 'brand_id' ] ?? 0; //品牌
$min_price = $this->params['min_price'] ?? 0;//价格区间,小
$max_price = $this->params['max_price'] ?? 0;//价格区间,大
$is_free_shipping = $this->params['is_free_shipping'] ?? 0;//是否免邮
$order = $this->params['order'] ?? '';//排序(综合、销量、价格)
$sort = $this->params['sort'] ?? '';//升序、降序
$coupon = $this->params['coupon'] ?? 0;//优惠券
$condition = [];
$condition[] = [ 'gs.site_id', '=', $this->site_id ];
$condition[] = [ '', 'exp', Db::raw("(g.sale_channel = 'all' OR g.sale_channel = 'online')") ];
if (!empty($goods_id_arr)) {
$condition[] = [ 'gs.goods_id', 'in', $goods_id_arr ];
}
if (!empty($keyword)) {
$word_split_model = new SplitWord();
$split_word = $word_split_model->getSplitWord($keyword);
if(!empty($split_word['data'])){
foreach ($split_word['data'] as $key=>$val) {
$exp_arr[] = '( INSTR(g.goods_name,\''.$val.'\') > 0 OR INSTR(g.introduction,\''.$val.'\') > 0 OR INSTR(gs.keywords,\''.$val.'\') > 0 OR INSTR(gs.sku_name,\''.$val.'\') > 0 )';
}
$condition[] = [ '', 'exp', \think\facade\Db::raw(join(' or ', $exp_arr)) ];
}else{
$condition[] = [ 'g.goods_name|g.introduction|gs.sku_name|gs.keywords', 'like', '%' . $keyword . '%' ];
}
}
if (!empty($brand_id)) {
$condition[] = [ 'g.brand_id', '=', $brand_id ];
}
$goods_category_model = new GoodsCategoryModel();
if (!empty($category_id)) {
// 查询当前
$category_list = $goods_category_model->getCategoryList([ [ 'category_id', '=', $category_id ], [ 'site_id', '=', $this->site_id ] ], 'category_id,pid,level')[ 'data' ];
// 查询子级
$category_child_list = $goods_category_model->getCategoryList([ [ 'pid', '=', $category_id ], [ 'site_id', '=', $this->site_id ] ], 'category_id,pid,level')[ 'data' ];
$temp_category_list = [];
if (!empty($category_list)) {
$temp_category_list = $category_list;
} elseif (!empty($category_child_list)) {
$temp_category_list = $category_child_list;
}
if (!empty($temp_category_list)) {
$category_id_arr = [];
foreach ($temp_category_list as $k => $v) {
// 三级分类,并且都能查询到
if ($v[ 'level' ] == 3 && !empty($category_list) && !empty($category_child_list)) {
$category_id_arr[] = $v['pid'];
} else {
$category_id_arr[] = $v['category_id'];
}
}
$category_id_arr = array_unique($category_id_arr);
$temp_condition = [];
foreach ($category_id_arr as $ck => $cv) {
$temp_condition[] = '%,' . $cv . ',%';
}
$category_condition = $temp_condition;
$condition[] = [ 'g.category_id', 'like', $category_condition, 'or' ];
}
}
if ($min_price != '' && $max_price != '') {
$condition[] = [ 'gs.discount_price', 'between', [ $min_price, $max_price ] ];
} elseif ($min_price != '') {
$condition[] = [ 'gs.discount_price', '>=', $min_price ];
} elseif ($max_price != '') {
$condition[] = [ 'gs.discount_price', '<=', $max_price ];
}
if (!empty($is_free_shipping)) {
$condition[] = [ 'gs.is_free_shipping', '=', $is_free_shipping ];
}
// 非法参数进行过滤
if ($sort != 'desc' && $sort != 'asc') {
$sort = '';
}
// 非法参数进行过滤
if ($order != '') {
if ($order != 'sale_num' && $order != 'discount_price' && $order != 'create_time') {
$order = 'gs.sort';
} elseif ($order == 'sale_num') {
$order = 'sale_sort';
} elseif ($order == 'create_time') {
$order = 'g.create_time';
} else {
$order = 'gs.' . $order;
}
$order_by = $order . ' ' . $sort;
} else {
$config_model = new ConfigModel();
$sort_config = $config_model->getGoodsSort($this->site_id)[ 'data' ][ 'value' ];
$order_by = 'g.sort ' . $sort_config[ 'type' ] . ',g.create_time desc';
}
// 优惠券
if (!empty($coupon)) {
$coupon_type = new CouponType();
$coupon_type_info = $coupon_type->getInfo([
[ 'coupon_type_id', '=', $coupon ],
[ 'site_id', '=', $this->site_id ],
], 'goods_ids,goods_type')[ 'data' ];
if (isset($coupon_type_info[ 'goods_ids' ]) && !empty($coupon_type_info[ 'goods_ids' ])) {
switch($coupon_type_info['goods_type']){
case CouponDict::selected:
case CouponDict::selected_out:
$exp = $coupon_type_info['goods_type'] == CouponDict::selected ? 'in' : 'not in';
$condition[] = [ 'g.goods_id', $exp, explode(',', trim($coupon_type_info[ 'goods_ids' ], ',')) ];
break;
case CouponDict::category_selected:
case CouponDict::category_selected_out:
$category_leaf_ids = $goods_category_model->getGoodsCategoryLeafIds($coupon_type_info['goods_ids'])['data'];
$sql_arr = [];
foreach ($category_leaf_ids as $category_leaf_id){
$sql_arr[] = "FIND_IN_SET({$category_leaf_id}, g.category_id)";
}
$sql = join( " or ", $sql_arr);
if($coupon_type_info['goods_type'] == CouponDict::category_selected_out){
$sql = "not ({$sql})";
}
$condition[] = ['', 'exp', Db::raw($sql)];
break;
}
}
}
$condition[] = [ 'g.goods_state', '=', 1 ];
$condition[] = [ 'g.is_delete', '=', 0 ];
$alias = 'gs';
$field = 'gs.is_consume_discount,gs.discount_config,gs.discount_method,gs.member_price,gs.goods_id,gs.sort,gs.sku_id,gs.sku_name,gs.price,gs.market_price,gs.discount_price,gs.stock,(g.sale_num + g.virtual_sale) as sale_num,(gs.sale_num + gs.virtual_sale) as sale_sort,gs.sku_image,gs.goods_name,gs.site_id,gs.is_free_shipping,gs.introduction,gs.promotion_type,g.goods_stock,g.goods_image,g.promotion_addon,gs.is_virtual,g.goods_spec_format,g.recommend_way,gs.max_buy,gs.min_buy,gs.unit,gs.is_limit,gs.limit_type,g.label_name,g.stock_show,g.sale_show,g.market_price_show,g.barrage_show,g.sale_channel,g.sale_store';
$join = [
[ 'goods g', 'gs.sku_id = g.sku_id', 'inner' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'sgs.status = 1 and g.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'right' ];
$join[] = [ 'store_goods sg', 'sg.status = 1 and g.goods_id = sg.goods_id and sg.store_id=' . $this->store_id, 'right' ];
$condition[] = [ 'g.sale_store', 'like', [ '%all%', '%,' . $this->store_id . ',%' ], 'or' ];
$field = str_replace('gs.price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as price', $field);
$field = str_replace('gs.discount_price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('gs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
$field = str_replace('g.goods_stock', 'IFNULL(sg.stock, 0) as goods_stock', $field);
}
}
$goods = new Goods();
$list = $goods->getGoodsSkuPageList($condition, $page, $page_size, $order_by, $field, $alias, $join);
//库存转换
$list['data']['list'] = $goods->goodsStockTransform($list['data']['list'], $this->store_id, $this->store_data['config']['store_business']);
if (!empty($list[ 'data' ][ 'list' ])) {
// 商品列表配置
$config_model = new ConfigModel();
$goods_list_config = $config_model->getGoodsListConfig($this->site_id, $this->app_module)[ 'data' ][ 'value' ];
$list[ 'data' ][ 'config' ] = $goods_list_config;
}
$token = $this->checkToken();
if ($token[ 'code' ] >= 0) {
if (!empty($list[ 'data' ][ 'list' ])) {
$list[ 'data' ][ 'list' ] = $goods->getGoodsListMemberPrice($list[ 'data' ][ 'list' ], $this->member_id);
}
}
return $this->response($list);
}
/**
* 查询商品列表供组件调用
*/
public function pageComponents()
{
$token = $this->checkToken();
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$goods_id_arr = $this->params['goods_id_arr'] ?? '';//goods_id数组
$category_id = $this->params['category_id'] ?? 0;//分类
$order = $this->params['order'] ?? '';//排序(综合、销量、价格)
$condition = [
[ 'g.goods_state', '=', 1 ],
[ 'g.is_delete', '=', 0 ],
[ 'g.site_id', '=', $this->site_id ],
[ '', 'exp', Db::raw("(g.sale_channel = 'all' OR g.sale_channel = 'online')") ]
];
if (!empty($category_id)) {
$condition[] = [ 'category_id', 'like', '%,' . $category_id . ',%' ];
}
if (!empty($goods_id_arr)) {
$condition[] = [ 'g.goods_id', 'in', $goods_id_arr ];
}
// 非法参数进行过滤
if ($order != '') {
if ($order == 'default') {
// 综合排序
$order = 'g.sort asc,g.create_time';
$sort = 'desc';
} elseif ($order == 'sales') {
// 销量排序
$order = 'sale_num';
$sort = 'desc';
} else if ($order == 'price') {
// 价格排序
$order = 'gs.discount_price';
$sort = 'asc';
} else if ($order == 'news') {
// 上架时间排序
$order = 'g.create_time';
$sort = 'desc';
} else {
$order = 'g.' . $order;
$sort = 'asc';
}
$order_by = $order . ' ' . $sort;
$order_by_pre = 'IF(g.goods_stock > 0, 1, 0) desc';
} else {
$config_model = new ConfigModel();
$sort_config = $config_model->getGoodsSort($this->site_id)[ 'data' ][ 'value' ];
$order_by = 'g.sort ' . $sort_config[ 'type' ] . ',g.create_time desc';
}
$field = 'gs.goods_id,gs.sku_id,gs.price,gs.market_price,gs.discount_price,gs.stock,g.goods_stock,(g.sale_num + g.virtual_sale) as sale_num,g.goods_name,gs.site_id,gs.is_free_shipping,g.goods_image,gs.is_virtual,g.recommend_way,gs.unit,gs.promotion_type,g.label_name,g.goods_spec_format';
if ($token[ 'code' ] >= 0) {
$field .= ',gs.is_consume_discount,gs.discount_config,gs.member_price,gs.discount_method';
}
$alias = 'gs';
$join = [
[ 'goods g', 'gs.sku_id = g.sku_id', 'inner' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'sgs.status = 1 and g.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'right' ];
$join[] = [ 'store_goods sg', 'sg.status = 1 and g.goods_id = sg.goods_id and sg.store_id=' . $this->store_id, 'right' ];
$condition[] = [ 'g.sale_store', 'like', [ '%all%', '%,' . $this->store_id . ',%' ], 'or' ];
$field = str_replace('gs.price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as price', $field);
$field = str_replace('gs.discount_price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('gs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
$field = str_replace('g.goods_stock', 'IFNULL(sg.stock, 0) as goods_stock', $field);
$order_by_pre = 'IF(sg.stock > 0, 1, 0) desc';
}
}
if(isset($order_by_pre)){
$order_by = Db::raw($order_by_pre.','.$order_by);
}
$goods = new Goods();
$list = $goods->getGoodsSkuPageList($condition, $page, $page_size, $order_by, $field, $alias, $join);
//库存转换
$list['data']['list'] = $goods->goodsStockTransform($list['data']['list'], $this->store_id, $this->store_data['config']['store_business']);
if (!empty($list[ 'data' ][ 'list' ]) && $token[ 'code' ] >= 0) {
$list[ 'data' ][ 'list' ] = $goods->getGoodsListMemberPrice($list[ 'data' ][ 'list' ], $this->member_id);
}
return $this->response($list);
}
/**
* 查询商品列表供组件调用
*/
public function components()
{
$token = $this->checkToken();
$num = $this->params['num'] ?? 0;
$goods_id_arr = $this->params['goods_id_arr'] ?? '';//goods_id数组
$category_id = $this->params['category_id'] ?? 0;//分类
$order = $this->params['order'] ?? '';//排序(综合、销量、价格)
$condition = [
[ 'g.goods_state', '=', 1 ],
[ 'g.is_delete', '=', 0 ],
[ 'g.site_id', '=', $this->site_id ],
[ '', 'exp', Db::raw("(g.sale_channel = 'all' OR g.sale_channel = 'online')") ]
];
if (!empty($category_id)) {
$condition[] = [ 'category_id', 'like', '%,' . $category_id . ',%' ];
}
if (!empty($goods_id_arr)) {
$condition[] = [ 'g.goods_id', 'in', $goods_id_arr ];
}
// 非法参数进行过滤
if ($order != '') {
if ($order == 'default') {
// 综合排序
$order = 'g.sort asc,g.create_time';
$sort = 'desc';
} elseif ($order == 'sales') {
// 销量排序
$order = 'sale_num';
$sort = 'desc';
} else if ($order == 'price') {
// 价格排序
$order = 'gs.discount_price';
$sort = 'desc';
} else if ($order == 'news') {
// 上架时间排序
$order = 'g.create_time';
$sort = 'desc';
} else {
$order = 'g.' . $order;
$sort = 'asc';
}
$order_by = $order . ' ' . $sort;
$order_by_pre = 'IF(g.goods_stock > 0, 1, 0) desc';
} else {
$config_model = new ConfigModel();
$sort_config = $config_model->getGoodsSort($this->site_id)[ 'data' ][ 'value' ];
$order_by = 'g.sort ' . $sort_config[ 'type' ] . ',g.create_time desc';
}
$field = 'gs.goods_id,gs.sku_id,gs.price,gs.market_price,gs.discount_price,gs.stock,g.goods_stock,(g.sale_num + g.virtual_sale) as sale_num,g.goods_name,gs.site_id,gs.is_free_shipping,g.goods_image,gs.is_virtual,g.recommend_way,gs.unit,gs.promotion_type,g.label_name,g.goods_spec_format, gs.min_buy, gs.max_buy, gs.is_limit';
if ($token[ 'code' ] >= 0) {
$field .= ',gs.is_consume_discount,gs.discount_config,gs.member_price,gs.discount_method';
}
$alias = 'gs';
$join = [
[ 'goods g', 'gs.sku_id = g.sku_id', 'inner' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods sg', 'sg.status = 1 and g.goods_id=sg.goods_id and sg.store_id=' . $this->store_id, 'right' ];
$condition[] = [ 'g.sale_store', 'like', [ '%all%', '%,' . $this->store_id . ',%' ], 'or' ];
$field = str_replace('gs.price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sg.price), gs.price) as price', $field);
$field = str_replace('gs.discount_price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sg.price), gs.price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('g.goods_stock', 'IFNULL(sg.stock, 0) as goods_stock', $field);
$order_by_pre = 'IF(sg.stock > 0, 1, 0) desc';
}
}
if(isset($order_by_pre)){
$order_by = Db::raw($order_by_pre.','.$order_by);
}
$goods = new Goods();
$list = $goods->getGoodsSkuList($condition, $field, $order_by, $num, $alias, $join);
//库存转换
$list['data'] = $goods->goodsStockTransform($list['data'], $this->store_id, $this->store_data['config']['store_business']);
if (!empty($list[ 'data' ]) && $token[ 'code' ] >= 0) {
$list[ 'data' ] = $goods->getGoodsListMemberPrice($list[ 'data' ], $this->member_id);
}
return $this->response($list);
}
/**
* 查询商品列表,商品分类页面用
*/
public function pageByCategory()
{
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$category_id = $this->params['category_id'] ?? 0;//分类
$order = $this->params['order'] ?? '';//排序(综合、销量、价格)
$sort = $this->params['sort'] ?? '';//升序、降序
$condition = [];
$condition[] = [ 'gs.site_id', '=', $this->site_id ];
$condition[] = [ '', 'exp', Db::raw("(g.sale_channel = 'all' OR g.sale_channel = 'online')") ];
if (!empty($category_id)) {
$goods_category_model = new GoodsCategoryModel();
// 查询当前
$category_list = $goods_category_model->getCategoryList([ [ 'category_id', '=', $category_id ], [ 'site_id', '=', $this->site_id ] ], 'category_id,pid,level')[ 'data' ];
// 查询子级
$category_child_list = $goods_category_model->getCategoryList([ [ 'pid', '=', $category_id ], [ 'site_id', '=', $this->site_id ] ], 'category_id,pid,level')[ 'data' ];
$temp_category_list = [];
if (!empty($category_list)) {
$temp_category_list = $category_list;
} elseif (!empty($category_child_list)) {
$temp_category_list = $category_child_list;
}
if (!empty($temp_category_list)) {
$category_id_arr = [];
foreach ($temp_category_list as $k => $v) {
// 三级分类,并且都能查询到
if ($v[ 'level' ] == 3 && !empty($category_list) && !empty($category_child_list)) {
$category_id_arr[] = $v['pid'];
} else {
$category_id_arr[] = $v['category_id'];
}
}
$category_id_arr = array_unique($category_id_arr);
$temp_condition = [];
foreach ($category_id_arr as $ck => $cv) {
$temp_condition[] = '%,' . $cv . ',%';
}
$category_condition = $temp_condition;
$condition[] = [ 'g.category_id', 'like', $category_condition, 'or' ];
}
}
// 非法参数进行过滤
if ($sort != 'desc' && $sort != 'asc') {
$sort = '';
}
// 非法参数进行过滤
if ($order != '') {
if ($order != 'sale_num' && $order != 'discount_price' && $order != 'create_time') {
$order = 'gs.sort';
} elseif ($order == 'sale_num') {
$order = 'sale_sort';
} elseif ($order == 'create_time') {
$order = 'g.create_time';
} else {
$order = 'gs.' . $order;
}
$order_by = $order . ' ' . $sort;
} else {
$config_model = new ConfigModel();
$sort_config = $config_model->getGoodsSort($this->site_id)[ 'data' ][ 'value' ];
$order_by = 'g.sort ' . $sort_config[ 'type' ] . ',g.create_time desc';
}
$condition[] = [ 'g.goods_state', '=', 1 ];
$condition[] = [ 'g.is_delete', '=', 0 ];
$alias = 'gs';
$field = 'gs.is_consume_discount,gs.discount_config,gs.discount_method,gs.member_price,gs.goods_id,gs.sku_id,gs.sku_name,gs.price,gs.market_price,gs.discount_price,gs.stock,gs.goods_name,gs.stock,g.goods_stock,
g.goods_image,gs.is_virtual,g.goods_spec_format,gs.max_buy,gs.min_buy,gs.unit,gs.is_limit,gs.limit_type,g.label_name,g.stock_show,g.sale_show,g.market_price_show,g.sale_channel';
$join = [
[ 'goods g', 'gs.sku_id = g.sku_id', 'inner' ]
];
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'sgs.status = 1 and g.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'right' ];
$join[] = [ 'store_goods sg', 'sg.status = 1 and g.goods_id = sg.goods_id and sg.store_id=' . $this->store_id, 'right' ];
$condition[] = [ 'g.sale_store', 'like', [ '%all%', '%,' . $this->store_id . ',%' ], 'or' ];
$field = str_replace('gs.price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as price', $field);
$field = str_replace('gs.discount_price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('gs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
$field = str_replace('g.goods_stock', 'IFNULL(sg.stock, 0) as goods_stock', $field);
}
}
$goods = new Goods();
$list = $goods->getGoodsSkuPageList($condition, $page, $page_size, $order_by, $field, $alias, $join);
//库存转换
$list['data']['list'] = $goods->goodsStockTransform($list['data']['list'], $this->store_id, $this->store_data['config']['store_business']);
$token = $this->checkToken();
if ($token[ 'code' ] >= 0) {
if (!empty($list[ 'data' ][ 'list' ])) {
$list[ 'data' ][ 'list' ] = $goods->getGoodsListMemberPrice($list[ 'data' ][ 'list' ], $this->member_id);
}
}
return $this->response($list);
}
/**
* 商品推荐
* @return string
*/
public function recommend()
{
$token = $this->checkToken();
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$route = $this->params['route'] ?? '';
// PC端
if ($this->params[ 'app_type' ] == 'pc') {
$route = 'goods_detail';
}
if (empty($route)) {
return $this->response($this->error(''));
}
$condition[] = [ 'gs.goods_state', '=', 1 ];
$condition[] = [ 'gs.is_delete', '=', 0 ];
$condition[] = [ 'gs.site_id', '=', $this->site_id ];
$condition[] = [ '', 'exp', Db::raw("(g.sale_channel = 'all' OR g.sale_channel = 'online')") ];
$goods = new Goods();
$alias = 'gs';
$config_model = new ConfigModel();
$order_by = '';
// 根据后台设置推荐商品
$guess_you_like = $config_model->getGuessYouLike($this->site_id, $this->app_module)[ 'data' ][ 'value' ];
if (in_array($route, $guess_you_like[ 'supportPage' ]) === false) {
return $this->response($this->error(''));
}
if ($guess_you_like[ 'sources' ] == 'sort') {
$sort_config = $config_model->getGoodsSort($this->site_id)[ 'data' ][ 'value' ];
$order_by = 'gs.sort ' . $sort_config[ 'type' ] . ',gs.create_time desc';
} else if ($guess_you_like[ 'sources' ] == 'browse') {
$condition[] = [ 'gb.member_id', '=', $this->member_id ];
$condition[] = [ 'gb.site_id', '=', $this->site_id ];
$order_by = 'browse_time desc';
} else if ($guess_you_like[ 'sources' ] == 'sale') {
$order_by = 'sale_num desc';
} else if ($guess_you_like[ 'sources' ] == 'diy') {
$condition[] = [ 'gs.goods_id', 'in', $guess_you_like[ 'goodsIds' ] ];
}
$order_by_pre = 'IF(g.goods_stock > 0, 1, 0) desc';
$field = 'gs.is_consume_discount,gs.discount_config,gs.discount_method,gs.member_price,g.market_price_show,g.sale_show,gs.goods_id,gs.sku_id,gs.sku_name,gs.price,gs.market_price,gs.discount_price,gs.stock,g.goods_stock,(g.sale_num + g.virtual_sale) as sale_num,gs.goods_name,gs.promotion_type,g.goods_image,gs.unit,g.label_name,gs.sku_image,gs.is_virtual';
if ($guess_you_like[ 'sources' ] == 'browse') {
$join = [
[ 'goods g', 'gs.sku_id = g.sku_id', 'inner' ],
[ 'goods_browse gb', 'gb.sku_id = gs.sku_id', 'inner' ]
];
} else {
$join = [
[ 'goods g', 'gs.sku_id = g.sku_id', 'inner' ]
];
}
// 如果是连锁运营模式
if ($this->store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'sgs.status = 1 and g.sku_id = sgs.sku_id and sgs.store_id=' . $this->store_id, 'right' ];
$join[] = [ 'store_goods sg', 'sg.status = 1 and g.goods_id = sg.goods_id and sg.store_id=' . $this->store_id, 'right' ];
$condition[] = [ 'g.sale_store', 'like', [ '%all%', '%,' . $this->store_id . ',%' ], 'or' ];
$field = str_replace('gs.price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as price', $field);
$field = str_replace('gs.discount_price', 'IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as discount_price', $field);
if ($this->store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('gs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
$field = str_replace('g.goods_stock', 'IFNULL(sg.stock, 0) as goods_stock', $field);
$order_by_pre = 'IF(sg.stock > 0, 1, 0) desc';
}
}
$order_by = $order_by_pre.($order_by?','.$order_by:'');
$order_by = Db::raw($order_by);
$list = $goods->getGoodsSkuPageList($condition, $page, $page_size, $order_by, $field, $alias, $join);
//库存转换
$list['data']['list'] = $goods->goodsStockTransform($list['data']['list'], $this->store_id, $this->store_data['config']['store_business']);
if (!empty($list[ 'data' ][ 'list' ])) {
$list[ 'data' ][ 'list' ] = $goods->getGoodsListMemberPrice($list[ 'data' ][ 'list' ], $this->member_id);
$list[ 'data' ][ 'config' ] = $guess_you_like;
}
return $this->response($list);
}
/**
* 商品二维码
* return
*/
public function goodsQrcode()
{
$sku_id = $this->params['sku_id'] ?? 0;
if (empty($sku_id)) {
return $this->response($this->error('', 'REQUEST_SKU_ID'));
}
$goods_model = new Goods();
$goods_sku_info = $goods_model->getGoodsSkuInfo([ [ 'sku_id', '=', $sku_id ] ], 'goods_id,sku_id,goods_name')[ 'data' ];
$res = $goods_model->qrcode($goods_sku_info[ 'goods_id' ], $goods_sku_info[ 'goods_name' ], $this->site_id);
return $this->response($res);
}
/**
* 处理商品详情公共数据
* @param $data
*/
public function handleGoodsDetailData(&$data)
{
$goods = new Goods();
if (!empty($data[ 'sku_images' ])) $data[ 'sku_images_list' ] = $goods->getGoodsImage($data[ 'sku_images' ], $this->site_id)[ 'data' ] ?? [];
if (!empty($data[ 'sku_image' ])) $data[ 'sku_image_list' ] = $goods->getGoodsImage($data[ 'sku_image' ], $this->site_id)[ 'data' ] ?? [];
if (!empty($data[ 'goods_image' ])) $data[ 'goods_image_list' ] = $goods->getGoodsImage($data[ 'goods_image' ], $this->site_id)[ 'data' ] ?? [];
// 商品服务
$goods_service = new GoodsService();
$data[ 'goods_service' ] = $goods_service->getServiceList([ [ 'site_id', '=', $this->site_id ], [ 'id', 'in', $data[ 'goods_service_ids' ] ] ], 'service_name,desc,icon')[ 'data' ];
// 商品详情配置
$config_model = new ConfigModel();
$data[ 'config' ] = $config_model->getGoodsDetailConfig($this->site_id)[ 'data' ][ 'value' ];
if ($data[ 'is_virtual' ] == 0) {
$data[ 'express_type' ] = ( new ExpressConfig() )->getEnabledExpressType($this->site_id);
}
// 获取用户是否关注
$goods_collect_api = new Goodscollect();
$data[ 'is_collect' ] = json_decode($goods_collect_api->iscollect($data[ 'goods_id' ]), true)[ 'data' ];
// 评价查询
$goods_evaluate_api = new Goodsevaluate();
$data[ 'evaluate_config' ] = json_decode($goods_evaluate_api->config(), true)[ 'data' ];
$data[ 'evaluate_list' ] = json_decode($goods_evaluate_api->firstinfo($data[ 'goods_id' ]), true)[ 'data' ];
$data[ 'evaluate_count' ] = json_decode($goods_evaluate_api->count($data[ 'goods_id' ]), true)[ 'data' ];
}
}

61
app/api/controller/Help.php Executable file
View File

@@ -0,0 +1,61 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\web\Help as HelpModel;
/**
* 系统帮助
* @author Administrator
*
*/
class Help extends BaseApi
{
/**
* 基础信息
*/
public function info()
{
$help_id = $this->params['id'] ?? 0;
if (empty($help_id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$help = new HelpModel();
$info = $help->getHelpInfo($help_id);
return $this->response($info);
}
/**
* 分页列表信息
*/
public function page()
{
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$class_id = $this->params['class_id'] ?? 0;
$condition = [
['class_id', '=', $class_id],
['site_id', '=', $this->site_id]
];
$order = 'sort asc, create_time desc';
$field = 'id,title,class_id,class_name,sort,create_time';
$help = new HelpModel();
$list = $help->getHelpPageList($condition, $page, $page_size, $order, $field);
return $this->response($list);
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\web\Help as HelpModel;
class Helpclass extends BaseApi
{
/**
* 列表信息
*/
public function lists()
{
$help = new HelpModel();
$condition = [
[ 'site_id', '=', $this->site_id ]
];
$list = $help->getHelpClassList($condition, 'class_id, class_name', 'sort asc, create_time desc');
$order = 'sort asc, create_time desc';
$field = 'id,title,link_address';
if (!empty($list[ 'data' ])) {
foreach ($list[ 'data' ] as $k => $v) {
$condition = [
[ 'class_id', '=', $v[ 'class_id' ] ],
[ 'site_id', '=', $this->site_id ]
];
$child_list = $help->getHelpList($condition, $field, $order);
$child_list = $child_list[ 'data' ];
$list[ 'data' ][ $k ][ 'child_list' ] = $child_list;
}
}
return $this->response($list);
}
}

47
app/api/controller/Invoice.php Executable file
View File

@@ -0,0 +1,47 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\order\OrderCreate as OrderCreateModel;
class Invoice extends BaseOrderCreateApi
{
/**
* 订单申请开票
*/
public function applyInvoice()
{
$token = $this->checkToken();
if ($token['code'] < 0) return $this->response($token);
$order_create = new OrderCreateModel();
$data = array_merge(
[
'order_id' => $this->params['order_id']
],
$this->getInvoiceParam()
);
$result = $order_create->initInvoice($data);
if ($result['code'] < 0) {
return $this->response($result);
}
$order_create->calculateInvoice();
if ($order_create->error) {
return $this->response($this->error($order_create->error_msg));
}
$res = $order_create->saveInvoice();
return $this->response($res);
}
}

408
app/api/controller/Login.php Executable file
View File

@@ -0,0 +1,408 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\member\Login as LoginModel;
use app\model\message\Message;
use app\model\member\Register as RegisterModel;
use Exception;
use think\facade\Cache;
use app\model\member\Config as ConfigModel;
use app\model\web\Config;
use think\facade\Session;
class Login extends BaseApi
{
#can_receive_registergift 判断新人礼
/**
* 登录方法
*/
public function login()
{
$config = new ConfigModel();
$config_info = $config->getRegisterConfig($this->site_id, 'shop');
if (strstr($config_info[ 'data' ][ 'value' ][ 'login' ], 'username') === false) return $this->response($this->error([], '用户名登录未开启!'));
// $auth_info = Session::get("auth_info");
// if (!empty($auth_info)) {
// $this->params = array_merge($this->params, $auth_info);
// }
// 校验验证码
// $config_model = new Config();
// $info = $config_model->getCaptchaConfig();
// if ($info[ 'data' ][ 'value' ][ 'shop_reception_login' ] == 1) {
// $captcha = new Captcha();
// $check_res = $captcha->checkCaptcha();
// if ($check_res[ 'code' ] < 0) return $this->response($check_res);
// }
// 登录
$login = new LoginModel();
if (empty($this->params[ 'password' ]))
return $this->response($this->error([], '密码不可为空!'));
$res = $login->login($this->params);
//生成access_token
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
return $this->response($this->success(['token' => $token, 'can_receive_registergift' => $res[ 'data' ][ 'can_receive_registergift' ]]));
}
return $this->response($res);
}
/**
* 第三方登录
*/
public function auth()
{
$login = new LoginModel();
$res = $login->authLogin($this->params);
//生成access_token
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
$data = [
'token' => $token,
'can_receive_registergift' => $res[ 'data' ][ 'can_receive_registergift' ]
];
if (isset($res[ 'data' ][ 'is_register' ])) $data[ 'is_register' ] = 1;
return $this->response($this->success($data));
}
return $this->response($res);
}
/**
* 授权登录仅登录
* @return false|string
*/
public function authOnlyLogin()
{
$login = new LoginModel();
$res = $login->authOnlyLogin($this->params);
//生成access_token
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
$data = [
'token' => $token,
];
return $this->response($this->success($data));
}
return $this->response($res);
}
/**
* 检测openid是否存在
*/
public function openidIsExits()
{
$login = new LoginModel();
$res = $login->openidIsExits($this->params);
return $this->response($res);
}
/**
* 手机动态码登录
*/
public function mobile()
{
$config = new ConfigModel();
$config_info = $config->getRegisterConfig($this->site_id, 'shop');
if (strstr($config_info[ 'data' ][ 'value' ][ 'login' ], 'mobile') === false) return $this->response($this->error([], '动态码登录未开启!'));
$key = $this->params[ 'key' ];
$verify_data = Cache::get($key);
if (!empty($verify_data) && $verify_data[ 'mobile' ] == $this->params[ 'mobile' ] && $verify_data[ 'code' ] == $this->params[ 'code' ]) {
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
$login = new LoginModel();
$res = $login->mobileLogin($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
$res = $this->success(['token' => $token, 'can_receive_registergift' => $res[ 'data' ][ 'can_receive_registergift' ]]);
}
} else {
$res = $this->error('', '该手机号未注册');
}
} else {
$res = $this->error('', '手机动态码不正确');
}
return $this->response($res);
}
/**
* 微信公众号登录 新增2021.06.18
* captcha_id 验证码id
* captcha_code 验证码
* mobile 手机号码
* code 手机验证码
*/
public function wechatLogin()
{
//校验验证码
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha();
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
$auth_info = Session::get('auth_info');
if (!empty($auth_info)) {
$this->params = array_merge($this->params, $auth_info);
}
$key = $this->params[ 'key' ];
$verify_data = Cache::get($key);
//判断手机验证码
if (!empty($verify_data) && $verify_data[ 'mobile' ] == $this->params[ 'mobile' ] && $verify_data[ 'code' ] == $this->params[ 'code' ]) {
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
//手机号码存在绑定wx_openid并登录
//绑定openid 如果该手机号有openid直接替换
$member_id = $register->getMemberId($this->params[ 'mobile' ], $this->site_id);
$res = $register->wxopenidBind(['wx_openid' => $this->params[ 'wx_openid' ], 'member_id' => $member_id, 'site_id' => $this->site_id]);
if ($res[ 'code' ] >= 0) {
$login = new LoginModel();
$res = $login->mobileLogin($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
$res = $this->success(['token' => $token, 'can_receive_registergift' => $res[ 'data' ][ 'can_receive_registergift' ]]);
}
}
} else {
//获取存放的缓存推荐人id
$source_member = Session::get('source_member') ?? 0;
if ($source_member > 0) {
$this->params[ 'source_member' ] = $source_member;
}
//手机号码不存在注册账号
$res = $register->mobileRegister($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ]);
$res = $this->success(['token' => $token]);
}
}
} else {
$res = $this->error('', '手机动态码不正确');
}
return $this->response($res);
}
/**
* 获取手机号登录验证码
* @throws Exception
*/
public function mobileCode()
{
// 校验验证码
$config_model = new Config();
$info = $config_model->getCaptchaConfig();
if ($info[ 'data' ][ 'value' ][ 'shop_reception_login' ] == 1) {
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha(false);
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
}
$mobile = $this->params[ 'mobile' ];
if (empty($mobile)) return $this->response($this->error([], '手机号不可为空!'));
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if (!$exist) return $this->response($this->error([], '该手机号未注册!'));
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage(['type' => 'code', 'mobile' => $mobile, 'site_id' => $this->site_id, 'support_type' => ['sms'], 'code' => $code, 'keywords' => 'LOGIN_CODE']);
if ($res[ 'code' ] >= 0) {
//将验证码存入缓存
$key = 'login_mobile_code_' . md5(uniqid(null, true));
Cache::tag('login_mobile_code')->set($key, ['mobile' => $mobile, 'code' => $code], 600);
return $this->response($this->success(['key' => $key]));
} else {
return $this->response($res);
}
}
/**
* 获取第三方首次扫码登录绑定/注册手机号码验证码 手机号码存不存在都可以发送 新增2021.06.18
* captcha_id 验证码id
* captcha_code 验证码
* mobile 手机号码
*/
public function getMobileCode()
{
// 校验验证码 start
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha(false);
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
// 校验验证码 end
$mobile = $this->params[ 'mobile' ];
if (empty($mobile)) return $this->response($this->error([], '手机号不可为空!'));
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
//判断该手机号码是否已绑定wx_openid
// $opneid_exist = $register->openidExist($this->params["mobile"], $this->site_id);
// if ($opneid_exist) return $this->response($this->error([], "该手机号已绑定其他微信公众号!"));
if ($exist) {
$keywords = 'LOGIN_CODE';
} else {
$keywords = 'REGISTER_CODE';
}
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage(['type' => 'code', 'mobile' => $mobile, 'site_id' => $this->site_id, 'support_type' => ['sms'], 'code' => $code, 'keywords' => $keywords]);
if ($res[ 'code' ] >= 0) {
// if ($res["code"]) {
//将验证码存入缓存
$key = 'login_mobile_code_' . md5(uniqid(null, true));
Cache::tag('login_mobile_code')->set($key, ['mobile' => $mobile, 'code' => $code], 600);
return $this->response($this->success(['key' => $key]));
// return $this->response($this->success(["key" => $key,"code"=>$code]));
} else {
return $this->response($res);
}
}
/**
* 手机号授权登录
*/
public function mobileAuth()
{
$decrypt_data = event('DecryptData', $this->params, true);
if ($decrypt_data[ 'code' ] < 0) return $this->response($decrypt_data);
$this->params[ 'mobile' ] = $decrypt_data[ 'data' ][ 'purePhoneNumber' ];
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
$login = new LoginModel();
$res = $login->mobileLogin($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
$res = $this->success(['token' => $token]);
}
} else {
$res = $register->mobileRegister($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ]);
$res = $this->success(['token' => $token]);
}
}
return $this->response($res);
}
/**
* 验证token有效性
*/
public function verifyToken()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
return $this->response($this->success());
}
/**
* 检测登录
* @return false|string
*/
public function checkLogin()
{
$key = $this->params[ 'key' ];
$cache = Cache::get('wechat_' . $key);
if (!empty($cache)) {
if (isset($cache[ 'openid' ]) && !empty($cache[ 'openid' ])) {
$login = new LoginModel();
$data = [
'wx_openid' => $cache[ 'openid' ],
'site_id' => $this->site_id
];
$is_exits = $login->openidIsExits($data);
if ($is_exits[ 'data' ]) {
// 存在即登录
$res = $login->authLogin($data);
//生成access_token
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
// Session::set($this->params[ 'app_type' ] . "_token_" . $this->site_id, $token);
// Session::set($this->params[ 'app_type' ] . "_member_id_" . $this->site_id, $res[ 'data' ][ 'member_id' ]);
return $this->response($this->success(['token' => $token, 'can_receive_registergift' => $res[ 'data' ][ 'can_receive_registergift' ]]));
}
return $this->response($res);
} else {
// 将openid存入session
Session::set('auth_info', [
'wx_openid' => $cache[ 'openid' ],
'nickname' => $cache[ 'nickname' ],
'headimg' => $cache[ 'headimgurl' ]
]);
$config = new ConfigModel();
$config_info = $config->getRegisterConfig($this->site_id, 'shop');
if ($config_info[ 'data' ][ 'value' ][ 'third_party' ] && !$config_info[ 'data' ][ 'value' ][ 'bind_mobile' ]) {
$data = [
'wx_openid' => $cache[ 'openid' ] ?? '',
'site_id' => $this->site_id,
'avatarUrl' => $cache[ 'headimgurl' ],
'nickName' => $cache[ 'nickname' ],
'wx_unionid' => $cache[ 'unionid' ],
];
Cache::set('wechat_' . $key, null);
$res = $login->authLogin($data);
//生成access_token
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
// Session::set($this->params[ 'app_type' ] . "_token_" . $this->site_id, $token);
// Session::set($this->params[ 'app_type' ] . "_member_id_" . $this->site_id, $res[ 'data' ][ 'member_id' ]);
return $this->response($this->success(['token' => $token, 'can_receive_registergift' => $res[ 'data' ][ 'can_receive_registergift' ]]));
}
}
Cache::set('wechat_' . $key, null);
return $this->response($this->success());
}
} elseif (time() > $cache[ 'expire_time' ]) {
Cache::set('wechat_' . $key, null);
return $this->response($this->error('', '已失效'));
} else {
return $this->response($this->error('', 'no login'));
}
} else {
return $this->response($this->error('', '已失效'));
}
}
}

541
app/api/controller/Member.php Executable file
View File

@@ -0,0 +1,541 @@
<?php
/**
* Member.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\member\Member as MemberModel;
use app\model\member\MemberSignin as MemberSigninModel;
use app\model\member\Register as RegisterModel;
use app\model\message\Message;
use think\facade\Cache;
use app\model\member\MemberLevel as MemberLevelModel;
class Member extends BaseApi
{
/**
* 基础信息
*/
public function info()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_model = new MemberModel();
$info = $member_model->getMemberInfo([ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ], 'member_id,source_member,username,nickname,mobile,email,status,headimg,member_level,member_level_name,member_label,member_label_name,qq,qq_openid,wx_openid,wx_unionid,ali_openid,baidu_openid,toutiao_openid,douyin_openid,realname,sex,location,birthday,point,balance,balance_money,growth,password,member_level_type,level_expire_time,is_edit_username,is_fenxiao,province_id,city_id,district_id,community_id,address,full_address,longitude,latitude,member_code');
if (!empty($info[ 'data' ])) {
$info[ 'data' ][ 'password' ] = empty($info[ 'data' ][ 'password' ]) ? 0 : 1;
$member_level_model = new MemberLevelModel();
$member_level_result = $member_level_model->getMemberLevelInfo([ [ 'level_id', '=', $info[ 'data' ][ 'member_level' ] ] ]);
$member_level = $member_level_result[ 'data' ] ?? [];
$info[ 'data' ][ 'member_level_info' ] = $member_level;
//连续签到天数
$member_signin = new MemberSigninModel();
$info['data']['sign_days_series'] = $member_signin->getMemberSignDaysSeries($token[ 'data' ][ 'member_id' ])['data'];
}
return $this->response($info);
}
/**
* 修改会员头像
* @return string
*/
public function modifyheadimg()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$headimg = $this->params['headimg'] ?? '';
$member_model = new MemberModel();
$res = $member_model->editMember([ 'headimg' => $headimg ], [ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ]);
return $this->response($res);
}
/**
* 修改用户名
* @return false|string
*/
public function modifyUsername()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$username = $this->params['username'] ?? '';
$member_model = new MemberModel();
$res = $member_model->editUsername($this->member_id, $this->site_id, $username);
return $this->response($res);
}
/**
* 修改昵称
* @return string
*/
public function modifynickname()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$nickname = $this->params['nickname'] ?? '';
$nickname = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $nickname);
$member_model = new MemberModel();
$res = $member_model->editMember([ 'nickname' => $nickname ], [ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ]);
return $this->response($res);
}
/**
* 修改手机号
* @return string
*/
public function modifymobile()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
// 校验验证码
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha(false);
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
return $this->response($this->error('', '手机号已存在'));
} else {
$key = $this->params[ 'key' ];
$verify_data = Cache::get($key);
if (!empty($verify_data) && $verify_data['mobile'] == $this->params['mobile'] && $verify_data['code'] == $this->params['code']) {
$mobile = $this->params['mobile'] ?? '';
$member_model = new MemberModel();
$res = $member_model->editMember([ 'mobile' => $mobile ], [ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ]);
} else {
$res = $this->error('', '动态码不正确');
}
return $this->response($res);
}
}
/**
* 修改密码
* @return string
*/
public function modifypassword()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$old_password = $this->params['old_password'] ?? '';
$new_password = $this->params['new_password'] ?? '';
$member_model = new MemberModel();
$info = $member_model->getMemberInfo([ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ], 'password');
// 未设置密码时设置密码需验证身份
if (empty($info[ 'data' ][ 'password' ])) {
$key = $this->params[ 'key' ] ?? '';
$code = $this->params[ 'code' ] ?? '';
$verify_data = Cache::get($key);
if (empty($verify_data) || $verify_data['code'] != $code) {
return $this->response($this->error('', '手机验证码不正确'));
}
}
$res = $member_model->modifyMemberPassword($token[ 'data' ][ 'member_id' ], $old_password, $new_password);
return $this->response($res);
}
/**
* 绑定短信验证码
*/
public function bindmobliecode()
{
// 校验验证码
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha(false);
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
$mobile = $this->params[ 'mobile' ];//注册手机号
$register = new RegisterModel();
$exist = $register->mobileExist($mobile, $this->site_id);
if ($exist) {
return $this->response($this->error('', '当前手机号已存在'));
} else {
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage([ 'type' => 'code', 'mobile' => $mobile, 'site_id' => $this->site_id, 'code' => $code, 'support_type' => ['sms'], 'keywords' => 'MEMBER_BIND']);
if ($res['code'] >= 0) {
//将验证码存入缓存
$key = 'bind_mobile_code_' . md5(uniqid(null, true));
Cache::tag('bind_mobile_code')->set($key, [ 'mobile' => $mobile, 'code' => $code ], 600);
return $this->response($this->success([ 'key' => $key ]));
} else {
return $this->response($res);
}
}
}
/**
* 设置密码时获取验证码
*/
public function pwdmobliecode()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
// 校验验证码
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha(false);
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
$member_model = new MemberModel();
$info = $member_model->getMemberInfo([ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ], 'mobile');
if (empty($info[ 'data' ])) return $this->response($this->error([], '未获取到会员信息!'));
if (empty($info[ 'data' ][ 'mobile' ])) return $this->response($this->error([], '会员信息尚未绑定手机号!'));
$mobile = $info[ 'data' ][ 'mobile' ];
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage([ 'type' => 'code', 'mobile' => $mobile, 'site_id' => $this->site_id, 'code' => $code, 'support_type' => ['sms'], 'keywords' => 'SET_PASSWORD']);
if (isset($res['code']) && $res['code'] >= 0) {
//将验证码存入缓存
$key = 'password_mobile_code_' . md5(uniqid(null, true));
Cache::tag('password_mobile_code_')->set($key, [ 'mobile' => $mobile, 'code' => $code ], 600);
return $this->response($this->success([ 'key' => $key, 'code' => $code ]));
} else {
return $this->response($this->error('', '发送失败'));
}
}
/**
* 验证手机号
* @return string
*/
public function checkmobile()
{
$mobile = $this->params['mobile'] ?? '';
if (empty($mobile)) {
return $this->response($this->error('', 'REQUEST_MOBILE'));
}
$member_model = new MemberModel();
$condition = [
[ 'mobile', '=', $mobile ],
[ 'site_id', '=', $this->site_id ]
];
$res = $member_model->getMemberCount($condition);
if ($res[ 'data' ] > 0) {
return $this->response($this->error('', '当前手机号已存在'));
}
return $this->response($this->success());
}
/**
* 修改支付密码
* @return string
*/
public function modifypaypassword()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$key = $this->params[ 'key' ] ?? '';
$code = $this->params[ 'code' ] ?? '';
$password = isset($this->params[ 'password' ]) ? trim($this->params[ 'password' ]) : '';
if (empty($password)) return $this->response($this->error('', '支付密码不可为空'));
$verify_data = Cache::get($key);
if (!empty($verify_data) && $verify_data['code'] == $this->params['code']) {
$member_model = new MemberModel();
$res = $member_model->modifyMemberPayPassword($token[ 'data' ][ 'member_id' ], $password);
} else {
$res = $this->error('', '验证码不正确');
}
return $this->response($res);
}
/**
* 检测会员是否设置支付密码
*/
public function issetpayaassword()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_model = new MemberModel();
$res = $member_model->memberIsSetPayPassword($this->member_id);
return $this->response($res);
}
/**
* 检测支付密码是否正确
*/
public function checkpaypassword()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$password = isset($this->params[ 'pay_password' ]) ? trim($this->params[ 'pay_password' ]) : '';
if (empty($password)) return $this->response($this->error('', '支付密码不可为空'));
$member_model = new MemberModel();
$res = $member_model->checkPayPassword($this->member_id, $password);
return $this->response($res);
}
/**
*
* 修改支付密码发送手机验证码
*/
public function paypwdcode()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage([ 'type' => 'code', 'member_id' => $this->member_id, 'site_id' => $this->site_id, 'code' => $code, 'support_type' => ['sms'], 'keywords' => 'MEMBER_PAY_PASSWORD']);
if ($res['code'] >= 0) {
//将验证码存入缓存
$key = 'pay_password_code_' . md5(uniqid(null, true));
Cache::tag('pay_password_code')->set($key, [ 'member_id' => $this->member_id, 'code' => $code ], 600);
return $this->response($this->success([ 'key' => $key ]));
} else {
return $this->response($res);
}
}
/**
* 验证修改支付密码动态码
*/
public function verifypaypwdcode()
{
$key = isset($this->params[ 'key' ]) ? trim($this->params[ 'key' ]) : '';
$verify_data = Cache::get($key);
if (!empty($verify_data) && $verify_data['code'] == $this->params['code']) {
$res = $this->success([]);
} else {
$res = $this->error('', '验证码不正确');
}
return $this->response($res);
}
/**
* 通过token得到会员id
*/
public function id()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
return $this->response($this->success($this->member_id));
}
/**
* 账户奖励规则说明
* @return false|string
*/
public function accountrule()
{
//积分
$rule = event('MemberAccountRule', [ 'site_id' => $this->site_id ]);
$point = [];
$balance = [];
$growth = [];
foreach ($rule as $k => $v)
{
if(isset($v['point']))
{
$point[] = $v['point'];
}
if(isset($v['balance']))
{
$balance[] = $v['balance'];
}
if(isset($v['growth']))
{
$growth[] = $v['growth'];
}
}
$res = [
'point' => $point,
'balance' => $balance,
'growth' => $growth
];
return $this->response($this->success($res));
}
/**
* 拉取会员头像
*/
public function pullheadimg()
{
$member_id = input('member_id', '');
$member = new MemberModel();
$member->pullHeadimg($member_id);
}
/**
* 修改真实姓名
*/
public function modifyrealname()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$realname = $this->params['realname'] ?? '';
$member_model = new MemberModel();
$res = $member_model->editMember([ 'realname' => $realname ], [ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ]);
return $this->response($res);
}
/**
* 修改性别
*/
public function modifysex()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$sex = $this->params['sex'] ?? 0;
$member_model = new MemberModel();
$res = $member_model->editMember([ 'sex' => $sex ], [ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ]);
return $this->response($res);
}
/**
* 修改生日
*/
public function modifybirthday()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$birthday = $this->params['birthday'] ?? '';
$member_model = new MemberModel();
$res = $member_model->editMember([ 'birthday' => $birthday ], [ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ]);
return $this->response($res);
}
/**
* 生成会员二维码
*/
public function membereqrcode()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_id = $token[ 'data' ][ 'member_id' ];
$member_model = new MemberModel();
$member_info = $member_model->getMemberInfo([ [ 'member_id', '=', $member_id ] ], 'member_code,mobile')[ 'data' ] ?? [];
if (!empty($member_info[ 'member_code' ])) {
$number = $member_info[ 'member_code' ];
} elseif (!empty($member_info[ 'mobile' ])) {
$number = $member_info[ 'mobile' ];
}
// 二维码
$qrcode_dir = 'upload/qrcode/qrcodereduceaccount';
if (!is_dir($qrcode_dir) && !mkdir($qrcode_dir, intval('0755', 8), true)) {
return $this->error('', '会员码生成失败');
}
$qrcode_name = 'memberqrcode_' . $member_id . '_' . $this->site_id;
// 二维码
$res = event('Qrcode', [
'site_id' => $this->site_id,
'app_type' => 'h5',
'type' => 'create',
'data' => [ 'number' => $number ],
'page' => $this->params[ 'page' ] ? : '',
'qrcode_path' => 'upload/qrcode/qrcodereduceaccount',
'qrcode_name' => 'memberqrcode_' . $member_id . '_' . $this->site_id,
'qrcode_size' => 16
], true);
$bar_code = getBarcode($number, '', 3);
$res[ 'bar_code' ] = $bar_code;
$res[ 'member_code' ] = $number;
// 动态码
$dynamic_number = NoRand(0, 9, 4);
$res[ 'dynamic_number' ] = $dynamic_number;
return $this->response($res);
}
//更改分享人信息
public function alterShareRelation()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$share_member = $this->params[ 'share_member' ] ?? 0;
if (empty($share_member)) {
return $this->response($this->error(null, '未传分享人id'));
}
$member_model = new MemberModel();
$result = $member_model->alterShareRelation($this->member_id, $share_member, $this->site_id);
return $this->response($result);
}
/**
* 修改会员地址
* @return false|string
*/
public function modifyaddress()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$data = [
'province_id' => $this->params[ 'province_id' ] ?? 0,
'city_id' => $this->params[ 'city_id' ] ?? 0,
'district_id' => $this->params[ 'district_id' ] ?? 0,
'address' => $this->params[ 'address' ] ?? '',
'full_address' => $this->params[ 'full_address' ] ?? ''
];
$member_model = new MemberModel();
$res = $member_model->editMember($data, [ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ], [ 'site_id', '=', $this->site_id ] ] ]);
return $this->response($res);
}
/**
* 手机号授权绑定
*/
public function mobileAuth()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$decrypt_data = event('PhoneNumber', $this->params, true);
if (empty($decrypt_data)) return $this->error('', '没有获取手机号的渠道');
if ($decrypt_data[ 'code' ] < 0) return $this->response($decrypt_data);
$this->params[ 'mobile' ] = $decrypt_data[ 'data' ];
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
return $this->response($this->error('', '手机号已存在'));
} else {
$mobile = $this->params['mobile'] ?? '';
$member_model = new MemberModel();
$res = $member_model->editMember([ 'mobile' => $mobile ], [ [ 'member_id', '=', $this->member_id ], [ 'site_id', '=', $this->site_id ] ]);
return $this->response($res);
}
}
}

View File

@@ -0,0 +1,155 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\member\MemberAccount as MemberAccountModel;
use app\model\member\Member as MemberModel;
class Memberaccount extends BaseApi
{
/**
* 基础信息
*/
public function info()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$account_type = $this->params['account_type'] ?? 'balance,balance_money'; //账户类型 余额:balance积分:point
if (!in_array($account_type, [ 'point', 'balance', 'balance,balance_money' ])) return $this->response($this->error('', 'INVALID_PARAMETER'));
$member_model = new MemberModel();
$info = $member_model->getMemberInfo([ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ] ], $account_type);
return $this->response($info);
}
/**
* 列表信息
*/
public function page()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$account_type = $this->params['account_type'] ?? 'balance,balance_money';//账户类型 余额:balance积分:point
$start_time = empty($this->params[ 'date' ]) ? strtotime(date('Y-m', strtotime('today'))) : strtotime($this->params[ 'date' ]);
$end_time = strtotime('+1 month', $start_time);
$from_type = $this->params['from_type'] ?? '';
$related_id = $this->params['related_id'] ?? 0;
if (!in_array($account_type, [ 'point', 'balance', 'balance,balance_money' ])) return $this->response($this->error('', 'INVALID_PARAMETER'));
$condition[] = [ 'account_type', 'in', $account_type ];
$condition[] = [ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ];
if ($this->params['app_type'] != 'pc') {
$condition[] = [ 'create_time', 'between', [ $start_time, $end_time ] ];
}
if (!empty($from_type)) {
$condition[] = [ 'from_type', '=', $from_type ];
}
if (!empty($related_id)) {
$condition[] = [ 'related_id', '=', $related_id ];
}
$member_account_model = new MemberAccountModel();
$list = $member_account_model->getMemberAccountPageList($condition, $page, $page_size);
return $this->response($list);
}
/**
* 获取类型
* @return false|string
*/
public function fromType()
{
$member_account_model = new MemberAccountModel();
$lists = $member_account_model->getFromType();
return $this->response($lists);
}
/**
* 月份数据
*/
public function monthData()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_account_model = new MemberAccountModel();
$res = $member_account_model->getMemberAccountMonthData([['member_id', '=', $this->member_id]]);
if(empty($res['data'])){
$res['data'][] = date('Y-m');
}
return $this->response($res);
}
/**
* 获取账户总额
*/
public function sum()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$account_type = $this->params[ 'account_type' ] ?? 'point'; // 账户类型 余额:balance积分:point
$from_type = $this->params[ 'from_type' ] ?? '';
$query_type = $this->params[ 'query_type' ] ?? ''; // 查询类型 收入income 支出pay
$start_time = $this->params[ 'start_time' ] ?? 0;
$end_time = $this->params[ 'end_time' ] ?? 0;
if (!in_array($account_type, [ 'point', 'balance', 'balance_money', 'growth' ])) return $this->response($this->error('', 'INVALID_PARAMETER'));
$member_account_model = new MemberAccountModel();
$condition = [
[ 'member_id', '=', $this->member_id ],
[ 'site_id', '=', $this->site_id ],
[ 'account_type', '=', $account_type ]
];
if (!empty($from_type)) $condition[] = [ 'from_type', '=', $from_type ];
if ($query_type == 'income') $condition[] = [ 'account_data', '>', 0 ];
if ($query_type == 'pay') $condition[] = [ 'account_data', '<', 0 ];
if ($start_time && $end_time) $condition[] = [ 'create_time', 'between', [ $start_time, $end_time ] ];
$data = $member_account_model->getMemberAccountSum($condition, 'account_data');
return $this->response($data);
}
/**
* 会员积分信息(当前积分,累计获取,累计使用,今日获取)
* @return false|string
*/
public function point()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$point_data = (new MemberAccountModel())->getMemberAccountPointInApi($token[ 'data' ][ 'member_id' ]);
return $this->response($point_data);
}
/**
* 获取用户可用余额
* @return false|string
*/
public function usableBalance()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$data = ( new MemberModel() )->getMemberUsableBalance($this->site_id, $this->member_id);
return $this->response($data);
}
}

View File

@@ -0,0 +1,288 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\member\MemberAddress as MemberAddressModel;
use app\model\system\Address;
use app\model\express\Local;
class Memberaddress extends BaseApi
{
/**
* 添加信息
*/
public function add()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$this->params[ 'name' ] = preg_replace('/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}]/u', '', $this->params[ 'name' ]);
$this->params[ 'name' ] = preg_replace_callback('/./u',
function(array $match) {
return strlen($match[ 0 ]) >= 4 ? '' : $match[ 0 ];
},
$this->params[ 'name' ]);
$data = [
'site_id' => $this->site_id,
'member_id' => $token[ 'data' ][ 'member_id' ],
'name' => paramFilter($this->params[ 'name' ]),
'mobile' => $this->params[ 'mobile' ],
'telephone' => $this->params[ 'telephone' ],
'province_id' => $this->params[ 'province_id' ],
'city_id' => $this->params[ 'city_id' ],
'district_id' => $this->params[ 'district_id' ],
'community_id' => $this->params[ 'community_id' ],
'address' => paramFilter($this->params[ 'address' ]),
'full_address' => $this->params[ 'full_address' ],
'longitude' => $this->params[ 'longitude' ],
'latitude' => $this->params[ 'latitude' ],
'is_default' => $this->params[ 'is_default' ]
];
$member_address = new MemberAddressModel();
$res = $member_address->addMemberAddress($data);
return $this->response($res);
}
/**
* 编辑信息
*/
public function edit()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$data = [
'site_id' => $this->site_id,
'id' => $this->params[ 'id' ],
'member_id' => $token[ 'data' ][ 'member_id' ],
'name' => paramFilter($this->params[ 'name' ]),
'mobile' => $this->params[ 'mobile' ],
'telephone' => $this->params[ 'telephone' ],
'province_id' => $this->params[ 'province_id' ],
'city_id' => $this->params[ 'city_id' ] != 'undefined' ? $this->params[ 'city_id' ] : '',
'district_id' => $this->params[ 'district_id' ] != 'undefined' ? $this->params[ 'district_id' ] : '',
'community_id' => $this->params[ 'community_id' ],
'address' => paramFilter($this->params[ 'address' ]),
'full_address' => $this->params[ 'full_address' ],
'longitude' => $this->params[ 'longitude' ],
'latitude' => $this->params[ 'latitude' ],
'is_default' => $this->params[ 'is_default' ]
];
$member_address = new MemberAddressModel();
$res = $member_address->editMemberAddress($data);
return $this->response($res);
}
/**
* 设置默认地址
* @return string
*/
public function setdefault()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$member_address = new MemberAddressModel();
$res = $member_address->setMemberDefaultAddress($id, $token[ 'data' ][ 'member_id' ]);
return $this->response($res);
}
/**
* 删除信息
*/
public function delete()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'id', '=', $id ],
[ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ]
];
$member_address = new MemberAddressModel();
$res = $member_address->deleteMemberAddress($condition);
return $this->response($res);
}
/**
* 基础信息
*/
public function info()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$default = $this->params['default'] ?? 0;
if ($default) {
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'is_default', '=', 1 ],
[ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ],
];
} else {
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'id', '=', $id ],
[ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ],
];
}
$member_address = new MemberAddressModel();
$res = $member_address->getMemberAddressInfo($condition, 'id, member_id, name, mobile, telephone, province_id, district_id, city_id, community_id, address, full_address, longitude, latitude, is_default, type');
return $this->response($res);
}
/**
* 分页列表信息
*/
public function page()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$type = $this->params['type'] ?? '';
$store_id = $this->params['store_id'] ?? 0;
$member_address = new MemberAddressModel();
$condition = [
[ 'member_id', '=', $this->member_id ],
[ 'site_id', '=', $this->site_id ]
];
if (!empty($type)) {
$condition[] = [ 'type', '=', $type ];
}
$field = 'id,member_id, site_id, name, mobile, telephone,province_id,city_id,district_id,community_id,address,full_address,longitude,latitude,is_default,type';
$list = $member_address->getMemberAddressPageList($condition, $page, $page_size, 'is_default desc,id desc', $field);
//同城配送验证是否可用
if ($type == 2) {
$local = new Local();
foreach ($list[ 'data' ][ 'list' ] as $k => $v) {
$v['store_id'] = $store_id;
$local_res = $local->isSupportDelivery($v);
if ($local_res[ 'code' ] < 0) {
$list[ 'data' ][ 'list' ][ $k ][ 'local_data' ] = $local_res[ 'message' ];
}
}
}
return $this->response($list);
}
/**
* 添加第三方收货地址
*/
public function addThreeParties()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$address = new Address();
//省查询
$province_info = $address->getAreasInfo([
[ 'level', '=', 1 ],
[ 'name', 'like', '%' . $this->params[ 'province' ] . '%' ],
], 'id');
if ($province_info[ 'code' ] < 0) return $this->response(error('', '地址库中未获取到' . $this->params[ 'province' ] . '的信息'));
//市查询
$city_info = $address->getAreasInfo([
[ 'level', '=', 2 ],
[ 'pid', '=', $province_info[ 'data' ][ 'id' ] ],
[ 'name', 'like', '%' . $this->params[ 'city' ] . '%' ],
], 'id');
if ($city_info[ 'code' ] < 0) return $this->response(error('', '地址库中未获取到' . $this->params[ 'city' ] . '的信息'));
//区县查询
$district_info = $address->getAreasInfo([
[ 'level', '=', 3 ],
[ 'pid', '=', $city_info[ 'data' ][ 'id' ] ],
[ 'name', 'like', '%' . $this->params[ 'district' ] . '%' ],
], 'id');
if ($district_info[ 'code' ] < 0) return $this->response(error('', '地址库中未获取到' . $this->params[ 'district' ] . '的信息'));
$data = [
'site_id' => $this->site_id,
'member_id' => $token[ 'data' ][ 'member_id' ],
'name' => $this->params[ 'name' ],
'mobile' => $this->params[ 'mobile' ],
'telephone' => $this->params[ 'telephone' ] ?? '',
'province_id' => $province_info[ 'data' ][ 'id' ],
'city_id' => $city_info[ 'data' ][ 'id' ],
'district_id' => $district_info[ 'data' ][ 'id' ],
'community_id' => $this->params[ 'community_id' ] ?? 0,
'address' => $this->params[ 'address' ],
'full_address' => $this->params[ 'full_address' ],
'longitude' => $this->params[ 'longitude' ] ?? '',
'latitude' => $this->params[ 'latitude' ] ?? '',
'is_default' => $this->params[ 'is_default' ] ?? 0
];
$member_address = new MemberAddressModel();
$res = $member_address->addMemberAddress($data);
return $this->response($res);
}
/**
* 转化省市区地址形式为实际的省市区id
*/
public function tranAddressInfo()
{
$latlng = $this->params[ 'latlng' ] ?? '';
$address_model = new Address();
$address_result = $address_model->getAddressByLatlng([ 'latlng' => $latlng ]);
if ($address_result[ 'code' ] < 0)
return $this->response($address_result);
$address_data = $address_result[ 'data' ];
$province = $address_data[ 'province' ];
$city = $address_data[ 'city' ];
$district = $address_data[ 'district' ];
$province = str_replace('省', '', $province);
$province = str_replace('市', '', $province);
$province_info = $address_model->getAreasInfo([['name', 'like', '%' . $province . '%'],['level', '=', 1],], '*')[ 'data' ];
if (!empty($province_info)){
$city_info = $address_model->getAreasInfo([['name', 'like', '%' . $city . '%'], ['level', '=', 2 ], ['pid', '=', $province_info['id']],], '*')[ 'data' ];
if(!empty($city_info)){
$district_info = $address_model->getAreasInfo([['name', 'like', '%' . $district . '%'], ['level', '=', 3], ['pid', '=', $city_info['id']],], '*')[ 'data' ];
}
}
$data = [
'province_id' => $province_info['id'] ?? 0,
'city_id' => $city_info['id'] ?? 0,
'district_id' => $district_info['id'] ?? 0,
'province' => $province_info['name'] ?? '',
'city' => $city_info['name'] ?? '',
'district' => $district_info['name'] ?? '',
];
return $this->response($this->success($data));
}
}

View File

@@ -0,0 +1,209 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\member\MemberBankAccount as MemberBankAccountModel;
/**
* 会员提现账号
* Class Memberbankaccount
* @package app\api\controller
*/
class Memberbankaccount extends BaseApi
{
/**
* 添加信息
*/
public function add()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$realname = $this->params['realname'] ?? '';
$mobile = $this->params['mobile'] ?? '';
$withdraw_type = $this->params['withdraw_type'] ?? '';// '账户类型 alipay 支付宝 bank 银行卡
$branch_bank_name = $this->params['branch_bank_name'] ?? '';// 银行支行信息
$bank_account = $this->params['bank_account'] ?? '';// 银行账号
if (empty($realname)) {
return $this->response($this->error('', 'REQUEST_REAL_NAME'));
}
if (empty($mobile)) {
return $this->response($this->error('', 'REQUEST_MOBILE'));
}
if (empty($withdraw_type)) {
return $this->response($this->error('', 'REQUEST_WITHDRAW_TYPE'));
}
if (!empty($withdraw_type) && $withdraw_type == 'bank') {
if (empty($branch_bank_name)) {
return $this->response($this->error('', 'REQUEST_BRANCH_BANK_NAME'));
}
if (empty($bank_account)) {
return $this->response($this->error('', 'REQUEST_BRANCH_BANK_ACCOUNT'));
}
}
$member_bank_account_model = new MemberBankAccountModel();
$data = [
'member_id' => $this->member_id,
'realname' => $realname,
'mobile' => $mobile,
'withdraw_type' => $withdraw_type,
'branch_bank_name' => $branch_bank_name,
'bank_account' => $bank_account,
'is_default' => 1
];
$res = $member_bank_account_model->addMemberBankAccount($data);
return $this->response($res);
}
/**
* 编辑信息
*/
public function edit()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
$realname = $this->params['realname'] ?? '';
$mobile = $this->params['mobile'] ?? '';
$withdraw_type = $this->params['withdraw_type'] ?? '';// '账户类型 alipay 支付宝 bank 银行卡
$branch_bank_name = $this->params['branch_bank_name'] ?? '';// 银行支行信息
$bank_account = $this->params['bank_account'] ?? '';// 银行账号
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
if (empty($realname)) {
return $this->response($this->error('', 'REQUEST_REAL_NAME'));
}
if (empty($mobile)) {
return $this->response($this->error('', 'REQUEST_MOBILE'));
}
if (empty($withdraw_type)) {
return $this->response($this->error('', 'REQUEST_WITHDRAW_TYPE'));
}
if (!empty($withdraw_type) && $withdraw_type == 'bank') {
if (empty($branch_bank_name)) {
return $this->response($this->error('', 'REQUEST_BRANCH_BANK_NAME'));
}
if (empty($bank_account)) {
return $this->response($this->error('', 'REQUEST_BRANCH_BANK_ACCOUNT'));
}
}
$member_bank_account_model = new MemberBankAccountModel();
$data = [
'id' => $id,
'member_id' => $this->member_id,
'realname' => $realname,
'mobile' => $mobile,
'withdraw_type' => $withdraw_type,
'branch_bank_name' => $branch_bank_name,
'bank_account' => $bank_account,
'is_default' => 1
];
$res = $member_bank_account_model->editMemberBankAccount($data);
return $this->response($res);
}
/**
* 删除信息
*/
public function delete()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$member_bank_account_model = new MemberBankAccountModel();
$res = $member_bank_account_model->deleteMemberBankAccount([ [ 'member_id', '=', $this->member_id ], [ 'id', '=', $id ] ]);
return $this->response($res);
}
/**
* 基础信息
*/
public function setDefault()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$member_bank_account_model = new MemberBankAccountModel();
$info = $member_bank_account_model->modifyDefaultAccount($id, $this->member_id);
return $this->response($info);
}
/**
* 基础信息
*/
public function info()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$member_bank_account_model = new MemberBankAccountModel();
$info = $member_bank_account_model->getMemberBankAccountInfo([ [ 'member_id', '=', $this->member_id ], [ 'id', '=', $id ] ], 'id,member_id,realname,mobile,withdraw_type,branch_bank_name,bank_account,is_default');
if (!empty($info[ 'data' ])) {
$info[ 'data' ][ 'withdraw_type_name' ] = $member_bank_account_model->getWithdrawType()[ $info[ 'data' ][ 'withdraw_type' ] ];
}
return $this->response($info);
}
/**
* 获取默认账户信息
*/
public function defaultInfo()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_bank_account_model = new MemberBankAccountModel();
$info = $member_bank_account_model->getMemberBankAccountInfo([ [ 'member_id', '=', $this->member_id ], [ 'is_default', '=', 1 ] ], 'id,member_id,realname,mobile,withdraw_type,branch_bank_name,bank_account,is_default');
if (!empty($info[ 'data' ])) {
$info[ 'data' ][ 'withdraw_type_name' ] = $member_bank_account_model->getWithdrawType()[ $info[ 'data' ][ 'withdraw_type' ] ];
}
return $this->response($info);
}
/**
* 分页列表信息
*/
public function page()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$member_bank_account_model = new MemberBankAccountModel();
$list = $member_bank_account_model->getMemberBankAccountPageList([ [ 'member_id', '=', $this->member_id ] ], $page, $page_size);
return $this->response($list);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\member\MemberLevel as MemberLevelModel;
class Memberlevel extends BaseApi
{
/**
* 列表信息
*/
public function lists()
{
$member_level_model = new MemberLevelModel();
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'level_type', '=', 0 ],
[ 'status', '=', 1 ],
];
$field = 'level_id,level_name,growth,remark,consume_discount,is_free_shipping,point_feedback,send_point,send_balance,send_coupon,charge_rule,charge_type,bg_color,is_default,level_text_color,level_picture';
$member_level_list = $member_level_model->getMemberLevelList($condition, $field, 'growth asc,level_id desc');
return $this->response($member_level_list);
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* Membersignin.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use addon\membersignin\model\Signin;
use app\model\member\MemberSignin as MemberSigninModel;
class Membersignin extends BaseApi
{
/**
* 是否已签到
*/
public function issign()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_signin = new MemberSigninModel();
$res = $member_signin->isSign($token[ 'data' ][ 'member_id' ]);
return $this->response($res);
}
/**
* 签到
*/
public function signin()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_signin = new MemberSigninModel();
$res = $member_signin->signin($token[ 'data' ][ 'member_id' ], $this->site_id);
return $this->response($res);
}
/**
* 签到奖励规则
* @return string
*/
public function award()
{
$member_signin = new MemberSigninModel();
$info = $member_signin->getAward($this->site_id);
return $this->response($info);
}
/**
* 获取签到记录
*/
public function getSignRecords()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_signin = new MemberSigninModel();
$date = strtotime(date('Y-m-01 00:00:00')) - 86400 * 6;
$condition = [
[ 'member_id', '=', $this->member_id ],
[ 'create_time', 'between', [ $date, time() ] ],
[ 'action', '=', 'membersignin' ]
];
$list = $member_signin->getMemberSigninList($condition, 'create_time', 'id asc');
return $this->response($list);
}
/**
* 获取签到是否开启
*/
public function getSignStatus()
{
$config_model = new Signin();
$config_result = $config_model->getConfig($this->site_id);
return $this->response($config_result);
}
}

View File

@@ -0,0 +1,148 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\api\controller;
use addon\wechat\model\Config as WechatConfig;
use app\model\member\Withdraw as WithdrawModel;
use app\model\member\Member as MemberModel;
/**
* 会员提现
*/
class Memberwithdraw extends BaseApi
{
/**
* 会员提现信息
*/
public function info()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_model = new MemberModel();
$member_info_result = $member_model->getMemberInfo([ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ] ], 'site_id,balance_money,balance_withdraw_apply,balance_withdraw');
$config_model = new WithdrawModel();
$config_result = $config_model->getConfig($member_info_result[ 'data' ][ 'site_id' ], 'shop');
$config = $config_result['data'][ 'value' ];
$config[ 'is_use' ] = $config_result['data'][ 'is_use' ];
$data = [
'member_info' => $member_info_result['data'],
'config' => $config
];
return $this->response($this->success($data));
}
/**
* 会员提现配置
*/
public function config()
{
$config_model = new WithdrawModel();
$config_result = $config_model->getConfig($this->site_id, 'shop');
return $this->response($config_result);
}
/**
* 获取转账方式
* @return false|string
*/
public function transferType()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_model = new MemberModel();
$member_info = $member_model->getMemberInfo([ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ] ], 'site_id,wx_openid,weapp_openid');
$withdraw_model = new WithdrawModel();
$transfer_type_list = $withdraw_model->getTransferType($member_info[ 'data' ][ 'site_id' ]);
if (empty($member_info[ 'data' ][ 'wx_openid' ]) && empty($member_info[ 'data' ][ 'weapp_openid' ])) {
unset($transfer_type_list[ 'wechatpay' ]);
}
return $this->response($this->success($transfer_type_list));
}
/**
* 申请提现
* @return false|string
*/
public function apply()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$apply_money = $this->params['apply_money'] ?? 0;
$transfer_type = $this->params['transfer_type'] ?? '';//提现方式
$realname = $this->params['realname'] ?? '';//真实姓名
$bank_name = $this->params['bank_name'] ?? '';//银行名称
$account_number = $this->params['account_number'] ?? '';//账号名称
$mobile = $this->params['mobile'] ?? '';//手机号
$app_type = $this->params[ 'app_type' ];
$member_model = new MemberModel();
$member_info = $member_model->getMemberInfo([ [ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ] ], 'site_id');
$withdraw_model = new WithdrawModel();
$data = [
'member_id' => $token[ 'data' ][ 'member_id' ],
'transfer_type' => $transfer_type,
'realname' => $realname,
'bank_name' => $bank_name,
'account_number' => $account_number,
'apply_money' => $apply_money,
'mobile' => $mobile,
'app_type' => $app_type
];
$result = $withdraw_model->apply($data, $member_info[ 'data' ][ 'site_id' ], 'shop');
return $this->response($result);
}
/**
* 提现详情
* @return false|string
*/
public function detail()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$condition = [
['member_id', '=', $token[ 'data' ][ 'member_id' ] ],
['id', '=', $id ]
];
$withdraw_model = new WithdrawModel();
$info = $withdraw_model->getMemberWithdrawDetail($condition);
return $this->response($info);
}
/**
* 提现记录
* @return false|string
*/
public function page()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$condition = [
['member_id', '=', $token[ 'data' ][ 'member_id' ] ]
];
$withdraw_model = new WithdrawModel();
$list = $withdraw_model->getMemberWithdrawPageList($condition, $page, $page_size, 'apply_time desc', 'id,withdraw_no,apply_money,apply_time,status,status_name,transfer_type_name,fail_reason,refuse_reason,transfer_type');
return $this->response($list);
}
}

69
app/api/controller/Notice.php Executable file
View File

@@ -0,0 +1,69 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\api\controller;
use app\model\web\Notice as NoticeModel;
/**
* Class Notice
* @package app\api\controller
*/
class Notice extends BaseApi
{
/**
* 基础信息
*/
public function info()
{
$id = $this->params['id'] ?? 0;
if (empty($id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$notice = new NoticeModel();
$info = $notice->getNoticeInfo([ [ 'id', '=', $id ], [ 'site_id', '=', $this->site_id ] ]);
return $this->response($info);
}
public function lists()
{
$id_arr = $this->params['id_arr'] ?? '';//id数组
$notice = new NoticeModel();
$condition = [
[ 'receiving_type', 'like', '%mobile%' ],
[ 'site_id', '=', $this->site_id ],
[ 'id', 'in', $id_arr ]
];
$list = $notice->getNoticeList($condition);
return $this->response($list);
}
public function page()
{
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$id_arr = $this->params['id_arr'] ?? '';//id数组
$notice = new NoticeModel();
$order = 'is_top desc,sort desc,create_time desc';
$condition = [
[ 'receiving_type', 'like', '%mobile%' ],
[ 'site_id', '=', $this->site_id ]
];
if (!empty($id_arr)) {
$condition[] = [ 'id', 'in', $id_arr ];
}
$list = $notice->getNoticePageList($condition, $page, $page_size, $order);
return $this->response($list);
}
}

336
app/api/controller/Order.php Executable file
View File

@@ -0,0 +1,336 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use addon\weapp\model\Weapp;
use addon\wechatpay\model\Config as WechatPayModel;
use app\dict\order\OrderDict;
use app\dict\order_refund\OrderRefundDict;
use app\model\express\ExpressPackage;
use app\model\order\Order as OrderModel;
use app\model\order\OrderCommon as OrderCommonModel;
use app\model\order\Config as ConfigModel;
use app\model\order\VirtualOrder;
use think\facade\Db;
class Order extends BaseApi
{
/**
* 详情信息
*/
public function detail()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? 0;
$merchant_trade_no = $this->params['merchant_trade_no'] ?? '';
if (empty($order_id) && empty($merchant_trade_no)) {
return $this->response($this->error('', '缺少参数order_id|merchant_trade_no'));
}
$order_common_model = new OrderCommonModel();
$result = $order_common_model->getMemberOrderDetail($order_id, $this->member_id, $this->site_id, $merchant_trade_no);
//获取未付款订单自动关闭时间 字段'auto_close'
$config_model = new ConfigModel();
$order_event_time_config = $config_model->getOrderEventTimeConfig($this->site_id, 'shop');
$auto_close = $order_event_time_config[ 'data' ][ 'value' ][ 'auto_close' ] * 60 ?? [];
$result[ 'data' ][ 'auto_close' ] = $auto_close;
$result[ 'data' ][ 'pay_config' ] = ( new WechatPayModel() )->getPayConfig($this->site_id, $this->app_module, true)[ 'data' ][ 'value' ];
// 检测微信小程序是否已开通发货信息管理服务
$weapp_model = new Weapp($this->site_id);
$result[ 'data' ][ 'is_trade_managed' ] = $weapp_model->orderShippingIsTradeManaged()[ 'data' ];
return $this->response($result);
}
/**
* 列表信息
*/
public function lists()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$search_text = $this->params['searchText'] ?? '';
$order_status = $this->params['order_status'] ?? 'all';
$page_index = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$order_id = $this->params['order_id'] ?? 0;
$condition = [
['o.member_id', '=', $this->member_id ],
['o.site_id', '=', $this->site_id ],
['o.is_delete', '=', 0 ]
];
switch ( $order_status ) {
case 'waitpay'://待付款
$condition[] = ['o.order_status', '=', 0 ];
$condition[] = [ 'o.order_scene', '=', 'online' ];
break;
case 'waitsend'://待发货
$condition[] = ['o.order_status', '=', 1 ];
break;
case 'waitconfirm'://待收货
$condition[] = ['o.order_status', 'in', [ 2, 3 ] ];
$condition[] = ['o.order_type', '<>', 4 ];
break;
//todo 这儿改了之后要考虑旧数据的问题
case 'wait_use'://待使用
$condition[] = ['o.order_status', 'in', [ 3, 11 ] ];
$condition[] = ['o.order_type', '=', 4 ];
break;
case 'waitrate'://待评价
$condition[] = ['o.order_status', 'in', [ 4, 10 ] ];
$condition[] = ['o.is_evaluate', '=', 1 ];
$condition[] = ['o.evaluate_status', '=', OrderDict::evaluate_wait ];
break;
default:
$condition[] = [ '', 'exp', Db::raw("o.order_scene = 'online' OR (o.order_scene = 'cashier' AND o.pay_status = 1)") ];
}
// if (c !== "all") {
// $condition[] = [ "order_status", "=", $order_status ];
// }
//获取未付款订单自动关闭时间 字段'auto_close'
$config_model = new ConfigModel();
$order_event_time_config = $config_model->getOrderEventTimeConfig($this->site_id, 'shop');
if ($order_id) {
$condition[] = ['o.order_id', '=', $order_id ];
}
$join = [];
$alias = 'o';
if ($search_text) {
$condition[] = [ 'o.order_name|o.order_no', 'like', '%' . $search_text . '%' ];
// $join = [
// [ 'order_goods og', 'og.order_id = o.order_id', 'left' ]
// ];
}
$order_common_model = new OrderCommonModel();
$res = $order_common_model->getMemberOrderPageList($condition, $page_index, $page_size, 'o.create_time desc', '*', $alias, $join);
$auto_close = $order_event_time_config[ 'data' ][ 'value' ][ 'auto_close' ] * 60 ?? [];
$res[ 'data' ][ 'auto_close' ] = $auto_close;
$res[ 'data' ][ 'pay_config' ] = ( new WechatPayModel() )->getPayConfig($this->site_id, $this->app_module, true)[ 'data' ][ 'value' ];
// 检测微信小程序是否已开通发货信息管理服务
$weapp_model = new Weapp($this->site_id);
$res[ 'data' ][ 'is_trade_managed' ] = $weapp_model->orderShippingIsTradeManaged()[ 'data' ];
return $this->response($res);
}
/**
* 订单评价基础信息
*/
public function evluateinfo()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? 0;
if (empty($order_id)) {
return $this->response($this->error('', 'REQUEST_ORDER_ID'));
}
$order_common_model = new OrderCommonModel();
$order_info = $order_common_model->getOrderInfo([
[ 'order_id', '=', $order_id ],
[ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ],
[ 'order_status', 'in', ( '4,10' ) ],
[ 'is_evaluate', '=', 1 ],
], 'evaluate_status,evaluate_status_name');
$res = $order_info[ 'data' ];
if (!empty($res)) {
if ($res[ 'evaluate_status' ] == OrderDict::evaluate_again) {
return $this->response($this->error('', '该订单已评价'));
} else {
$condition = [
[ 'order_id', '=', $order_id ],
[ 'member_id', '=', $token[ 'data' ][ 'member_id' ] ],
[ 'refund_status', '<>', OrderRefundDict::REFUND_COMPLETE ],
];
$res[ 'list' ] = $order_common_model->getOrderGoodsList($condition, 'order_goods_id,order_id,order_no,site_id,member_id,goods_id,sku_id,sku_name,sku_image,price,num')[ 'data' ];
return $this->response($this->success($res));
}
} else {
return $this->response($this->error('', '没有找到该订单'));
}
}
/**
* 订单收货(收到所有货物)
*/
public function takeDelivery()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? 0;
if (empty($order_id)) {
return $this->response($this->error('', 'REQUEST_ORDER_ID'));
}
$order_model = new OrderCommonModel();
$log_data = [
'uid' => $this->member_id,
'action_way' => 1
];
$result = $order_model->orderCommonTakeDelivery($order_id, $log_data);
return $this->response($result);
}
/**
* 关闭订单
*/
public function close()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? 0;
if (empty($order_id)) {
return $this->response($this->error('', 'REQUEST_ORDER_ID'));
}
$order_model = new OrderModel();
//关闭检测
$check_res = $order_model->activeOrderCloseCheck($order_id);
if($check_res['code'] < 0) $this->response($check_res);
$log_data = [
'uid' => $this->member_id,
'action_way' => 1
];
$result = $order_model->orderClose($order_id, $log_data);
return $this->response($result);
}
/**
* 获取订单数量
*/
public function num()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_common_model = new OrderCommonModel();
$data = $order_common_model->getMemberOrderNum($this->member_id);
return $this->response($data);
}
/**
* 订单包裹信息
*/
public function package()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? '';//订单id
$express_package_model = new ExpressPackage();
$condition = [
['member_id', '=', $this->member_id ],
['order_id', '=', $order_id ],
];
$order_common_model = new OrderCommonModel();
$order_detail = $order_common_model->getOrderInfo([ [ 'member_id', '=', $this->member_id ], [ 'order_id', '=', $order_id ], [ 'site_id', '=', $this->site_id ] ]);
$save_trace = $order_detail['data']['order_status'] == OrderCommonModel::ORDER_TAKE_DELIVERY;
$result = $express_package_model->package($condition, $order_detail[ 'data' ][ 'mobile' ], $save_trace);
if (!empty($result)) {
foreach ($result as $kk => $vv) {
if (!empty($vv[ 'trace' ][ 'list' ])) {
$result[ $kk ][ 'trace' ][ 'list' ] = array_reverse($vv[ 'trace' ][ 'list' ]);
}
}
}
if ($result) return $this->response($this->success($result));
else return $this->response($this->error());
}
/**
* 订单支付
* @return string
*/
public function pay()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_ids = $this->params['order_ids'] ?? '';//订单id
if (empty($order_ids)) return $this->response($this->error('', '订单数据为空'));
$order_common_model = new OrderCommonModel();
$result = $order_common_model->splitOrderPay($order_ids);
return $this->response($result);
}
/**
* 交易协议
* @return false|string
*/
public function transactionAgreement()
{
$config_model = new ConfigModel();
$document_info = $config_model->getTransactionDocument($this->site_id, $this->app_module);
return $this->response($document_info);
}
/**
* 虚拟订单收货
*/
public function memberVirtualTakeDelivery()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params[ 'order_id' ] ?? 0;//订单id
if (empty($order_id)) return $this->response($this->error('', '订单数据为空'));
$virtual_order_model = new VirtualOrder();
$params = [
'order_id' => $order_id,
'site_id' => $this->site_id,
'member_id' => $this->member_id
];
$log_data = [
'uid' => $this->member_id,
'action_way' => 1
];
$result = $virtual_order_model->virtualTakeDelivery($params, $log_data);
return $this->response($result);
}
/**
* 删除订单
*/
public function delete()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_id = $this->params['order_id'] ?? 0;
$order_model = new OrderModel();
$result = $order_model->deleteOrder([['order_id', '=', $order_id], ['member_id', '=', $this->member_id], ['order_status', '=', OrderModel::ORDER_CLOSE]]);
return $this->response($result);
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\order\OrderCreate as OrderCreateModel;
/**
* 订单创建
*/
class Ordercreate extends BaseOrderCreateApi
{
/**
* 创建
*/
public function create()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_create = new OrderCreateModel();
$data = [
'order_key' => $this->params[ 'order_key' ] ?? '',
'is_balance' => $this->params[ 'is_balance' ] ?? 0,//是否使用余额
'is_point' => $this->params[ 'is_point' ] ?? 1,//是否使用积分
'coupon' => isset($this->params[ 'coupon' ]) && !empty($this->params[ 'coupon' ]) ? json_decode($this->params[ 'coupon' ], true) : [],
//会员卡项
'member_card_unit' => $this->params[ 'member_card_unit' ] ?? '',
//门店专属
'store_id' => $this->params[ 'store_id' ] ?? 0,
];
$res = $order_create->setParam(array_merge($data, $this->getInputParam(), $this->getCommonParam(), $this->getDeliveryParam(), $this->getInvoiceParam()))->create();
return $this->response($res);
}
/**
* 计算
*/
public function calculate()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_create = new OrderCreateModel();
$data = [
'order_key' => $this->params[ 'order_key' ] ?? '',//是否使用余额
'is_balance' => $this->params[ 'is_balance' ] ?? 0,//是否使用余额
'is_point' => $this->params[ 'is_point' ] ?? 1,//是否使用积分
'coupon' => isset($this->params[ 'coupon' ]) && !empty($this->params[ 'coupon' ]) ? json_decode($this->params[ 'coupon' ], true) : [],
//会员卡项
'member_card_unit' => $this->params[ 'member_card_unit' ] ?? '',
//门店专属
'store_id' => $this->params[ 'store_id' ] ?? 0,
];
$res = $order_create->setParam(array_merge($data, $this->getCommonParam(), $this->getDeliveryParam(), $this->getInvoiceParam()))->confirm();
return $this->response($this->success($res));
}
/**
* 待支付订单 数据初始化
* @return string
*/
public function payment()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_create = new OrderCreateModel();
$data = [
//商品项
'cart_ids' => $this->params[ 'cart_ids' ] ?? '',
'sku_id' => $this->params[ 'sku_id' ] ?? '',
'num' => $this->params[ 'num' ] ?? '',
//会员卡项
'member_goods_card' => isset($this->params[ 'member_goods_card' ]) && !empty($this->params[ 'member_goods_card' ]) ? json_decode($this->params[ 'member_goods_card' ], true) : [],
//接龙活动id
'jielong_id' => $this->params[ 'jielong_id' ] ?? '',
//会员卡项
'is_open_card' => $this->params[ 'is_open_card' ] ?? 0,
'member_card_unit' => $this->params[ 'member_card_unit' ] ?? '',
//门店专属
'store_id' => $this->params[ 'store_id' ] ?? 0,
];
if (!$data[ 'cart_ids' ] && !$data[ 'sku_id' ]) return $this->response($this->error('', '缺少必填参数商品数据'));
$res = $order_create->setParam(array_merge($data, $this->getInputParam(), $this->getCommonParam(), $this->getDeliveryParam()))->orderPayment();
return $this->response($this->success($res));
}
/**
* 查询订单可用的优惠券
* @return false|string
*/
public function getCouponList(){
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_create = new OrderCreateModel();
$data = [
'order_key' => $this->params[ 'order_key' ] ?? '',//是否使用余额
'store_id' => $this->params[ 'store_id' ] ?? 0,//可能没有门店id要做默认处理
'delivery' => $this->params[ 'delivery' ],
];
$res = $order_create->setParam(array_merge($data, $this->getCommonParam()))->getOrderCouponList();
return $this->response($this->success($res));
}
}

View File

@@ -0,0 +1,233 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\dict\order_refund\OrderRefundDict;
use app\model\member\Member as MemberModel;
use app\model\order\Config as ConfigModel;
use app\model\order\OrderRefund as OrderRefundModel;
class Orderrefund extends BaseApi
{
/**
* 售后列表
*/
public function lists()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_refund_model = new OrderRefundModel();
$condition = [
[ 'nop.member_id', '=', $this->member_id ],
];
$refund_status = $this->params['refund_status'] ?? 'all';
switch ( $refund_status ) {
// case 'waitpay'://处理中
// $condition[] = [ 'refund_status', '=', 1 ];
// break;
default :
$condition[] = [ 'nop.refund_status', '<>', OrderRefundDict::REFUND_NOT_APPLY ];
break;
}
$page_index = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$res = $order_refund_model->getRefundOrderGoodsPageList($condition, $page_index, $page_size, 'refund_action_time desc');
return $this->response($res);
}
/**
* 退款数据查询
* @return string
*/
public function refundData()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_goods_id = $this->params['order_goods_id'] ?? '0';
$order_refund_model = new OrderRefundModel();
$order_goods_info = $order_refund_model->getRefundDetail($order_goods_id)[ 'data' ];//订单项信息
$refund_money_array = $order_refund_model->getOrderRefundMoney($order_goods_id);
if (isset($refund_money_array[ 'code' ]) && $refund_money_array[ 'code' ] != 0) return $this->response($refund_money_array);
$refund_delivery_money = $refund_money_array[ 'refund_delivery_money' ];//其中的运费
$refund_money = $refund_money_array[ 'refund_money' ];//总退款
$refund_type = $order_refund_model->getRefundType($order_goods_info);
$refund_reason_type = OrderRefundDict::getRefundReasonType($this->site_id);
$result = [
'order_goods_info' => $order_goods_info,
'refund_money' => $refund_money,
'refund_type' => $refund_type,
'refund_reason_type' => $refund_reason_type,
'refund_delivery_money' => $refund_delivery_money
];
return $this->response($this->success($result));
}
/**
* 多个退款数据查询
*/
public function refundDataBatch()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_goods_ids = $this->params['order_goods_ids'] ?? '';
$order_refund_model = new OrderRefundModel();
if (empty($order_goods_ids)) return $this->response($this->error('', '未传order_goods_ids'));
$order_goods_id_arr = explode(',', $order_goods_ids);
$order_goods_info_result = [];
foreach ($order_goods_id_arr as $item) {
$order_goods_info_result[] = $order_refund_model->getRefundDetail($item)[ 'data' ] ?? [];
}
$order_goods_info = $order_goods_info_result;//订单项信息
$refund_money_array = $order_refund_model->getOrderRefundMoney($order_goods_ids);
$refund_delivery_money = $refund_money_array[ 'refund_delivery_money' ];//其中的运费
$refund_money = $refund_money_array[ 'refund_money' ];//总退款
$refund_type = $order_refund_model->getRefundOrderType($order_goods_info[ 0 ][ 'order_id' ]);
$refund_reason_type = OrderRefundDict::getRefundReasonType($this->site_id);
$result = [
'order_goods_info' => $order_goods_info,
'refund_money' => $refund_money,
'refund_type' => $refund_type,
'refund_reason_type' => $refund_reason_type,
'refund_delivery_money' => $refund_delivery_money
];
return $this->response($this->success($result));
}
/**
* 发起退款
*/
public function refund()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_model = new MemberModel();
$member_info_result = $member_model->getMemberInfo([ [ 'member_id', '=', $this->member_id ] ]);
$member_info = $member_info_result[ 'data' ];
$order_refund_model = new OrderRefundModel();
$order_goods_ids = $this->params[ 'order_goods_ids' ] ?? '0';
$refund_type = $this->params[ 'refund_type' ] ?? 1;
$refund_reason = $this->params[ 'refund_reason' ] ?? '';
$refund_remark = $this->params[ 'refund_remark' ] ?? '';
$refund_images = $this->params[ 'refund_images' ] ?? '';
if (empty($order_goods_ids)) return $this->response($this->error('', '未传order_goods_ids'));
$log_data = [
'uid' => $this->member_id,
'nick_name' => $member_info[ 'nickname' ],
'action' => '买家发起了退款申请',
'action_way' => 1
];
$order_goods_ids = explode(',', $order_goods_ids);
foreach ($order_goods_ids as $item) {
$data = [
'order_goods_id' => $item,
'refund_type' => $refund_type,
'refund_reason' => $refund_reason,
'refund_remark' => $refund_remark,
'refund_images' => $refund_images,
];
$result = $order_refund_model->apply($data, $member_info, $log_data);
}
//新增未发货订单自动退款逻辑
$config_model = new ConfigModel();
$order_refund_config = $config_model->getOrderRefundConfig($this->site_id, $this->app_module);
if($order_refund_config['data']['value']['auto_refund'] == 1){
foreach ($order_goods_ids as $item) {
$order_refund_model->autoRefundOrder($item);
}
}
return $this->response($result);
}
/**
* 取消发起的退款申请
*/
public function cancel()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_model = new MemberModel();
$member_info_result = $member_model->getMemberInfo([ [ 'member_id', '=', $this->member_id ] ]);
$member_info = $member_info_result[ 'data' ];
$order_refund_model = new OrderRefundModel();
$order_goods_id = $this->params['order_goods_id'] ?? '0';
$data = [
'order_goods_id' => $order_goods_id
];
$log_data = [
'uid' => $this->member_id,
'nick_name' => $member_info[ 'nickname' ],
'action' => '买家撤销了维权',
'action_way' => 1
];
$res = $order_refund_model->cancel($data, $member_info, $log_data);
return $this->response($res);
}
/**
* 买家退货
* @return string
*/
public function delivery()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$member_model = new MemberModel();
$member_info_result = $member_model->getMemberInfo([ [ 'member_id', '=', $this->member_id ] ]);
$member_info = $member_info_result[ 'data' ];
$order_refund_model = new OrderRefundModel();
$order_goods_id = $this->params['order_goods_id'] ?? '0';
$refund_delivery_name = $this->params['refund_delivery_name'] ?? '';//物流公司名称
$refund_delivery_no = $this->params['refund_delivery_no'] ?? '';//物流编号
$refund_delivery_remark = $this->params['refund_delivery_remark'] ?? '';//买家发货说明
$data = [
'order_goods_id' => $order_goods_id,
'refund_delivery_name' => $refund_delivery_name,
'refund_delivery_no' => $refund_delivery_no,
'refund_delivery_remark' => $refund_delivery_remark
];
$res = $order_refund_model->orderRefundDelivery($data, $member_info);
return $this->response($res);
}
/**
* 维权详情
* @return string
*/
public function detail()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$order_refund_model = new OrderRefundModel();
$order_goods_id = $this->params['order_goods_id'] ?? '0';
$order_goods_info_result = $order_refund_model->getMemberRefundDetail($order_goods_id, $this->member_id);
$order_goods_info = $order_goods_info_result[ 'data' ] ?? [];
if ($order_goods_info) {
//查询店铺收货地址
$order_goods_info_result[ 'data' ] = array_merge($order_goods_info_result[ 'data' ], $order_refund_model->getRefundAddress($this->site_id, $order_goods_info[ 'refund_address_id' ]));
}
return $this->response($order_goods_info_result);
}
}

175
app/api/controller/Pay.php Executable file
View File

@@ -0,0 +1,175 @@
<?php
/**
* Pay.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\order\Order as OrderModel;
use app\model\system\Pay as PayModel;
use app\model\order\Config;
use app\model\system\PayBalance;
/**
* 支付控制器
*/
class Pay extends BaseApi
{
/**
* 支付信息
*/
public function info()
{
$out_trade_no = $this->params[ 'out_trade_no' ];
$pay = new PayModel();
$info = $pay->getPayInfo($out_trade_no)[ 'data' ] ?? [];
if (!empty($info)) {
if (in_array($info[ 'event' ], [ 'OrderPayNotify', 'CashierOrderPayNotify' ])) {
$order_model = new OrderModel();
$order_info = $order_model->getOrderInfo([ [ 'out_trade_no', '=', $out_trade_no ] ], 'order_id,order_type,create_time')[ 'data' ];
if (!empty($order_info)) {
$info[ 'order_id' ] = $order_info[ 'order_id' ];
$info[ 'order_type' ] = $order_info[ 'order_type' ];
//获取未付款订单自动关闭时间
$config_model = new Config();
$order_event_time_config = $config_model->getOrderEventTimeConfig($this->site_id, 'shop');
$info['auto_close_time'] = $order_event_time_config[ 'data' ][ 'value' ][ 'auto_close' ] * 60 + $order_info['create_time'];
}
}
}
return $this->response($this->success($info));
}
/**
* 支付调用
*/
public function pay()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$pay_type = $this->params[ 'pay_type' ];
$out_trade_no = $this->params[ 'out_trade_no' ];
$app_type = $this->params[ 'app_type' ];
$return_url = isset($this->params[ 'return_url' ]) && !empty($this->params[ 'return_url' ]) ? urldecode($this->params[ 'return_url' ]) : null;
$scene = $this->params[ 'scene' ] ?? 0;
$is_balance = $this->params[ 'is_balance' ] ?? 0;
$pay = new PayModel();
$info = $pay->pay($pay_type, $out_trade_no, $app_type, $this->member_id, $return_url, $is_balance, $scene);
return $this->response($info);
}
/**
* 支付方式
*/
public function type()
{
$pay = new PayModel();
$info = $pay->getPayType($this->params);
$temp = empty($info) ? [] : $info;
$type = [];
foreach ($temp[ 'data' ] as $k => $v) {
$type[] = $v['pay_type'];
}
$type = implode(',', $type);
return $this->response(success(0, '', [ 'pay_type' => $type ]));
}
/**
* 获取订单支付状态
*/
public function status()
{
$pay = new PayModel();
$out_trade_no = $this->params[ 'out_trade_no' ];
$res = $pay->getPayInfo($out_trade_no);
if(empty($res['data'])) $res = $pay->error();
return $this->response($res);
}
/**
* 获取余额支付配置
*/
public function getBalanceConfig()
{
$config_model = new Config();
$res = $order_evaluate_config = $config_model->getBalanceConfig($this->site_id);
return $this->response($this->success($res[ 'data' ][ 'value' ]));
}
/**
* 重置支付
*/
public function resetPay()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$out_trade_no = $this->params[ 'out_trade_no' ];
$pay = new PayModel();
$result = $pay->resetPay([ 'out_trade_no' => $out_trade_no ]);
return $this->response($result);
}
/**
* 会员付款码
*/
public function memberPayCode()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$data = ( new PayBalance() )->create([ 'member_id' => $this->member_id, 'site_id' => $this->site_id ]);
return $this->response($data);
}
/**
* 查询会员付款码信息
* @return false|string
*/
public function memberPayInfo()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$auth_code = $this->params[ 'auth_code' ] ?? '';
$data = ( new PayBalance() )->getInfo([ [ 'member_id', '=', $this->member_id ], [ 'site_id', '=', $this->site_id ], [ 'auth_code', '=', $auth_code ] ], 'status,out_trade_no');
return $this->response($data);
}
/**
* 通过外部交易号获取订单详情路径
*/
public function outTradeNoToOrderDetailPath()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$out_trade_no = $this->params[ 'out_trade_no' ] ?? '';
$pay_model = new PayModel();
$pay_info = $pay_model->getPayInfo($out_trade_no)[ 'data' ];
if(empty($pay_info)){
return $this->response($this->error(null, '交易信息有误'));
}
if($this->app_type == 'pc'){
$event = 'PcOrderDetailPathByPayInfo';
}else{
$event = 'WapOrderDetailPathByPayInfo';
}
$order_detail_path = event($event, $pay_info, true);
if(empty($order_detail_path)){
return $this->response($this->error(null, '未获取到订单详情路径'));
}
return $this->response($this->success($order_detail_path));
}
}

114
app/api/controller/Pc.php Executable file
View File

@@ -0,0 +1,114 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 山西牛酷信息科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和使用。
* 任何企业和个人不允许对程序代码以任何形式任何目的再发布。
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\goods\Goods as GoodsModel;
use app\model\goods\GoodsCategory as GoodsCategoryModel;
use addon\pc\model\Pc as PcModel;
use app\model\web\Config as ConfigModel;
/**
* Pc端接口
* @author Administrator
*
*/
class Pc extends BaseApi
{
/**
* 获取首页浮层
*/
public function floatLayer()
{
$pc_model = new PcModel();
$info = $pc_model->getFloatLayer($this->site_id);
return $this->response($this->success($info[ 'data' ][ 'value' ]));
}
/**
* 楼层列表
*
* @return string
*/
public function floors()
{
$pc_model = new PcModel();
$condition = [
[ 'state', '=', 1 ],
[ 'site_id', '=', $this->site_id ]
];
$list = $pc_model->getFloorList($condition, 'pf.title,pf.value,fb.name as block_name,fb.title as block_title');
if (!empty($list[ 'data' ])) {
$config_model = new ConfigModel();
$sort_config = $config_model->getGoodsSort($this->site_id);
$sort_config = $sort_config[ 'data' ][ 'value' ];
$goods_model = new GoodsModel();
$goods_category_model = new GoodsCategoryModel();
foreach ($list[ 'data' ] as $k => $v) {
$value = $v[ 'value' ];
if (!empty($value)) {
$value = json_decode($value, true);
foreach ($value as $ck => $cv) {
if (!empty($cv[ 'type' ])) {
if ($cv[ 'type' ] == 'goods') {
$field = 'gs.sku_id,gs.price,gs.market_price,gs.discount_price,g.goods_stock,(g.sale_num + g.virtual_sale) as sale_num,g.goods_image,g.goods_name,g.introduction';
$order = 'g.sort ' . $sort_config[ 'type' ] . ',g.create_time desc';
$join = [
[ 'goods g', 'gs.sku_id = g.sku_id', 'inner' ]
];
$goods_sku_list = $goods_model->getGoodsSkuPageList([ [ 'gs.goods_id', 'in', $cv[ 'value' ][ 'goods_ids' ] ] ], 1, 0, $order, $field, 'gs', $join)[ 'data' ][ 'list' ];
$value[ $ck ][ 'value' ][ 'list' ] = $goods_sku_list;
} elseif ($cv[ 'type' ] == 'category') {
// 商品分类
$condition = [
[ 'category_id', 'in', $cv[ 'value' ][ 'category_ids' ] ],
[ 'site_id', '=', $this->site_id ]
];
$category_list = $goods_category_model->getCategoryList($condition, 'category_id,category_name,short_name,level,image,image_adv');
$category_list = $category_list[ 'data' ];
$value[ $ck ][ 'value' ][ 'list' ] = $category_list;
}
}
}
$list[ 'data' ][ $k ][ 'value' ] = $value;
}
}
}
return $this->response($list);
}
/**
* 获取导航
*/
public function navList()
{
$pc_model = new PcModel();
$data = $pc_model->getNavList([ [ 'is_show', '=', 1 ], [ 'site_id', '=', $this->site_id ] ], 'id,nav_title,nav_url,sort,is_blank,create_time,modify_time,nav_icon,is_show', 'sort asc,create_time desc');
return $this->response($data);
}
/**
* 获取友情链接
*/
public function friendlyLink()
{
$pc_model = new PcModel();
$data = $pc_model->getLinkList([ [ 'is_show', '=', 1 ], [ 'site_id', '=', $this->site_id ] ], 'id,link_title,link_url,link_pic,link_sort,is_blank', 'link_sort asc,id desc');
return $this->response($data);
}
}

179
app/api/controller/Register.php Executable file
View File

@@ -0,0 +1,179 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\exception\ApiException;
use app\model\member\Config;
use app\model\member\Register as RegisterModel;
use app\model\message\Message;
use think\facade\Cache;
class Register extends BaseApi
{
/**
* 注册设置
*/
public function config()
{
$register = new Config();
$info = $register->getRegisterConfig($this->site_id, 'shop');
return $this->response($info);
}
/**
* 相关协议
*/
public function aggrement()
{
$type = $this->params['type'] ?? 'SERVICE';
$register = new Config();
switch($type){
case 'SERVICE':
$res = $register->getRegisterDocument($this->site_id, 'shop');
break;
case 'PRIVACY':
$res = $register->getPrivacyDocument($this->site_id, 'shop');
break;
default:
$res = $register->error(null, '不支持的类型');
}
return $this->response($res);
}
/**
* 用户名密码注册
*/
public function username()
{
$config = new Config();
$config_info = $config->getRegisterConfig($this->site_id);
if (strstr($config_info[ 'data' ][ 'value' ][ 'register' ], 'username') === false) return $this->response($this->error('', 'REGISTER_REFUND'));
$register = new RegisterModel();
$this->params[ 'username' ] = str_replace(' ', '', $this->params[ 'username' ]);
if (empty($this->params[ 'username' ])) return $this->response($this->error('', '用户名已存在'));
$exist = $register->usernameExist($this->params[ 'username' ], $this->site_id);
if ($exist) {
return $this->response($this->error('', '用户名已存在'));
} else {
// 校验验证码
$config_model = new \app\model\web\Config();
$info = $config_model->getCaptchaConfig();
$captcha = new Captcha();
if ($info[ 'data' ][ 'value' ][ 'shop_reception_register' ] == 1) {
$check_res = $captcha->checkCaptcha();
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
}
$res = $register->usernameRegister($this->params);
//生成access_token
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ]);
return $this->response($this->success(['token' => $token]));
}
return $this->response($res);
}
}
/**
* 手机号注册
* @return false|string
*/
public function mobile()
{
$config = new Config();
$config_info = $config->getRegisterConfig($this->site_id);
if (strstr($config_info[ 'data' ][ 'value' ][ 'register' ], 'mobile') === false) return $this->response($this->error('', 'REGISTER_REFUND'));
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
return $this->response($this->error('', '手机号已存在'));
} else {
$key = $this->params[ 'key' ];
$verify_data = Cache::get($key);
if (!empty($verify_data) && $verify_data[ 'mobile' ] == $this->params[ 'mobile' ] && $verify_data[ 'code' ] == $this->params[ 'code' ]) {
$res = $register->mobileRegister($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ]);
$res = $this->success(['token' => $token]);
}
} else {
$res = $this->error('', '手机动态码不正确');
}
return $this->response($res);
}
}
/**
* 检测用户名称或者手机是否存在
*/
public function exist()
{
$type = $this->params[ 'type' ];
$register = new RegisterModel();
switch ($type) {
case 'username' :
$res = $register->usernameExist($this->params[ 'username' ], $this->site_id);
break;
case 'mobile' :
$res = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
break;
default:
$res = 0;
break;
}
if ($res) {
return $this->response($this->error('', '账户已存在'));
} else {
return $this->response($this->success());
}
}
/**
* 短信验证码
* @return false|string
* @throws ApiException
*/
public function mobileCode()
{
// 校验验证码
$config_model = new \app\model\web\Config();
$info = $config_model->getCaptchaConfig();
if ($info[ 'data' ][ 'value' ][ 'shop_reception_register' ] == 1) {
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha(false);
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
}
$mobile = $this->params[ 'mobile' ];//注册手机号
$register = new RegisterModel();
$exist = $register->mobileExist($mobile, $this->site_id);
if ($exist) {
return $this->response($this->error('', '手机号已存在'));
} else {
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage(['type' => 'code', 'mobile' => $mobile, 'site_id' => $this->site_id, 'code' => $code, 'support_type' => ['sms'], 'keywords' => 'REGISTER_CODE']);
if ($res[ 'code' ] >= 0) {
//将验证码存入缓存
$key = 'register_mobile_code_' . md5(uniqid(null, true));
Cache::tag('register_mobile_code')->set($key, ['mobile' => $mobile, 'code' => $code], 600);
return $this->response($this->success(['key' => $key]));
} else {
return $this->response($res);
}
}
}
}

90
app/api/controller/Site.php Executable file
View File

@@ -0,0 +1,90 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\system\Site as SiteModel;
use app\model\shop\Shop as ShopModel;
/**
* 店铺
* @author Administrator
*
*/
class Site extends BaseApi
{
public function __construct()
{
parent::__construct();
$this->initStoreData();
}
/**
* 基础信息
*/
public function info()
{
$field = 'site_id,site_domain,site_name,logo,seo_title,seo_keywords,seo_description,site_tel,logo_square';
$website_model = new SiteModel();
$info = $website_model->getSiteInfo([ [ 'site_id', '=', $this->site_id ] ], $field);
//店铺状态
$shop_model = new ShopModel();
$shop_status_result = $shop_model->getShopStatus($this->site_id, $this->app_module);
$shop_status = $shop_status_result[ 'data' ][ 'value' ];
$info[ 'data' ][ 'shop_status' ] = $shop_status[ 'shop_pc_status' ];
return $this->response($info);
}
/**
* 手机端二维码
* @return false|string
*/
public function wapQrcode()
{
$shop_model = new ShopModel();
$res = $shop_model->qrcode($this->site_id);
return $this->response($res);
}
/**
* 是否显示店铺相关功能,用于审核小程序
*/
public function isShow()
{
$res = 1;// 0 隐藏1 显示
return $this->response($this->success($res));
}
/**
* 店铺状态
* @return false|string
*/
public function status()
{
return $this->response($this->success());
}
/**
* 店铺联系方式
* @return false|string
*/
public function shopContact()
{
$data = ( new ShopModel() )->getShopInfo([ [ 'site_id', '=', $this->site_id ] ], 'mobile');
return $this->response($data);
}
}

254
app/api/controller/Store.php Executable file
View File

@@ -0,0 +1,254 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\store\Store as StoreModel;
use extend\api\HttpClient;
use app\model\web\Config as ConfigModel;
use app\model\goods\Goods;
/**
* 门店
* @author Administrator
*
*/
class Store extends BaseApi
{
/**
* 列表信息
*/
public function page()
{
$latitude = $this->params['latitude'] ?? null; // 纬度
$longitude = $this->params['longitude'] ?? null; // 经度
$keyword = $this->params['keyword'] ?? ''; // 搜索关键词
$status = $this->params['status'] ?? 'all';//营业状态
$store_ids = $this->params['store_ids'] ?? '';//指定门店id
if($store_ids == 'undefined') $store_ids = 'all';
$store_model = new StoreModel();
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'is_frozen', '=', 0],
];
//营业状态
if(!in_array($status, [1,0,'all'])) $status = 1;
if($status != 'all'){
$condition[] = ['status', '=', $status];
}else{
$condition[] = ['status|close_show', '=', 1];
}
//指定门店
if(!empty($store_ids) && $store_ids != 'all'){
$condition[] = ['store_id', 'in', $store_ids];
}
if (!empty($keyword)) {
$condition[] = [ 'store_name', 'like', '%' . paramFilter($keyword) . '%' ];
}
$latlng = [
'lat' => $latitude,
'lng' => $longitude,
];
$field = '*';
$list_result = $store_model->getLocationStoreList($condition, $field, $latlng);
$list = $list_result[ 'data' ];
if (!empty($longitude) && !empty($latitude) && !empty($list)) {
foreach ($list as $k => $item) {
if ($item[ 'longitude' ] && $item[ 'latitude' ]) {
$distance = getDistance((float) $item[ 'longitude' ], (float) $item[ 'latitude' ], (float) $longitude, (float) $latitude);
$list[ $k ][ 'distance' ] = $distance / 1000;
} else {
$list[ $k ][ 'distance' ] = 0;
}
}
// 按距离就近排序
array_multisort(array_column($list, 'distance'), SORT_ASC, $list);
}
$default_store_id = 0;
if (!empty($list)) {
$default_store_id = $list[ 0 ][ 'store_id' ];
}
return $this->response($this->success([ 'list' => $list, 'store_id' => $default_store_id ]));
}
/**
* 获取离自己最近的一个门店
*/
public function nearestStore()
{
$this->initStoreData();
$latitude = $this->params['latitude'] ?? null; // 纬度
$longitude = $this->params['longitude'] ?? null; // 经度
$store_model = new StoreModel();
$condition = [
[ 'site_id', '=', $this->site_id ],
[ 'status', '=', 1 ],
[ 'is_frozen', '=', 0 ]
];
// if ($this->store_data[ 'config' ][ 'store_business' ] == 'shop') {
// // 平台运营模式,直接取默认门店
// if (!empty($this->store_data[ 'store_info' ])) {
// return $this->response($this->success($this->store_data[ 'store_info' ]));
// }
// }
if (in_array($this->store_data[ 'config' ][ 'store_business' ],['store','shop'])) {
// 连锁门店运营模式,查询距离自己最近的门店
$latlng = [
'lat' => $latitude,
'lng' => $longitude,
];
$field = '*';
$list = $store_model->getLocationStoreList($condition, $field, $latlng)[ 'data' ];
if (!empty($longitude) && !empty($latitude) && !empty($list)) {
foreach ($list as $k => $item) {
if ($item[ 'longitude' ] && $item[ 'latitude' ]) {
$distance = getDistance((float) $item[ 'longitude' ], (float) $item[ 'latitude' ], (float) $longitude, (float) $latitude);
$list[ $k ][ 'distance' ] = $distance / 1000;
} else {
$list[ $k ][ 'distance' ] = 0;
}
}
// 按距离就近排序
array_multisort(array_column($list, 'distance'), SORT_ASC, $list);
return $this->response($this->success($list[ 0 ]));
}
}
return $this->response($this->error());
}
/**
* 基础信息
* @return false|string
*/
public function info()
{
$store_id = $this->params['store_id'] ?? 0;
$latitude = $this->params['latitude'] ?? null; // 纬度
$longitude = $this->params['longitude'] ?? null; // 经度
if (empty($store_id)) {
return $this->response($this->error('', 'REQUEST_STORE_ID'));
}
$condition = [
[ 'store_id', '=', $store_id ],
[ 'site_id', '=', $this->site_id ],
];
$latitude = paramFilter($latitude);
$longitude = paramFilter($longitude);
$latlng = [
'lat' => $latitude,
'lng' => $longitude,
];
$store_model = new StoreModel();
$field = 'store_id,store_name,telphone,store_image,site_id,address,full_address,longitude,latitude,open_date,label_name,store_images,store_introduce,is_default,is_express,is_pickup,is_o2o,is_frozen,status,close_desc';
if (!empty($latlng[ 'lat' ]) && !empty($latlng[ 'lng' ])) {
$field .= ',FORMAT(st_distance ( point ( ' . $latlng[ 'lng' ] . ', ' . $latlng[ 'lat' ] . ' ), point ( longitude, latitude ) ) * 111195 / 1000, 2) as distance';
}
$res = $store_model->getStoreInfo($condition, $field);
if (!empty($res[ 'data' ])) {
if (!empty($res[ 'data' ][ 'store_images' ])) {
$res[ 'data' ][ 'store_images' ] = ( new Goods() )->getGoodsImage(explode(',', $res[ 'data' ][ 'store_images' ]), $this->site_id)[ 'data' ];
}
}
return $this->response($res);
}
/**
* 根据经纬度获取位置
* @return false|string
*/
public function getLocation()
{
$latitude = $this->params['latitude'] ?? null; // 纬度
$longitude = $this->params['longitude'] ?? null; // 经度
$qq_map = new \app\model\map\QqMap();
$res = $qq_map->locationToDetail([
'location' => $latitude . ',' . $longitude,
]);
if ($res[ 'status' ] == 0) {
$result = $res[ 'result' ];
return $this->response($this->success($result));
} else {
return $this->response($this->error('', $res[ 'message' ]));
}
}
/**
* 分页查询门店
* @return false|string
*/
public function getStorePage()
{
$latitude = $this->params['latitude'] ?? null; // 纬度
$longitude = $this->params['longitude'] ?? null; // 经度
$page = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$type = $this->params['type'] ?? '';
$store_ids = $this->params['store_ids'] ?? '';//指定门店id
$store_model = new StoreModel();
if($type == 'local'){
$store_condition = [
['site_id', '=', $this->site_id],
];
if (addon_is_exit('store', $this->site_id)) {
if(empty($store_ids)){
$store_condition[] = ['is_o2o', '=', 1];
$store_condition[] = ['status', '=', 1];
}
$store_condition[] = ['is_frozen', '=', 0];
} else {
$store_condition[] = ['is_default', '=', 1];
}
}else{
$store_condition = [
[ 'site_id', '=', $this->site_id ],
[ 'is_frozen', '=', 0 ],
];
if(empty($store_ids)){
$store_condition[] = ['is_pickup', '=', 1];
$store_condition[] = ['status', '=', 1];
}
}
//指定门店
if(!empty($store_ids) && $store_ids != 'all'){
$store_condition[] = ['store_id', 'in', $store_ids];
}
$latlng = [
'lat' => $latitude,
'lng' => $longitude,
];
$store_list = $store_model->getLocationStorePageList($store_condition, $page, $page_size, '*', $latlng);
return $this->response($store_list);
}
}

43
app/api/controller/Text.php Executable file
View File

@@ -0,0 +1,43 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\web\Help as HelpModel;
/**
*测试
* @author Administrator
*
*/
class Text extends BaseApi
{
/**
* 基础信息
*/
public function cronVerifyCodeExpire()
{
$order_id = $this->params['order_id'] ?? 0;
if (empty($order_id)) {
return $this->response($this->error('', 'REQUEST_ID'));
}
$res = event('CronVerifyCodeExpire', ['relate_id' => $order_id]);
dd($res);
}
}

34
app/api/controller/Transfer.php Executable file
View File

@@ -0,0 +1,34 @@
<?php
/**
* Transfer.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use addon\memberwithdraw\model\Withdraw as WithdrawModel;
use app\exception\ApiException;
use app\model\system\Site as SiteModel;
use app\model\shop\Shop as ShopModel;
use think\facade\Cache;
/**
* 店铺
* @author Administrator
*
*/
class Transfer extends BaseApi
{
public function __construct()
{
parent::__construct();
}
}

136
app/api/controller/Tripartite.php Executable file
View File

@@ -0,0 +1,136 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
*/
namespace app\api\controller;
use app\model\member\Login as LoginModel;
use app\model\message\Message;
use app\model\member\Register as RegisterModel;
use app\model\web\Config as WebConfig;
use think\facade\Cache;
/**
* 第三方自动注册绑定手机
* Class Tripartite
* @package app\api\controller
*/
class Tripartite extends BaseApi
{
/**
* 绑定手机号
*/
public function mobile()
{
$key = $this->params[ 'key' ];
$verify_data = Cache::get($key);
if (!empty($verify_data) && $verify_data[ 'mobile' ] == $this->params[ 'mobile' ] && $verify_data[ 'code' ] == $this->params[ 'code' ]) {
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
$login = new LoginModel();
$res = $login->mobileLogin($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
$res = $this->success(['token' => $token]);
}
} else {
$res = $register->mobileRegister($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ]);
$res = $this->success(['token' => $token, 'is_register' => 1]);
}
}
} else {
$res = $this->error('', '手机动态码不正确');
}
return $this->response($res);
}
/**
* 绑定手机验证码
* @throws Exception
*/
public function mobileCode()
{
// 校验验证码
$config_model = new WebConfig();
$info = $config_model->getCaptchaConfig();
if ($info[ 'data' ][ 'value' ][ 'shop_reception_login' ] == 1) {
$captcha = new Captcha();
$check_res = $captcha->checkCaptcha(false);
if ($check_res[ 'code' ] < 0) return $this->response($check_res);
}
$mobile = $this->params[ 'mobile' ];
if (empty($mobile)) return $this->response($this->error([], '手机号不可为空!'));
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);// 生成4位随机数左侧补0
$message_model = new Message();
$res = $message_model->sendMessage(['type' => 'code', 'mobile' => $mobile, 'site_id' => $this->site_id, 'support_type' => ['sms'], 'code' => $code, 'keywords' => 'MEMBER_BIND']);
if ($res[ 'code' ] >= 0) {
//将验证码存入缓存
$key = 'bind_mobile_code_' . md5(uniqid(null, true));
Cache::tag('bind_mobile_code_')->set($key, ['mobile' => $mobile, 'code' => $code], 600);
return $this->response($this->success(['key' => $key]));
} else {
return $this->response($res);
}
}
/**
* 手机号授权登录
*/
public function mobileAuth()
{
try{
$decrypt_data = event('PhoneNumber', $this->params, true);
if ($decrypt_data[ 'code' ] < 0) return $this->response($decrypt_data);
$this->params[ 'mobile' ] = $decrypt_data[ 'data' ];
$register = new RegisterModel();
$exist = $register->mobileExist($this->params[ 'mobile' ], $this->site_id);
if ($exist) {
$login = new LoginModel();
$res = $login->mobileLogin($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ][ 'member_id' ]);
$res = $this->success(['token' => $token, 'can_receive_registergift' => $res[ 'data' ][ 'can_receive_registergift' ]]);
}
} else {
$res = $register->mobileRegister($this->params);
if ($res[ 'code' ] >= 0) {
$token = $this->createToken($res[ 'data' ]);
$res = $this->success(['token' => $token, 'is_register' => 1]);
}
}
return $this->response($res);
}catch (\Exception $e){
return $this->response($this->error('',$e->getMessage().','.$e->getFile().','.$e->getLine()));
}
}
/**
* 获取手机号
* @return false|string
*/
public function getPhoneNumber()
{
$decrypt_data = event('PhoneNumber', $this->params, true);
if (empty($decrypt_data)) return $this->response(error('', '没有获取手机号的渠道'));
if ($decrypt_data[ 'code' ] < 0) return $this->response($decrypt_data);
return $this->response(success(0, '', ['mobile' => $decrypt_data[ 'data' ]]));
}
}

119
app/api/controller/Upload.php Executable file
View File

@@ -0,0 +1,119 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\upload\Upload as UploadModel;
/**
* 上传管理
* @author Administrator
*
*/
class Upload extends BaseApi
{
/**
* 头像上传
*/
public function headimg()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$upload_model = new UploadModel($this->site_id);
$param = [
'thumb_type' => '',
'name' => 'file',
'watermark' => 0,
'cloud' => 1
];
$result = $upload_model->setPath('headimg/' . date('Ymd') . '/')->image($param);
return $this->response($result);
}
/**
* 退款图片
*/
public function refundimg()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$upload_model = new UploadModel($this->site_id);
$param = [
'thumb_type' => '',
'name' => 'file',
'watermark' => 0,
'cloud' => 1
];
$result = $upload_model->setPath('refundimg/' . date('Ymd') . '/')->image($param);
return $this->response($result);
}
/**
* 评价上传
*/
public function evaluateimg()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0 ) return $this->response($token);
$upload_model = new UploadModel($this->site_id);
$param = [
'thumb_type' => '',
'name' => 'file',
'watermark' => 0,
'cloud' => 1
];
$result = $upload_model->setPath('evaluate_img/' . date('Ymd') . '/')->image($param);
return $this->response($result);
}
public function headimgBase64()
{
$sign = $this->checkSign();
if ( $this->checkToken()['code'] < 0 && $sign[ 'code' ] < 0) return $this->response($sign);
$upload_model = new UploadModel($this->site_id);
$file = input('images', '');
$file = base64_to_blob($file);
$result = $upload_model->setPath('headimg/' . date('Ymd') . '/')->binaryImage($file[ 'blob' ]);
return $this->response($result);
}
public function headimgPull()
{
$sign = $this->checkSign();
if ( $this->checkToken()['code'] < 0 && $sign[ 'code' ] < 0) return $this->response($sign);
$upload_model = new UploadModel($this->site_id);
$path = input('path', '');
$result = $upload_model->setPath('headimg/' . date('Ymd') . '/')->remotePull($path);
return $this->response($result);
}
/**
* 聊天图片上传
*/
public function chatimg()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$upload_model = new UploadModel(0);
$param = [
'thumb_type' => '',
'name' => 'file'
];
$result = $upload_model->setPath('chat_img/' . date('Ymd') . '/')->image($param);
return $this->response($result);
}
}

122
app/api/controller/Verify.php Executable file
View File

@@ -0,0 +1,122 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\verify\Verifier;
use app\model\verify\Verify as VerifyModel;
/**
* 核销管理
* @author Administrator
*
*/
class Verify extends BaseApi
{
/**
* 核销列表
*/
public function lists()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$verifier_model = new Verifier();
$condition = [
['member_id', '=', $this->member_id ],
['site_id', '=', $this->site_id ]
];
$res = $verifier_model->checkIsVerifier($condition);
if ($res['code'] != 0)
return $this->response($res);
$verifier_id = $res['data']['verifier_id'];
$verify_model = new VerifyModel();
$condition = [
['verifier_id', '=', $verifier_id ],
];
$verify_type = $this->params['verify_type'] ?? 'all';
if ($verify_type != 'all') {
$condition[] = ['verify_type', '=', $verify_type ];
}
$page_index = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$res = $verify_model->getVerifyPageList($condition, $page_index, $page_size, 'verify_time desc');
return $this->response($res);
}
/**
* 获取核销类型
*/
public function getVerifyType()
{
$verify_model = new VerifyModel();
$res = $verify_model->getVerifyType();
return $this->response($this->success($res));
}
/**
* 验证核销员身份
*/
public function checkIsVerifier()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$verifier_model = new Verifier();
$condition = [
['member_id', '=', $this->member_id ],
['site_id', '=', $this->site_id ]
];
$res = $verifier_model->checkIsVerifier($condition);
return $this->response($res);
}
/**
* 核销验证信息
*/
public function verifyInfo()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$verify_code = $this->params['verify_code'] ?? '';
$verify_model = new VerifyModel();
$res = $verify_model->checkMemberVerify($this->member_id, $verify_code);
if ($res['code'] != 0)
return $this->response($res);
return $this->response($this->success($res['data']['verify']));
}
/**
* 核销
* @return string
*/
public function verify()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$verify_code = $this->params['verify_code'] ?? '';
$verify_model = new VerifyModel();
$res = $verify_model->checkMemberVerify($this->member_id, $verify_code);
if ($res['code'] != 0)
return $this->response($res);
$verifier_info = $res['data']['verifier'];
$verifier_info[ 'verify_from' ] = 'mobile';
$res = $verify_model->verify($verifier_info, $verify_code);
return $this->response($res);
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* Index.php
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2015-2025 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
* @author : niuteam
* @date : 2022.8.8
* @version : v5.0.0.1
*/
namespace app\api\controller;
use app\model\goods\VirtualGoods as VirtualGoodsModel;
class Virtualgoods extends BaseApi
{
/**
* 我的虚拟商品
*/
public function lists()
{
$token = $this->checkToken();
if ($token[ 'code' ] < 0) return $this->response($token);
$virtual_goods_model = new VirtualGoodsModel();
$condition = [
['member_id', '=', $this->member_id ],
];
$is_verify = $this->params['is_verify'] ?? 'all';//是否已核销
if ($is_verify != 'all') {
$condition[] = ['is_verify', '=', $is_verify ];
}
$page_index = $this->params['page'] ?? 1;
$page_size = $this->params['page_size'] ?? PAGE_LIST_ROWS;
$res = $virtual_goods_model->getVirtualGoodsPageList($condition, $page_index, $page_size, 'id desc');
return $this->response($res);
}
}

53
app/api/lang/code.php Executable file
View File

@@ -0,0 +1,53 @@
<?php
return [
'SUCCESS' => 0,
'ERROR' => -1,
'SITE_NOT_EXIST' => -2,
'SITE_CLOSE' => -3,
'FAIL' => -10001,
'SAVE_SUCCESS' => 10002,
'SAVE_FAIL' => -10002,
'REQUEST_SUCCESS' => 10003,
'REQUEST_FAIL' => -10003,
'DELETE_SUCCESS' => 10004,
'DELETE_FAIL' => -10004,
'UNKNOW_ERROR' => -10005,
'PARAMETER_ERROR' => -10006,
'REQUEST_SITE_ID' => -10007,
'REQUEST_APP_MODULE' => -10008,
'TOKEN_NOT_EXIST' => -1,
'TOKEN_ERROR' => -10009,
'TOKEN_EXPIRE' => -10010,
'CAPTCHA_FAILURE' => -1,
'CAPTCHA_ERROR' => -1,
'REQUEST_COUPON_TYPE_ID' => -1,
'REQUEST_CAPTCHA_ID' => -1,
'REQUEST_CAPTCHA_CODE' => -1,
'REQUEST_SKU_ID' => -1,
'REQUEST_NUM' => -1,
'REQUEST_CART_ID' => -1,
'REQUEST_CATEGORY_ID' => -1,
'REQUEST_ID' => -1,
'REQUEST_ORDER_ID' => -1,
'REQUEST_GOODS_EVALUATE' => -1,
'REQUEST_ORDER_STATUS' => -1,
'REQUEST_DIY_ID_NAME' => -1,
'REQUEST_TOPIC_ID' => -1,
'REQUEST_SECKILL_ID' => -1,
'REQUEST_KEYWORD' => -1,
'REQUEST_GOODS_ID' => -1,
'REQUEST_PINTUAN_ID' => -1,
'REQUEST_EMAIL' => -1,
'REQUEST_MOBILE' => -1,
'REQUEST_GROUPBUY_ID' => -1,
'REQUEST_RECHARGE_ID' => -1,
'REQUEST_BL_ID' => -1,
'REQUEST_NAME' => -1,
'REQUEST_STORE_ID' => -1,
'REQUEST_REAL_NAME' => -1,
'REQUEST_WITHDRAW_TYPE' => -1,
'REQUEST_BRANCH_BANK_NAME' => -1,
'REQUEST_BRANCH_BANK_ACCOUNT' => -1,
'STORE_CLOSE' => -3
];

17
app/api/lang/en-us.php Executable file
View File

@@ -0,0 +1,17 @@
<?php
return [
'SUCCESS' => 'success',
'ERROR' => 'error',
'FAIL' => 'fail',
'SAVE_SUCCESS' => 'save success',
'SAVE_FAIL' => 'save fail',
'REQUEST_SUCCESS' => 'request success',
'REQUEST_FAIL' => 'request error',
'DELETE_SUCCESS' => 'delete success',
'DELETE_FAIL' => 'delete fail',
'UNKNOW_ERROR' => 'unknow error',
'PARAMETER_ERROR' => 'parameter error',
'REQUEST_SITE_ID' => 'request site id',
'REQUEST_APP_MODULE' => 'request app module'
];

57
app/api/lang/zh-cn.php Executable file
View File

@@ -0,0 +1,57 @@
<?php
return [
'SUCCESS' => '操作成功',
'ERROR' => '操作失败',
'SITE_NOT_EXIST' => '该店铺不存在',
'SITE_CLOSE' => '该店铺已打烊',
'SAVE_SUCCESS' => '保存成功',
'SAVE_FAIL' => '保存失败',
'REQUEST_SUCCESS' => '请求成功',
'REQUEST_FAIL' => '请求失败',
'DELETE_SUCCESS' => '删除成功',
'DELETE_FAIL' => '删除失败',
'UNKNOW_ERROR' => '未知错误',
'PARAMETER_ERROR' => '参数错误',
'REQUEST_SITE_ID' => '缺少必须参数站点id',
'REQUEST_APP_MODULE' => '缺少必须参数应用模块',
'TOKEN_NOT_EXIST' => '您尚未登录,请先进行登录',
'TOKEN_ERROR' => 'token错误',
'TOKEN_EXPIRE' => 'token已过期',
'CAPTCHA_FAILURE' => '验证码已失效',
'CAPTCHA_ERROR' => '验证码不正确',
'REQUEST_COUPON_TYPE_ID' => '缺少参数coupon_type_id',
'REQUEST_CAPTCHA_ID' => '缺少参数captcha_id',
'REQUEST_CAPTCHA_CODE' => '缺少参数captcha_code',
'REQUEST_SKU_ID' => '缺少参数sku_id',
'REQUEST_NUM' => '缺少参数num',
'REQUEST_CART_ID' => '缺少参数cart_id',
'REQUEST_CATEGORY_ID' => '缺少参数category_id',
'REQUEST_ID' => '缺少参数id',
'REQUEST_ORDER_ID' => '缺少参数order_id',
'REQUEST_GOODS_EVALUATE' => '缺少参数goods_evaluate',
'REQUEST_ORDER_STATUS' => '缺少参数order_status',
'REQUEST_DIY_ID_NAME' => '缺少参数id/name',
'REQUEST_TOPIC_ID' => '缺少参数topic_id',
'REQUEST_SECKILL_ID' => '缺少参数seckill_id',
'REQUEST_KEYWORD' => '缺少参数keyword',
'REQUEST_GOODS_ID' => '缺少参数goods_id',
'REQUEST_PINTUAN_ID' => '缺少参数pintuan_id',
'REQUEST_EMAIL' => '缺少参数email',
'REQUEST_MOBILE' => '缺少参数mobile',
'REQUEST_GROUPBUY_ID' => '缺少参数groupbuy_id',
'REQUEST_RECHARGE_ID' => '缺少参数recharge_id',
'REQUEST_BL_ID' => '缺少参数bl_id',
'REQUEST_NAME' => '缺少参数name',
'REQUEST_STORE_ID' => '缺少参数store_id',
'REQUEST_REAL_NAME' => '缺少参数real_name',
'REQUEST_WITHDRAW_TYPE' => '缺少参数withdraw_type',
'REQUEST_BRANCH_BANK_NAME' => '缺少参数branch_bank_name',
'REQUEST_BRANCH_BANK_ACCOUNT' => '缺少参数bank_account',
'REQUEST_NOTE_ID' => '缺少参数note_id',
'REQUEST_PRESALE_ID' => '缺少参数presale_id',
'REQUEST_JIELONG_ID' => '缺少参数jielong_id',
'STORE_CLOSE' => '该门店已停业'
];

28
app/command/Schedule.php Executable file
View File

@@ -0,0 +1,28 @@
<?php
namespace app\command;
use app\dict\system\ScheduleDict;
use app\model\system\Cron;
use think\facade\Log;
use yunwuxin\cron\Task;
class Schedule extends Task
{
public function configure()
{
$this->everyMinute(); //设置任务的周期,每分钟执行一次
}
/**
* 执行任务
* @return void
*/
protected function execute()
{
//...具体的任务执行
$cron_model = new Cron();
$cron_model->execute(ScheduleDict::cli);
}
}

2121
app/common.php Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,18 @@
<?php
namespace app\component\controller;
/**
* 文章·组件
*/
class Article extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("article/design.html");
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace app\component\controller;
use app\Controller;
use liliuwei\think\Jump;
class BaseDiyView extends Controller
{
use Jump;
// 当前组件路径
private $path;
// 资源路径
private $resource_path;
// 相对路径
private $relative_path;
public function __construct()
{
parent::__construct();
$class = get_class($this);
$routes = explode('\\', $class);
if ($routes[ 0 ] == 'app') {
//系统·组件app/component/controller/Text
$this->path = './' . $routes[ 0 ] . '/';
$this->resource_path = __ROOT__ . '/' . $routes[ 0 ] . '/' . $routes[ 1 ] . '/view';
$this->relative_path = $routes[ 0 ] . '/' . $routes[ 1 ] . '/view';
} elseif ($routes[ 0 ] == 'addon') {
//插件·组件addon/seckill/component/controller/seckill
$this->path = './' . $routes[ 0 ] . '/' . $routes[ 1 ] . '/';
$this->resource_path = __ROOT__ . '/' . $routes[ 0 ] . '/' . $routes[ 1 ] . '/' . $routes[ 2 ] . '/view';
$this->relative_path = $routes[ 0 ] . '/' . $routes[ 1 ] . '/' . $routes[ 2 ] . '/view';
}
}
/**
* 后台编辑界面
*/
public function design()
{
}
/**
* 加载模板输出
*
* @access protected
* @param string $template 模板文件名
* @param array $vars 模板输出变量
* @param array $replace 模板替换
*/
protected function fetch($template = '', $vars = [], $replace = [])
{
$comp_folder_name = explode('/', $template)[ 0 ];// 获取组件文件夹名称
$template = $this->path . 'component/view/' . $template;
$this->resource_path .= '/' . $comp_folder_name; // 拼接组件文件夹名称
$this->relative_path .= '/' . $comp_folder_name; // 拼接组件文件夹名称
parent::assign('resource_path', $this->resource_path);
parent::assign('relative_path', $this->relative_path);
return parent::fetch($template, $vars, $replace);
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 商品分类·组件
*/
class FloatBtn extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("float_btn/design.html");
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace app\component\controller;
/**
* 关注公众号·组件
*/
class FollowOfficialAccount extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("follow_official_account/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 商品品牌·组件
*/
class GoodsBrand extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("goods_brand/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 商品分类·组件
*/
class GoodsCategory extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("goods_category/design.html");
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace app\component\controller;
use app\model\goods\GoodsCategory;
/**
* 商品列表·组件
*/
class GoodsList extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
$site_id = request()->siteid();
$goods_category_model = new GoodsCategory();
$category_condition = [
[ 'site_id', '=', $site_id ]
];
$category_list = $goods_category_model->getCategoryTree($category_condition)[ 'data' ];
$this->assign("category_list", $category_list);
return $this->fetch("goods_list/design.html");
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace app\component\controller;
use app\model\goods\GoodsCategory;
/**
* 商品推荐·组件
*/
class GoodsRecommend extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
$site_id = request()->siteid();
$goods_category_model = new GoodsCategory();
$category_condition = [
[ 'site_id', '=', $site_id ]
];
$category_list = $goods_category_model->getCategoryTree($category_condition)[ 'data' ];
$this->assign("category_list", $category_list);
return $this->fetch("goods_recommend/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 图文导航·组件
*/
class GraphicNav extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("graphic_nav/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 辅助空白·组件
*/
class HorzBlank extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("horz_blank/design.html");
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace app\component\controller;
/**
* 辅助线·组件
*
*/
class HorzLine extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("horz_line/design.html");
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace app\component\controller;
/**
* 热区·组件
*/
class HotArea extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("hot_area/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 图片广告·组件
*/
class ImageAds extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("image_ads/design.html");
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace app\component\controller;
use app\model\goods\GoodsCategory;
/**
* 商品列表·组件
*/
class ManyGoodsList extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
$site_id = request()->siteid();
$goods_category_model = new GoodsCategory();
$category_condition = [
[ 'site_id', '=', $site_id ]
];
$category_list = $goods_category_model->getCategoryTree($category_condition)[ 'data' ];
$this->assign("category_list", $category_list);
return $this->fetch("many_goods_list/design.html");
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace app\component\controller;
use app\model\web\DiyView as DiyViewModel;
/**
* 会员中心—>会员信息·组件
*/
class MemberInfo extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
$site_id = request()->siteid();
$diy_view = new DiyViewModel();
$system_color = $diy_view->getStyleConfig($site_id)[ 'data' ][ 'value' ];
$this->assign('system_color', $system_color);
return $this->fetch("member_info/design.html");
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace app\component\controller;
/**
* 会员中心—>我的订单·组件
*/
class MemberMyOrder extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("member_my_order/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 公告·组件
*/
class Notice extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("notice/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 快捷导航·组件
*/
class QuickNav extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("quick_nav/design.html");
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace app\component\controller;
/**
* 富文本·组件
*
*/
class RichText extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
$this->assign("unique_random", unique_random());
return $this->fetch("rich_text/design.html");
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace app\component\controller;
/**
* 魔方·组件
*/
class RubikCube extends BaseDiyView
{
/**
* 前台输出
*/
public function parseHtml($attr)
{
if (!empty($attr['diyHtml'])) {
$attr['diyHtml'] = str_replace("&quot;", '"', $attr['diyHtml']);
}
$this->assign("attr", $attr);
return $this->fetch('rubik_cube/rubik_cube.html');
}
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("rubik_cube/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 商品搜索·组件
*/
class Search extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("search/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 文本·组件
*/
class Text extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("text/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 店铺搜索·组件
*/
class TopCategory extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("top_category/design.html");
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace app\component\controller;
/**
* 视频·组件
*/
class Video extends BaseDiyView
{
/**
* 后台编辑界面
*/
public function design()
{
return $this->fetch("video/design.html");
}
}

View File

@@ -0,0 +1,16 @@
@CHARSET "UTF-8";
/* 文章组件 */
.article-wrap .list-wrap.style-1{}
.article-wrap .list-wrap.style-1 .item{display: flex;padding: 10px;margin-bottom: 10px;}
.article-wrap .list-wrap.style-1 .item:last-child{margin-bottom: 0;}
.article-wrap .list-wrap.style-1 .item .img-wrap{text-align: center;margin-right: 10px;width: 80px;}
.article-wrap .list-wrap.style-1 .item .img-wrap img{max-width: 100%;max-height: 100%;}
.article-wrap .list-wrap.style-1 .item .img-wrap span{display: block;background-color:#F6F6F6;height: 50px;line-height: 50px;padding: 20px;}
.article-wrap .list-wrap.style-1 .item .info-wrap {flex:1;display:flex;flex-direction:column;justify-content:space-between;}
.article-wrap .list-wrap.style-1 .item .info-wrap .title {font-weight:bold;margin-bottom:5px;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:15px;line-height:1.5;}
.article-wrap .list-wrap.style-1 .item .info-wrap .abstract {overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;font-size:12px;}
.article-wrap .list-wrap.style-1 .item .info-wrap .read-wrap {display:flex;color:#999ca7;justify-content:flex-start;align-items:center;margin-top:5px;line-height:1;}
.article-wrap .list-wrap.style-1 .item .info-wrap .read-wrap text {font-size:12px;}
.article-wrap .list-wrap.style-1 .item .info-wrap .read-wrap .iconfont {font-size:18px;vertical-align:bottom;margin-right:5px;}
.article-wrap .list-wrap.style-1 .item .info-wrap .read-wrap .category-icon {width:4px;height:4px;border-radius:50%;margin-right:5px;}
.article-wrap .list-wrap.style-1 .item .info-wrap .read-wrap .date {margin-left:10px;}

View File

@@ -0,0 +1,105 @@
<nc-component :data="data[index]" class="article-wrap">
<!-- 预览 -->
<template slot="preview">
<div :class="['list-wrap',nc.style]" :style="{ backgroundColor: nc.componentBgColor,
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
}">
<template v-if="nc.previewList && Object.keys(nc.previewList).length">
<div class="item" v-for="(item, previewIndex) in nc.previewList" :key="previewIndex" :style="{
borderTopLeftRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
backgroundColor: nc.elementBgColor,
boxShadow: nc.ornament.type == 'shadow' ? ('0 0 5px ' + nc.ornament.color) : '',
border: nc.ornament.type == 'stroke' ? '1px solid ' + nc.ornament.color : ''
}">
<div class="img-wrap">
<img :src="item.cover_img ? changeImgUrl(item.cover_img) : changeImgUrl('public/static/img/default_img/square.png')" />
</div>
<div class="info-wrap">
<div class="title">{{ item.article_title }}</div>
<div class="read-wrap">
<span class="category-icon bg-color" v-if="item.category_name"></span>
<span v-if="item.category_name">{{ item.category_name }}</span>
<span class="date">{{ nc.tempData.methods ? nc.tempData.methods.timeFormat(item.create_time, 'YYYY-MM-DD') : '' }}</span>
</div>
</div>
</div>
</template>
</div>
</template>
<!-- 内容编辑 -->
<template slot="edit-content">
<template v-if="nc.lazyLoad">
<article-sources></article-sources>
<div class="template-edit-title">
<h3>文章数据</h3>
<div class="layui-form-item" v-if="nc.tempData.goodsSources">
<label class="layui-form-label sm">数据来源</label>
<div class="layui-input-block">
<div class="source-selected">
<div class="source">{{ nc.tempData.goodsSources[nc.sources].text }}</div>
<div v-for="(item,sourcesKey) in nc.tempData.goodsSources" :key="sourcesKey" class="source-item" :title="item.text" @click="nc.sources=sourcesKey" :class="{ 'text-color border-color' : (nc.sources == sourcesKey) }">
<i class='iconfont' :class='item.icon'></i>
</div>
</div>
</div>
</div>
<div class="layui-form-item" v-if="nc.sources == 'diy'">
<label class="layui-form-label sm">手动选择</label>
<div class="layui-input-block">
<div class="selected-style" @click="nc.tempData.methods.addArticle()">
<span v-if="nc.articleIds.length == 0">请选择</span>
<span v-if="nc.articleIds.length > 0" class="text-color">已选{{ nc.articleIds.length }}个</span>
<i class="iconfont iconyoujiantou"></i>
</div>
</div>
</div>
<slide :data="{ field : 'count', label: '文章数量', min:1, max: 30}" v-if="nc.sources != 'diy'"></slide>
</div>
</template>
</template>
<!-- 样式编辑 -->
<template slot="edit-style">
<template v-if="nc.lazyLoad">
<div class="template-edit-title">
<h3>文章样式</h3>
<div class="layui-form-item tag-wrap">
<label class="layui-form-label sm">边框</label>
<div class="layui-input-block">
<div v-for="(item,ornamentIndex) in nc.tempData.ornamentList" :key="ornamentIndex" @click="nc.ornament.type=item.type" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.ornament.type==item.type) }">
<i class="layui-anim layui-icon">{{ nc.ornament.type == item.type ? "&#xe643;" : "&#xe63f;" }}</i>
<div>{{item.text}}</div>
</div>
</div>
</div>
<color v-if="nc.ornament.type != 'default'" :data="{ field : 'color', 'label' : '边框颜色', parent : 'ornament', defaultColor : '#EDEDED' }"></color>
<color :data="{ field : 'elementBgColor', 'label' : '文章背景' }"></color>
<slide v-show="nc.elementAngle == 'round'" :data="{ field : 'topElementAroundRadius', label : '上圆角', max : 50 }"></slide>
<slide v-show="nc.elementAngle == 'round'" :data="{ field : 'bottomElementAroundRadius', label : '下圆角', max : 50 }"></slide>
</div>
</template>
</template>
<!-- 资源 -->
<template slot="resource">
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>

View File

@@ -0,0 +1,80 @@
var articleHtml = '<div></div>';
Vue.component("article-sources", {
template: articleHtml,
data: function () {
return {
data: this.$parent.data,
goodsSources: {
initial: {
text: "默认",
icon: "iconmofang"
},
diy: {
text: "手动选择",
icon: "iconshoudongxuanze"
},
},
ornamentList: [
{
type: 'default',
text: '默认',
},
{
type: 'shadow',
text: '投影',
},
{
type: 'stroke',
text: '描边',
},
],
};
},
created: function () {
this.$parent.data.ignore = [];//加载忽略内容 -- 其他设置中的属性设置
this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载
if(Object.keys(this.$parent.data.previewList).length == 0) {
for (var i = 1; i < 3; i++) {
this.$parent.data.previewList["brand_id_" + ns.gen_non_duplicate(i)] = {
article_title: "文章标题",
article_abstract: '这里是文章内容',
read_num: (i + 1) * 12,
category_name: '文章分类',
create_time: 1662202804
};
}
}
// 组件所需的临时数据
this.$parent.data.tempData = {
goodsSources: this.goodsSources,
ornamentList: this.ornamentList,
methods: {
addArticle: this.addArticle,
timeFormat: this.timeFormat
},
};
},
methods: {
verify: function (index) {
var res = {code: true, message: ""};
if (vue.data[index].sources === 'diy' && vue.data[index].articleIds.length === 0) {
res.code = false;
res.message = "请选择文章";
}
return res;
},
addArticle: function () {
var self = this;
articleSelect(function (res) {
self.$parent.data.articleIds = res.articleIds;
self.$parent.data.previewList = res.list;
}, {select_id: self.$parent.data.articleIds.toString()});
},
timeFormat(time, format){
return ns.time_to_date(time, format)
}
}
});

View File

@@ -0,0 +1,31 @@
.float-btn .comp-title {display: none;}
.float-btn .float-btn-box {display: flex;flex-direction: column;align-items: flex-end;justify-content: center;text-align: center;border: 1px dashed;}
.float-btn .float-btn-item:nth-last-child(1) {margin-bottom: 0;}
.float-btn .float-btn-item {display: flex;justify-content: center;align-items: center;flex-direction: column;margin-bottom: 10px;overflow: hidden;}
.float-btn .float-btn-item .img-box, .float-btn .float-btn-item .icon-box {overflow: hidden;display: flex;justify-content: center;align-items: center;}
.float-btn .float-btn-item .img-box img {max-width: 100%;max-height: 100%;}
.float-btn .float-btn-item span {margin-top: 5px;color: #333;font-size: 12px;}
.float-btn .float-btn-list li, .float-btn .float-btn-list .add-item {display: flex;align-items: end;border: 1px dashed #e5e5e5;padding: 10px;}
.float-btn .float-btn-list li + li {margin: 10px 0;}
.float-btn .float-btn-list .right-wrap {display: flex;flex-direction: column;flex: 1;width: 0;}
.float-btn-list .right-wrap .action-box {display: flex;margin-bottom: 4px;}
.float-btn-list .action {margin-right: 10px;width: 42px;height: 28px;line-height: 28px;text-align: center;border: 1px solid #EEEEEE;cursor: pointer;}
.float-btn-list .action .iconfont {font-size: 20px;}
.float-btn-list .action:hover {border-color: var(--base-color);color: var(--base-color);}
.float-btn .right-wrap .layui-form-item {margin-bottom: 0;}
.float-btn .right-wrap .layui-form-label {text-align: left;}
.float-btn .float-btn-list .add-item {justify-content: center;align-items: center;margin: 10px 0;cursor: pointer;}
.float-btn .float-btn-list .add-item i {font-weight: bold;display: inline-block;height: 24px;line-height: 24px;font-size: 18px;margin-right: 10px;}
.float-btn .float-btn-list .add-item span {display: inline-block;height: 24px;line-height: 24px;}
.float-btn .float-btn-list li {position: relative;}
.float-btn .float-btn-list li:hover .del {display: block;}
.float-btn {position: absolute;}
.float-btn .preview-draggable {padding: 0;}
.float-btn.left {background: rgba(255, 255, 255, 0.45);margin-left: 10px;top: 130px;}
.float-btn.left .edit-attribute {right: -980px;top: -100px;}
.float-btn.right_bottom {margin-left: 10px;bottom: 130px;left: 642px;}
.float-btn-list {margin-left: 20px;}
.float-btn-list .hint {margin: 10px 0 10px 0;color: #909399;font-size: 12px;}
.float-btn .tab-wrap {display: none !important;}
.float-btn .icon-radio .icon-wrap i {color: #303133;}
.float-btn .preview-draggable .del {right: -20px;}

View File

@@ -0,0 +1,48 @@
<nc-component :data="data[index]" class="float-btn" data-disabled="1">
<!-- 预览 -->
<template slot="preview">
<template v-if="nc.lazyLoad">
<div class="float-btn-box border-color" data-disabled="1">
<div v-for="(item,previewIndex) in nc.list" :key="previewIndex" :index="previewIndex" class="float-btn-item" data-disabled="1">
<div class="img-box" data-disabled="1" v-if="!item.iconType || item.iconType == 'img'" :style="{ width : nc.imageSize + 'px',height : nc.imageSize + 'px' }">
<img :src="changeImgUrl(item.imageUrl)" data-disabled="1">
</div>
<div class="icon-box" data-disabled="1" v-if="item.iconType && item.iconType == 'icon'" :style="{ width : nc.imageSize + 'px',height : nc.imageSize + 'px',fontSize : nc.imageSize + 'px' }">
<iconfont :icon="item.icon" v-if="item.icon" :value="item.style ? item.style : ''"></iconfont>
</div>
</div>
</div>
</template>
</template>
<!-- 内容编辑 -->
<template slot="edit-content">
<template v-if="nc.lazyLoad">
<div class="template-edit-title">
<h3>按钮位置</h3>
<btn-position></btn-position>
<slide :data="{ field : 'btnBottom', label : '上下偏移' }"></slide>
</div>
<div class="template-edit-title">
<h3>图片设置</h3>
<slide :data="{ field : 'imageSize', label : '图片大小', min: 40, max : 100 }"></slide>
<float-btn-list></float-btn-list>
</div>
</template>
</template>
<!-- 样式编辑 -->
<template slot="edit-style"></template>
<!-- 资源 -->
<template slot="resource">
<js>
var floatBtnResourcePath = "{$resource_path}"; // http路径
var floatBtnRelativePath = "{$relative_path}"; // 相对路径
</js>
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>

View File

@@ -0,0 +1,309 @@
var floatBtnListHtml = '<div class="float-btn-list">';
floatBtnListHtml += '<p class="hint" style="font-size: 12px; margin: 5px 0 8px;">建议上传正方形图片</p>';
floatBtnListHtml += '<ul>';
floatBtnListHtml += '<li v-for="(item,index) in list" :key="item.id">';
floatBtnListHtml += '<img-icon-upload :data="{data : item}"></img-icon-upload>';
floatBtnListHtml += '<div class="right-wrap">';
floatBtnListHtml += '<div class="action-box" v-show="item.iconType == \'icon\'">';
floatBtnListHtml += '<div class="action" @click="iconStyle($event, index)"><i class="iconfont iconpifu"></i></div>';
floatBtnListHtml += '<div class="action" :id="\'float-btn-color-\' + index"><i class="iconfont iconyanse"></i></div>';
floatBtnListHtml += '</div>';
floatBtnListHtml += '<nc-link :data="{field: $parent.data.list[index].link}"></nc-link>';
floatBtnListHtml += '</div>';
floatBtnListHtml += '<i class="del" @click="del(index)" data-disabled="1">x</i>';
floatBtnListHtml += '<div class="error-msg"></div>';
floatBtnListHtml += '</li>';
floatBtnListHtml += '</ul>';
floatBtnListHtml += '<div class="add-item text-color" v-if="showAddItem" @click="add">';
floatBtnListHtml += '<i>+</i>';
floatBtnListHtml += '<span>添加一个浮动按钮</span>';
floatBtnListHtml += '</div>';
floatBtnListHtml += '</div>';
Vue.component("float-btn-list",{
data: function () {
return {
list: this.$parent.data.list,
maxTip : 3,//最大上传数量提示
showAddItem : true,
screenWidth:0,
colorPicker:{}
};
},
created : function(){
if(!this.$parent.data.verify) this.$parent.data.verify = [];
this.$parent.data.verify.push(this.verify);//加载验证方法
this.$parent.data.ignore = ['textColor','pageBgColor','componentBgColor','elementBgColor','marginTop','marginBottom','marginBoth','componentAngle','elementAngle'];//加载忽略内容 -- 其他设置中的属性设置
this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载
getElementPosition(this.$parent);
window.onresize = () => {
return (() => {
window.screenWidth = document.body.clientWidth;
this.screenWidth = window.screenWidth
})()
};
this.changeShowAddItem();//获取默认值
this.list.forEach(function (item) {
if (!item.id) item.id = ns.gen_non_duplicate(10)
})
},
watch : {
list : function(){
this.changeShowAddItem();
getElementPosition(this.$parent)
},
screenWidth(val){
// 为了避免频繁触发resize函数导致页面卡顿使用定时器
getElementPosition(this.$parent);
},
"$parent.data.btnBottom": function () {
getElementPosition(this.$parent);
}
},
mounted(){
this.fetchAllMenuIconColor();
},
methods: {
verify :function () {
var res = { code: true, message: "" };
if(this.list.length >0){
for(var i=0;i < this.list.length;i++){
if(this.$parent.data.list[i].imageUrl == "" && this.$parent.data.list[i].icon == ""){
res.code = false;
res.message = "请添加图片";
break;
}
}
}else{
res.code = false;
res.message = "请添加一个浮动按钮";
}
return res;
},
//改变添加浮动按钮
changeShowAddItem(){
if(this.list.length >= this.maxTip) this.showAddItem = false;
else this.showAddItem = true;
},
/**
* 选择图标风格
* @param event
* @param index
*/
iconStyle(event, index){
var self = this;
selectIconStyle({
elem: event.currentTarget,
icon: self.list[index].icon,
callback: function (data) {
if (data) {
self.list[index].style = data;
} else {
iconStyleSet({
style: JSON.stringify(self.list[index].style),
query: {
icon: self.list[index].icon
}
}, function(style){
self.list[index].style = style;
})
}
}
})
},
/**
* 渲染颜色组件
* @param id
* @param color
* @param callback
*/
colorRender(id, color, callback){
var self = this;
if (this.colorPicker[id]) return;
setTimeout(function () {
self.colorPicker[id] = Colorpicker.create({
el: id,
color: color,
change: function (elem, hex) {
callback(elem, hex)
}
});
})
},
/**
* 渲染全部菜单颜色选择器
*/
fetchAllMenuIconColor(){
var self = this;
this.list.forEach(function (item, index) {
self.colorRender('float-btn-color-' + index, '', function (elem, color) {
index = $(elem).parents('li').index();
if (self.list[index].style.iconBgColor.length || self.list[index].style.iconBgImg) {
self.list[index].style.iconBgColor = [color];
} else {
self.list[index].style.iconColor = [color];
}
self.$forceUpdate();
})
})
},
add(){
var self = this;
this.list.push({ imageUrl : '', title : '', link : {name: ''}, iconType: 'img', icon: '', style: {fontSize: 60, iconBgColor: [], iconBgColorDeg: 0,iconBgImg: '',bgRadius: 0,iconColor: ['#000'],iconColorDeg: 0}})
this.colorRender('float-btn-color-' + (this.list.length - 1), '', function (elem, color) {
var index = $(elem).parents('li').index();
if (self.list[index].style.iconBgColor.length || self.list[index].style.iconBgImg) {
self.list[index].style.iconBgColor = [color];
} else {
self.list[index].style.iconColor = [color];
}
self.$forceUpdate();
})
},
del(index){
this.list.splice(index, 1);
delete this.colorPicker['float-btn-color-' + index];
}
},
template: floatBtnListHtml
});
/**
* 按钮位置
*/
var btnPosition = '<div class="layui-form-item icon-radio">';
btnPosition += '<label class="layui-form-label sm">{{data.label}}</label>';
btnPosition += '<div class="layui-input-block">';
btnPosition += '<template v-for="(item,index) in list">';
btnPosition += '<span :class="[parent[data.field] == item.value ? \'\' : \'layui-hide\']">{{item.label}}</span>';
btnPosition += '</template>';
btnPosition += '<ul class="icon-wrap">';
btnPosition += '<template v-for="(item,index) in list">';
btnPosition += '<li @click="changePosition(item.value)" :class="{\'border-color\':parent[data.field] == item.value}">';
btnPosition += '<i class="iconfont" :class="[item.icon_img,parent[data.field] == item.value ? \'text-color\' : \'\']"></i>';
btnPosition += '</li>';
btnPosition += '</template>';
btnPosition += '</ul>';
btnPosition += '</div>';
btnPosition += '</div>';
Vue.component("btn-position", {
props: {
data: {
type: Object,
default: function () {
return {
field: "bottomPosition",
label: "按钮位置"
};
}
}
},
data: function () {
return {
list: [
{
label: "左上",
value: "1",
icon_img: "iconzuoshangjiao",
},
{
label: "右上",
value: "2",
icon_img: "iconyoushangjiao",
},
{
label: "左下",
value: "3",
icon_img: "iconzuoxiajiao",
},
{
label: "右下",
value: "4",
icon_img: "iconyouxiajiao",
},
],
parent: this.$parent.data,
imageSize: this.$parent.data.imageSize,
};
},
created: function () {
$('.float-btn').parent('.draggable-element').css({"border": "none"});// 将边框进行隐藏掉
},
watch: {
"$parent.data.imageSize": function () {
getElementPosition(this.$parent);
}
},
methods: {
changePosition:function(val){
this.parent.bottomPosition = val;
getElementPosition(this.$parent)
}
},
template: btnPosition
});
function getElementPosition(params) {
var type = parseInt(params.data.bottomPosition), //布局类型1为第一种2为第二种依次类推
bottomNumber = parseInt(params.data.btnBottom); //上下偏移的变量
/**
* #diyView .diy-view-wrap .preview-block =》 显示框【定位的参照对象是body】#diyView =》 外边框【定位的参照对象是body】
* 1、弹窗按钮是根据“外边框”进行定位的,但弹窗按钮是需要在“显示框”中展示
* 2、弹窗按钮与显示框的上下间距定义为50px,左右为30px这个是常量
* 3、计算弹窗按钮的四个位置都是根据 topleft进行计算的
* */
var box = document.querySelector("#diyView .diy-view-wrap .preview-block").getBoundingClientRect();
var box1 = document.querySelector("#diyView").getBoundingClientRect();
var topVal = 0; //弹窗按钮的top
var leftVal = 0; //弹窗按钮的left
var leftOffSet = 30; //弹窗按钮左右的偏移量
if (type == 1) {
// topVal = 显示框的top - 外边框的top + 距离显示框下边距的50px + 偏移量
// leftVal = 显示框的left - 外边框的left + 距离显示框右边距的30px
topVal = 100 + bottomNumber + "px";
leftVal = box.left - box1.left + leftOffSet + "px";
} else if (type == 2) {
// topVal = 显示框的top - 外边框的top + 距离显示框下边距的50px + 偏移量
// leftVal = 显示框的left - 外边框的left + 显示框的width82 - 弹窗按钮的width - 距离显示框右边距的30px
topVal = 100 + bottomNumber + "px";
leftVal = box.left - box1.left + box.width - params.data.imageSize - 2 - leftOffSet + "px";
} else if (type == 3) {
// topVal = 显示框的top - 外边框的上边距(20) - 防止贴边(20) - 弹出按钮高度 - 弹出按钮的下外边距 - 偏移量
// leftVal = 显示框的left - 外边框的left + 距离显示框左边距的30px
// topVal = box.top - box1.top + box.height - 82 - topOff - bottomNumber + "px";
topVal = $("#diyView .preview-wrap .div-wrap").height() - 20 - 20 - (params.data.list.length * params.data.imageSize) - ((params.data.list.length - 1) * 10) - bottomNumber + 'px';
leftVal = box.left - box1.left + leftOffSet + "px";
} else if (type == 4) {
// topVal = 显示框的top - 外边框的上边距(20) - 防止贴边(20) - 弹出按钮高度 - 弹出按钮的下外边距 - 偏移量
// leftVal = 显示框的left - 外边框的left + 显示框的width - 弹窗按钮的width - 边框width - 距离显示框右边距的30px
topVal = $("#diyView .preview-wrap .div-wrap").height() - 20 - 20 - (params.data.list.length * params.data.imageSize) - ((params.data.list.length - 1) * 10) - bottomNumber + 'px';
leftVal = box.left - box1.left + box.width - params.data.imageSize - 2 - leftOffSet + "px";
}
$(".draggable-element .float-btn").css({
left: leftVal,
top: topVal,
'z-index': 999
});
$(".draggable-element .float-btn .edit-attribute").css({
position: 'fixed',
right: '15px',
top: Math.abs(box1.top)
})
}

View File

@@ -0,0 +1,71 @@
@CHARSET "UTF-8";
.follow-official-account-wrap{
/*position: absolute;*/
/*width: 370px;*/
/*z-index: 999;*/
}
.follow-official-account-wrap .preview-draggable{
/*padding: 0 !important;*/
}
/* 关注公众号 */
.site-info-box {
padding: 5px 10px;
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(0, 0, 0, 0.6);
/*position: absolute;*/
/*width: calc(100% - 20px);*/
/*left:0;*/
}
.site-info-box .site-info {
display: flex;
align-items: center;
}
.site-info-box .site-info .img-box {
width: 35px;
height: 35px;
line-height: initial;
border-radius: 50%;
overflow: hidden;
}
.site-info-box .site-info .img-box img {
width: 100%;
height: 100%;
}
.site-info-box .site-info .info-box {
display: flex;
flex-direction: column;
color: #fff;
justify-content: space-between;
margin-left: 10px;
text-align: left;
width: 200px;
}
.site-info-box .site-info span {
display: -webkit-box;
font-size: 12px;
overflow: hidden;
opacity: 0.8;
white-space: normal;
text-overflow: ellipsis;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
.site-info-box .site-info span:nth-child(1) {
width: 150px;
font-weight: bold;
opacity: 1;
font-size: 14px;
}
.site-info-box button {
width: 90px;
height: 28px;
line-height: 28px;
border-radius: 33px;
font-size: 12px;
padding: 0;
}

View File

@@ -0,0 +1,64 @@
<nc-component :data="data[index]" class="follow-official-account-wrap">
<!-- 预览 -->
<template slot="preview">
<div class="site-info-box" :style="{ }" data-disabled="1">
<div class="site-info" data-disabled="1">
<div class="img-box" data-disabled="1">
<img :src="changeImgUrl('public/static/img/default_img/square.png')" />
</div>
<div class="info-box" :style="{ color: '#ffffff' }" data-disabled="1">
<span class="font-size-base">店铺名称</span>
<span>{{ nc.welcomeMsg }}</span>
</div>
</div>
<button class="layui-btn layui-btn-primary text-color">关注公众号</button>
</div>
</template>
<!-- 内容编辑 -->
<template slot="edit-content">
<div class="template-edit-title">
<h3>内容设置</h3>
<div class="layui-form-item">
<label class="layui-form-label sm">欢迎语</label>
<div class="layui-input-block">
<input type="text" v-model="nc.welcomeMsg" placeholder="请输入欢迎语" class="layui-input" maxlength="20">
</div>
</div>
<div class="layui-form-item checkbox-wrap">
<label class="layui-form-label sm">展示开关</label>
<div class="layui-input-block">
<span v-if="nc.isShow == true">显示</span>
<span v-else>隐藏</span>
<div v-if="nc.isShow == true" @click="nc.isShow = false" class="layui-unselect layui-form-checkbox layui-form-checked" lay-skin="primary">
<i class="layui-icon layui-icon-ok"></i>
</div>
<div v-else @click="nc.isShow = true" class="layui-unselect layui-form-checkbox" lay-skin="primary">
<i class="layui-icon layui-icon-ok"></i>
</div>
</div>
<div class="word-aux diy-word-aux">该组件只会在微信内部展示,在普画浏览器或者小程序不展示,需要配置微信公众号,同时用户关注后会自动隐藏</div>
</div>
</div>
</template>
<!-- 样式编辑 -->
<template slot="edit-style">
<template v-if="nc.lazyLoad">
<follow-official-account-sources></follow-official-account-sources>
</template>
</template>
<!-- 资源 -->
<template slot="resource">
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>

View File

@@ -0,0 +1,38 @@
var followOfficialAccountHtml = '<div></div>';
Vue.component("follow-official-account-sources", {
template: followOfficialAccountHtml,
data: function () {
return {
data: this.$parent.data,
};
},
created: function () {
if (!this.$parent.data.verify) this.$parent.data.verify = [];
this.$parent.data.verify.push(this.verify);//加载验证方法
this.$parent.data.ignore = ['pageBgColor','componentBgColor','textColor','marginBoth','componentAngle'];//加载忽略内容 -- 其他设置中的属性设置
this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载
// $(".draggable-element .follow-official-account-wrap").css({
// top: 86, // 55+20+11
// });
//
// $(".draggable-element .follow-official-account-wrap .edit-attribute").css({
// position: 'fixed',
// right:15,
// top: 55 // layui-header-right 的高度
// })
},
methods: {
verify: function (index) {
var res = {code: true, message: ""};
if (vue.data[index].welcomeMsg.length === 0) {
res.code = false;
res.message = "请输入欢迎语";
}
return res;
},
}
});

View File

@@ -0,0 +1,9 @@
@CHARSET "UTF-8";
/* 商品品牌组件 */
.goods-brand .title-wrap{text-align: center;padding: 10px 0 5px;}
.goods-brand ul{display: flex;flex-wrap: wrap;align-items: center;padding: 10px;}
.goods-brand ul li{width: 22.59%;margin-top: 10px;text-align: center;margin-right: 10px;}
.goods-brand ul li:nth-of-type(1),.goods-brand ul li:nth-of-type(2),.goods-brand ul li:nth-of-type(3),.goods-brand ul li:nth-of-type(4){margin-top: 0;}
.goods-brand ul li:nth-of-type(4n){margin-right: 0;}
.goods-brand ul li img{max-width: 100%;}
.goods-brand ul li span{display: block;height: 40px;background: #c7c7c7;line-height: 40px;color: #fff;padding: 5px;}

View File

@@ -0,0 +1,112 @@
<nc-component :data="data[index]" class="goods-brand">
<!-- 预览 -->
<template slot="preview">
<div class="brand-wrap" :style="{ backgroundColor: nc.componentBgColor,
borderTopLeftRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.componentAngle == 'round' ? nc.topAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.componentAngle == 'round' ? nc.bottomAroundRadius + 'px' : 0),
boxShadow: nc.ornament.type == 'shadow' ? ('0 0 5px ' + nc.ornament.color) : '',
border: nc.ornament.type == 'stroke' ? '1px solid ' + nc.ornament.color : ''
}">
<h3 class="title-wrap" v-show="nc.title" :style="{ color : nc.textColor, fontWeight : nc.fontWeight ? 'bold' : ''}">{{ nc.title }}</h3>
<ul v-if="nc.previewList && Object.keys(nc.previewList).length">
<li v-for="(item, previewIndex) in nc.previewList" :key="previewIndex">
<img :src="item.image_url ? changeImgUrl(item.image_url) : '{$resource_path}/img/default.png'" :style="{
borderTopLeftRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
borderTopRightRadius: (nc.elementAngle == 'round' ? nc.topElementAroundRadius + 'px' : 0),
borderBottomLeftRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0),
borderBottomRightRadius: (nc.elementAngle == 'round' ? nc.bottomElementAroundRadius + 'px' : 0)
}" onerror="this.src = '{$resource_path}/img/default.png';" />
</li>
</ul>
</div>
</template>
<!-- 内容编辑 -->
<template slot="edit-content">
<template v-if="nc.lazyLoad">
<goods-brand-sources></goods-brand-sources>
<div class="template-edit-title">
<h3>品牌标题</h3>
<div class="layui-form-item">
<label class="layui-form-label sm">标题</label>
<div class="layui-input-block">
<input type="text" v-model="nc.title" maxlength="20" placeholder="请输入标题" class="layui-input">
</div>
</div>
</div>
<div class="template-edit-title">
<h3>品牌数据</h3>
<div class="layui-form-item" v-if="nc.tempData.goodsSources">
<label class="layui-form-label sm">数据来源</label>
<div class="layui-input-block">
<div class="source-selected">
<div class="source">{{ nc.tempData.goodsSources[nc.sources].text }}</div>
<div v-for="(item,sourcesKey) in nc.tempData.goodsSources" :key="sourcesKey" class="source-item" :title="item.text" @click="nc.sources=sourcesKey" :class="{ 'text-color border-color' : (nc.sources == sourcesKey) }">
<i class='iconfont' :class='item.icon'></i>
</div>
</div>
</div>
</div>
<div class="layui-form-item" v-if="nc.sources == 'diy'">
<label class="layui-form-label sm">手动选择</label>
<div class="layui-input-block">
<div class="selected-style" @click="nc.tempData.methods.addBrand()">
<span v-if="nc.brandIds.length == 0">请选择</span>
<span v-if="nc.brandIds.length > 0" class="text-color">已选{{ nc.brandIds.length }}个</span>
<i class="iconfont iconyoujiantou"></i>
</div>
</div>
</div>
<slide :data="{ field : 'count', label: '品牌数量', min:1, max: 30}" v-if="nc.sources != 'diy'"></slide>
</div>
</template>
</template>
<!-- 样式编辑 -->
<template slot="edit-style">
<template v-if="nc.lazyLoad">
<div class="template-edit-title">
<h3>品牌样式</h3>
<div class="layui-form-item">
<label class="layui-form-label sm">标题粗细</label>
<div class="layui-input-block">
<div class="layui-unselect layui-form-checkbox" lay-skin="primary" @click="nc.fontWeight = !nc.fontWeight" :class="{ 'layui-form-checked' : nc.fontWeight }">
<span>{{ nc.fontWeight ? '粗' : '细' }}</span>
<i class="layui-icon layui-icon-ok"></i>
</div>
</div>
</div>
<div class="layui-form-item tag-wrap">
<label class="layui-form-label sm">边框</label>
<div class="layui-input-block">
<div v-for="(item,ornamentIndex) in nc.tempData.ornamentList" :key="ornamentIndex" @click="nc.ornament.type=item.type" :class="{ 'layui-unselect layui-form-radio' : true,'layui-form-radioed' : (nc.ornament.type==item.type) }">
<i class="layui-anim layui-icon">{{ nc.ornament.type == item.type ? "&#xe643;" : "&#xe63f;" }}</i>
<div>{{item.text}}</div>
</div>
</div>
</div>
<color v-if="nc.ornament.type != 'default'" :data="{ field : 'color', 'label' : '边框颜色', parent : 'ornament', defaultColor : '#EDEDED' }"></color>
<slide v-show="nc.elementAngle == 'round'" :data="{ field : 'topElementAroundRadius', label : '上圆角', max : 50 }"></slide>
<slide v-show="nc.elementAngle == 'round'" :data="{ field : 'bottomElementAroundRadius', label : '下圆角', max : 50 }"></slide>
</div>
</template>
</template>
<!-- 资源 -->
<template slot="resource">
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,72 @@
var brandHtml = '<div></div>';
Vue.component("goods-brand-sources", {
template: brandHtml,
data: function () {
return {
data: this.$parent.data,
goodsSources: {
initial: {
text: "默认",
icon: "iconmofang"
},
diy: {
text: "手动选择",
icon: "iconshoudongxuanze"
},
},
ornamentList: [
{
type: 'default',
text: '默认',
},
{
type: 'shadow',
text: '投影',
},
{
type: 'stroke',
text: '描边',
},
],
};
},
created: function () {
this.$parent.data.ignore = ['elementBgColor'];//加载忽略内容 -- 其他设置中的属性设置
this.$parent.data.ignoreLoad = true; // 等待忽略数组赋值后加载
if(Object.keys(this.$parent.data.previewList).length == 0) {
for (var i = 1; i < 5; i++) {
this.$parent.data.previewList["brand_id_" + ns.gen_non_duplicate(i)] = {
image_url: "",
};
}
}
// 组件所需的临时数据
this.$parent.data.tempData = {
goodsSources: this.goodsSources,
ornamentList: this.ornamentList,
methods: {
addBrand: this.addBrand,
},
};
},
methods: {
verify: function (index) {
var res = {code: true, message: ""};
if (vue.data[index].sources === 'diy' && vue.data[index].brandIds.length === 0) {
res.code = false;
res.message = "请选择文章";
}
return res;
},
addBrand: function () {
var self = this;
goodsBrandSelect(function (res) {
self.$parent.data.brandIds = res.brandIds;
self.$parent.data.previewList = res.list;
}, {select_id: self.$parent.data.brandIds.toString()});
},
}
});

View File

@@ -0,0 +1,18 @@
/* 公共*/
.goods-category .preview-draggable{padding:0;}
.goods-category{background: #ffffff;}
.goods-category .templet-list{display: flex;justify-content: space-between;flex-wrap: wrap;}
.goods-category .templet-img-box{display: flex;justify-content: center;align-items: center;width: 150px;min-height: 90px;border: 1px solid #eee;margin-bottom: 10px;}
.goods-category .templet-img-box img{max-height: 100%;max-width: 100%;}
.goods-category .real-image-box{/*width: 375px;height: 550px;*/}
.goods-category .real-image-box img{/*max-height: 100%;*/max-width: 100%;}
.goods-category-popup-wrap{display: none;}
/* 弹框中的分类样式*/
.goods-classification-style{padding:0 !important;}
.goods-classification-style .style-title{display: flex;margin-bottom: 20px;}
.goods-classification-style .style-title li{width: 110px;height: 35px;line-height: 35px;text-align: center;border: 1px solid #f1f1f1;color: #666;margin-right: 15px;cursor: pointer;}
.goods-classification-style .style-title li.selected{color: #fff;}
.goods-classification-style .style-content li{display: flex;justify-content: space-between;flex-wrap: wrap;}
.goods-classification-style .style-content li .style-img-box{overflow: hidden;position: relative;width: 280px;height: 480px;border: 1px solid #f4f4f4;display: flex;justify-content: space-between;align-items: center;cursor: pointer;margin-top: 15px;}
.goods-classification-style .style-content li .style-img-box:nth-child(1), .goods-classification-style .style-content li .style-img-box:nth-child(2), .goods-classification-style .style-content li .style-img-box:nth-child(3){margin-top: 0;}
.goods-classification-style .style-content li .style-img-box img{max-height: 100%;max-width: 100%;}

View File

@@ -0,0 +1,54 @@
<nc-component :data="data[index]" class="goods-category">
<!-- 预览 -->
<template slot="preview">
<div class="real-image-box" data-disabled="1">
<img :src="'{$resource_path}/img/category_style_' + nc.template + ((nc.template == 1 && nc.level == 2 || nc.template != 1 && nc.goodsLevel ==1) ? '_1' : '') + ((nc.template == 1 && nc.level == 3 || nc.template != 1 && nc.goodsLevel == 2) ? '_2' : '') + (nc.quickBuy ? '_quickBuy' : '') + (nc.search ? '_search' : '') +'.jpg'">
</div>
</template>
<!-- 内容编辑 -->
<template slot="edit-content">
<template v-if="nc.lazyLoad">
<goods-category></goods-category>
</template>
<div class="goods-category-popup-wrap">
<div class="goods-classification-style layui-form">
<ul class="style-content">
<li>
<div :class="{'style-img-box':true,'selected border-color': nc.template == 1}">
<img src="{$resource_path}/img/category_style_1_1_search.jpg" alt="">
</div>
<div :class="{'style-img-box':true,'selected border-color': nc.template == 2}">
<img src="{$resource_path}/img/category_style_2_1_quickBuy_search.jpg" alt="">
</div>
<div :class="{'style-img-box':true,'selected border-color': nc.template == 3}">
<img src="{$resource_path}/img/category_style_3_1_search.jpg" alt="">
</div>
<div :class="{'style-img-box':true,'selected border-color': nc.template == 4}">
<img src="{$resource_path}/img/category_style_4_1_quickBuy_search.jpg" alt="">
</div>
</li>
</ul>
<input type="hidden" class="layui-input" name="level">
<input type="hidden" class="layui-input" name="template">
</div>
</div>
</template>
<!-- 样式编辑 -->
<template slot="edit-style"></template>
<!-- 资源 -->
<template slot="resource">
<js>
var goodsCategoryResourcePath = "{$resource_path}"; // http路径
var goodsCategoryRelativePath = "{$relative_path}"; // 相对路径
</js>
<css src="{$resource_path}/css/design.css"></css>
<js src="{$resource_path}/js/design.js"></js>
</template>
</nc-component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Some files were not shown because too many files have changed in this diff Show More