同步代码

This commit is contained in:
邹景立 2021-01-20 18:17:14 +08:00
parent 43aa856db3
commit 9dbc5cc4f2
49 changed files with 1927 additions and 318 deletions

View File

@ -0,0 +1,87 @@
<?php
namespace app\data\command;
use app\data\service\OrderService;
use think\admin\Command;
use think\admin\Exception;
use think\console\Input;
use think\console\Output;
/**
* 自动清理商城订单
* Class OrderClear
* @package app\data\command
*/
class OrderClear extends Command
{
protected function configure()
{
$this->setName('xdata:OrderClear');
$this->setDescription('定时清理商城订单数据');
}
/**
* 业务指令执行
* @param Input $input
* @param Output $output
* @return void
* @throws Exception
*/
protected function execute(Input $input, Output $output)
{
$this->_autoCancelOrder();
$this->_autoRemoveOrder();
}
/**
* 自动取消30分钟未支付的订单
* @throws Exception
*/
private function _autoCancelOrder()
{
try {
$map = [];
$map[] = ['status', '=', '1'];
$map[] = ['payment_status', '=', '0'];
$map[] = ['create_at', '<', date('Y-m-d H:i:s', strtotime('-30 minutes'))];
[$count, $used] = [$this->app->db->name('ShopOrder')->where($map)->count(), 0];
$this->app->db->name('ShopOrder')->where($map)->select()->map(function ($item) use ($count, &$used) {
$this->queue->message($count, ++$used, "开始取消未支付的订单 {$item['order_no']}");
$this->app->db->name('ShopOrder')->where(['order_no' => $item['order_no']])->update([
'status' => '0',
'cancel_status' => '1',
'cancel_datetime' => date('Y-m-d H:i:s'),
'cancel_remark' => '30分钟未完成支付已自动取消',
]);
OrderService::instance()->syncStock($item['order_no']);
$this->queue->message($count, $used, "完成取消未支付的订单 {$item['order_no']}", 1);
});
} catch (\Exception $exception) {
$this->queue->error($exception->getMessage());
}
}
/**
* 自动清理已经取消的订单
* @throws Exception
*/
private function _autoRemoveOrder()
{
try {
$map = [];
$map[] = ['status', '=', 0];
$map[] = ['payment_status', '=', 0];
$map[] = ['create_at', '<', date('Y-m-d H:i:s', strtotime('-3 days'))];
[$count, $used] = [$this->app->db->name('ShopOrder')->where($map)->count(), 0];
$this->app->db->name('ShopOrder')->where($map)->select()->map(function ($item) use ($count, &$used) {
$this->queue->message($count, ++$used, "开始清理已取消的订单 {$item['order_no']}");
$this->app->db->name('ShopOrder')->where(['order_no' => $item['order_no']])->delete();
$this->app->db->name('ShopOrderItem')->where(['order_no' => $item['order_no']])->delete();
$this->queue->message($count, $used, "完成清理已取消的订单 {$item['order_no']}", 1);
});
} catch (\Exception $exception) {
$this->queue->error($exception->getMessage());
}
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace app\data\command;
use app\data\service\UserService;
use think\admin\Command;
use think\admin\Exception;
use think\console\Input;
use think\console\Output;
/**
* 同步计算用户余额
* Class UserBalance
* @package app\data\command
*/
class UserBalance extends Command
{
protected function configure()
{
$this->setName('xdata:UserBalance');
$this->setDescription('批量重新计算用户余额');
}
/**
* @param Input $input
* @param Output $output
* @return void
* @throws Exception
*/
protected function execute(Input $input, Output $output)
{
try {
[$total, $count] = [$this->app->db->name('DataUser')->count(), 0];
foreach ($this->app->db->name('DataUser')->field('id')->cursor() as $user) {
$this->queue->message($total, ++$count, "正在计算用户 [{$user['id']}] 的余额");
UserService::instance()->balance($user['id']);
$this->queue->message($total, $count, "完成计算用户 [{$user['id']}] 的余额");
}
} catch (\Exception $exception) {
$this->queue->error($exception->getMessage());
}
}
}

View File

@ -163,22 +163,21 @@ class ShopGoods extends Controller
if (empty($data['slider'])) $this->error('轮播图不能为空!');
// 商品规格保存
$data['mark'] = arr2str($data['mark'] ?? []);
[$count, $items] = [0, json_decode($data['data_items'], true)];
foreach ($items as $item) {
$count += intval($item[0]['status']);
if (empty($data['price_market'])) $data['price_market'] = $item[0]['market'];
}
[$count, $items] = [0, array_column(json_decode($data['data_items'], true), 0)];
foreach ($items as $item) $count += intval($item['status']);
if (empty($count)) $this->error('无效的的商品价格信息!');
if (empty($data['price_market'])) $data['price_market'] = min(array_column($items, 'market'));
if (empty($data['price_selling'])) $data['price_selling'] = min(array_column($items, 'selling'));
$this->app->db->name('ShopGoodsItem')->where(['goods_code' => $data['code']])->update(['status' => 0]);
foreach ($items as $item) data_save('ShopGoodsItem', [
'goods_code' => $data['code'],
'goods_sku' => $item[0]['sku'],
'goods_spec' => $item[0]['key'],
'price_market' => $item[0]['market'],
'price_selling' => $item[0]['selling'],
'number_virtual' => $item[0]['virtual'],
'number_express' => $item[0]['express'],
'status' => $item[0]['status'] ? 1 : 0,
'goods_sku' => $item['sku'],
'goods_spec' => $item['key'],
'price_market' => $item['market'],
'price_selling' => $item['selling'],
'number_virtual' => $item['virtual'],
'number_express' => $item['express'],
'status' => $item['status'] ? 1 : 0,
], 'goods_spec', ['goods_code' => $data['code']]);
}
}

View File

@ -3,7 +3,9 @@
namespace app\data\controller;
use app\data\service\OrderService;
use app\data\service\PaymentService;
use app\data\service\TruckService;
use app\data\service\UserService;
use think\admin\Controller;
use think\exception\HttpResponseException;
@ -20,6 +22,18 @@ class ShopOrder extends Controller
*/
private $table = 'ShopOrder';
/**
* 支付方式
* @var array
*/
protected $payments = [];
protected function initialize()
{
parent::initialize();
$this->payments = PaymentService::types();
}
/**
* 订单数据管理
* @auth true
@ -46,7 +60,7 @@ class ShopOrder extends Controller
$db = $this->_query('ShopOrderSend')->like('address_name#truck_address_name,address_phone#truck_address_phone,address_province|address_city|address_area|address_content#truck_address_content')->db();
if ($db->getOptions('where')) $query->whereRaw("order_no in {$db->field('order_no')->buildSql()}");
// 用户搜索查询
$db = $this->_query('DataUser')->like('phone#member_phone,nickname#member_nickname')->db();
$db = $this->_query('DataUser')->like('phone#user_phone,nickname#user_nickname')->db();
if ($db->getOptions('where')) $query->whereRaw("uid in {$db->field('id')->buildSql()}");
// 推荐人搜索查询
$db = $this->_query('DataUser')->like('phone#from_phone,nickname#from_nickname')->db();
@ -54,7 +68,7 @@ class ShopOrder extends Controller
// 列表选项卡
if (is_numeric($this->type = trim(input('type', 'ta'), 't'))) $query->where(['status' => $this->type]);
// 分页排序处理
$query->order('id desc');
$query->where(['deleted' => 0])->order('id desc');
if (input('output') === 'json') {
$this->success('获取数据成功', $query->page(true, false));
} else {
@ -71,7 +85,12 @@ class ShopOrder extends Controller
*/
protected function _index_page_filter(array &$data)
{
UserService::instance()->buildByUid($data);
UserService::instance()->buildByUid($data, 'from', 'fromer');
OrderService::instance()->buildItemData($data);
foreach ($data as &$vo) {
$vo['payment_name'] = PaymentService::name($vo['payment_type']);
}
}
/**
@ -140,6 +159,15 @@ class ShopOrder extends Controller
}
}
/**
* 清理订单数据
* @auth true
*/
public function clean()
{
$this->_queue('定时清理无效订单数据', "xdata:OrderClear", 0, [], 0, 60);
}
/**
* 取消未支付的订单
* @auth true
@ -164,6 +192,7 @@ class ShopOrder extends Controller
'cancel_datetime' => date('Y-m-d H:i:s'),
]);
if ($result !== false) {
OrderService::instance()->syncStock($order['order_no']);
$this->success('取消未支付的订单成功!');
} else {
$this->error('取消支付的订单失败!');

View File

@ -2,6 +2,8 @@
namespace app\data\controller;
use app\data\service\OrderService;
use app\data\service\UserService;
use think\admin\Controller;
/**
@ -28,6 +30,8 @@ class ShopOrderSend extends Controller
public function index()
{
$this->title = '订单发货管理';
// 发货地址数据
$this->address = sysdata('ordersend');
// 状态数据统计
$this->total = ['t0' => 0, 't1' => 0, 't2' => 0, 'ta' => 0];
$this->app->db->name($this->table)->fieldRaw('status,count(1) total')->group('status')->select()->map(function ($vo) {
@ -36,10 +40,10 @@ class ShopOrderSend extends Controller
});
// 订单列表查询
$query = $this->_query($this->table)->order('id desc');
$query->dateBetween('address_datetime,send_datetime')->equal('status')->like('send_number#truck_number');
$query->dateBetween('address_datetime,send_datetime')->equal('status')->like('send_number#truck_number,order_no');
$query->like('address_phone,address_name,address_province|address_city|address_area|address_content#address_content');
// 用户搜索查询
$db = $this->_query('DataUser')->like('phone#member_phone,nickname#member_nickname')->db();
$db = $this->_query('DataUser')->like('phone#user_phone,nickname#user_nickname')->db();
if ($db->getOptions('where')) $query->whereRaw("uid in {$db->field('id')->buildSql()}");
// 订单搜索查询
$db = $this->_query('ShopOrder')->whereIn('status', [3, 4, 5])->db();
@ -60,12 +64,31 @@ class ShopOrderSend extends Controller
/**
* 订单列表处理
* @param array $data
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function _index_page_filter(array &$data)
{
$uids = array_unique(array_column($data, 'uid'));
$users = $this->app->db->name('DataUser')->whereIn('id', $uids)->column('*', 'id');
foreach ($data as &$vo) $vo['member'] = $users[$vo['uid']] ?? [];
OrderService::instance()->buildItemData($data, false);
}
/**
* 修改发货地址
* @auth true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function config()
{
if ($this->request->isGet()) {
$this->vo = sysdata('ordersend');
$this->fetch();
} else {
sysdata('ordersend', $this->request->post());
$this->success('发货地址保存成功');
}
}
}

View File

@ -0,0 +1,130 @@
<?php
namespace app\data\controller;
use app\data\service\PaymentService;
use app\data\service\UserService;
use think\admin\Controller;
use think\admin\extend\CodeExtend;
/**
* 支付参数通道
* Class ShopPayment
* @package app\data\controller
*/
class ShopPayment extends Controller
{
/**
* 绑定数据表
* @var string
*/
private $table = 'ShopPayment';
/**
* 支付参数类型
* @var array
*/
protected $types = PaymentService::TYPES;
/**
* 支付参数管理
* @auth true
* @menu true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function index()
{
$this->title = '支付参数管理';
$query = $this->_query($this->table);
$query->where(['deleted' => 0])->order('sort desc,id desc');
$query->equal('type,status')->like('name')->dateBetween('create_at')->page();
}
/**
* 添加支付参数
* @auth true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function add()
{
$this->title = '添加支付参数';
$this->_form($this->table, 'form');
}
/**
* 编辑支付参数
* @auth true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function edit()
{
$this->title = '编辑支付参数';
$this->_form($this->table, 'form');
}
/**
* 数据表单处理
* @param array $data
*/
protected function _form_filter(array &$data)
{
if (empty($data['code'])) {
$data['code'] = CodeExtend::uniqidNumber(14, 'M');
}
if ($this->request->isGet()) {
$this->payments = [];
foreach ($this->types as $k => $vo) {
$allow = [];
foreach ($vo['bind'] as $api) if (isset(UserService::TYPES[$api])) {
$allow[$api] = UserService::TYPES[$api]['name'];
}
$this->payments[$k] = array_merge($vo, ['allow' => join('、', $allow)]);
}
$data['content'] = json_decode($data['content'] ?? '[]', true) ?: [];
} else {
if (empty($data['type'])) $this->error('请选择支付参数并配置支付参数!');
$data['content'] = json_encode($this->request->post() ?: [], JSON_UNESCAPED_UNICODE);
}
}
/**
* 表单结果处理
* @param boolean $state
*/
protected function _form_result(bool $state)
{
if ($state) {
$this->success('支付参数保存成功!', 'javascript:history.back()');
}
}
/**
* 修改支付参数状态
* @auth true
* @throws \think\db\exception\DbException
*/
public function state()
{
$this->_save($this->table, $this->_vali([
'status.in:0,1' => '状态值范围异常!',
'status.require' => '状态值不能为空!',
]));
}
/**
* 删除支付参数
* @auth true
* @throws \think\db\exception\DbException
*/
public function remove()
{
$this->_delete($this->table);
}
}

View File

@ -0,0 +1,124 @@
<?php
namespace app\data\controller;
use app\data\service\UserService;
use think\admin\Controller;
use think\admin\extend\CodeExtend;
use think\admin\service\AdminService;
/**
* 余额充值管理
* Class UserBalance
* @package app\data\controller
*/
class UserBalance extends Controller
{
/**
* 绑定数据表
* @var string
*/
private $table = 'DataUserBalance';
/**
* 余额充值管理
* @auth true
* @menu true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function index()
{
$this->title = '余额充值管理';
$query = $this->_query($this->table);
// 用户搜索查询
$db = $this->_query('DataUser')->like('phone#user_phone,nickname#user_nickname')->db();
if ($db->getOptions('where')) $query->whereRaw("uid in {$db->field('id')->buildSql()}");
// 数据查询分页
$query->where(['deleted' => 0])->like('code,name')->dateBetween('create_at')->order('id desc')->page();
}
/**
* 数据列表处理
* @param array $data
*/
protected function _index_page_filter(array &$data)
{
UserService::instance()->buildByUid($data);
$uids = array_unique(array_column($data, 'create_by'));
$users = $this->app->db->name('SystemUser')->whereIn('id', $uids)->column('username', 'id');
foreach ($data as &$vo) $vo['create_byname'] = $users[$vo['create_by']] ?? $vo['create_by'];
}
/**
* 添加余额充值
* @auth true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function add()
{
$data = $this->_vali(['uid.require' => '用户UID不能为空']);
$this->user = $this->app->db->name('DataUser')->where(['id' => $data['uid']])->find();
if (empty($this->user)) $this->error('待充值的用户不存在!');
$this->_form($this->table, 'form');
}
/**
* 表单数据处理
* @param array $data
*/
protected function _form_filter(array &$data)
{
if (empty($data['code'])) {
$data['code'] = CodeExtend::uniqidDate('16', 'B');
}
if ($this->request->isPost()) {
if ($data['amount'] <= 0) {
$this->error('充值金额不能少于零');
}
$data['create_by'] = AdminService::instance()->getUserId();
}
}
/**
* 表单结果处理
* @param bool $state
* @param array $data
* @throws \think\db\exception\DbException
*/
protected function _form_result(bool $state, array $data)
{
if ($state && isset($data['uid'])) {
UserService::instance()->balance($data['uid']);
}
}
/**
* 删除充值记录
* @auth true
* @throws \think\db\exception\DbException
*/
public function remove()
{
$this->_delete($this->table);
}
/**
* 删除结果处理
* @param bool $state
* @throws \think\db\exception\DbException
*/
protected function _delete_result(bool $state)
{
if ($state) {
$ids = str2arr(input('id', ''));
$query = $this->app->db->name($this->table);
foreach ($query->whereIn('id', $ids)->cursor() as $vo) {
UserService::instance()->balance($vo['uid']);
}
}
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace app\data\controller;
use think\admin\Controller;
/**
* 用户通知管理
* Class UserNotify
* @package app\data\controller
*/
class UserNotify extends Controller
{
/**
* 绑定数据表
* @var string
*/
private $table = 'DataUserNotify';
/**
* 系统通知管理
* @auth true
* @menu true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function index()
{
$this->title = '系统通知管理';
$query = $this->_query($this->table);
$query->like('name')->equal('status')->dateBetween('create_at');
$query->where(['deleted' => 0])->order('sort desc,id desc')->page();
}
/**
* 添加系统通知
* @auth true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function add()
{
$this->_form($this->table, 'form');
}
/**
* 编辑系统通知
* @auth true
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function edit()
{
$this->_form($this->table, 'form');
}
/**
* 表单结果处理
* @param boolean $state
*/
protected function _form_result(bool $state)
{
if ($state) {
$this->success('内容保存成功!', 'javascript:history.back()');
}
}
/**
* 修改系统通知状态
* @auth true
* @throws \think\db\exception\DbException
*/
public function state()
{
$this->_save($this->table, $this->_vali([
'status.in:0,1' => '状态值范围异常!',
'status.require' => '状态值不能为空!',
]));
}
/**
* 删除系统通知
* @auth true
* @throws \think\db\exception\DbException
*/
public function remove()
{
$this->_delete($this->table);
}
}

View File

@ -41,10 +41,13 @@ abstract class Auth extends Controller
*/
protected function initialize()
{
$this->type = input('api', UserService::APITYPE_WXAPP);
// 接口数据类型
$this->type = input('api') ?: $this->request->header('api-type');
$this->type = $this->type ?: UserService::APITYPE_WXAPP;
if (empty(UserService::TYPES[$this->type])) {
$this->error("接口通道[{$this->type}]未定义规则!");
}
// 获取用户数据
$this->user = $this->getUser();
$this->uuid = $this->user['id'];
}
@ -56,14 +59,14 @@ abstract class Auth extends Controller
protected function getUser(): array
{
try {
$service = UserService::instance();
$user = UserService::instance();
if (empty($this->uuid)) {
$token = input('token') ?: $this->request->header('token');
if (empty($token)) $this->error('登录认证令牌不能为空!');
[$state, $info, $this->uuid] = $service->checkUserToken($this->type, $token);
$token = input('token') ?: $this->request->header('api-token');
if (empty($token)) $this->error('登录认证TOKEN不能为空!');
[$state, $info, $this->uuid] = $user->check($this->type, $token);
if (empty($state)) $this->error($info, '{-null-}', 401);
}
return $service->get($this->type, $this->uuid);
return $user->get($this->type, $this->uuid);
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $exception) {

View File

@ -22,4 +22,17 @@ class Data extends Controller
$data = sysdata(input('keys', 'slider'));
$this->success('获取轮播图片数据', $data);
}
/**
* 获取系统通知数据
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getNotify()
{
$query = $this->_query('DataUserNotify')->where(['status' => 1, 'deleted' => 0]);
$result = $query->equal('id')->order('sort desc,id desc')->page(true, false, false, 20);
$this->success('获取系统通知数据', $result);
}
}

View File

@ -17,7 +17,7 @@ class Notify extends Controller
/**
* 微信支付通知
* @param string $scene 支付场景
* @param string $param 支付通道
* @param string $param 支付参数
* @return string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \think\Exception
@ -37,7 +37,7 @@ class Notify extends Controller
/**
* 支付宝支付通知
* @param string $scene 支付场景
* @param string $param 支付通道
* @param string $param 支付参数
* @return string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \think\Exception
@ -57,7 +57,7 @@ class Notify extends Controller
/**
* 汇聚支付通知
* @param string $scene 支付场景
* @param string $param 支付通道
* @param string $param 支付参数
* @return string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \think\Exception

View File

@ -45,12 +45,12 @@ class Address extends Auth
if ($count > 0) $this->error('抱歉,该地址已经存在!');
$data['code'] = CodeExtend::uniqidDate(12, 'A');
if ($this->app->db->name($this->table)->insert($data) === false) {
$this->error('添加收货地址失败!');
$this->error('添加地址失败!');
}
} else {
$map = ['uid' => $this->uuid, 'code' => $data['code']];
$address = $this->app->db->name($this->table)->where($map)->find();
if (empty($address)) $this->error('修改收货地址不存在!');
if (empty($address)) $this->error('修改地址不存在!');
$this->app->db->name($this->table)->where($map)->update($data);
}
// 去除其它默认选项
@ -58,7 +58,7 @@ class Address extends Auth
$map = [['uid', '=', $this->uuid], ['code', '<>', $data['code']]];
$this->app->db->name($this->table)->where($map)->update(['type' => 0]);
}
$this->success('添加收货地址成功!', $this->_getAddress($data['code']));
$this->success('地址保存成功!', $this->_getAddress($data['code']));
}
/**
@ -72,7 +72,7 @@ class Address extends Auth
$query = $this->_query($this->table)->withoutField('deleted');
$query->equal('code')->where(['uid' => $this->uuid, 'deleted' => 0]);
$result = $query->order('type desc,id desc')->page(false, false, false, 15);
$this->success('获取收货地址数据!', $result);
$this->success('获取地址数据!', $result);
}
/**

View File

@ -0,0 +1,75 @@
<?php
namespace app\data\controller\api\auth;
use app\data\controller\api\Auth;
use app\data\controller\User;
use app\data\service\UserService;
use think\admin\extend\CodeExtend;
/**
* 用户余额转账
* Class Balance
* @package app\data\controller\api\auth
*/
class Balance extends Auth
{
/**
* 绑定数据表
* @var string
*/
private $table = 'DataUserBalanceTransfer';
/**
* 获取用户转账记录
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function get()
{
$query = $this->_query($this->table);
$query->where(['uid|from' => $this->uuid, 'deleted' => 0]);
$result = $query->order('id desc')->page(true, false, false, 15);
if (count($result['list']) > 0) {
UserService::instance()->buildByUid($result['list'], 'uid', 'selfer');
UserService::instance()->buildByUid($result['list'], 'from', 'fromer');
}
$this->success('获取数据成功', $result);
}
/**
* 创建余额转账申请
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function add()
{
$data = $this->_vali([
'from.value' => $this->uuid,
'code.value' => CodeExtend::uniqidDate(18, 'T'),
'uid.require' => '目标用户不能为空!',
'name.default' => '用户余额转账',
'amount.require' => '转账金额不能为空!',
]);
if ($data['uid'] == $this->uuid) {
$this->error('不能给自己转账!');
}
// 检测目标用户状态
$map = ['id' => $data['uid'], 'deleted' => 0];
$user = $this->app->db->name('DataUser')->where($map)->find();
if (empty($user)) $this->error('目标用户不存在!');
// 检测用户是否有足够的余额
[$total, $used] = UserService::instance()->balance($this->uuid);
if ($data['amount'] > $total - $used) $this->error('可转账余额不足!');
// 写入余额转账记录
if ($this->app->db->name($this->table)->insert($data) !== false) {
UserService::instance()->balance($data['uid']);
UserService::instance()->balance($data['from']);
$this->success('余额转账成功!');
} else {
$this->error('余额转账失败!');
}
}
}

View File

@ -54,14 +54,6 @@ class Center extends Auth
$this->success('获取用户资料', $this->getUser());
}
/**
* 获取用户数据统计
*/
public function total()
{
$this->success('获取用户统计!', UserService::instance()->total($this->uuid));
}
/**
* Base64 图片上传
*/
@ -106,6 +98,32 @@ class Center extends Auth
}
}
/**
* 获取我邀请的朋友
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getFrom()
{
$where = [];
$where[] = ['deleted', '=', '0'];
$where[] = ['path', 'like', "%-{$this->uuid}-%"];
// 查询邀请的朋友
$query = $this->_query($this->table);
$query->like('nickname|username#nickname')->equal('from,id#uid');
$query->field('id,from,username,nickname,headimg,amount_total,create_at');
$result = $query->where($where)->order('id desc')->page(true, false, false, 15);
// 统计当前用户所有下属数
$userTotal = $this->app->db->name($this->table)->where($where)->count();
// 统计当前用户本月下属数
$where[] = ['create_at', 'like', date('Y-m-%')];
$userMonth = $this->app->db->name($this->table)->where($where)->count();
// 返回结果列表数据及统计
$result['total'] = ['user_total' => $userTotal, 'user_month' => $userMonth];
$this->success('获取我邀请的朋友', $result);
}
/**
* 绑定用户邀请人
* @throws \think\Exception
@ -122,23 +140,13 @@ class Center extends Auth
$from = $this->app->db->name($this->table)->where(['id' => $data['from']])->find();
if (empty($from)) $this->error('邀请人状态异常', UserService::instance()->get($this->type, $this->uuid));
if ($this->user['from'] > 0) $this->error('已绑定了邀请人', UserService::instance()->total($this->uuid));
if (is_numeric(stripos($from['path'], "-{$this->uuid}-"))) $this->error('不能绑定下属');
$data['path'] = rtrim($from['path'] ?: '-', '-') . '-' . $from['id'] . '-';
$data['layer'] = substr_count($data['path'], '-');
if ($this->app->db->name($this->table)->where(['id' => $this->uuid])->update($data) !== false) {
$this->success('绑定邀请人成功', UserService::instance()->total($this->uuid));
} else {
$this->error('绑定邀请人失败', UserService::instance()->total($this->uuid));
}
}
/**
* 获取我邀请的朋友
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getFrom()
{
$query = $this->_query($this->table)->field('id,from,username,nickname,headimg,create_at');
$this->success('获取我邀请的朋友', $query->where(['from' => $this->uuid])->order('id desc')->page(true, false, false, 15));
}
}

View File

@ -13,7 +13,7 @@ use app\data\service\PaymentService;
class Config extends Auth
{
/**
* 获取支付通道数据
* 获取支付参数数据
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
@ -27,8 +27,8 @@ class Config extends Auth
}
}
$map = ['status' => 1, 'deleted' => 0];
$query = $this->app->db->name('DataPayment')->where($map)->whereIn('type', $types);
$query = $this->app->db->name('ShopPayment')->where($map)->whereIn('type', $types);
$collect = $query->order('sort desc,id desc')->field('code,name,type')->select();
$this->success('获取支付通道数据', $collect->toArray());
$this->success('获取支付参数数据', $collect->toArray());
}
}

View File

@ -37,10 +37,7 @@ class Order extends Auth
*/
public function get()
{
$map = [['uid', '=', $this->uuid]];
if (!$this->request->has('order_no', 'param', true)) {
$map[] = ['status', 'in', [0, 2, 3, 4, 5]];
}
$map = ['uid' => $this->uuid, 'deleted' => 0];
$query = $this->_query('ShopOrder')->in('status')->equal('order_no');
$result = $query->where($map)->order('id desc')->page(true, false, false, 20);
if (count($result['list']) > 0) OrderService::instance()->buildItemData($result['list']);
@ -57,32 +54,31 @@ class Order extends Auth
{
// 商品规则
$rules = $this->request->post('items', '');
if (empty($rules)) $this->error('商品规则不能为空');
if (empty($rules)) $this->error('商品不能为空');
// 订单数据
[$codes, $items] = [[], []];
$order = ['uid' => $this->uuid, 'from' => input('from_mid', '0'), 'status' => 1];
$order = ['uid' => $this->uuid, 'status' => 1];
$order['order_no'] = CodeExtend::uniqidDate(18, 'N');
// 推荐人处理
if ($order['from'] == $this->uuid) {
$order['from'] = 0;
}
$order['from'] = input('from_uid', $this->user['from']);
if ($order['from'] == $this->uuid) $order['from'] = 0;
if ($order['from'] > 0) {
$map = ['id' => $order['from'], 'status' => 1];
$from = $this->app->db->name('ShopMember')->where($map)->find();
if (empty($from)) $this->error('推荐人信息异常');
$from = $this->app->db->name('DataUser')->where($map)->find();
if (empty($from)) $this->error('推荐人异常');
}
foreach (explode('||', $rules) as $rule) {
[$code, $spec, $count] = explode('@', $rule);
// 商品信息检查
$map = ['code' => $code, 'status' => 1, 'deleted' => 0];
$goodsInfo = $this->app->db->name('ShopGoods')->where($map)->find();
if (empty($goodsInfo)) $this->error('商品主体异常,请稍候再试!');
if (empty($goodsInfo)) $this->error('商品数据异常');
$map = ['goods_code' => $code, 'goods_spec' => $spec, 'status' => 1];
$goodsItem = $this->app->db->name('ShopGoodsItem')->where($map)->find();
if (empty($goodsItem)) $this->error('商品规格异常,请稍候再试!');
if (empty($goodsItem)) $this->error('商品规格异常');
// 商品库存检查
if ($goodsItem['stock_sales'] + $count > $goodsItem['stock_total']) {
$this->error('商品库存不足,请购买其它商品!');
$this->error('商品库存不足');
}
// 订单详情处理
$items[] = [
@ -106,29 +102,34 @@ class Order extends Auth
];
}
try {
// 统计订单商品
$order['amount_reduct'] = OrderService::instance()->getReduct();
// 统计订单金额
// 统计商品数量
$order['number_goods'] = array_sum(array_column($items, 'stock_sales'));
// 统计商品金额
$order['amount_goods'] = array_sum(array_column($items, 'total_selling'));
$order['amount_total'] = $order['amount_goods'] - $order['amount_reduct'];
// 支付金额不能为零
if ($order['amount_total'] <= 0) $order['amount_total'] = 0.01;
// 订单随机免减
$order['amount_reduct'] = OrderService::instance()->getReduct();
if ($order['amount_reduct'] > $order['amount_goods']) {
$order['amount_reduct'] = $order['amount_goods'];
}
// 统计订单金额
$order['amount_real'] = $order['amount_goods'] - $order['amount_reduct'];
$order['amount_total'] = $order['amount_goods'];
// 写入订单商品数据
$this->app->db->name('ShopOrder')->insert($order);
$this->app->db->name('ShopOrderItem')->insertAll($items);
// 同步商品库存销量
foreach ($codes as $code) GoodsService::instance()->syncStock($code);
// 返回订单数据接口
$order['items'] = $items;
// 触发订单创建事件
$this->app->event->trigger('ShopOrderCreate', $order['order_no']);
// 组装订单商品数据
$order['items'] = $items;
// 返回处理成功数据
$this->success('预购订单创建成功,请补全收货地址', $order);
$this->success('商品下单成功', $order);
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $exception) {
$this->error("创建订单失败,{$exception->getMessage()}");
$this->error("商品下单失败,{$exception->getMessage()}");
}
}
@ -141,13 +142,13 @@ class Order extends Auth
public function express()
{
$data = $this->_vali([
'code.require' => '收货地址不能为空',
'order_no.require' => '订单单号不能为空',
'code.require' => '地址不能为空',
'order_no.require' => '单号不能为空',
]);
// 用户收货地址
$map = ['uid' => $this->uuid, 'code' => $data['code']];
$addr = $this->app->db->name('DataUserAddress')->where($map)->find();
if (empty($addr)) $this->error('用户收货地址异常');
if (empty($addr)) $this->error('收货地址异常');
// 订单状态检查
$map = ['uid' => $this->uuid, 'order_no' => $data['order_no']];
$tCount = $this->app->db->name('ShopOrderItem')->where($map)->sum('truck_count');
@ -167,18 +168,18 @@ class Order extends Auth
public function perfect()
{
$data = $this->_vali([
'code.require' => '地址编号不能为空',
'order_no.require' => '订单单号不能为空',
'code.require' => '地址不能为空',
'order_no.require' => '单号不能为空',
]);
// 用户收货地址
$map = ['uid' => $this->uuid, 'code' => $data['code'], 'deleted' => 0];
$addr = $this->app->db->name('DataUserAddress')->where($map)->find();
if (empty($addr)) $this->error('用户收货地址异常');
if (empty($addr)) $this->error('收货地址异常');
// 订单状态检查
$map = ['uid' => $this->uuid, 'order_no' => $data['order_no']];
$order = $this->app->db->name('ShopOrder')->where($map)->whereIn('status', [1, 2])->find();
$tCount = $this->app->db->name('ShopOrderItem')->where($map)->sum('truck_count');
if (empty($order)) $this->error('不能修改收货地址哦!');
if (empty($order)) $this->error('不能修改地址');
// 根据地址计算运费
$map = ['status' => 1, 'deleted' => 0, 'order_no' => $data['order_no']];
$tCodes = $this->app->db->name('ShopOrderItem')->where($map)->column('truck_tcode');
@ -192,25 +193,30 @@ class Order extends Auth
$express['address_code'] = $data['code'];
$express['address_name'] = $addr['name'];
$express['address_phone'] = $addr['phone'];
$express['address_idcode'] = $addr['idcode'];
$express['address_province'] = $addr['province'];
$express['address_city'] = $addr['city'];
$express['address_area'] = $addr['area'];
$express['address_content'] = $addr['address'];
$express['address_datetime'] = date('Y-m-d H:i:s');
data_save('ShopOrderSend', $express, 'order_no');
// 更新订单状态,刷新订单金额
$map = ['uid' => $this->uuid, 'order_no' => $data['order_no']];
// 组装更新订单数据
$update = ['status' => 2, 'amount_express' => $express['template_amount']];
$update['amount_total'] = $order['amount_goods'] + $amount - $order['amount_reduct'] - $order['amount_discount'];
// 重新计算订单金额
$update['amount_real'] = $order['amount_goods'] + $amount - $order['amount_reduct'] - $order['amount_discount'];
$update['amount_total'] = $order['amount_goods'] + $amount;
// 支付金额不能为零
if ($update['amount_total'] <= 0) $update['amount_total'] = 0.01;
if ($update['amount_real'] <= 0) $update['amount_real'] = 0.00;
if ($update['amount_total'] <= 0) $update['amount_total'] = 0.00;
// 更新用户订单数据
$map = ['uid' => $this->uuid, 'order_no' => $data['order_no']];
if ($this->app->db->name('ShopOrder')->where($map)->update($update) !== false) {
// 触发订单确认事件
$this->app->event->trigger('ShopOrderPerfect', $order['order_no']);
// 返回处理成功数据
$this->success('订单确认成功', ['order_no' => $order['order_no']]);
$this->success('订单确认成功', ['order_no' => $order['order_no']]);
} else {
$this->error('订单确认失败,请稍候再试!');
$this->error('订单确认失败');
}
}
@ -223,27 +229,30 @@ class Order extends Auth
public function payment()
{
$data = $this->_vali([
'order_no.require' => '订单单号不能为空',
'payment_code.require' => '支付通道不能为空!',
'order_no.require' => '单号不能为空',
'payment_code.require' => '参数不能为空',
'payment_back.default' => '', # 支付回跳地址
]);
$map = ['order_no' => $data['order_no']];
$order = $this->app->db->name('ShopOrder')->where($map)->find();
if (empty($order)) $this->error('获取订单数据失败!');
if ($order['status'] != 2) $this->error('订单不能发起支付哦!');
if ($order['payment_status'] > 0) $this->error('订单已经完成支付');
if (empty($order)) $this->error('读取订单失败');
if ($order['status'] != 2) $this->error('不能发起支付');
if ($order['payment_status'] > 0) $this->error('已经完成支付');
try {
$openid = '';
if (in_array($this->type, [UserService::APITYPE_WXAPP, UserService::APITYPE_WECHAT])) {
$openid = $this->user[UserService::TYPES[$this->type]['auth']] ?? '';
if (empty($openid)) $this->error("无法创建支付未获取到OPENID");
if (empty($openid)) $this->error("无法创建支付");
}
$params = PaymentService::instance($data['payment_code'])->create($openid, $order['order_no'], $order['amount_total'], '商城订单支付', '', $data['payment_back']);
$this->success('获取支付参数成功!', $params);
// 返回订单数据及支付发起参数
$type = $order['amount_real'] <= 0 ? 'empty' : $data['payment_code'];
$param = PaymentService::instance($type)->create($openid, $order['order_no'], $order['amount_real'], '商城订单支付', '', $data['payment_back']);
$order = $this->app->db->name('ShopOrder')->where($map)->find() ?: new \stdClass();
$this->success('获取支付参数', ['order' => $order, 'param' => $param]);
} catch (HttpResponseException $exception) {
throw $exception;
} catch (\Exception $exception) {
$this->error("创建支付参数失败,{$exception->getMessage()}");
$this->error($exception->getMessage());
}
}
@ -257,10 +266,10 @@ class Order extends Auth
{
$map = $this->_vali([
'uid.value' => $this->uuid,
'order_no.require' => '单号不能为空',
'order_no.require' => '单号不能为空',
]);
$order = $this->app->db->name('ShopOrder')->where($map)->find();
if (empty($order)) $this->error('订单查询失败,请稍候再试!');
if (empty($order)) $this->error('读取订单失败');
if (in_array($order['status'], [1, 2])) {
$result = $this->app->db->name('ShopOrder')->where($map)->update([
'status' => 0,
@ -272,12 +281,46 @@ class Order extends Auth
// 触发订单取消事件
$this->app->event->trigger('ShopOrderCancel', $order['order_no']);
// 返回处理成功数据
$this->success('订单取消成功');
$this->success('订单取消成功');
} else {
$this->error('订单取消失败,请稍候再试!');
$this->error('订单取消失败');
}
} else {
$this->error('该订单状态不能取消哦~');
$this->error('订单不可取消');
}
}
/**
* 用户主动删除已取消的订单
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function remove()
{
$map = $this->_vali([
'uid.value' => $this->uuid,
'order_no.require' => '单号不能为空',
]);
$order = $this->app->db->name('ShopOrder')->where($map)->find();
if (empty($order)) $this->error('读取订单失败');
if (in_array($order['status'], [0])) {
$result = $this->app->db->name('ShopOrder')->where($map)->update([
'status' => 0,
'deleted' => 1,
'deleted_remark' => '用户主动删除订单!',
'deleted_datetime' => date('Y-m-d H:i:s'),
]);
if ($result !== false) {
// 触发订单删除事件
$this->app->event->trigger('ShopOrderRemove', $order['order_no']);
// 返回处理成功数据
$this->success('订单删除成功');
} else {
$this->error('订单删除失败');
}
} else {
$this->error('订单不可删除');
}
}
@ -291,21 +334,21 @@ class Order extends Auth
{
$map = $this->_vali([
'uid.value' => $this->uuid,
'order_no.require' => '单号不能为空',
'order_no.require' => '单号不能为空',
]);
$order = $this->app->db->name('ShopOrder')->where($map)->find();
if (empty($order)) $this->error('订单查询失败,请稍候再试!');
if (empty($order)) $this->error('读取订单失败');
if (in_array($order['status'], [4])) {
if ($this->app->db->name('ShopOrder')->where($map)->update(['status' => 5]) !== false) {
// 触发订单确认事件
$this->app->event->trigger('ShopOrderConfirm', $order['order_no']);
// 返回处理成功数据
$this->success('订单确认成功');
$this->success('订单确认成功');
} else {
$this->error('订单确认失败,请稍候再试!');
$this->error('订单确认失败');
}
} else {
$this->error('订单不能确认收货哦~');
$this->error('订单确认失败');
}
}
@ -323,7 +366,7 @@ class Order extends Auth
$query->where($map)->group('status')->select()->each(function ($item) use (&$data) {
$data["t{$item['status']}"] = $item['count'];
});
$this->success('获取状态统计成功', $data);
$this->success('获取统计成功', $data);
}
/**
@ -333,8 +376,8 @@ class Order extends Auth
{
try {
$data = $this->_vali([
'code.require' => '快递编号不能为空',
'number.require' => '配送单号不能为空',
'code.require' => '快递不能为空',
'number.require' => '单号不能为空',
]);
$result = TruckService::instance()->query($data['code'], $data['number']);
empty($result['code']) ? $this->error($result['info']) : $this->success('快递追踪信息', $result);

View File

@ -46,7 +46,7 @@ class NewsService extends Service
foreach ($list as &$vo) $vo['record'] = $items[$vo['code']] ?? [];
/*! 绑定用户数据 */
$colls = 'id,phone,nickname,username,headimg,status';
UserService::instance()->buildByUid($list, 'uid', 'member', $colls);
UserService::instance()->buildByUid($list, 'uid', 'user', $colls);
}
return $list;
}

View File

@ -11,17 +11,6 @@ use think\admin\Service;
*/
class OrderService extends Service
{
/**
* 同步订单支付状态
* @param string $orderno
* @return bool
*/
public function syncAmount(string $orderno): bool
{
//@todo 处理订单支付完成的动作
return true;
}
/**
* 获取随机减免金额
* @return float
@ -50,12 +39,13 @@ class OrderService extends Service
/**
* 绑定订单详情数据
* @param array $data
* @param bool $fromer
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function buildItemData(array &$data = []): array
public function buildItemData(array &$data = [], $fromer = true): array
{
// 关联发货信息
$nobs = array_unique(array_column($data, 'order_no'));
@ -66,8 +56,8 @@ class OrderService extends Service
$items = $query->withoutField('id,uid,status,deleted,create_at')->whereIn('order_no', $nobs)->select()->toArray();
// 关联用户数据
$fields = 'username,phone,nickname,headimg,status';
UserService::instance()->buildByUid($data, 'uid', 'member', $fields);
UserService::instance()->buildByUid($data, 'from', 'fromer', $fields);
UserService::instance()->buildByUid($data, 'uid', 'user', $fields);
if ($fromer) UserService::instance()->buildByUid($data, 'from', 'fromer', $fields);
foreach ($data as &$vo) {
$vo['sales'] = 0;
$vo['truck'] = $trucks[$vo['order_no']] ?? [];

View File

@ -3,6 +3,8 @@
namespace app\data\service;
use app\data\service\payment\AlipayPaymentService;
use app\data\service\payment\BalancePyamentService;
use app\data\service\payment\EmptyPaymentService;
use app\data\service\payment\JoinPaymentService;
use app\data\service\payment\WechatPaymentService;
use think\App;
@ -17,7 +19,11 @@ use think\Exception;
abstract class PaymentService
{
// 汇聚支付通道
// 用户余额支付
const PAYMENT_EMPTY = 'empty';
const PAYMENT_BALANCE = 'balance';
// 汇聚支付参数
const PAYMENT_JOINPAY_GZH = 'joinpay_gzh';
const PAYMENT_JOINPAY_XCX = 'joinpay_xcx';
@ -28,62 +34,76 @@ abstract class PaymentService
const PAYMENT_WECHAT_WAP = 'wechat_wap';
const PAYMENT_WECHAT_QRC = 'wechat_qrc';
// 支付宝支付通道
// 支付宝支付参数
const PAYMENT_ALIAPY_APP = 'alipay_app';
const PAYMENT_ALIPAY_WAP = 'alipay_wap';
const PAYMENT_ALIPAY_WEB = 'alipay_web';
// 支付通道配置
// 支付参数配置
const TYPES = [
// 微信支付配置(不需要的直接注释)
PaymentService::PAYMENT_WECHAT_WAP => [
self::PAYMENT_EMPTY => [
'type' => 'EMPTY',
'name' => '订单无需支付',
'bind' => [],
],
self::PAYMENT_BALANCE => [
'type' => 'BALANCE',
'name' => '账号余额支付',
'bind' => [
UserService::APITYPE_WAP, UserService::APITYPE_WEB,
UserService::APITYPE_WXAPP, UserService::APITYPE_WECHAT,
UserService::APITYPE_IOSAPP, UserService::APITYPE_ANDROID,
],
],
self::PAYMENT_WECHAT_WAP => [
'type' => 'MWEB',
'name' => '微信商户 H5 支付',
'name' => '微信WAP支付',
'bind' => [UserService::APITYPE_WAP],
],
PaymentService::PAYMENT_WECHAT_APP => [
self::PAYMENT_WECHAT_APP => [
'type' => 'APP',
'name' => '微信商户 APP 支付',
'name' => '微信APP支付',
'bind' => [UserService::APITYPE_IOSAPP, UserService::APITYPE_ANDROID],
],
PaymentService::PAYMENT_WECHAT_XCX => [
self::PAYMENT_WECHAT_XCX => [
'type' => 'JSAPI',
'name' => '微信商户 小程序 支付',
'name' => '微信小程序支付',
'bind' => [UserService::APITYPE_WXAPP],
],
PaymentService::PAYMENT_WECHAT_GZH => [
self::PAYMENT_WECHAT_GZH => [
'type' => 'JSAPI',
'name' => '微信商户 公众号 支付',
'name' => '微信公众号支付',
'bind' => [UserService::APITYPE_WECHAT],
],
PaymentService::PAYMENT_WECHAT_QRC => [
self::PAYMENT_WECHAT_QRC => [
'type' => 'NATIVE',
'name' => '微信商户 二维码 支付',
'name' => '微信二维码支付',
'bind' => [UserService::APITYPE_WEB],
],
// 支付宝支持配置(不需要的直接注释)
PaymentService::PAYMENT_ALIPAY_WAP => [
self::PAYMENT_ALIPAY_WAP => [
'type' => '',
'name' => '支付宝WAP支付',
'bind' => [UserService::APITYPE_WAP],
],
PaymentService::PAYMENT_ALIPAY_WEB => [
self::PAYMENT_ALIPAY_WEB => [
'type' => '',
'name' => '支付宝WEB支付',
'bind' => [UserService::APITYPE_WEB],
],
PaymentService::PAYMENT_ALIAPY_APP => [
self::PAYMENT_ALIAPY_APP => [
'type' => '',
'name' => '支付宝APP支付',
'bind' => [UserService::APITYPE_ANDROID, UserService::APITYPE_IOSAPP],
],
// 汇聚支持配置(不需要的直接注释)
PaymentService::PAYMENT_JOINPAY_XCX => [
self::PAYMENT_JOINPAY_XCX => [
'type' => 'WEIXIN_XCX',
'name' => '汇聚小程序支付',
'bind' => [UserService::APITYPE_WXAPP],
],
PaymentService::PAYMENT_JOINPAY_GZH => [
self::PAYMENT_JOINPAY_GZH => [
'type' => 'WEIXIN_GZH',
'name' => '汇聚公众号支付',
'bind' => [UserService::APITYPE_WECHAT],
@ -97,7 +117,7 @@ abstract class PaymentService
protected $app;
/**
* 支付通道编号
* 支付参数编号
* @var string
*/
protected $code;
@ -109,7 +129,7 @@ abstract class PaymentService
protected $type;
/**
* 当前支付通道
* 当前支付参数
* @var array
*/
protected $params;
@ -123,9 +143,9 @@ abstract class PaymentService
/**
* PaymentService constructor.
* @param App $app 当前应用对象
* @param string $code 支付通道编号
* @param string $code 支付参数编号
* @param string $type 支付类型代码
* @param array $params 支付通道配置
* @param array $params 支付参数配置
*/
public function __construct(App $app, string $code, string $type, array $params)
{
@ -140,17 +160,23 @@ abstract class PaymentService
/**
* 根据配置实例支付服务
* @param string $code 支付通道编号
* @param string $code 支付参数编号
* @return JoinPaymentService|WechatPaymentService|AlipayPaymentService
* @throws Exception
*/
public static function instance(string $code): PaymentService
{
if ($code === 'empty') {
$vars = ['code' => 'empty', 'type' => 'empty', 'params' => []];
return static::$driver[$code] = Container::getInstance()->make(EmptyPaymentService::class, $vars);
}
[, $type, $params] = self::config($code);
if (isset(static::$driver[$code])) return static::$driver[$code];
$vars = ['code' => $code, 'type' => $type, 'params' => $params];
// 实例化具体支付通道类型
if (stripos($type, 'alipay_') === 0) {
// 实例化具体支付参数类型
if (stripos($type, 'balance') === 0) {
return static::$driver[$code] = Container::getInstance()->make(BalancePyamentService::class, $vars);
} elseif (stripos($type, 'alipay_') === 0) {
return static::$driver[$code] = Container::getInstance()->make(AlipayPaymentService::class, $vars);
} elseif (stripos($type, 'wechat_') === 0) {
return static::$driver[$code] = Container::getInstance()->make(WechatPaymentService::class, $vars);
@ -161,6 +187,31 @@ abstract class PaymentService
}
}
/**
* 获取支付通道名称
* @param string $type
* @return string
*/
public static function name(string $type): string
{
return self::TYPES[$type]['name'] ?? $type;
}
/**
* 获取支付类型
* @return array
*/
public static function types(): array
{
$types = [];
foreach (self::TYPES as $k => $v) if (isset($v['bind'])) {
if (array_intersect($v['bind'], array_keys(UserService::TYPES))) {
$types[$k] = $v;
}
}
return $types;
}
/**
* 获取通道配置参数
* @param string $code
@ -173,17 +224,17 @@ abstract class PaymentService
try {
if (empty($payment)) {
$map = ['code' => $code, 'status' => 1, 'deleted' => 0];
$payment = app()->db->name('DataPayment')->where($map)->find();
$payment = app()->db->name('ShopPayment')->where($map)->find();
}
if (empty($payment)) {
throw new Exception("支付通道[#{$code}]禁用关闭");
throw new Exception("支付参数[#{$code}]禁用关闭");
}
$params = @json_decode($payment['content'], true);
if (empty($params)) {
throw new Exception("支付通道[#{$code}]配置无效");
throw new Exception("支付参数[#{$code}]配置无效");
}
if (empty(static::TYPES[$payment['type']])) {
throw new Exception("支付通道[@{$payment['type']}]匹配失败");
throw new Exception("支付参数[@{$payment['type']}]匹配失败");
}
return [$payment['code'], $payment['type'], $params];
} catch (\Exception $exception) {
@ -196,12 +247,13 @@ abstract class PaymentService
* @param string $orderNo 订单单号
* @param string $paymentTrade 交易单号
* @param string $paymentAmount 支付金额
* @param string $paymentRemark 支付描述
* @return boolean
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function updateOrder(string $orderNo, string $paymentTrade, string $paymentAmount): bool
public function updateOrder(string $orderNo, string $paymentTrade, string $paymentAmount, $paymentRemark = '在线支付'): bool
{
// 检查订单支付状态
$map = ['order_no' => $orderNo, 'payment_status' => 0, 'status' => 2];
@ -214,14 +266,12 @@ abstract class PaymentService
'payment_code' => $this->code,
'payment_trade' => $paymentTrade,
'payment_amount' => $paymentAmount,
'payment_remark' => $paymentRemark,
'payment_status' => 1,
'payment_remark' => '在线支付',
'payment_datetime' => date('Y-m-d H:i:s'),
];
if (empty($data['payment_type'])) unset($data['payment_type']);
$this->app->db->name('ShopOrder')->where($map)->update($data);
// 调用用户升级机制
OrderService::instance()->syncAmount($order['order_no']);
// 触发订单更新事件
$this->app->event->trigger('ShopOrderPayment', $orderNo);
return true;
@ -235,7 +285,7 @@ abstract class PaymentService
*/
protected function createPaymentAction(string $orderNo, string $paymentTitle, string $paymentAmount)
{
$this->app->db->name('DataPaymentItem')->insert([
$this->app->db->name('ShopPaymentItem')->insert([
'payment_code' => $this->code, 'payment_type' => $this->type,
'order_amount' => $paymentAmount, 'order_name' => $paymentTitle, 'order_no' => $orderNo,
]);
@ -246,15 +296,16 @@ abstract class PaymentService
* @param string $orderNo 商户订单单号
* @param string $paymentTrade 平台交易单号
* @param string $paymentAmount 实际到账金额
* @param string $paymentRemark 平台支付备注
* @return boolean
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function updatePaymentAction(string $orderNo, string $paymentTrade, string $paymentAmount): bool
protected function updatePaymentAction(string $orderNo, string $paymentTrade, string $paymentAmount, string $paymentRemark = '在线支付'): bool
{
// 更新支付记录
data_save('DataPaymentItem', [
data_save('ShopPaymentItem', [
'order_no' => $orderNo,
'payment_code' => $this->code,
'payment_type' => $this->type,
@ -267,7 +318,7 @@ abstract class PaymentService
'payment_type' => $this->type,
]);
// 更新记录状态
return $this->updateOrder($orderNo, $paymentTrade, $paymentAmount);
return $this->updateOrder($orderNo, $paymentTrade, $paymentAmount, $paymentRemark);
}
/**

View File

@ -15,7 +15,7 @@ class UserService extends Service
const APITYPE_WEB = 'web';
const APITYPE_WXAPP = 'wxapp';
const APITYPE_WECHAT = 'wechat';
const APITYPE_IOSAPP = 'ios';
const APITYPE_IOSAPP = 'iosapp';
const APITYPE_ANDROID = 'android';
const TYPES = [
@ -64,8 +64,8 @@ class UserService extends Service
$data = $this->app->db->name('DataUserToken')->where(['uid' => $uuid, 'type' => $type])->where(function ($query) {
$query->where(['tokenv' => ''])->whereOr(['tokenv' => $this->_buildTokenVerify()]);
})->findOrEmpty();
unset($user['deleted'], $user['password']);
$user['token'] = ['token' => $data['token'], 'expire' => $data['time']];
unset($user['deleted'], $user['password']);
return $user;
}
@ -89,43 +89,56 @@ class UserService extends Service
} else {
$uuid = $this->app->db->name('DataUser')->strict(false)->insertGetId($data);
}
if ($force) $this->buildUserToken(intval($uuid), $type);
if ($force) $this->token(intval($uuid), $type);
return $this->get($type, $uuid);
}
/**
* 获取用户数据统计
* @param int $uid 用户UID
* @return array
* 同步刷新用户余额
* @param int $uuid 用户UID
* @param array $nots 排除的订单
* @return array [total,count]
* @throws \think\db\exception\DbException
*/
public function total(int $uid): array
public function balance(int $uuid, array $nots = []): array
{
$query = $this->app->db->name('DataUser');
return ['my_invite' => $query->where(['from' => $uid])->count()];
$total = $this->app->db->name('DataUserBalance')->where(['uid' => $uuid, 'deleted' => 0])->sum('amount');
$total += $this->app->db->name('DataUserBalanceTransfer')->where(['uid' => $uuid, 'deleted' => 0])->sum('amount');
$count = $this->app->db->name('DataUserBalanceTransfer')->where(['from' => $uuid, 'deleted' => 0])->sum('amount');
if (empty($nots)) {
$count += $this->app->db->name('ShopOrder')->whereRaw("uid={$uuid} and status>1")->sum('amount_balance');
$this->app->db->name('DataUser')->where(['id' => $uuid])->update(['balance_total' => $total, 'balance_used' => $count]);
} else {
$count += $this->app->db->name('ShopOrder')->whereRaw("uid={$uuid} and status>1")->whereNotIn('order_no', $nots)->sum('amount_balance');
}
return [$total, $count];
}
/**
* 生成新的用户令牌
* @param int $uid 授权用户
* 检查 TOKEN 是否有效
* @param string $type 接口类型
* @return array [创建状态, 状态描述, 令牌数据]
* @param string $token 认证令牌
* @param array $data 认证数据
* @return array [ 检查状态状态描述用户UID, 有效时间 ]
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function buildUserToken(int $uid, string $type): array
public function check(string $type, string $token, array $data = []): array
{
// 清理历史认证及已过期的认证
$map1 = [['time', '<', $time = time()]];
$map2 = [['uid', '=', $uid], ['type', '=', $type]];
$this->app->db->name('DataUserToken')->whereOr([$map1, $map2])->delete();
// 创建新的用户认证数据
do $map = ['type' => $type, 'token' => md5(uniqid('', true) . rand(100, 999))];
while ($this->app->db->name('DataUserToken')->where($map)->count() > 0);
// 写入接口用户认证数据
$data = array_merge($map, ['uid' => $uid, 'time' => $time + $this->expire, 'tokenv' => $this->_buildTokenVerify()]);
if ($this->app->db->name('DataUserToken')->insert($data) !== false) {
return [1, '刷新认证成功', $data];
if (empty($data)) {
$map = ['type' => $type, 'token' => $token];
$data = $this->app->db->name('DataUserToken')->where($map)->find();
}
if (empty($data) || empty($data['uid'])) {
return [0, '请重新登录,登录认证无效', 0, 0];
} elseif ($data['time'] < time()) {
return [0, '请重新登录,登录认证失效', 0, 0];
} elseif ($token !== 'token' && $data['tokenv'] !== $this->_buildTokenVerify()) {
return [0, '请重新登录,客户端已更换', 0, 0];
} else {
return [0, '刷新认证失败', []];
$this->expire($type, $token);
return [1, '登录验证成功', $data['uid'], $data['time']];
}
}
@ -135,7 +148,7 @@ class UserService extends Service
* @param string $token 授权令牌
* @throws \think\db\exception\DbException
*/
public function expireUserToken(string $type, string $token)
public function expire(string $type, string $token)
{
$map = ['type' => $type, 'token' => $token];
$this->app->db->name('DataUserToken')->where($map)->update([
@ -143,34 +156,6 @@ class UserService extends Service
]);
}
/**
* 检查接口授权 TOKEN 是否有效
* @param string $type 接口类型
* @param string $token 认证令牌
* @param array $data 认证数据
* @return array [ 检查状态状态描述用户UID, 有效时间 ]
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function checkUserToken(string $type, string $token, array $data = []): array
{
if (empty($data)) {
$map = ['type' => $type, 'token' => $token];
$data = $this->app->db->name('DataUserToken')->where($map)->find();
}
if (empty($data) || empty($data['uid'])) {
return [0, '请重新登录,登录认证无效', 0, 0];
} elseif ($data['time'] < time()) {
return [0, '请重新登录,登录认证已失效', 0, 0];
} elseif ($data['tokenv'] !== $this->_buildTokenVerify() && $token !== 'token') {
return [0, '请重新登录,客户端已更换', 0, 0];
} else {
$this->expireUserToken($type, $token);
return [1, '登录验证成功', $data['uid'], $data['time']];
}
}
/**
* 列表绑定用户数据
* @param array $list 原数据列表
@ -188,6 +173,42 @@ class UserService extends Service
return $list;
}
/**
* 获取用户数据统计
* @param int $uuid 用户UID
* @return array
*/
public function total(int $uuid): array
{
$query = $this->app->db->name('DataUser');
return ['my_invite' => $query->where(['from' => $uuid])->count()];
}
/**
* 生成新的用户令牌
* @param int $uuid 授权用户
* @param string $type 接口类型
* @return array [创建状态, 状态描述, 令牌数据]
* @throws \think\db\exception\DbException
*/
public function token(int $uuid, string $type): array
{
// 清理无效认证数据
$map1 = [['time', '<', $time = time()]];
$map2 = [['uid', '=', $uuid], ['type', '=', $type]];
$this->app->db->name('DataUserToken')->whereOr([$map1, $map2])->delete();
// 创建新的认证数据
do $map = ['type' => $type, 'token' => md5(uniqid() . rand(100, 999))];
while ($this->app->db->name('DataUserToken')->where($map)->count() > 0);
// 写入用户认证数据
$data = array_merge($map, ['uid' => $uuid, 'time' => $time + $this->expire, 'tokenv' => $this->_buildTokenVerify()]);
if ($this->app->db->name('DataUserToken')->insert($data) !== false) {
return [1, '刷新认证成功', $data];
} else {
return [0, '刷新认证失败', []];
}
}
/**
* 获取令牌的认证值
* @return string
@ -196,5 +217,4 @@ class UserService extends Service
{
return md5($this->app->request->server('HTTP_USER_AGENT', '-'));
}
}

View File

@ -0,0 +1,67 @@
<?php
namespace app\data\service\payment;
use app\data\service\PaymentService;
use app\data\service\UserService;
use think\admin\extend\CodeExtend;
use think\Exception;
/**
* 账号余额支付参数处理
* Class BalancePyamentService
* @package app\data\service\payment
*/
class BalancePyamentService extends PaymentService
{
/**
* 订单信息查询
* @param string $orderNo
* @return array
*/
public function query(string $orderNo): array
{
return [];
}
/**
* 支付通知处理
* @return string
*/
public function notify(): string
{
return 'SUCCESS';
}
/**
* 创建余额支付
* @param string $openid
* @param string $orderNo
* @param string $paymentAmount
* @param string $paymentTitle
* @param string $paymentRemark
* @param string $paymentReturn
* @return array
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function create(string $openid, string $orderNo, string $paymentAmount, string $paymentTitle, string $paymentRemark, string $paymentReturn = ''): array
{
$order = $this->app->db->name('ShopOrder')->where(['order_no' => $orderNo])->find();
if (empty($order)) throw new Exception("订单不存在");
if ($order['status'] !== 2) throw new Exception("不可发起支付");
// 创建支付行为
$this->createPaymentAction($orderNo, $paymentTitle, $paymentAmount);
// 扣减用户余额
[$total, $used] = UserService::instance()->balance($order['uid'], [$orderNo]);
if ($paymentAmount > $total - $used) throw new Exception("可抵扣余额不足");
$this->app->db->name('ShopOrder')->where(['order_no' => $orderNo])->update(['amount_balance' => $paymentAmount]);
// 更新支付行为
$this->updatePaymentAction($orderNo, CodeExtend::uniqidDate(20), $paymentAmount, '账户余额支付');
// 刷新用户余额
UserService::instance()->balance($order['uid']);
return ['info' => '余额支付完成'];
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace app\data\service\payment;
use app\data\service\PaymentService;
use think\admin\extend\CodeExtend;
use think\Exception;
/**
* 空支付通道
* Class EmptyPaymentService
* @package app\data\service\payment
*/
class EmptyPaymentService extends PaymentService
{
/**
* 订单主动查询
* @param string $orderNo
* @return array
*/
public function query(string $orderNo): array
{
return [];
}
/**
* 支付通知处理
* @return string
*/
public function notify(): string
{
return '';
}
/**
* 创建支付订单
* @param string $openid 会员OPENID
* @param string $orderNo 交易订单单号
* @param string $paymentAmount 交易订单金额(元)
* @param string $paymentTitle 交易订单名称
* @param string $paymentRemark 交易订单描述
* @param string $paymentReturn 支付回跳地址
* @return array
* @throws Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function create(string $openid, string $orderNo, string $paymentAmount, string $paymentTitle, string $paymentRemark, string $paymentReturn = ''): array
{
$order = $this->app->db->name('ShopOrder')->where(['order_no' => $orderNo])->find();
if (empty($order)) throw new Exception("订单不存在");
if ($order['status'] !== 2) throw new Exception("不可发起支付");
// 创建支付行为
$this->createPaymentAction($orderNo, $paymentTitle, $paymentAmount);
// 更新支付行为
$this->updatePaymentAction($orderNo, CodeExtend::uniqidDate(20), $paymentAmount, '无需支付');
return ['info' => '无需支付'];
}
}

View File

@ -1,4 +1,16 @@
<?php
use app\data\command\OrderClear;
use app\data\command\UserBalance;
use think\Console;
Console::starting(function (Console $console) {
if (app()->request->isCli()) {
$console->addCommand(OrderClear::class);
$console->addCommand(UserBalance::class);
}
});
if (!function_exists('show_goods_spec')) {
/**
* 商品规格过滤显示

View File

@ -112,7 +112,7 @@
</thead>
<tbody>
<tr ng-repeat="rows in items track by $index">
<td class="layui-bg-gray" ng-if="td.show" ng-repeat="td in rows" ng-bind="td.name"></td>
<td class="layui-bg-gray nowrap" ng-if="td.show" ng-repeat="td in rows" ng-bind="td.name"></td>
<td class="padding-0">
<label class="padding-0 margin-0">
<input ng-blur="rows[0].sku=setValue(rows[0].key,'sku',$event.target.value)" class="layui-input border-0 padding-left-0 text-center" ng-model="rows[0].sku">
@ -269,7 +269,7 @@
keys.push(item.group + '::' + item.name);
}), rows.every(function (item) {
item.key = keys.join(';;');
item.sku = $rootScope.getValue(item.key, 'sku', getRand(12, 'S'));
item.sku = $rootScope.getValue(item.key, 'sku', getRand(14, 'S'));
item.status = !!$rootScope.getValue(item.key, 'status', 1);
item.market = $rootScope.getValue(item.key, 'market', '0.00');
item.selling = $rootScope.getValue(item.key, 'selling', '0.00');

View File

@ -8,6 +8,7 @@
<!--{if auth("add")}-->
<button data-open='{:url("add")}' class='layui-btn layui-btn-sm layui-btn-primary'>添加商品</button>
<!--{/if}-->
{if isset($type) and $type eq 'index'}
<!--{if auth("remove")}-->
<button data-action='{:url("remove")}' data-rule="code#{key};deleted#1" class='layui-btn layui-btn-sm layui-btn-primary'>删除商品</button>
@ -42,8 +43,8 @@
<button type="button" data-reload class="layui-btn layui-btn-xs">刷 新</button>
</th>
<th class='text-left nowrap'>商品信息</th>
<th></th>
<th></th>
<th class='text-left nowrap'>标签分类</th>
<th class='text-left nowrap'>商品状态</th>
<th></th>
</tr>
</thead>
@ -67,15 +68,20 @@
</div>
</td>
<td class="text-left">
{notempty name='vo.mark'}{foreach $vo.mark as $mark}
<span class="notselect nowrap layui-badge layui-bg-cyan">{$mark}</span>
{/foreach}{/notempty}
</td>
<td class='nowrap'>
销售状态:{eq name='vo.status' value='0'}<span class="layui-badge">已下架</span>{else}<span class="layui-badge layui-bg-green">销售中</span>{/eq}<br>
<div>
<!--{notempty name='clist'}-->
所属分类:{$vo.cate.name|default='-'}<br>
<!--{/notempty}-->
</div>
<div>
{notempty name='vo.mark'}{foreach $vo.mark as $mark}
<span class="notselect nowrap layui-badge layui-bg-cyan">{$mark}</span>
{/foreach}{/notempty}
</div>
</td>
<td class='nowrap'>
<div>销售状态:{eq name='vo.status' value='0'}<span class="layui-badge">已下架</span>{else}<span class="layui-badge layui-bg-green">销售中</span>{/eq}</div>
<div>创建时间:{$vo.create_at|format_datetime}</div>
</td>
<td class='nowrap sub-span-blue'>
<div class="margin-bottom-5">剩余库存 <span>{$vo.stock_total-$vo.stock_sales}</span> 件 ( 已销售 <span>{$vo.stock_sales}</span> 件 )</div>

View File

@ -5,37 +5,61 @@
<span class="color-desc margin-left-5">Goods Name</span>
<div class="layui-input layui-bg-gray">{$vo.name|default=''}</div>
</div>
<div class="layui-form-item">
<div class="relative block">
<span class="color-green font-w7">规格数据</span>
<span class="color-desc margin-left-5">Specification Data</span>
<table class="layui-table" lay-skin="line">
<span class="color-green font-w7">库存数据</span>
<span class="color-desc margin-left-5">Stock Data</span>
<table class="layui-table border-0 margin-0" lay-skin="line">
<colgroup>
<col style="width:auto">
<col style="width:80px">
<col style="width:80px">
<col style="width:80px">
<col style="width:80px">
<col style="width:80px">
<col style="width:99px">
<col style="width:18px">
</colgroup>
<thead>
<tr class="layui-bg-cyan">
<th class="text-left nowrap border-0">商品规格</th>
<th class="text-center nowrap border-0">市场价格</th>
<th class="text-center nowrap border-0">销售价格</th>
<th class="text-center nowrap border-0">库存统计</th>
<th class="text-center nowrap border-0">总销统计</th>
<th class="text-center nowrap border-0">库存剩余</th>
<th class="text-center nowrap border-0">入库数量</th>
<tr class="layui-bg-cyan notselect">
<th class="text-left nowrap">商品规格</th>
<th class="text-center nowrap">市场价格</th>
<th class="text-center nowrap">销售价格</th>
<th class="text-center nowrap">库存统计</th>
<th class="text-center nowrap">总销统计</th>
<th class="text-center nowrap">库存剩余</th>
<th class="text-center nowrap">入库数量</th>
<th class="padding-0 nowrap"></th>
</tr>
</thead>
</table>
<div style="max-height:500px;overflow-y:scroll">
<table class="layui-table margin-0" lay-skin="line">
<colgroup>
<col style="width:auto">
<col style="width:80px">
<col style="width:80px">
<col style="width:80px">
<col style="width:80px">
<col style="width:80px">
<col style="width:99px">
</colgroup>
<tbody>
{foreach $vo.items as $goods}
<tr>
<td class="layui-bg-gray" width="28%">{$goods.goods_spec|show_goods_spec}</td>
<td class="layui-bg-gray text-center" width="12%">¥{$goods.price_market+0}</td>
<td class="layui-bg-gray text-center" width="12%">¥{$goods.price_selling+0}</td>
<td class="layui-bg-gray text-center" width="12%">{$goods.stock_total|default=0}</td>
<td class="layui-bg-gray text-center" width="12%">{$goods.stock_sales|default=0}</td>
<td class="layui-bg-gray text-center" width="12%">{$goods.stock_total-$goods.stock_sales}</td>
<td class="padding-0 nowrap" width="12%">
<td class="layui-bg-gray layui-elip">{$goods.goods_spec|show_goods_spec}</td>
<td class="layui-bg-gray text-center">¥{$goods.price_market+0}</td>
<td class="layui-bg-gray text-center">¥{$goods.price_selling+0}</td>
<td class="layui-bg-gray text-center">{$goods.stock_total|default=0}</td>
<td class="layui-bg-gray text-center">{$goods.stock_sales|default=0}</td>
<td class="layui-bg-gray text-center">{$goods.stock_total-$goods.stock_sales}</td>
<td class="padding-0 nowrap">
<input type="hidden" name="goods_code[]" value="{$goods.goods_code|default=''}">
<input type="hidden" name="goods_spec[]" value="{$goods.goods_spec|default=''}">
<label>
<input class="layui-input text-right border-0 padding-right-30" maxlength="20" data-blur-number="0" name="goods_stock[]" value="0">
<span class="input-right-icon"></span>
<input class="layui-input text-right border-0 padding-right-40" maxlength="20" data-blur-number="0" name="goods_stock[]" value="0">
<span class="input-right-icon layui-bg-gray"></span>
</label>
</td>
</tr>
@ -45,6 +69,8 @@
</div>
</div>
</div>
</div>
<div class="hr-line-dashed"></div>
<div class="layui-form-item text-center">
<button class="layui-btn" type='submit'>确定入库</button>

View File

@ -1,5 +1,11 @@
{extend name="../../admin/view/main"}
{block name="button"}
<!--{if auth("clean")}-->
<button data-queue='{:url("clean")}' class='layui-btn layui-btn-sm layui-btn-primary'>定时清理订单</button>
<!--{/if}-->
{/block}
{block name="content"}
<div class="layui-tab layui-tab-card table-block">
<ul class="layui-tab-title notselect">
@ -41,10 +47,10 @@
</div>
</div>
<div>
<div class="headimg" data-tips-image data-lazy-src="{$vo.member.headimg|default='__ROOT__/static/theme/img/headimg.png'}"></div>
<div class="headimg" data-tips-image data-lazy-src="{$vo.user.headimg|default='__ROOT__/static/theme/img/headimg.png'}"></div>
<div class="inline-block sub-span-blue">
用户昵称:{$vo.member.nickname|default='--'}<br>
用户手机:<span>{$vo.member.phone|default='--'}</span><br>
用户昵称:{$vo.user.nickname|default='--'}<br>
用户手机:<span>{$vo.user.phone|default='--'}</span><br>
</div>
</div>
</td>
@ -57,9 +63,13 @@
{eq name='vo.status' value='5'}<span class="layui-badge layui-badge-middle layui-bg-blue">已完成</span>{/eq}
<div class="inline-block text-middle">
订单单号:<span class="color-blue">{$vo.order_no|default=''}</span><br>
订单金额:<b class="color-blue">{$vo.amount_total+0}</b><span class="color-blue">{if $vo.amount_express>0}(含邮费{$vo.amount_express+0}元){else}(包邮){/if}</span>已支付 <b class="color-blue">{$vo.payment_amount+0}</b><br>
订单总计 <b class="color-blue">{$vo.amount_total+0}</b><span class="color-blue">{if $vo.amount_express>0}(含邮费{$vo.amount_express+0}元){else}(包邮){/if}</span>已支付 <b class="color-blue">{$vo.payment_amount+0}</b><br>
下单时间:{$vo.create_at|format_datetime}<br>
支付时间:{$vo.payment_datetime|format_datetime} {notempty name='vo.pay_type'}<span class="color-blue"> ({$vo.pay_type|default='-'})</span>{/notempty}<br>
<!--{notempty name='vo.payment_status'}-->
支付时间:{$vo.payment_datetime|format_datetime} {notempty name='vo.payment_name'}<span class="color-blue"> ({$vo.payment_name|default='-'})</span>{/notempty}<br>
<!--{else}-->
支付状态:<span class="color-desc">还未支付</span>
<!--{/notempty}-->
</div>
</td>
<td class="nowrap">

View File

@ -5,14 +5,14 @@
<div class="layui-form-item layui-inline">
<label class="layui-form-label">用户手机</label>
<label class="layui-input-inline">
<input name="member_phone" value="{:input('member_phone')}" placeholder="请输入用户手机" class="layui-input">
<input name="user_phone" value="{:input('user_phone')}" placeholder="请输入用户手机" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">用户昵称</label>
<label class="layui-input-inline">
<input name="member_nickname" value="{:input('member_nickname')}" placeholder="请输入用户昵称" class="layui-input">
<input name="user_nickname" value="{:input('user_nickname')}" placeholder="请输入用户昵称" class="layui-input">
</label>
</div>
@ -63,7 +63,7 @@
<label class="layui-form-label">付款状态</label>
<label class="layui-input-inline">
<select class="layui-select" name="payment_status">
<option value=''>- 全部订单 -</option>
<option value=''>-- 全部 --</option>
{foreach ['0'=>'未支付的订单','1'=>'已支付的订单'] as $k=>$v}
{if input('payment_status') eq $k.''}
<option selected value="{$k}">{$v}</option>
@ -74,6 +74,21 @@
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">支付方式</label>
<label class="layui-input-inline">
<select class="layui-select" name="payment_type">
<option value=''>-- 全部 --</option>
{foreach $payments as $k=>$v}
{if input('payment_type') eq $k.''}
<option selected value="{$k}">{$v.name}</option>
{else}
<option value="{$k}">{$v.name}</option>
{/if}{/foreach}
</select>
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">下单时间</label>
<label class="layui-input-inline">
@ -125,8 +140,8 @@
data.forEach(function (item, index) {
data[index] = [
item.order_no,
item.member.phone,
item.member.username || item.member.nickname || '',
item.user.phone,
item.user.username || item.user.nickname || '',
item.payment_trade || '',
item.payment_status ? '已支付' : '未支付',
item.payment_amount || '0.00',

View File

@ -5,23 +5,26 @@
<div class="layui-form-item layui-row layui-col-space10">
<label class="layui-col-xs6 relative block">
<span class="color-green font-w7 label-required-prev">收货人姓名</span>
<span class="color-desc margin-left-5">Consignee Name</span>
<span class="color-desc margin-left-5">User Name</span>
<input class="layui-input" required placeholder="请输入收货姓名" name="address_name" value="{$vo.address_name|default=''}">
</label>
<label class="layui-col-xs6 relative block">
<span class="color-green font-w7 label-required-prev">收货人手机</span>
<span class="color-desc margin-left-5">Consignee mobile</span>
<span class="color-desc margin-left-5">User Mobile</span>
<input class="layui-input" required placeholder="请输入收货人手机" name="address_phone" value="{$vo.address_phone|default=''}">
</label>
<div class="layui-col-xs12 relative block">
<span class="color-green font-w7 label-required-prev">收货所在区域</span>
<span class="color-desc margin-left-5">(原区域:{$vo.address_province|default='--'} {$vo.address_city|default=''} {$vo.address_area|default=''} </span>
<span class="color-desc margin-left-5">(原区域:{$vo.address_province|default='--'} - {$vo.address_city|default=''} - {$vo.address_area|default=''} </span>
<div class="layui-row layui-col-space10">
<label class="layui-col-xs4"><select class="layui-select block full-width" lay-ignore name="form_province"></select></label>
<label class="layui-col-xs4"><select class="layui-select block full-width" lay-ignore name="form_city"></select></label>
<label class="layui-col-xs4"><select class="layui-select block full-width" lay-ignore name="form_area"></select></label>
</div>
</div>
<label class="layui-col-xs12 relative block">
<span class="color-green font-w7 label-required-prev">收货详细地址</span>
<span class="color-desc margin-left-5">(原地址:{$vo.address_content|default=""} )</span>
@ -29,11 +32,12 @@
</label>
</div>
</fieldset>
<fieldset class="margin-top-20">
<legend><span class="layui-badge layui-bg-cyan">快递信息</span> <a class="margin-left-10 layui-badge layui-bg-blue" data-express-query>快递跟踪</a></legend>
<label class="layui-form-item relative block">
<span class="color-green font-w7 label-required-prev">快递配送公司</span>
<span class="color-desc margin-left-5">Express delivery company</span>
<span class="color-desc margin-left-5">Express Company</span>
<select data-truck-code class="layui-select" name="company_code" lay-search>
{foreach $items as $item}
{if isset($vo.company_code) and $vo.company_code eq $item.code_1}
@ -43,25 +47,30 @@
{/if}{/foreach}
</select>
</label>
<label class="layui-form-item relative block">
<span class="color-green font-w7 label-required-prev">快递配送单号</span>
<span class="color-desc margin-left-5">Express delivery number</span>
<span class="color-desc margin-left-5">Express Number</span>
<input data-truck-number name="send_number" required value='{$vo.send_number|default=""}' placeholder="请输入快递配送单号" class="layui-input">
</label>
<label class="layui-form-item relative block">
<span class="color-green font-w7">快递配送描述</span>
<span class="color-desc margin-left-5">Express delivery description</span>
<span class="color-desc margin-left-5">Express Description</span>
<textarea placeholder="请输入快递配送描述" class="layui-textarea" name="send_remark">{$vo.send_remark|default=""}</textarea>
</label>
</fieldset>
</div>
<div class="hr-line-dashed"></div>
{notempty name='vo.order_no'}<input type='hidden' value='{$vo.order_no}' name='order_no'>{/notempty}
{notempty name='vo.send_datetime'}<input type='hidden' value='{$vo.send_datetime}' name='send_datetime'>{/notempty}
<div class="layui-form-item text-center">
<button class="layui-btn" type='submit'>保存数据</button>
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
</div>
<script>
require(['pcasunzips'], function () {
(function (province, city, area) {

View File

@ -0,0 +1,43 @@
<form class="layui-form layui-card margin-bottom-0" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
<div class="layui-card-body padding-left-40">
<label class="layui-form-item relative block">
<span class="color-green font-w7 label-required-prev">发货人姓名</span>
<input class="layui-input" required placeholder="请输入发货姓名" name="name" value="{$vo.name|default=''}">
</label>
<label class="layui-form-item relative block">
<span class="color-green font-w7 label-required-prev">发货人手机</span>
<input class="layui-input" required placeholder="请输入发货人手机" name="phone" value="{$vo.phone|default=''}">
</label>
<div class="layui-form-item relative block">
<span class="color-green font-w7 label-required-prev">发货所在区域</span>
<div class="layui-row layui-col-space10">
<label class="layui-col-xs4"><select class="layui-select block full-width" lay-ignore name="province"></select></label>
<label class="layui-col-xs4"><select class="layui-select block full-width" lay-ignore name="city"></select></label>
<label class="layui-col-xs4"><select class="layui-select block full-width" lay-ignore name="area"></select></label>
</div>
</div>
<label class="layui-form-item relative block">
<span class="color-green font-w7 label-required-prev">发货详细地址</span>
<textarea class="layui-textarea" name="content" required placeholder="请输入发货详细地址">{$vo.content|default=""}</textarea>
</label>
</div>
<div class="hr-line-dashed"></div>
<div class="layui-form-item text-center">
<button class="layui-btn" type='submit'>保存数据</button>
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
</div>
<script>
require(['pcasunzips'], function () {
(function (province, city, area) {
new PCAS("province", "city", "area", province, city, area);
})('{$vo.province|default=""}', '{$vo.city|default=""}', '{$vo.area|default=""}');
});
</script>
</form>

View File

@ -1,5 +1,11 @@
{extend name="../../admin/view/main"}
{block name="button"}
<!--{if auth('config')}-->
<a class="layui-btn layui-btn-sm layui-btn-primary" data-modal="{:url('config')}">发货地址管理</a>
<!--{/if}-->
{/block}
{block name="content"}
<div class="layui-tab layui-tab-card table-block">
<ul class="layui-tab-title notselect">
@ -33,26 +39,27 @@
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
</td>
<td class="nowrap relative">
<div class="headimg" style="width:56px;height:56px" data-tips-image data-lazy-src="{$vo.member.headimg|default='__ROOT__/static/theme/img/headimg.png'}"></div>
<div class="headimg" style="width:56px;height:56px" data-tips-image data-lazy-src="{$vo.user.headimg|default='__ROOT__/static/theme/img/headimg.png'}"></div>
<div class="inline-block sub-span-blue">
用户昵称:<span>{$vo.member.nickname|default='--'}</span><br>
用户手机:<span>{$vo.member.phone|default='--'}</span><br>
订单单号:<span>{$vo.order_no|default='--'}</span><br>
用户昵称:<span>{$vo.user.nickname|default='-'}</span><br>
用户手机:<span>{$vo.user.phone|default='-'}</span><br>
订单单号:<span>{$vo.order_no|default='-'}</span><br>
</div>
</td>
<td class="nowrap">
收货姓名:{$vo.address_name|default='--'}<span class="margin-left-5 color-blue">{$vo.address_phone}</span><br>
收货地址:{$vo.address_province|default='--'}{$vo.address_city}{$vo.address_area}{$vo.address_content}<br>
提交时间:{$vo.address_datetime|format_datetime}<br>
<div>身份证号:{$vo.address_idcode|default='-'}</div>
<div>收货姓名:{$vo.address_name|default='-'}<span class="margin-left-5 color-blue">{$vo.address_phone}</span></div>
<div>收货地址:{$vo.address_province|default='-'}{$vo.address_city}{$vo.address_area}{$vo.address_content}</div>
<div>提交时间:{$vo.address_datetime|format_datetime}</div>
</td>
<td class="nowrap">
{if empty($vo.send_datetime)}
<span class="layui-badge layui-bg-black">未发货</span>
{else}
<span class="layui-badge layui-bg-blue">{$vo.company_name|default='--'}</span>
<span class="layui-badge layui-bg-blue">{$vo.company_name|default='-'}</span>
<a data-title="{$vo.company_name}{$vo.send_number}" data-tips-text="快递追踪查询"
data-modal="{:url('shop_order/truckQuery')}?code={$vo.company_code}&number={$vo.send_number}"
class="layui-badge layui-bg-orange margin-left-5">{$vo.send_number|default='--'}</a>
class="layui-badge layui-bg-orange margin-left-5">{$vo.send_number|default='-'}</a>
<div class="margin-top-5"><b>{$vo.send_datetime|format_datetime} 发货!</b></div>
{/if}
</td>

View File

@ -4,14 +4,14 @@
<div class="layui-form-item layui-inline">
<label class="layui-form-label">用户手机</label>
<label class="layui-input-inline">
<input name="member_phone" value="{:input('member_phone')}" placeholder="请输入用户手机" class="layui-input">
<input name="user_phone" value="{:input('user_phone')}" placeholder="请输入用户手机" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">用户昵称</label>
<label class="layui-input-inline">
<input name="member_nickname" value="{:input('member_nickname')}" placeholder="请输入用户昵称" class="layui-input">
<input name="user_nickname" value="{:input('user_nickname')}" placeholder="请输入用户昵称" class="layui-input">
</label>
</div>
@ -92,21 +92,31 @@
window.form.render();
require(['excel'], function (excel) {
excel.bind(function (data) {
data.forEach(function (item, index) {
data[index] = [
item.order_no, item.member.phone,
item.member.username || item.member.nickname || '',
item.address_name || '', item.address_phone || '',
item.address_province || '', item.address_city || '', item.address_area || '',
item.address_content || '', item.address_datetime || '',
item.company_name || '', item.send_number || '', item.send_datetime || '',
];
});
data.unshift([
'订单单号', '用户手机', '用户姓名', '收货人姓名', '收货人手机', '配送省份', '配送城市',
'配送区域', '配送详细地址', '提交时间', '快递公司', '配送单号', '发货时间'
var rows = [];
data.forEach(function (order) {
order.items.forEach(function (item) {
rows.push([
order.order_no,
item.goods_name,
item.stock_sales,
item.price_selling,
item.total_selling,
'{$address.name|default=""}',
order.truck.address_idcode,
order.truck.address_name,
order.truck.address_phone,
order.truck.address_province,
order.truck.address_city,
order.truck.address_area,
order.truck.address_content,
]);
return data;
})
});
rows.unshift([
'订单号', '物品名称', '数量', '单价', '总额',
'寄件方', '身份证号', '收货人', '电话', '省份', '城市', '区', '地址'
]);
return rows;
}, '订单发货记录');
});
</script>

View File

@ -0,0 +1,89 @@
{extend name="../../admin/view/main"}
{block name='content'}
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
<div class="layui-card-body padding-40">
<label class="layui-form-item relative block">
<span class="color-green font-w7">支付名称</span>
<span class="color-desc margin-left-5">Payment Name</span>
<input class="layui-input" required placeholder="请输入支付名称" maxlength="50" name="name" value="{$vo.name|default=''}"/>
<span class="help-block"><b>必填,</b>请填写支付参数名称通道名称尽量不要重复字符不要太长一般4-6个汉字</span>
</label>
<div class="layui-form-item">
<span class="color-green font-w7 label-required-prev">支付方式</span>
<span class="color-desc margin-left-5">Payment Channel</span>
<label class="block full-width">
{empty name='vo.type'}
<select name="type" class="layui-select" lay-search lay-filter="payment-type">
{foreach $payments as $k=>$v}{if isset($vo.type) and $vo.type eq $k}
<option selected value="{$k}">{$v.name} ( {$v.allow} )</option>
{else}
<option value="{$k}">{$v.name} ( {$v.allow} )</option>
{/if}{/foreach}
</select>
{else}
<select name="type" disabled class="layui-select" lay-filter="payment-type">
{foreach $payments as $k=>$v}{if isset($vo.type) and $vo.type eq $k}
<option selected value="{$k}">{$v.name} ( {$v.allow} )</option>
{else}
<option value="{$k}">{$v.name} ( {$v.allow} )</option>
{/if}{/foreach}
</select>
<input type="hidden" name="type" value="{$vo.type}">
{/empty}
<span class="help-block"><b>必选,</b>请选择预置的支付方式,支付参数创建之后不能修改,请谨慎选择并配置参数</span>
</label>
</div>
<div data-payment-type="wechat">{include file='shop_payment/form_wechat'}</div>
<div data-payment-type="alipay" class="layui-hide">{include file='shop_payment/form_alipay'}</div>
<div data-payment-type="joinpay" class="layui-hide">{include file='shop_payment/form_joinpay'}</div>
<div class="layui-form-item relative layui-hide">
<span class="color-green font-w7">支付描述</span>
<span class="color-desc margin-left-5">Payment Remark</span>
<label class="relative block">
<textarea class="layui-textarea" placeholder="请输入支付描述" name="remark">{$vo.remark|default=''}</textarea>
</label>
</div>
<div class="hr-line-dashed"></div>
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
{notempty name='vo.code'}<input type='hidden' value='{$vo.code}' name='code'>{/notempty}
<div class="layui-form-item text-center">
<button class="layui-btn" type='submit'>保存数据</button>
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-history-back>取消编辑</button>
</div>
</div>
</form>
{/block}
{block name='script'}
<script>
(function () {
layui.form.render();
apply({value: $('select[name=type]').val()});
layui.form.on('select(payment-type)', apply);
function apply(data) {
if (data.value.indexOf('wechat') > -1) {
$('[data-payment-type]').not($('[data-payment-type="wechat"]').removeClass('layui-hide')).addClass('layui-hide');
} else if (data.value.indexOf('alipay') > -1) {
$('[data-payment-type]').not($('[data-payment-type="alipay"]').removeClass('layui-hide')).addClass('layui-hide');
} else if (data.value.indexOf('joinpay') > -1) {
$('[data-payment-type]').not($('[data-payment-type="joinpay"]').removeClass('layui-hide')).addClass('layui-hide');
} else {
$('[data-payment-type]').addClass('layui-hide');
}
}
})();
</script>
{/block}

View File

@ -0,0 +1,18 @@
<label class="layui-form-item block relative">
<span class="color-green font-w7">支付宝商户编号</span>
<span class="color-desc margin-left-5">Alipay Payment Number</span>
<input name="alipay_appid" required placeholder="请输入支付宝商户编号(必填)" value="{$vo.content.alipay_appid|default=''}" class="layui-input">
<span class="help-block">支付宝商户编号,开通企业支付宝的唯一商户编号</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7">支付宝私钥文件内容</span><span class="nowrap color-desc"> 需要填写文件的全部内容 </span>
<textarea name="alipay_private_key" required placeholder="请输入支付宝私钥文件内容(必填)" class="layui-textarea">{$vo.content.alipay_private_key|default=''}</textarea>
<span class="help-block">从商户平台上下载支付证书,解压并取得其中的支付宝私钥文件用记事本打开并复制文件内容填至此处</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7">应用公钥证书文件内容</span><span class="nowrap color-desc"> 需要填写文件的全部内容 </span>
<textarea name="alipay_public_key" required placeholder="请输入应用公钥证书文件内容(必填)" class="layui-textarea">{$vo.content.alipay_public_key|default=''}</textarea>
<span class="help-block">从商户平台上下载支付证书,解压并取得其中的应用公钥证书文件用记事本打开并复制文件内容填至此处</span>
</label>

View File

@ -0,0 +1,23 @@
<label class="layui-form-item block relative">
<span class="color-green font-w7">商户绑定的公众号</span>
<input name="joinpay_appid" required placeholder="请输入商户绑定的公众号(必填)" value="{$vo.content.joinpay_appid|default=''}" class="layui-input">
<span class="help-block">商户绑定的公众号授权给汇聚支付平台的公众号APPID</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7">汇聚支付报备商户号</span>
<input name="joinpay_trade" required maxlength="15" placeholder="请输入汇聚支付报备商户号(必填)" value="{$vo.content.joinpay_trade|default=''}" class="layui-input">
<span class="help-block">汇聚支付报备商户号,需要联系汇聚支付平台的客服获取,通常以 777 开头的15位数字</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7 margin-right-10">汇聚支付的商户编号</span>
<input name="joinpay_mch_id" required maxlength="15" placeholder="请输入汇聚支付的商户编号(必填)" value="{$vo.content.joinpay_mch_id|default=''}" class="layui-input">
<span class="help-block">汇聚支付的商户编号,需要在汇聚支付平台商户中心获取,通常是以 888 开头的15位数字</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7 margin-right-10">汇聚支付的商户密钥</span>
<input name="joinpay_mch_key" required maxlength="32" placeholder="请输入汇聚支付的商户密钥(必填)" value="{$vo.content.joinpay_mch_key|default=''}" class="layui-input">
<span class="help-block">汇聚支付的商户密钥需要在汇聚支付平台商户中心的密钥管理处获取通常为32位字符串</span>
</label>

View File

@ -0,0 +1,32 @@
<label class="layui-form-item block relative">
<span class="color-green font-w7">绑定公众号</span>
<span class="color-desc margin-left-5">Bind WeChat Appid</span>
<input name="wechat_appid" required maxlength="18" pattern="^wx[0-9a-z]{16}$" placeholder="请输入18位绑定公众号必填" value="{$vo.content.wechat_appid|default=''}" class="layui-input">
<span class="help-block">公众号APPID微信商户绑定的服务号APPID或小程序APPID</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7 margin-right-10">微信商户号</span>
<span class="color-desc margin-left-5">WeChat Payment Number</span>
<input name="wechat_mch_id" required placeholder="请输入微信商户号(必填)" value="{$vo.content.wechat_mch_id|default=''}" class="layui-input">
<span class="help-block">微信商户编号,需要在微信商户平台获取,微信商户号 与 公众号APPID 匹配</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7 margin-right-10">微信商户密钥</span>
<span class="color-desc margin-left-5">WeChat Payment Secret Key</span>
<input name="wechat_mch_key" required maxlength="32" pattern=".{32}" placeholder="请输入32位微信商户密钥必填" value="{$vo.content.wechat_mch_key|default=''}" class="layui-input">
<span class="help-block">微信商户密钥,需要在微信商户平台操作设置密码并获取密钥,建议定期更换密钥</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7">微信商户密钥文件内容</span><span class="nowrap color-desc"> 需要填写文件的全部内容 </span>
<textarea name="wechat_mch_key_text" placeholder="请输入微信KEY密钥内容" class="layui-textarea">{$vo.content.wechat_mch_key_text|default=''}</textarea>
<span class="help-block">从商户平台上下载支付证书,解压并取得其中的 apiclient_key.pem 用记事本打开并复制文件内容填至此处</span>
</label>
<label class="layui-form-item block relative">
<span class="color-green font-w7">微信商户证书文件内容</span><span class="nowrap color-desc"> 需要填写文件的全部内容 </span>
<textarea name="wechat_mch_cert_text" placeholder="请输入微信CERT证书内容" class="layui-textarea">{$vo.content.wechat_mch_cert_text|default=''}</textarea>
<span class="help-block">从商户平台上下载支付证书,解压并取得其中的 apiclient_cert.pem 用记事本打开并复制文件内容填至此处</span>
</label>

View File

@ -0,0 +1,70 @@
{extend name="../../admin/view/main"}
{block name="button"}
<!--{if auth("add")}-->
<button data-open='{:url("add")}' class='layui-btn layui-btn-sm layui-btn-primary'>添加支付</button>
<!--{/if}-->
<!--{if auth("remove")}-->
<button data-action='{:url("remove")}' data-rule="id#{key}" data-confirm="确定要删除这些支付吗?" class='layui-btn layui-btn-sm layui-btn-primary'>删除支付</button>
<!--{/if}-->
{/block}
{block name='content'}
<div class="think-box-shadow">
{include file='shop_payment/index_search'}
<table class="layui-table margin-top-10" lay-skin="line">
{notempty name='list'}
<thead>
<tr>
<th class='list-table-check-td think-checkbox'>
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
</th>
<th class='list-table-sort-td'>
<button type="button" data-reload class="layui-btn layui-btn-xs">刷 新</button>
</th>
<th class="text-left nowrap">通道名称</th>
<th class="text-left nowrap">通道编号</th>
<th class="text-left nowrap">支付方式</th>
<th class="text-left nowrap">使用状态</th>
<th class="text-left nowrap">创建时间</th>
<th class="text-left nowrap"></th>
</tr>
</thead>
{/notempty}
<tbody>
{foreach $list as $key=>$vo}
<tr data-dbclick>
<td class='list-table-check-td think-checkbox'>
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
</td>
<td class='list-table-sort-td'>
<label><input data-action-blur="{:request()->url()}" data-value="id#{$vo.id};action#sort;sort#{value}" data-loading="false" value="{$vo.sort}" class="list-sort-input"></label>
</td>
<td class="text-left nowrap">{$vo.name|default=''}</td>
<td class="text-left nowrap">{$vo.code|default=''}</td>
<td class="text-left nowrap">{$types[$vo.type]['name']??$vo.type}</td>
<td>{if $vo.status eq 0}<span class="color-red">已禁用</span>{elseif $vo.status eq 1}<span class="color-green">已激活</span>{/if}</td>
<td class="text-left nowrap">{$vo.create_at|format_datetime}</td>
<td class='text-left nowrap'>
<!--{if auth("edit")}-->
<a data-dbclick class="layui-btn layui-btn-sm" data-open="{:url('edit')}?id={$vo.id}">编 辑</a>
<!--{/if}-->
<!--{if auth("state") and $vo.status eq 1}-->
<a class="layui-btn layui-btn-sm layui-btn-warm" data-action="{:url('state')}" data-value="id#{$vo.id};status#0">禁 用</a>
<!--{elseif auth("state") and $vo.status eq 0}-->
<a class="layui-btn layui-btn-sm layui-btn-warm" data-action="{:url('state')}" data-value="id#{$vo.id};status#1">激 活</a>
<!--{/if}-->
<!--{if auth("remove")}-->
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该支付吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}">删 除</a>
<!--{/if}-->
</td>
</tr>
{/foreach}
</tbody>
</table>
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
</div>
{/block}

View File

@ -0,0 +1,54 @@
<fieldset>
<legend>条件搜索</legend>
<form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
<div class="layui-form-item layui-inline">
<label class="layui-form-label">支付名称</label>
<label class="layui-input-inline">
<input name="name" value="{:input('name','')}" placeholder="请输入支付名称" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">支付方式</label>
<div class="layui-input-inline">
<select class="layui-select" name="type">
<option value="">-- 全部 --</option>
{foreach $types as $k=>$v}
{if $k eq input('type')}
<option selected value="{$k}">{$v.name}</option>
{else}
<option value="{$k}">{$v.name}</option>
{/if}{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">使用状态</label>
<div class="layui-input-inline">
<select class="layui-select" name="status">
<option value="">-- 全部 --</option>
{foreach ['已禁用的记录','已激活的记录'] as $k=>$v}
{if $k.'' eq input('status')}
<option selected value="{$k}">{$v}</option>
{else}
<option value="{$k}">{$v}</option>
{/if}{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">创建时间</label>
<label class="layui-input-inline">
<input data-date-range name="create_at" value="{:input('create_at','')}" placeholder="请选择创建时间" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<button class="layui-btn layui-btn-primary"><i class="layui-icon">&#xe615;</i> 搜 索</button>
</div>
</form>
<script>window.form.render()</script>
</fieldset>

View File

@ -4,15 +4,19 @@
<!--{if auth("synchronize") and $type eq 'index'}-->
<button data-load='{:url("synchronize")}' data-confirm="确定要同步快递公司数据吗?" class='layui-btn layui-btn-sm layui-btn-primary'>同步公司</button>
<!--{/if}-->
<!--{if auth("add") and $type eq 'index'}-->
<button data-modal='{:url("add")}' data-title="添加快递公司" class='layui-btn layui-btn-sm layui-btn-primary'>添加公司</button>
<!--{/if}-->
<!--{if auth("state") and $type eq 'index'}-->
<button data-action='{:url("state")}' data-confirm="确定要禁用快递公司?" data-rule="id#{key};status#0" class='layui-btn layui-btn-sm layui-btn-primary'>批量禁用</button>
<!--{/if}-->
<!--{if auth("state") and $type eq 'recycle'}-->
<button data-action='{:url("state")}' data-rule="id#{key};status#1" class='layui-btn layui-btn-sm layui-btn-primary'>批量启用</button>
<!--{/if}-->
<!--{if auth("remove") and $type eq 'recycle'}-->
<button data-action='{:url("remove")}' data-csrf="{:systoken('remove')}" data-rule="id#{key}" class='layui-btn layui-btn-sm layui-btn-primary'>批量删除</button>
<!--{/if}-->
@ -56,9 +60,7 @@
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
</td>
<td class='list-table-sort-td'>
<label>
<input data-action-blur="{:request()->url()}" data-value="id#{$vo.id};action#sort;sort#{value}" data-loading="false" value="{$vo.sort}" class="list-sort-input">
</label>
<label><input data-action-blur="{:request()->url()}" data-value="id#{$vo.id};action#sort;sort#{value}" data-loading="false" value="{$vo.sort}" class="list-sort-input"></label>
</td>
<td class='text-left nowrap'>{$vo.name|default=''}</td>
<td class='text-center nowrap'>{$vo.code_1|default='-'}</td>
@ -69,11 +71,13 @@
<!--{if auth("edit") and $type eq 'index'}-->
<a data-dbclick class="layui-btn layui-btn-sm" data-title="编辑快递公司" data-modal='{:url("edit")}?id={$vo.id}'>编 辑</a>
<!--{/if}-->
<!--{if $vo.status eq 1 and auth("state")}-->
<a class="layui-btn layui-btn-warm layui-btn-sm" data-action="{:url('state')}" data-value="id#{$vo.id};status#0">禁 用</a>
<!--{elseif auth("state")}-->
<a class="layui-btn layui-btn-warm layui-btn-sm" data-action="{:url('state')}" data-value="id#{$vo.id};status#1">激 活</a>
<!--{/if}-->
<!--{if auth("remove") and $type eq 'recycle'}-->
<a class="layui-btn layui-btn-danger layui-btn-sm" data-confirm="确定要删除数据吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}">删 除</a>
<!--{/if}-->

View File

@ -34,9 +34,11 @@
<button class="layui-btn" ng-click="Confirm()">确定修改</button>
</div>
</div>
<label class="layui-hide">
<textarea class="layui-textarea" id="RegionData">{$citys|json_encode|raw}</textarea>
</label>
<script>
require(['angular'], function () {
var app = angular.module("TruckForm", []).run(callback);

View File

@ -35,9 +35,7 @@
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
</td>
<td class='list-table-sort-td'>
<label>
<input data-action-blur="{:request()->url()}" data-value="id#{$vo.id};action#sort;sort#{value}" data-loading="false" value="{$vo.sort}" class="list-sort-input">
</label>
<label><input data-action-blur="{:request()->url()}" data-value="id#{$vo.id};action#sort;sort#{value}" data-loading="false" value="{$vo.sort}" class="list-sort-input"></label>
</td>
<td class='text-left nowrap'>{$vo.code|default=''}</td>
<td class='text-left nowrap'>{$vo.name|default=''}</td>
@ -48,9 +46,9 @@
<a data-dbclick class="layui-btn layui-btn-sm" data-title="编辑快递公司" data-open='{:url("edit")}?code={$vo.code}'>编 辑</a>
<!--{/if}-->
<!--{if $vo.status eq 1 and auth("state")}-->
<!--{if auth("state") and $vo.status eq 1}-->
<a class="layui-btn layui-btn-warm layui-btn-sm" data-action="{:url('state')}" data-value="code#{$vo.code};status#0">禁 用</a>
<!--{elseif auth("state")}-->
<!--{elseif auth("state") and $vo.status eq 0}-->
<a class="layui-btn layui-btn-warm layui-btn-sm" data-action="{:url('state')}" data-value="code#{$vo.code};status#1">激 活</a>
<!--{/if}-->

View File

@ -12,6 +12,7 @@
</th>
<th class='nowrap'>用户信息</th>
<th class='nowrap'>推荐人信息</th>
<th class='nowrap'>余额信息</th>
<th class='nowrap'>注册时间</th>
<th class='nowrap'></th>
</tr>
@ -49,11 +50,20 @@
<div class="color-desc">没有推荐人</div>
{/notempty}
</td>
<td class="nowrap sub-span-blue">
<div>余额统计:累计充值 <span>{$vo.balance_total+0}</span> 元,已使用 <span>{$vo.balance_used+0}</span></div>
<div>奖励统计:共奖励金额 <span>{$vo.amount_total+0}</span> 元,已提现 <span>{$vo.amount_used+0}</span></div>
</td>
<td class="nowrap">
使用状态:{if $vo.status eq 0}<b class="color-red margin-right-5">已冻结</b>{elseif $vo.status eq 1}<b class="color-green margin-right-5">已激活</b>{/if}<br>
注册时间:{$vo.create_at|format_datetime}
</td>
<td class="nowrap">
<!--{if auth("user_balance/add")}-->
<a class="layui-btn layui-btn-sm layui-btn-primary" data-modal="{:url('user_balance/add')}?uid={$vo.id}">余额充值</a>
<!--{/if}-->
<!--{if auth("state") and $vo.status eq 1}-->
<a class="layui-btn layui-btn-sm layui-btn-danger" data-action="{:url('state')}" data-value="id#{$vo.id};status#0">冻结账号</a>
<!--{/if}-->

View File

@ -0,0 +1,70 @@
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
<div class="layui-card-body padding-left-40">
<fieldset class="layui-form-item">
<legend>用户资料</legend>
<div class="layui-row layui-col-space15">
<div class="layui-col-xs3">
<div class="layui-table">
<div class="headimg WechatUserHead" data-tips-image data-lazy-src="{$user.headimg|default='__ROOT__/static/theme/img/headimg.png'}"></div>
</div>
</div>
<div class="layui-col-xs9">
<label class="layui-form-item relative block">
<span class="color-green font-w7">微信昵称</span>
<span class="color-desc margin-left-5">Wechat Nickname</span>
<input data-bind="nickname" class="layui-input layui-bg-gray" readonly required placeholder="请使用微信扫码登录" value="{$user.nickname|default=''}"/>
</label>
<label class="relative block">
<span class="color-green font-w7">微信标识</span>
<span class="color-desc margin-left-5">Wechat Openid</span>
<input data-bind="openid" class="layui-input layui-bg-gray" readonly required placeholder="请使用微信扫码登录" value="{$user.openid2|default=''}"/>
</label>
</div>
</div>
</fieldset>
<label class="layui-form-item relative block">
<span class="color-green font-w7">充值单号</span>
<span class="color-desc margin-left-5">Code</span>
<input class="layui-input layui-bg-gray" readonly required placeholder="请输入充值单号" name="name" value="{$vo.code|default=''}"/>
</label>
<label class="layui-form-item relative block">
<span class="color-green font-w7">充值名称</span>
<span class="color-desc margin-left-5">Name</span>
<input class="layui-input" required placeholder="请输入充值名称" name="name" value="{$vo.name|default='后台充值'}"/>
</label>
<label class="layui-form-item relative block">
<span class="color-green font-w7">充值金额</span>
<span class="color-desc margin-left-5">Amount</span>
<input class="layui-input" data-blur-number="2" required placeholder="请输入充值金额" name="amount" value="{$vo.amount|default='0.00'}"/>
</label>
<div class="layui-form-item relative block">
<span class="color-green font-w7">充值备注</span>
<span class="color-desc margin-left-5">Remark</span>
<label class="relative block">
<textarea class="layui-textarea" placeholder="请输入充值备注" name="remark">{$vo.remark|default=''}</textarea>
</label>
</div>
</div>
<div class="hr-line-dashed"></div>
<input type='hidden' value='{$vo.uid|default=$user.id}' name='uid'>
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
<div class="layui-form-item text-center">
<button class="layui-btn" type='submit'>保存数据</button>
<button class="layui-btn layui-btn-danger" type='button' data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
</div>
</form>
<style>
.WechatUserHead {
width: 138px !important;
height: 138px !important;
}
</style>

View File

@ -0,0 +1,63 @@
{extend name="../../admin/view/main"}
{block name="button"}
<!--{if auth("remove")}-->
<button data-action='{:url("remove")}' data-rule="id#{key}" data-confirm="确定要删除这些充值记录吗?" class='layui-btn layui-btn-sm layui-btn-primary'>删除充值</button>
<!--{/if}-->
{/block}
{block name="content"}
<div class="think-box-shadow">
{include file='user_balance/index_search'}
<table class="layui-table margin-top-10" lay-skin="line">
{notempty name='list'}
<thead>
<tr>
<th class='list-table-check-td think-checkbox'>
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
</th>
<th class='text-left nowrap'>用户信息</th>
<th class='text-left nowrap'>充值金额</th>
<th class='text-left nowrap'>充值描述</th>
<th class='text-left nowrap'>操作用户</th>
<th></th>
</tr>
</thead>
{/notempty}
<tbody>
{foreach $list as $key=>$vo}
<tr>
<td class='list-table-check-td think-checkbox'>
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
</td>
<td class="nowrap">
<div class="headimg" data-tips-image data-lazy-src="{$vo.user.headimg|default='__ROOT__/static/theme/img/headimg.png'}"></div>
<div class="inline-block sub-span-blue">
用户昵称:{$vo.user.nickname|default='--'}<br>
用户手机:<span>{$vo.user.phone|default='--'}</span><br>
</div>
</td>
<td class="nowrap sub-span-blue">
<div>充值金额:<span>{$vo.amount+0}</span></div>
<div>充值单号:{$vo.code|default='-'}</div>
</td>
<td class="nowrap">
<div>充值名称:{$vo.name|default='-'}</div>
<div>充值备注:{$vo.remark|default='-'}</div>
</td>
<td class="nowrap">
<div>操作账号:{$vo.create_byname|default=''}</div>
<div>操作时间:{$vo.create_at|default=''}</div>
</td>
<td class="nowrap">
<!--{if auth("remove")}-->
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除数据吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}">删 除</a>
<!--{/if}-->
</td>
</tr>
{/foreach}
</tbody>
</table>
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
</div>
{/block}

View File

@ -0,0 +1,30 @@
<fieldset>
<legend>条件搜索</legend>
<form class="layui-form layui-form-pane form-search" action="{$request->url()}" onsubmit="return false" method="get" autocomplete="off">
<div class="layui-form-item layui-inline">
<label class="layui-form-label">用户手机</label>
<label class="layui-input-inline">
<input name="user_phone" value="{:input('user_phone')}" placeholder="请输入用户手机" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">用户昵称</label>
<label class="layui-input-inline">
<input name="user_nickname" value="{:input('user_nickname')}" placeholder="请输入用户昵称" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">充值时间</label>
<div class="layui-input-inline">
<input data-date-range name="create_at" value="{:input('create_at','')}" placeholder="请选择充值时间" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-inline">
<button class="layui-btn layui-btn-primary"><i class="layui-icon">&#xe615;</i> 搜 索</button>
</div>
</form>
<script>form.render()</script>
</fieldset>

View File

@ -0,0 +1,40 @@
{extend name="../../admin/view/main"}
{block name='content'}
<form class="layui-form layui-card" action="{:request()->url()}" data-auto="true" method="post" autocomplete="off">
<div class="layui-card-body padding-40">
<label class="layui-form-item relative block">
<span class="color-green font-w7">通知标题</span>
<span class="color-desc margin-left-5">Notify Title</span>
<input required name="name" value='{$vo.name|default=""}' placeholder="请输入通知标题" class="layui-input">
</label>
<div class="layui-form-item relative block">
<span class="color-green font-w7 label-required-prev">通知内容</span>
<span class="color-desc margin-left-5">Notify Content</span>
<label class="relative block">
<textarea class="layui-textarea" placeholder="请输入通知内容" name="content">{$vo.content|default=''}</textarea>
</label>
</div>
<div class="hr-line-dashed"></div>
{notempty name='vo.id'}<input type='hidden' value='{$vo.id}' name='id'>{/notempty}
{notempty name='vo.code'}<input type='hidden' value='{$vo.code}' name='code'>{/notempty}
<div class="layui-form-item text-center">
<button type="submit" class="layui-btn">保存数据</button>
<button type='button' class="layui-btn layui-btn-danger" data-confirm="确定要取消编辑吗?" data-close>取消编辑</button>
</div>
</div>
</form>
<script>
require(['ckeditor'], function () {
window.createEditor('[name=content]', {height: 300});
});
</script>
{/block}

View File

@ -0,0 +1,69 @@
{extend name="../../admin/view/main"}
{block name="button"}
<!--{if auth("add")}-->
<button data-open='{:url("add")}' class='layui-btn layui-btn-sm layui-btn-primary'>添加通知</button>
<!--{/if}-->
<!--{if auth("remove")}-->
<button data-action='{:url("remove")}' data-rule="id#{key}" data-confirm="确定要删除这些通知吗?" class='layui-btn layui-btn-sm layui-btn-primary'>删除通知</button>
<!--{/if}-->
{/block}
{block name='content'}
<div class="think-box-shadow table-block">
{include file='user_notify/index_search'}
<table class="layui-table margin-top-10" lay-skin="line">
{notempty name='list'}
<thead>
<tr>
<th class='list-table-check-td think-checkbox'>
<label><input data-auto-none data-check-target='.list-check-box' type='checkbox'></label>
</th>
<th class='list-table-sort-td'>
<button type="button" data-reload class="layui-btn layui-btn-xs">刷 新</button>
</th>
<th class="text-left nowrap">通知标题</th>
<th class="text-left nowrap">通知状态</th>
<th class="text-left nowrap">创建时间</th>
<th class="text-left nowrap"></th>
</tr>
</thead>
{/notempty}
<tbody>
{foreach $list as $key=>$vo}
<tr>
<td class='list-table-check-td think-checkbox'>
<label><input class="list-check-box" value='{$vo.id}' type='checkbox'></label>
</td>
<td class='list-table-sort-td'>
<label><input data-action-blur="{:request()->url()}" data-value="id#{$vo.id};action#sort;sort#{value}" data-loading="false" value="{$vo.sort}" class="list-sort-input"></label>
</td>
<td class="text-left nowrap">{$vo.name|default=''}</td>
<td class="text-left nowrap">{if $vo.status eq 0}<span class="color-red">已禁用</span>{elseif $vo.status eq 1}<span class="color-green">已激活</span>{/if}</td>
<td class="text-left nowrap">{$vo.create_at|format_datetime}</td>
<td class='text-left nowrap'>
<!--{if auth("edit")}-->
<a data-dbclick class="layui-btn layui-btn-sm" data-title="编辑系统通知" data-open="{:url('edit')}?id={$vo.id}">编 辑</a>
<!--{/if}-->
<!--{if auth("state") and $vo.status eq 1}-->
<a class="layui-btn layui-btn-sm layui-btn-warm" data-action="{:url('state')}" data-value="id#{$vo.id};status#0">禁 用</a>
<!--{elseif auth("state") and $vo.status eq 0}-->
<a class="layui-btn layui-btn-sm layui-btn-warm" data-action="{:url('state')}" data-value="id#{$vo.id};status#1">激 活</a>
<!--{/if}-->
<!--{if auth("remove")}-->
<a class="layui-btn layui-btn-sm layui-btn-danger" data-confirm="确定要删除该通知吗?" data-action="{:url('remove')}" data-value="id#{$vo.id}">删 除</a>
<!--{/if}-->
</td>
</tr>
{/foreach}
</tbody>
</table>
{empty name='list'}<span class="notdata">没有记录哦</span>{else}{$pagehtml|raw|default=''}{/empty}
</div>
{/block}

View File

@ -0,0 +1,39 @@
<fieldset>
<legend>条件搜索</legend>
<form class="layui-form layui-form-pane form-search" action="{:request()->url()}" onsubmit="return false" method="get" autocomplete="off">
<div class="layui-form-item layui-inline">
<label class="layui-form-label">通知标题</label>
<label class="layui-input-inline">
<input name="name" value="{:input('name','')}" placeholder="请输入通知标题" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">使用状态</label>
<div class="layui-input-inline">
<select class="layui-select" name="status">
<option value=''>-- 全部 --</option>
{foreach ['显示禁止的通知', '显示正常的通知'] as $k=>$v}
{if $k.'' eq input('status')}
<option selected value="{$k}">{$v}</option>
{else}
<option value="{$k}">{$v}</option>
{/if}{/foreach}
</select>
</div>
</div>
<div class="layui-form-item layui-inline">
<label class="layui-form-label">创建时间</label>
<label class="layui-input-inline">
<input data-date-range name="create_at" value="{:input('create_at','')}" placeholder="请选择创建时间" class="layui-input">
</label>
</div>
<div class="layui-form-item layui-inline">
<button class="layui-btn layui-btn-primary"><i class="layui-icon">&#xe615;</i> 搜 索</button>
</div>
</form>
<script>form.render()</script>
</fieldset>

View File

@ -28,7 +28,7 @@ return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
'hostname' => 'server.cuci.cc',
// 数据库名
'database' => 'admin_v6',
// 用户名