Commit db954948 authored by CHINAMI-OOGFOG1\Administrator's avatar CHINAMI-OOGFOG1\Administrator

Merge branch 'dev' of http://rungit.jxdsy.cn:10000/sugar/jwhx into dev

# Conflicts:
#	modules/Order/app/Services/RefundService.php
#	modules/Wechat/app/Services/PayService.php
#	resources/admin/src/config/index.js
#	resources/admin/src/pages/order/exchange/index.vue
parents 5f30bc68 e1caa842
......@@ -33,3 +33,29 @@ SentOS管理系统是一个基于Laravel + Vue 开发的后台管理系统,主
- [x] 配置管理 参数的管理
- [x] 字典管理 字典数据管理
- [x] 操作日志 后台用户操作记录
注意:
unlink public/storage 删除现有的链接
php artisan storage:link 重新创建软链接访问图片
ln -s /www/wwwroot/jwhx.xicheda.cn/resources/attachs public/attachs 创建一个新的链接指向不同的目录
ls -l public/storage 检查是否存在链接
php artisan queue:work 命令启动一个队列工作进程(用于事件监听)
php artisan queue:work --daemon
清理和优化配置缓存
php artisan config:cache
清理和优化路由缓存
php artisan route:cache
清理和优化视图缓存
php artisan view:cache
清理日志文件
php artisan log:clear
注意:修改生成缓存文件权限
-----BEGIN CERTIFICATE-----
MIIEFDCCAvygAwIBAgIUQg/xTpir1cQyxxIQAZpCI1xWFsYwDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
Q0EwHhcNMjQwODA2MDkxMTU5WhcNMjkwODA1MDkxMTU5WjBuMRgwFgYDVQQDDA9U
ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl
bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGEwJDTjERMA8GA1UEBwwIU2hlblpo
ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPdcXZvCKERRiBqSic
HyCgj7h6/vJ/ofmPHOsNrxpEcJSKgQH/LkFdb6Ze5I4VwM75Hvg1+GJEECpkFV9r
y8b0NADroG6uBprJZ1FQN/lohYglXeGM60G2deEvw6iXUoebg5ZRm5ISiY+U+A0I
aqF4QvBU9EZBbMQVagMkqbPfEboOn9vZvFoRrCFCqIQScUmE8MsXCPvvmYZm8u9q
vAl5/UXD/HZMTnybUsrQQvxoKyZDJQQgOQPv05zhRoA1vCwidfuZcUD48pSj3IUu
oU34lz8HBKDMDrt0mMTeAoKGW5/jMFkcVDI5v8BKUstnPA44Bv5+3W09zjegmARx
sPNTAgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB
kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv
aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4
RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0
MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAVaZ+7FM6uSZoyumTYZ5WyWsvDYAcNQl/
oMaq8vRa7MDDi2pWiZGg0g0100vXj+JEwFBGNRck4PQM+iO4BLVPwjHE7d39QI7Z
VtzC3+z4jNEXjJ0hhH/N4PJqkM3k/+DO7UgUMCrwRFZfCBNMqt3MYSbmdAYbPXf7
axfr+vUB9tzyVjZ5LshVSmzN/H1bdvREeg40dPJHftSwGAH2WKwQCODLZQ9uIEFP
zygbj/Tupn+XHptRcpPFmhhOqlQCfMrl85qSsKuDFHaJJuQypLr3p5rN3wdLw4mZ
jjWmd4NAYqW+fm4pW96RMQOAVjba/+xDGNCDleIdJ+5hRxumDL7hcg==
-----END CERTIFICATE-----
\ No newline at end of file
......@@ -25,6 +25,7 @@ return [
// 商户证书
'private_key' => __DIR__ . '/certs/apiclient_key.pem',
'certificate' => __DIR__ . '/certs/apiclient_cert.pem',
'public_key' => __DIR__ . '/certs/public_cert_key.pem',
// v3 API 秘钥
'secret_key' => '60ed9440d9077499f0507471c933e563',
......
......@@ -38,7 +38,7 @@ class GoodsBlance implements ShouldQueue{
}
// 积分商品
if ($goods->goods_type == 0){
app(ScoreService::class)->createScore(order_id: $item->id, member_id: $member->uid, amount: $goods->score, type: 'income', remark: '积分商品购买积分');
app(ScoreService::class)->createScore(store_id: $item->store_id, order_id: $item->id, member_id: $member->uid, amount: $goods->score, type: 'income', account_type: 'order', remark: '积分商品购买积分');
// 更新会员等级
if ($member->level_id < $goods->level_id){
......
......@@ -19,7 +19,7 @@ class Goods extends BaseModel {
protected $table = 'goods';
protected $fillable = [
'title', 'user_id', 'brand_id', 'description', 'tags', 'goods_type','cover', 'images', 'price', 'original_price',
'service_amount', 'master_amount', 'partner_amount', 'is_partner', 'operate', 'content', 'status'
'service_amount', 'master_amount', 'partner_amount', 'is_partner', 'operate', 'content', 'status','goods_sn'
];
// protected $hidden = ['deleted_at'];
......
......@@ -13,7 +13,7 @@ use App\Models\BaseModel;
class GoodsSku extends BaseModel {
protected $table = 'goods_sku';
protected $fillable = ['goods_id', 'sku_value', 'sku', 'price', 'integral', 'stock', 'sales', 'cover', 'created_at', 'updated_at'];
protected $fillable = ['goods_id', 'sku_value', 'sku', 'price', 'integral', 'stock', 'sales', 'cover', 'created_at', 'updated_at','goods_sn'];
// protected $hidden = ['deleted_at'];
protected function casts(): array {
......
......@@ -9,6 +9,7 @@
namespace Modules\Goods\Services;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Modules\Goods\Models\Goods;
use App\Support\Tree;
......@@ -118,6 +119,7 @@ class GoodsService {
foreach ($goods->setFilterFields($request->all()) as $key => $value) {
$goods->$key = $value;
}
$goods->goods_sn = empty($request->input('goods_sn'))?"G".date('YmdHis'): $request->input('goods_sn');
$goods->save();
//更新栏目
......@@ -129,6 +131,7 @@ class GoodsService {
foreach ($sku as $key => $value) {
$sku[$key]['sku_value'] = isset($value['sku_value']) ? $value['sku_value'] : Arr::except($value, ['price', 'stock', 'cover', 'original_price', 'sales']);
$sku[$key]['sku'] = implode(';', $value['sku_value']);
$sku[$key]['goods_sn'] =empty($value['goods_sn'])?"S".date('YmdHi').rand(1000,9999): $value['goods_sn'];
}
$goods->sku()->createMany($sku);
}
......@@ -162,6 +165,8 @@ class GoodsService {
$goods->$key = $value;
}
$goods->goods_sn = empty($request->input('goods_sn'))?"G".date('YmdHis'):$request->input('goods_sn');
$goods->save();
//更新栏目
$goods->category()->sync($request->input('category_id'));
......@@ -174,6 +179,7 @@ class GoodsService {
foreach ($sku as $key => $value) {
$value['sku_value'] = isset($value['sku_value']) ? $value['sku_value'] : Arr::except($value, ['price', 'stock', 'cover', 'original_price', 'sales']);
$value['sku'] = implode(';', $value['sku_value']);
$value['goods_sn'] = empty($value['goods_sn'])?"S".date('YmdHi').rand(1000,9999):$value['goods_sn'];
$goods->sku()->updateOrCreate(['id' => $value['id'] ?? 0], $value);
}
}else{
......
......@@ -46,6 +46,7 @@ return new class extends Migration
$table->tinyInteger('status')->default(1)->comment('状态 1上架 0下架');
$table->timestamp('created_at')->nullable()->comment('创建时间');
$table->timestamp('updated_at')->nullable()->comment('更新时间');
$table->string('goods_sn')->nullable()->comment('商品编号');
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
......
......@@ -85,4 +85,21 @@ class Account extends BaseController{
return response()->json($this->data);
}
/**
* @title 通过提现
*
* @param AccountService $service
* @return void
*/
public function withdraw(Request $request, AccountService $service){
try {
$this->data['data'] = $service->withdraw($request);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
}
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Member\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Modules\Member\Services\PolymerService;
class Polymer extends BaseController{
/**
* @title 聚物通列表
*
* @param Request $request
* @param PolymerService $service
* @return void
*/
public function index(Request $request, PolymerService $service){
try {
$this->data['data'] = $service->getDataList($request);
} catch (\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
}
return response()->json($this->data);
}
/**
* @title 添加聚物通
*
* @param Request $request
* @param PolymerService $service
* @return void
*/
public function add(Request $request, PolymerService $service){
try {
$this->data['data'] = $service->createPolymer(store_id: 0, order_id: 0, member_id: $request->input('member_id'), amount: $request->input('amount'), type: $request->input('type'), account_type: 'system', remark: $request->input('remark'));
} catch (\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
}
return response()->json($this->data);
}
/**
* @title 修改聚物通
*
* @param Request $request
* @param PolymerService $service
* @return void
*/
public function edit(Request $request, PolymerService $service){
try {
$this->data['data'] = $service->update($request);
} catch (\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
}
return response()->json($this->data);
}
/**
* @title 删除聚物通
*
* @param Request $request
* @param PolymerService $service
* @return void
*/
public function delete(Request $request, PolymerService $service){
try {
$this->data['data'] = $service->delete($request);
} catch (\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
}
return response()->json($this->data);
}
}
\ No newline at end of file
......@@ -41,7 +41,7 @@ class Score extends BaseController{
*/
public function add(Request $request, ScoreService $service){
try {
$this->data['data'] = $service->createScore(order_id: 0, member_id: $request->input('member_id'), amount: $request->input('amount'), type: $request->input('type'), remark: $request->input('remark'));
$this->data['data'] = $service->createScore(store_id: 0, order_id: 0, member_id: $request->input('member_id'), amount: $request->input('amount'), type: $request->input('type'), account_type: 'system', remark: $request->input('remark'));
} catch (\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
......
<?php
namespace Modules\Member\Controllers\Admin;
use App\Http\Controllers\BaseController;
use Illuminate\Http\Request;
use Modules\Member\Services\SignService;
class Sign extends BaseController
{
/*
* 签到记录
*/
public function index(Request $request,SignService $service){
try {
$this->data['data'] = $service->getDataList($request);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
}
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Member\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Modules\Member\Services\PolymerService;
class Polymer extends BaseController {
/**
* @title 聚物通列表
*
* @param PolymerService $service
* @return void
*/
public function index(Request $request, PolymerService $service){
try {
$request->mergeIfMissing([
'is_user' => 1
]);
$this->data['data'] = $service->getDataList($request);
} catch (\think\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
}
return $this->data;
}
}
<?php
namespace Modules\Member\Controllers\Api;
use App\Http\Controllers\BaseController;
use Illuminate\Http\Request;
use Modules\Member\Services\SignService;
class Sign extends BaseController
{
/*
* 签到记录
*/
public function index(Request $request,SignService $service){
try {
$this->data['data'] = $service->getDataList($request);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
/**签到
* @param Request $request
* @param SignService $service
* @return array
*/
public function add(Request $request,SignService $service){
try {
$this->data['data'] = $service->create($request);
} catch (\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
}
return $this->data;
}
}
\ No newline at end of file
......@@ -21,6 +21,6 @@ class OrderRefundListener implements ShouldQueue{
$detail = $event->detail;
// 积分退还
app(ScoreService::class)->createScore(order_id: $detail->id, member_id: $detail->member_id, amount: $detail->total_integral, type: 'income', remark: '商品退货退款');
app(ScoreService::class)->createScore(store_id: $refund->store_id, order_id: $detail->id, member_id: $detail->member_id, amount: $detail->total_integral, type: 'income', type: 'refund', remark: '商品退货退款');
}
}
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Member\Models;
use App\Models\BaseModel;
class MemberPolymer extends BaseModel {
protected $table = 'member_polymer';
protected $fillable = ['store_id', 'order_id', 'member_id', 'type','account_type', 'amount', 'bf_amount', 'af_amount', 'status', 'remark'];
// protected $hidden = ['deleted_at'];
public function member() {
return $this->belongsTo(Member::class, 'member_id', 'uid');
}
public function admin(){
return $this->belongsTo(\Modules\Auth\Models\Admin::class, 'member_id', 'uid');
}
public function order(){
return $this->belongsTo(\Modules\Order\Models\OrderItem::class, 'order_id', 'id');
}
}
......@@ -13,7 +13,7 @@ use App\Models\BaseModel;
class MemberScore extends BaseModel {
protected $table = 'member_score';
protected $fillable = ['store_id', 'order_id', 'member_id', 'type', 'amount', 'bf_amount', 'af_amount', 'status', 'remark'];
protected $fillable = ['store_id', 'order_id', 'member_id', 'type', 'amount','account_type', 'bf_amount', 'af_amount', 'status', 'remark'];
// protected $hidden = ['deleted_at'];
public function member() {
......
<?php
namespace Modules\Member\Models;
use App\Models\BaseModel;
class SignRecord extends BaseModel
{
protected $table = 'sign_record';
protected $fillable = ['member_id','score','day','month'];
}
\ No newline at end of file
......@@ -10,10 +10,12 @@ namespace Modules\Member\Services;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use App\Support\Time;
use Modules\Member\Models\MemberAccount;
use Modules\Member\Models\Member;
use Modules\Wechat\Services\TransferService;
class AccountService {
......@@ -117,7 +119,7 @@ class AccountService {
*/
public function createAccount($store_id, $order_id, $member_id, $type, $account_type = 'order', $amount = 0, $remark = ''){
if ($order_id > 0) {
$account = MemberAccount::where('order_id', '=', $order_id)->where('member_id', '=', $member_id)->where('type', '=', $type)->first();
$account = MemberAccount::where('order_id', '=', $order_id)->where('member_id', '=', $member_id)->where('type', '=', $type)->where('account_type', '=', $account_type)->first();
if($account){
return $account;
}
......@@ -134,6 +136,7 @@ class AccountService {
'order_id' => $order_id,
'member_id' => $member_id,
'type' => $type,
'account_type' => $account_type,
'amount' => $amount,
'bf_amount' => $bf_amount,
'af_amount' => $af_amount,
......@@ -240,15 +243,17 @@ class AccountService {
'order_id' => 0,
'store_id' => 0,
'member_id' => $member['uid'],
'type' => 1,
'amount' => $request->input('amount'),
'type' => 'withdraw',
'account_type' => 'withdraw',
'af_amount' => $member['money'],
'bf_amount' => bcsub($member['money'], $request->input('amount'), 2),
'fee_rate' => $config['withdraw_fee_rate'],
'actual_amount' => bcsub($request->input('amount'), bcmul($request->input('amount'), bcdiv($config['withdraw_fee_rate'], 100, 2), 2), 2),
'pay_type' => $request->input('pay_type'),
'bank_id' => $request->input('bank_id', 0),
'status' => 0,
'request_no' => str_replace('-', '', Str::orderedUuid()),
'remark' => $request->input('remark', '用户提现'),
];
......@@ -259,6 +264,12 @@ class AccountService {
}
$account->save();
//扣除余额
$user = Member::find($member['uid']);
$user->money = bcsub($user->money, $request->input('amount'), 2);
$user->save();
return $account;
}
......@@ -271,17 +282,19 @@ class AccountService {
throw new \Exception("提现记录已处理!", 0);
}
if($request->filled('status')){
$account->status = $request->input('status');
$member = Member::where('uid', $account->member_id)->first();
if($request->input('status') == 1){
$member = Member::find($account->member_id);
$member->money = bcsub($member->money, $account->amount, 2);
$member->save();
if($account->pay_type=="wechat"){//
$result = TransferService::transfer($account->bank_realname,$account->request_no,$account->actual_amount,$member['username']);
if(isset($result['code'])){
throw new \Exception('异常:'.$result['code'].' '.$result['message'], 0);
}
MemberAccount::where(['id'=>$account->id])->update(['status'=>1,'out_batch_no'=>$result]);
}else if($account->pay_type=="bank"){
throw new \Exception("银行卡在开发中!", 0);
}else {
throw new \Exception("该提现方式不存在!", 0);
}
$account->save();
return $account;
}
......
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Member\Services;
use Modules\Member\Models\Member;
use Modules\Member\Models\MemberPolymer;
class PolymerService {
/**
* @title 获取会员列表
*
* @param [type] $request
* @return void
*/
public function getDataList($request){
$map = [];
$query = MemberPolymer::query();
if ($request->filled('store_id')) {
$map[] = ['store_id', '=', $request->input('store_id')];
}
if ($request->filled('member_id')) {
$map[] = ['member_id', '=', $request->input('member_id')];
}
if ($request->filled('is_user')) {
$map[] = ['member_id', '=', auth('api')->user()['uid']];
$query->whereIn('type', ['income', 'withdraw', 'pay']);
}
$query->where($map)->orderBy('id', 'desc');
if ($request->filled('username')) {
$query->whereHas('member', function($query) use ($request){
$query->where('username', 'like', '%' . $request->input('username') . '%');
});
}
if ($request->filled('mobile')) {
$query->whereHas('member', function($query) use ($request){
$query->where('mobile', 'like', '%' . $request->input('mobile') . '%');
});
}
if ($request->filled('store_title')) {
$query->whereHas('store', function($query) use ($request){
$query->where('title', 'like', '%' . $request->input('store_title') . '%');
});
}
if ($request->filled('is_admin') && auth('admin')->user()) {
$map[] = ['member_id', '=', auth('admin')->user()['uid']];
$query->whereIn('type', ['service_income', 'service_withdraw', 'service_transfer']);
}else{
$query->whereIn('type', ['income', 'withdraw', 'pay']);
}
if ($request->filled('type')) {
if (is_string($request->input('type'))){
$map[] = ['type', '=', $request->input('type')];
}else if (is_array($request->input('type'))){
$query->whereIn('type', $request->input('type'));
}
}
$query->where($map);
if($request->filled('page')){
$data = [
'total' => $query->count(),
'page' => $request->input('page', 1),
'data' => $query->offset($request->input('offset', 0))->limit($request->input('limit', 30))->get()->each(function($item){
if (in_array($item->type, ['income', 'withdraw','pay'])){
$item->member = $item->member()->select(['uid', 'username', 'nickname', 'avatar'])->first();
}else if (in_array($item->type, ['service_income', 'service_withdraw'])){
$item->member = $item->admin()->select(['uid', 'username', 'nickname', 'avatar'])->first();
}else{
$item->member = $item->member()->select(['uid', 'username', 'nickname', 'avatar'])->first();
}
}),
];
}else{
$data = $query->limit($request->input('limit', 30))->get();
}
return $data;
}
/**
* @title 添加会员
*
* @param Request $request
* @param MemberService $service
* @return void
*/
public function createPolymer($store_id, $order_id, $member_id, $amount, $type, $account_type, $remark){
if($order_id != 0){
$polymer = MemberPolymer::where('order_id', '=', $order_id)->where('member_id', '=', $member_id)->where('type', '=', $type)->where('account_type', '=', $account_type)->first();
if($polymer){
return $polymer;
}
}
$member = Member::where('uid', $member_id)->first();
if(!$member){
return false;
}
$af_amount = $member['polymer_money'] ? (in_array($type, ['pay', 'transfer']) ? bcsub($member['polymer_money'], $amount,2) : bcadd($member['polymer_money'], $amount,2)) : $amount;
$bf_amount = $member['polymer_money'] ? $member['polymer_money'] : 0;
$data = [
'store_id' => $store_id,
'order_id' => $order_id,
'member_id' => $member_id,
'type' => $type,
'account_type' => $account_type,
'amount' => $amount,
'bf_amount' => $bf_amount,
'af_amount' => $af_amount,
'status' => 0,
'remark' => $remark,
];
if ($af_amount < 0){
throw new \Exception("会员积分余额不足!", 0);
}
if (in_array($type, ['pay', 'transfer'])){
$member->polymer_money = bcsub($member->polymer_money, $amount, 2);
}else{
$member->polymer_money = bcadd($member->polymer_money, $amount, 2);
}
$member->save();
$polymer = MemberPolymer::create($data);
return $polymer;
}
/**
* @title 修改会员
*
* @param Request $request
* @param MemberService $service
* @return void
*/
public function update($request){
$request->validate([
'title' => 'required|max:255',
'name' => 'required|max:255|alpha_dash:ascii|unique:member_level,name,' . $request->input('id'),
]);
try {
$polymer = MemberPolymer::findOrFail($request->input('id'));
} catch (\Throwable $th) {
throw new \Exception("会员不存在!", 1);
}
$data = [
'title'=> $request->input('title', ''),
'name' => $request->input('name', ''),
'icon' => $request->input('icon', ''),
'sort' => $request->input('sort', 0),
'status' => $request->input('status', 1),
'remark' => $request->input('remark', ''),
];
$polymer->update($data);
return $polymer;
}
public function delete($request){
if($request->filled('id')){
try {
$polymer = MemberPolymer::findOrFail($request->input('id'));
} catch (\Throwable $th) {
throw new \Exception("会员等级不存在!", 1);
}
$polymer->delete();
}
if($request->filled('ids')){
try {
$polymer = MemberPolymer::whereIn('id', $request->input('ids'));
$polymer->delete();
} catch (\Throwable $th) {
throw new \Exception($th->getMessage(), 1);
}
}
return $polymer;
}
}
......@@ -68,7 +68,7 @@ class PromoterService {
$map[] = ['uid', '=', auth('api')->user()['uid']];
$member = Member::with(['level'])->select(['uid', 'username', 'nickname', 'mobile', 'avatar', 'score', 'money', 'level_id', 'invite_uid'])->where($map)->first();
$member = Member::with(['level'])->select(['uid', 'username', 'nickname', 'mobile', 'avatar', 'score', 'money', 'polymer_money', 'level_id', 'invite_uid'])->where($map)->first();
if ($member) {
$member->invite = Member::where('uid', $member->invite_uid)->select(['uid', 'username', 'nickname', 'avatar'])->first();
......
......@@ -93,9 +93,9 @@ class ScoreService {
* @param MemberService $service
* @return void
*/
public function createScore($order_id, $member_id, $amount, $type, $remark){
public function createScore($store_id, $order_id, $member_id, $amount, $type, $account_type, $remark){
if($order_id != 0){
$score = MemberScore::where('order_id', '=', $order_id)->where('member_id', '=', $member_id)->where('type', '=', $type)->first();
$score = MemberScore::where('order_id', '=', $order_id)->where('member_id', '=', $member_id)->where('type', '=', $type)->where('account_type', '=', $account_type)->first();
if($score){
return $score;
}
......@@ -106,14 +106,15 @@ class ScoreService {
if(!$member){
return false;
}
$af_amount = $member['score'] ? (in_array($type, ['pay', 'transfer']) ? bcsub($member['score'], $amount) : bcadd($member['score'], $amount)) : $amount;
$af_amount = $member['score'] ? (in_array($type, ['pay', 'transfer']) ? bcsub($member['score'], $amount,2) : bcadd($member['score'], $amount,2)) : $amount;
$bf_amount = $member['score'] ? $member['score'] : 0;
$data = [
'store_id' => 0,
'store_id' => $store_id,
'order_id' => $order_id,
'member_id' => $member_id,
'type' => $type,
'account_type' => $account_type,
'amount' => $amount,
'bf_amount' => $bf_amount,
'af_amount' => $af_amount,
......
<?php
namespace Modules\Member\Services;
use Modules\Member\Models\Member;
use Modules\Member\Models\SignRecord;
class SignService
{
/**
* @title 获取签到列表
*
* @param [type] $request
* @return void
*/
public function getDataList($request){
$map = [];
if($request->filled('is_user')){
$map[] = ['member_id', '=', auth('api')->user()['uid']];
}
if($request->filled('month')){
$map[] = ['month', '=', $request->input('month')];
}
$query = SignRecord::where($map)->orderBy('id', 'desc');
if($request->filled('page')){
$data = [
'total' => $query->count(),
'page' => $request->input('page', 1),
'data' => $query->offset($request->input('offset', 0))->limit($request->input('limit', 10))->get(),
];
}else{
$data = $query->get();
}
return $data;
}
/**
* @title 添加签到
*
* @param Request $request
* @return void
*/
public function create($request){
$member_id=auth('api')->user()['uid'];
$checkSign=SignRecord::where(['member_id' => $member_id])->whereDate('created_at', date('Y-m-d'))->count();
if($checkSign){
throw new \Exception('不能重复签到');
}
$config = cache()->get('config');
$member = Member::where('uid', $member_id)->first();
if(!$member){
throw new \Exception('用户不存在!');
}
if($config['sign_score']){//送积分
$member->score = bcadd($member->score, $config['sign_score']);
$member->save();
}
$record = new SignRecord();
$record->member_id = $member_id;
$record->score = $config['sign_score'];
$record->day = date('d');
$record->month = date('Y-m');
$record->save();
return $checkSign;
}
}
\ No newline at end of file
......@@ -65,6 +65,10 @@ return new class extends Migration {
$table->tinyInteger('status')->default(1)->comment('状态 0未用,1已转账,2已提现,3提现记录');
$table->timestamp('created_at')->nullable()->comment('创建时间');
$table->timestamp('updated_at')->nullable()->comment('更新时间');
$table->string('bank_realname', 255)->nullable()->comment('真实姓名');
$table->string('reason', 255)->nullable()->comment('申请理由');
$table->string('out_batch_no', 255)->nullable()->comment('商家批次单号');
$table->string('detail_status', 255)->nullable()->comment('单号查询状态');
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
......@@ -77,6 +81,7 @@ return new class extends Migration {
$table->unsignedBigInteger('order_id')->comment('订单ID');
$table->unsignedBigInteger('store_id')->comment('店铺ID');
$table->string('type', '20')->nullable()->comment('类型');
$table->string('account_type', '20')->nullable()->comment('账单类型');
$table->decimal('amount', total: 10, places: 2)->default(0)->comment('数量');
$table->decimal('bf_amount', total: 10, places: 2)->default(0)->comment('前数量');
$table->decimal('af_amount', total: 10, places: 2)->default(0)->comment('后数量');
......@@ -90,6 +95,26 @@ return new class extends Migration {
$table->collation = 'utf8mb4_unicode_ci';
$table->comment('会员积分表');
});
Schema::create('member_polymer', function (Blueprint $table) {
$table->id()->uniqid()->comment('主键id');
$table->unsignedBigInteger('member_id')->comment('会员id');
$table->unsignedBigInteger('order_id')->comment('订单ID');
$table->unsignedBigInteger('store_id')->comment('店铺ID');
$table->string('type', '20')->nullable()->comment('类型');
$table->string('account_type', '20')->nullable()->comment('账单类型');
$table->decimal('amount', total: 10, places: 2)->default(0)->comment('数量');
$table->decimal('bf_amount', total: 10, places: 2)->default(0)->comment('前数量');
$table->decimal('af_amount', total: 10, places: 2)->default(0)->comment('后数量');
$table->string('remark', 255)->nullable()->comment('备注');
$table->tinyInteger('status')->default(1)->comment('状态 0未用,1已核销');
$table->timestamp('created_at')->nullable()->comment('创建时间');
$table->timestamp('updated_at')->nullable()->comment('更新时间');
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
$table->comment('会员聚物通表');
});
Schema::create('member_bank', function (Blueprint $table) {
$table->id()->uniqid()->comment('主键id');
$table->unsignedBigInteger('member_id')->comment('会员id');
......@@ -119,6 +144,7 @@ return new class extends Migration {
Schema::dropIfExists('member_address');
Schema::dropIfExists('member_account');
Schema::dropIfExists('member_score');
Schema::dropIfExists('member_polymer');
Schema::dropIfExists('member_bank');
}
};
......@@ -28,6 +28,7 @@ Route::name('member.')->prefix('member')->middleware(['auth.check:admin'])->grou
Route::post('/add', 'add')->name('add');
Route::put('/edit', 'edit')->name('edit');
Route::delete('/delete', 'delete')->name('delete');
Route::post('/withdraw', 'withdraw')->name('withdraw');
});
Route::controller(Modules\Member\Controllers\Admin\Score::class)->prefix('score')->name('score.')->group(function () {
Route::get('/index', 'index')->name('index');
......@@ -35,8 +36,17 @@ Route::name('member.')->prefix('member')->middleware(['auth.check:admin'])->grou
Route::put('/edit', 'edit')->name('edit');
Route::delete('/delete', 'delete')->name('delete');
});
Route::controller(Modules\Member\Controllers\Admin\Polymer::class)->prefix('polymer')->name('polymer.')->group(function () {
Route::get('/index', 'index')->name('index');
Route::post('/add', 'add')->name('add');
Route::put('/edit', 'edit')->name('edit');
Route::delete('/delete', 'delete')->name('delete');
});
Route::controller(Modules\Member\Controllers\Admin\Promoter::class)->prefix('promoter')->name('promoter.')->group(function () {
Route::get('/index', 'index')->name('index');
Route::put('/audit', 'audit')->name('audit');
});
Route::controller(Modules\Member\Controllers\Admin\Sign::class)->prefix('sign')->name('sign.')->group(function () {
Route::get('/index', 'index')->name('index');
});
});
......@@ -42,6 +42,10 @@ Route::name('member.')->prefix('member')->middleware(['auth.check:api'])->group(
Route::get('/index', 'index')->name('index');
});
Route::controller(Modules\Member\Controllers\Api\Polymer::class)->prefix('polymer')->name('polymer.')->group(function () {
Route::get('/index', 'index')->name('index');
});
Route::controller(Modules\Member\Controllers\Api\Collect::class)->prefix('collect')->name('collect.')->group(function () {
Route::get('/index', 'index')->name('index');
Route::post('/add', 'add')->name('add');
......@@ -60,4 +64,9 @@ Route::name('member.')->prefix('member')->middleware(['auth.check:api'])->group(
Route::post('/withdraw', 'withdraw')->name('withdraw');
Route::get('/count', 'count')->name('count');
});
});
Route::controller(Modules\Member\Controllers\Api\Sign::class)->prefix('sign')->name('sign.')->group(function () {
Route::get('/index', 'index')->name('index');
Route::get('/add', 'add')->name('add');
});
});
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Order\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Modules\Order\Services\CashierService;
/**收银台
* Class Cashier
* @package Modules\Order\Controllers\Admin
*/
class Cashier extends BaseController {
/**
* @title 购物车列表
*
* @param Request $request
* @param CartService $service
* @return void
*/
public function index(Request $request, CashierService $service){
try {
$this->data['data'] = $service->getDataList(auth('admin')->user()['uid']);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
/**
* @title 添加购物车
*
* @param Request $request
* @param CartService $service
* @return void
*/
public function add(Request $request, CashierService $service){
try {
$this->data['data'] = $service->create($request);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
/**
* @title 更新购物车
*
* @param Request $request
* @param CartService $service
* @return void
*/
public function edit(Request $request, CashierService $service){
try {
$this->data['data'] = $service->update($request);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
/**
* @title 删除购物车
*
* @param Request $request
* @param CartService $service
* @return void
*/
public function delete(Request $request, CashierService $service){
try {
$this->data['data'] = $service->delete($request);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
/**
* @title 立即下单
*
* @param Request $request
* @param OrderService $service
* @return void
*/
public function simple(Request $request, CashierService $service){
try {
$this->data['data'] = $service->simple($request);
$this->data['message'] = '下单成功';
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
}
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Order\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Modules\Order\Services\ExchangeService;
class Exchange extends BaseController {
/**
* @title 列表
*
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request, ExchangeService $service){
try {
$this->data['data'] = $service->getDataList($request);
} catch (\Exception $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
}
return response()->json($this->data);
}
}
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Order\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Modules\Order\Services\ExchangeService;
class Exchange extends BaseController {
/**
* @title 添加置换收集订单记录
*
* @param Request $request
* @param ExchangeService $service
* @return void
*/
public function add(Request $request, ExchangeService $service){
try {
$this->data['data'] = $service->create($request);
$this->data['message'] = '添加成功,请耐心等候';
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
}
\ No newline at end of file
......@@ -62,7 +62,12 @@ class Order extends BaseController {
*/
public function add(Request $request, OrderService $service){
try {
$this->data['data'] = $service->create($request);
$this->data['data'] = $order = $service->create($request);
if(($order->amount - $order->polymer_money) == 0 ){
app(OrderService::class)->paySuccess($order->order_no);
$this->data['code'] =9999;
}
$this->data['message'] = '下单成功';
} catch (\Throwable $th) {
$this->data['code'] = 0;
......@@ -81,7 +86,12 @@ class Order extends BaseController {
*/
public function simple(Request $request, OrderService $service){
try {
$this->data['data'] = $service->simpleCreate($request);
$this->data['data'] = $order = $service->simpleCreate($request);
if(($order->amount - $order->polymer_money) == 0 ){
app(OrderService::class)->paySuccess($order->order_no);
$this->data['code'] =9999;
}
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
......
......@@ -91,7 +91,7 @@ class OrderBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $item->id, member_id: $store->service_id, type: 'service_income', account_type: 'order', amount: $balance_service_amount, remark: '分仓服务费');
}
if($balance_service_integral > 0 && $store->service_id){
app(ScoreService::class)->createScore(order_id: $item->id, member_id: $store->service_id, amount: $balance_service_integral, type: 'service_income', remark: '分仓服务费');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $item->id, member_id: $store->service_id, amount: $balance_service_integral, type: 'service_income', account_type: 'order', remark: '分仓服务费');
}
//推广人员服务费
......@@ -104,7 +104,7 @@ class OrderBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $item->id, member_id: $invite->uid, type: 'income', account_type: 'order', amount: $balance_service_amount, remark: '兼职代理服务费');
}
if($balance_service_integral > 0){
app(ScoreService::class)->createScore(order_id: $item->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', remark: '兼职代理服务费');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $item->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', account_type: 'order', remark: '兼职代理服务费');
}
}else if($invite->level->name == 'signings'){
// 签约代理
......@@ -114,7 +114,7 @@ class OrderBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $item->id, member_id: $invite->uid, type: 'income', account_type: 'order', amount: $balance_service_amount, remark: '签约代理服务费');
}
if($balance_service_integral > 0){
app(ScoreService::class)->createScore(order_id: $item->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', remark: '签约代理服务费');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $item->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', account_type: 'order', remark: '签约代理服务费');
}
}
}
......@@ -128,7 +128,7 @@ class OrderBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $item->id, member_id: $store->member_id, type: 'income', account_type: 'order', amount: $amount, remark: '店主门店收入');
}
if($integral > 0){
app(ScoreService::class)->createScore(order_id: $item->id, member_id: $store->member_id, amount: $integral, type: 'income', remark: '店主门店收入');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $item->id, member_id: $store->member_id, amount: $integral, type: 'income', account_type: 'order', remark: '店主门店收入');
}
}
}
......
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Order\Models;
use App\Models\BaseModel;
class Exchange extends BaseModel {
protected $table = 'exchange_order';
protected $fillable = ['uid', 'name', 'mobile', 'status', 'created_at', 'address', 'remark', 'updated_at'];
// protected $hidden = ['deleted'];
protected function casts(): array {
return [
'status' => 'integer',
'created_at' => 'datetime:Y-m-d H:i:s',
'updated_at' => 'datetime:Y-m-d H:i:s',
];
}
}
......@@ -13,7 +13,7 @@ use App\Models\BaseModel;
class Order extends BaseModel {
protected $table = 'order';
protected $fillable = ['order_no', 'store_id', 'member_id', 'invite_uid', 'amount', 'pay_type', 'pay_no', 'delivery_type', 'delivery_no', 'delivery_info', 'status', 'pay_time', 'confirm_time', 'comment_time', 'close_time', 'refund_time', 'refund_no'];
protected $fillable = ['order_no', 'store_id', 'member_id', 'invite_uid', 'amount', 'pay_type', 'pay_no', 'delivery_type', 'delivery_no', 'delivery_info', 'status', 'pay_time', 'confirm_time', 'comment_time', 'close_time', 'refund_time', 'refund_no','delivery_type'];
// protected $hidden = ['deleted_at'];
protected function casts(): array {
......
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Order\Services;
use Illuminate\Support\Str;
use Modules\Goods\Models\GoodsSku;
use Modules\Order\Models\Cart;
use Modules\Goods\Models\Goods;
use Modules\Order\Models\Order;
use Modules\Order\Models\OrderItem;
class CashierService {
/**
* @title 获取购物车列表
*
* @return void
*/
public function getDataList($admin_id){
$data = Cart::with(['goods:id,title,price,cover,stock,sales,integral', 'store:id,title,cover', 'sku'])->where('admin_id', $admin_id)->get();
return $data;
}
public function create($request){
$request->validate([
'goods_sn' => 'required',
'num' => 'required',
], [
'goods_sn.required' => '商品编号不能为空',
'num.required' => '商品数量不能为空',
]);
$goods_id = $request->input('goods_id');
$goods_sku_id = $request->input('goods_sku_id');
//通过扫码获取商品编号
if(!empty($request->input('goods_sn'))){
$goods_sn=$request->input('goods_sn');
$goodsSN=Goods::where(['goods_sn' => $goods_sn])->first();
if(!empty($goodsSN)){
$goods_id = empty($goodsSN)?$goods_id:$goodsSN->id;
}else{
$goodsSKUSN=GoodsSku::where(['goods_sn' => $goods_sn])->first();
if(!empty($goodsSKUSN)){
$goods_id = empty($goodsSKUSN)?$goods_id:$goodsSKUSN->goods_id;
$goods_sku_id = empty($goodsSKUSN)?$goods_id:$goodsSKUSN->id;
}
}
/*$firstChar = substr($goods_sn, 0, 1); // 截取第一个字符
if($firstChar == "G"){
$goodsSN=Goods::where(['goods_sn' => $goods_sn])->first();
$goods_id = empty($goodsSN)?$goods_id:$goodsSN->id;
}else if($firstChar == "S"){
$goodsSKUSN=GoodsSku::where(['goods_sn' => $goods_sn])->first();
$goods_id = empty($goodsSKUSN)?$goods_id:$goodsSKUSN->goods_id;
$goods_sku_id = empty($goodsSKUSN)?$goods_id:$goodsSKUSN->id;
}*/
}
/////////////////////////////////////////////////////////
$goods = Goods::find($goods_id);
if(!$goods){
throw new \Exception("商品不存在!", 1);
}
$cart = Cart::where('goods_id', $goods_id)->where('admin_id', auth('admin')->user()['uid'])->where('goods_sku_id', $goods_sku_id);
if($cart->doesntExist()){
$cart = new Cart();
$request->merge([
'admin_id' => auth('admin')->user()['uid']
]);
foreach ($cart->setFilterFields($request->all()) as $key => $value) {
if($value != ''){
$cart->$key = $value;
}
}
if($cart->num > $goods->stock){
throw new \Exception("商品库存不足!", 1);
}
}else{
$cart = $cart->first();
if($cart->num > $goods->stock){
throw new \Exception("商品库存不足!", 1);
}
$cart->num = $cart->num + $request->input('num', 1);
}
$cart->goods_id = $goods_id;
$cart->goods_sku_id = $goods_sku_id;
$cart->store_id = $goods->store_id;
$cart->save();
return $cart;
}
public function update($request){
$cart = Cart::where('id', $request->input('id'))->where('admin_id', auth('admin')->user()['uid'])->first();
if(!$cart){
throw new \Exception("购物车不存在!", 1);
}
foreach ($cart->setFilterFields($request->only(['goods_sku_id', 'num'])) as $key => $value) {
if($value){
$cart->$key = $value;
}
}
$cart->save();
return $cart;
}
public function delete($request){
if($request->filled('id')){
try {
$cart = Cart::findOrFail($request->input('id'));
} catch (\Throwable $th) {
throw new \Exception("购物车不存在!", 1);
}
$cart->delete();
}
if($request->filled('ids')){
try {
$cart = Cart::whereIn('id', $request->input('ids'));
} catch (\Throwable $th) {
throw new \Exception($th->getMessage(), 1);
}
$cart->delete();
}
return $cart;
}
/**
* @title 添加订单
*
* @param [type] $request
* @return void
*/
public function simple($request){
$request->validate([
'carts' => 'required',
], [
'carts.required' => '请选择商品',
]);
$order = new Order();
$request->mergeIfMissing(['admin_id' => auth('admin')->user()['uid']]);
if($request->filled('carts')){
$cartsQuery = Cart::with(['goods', 'sku'])->whereIn('id', $request->input('carts'))->where('admin_id', '=', $request->input('admin_id'));
}
if($cartsQuery->doesntExist()){
throw new \Exception("请先加入购物车!", 0);
}
$orderGoods = [];
$carts = $cartsQuery->get()->map(function($item) use (&$orderGoods, $request) {
if(!$item->goods){
throw new \Exception("商品不存在!", 0);
}
if($item->goods->status != 1){
throw new \Exception("商品已下架!", 0);
}
if(!$item->goods->is_repeat_buy){
$orderGoodsQuery = OrderItem::where('goods_id', '=', $item->goods_id)->where('admin_id', '=', $request->input('admin_id'))->where('status', '>=', 3);
if($orderGoodsQuery->exists()){
throw new \Exception("您已购买过此商品,当前产品不能复购!", 0);
}
}
if($item->sku){
if($item->sku->stock < $item->num){
throw new \Exception("商品库存不足!", 0);
}
$item->amount = $item->sku->price * $item->num;
$item->integral = $item->sku->integral * $item->num;
}else{
if($item->goods->stock < $item->num){
throw new \Exception("商品库存不足!", 0);
}
$item->amount = $item->goods->price * $item->num;
$item->integral = $item->goods->integral * $item->num;
}
$orderGoods[] = new OrderItem([
'member_id' =>0,
'store_id' => $item->store_id,
'goods_id' => $item->goods_id,
'goods_sku_id' => $item->goods_sku_id,
'title' => $item->goods->title,
'cover' => $item->goods->cover,
'price' => $item->goods->price,
'integral' => $item->goods->integral,
'total_price' => $item->amount,
'total_integral' => $item->integral,
'num' => $item->num,
'status' => 0,
]);
return $item;
});
$order->order_no = str_replace('-', '', Str::orderedUuid());
$order->member_id =0;
$order->invite_uid = $request->input('invite_uid') ?? 0;
$order->pay_type = $request->input('pay_type') ?? 'wechat';
$order->amount = $carts->sum('amount');
$order->integral = $carts->sum('integral');
$order->status = 0;
$order->admin_id = auth('admin')->user()['uid'];
$order->save();
//下单完成后,删除购物车
$cartsQuery->delete();
$order->detail()->saveMany($orderGoods);
return $order;
}
}
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Order\Services;
use Modules\Order\Models\Exchange;
class ExchangeService {
public function getDataList($request){
$map = [];
if($request->filled('name')){
$map[] = ['name', 'like', '%'.$request->input('name').'%'];
}
if($request->filled('is_user')){
$map[] = ['mobile', 'like', '%'.$request->input('mobile').'%'];
}
$query = Exchange::where($map)->orderBy('id', 'desc');
if($request->filled('page')){
$data = [
'total' => $query->count(),
'page' => $request->input('page', 1),
'data' => $query->offset($request->input('offset', 0))->limit($request->input('limit', 10))->get(),
];
}else{
$data = $query->get();
}
return $data;
}
/**
* @title 添加置换收集订单
*
* @param [type] $request
* @return void
*/
public function create($request)
{
$request->validate([
'name' => 'required',
'address' => 'required',
'mobile' => 'required',
], [
'name.required' => '请填写姓名',
'mobile.required' => '请填写手机号码',
// 'mobile.regex' => '手机号格式不正确',
'address.required' => '请填写所在地址'
]);
$exchange = new Exchange();
$info = Exchange::where(['mobile' => $request->input('mobile')])->first();
if($info){
throw new \Exception("此号码已填写过", 0);
}
$exchange->uid = auth('api')->user()['uid'];
$exchange->name = $request->input('name');
$exchange->mobile = $request->input('mobile');
$exchange->status = 1;
$exchange->address = $request->input('address');
$exchange->remark = $request->input('remark') ?? '';
$exchange->save();
return $exchange;
}
}
\ No newline at end of file
......@@ -193,6 +193,8 @@ class OrderService {
return $data;
}
/**
* @title 添加订单
*
......@@ -246,6 +248,9 @@ class OrderService {
$item->amount = $item->goods->price * $item->num;
$item->integral = $item->goods->integral * $item->num;
}
//使用聚物通资金不可用积分
$item->goods->integral = $item->integral = $request->input('pay_way')=="integral" ? $item->integral:0;
$orderGoods[] = new OrderItem([
'member_id' => auth('api')->user()['uid'],
'store_id' => $item->store_id,
......@@ -269,8 +274,17 @@ class OrderService {
$order->pay_type = $request->input('pay_type') ?? 'wechat';
$order->amount = $carts->sum('amount');
$order->integral = $carts->sum('integral');
$order->pay_way =$request->input('pay_way');
$order->status = 0;
if($request->input('pay_way') == "polymer_money"){
if(auth('api')->user()['polymer_money'] >= $order->amount){
$order->polymer_money = $order->amount;//聚物通
}else{
$order->polymer_money = auth('api')->user()['polymer_money'];
}
}
if($order->integral > auth('api')->user()['score']){
throw new \Exception("积分不足!", 0);
}
......@@ -297,6 +311,9 @@ class OrderService {
], [
'goods_id.required' => '请选择商品',
]);
$pay_way=$request->input('pay_way') ?? 'wechat';//付款方式
$order = new Order();
$goods = Goods::where('id', '=', $request->input('goods_id'))->first();
......@@ -331,6 +348,9 @@ class OrderService {
if(!$sku){
throw new \Exception("商品规格不存在!", 0);
}
//使用聚物通资金不可用积分
$sku->integral = $pay_way == "integral"?$sku->integral:0;
$orderGoods = new OrderItem([
'member_id' => auth('api')->user()['uid'],
'store_id' => $goods->store_id,
......@@ -348,6 +368,9 @@ class OrderService {
$amount = $sku->price;
$integral = $sku->integral;
}else{
//使用聚物通资金不可用积分
$goods->integral = $pay_way == "integral"?$goods->integral:0;
$orderGoods = new OrderItem([
'member_id' => auth('api')->user()['uid'],
'store_id' => $goods->store_id,
......@@ -370,10 +393,20 @@ class OrderService {
$order->member_id = auth('api')->user()['uid'];
$order->invite_uid = $request->input('invite_uid') ?? 0;
$order->pay_type = $request->input('pay_type') ?? 'wechat';
$order->delivery_type = $request->input('delivery_type') ?? 1;
$order->amount = $amount;
$order->integral = $integral;
$order->integral = $integral;//积分
$order->pay_way =$pay_way;
$order->status = 0;
if($pay_way == "polymer_money"){
if(auth('api')->user()['polymer_money'] >= $amount){
$order->polymer_money = $amount;//聚物通
}else{
$order->polymer_money = auth('api')->user()['polymer_money'];
}
}
if($order->integral > auth('api')->user()['score']){
throw new \Exception("积分不足!", 0);
}
......@@ -402,7 +435,7 @@ class OrderService {
* @return void
*/
public function update($request){
$order = Order::where('id', '=', $data['id'])->first();
$order = Order::where('id', '=', $request->input('id'))->first();
if(!$order){
throw new \Exception("订单不存在!", 0);
}
......@@ -517,10 +550,14 @@ class OrderService {
$itemCount = $order->detail()->count();
// 订单详情商品处理
$order->detail()->with(['goods', 'sku'])->get()->each(function($item) use ($order, $itemCount) {
$order->detail()->with(['goods', 'sku'])->get()->each(function($item,$key) use ($order, $itemCount) {
// 积分商品积分扣除
if($item->total_integral > 0){
app(\Modules\Member\Services\ScoreService::class)->createScore(order_id: $item->id, member_id: $order->member['uid'], type: 'pay', amount: $item->total_integral, remark: '订单支付');
app(\Modules\Member\Services\ScoreService::class)->createScore(store_id: $item->store_id, order_id: $item->id, member_id: $order->member['uid'], type: 'pay', account_type: 'order', amount: $item->total_integral, remark: '订单支付');
}
// 聚物通扣除
if( $key== 0 && $order->polymer_money > 0){
app(\Modules\Member\Services\PolymerService::class)->createPolymer(store_id: $item->store_id, order_id: $item->id, member_id: $order->member['uid'], type: 'pay', account_type: 'order', amount: $order->polymer_money, remark: '订单支付');
}
if($item->goods->goods_type == 0){
$item->status = 3;
......@@ -701,21 +738,51 @@ class OrderService {
if(!$order){
throw new \Exception("订单不存在!", 0);
}
//判断是否为店主
$level = auth('api')->user()->level()->where('store_id', '=', $order['store_id'])->first();
if(!$level || $level['name'] != 'master'){
throw new \Exception("您不是店主,无权发货!", 0);
$item = $order->detail()->where('id', $request->input('detail_id'))->first();
if(!$item){
throw new \Exception("订单详情不存在!", 0);
}
if ($request->is('api/*') && auth('api')->user()){
//判断是否为店主
$store = \Modules\Store\Models\Store::where('id', $item['store_id'])->where('status', 1)->select(['id', 'member_id', 'status'])->first();
if($store->member_id != auth('api')->user()->uid){
throw new \Exception("您不是店主,无权发货!", 0);
}
}else{
throw new \Exception("请先登录!", 0);
}
$order->status = 3;
$order->confirm_time = date('Y-m-d H:i:s');
$order->save();
\Modules\Goods\Events\OrderTake::dispatch($order);
$item->status = 3;
$item->delivery_time = date('Y-m-d H:i:s');
$item->delivery_type = $request->input('delivery_type', 'pickup');
$item->save();
\Modules\Order\Events\OrderTake::dispatch($order, $item);
return $order;
}
/**商家订单详情
* @param $request
* @return \Illuminate\Database\Concerns\TValue|null
* @throws \Exception
*/
public function getDetailsData($request){
$map = [];
$map[] = ['order_no', '=', $request->input('order_no')];
$data = Order::with(['member', 'detail', 'detail.goods:id,title,price,integral', 'detail.sku', 'detail.store:id,title,cover'])->where($map)->first();
if(!$data){
throw new \Exception("订单不存在!", 0);
}
return $data;
}
/**
* @title 订单退款
*
......
......@@ -89,7 +89,7 @@ class RefundService {
$refund->status = 0;
$refund->refund_no = str_replace('-', '', Str::orderedUuid());
$refund->amount = $item->total_price-$item->total_integral;
// $refund->amount = $item->total_price;
if($refund->save()){
$item->status = 4;
$item->save();
......
......@@ -45,6 +45,7 @@ return new class extends Migration
$table->string('refund_no')->nullable()->comment('退款单号');
$table->timestamp('created_at')->nullable()->comment('创建时间');
$table->timestamp('updated_at')->nullable()->comment('更新时间');
$table->string('delivery_type')->nullable()->comment('配送方式');
$table->softDeletes();
$table->engine = 'InnoDB';
......
......@@ -27,6 +27,7 @@ class OrderDatabaseSeeder extends Seeder
['title' => '订单', 'name' => 'order', 'path' => '/order', 'component' => '', 'type' => 'menu', 'sort' => 5, 'children' => [
['title' => '订单列表', 'name' => 'order.list', 'path' => '/order/list', 'component' => 'order/list', 'type' => 'menu'],
['title' => '售后订单', 'name' => 'order.refund', 'path' => '/order/refund', 'component' => 'order/refund', 'type' => 'menu'],
['title' => '置换订单联系记录', 'name' => 'order.exchange', 'path' => '/order/exchange', 'component' => 'order/exchange', 'type' => 'menu'],
]
]
];
......
......@@ -23,4 +23,13 @@ Route::name('order.')->prefix('order')->middleware(['auth.check:admin'])->group(
Route::get('/index', 'index')->name('index');
Route::put('/audit', 'audit')->name('audit');
});
Route::controller(Modules\Order\Controllers\Admin\Exchange::class)->prefix('exchange')->name('exchange.')->group(function () {
Route::get('/index', 'index')->name('index');
});
Route::controller(Modules\Order\Controllers\Admin\Cashier::class)->prefix('cashier')->name('cashier.')->group(function () {
Route::get('/index', 'index')->name('index');
Route::post('/add', 'add')->name('add');
Route::put('/edit', 'edit')->name('edit');
Route::post('/simple', 'simple')->name('simple');
});
});
......@@ -38,4 +38,7 @@ Route::name('order.')->prefix('order')->middleware(['auth.check:api'])->group(fu
Route::put('/edit', 'edit')->name('edit');
Route::delete('/delete', 'delete')->name('delete');
});
Route::controller(Modules\Order\Controllers\Api\Exchange::class)->prefix('exchange')->name('exchange.')->group(function () {
Route::post('/add', 'add')->name('add');
});
});
......@@ -10,7 +10,7 @@ namespace Modules\Store\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Modules\Goods\Services\OrderService;
use Modules\Order\Services\OrderService;
class Order extends BaseController {
......@@ -32,4 +32,22 @@ class Order extends BaseController {
return response()->json($this->data);
}
/**
* @title 订单详情
*
* @param Request $request
* @param \Modules\Order\Services\OrderService $service
* @return void
*/
public function detail(Request $request, OrderService $service){
try {
$this->data['data'] = $service->getDetailsData($request);
} catch (\Throwable $th) {
$this->data['code'] = 0;
$this->data['message'] = $th->getMessage();
}
return response()->json($this->data);
}
}
......@@ -42,7 +42,13 @@ class Payment extends BaseController {
'amount.required' => '请输入金额',
'integral.required' => '请输入积分',
]);
$this->data['data'] = $service->create(store_id: $request->input('store_id'), amount: $request->input('amount'), integral: $request->input('integral'), remark: $request->input('remark'));
$polymer_money=$request->input('polymer_money',0);
$this->data['data'] = $payment = $service->create(store_id: $request->input('store_id'), amount: $request->input('amount'), integral: $request->input('integral'), polymer_money: $polymer_money,pay_way: $request->input('pay_way'),remark: $request->input('remark'));
if($payment->amount == 0){//聚物通支付完成
app(PaymentService::class)->paySuccess($payment->order_no, null);
$this->data['code'] =9999;
}
} catch (\Throwable $e) {
$this->data['code'] = 0;
$this->data['message'] = $e->getMessage();
......
......@@ -8,6 +8,8 @@
// +----------------------------------------------------------------------
namespace Modules\Store\Listeners;
use Illuminate\Support\Facades\Log;
use Modules\Member\Services\PolymerService;
use Modules\Store\Events\PaySuccess;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
......@@ -21,7 +23,51 @@ class PayBlance implements ShouldQueue{
* Handle the event.
*/
public function handle(PaySuccess $event){
$order = $event->order;
$order = $event->payment;
$store = $order->store()->first();
//Log::info("分仓服务费".$store->balance_service_rate);
if($store->balance_service_rate > 0){//分仓服务费
$integral = $order->integral; //店主收入计算
$polymer_money = $order->polymer_money; //店主收入计算
//本金
$cost_money = bcdiv(($order->polymer_money + $order->amount),bcdiv(($store->balance_service_rate + 100),100,2),2);
//Log::info("分仓服务费本金".$cost_money);
//分仓服务费
$balance_service_amount = bcsub(($order->polymer_money + $order->amount), $cost_money, 2);
$amount = bcsub($order->amount, $balance_service_amount, 2); //店主收入计算
if($balance_service_amount > 0 && $store->service_id){
//Log::info("分仓服务费资金".$balance_service_amount);
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $order->id, member_id: $store->service_id, type: 'service_income', account_type: 'payment', amount: $balance_service_amount, remark: '店铺收款分仓服务费');
}
}else{
$amount = $order->amount; //店主收入计算
$integral = $order->integral; //店主收入计算
$polymer_money = $order->polymer_money; //店主收入计算
}
//店主收入
if($amount > 0){
app(AccountService::class)->createAccount(store_id: $order->store_id, order_id: $order->id, member_id: $store->member_id, type: 'income', account_type: 'payment', amount: $amount, remark: '店铺内客户支付');
}
if($integral > 0){
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $order->id, member_id: $store->member_id, amount: $integral, type: 'income', account_type: 'payment', remark: '店铺内客户支付');
}
if($polymer_money > 0){
app(PolymerService::class)->createPolymer(store_id: $store->id, order_id: $order->id, member_id: $store->member_id, type: 'income', account_type: 'payment', amount: $polymer_money, remark: '店铺内客户支付');
}
}
/**原始
* Handle the event.
*/
/*public function handle(PaySuccess $event){
$order = $event->payment;
$store = $order->store()->first();
......@@ -31,11 +77,11 @@ class PayBlance implements ShouldQueue{
$invite = null;
}
if($store->balance_rate > 0){
$balance_amount = bcmul($item->amount, bcdiv($store->balance_rate, 100, 2), 2);
$balance_integral = bcmul($item->integral, bcdiv($store->balance_rate, 100, 2), 2);
$balance_amount = bcmul($order->amount, bcdiv($store->balance_rate, 100, 2), 2);
$balance_integral = bcmul($order->integral, bcdiv($store->balance_rate, 100, 2), 2);
$amount = bcsub($item->amount, $balance_amount, 2); //店主收入计算
$integral = bcsub($item->integral, $balance_integral, 2); //店主收入计算
$amount = bcsub($order->amount, $balance_amount, 2); //店主收入计算
$integral = bcsub($order->integral, $balance_integral, 2); //店主收入计算
// 分仓服务费
$balance_service_amount = bcmul($balance_amount, bcdiv($store->balance_service_rate, 100, 2), 2);
......@@ -44,7 +90,7 @@ class PayBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $order->id, member_id: $store->service_id, type: 'service_income', account_type: 'payment', amount: $balance_service_amount, remark: '店铺收款分仓服务费');
}
if($balance_service_integral > 0 && $store->service_id){
app(ScoreService::class)->createScore(order_id: $order->id, member_id: $store->service_id, amount: $balance_service_integral, type: 'service_income', remark: '店铺收款分仓服务费');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $order->id, member_id: $store->service_id, amount: $balance_service_integral, type: 'service_income', account_type: 'payment', remark: '店铺收款分仓服务费');
}
//推广人员服务费
......@@ -57,7 +103,7 @@ class PayBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $order->id, member_id: $invite->uid, type: 'income', account_type: 'payment', amount: $balance_service_amount, remark: '店铺收款兼职代理服务费');
}
if($balance_service_integral > 0){
app(ScoreService::class)->createScore(order_id: $order->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', remark: '店铺收款兼职代理服务费');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $order->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', account_type: 'payment', remark: '店铺收款兼职代理服务费');
}
}else if($invite->level->name == 'signings'){
// 签约代理
......@@ -67,13 +113,13 @@ class PayBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $store->id, order_id: $order->id, member_id: $invite->uid, type: 'income', account_type: 'payment', amount: $balance_service_amount, remark: '店铺收款签约代理服务费');
}
if($balance_service_integral > 0){
app(ScoreService::class)->createScore(order_id: $order->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', remark: '店铺收款签约代理服务费');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $order->id, member_id: $invite->uid, amount: $balance_service_integral, type: 'income', account_type: 'payment', remark: '店铺收款签约代理服务费');
}
}
}
}else{
$amount = $item->amount; //店主收入计算
$integral = $item->integral; //店主收入计算
$amount = $order->amount; //店主收入计算
$integral = $order->integral; //店主收入计算
}
//店主收入
......@@ -81,7 +127,7 @@ class PayBlance implements ShouldQueue{
app(AccountService::class)->createAccount(store_id: $order->store_id, order_id: $order->id, member_id: $store->member_id, type: 'income', account_type: 'payment', amount: $amount, remark: '店铺内客户支付');
}
if($order->integral > 0){
app(ScoreService::class)->createScore(order_id: $order->id, member_id: $store->member_id, amount: $integral, type: 'income', remark: '店铺内客户支付');
app(ScoreService::class)->createScore(store_id: $store->id, order_id: $order->id, member_id: $store->member_id, amount: $integral, type: 'income', account_type: 'payment', remark: '店铺内客户支付');
}
}
}*/
}
\ No newline at end of file
......@@ -47,7 +47,7 @@ class PaymentService {
return $data;
}
public function create($store_id, $amount, $integral, $remark){
public function create($store_id, $amount, $integral, $polymer_money,$pay_way,$remark){
$payment = new Payment();
......@@ -56,15 +56,25 @@ class PaymentService {
$payment->member_id = auth('api')->user()->uid;
$payment->amount = $amount;
$payment->integral = $integral;
$payment->polymer_money = $polymer_money;
$payment->pay_way = $pay_way;
$payment->payment_remark = $remark ? $remark : '店铺收款';
$payment->payment_status = 0;
if(($amount + $integral +$polymer_money ) <=0){
throw new \Exception("请输入支付金额!", 0);
}
//判断积分是否满足
$member = auth('api')->user();
if($member['score'] < $integral){
if($pay_way == "integral" && $member['score'] < $integral){
throw new \Exception("积分不足!", 0);
}
if($pay_way == "polymer_money" && $member['polymer_money'] < $polymer_money){
throw new \Exception("聚物通不足!", 0);
}
$payment->save();
return $payment;
}
......@@ -95,16 +105,35 @@ class PaymentService {
}
public function paySuccess($order_no, $payment_no){
$payment = Payment::with(['member'])->where($order_no, $order_no)->first();
$payment = Payment::where('order_no', $order_no)->first();
if($payment && $payment->status == 0){
$payment->payment_status = 1;
$payment->payment_time = date('Y-m-d H:i:s');
$payment->payment_sn = $payment_no;
$payment->save();
app(ShippingService::class)->pushShipping($order_no, $payment->member_id, '店铺内付款支付');
\Modules\Store\Events\PaySuccess::dispatch($payment);
if($payment->integral > 0){//扣除积分
app(\Modules\Member\Services\ScoreService::class)->createScore(store_id: $item->store_id, order_id: $item->id, member_id: $order->member['uid'], type: 'pay', account_type: 'payment', amount: $item->total_integral, remark: '订单支付');
}
if($payment->polymer_money > 0){//扣除聚物通资金
app(\Modules\Member\Services\PolymerService::class)->createPolymer(store_id: $payment->store_id, order_id: $payment->id, member_id: $payment->member['uid'], type: 'pay', account_type: 'payment', amount: $payment->polymer_money, remark: '店铺支付');
}
$res = app(\Modules\Wechat\Services\PayService::class)->orderQuery($order_no);
if(isset($res['trade_state']) && $res['trade_state'] == 'SUCCESS'){
$payment->payment_status = 1;
$payment->payment_time = date('Y-m-d H:i:s');
$payment->payment_sn = $payment_no;
$payment->save();
// app(ShippingService::class)->pushShipping($order_no, $payment->member_id, '店铺内付款支付');
\Modules\Store\Events\PaySuccess::dispatch($payment);
}else if($payment->amount == 0){
$payment->payment_status = 1;
$payment->payment_time = date('Y-m-d H:i:s');
$payment->save();
if($payment->polymer_money > 0) {//入账聚物通资金
app(\Modules\Member\Services\PolymerService::class)->createPolymer(store_id: $payment->store_id, order_id: $payment->id, member_id: $payment->store['member_id'], type: 'income', account_type: 'payment', amount: $payment->polymer_money, remark: '店铺内客户支付');
}
}
}
}
......@@ -166,33 +195,41 @@ class PaymentService {
break;
case 'score':
app(ScoreService::class)->createScore(
store_id: 0,
order_id: 0,
member_id: auth('api')->user()['uid'],
amount: $amount,
type: 'transfer',
account_type: 'member',
remark: '用户转账扣除'
);
app(ScoreService::class)->createScore(
store_id: 0,
order_id: 0,
member_id: $uid,
amount: $amount,
type: 'income',
account_type: 'member',
remark: '用户转账'
);
break;
default:
app(ScoreService::class)->createScore(
store_id: 0,
order_id: 0,
member_id: auth('api')->user()['uid'],
amount: $amount,
type: 'transfer',
account_type: 'member',
remark: '用户转账扣除'
);
app(ScoreService::class)->createScore(
store_id: 0,
order_id: 0,
member_id: $uid,
amount: $amount,
type: 'income',
account_type: 'member',
remark: '用户转账'
);
break;
......@@ -261,17 +298,21 @@ class PaymentService {
break;
case 'score':
app(ScoreService::class)->createScore(
store_id: 0,
order_id: 0,
member_id: auth('api')->user()['uid'],
amount: $amount,
type: 'transfer',
account_type: 'receive',
remark: '店铺转账扣除'
);
app(ScoreService::class)->createScore(
store_id: 0,
order_id: 0,
member_id: $service_id,
amount: $amount,
type: 'service_income',
account_type: 'receive',
remark: '店铺转账'
);
break;
......
......@@ -21,6 +21,8 @@ return new class extends Migration {
$table->string('payment_remark')->nullable()->comment('收款备注');
$table->timestamp('created_at')->nullable()->comment('创建时间');
$table->timestamp('updated_at')->nullable()->comment('更新时间');
$table->decimal('polymer_money', total: 10, places: 2)->default(0)->comment('聚物通');
$table->string('pay_way')->nullable()->comment('付款方式');
$table->engine = 'InnoDB';
$table->charset = 'utf8mb4';
......
......@@ -10,6 +10,7 @@ namespace Modules\System\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\BaseController;
use Illuminate\Support\Facades\Storage;
class File extends BaseController {
......@@ -82,6 +83,9 @@ class File extends BaseController {
$path = $file->store('images/'.date('Ymd'));
// 保存图片到storage/app/public/images目录
//$bool = Storage::disk('public')->put($path, file_get_contents($file -> getRealPath()));//解决方式 换成 Storage::disk('')->put()
$data = [
'path' => $path,
'url' => Storage::disk()->url($path),
......
......@@ -44,4 +44,14 @@ class Notify extends BaseController {
}
return 'success';
}
public function transfer(Request $request, NotifyService $service){
try {
return $service->transferNotify($request);
} catch (\Throwable $th) {
$this->data['message'] = $th->getMessage();
$this->data['code'] = 0;
}
return 'success';
}
}
\ No newline at end of file
......@@ -24,4 +24,15 @@ class Pay extends BaseController {
return response()->json($this->data);
}
public function nativepc(Request $request, PayService $service){
try {
$this->data['data'] = $service->getNativePayData('native', $request);
} catch (\Exception $th) {
$this->data['message'] = $th->getMessage();
$this->data['code'] = $th->getCode();
}
return response()->json($this->data);
}
}
\ No newline at end of file
<?php
// +----------------------------------------------------------------------
// | SentCMS [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2024 http://www.tensent.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: molong <molong@tensent.cn> <http://www.tensent.cn>
// +----------------------------------------------------------------------
namespace Modules\Wechat\Listeners;
use Modules\Store\Events\PaySuccess;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Modules\Wechat\Services\ShippingService;
class StorePaymentSuccess implements ShouldQueue{
/**
* 任务应该被处理的时间(秒)。
*
* @var int
*/
public $delay = 60;
public function handle(PaySuccess $event){
$payment = $event->payment;
app(ShippingService::class)->pushShipping($payment->order_no, $payment->member_id, $payment->payment_remark, 3);
return true;
}
}
\ No newline at end of file
......@@ -30,6 +30,9 @@ class EventServiceProvider extends ServiceProvider
'Modules\Order\Events\OrderTake' => [
'Modules\Wechat\Listeners\OrderTakePush',
],
'Modules\Store\Events\PaySuccess' => [
'Modules\Wechat\Listeners\StorePaymentSuccess',
],
];
/**
......
......@@ -9,8 +9,12 @@
namespace Modules\Wechat\Services;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use EasyWeChat\Pay\Application;
use Modules\Member\Models\Member;
use Modules\Member\Models\MemberAccount;
use Modules\Order\Services\OrderService;
use Modules\Store\Services\PaymentService;
use Modules\Order\Services\RefundService;
......@@ -55,6 +59,36 @@ class NotifyService {
app(RefundService::class)->refundSuccess($message);
});
return $server->serve();
}
public function transferNotify($request){
$config = Config::get('wechat.miniapp');
$app = new Application($config);
$server = $app->getServer();
//Log::info("转账到零钱异步返回通知:");
// 处理退款结果事件
//DB::connection()->enableQueryLog();
$data= MemberAccount::where(['status'=>1,'detail_status'=>null])->whereNotNull("out_batch_no")->select()->get();
//print_r(DB::getQueryLog());
foreach ($data as $key=>$val){
$result = TransferService::transferQuery($val['out_batch_no'],$val['request_no']);
if(isset($result['code']) && !empty($result['code'])){
MemberAccount::where(['id'=>$val['id']])->update(['status'=>-2,'reason'=>$result['message'],'detail_status'=>$result['fail_reason']]);
//提现失败金额退回
/*$user = Member::find($val['member_id']);
$user->money = bcadd($user->money, $val['amount'], 2);
$user->save();*/
}else{
MemberAccount::where(['id'=>$val['id']])->update(['detail_status'=>'SUCCESS']);
}
}
return $server->serve();
}
}
\ No newline at end of file
......@@ -30,6 +30,7 @@ class PayService {
case 'order':
$data = app('Modules\Order\Services\OrderService')->getjsPayData($request, $from);
$description = "订单支付";
$data->amount = $data->amount - $data->integral - $data->polymer_money;
break;
case 'payment':
$data = app('Modules\Store\Services\PaymentService')->getjsPayData($request, $from);
......@@ -40,8 +41,6 @@ class PayService {
$description = "订单支付";
break;
}
$data->amount = $data->amount-$data->integral;
$payData = [
'mchid' => $config['mch_id'],
'appid' => $config['app_id'],
......@@ -113,4 +112,73 @@ class PayService {
// throw new \Exception($response->getContent(), $response->getStatusCode());
// }
}
public function orderQuery($order_no){
$config = Config::get('wechat.miniapp');
$app = new Application($config);
$api = $app->getClient();
$response = $api->get("v3/pay/transactions/out-trade-no/{$order_no}", [
'query' => [
'mchid' => $config['mch_id'],
]
]);
return $response->toArray();
}
/**
* 用户扫码支付
*/
public function getNativePayData($from,$request){
$config = Config::get('wechat.miniapp');
$app = new Application($config);
$utils = $app->getUtils();
$type = $request->input('type', 'order');
$description = "";
switch ($type) {
case 'order':
$data = app('Modules\Order\Services\OrderService')->getjsPayData($request, $from);
$description = "订单支付";
break;
default:
$data = app('Modules\Order\Services\OrderService')->getjsPayData($request, $from);
$description = "订单支付";
break;
}
$payData = [
'mchid' => $config['mch_id'],
'appid' => $config['app_id'],
'out_trade_no' => $data->order_no,
'description' => $description,
'notify_url' => request()->root() .'/api/wechat/notify/'.$type,
'amount' => [
'total' => intval($data->amount * 100),
'currency' => 'CNY',
],
];
$response = $app->getClient()->postJson("v3/pay/transactions/native", $payData);
if($response->isFailed()){
throw new \Exception($response->getContent(), $response->getStatusCode());
}
$prepayId = $response->toArray()['code_url'];
switch ($type) {
case 'order':
Order::where('id', $data->id)->update(['pay_no' => $prepayId, 'pay_type' => $from]);
break;
default:
Order::where('id', $data->id)->update(['pay_no' => $prepayId, 'pay_type' => $from]);
break;
}
return $utils->buildMiniAppConfig($prepayId, $config['app_id'], 'RSA');
}
}
\ No newline at end of file
<?php
namespace Modules\Wechat\Services;
use EasyWeChat\Pay\Application;
use Illuminate\Support\Facades\Config;
use Modules\Wechat\Utils\AesUtil;
use Modules\Wechat\Utils\WechatUtil;
class TransferService
{
/**
* 商家转账到零钱
* @param $batch_name
* @param $out_trade_no
* @param $money
* @param $openid
* @throws BaseException
*/
public static function transfer($batch_name, $out_trade_no, $money, $openid,$body='用户提现')
{
$config = Config::get('wechat.miniapp');
$app = new Application($config);
//获取微信支付平台证书序列号
$certificates=self::getCertificates();
$serial_no = isset($certificates['data'][0]['serial_no'])?$certificates['data'][0]['serial_no']:null;
$pars = [];
$pars['appid'] = $config['app_id'];//直连商户的appid
$pars['out_batch_no'] = 'batch' . date('Ymd') . mt_rand(1000, 9999);//商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一
$pars['batch_name'] = $body;//该笔批量转账的名称
$pars['batch_remark'] = $body;//转账说明,UTF8编码,最多允许32个字符
$pars['total_amount'] = intval($money * 100);//转账总金额 单位为“分”
$pars['total_num'] = 1;//转账总笔数
$pars['transfer_detail_list'][0] = [
'out_detail_no' => $out_trade_no,
'transfer_amount' => $pars['total_amount'],
'transfer_remark' => $body,
'openid' => $openid,
//'user_name'=> WechatUtil::getEncrypt($batch_name,$config['public_key']),
];//转账明细列表
$pars['notify_url'] = request()->root() .'/api/wechat/notify/transfer';
$result = $app->getClient()->postJson("v3/transfer/batches",$pars,[
'headers'=>[
'Wechatpay-Serial' => $serial_no,
],
]);
$response = json_decode($result, true);
if (!isset($response['create_time'])) { //批次受理失败
return ['code'=>$response['code'],'message'=>$response['message']];
}
return $response['out_batch_no'];
}
//获取微信支付平台证书序列号与生成公钥文件
public static function getCertificates($http_method ="GET"){
$url="https://api.mch.weixin.qq.com/v3/certificates";
$config = Config::get('wechat.miniapp');
$token=WechatUtil::getToken($url, $http_method, array(),$config['mch_id'],$config['certificate'],$config['private_key']);
$result = WechatUtil::https_request_transfer($url,array(),$token);
$result_arr = json_decode($result,true);
if(isset($result_arr['data'])){
$certificate=$result_arr['data'][0]['encrypt_certificate'];
$AesUtil = new AesUtil($config['secret_key']);
$dataDecrypt=$AesUtil->decryptToString($certificate['associated_data'],$certificate['nonce'],$certificate['ciphertext']);
$publicCertKey=fopen($config['public_key'], 'w');
fwrite($publicCertKey, $dataDecrypt);
fclose($publicCertKey);
}
return $result_arr;
}
/**查询商家转账到零钱订单状态
* @param $out_batch_no
* @param $out_detail_no
* @param string $http_method
* @return array|mixed
*/
public static function transferQuery($out_batch_no,$out_detail_no,$http_method ="GET")
{
$url = 'https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/'.$out_batch_no.'/details/out-detail-no/'.$out_detail_no;
$config = Config::get('wechat.miniapp');
$token=WechatUtil::getToken($url, $http_method, array(),$config['mch_id'],$config['certificate'],$config['private_key']);
$result = WechatUtil::https_request_transfer($url,array(),$token);
$result_arr = json_decode($result,true);
if(isset($result_arr['code']) && !empty($result_arr['code'])){
return ['code'=>-3,'message'=>$result_arr['message'],'fail_reason'=>$result_arr['code']];
}else if(isset($result_arr['fail_reason']) && !empty($result_arr['fail_reason'])){
if($result_arr['fail_reason'] === "ACCOUNT_FROZEN"){
return ['code'=>-3,'message'=>"该用户账户被冻结",'fail_reason'=>$result_arr['code']];
}else if($result_arr['fail_reason'] === "REAL_NAME_CHECK_FAIL"){
return ['code'=>-3,'message'=>"收款人未实名认证,需要用户完成微信实名认证",'fail_reason'=>$result_arr['code']];
}else if($result_arr['fail_reason'] === "NAME_NOT_CORRECT"){
return ['code'=>-3,'message'=>"收款人姓名校验不通过,请核实信息",'fail_reason'=>$result_arr['code']];
}else if($result_arr['fail_reason'] === "OPENID_INVALID"){
return ['code'=>-3,'message'=>"Openid格式错误或者不属于商家公众账号",'fail_reason'=>$result_arr['code']];
}else if($result_arr['fail_reason'] === "TRANSFER_QUOTA_EXCEED"){
return ['code'=>-3,'message'=>"超过用户单笔收款额度,核实产品设置是否准确",'fail_reason'=>$result_arr['code']];
}else if($result_arr['fail_reason'] === "DAY_RECEIVED_QUOTA_EXCEED"){
return ['code'=>-3,'message'=>"超过用户单日收款额度,核实产品设置是否准确",'fail_reason'=>$result_arr['code']];
}else if($result_arr['fail_reason'] === "DAY_RECEIVED_COUNT_EXCEED"){
return ['code'=>-3,'message'=>"超过用户单日收款次数,核实产品设置是否准确",'fail_reason'=>$result_arr['code']];
}else if($result_arr['fail_reason'] === "TRANSFER_RISK"){
return ['code'=>-3,'message'=>"该笔转账可能存在风险,已被微信拦截",'fail_reason'=>$result_arr['code']];
}else {
return ['code'=>-3,'message'=>$result_arr['fail_reason'],'fail_reason'=>$result_arr['code']];
}
}
return true;
}
}
\ No newline at end of file
<?php
namespace Modules\Wechat\Utils;
#php证书和回调报文解密
#https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi
use http\Exception\InvalidArgumentException;
class AesUtil
{
/**
* AES key
*
* @var string
*/
private $aesKey;
const KEY_LENGTH_BYTE = 32;
const AUTH_TAG_LENGTH_BYTE = 16;
/**
* Constructor
*/
public function __construct($aesKey)
{
if (strlen($aesKey) != self::KEY_LENGTH_BYTE) {
throw new InvalidArgumentException('无效的ApiV3Key,长度应为32个字节');
}
$this->aesKey = $aesKey;
}
/**
* Decrypt AEAD_AES_256_GCM ciphertext
*
* @param string $associatedData AES GCM additional authentication data
* @param string $nonceStr AES GCM nonce
* @param string $ciphertext AES GCM cipher text
*
* @return string|bool Decrypted string on success or FALSE on failure
*/
public function decryptToString($associatedData, $nonceStr, $ciphertext)
{
$ciphertext = \base64_decode($ciphertext);
if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
return false;
}
// ext-sodium (default installed on >= PHP 7.2)
if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') &&
\sodium_crypto_aead_aes256gcm_is_available()) {
return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
}
// ext-libsodium (need install libsodium-php 1.x via pecl)
if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') &&
\Sodium\crypto_aead_aes256gcm_is_available()) {
return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
}
// openssl (PHP >= 7.1 support AEAD)
if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
$ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
$authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
return \openssl_decrypt($ctext, 'aes-256-gcm', $this->aesKey, \OPENSSL_RAW_DATA, $nonceStr,
$authTag, $associatedData);
}
throw new \RuntimeException('AEAD_AES_256_GCM需要PHP 7.1以上或者安装libsodium-php');
}
}
\ No newline at end of file
<?php
namespace Modules\Wechat\Utils;
class WechatUtil
{
/**
* @notes 敏感信息加解密
*/
public static function getEncrypt($user_name,$cert_path)
{
//$str是待加密字符串
$public_key = file_get_contents($cert_path);
$encrypted = '';
if (openssl_public_encrypt($user_name, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) {
//base64编码
$sign = base64_encode($encrypted);
} else {
throw new \Exception('encrypt failed');
}
return $sign;
}
/**
* 敏感信息解密
* @param $str
* @return string
* @throws Exception
*/
public static function getDecrypt($data,$cert_path_key) {
$private_key = file_get_contents($cert_path_key);
$encrypted = '';
if (openssl_private_decrypt($data, $encrypted, $private_key, OPENSSL_PKCS1_OAEP_PADDING)) {
//base64编码
$sign = $encrypted;
} else {
throw new \Exception('解密失败');
}
return $sign;
}
/**
* @notes 获取签名
*/
public static function getToken($url, $http_method, $data,$mch_id,$wxpayCert,$wxPayCertKey)
{
$timestamp = time(); //请求时间戳
$url_parts = parse_url($url); //获取请求的绝对URL
$nonce = $timestamp . rand('10000', '99999'); //请求随机串
$body = empty($data) ? '' : json_encode((object)$data); //请求报文主体
$stream_opts = [
"ssl" => [
"verify_peer" => false,
"verify_peer_name" => false,
]
];
$apiclient_cert_arr = openssl_x509_parse(file_get_contents($wxpayCert, false, stream_context_create($stream_opts)));
$serial_no = $apiclient_cert_arr['serialNumberHex']; //证书序列号
$mch_private_key = file_get_contents($wxPayCertKey, false, stream_context_create($stream_opts)); //密钥
$merchant_id = $mch_id; //商户id
$canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
$message = $http_method . "\n" .
$canonical_url . "\n" .
$timestamp . "\n" .
$nonce . "\n" .
$body . "\n";
openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
$sign = base64_encode($raw_sign); //签名
$schema = 'WECHATPAY2-SHA256-RSA2048';
$token = sprintf(
'mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$merchant_id,
$nonce,
$timestamp,
$serial_no,
$sign
); //微信返回token
return $schema . ' ' . $token;
}
/**商家转账到零钱
* @notes 新发送请求
*/
public static function https_request_transfer($url, $data, $token,$serial_no='')
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, (string)$url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)) {
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//添加请求头
$headers = [
'Authorization:' . $token,
'Wechatpay-Serial: '.$serial_no,
'Accept: application/json',
'Content-Type: application/json; charset=utf-8',
'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
];
if (!empty($headers)) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
}
\ No newline at end of file
......@@ -23,7 +23,9 @@ Route::name('wechat.')->prefix('wechat')->middleware(['auth.check:api'])->group(
Route::post('miniapp', 'miniapp')->name('miniapp');
});
});
Route::post('/wechat/pay/nativepc', [Modules\Wechat\Controllers\Api\Pay::class, 'nativepc']);
Route::post('/wechat/notify/order', [Modules\Wechat\Controllers\Api\Notify::class, 'order']);
Route::post('/wechat/notify/payment', [Modules\Wechat\Controllers\Api\Notify::class, 'payment']);
Route::post('/wechat/notify/refund', [Modules\Wechat\Controllers\Api\Notify::class, 'refund']);
\ No newline at end of file
Route::post('/wechat/notify/refund', [Modules\Wechat\Controllers\Api\Notify::class, 'refund']);
Route::get('/wechat/notify/transfer', [Modules\Wechat\Controllers\Api\Notify::class, 'transfer']);
\ No newline at end of file
......@@ -9,33 +9,38 @@
"preview": "vite preview"
},
"dependencies": {
"@ckeditor/ckeditor5-vue": "^7.2.0",
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.7.2",
"ckeditor5": "^43.2.0",
"codemirror": "5.65.5",
"core-js": "3.29.0",
"cropperjs": "1.5.13",
"crypto-js": "4.1.1",
"echarts": "5.4.1",
"element-plus": "2.8.4",
"nprogress": "0.2.0",
"pinyin-match": "^1.2.4",
"qrcodejs2": "0.0.2",
"sortablejs": "1.15.0",
"vue": "^3.4.21",
"vue-i18n": "^9.13.1",
"vue-router": "^4.3.2",
"vuedraggable": "^4.0.3",
"vuex": "^4.1.0",
"xgplayer": "2.32.2",
"xgplayer-hls": "2.5.2",
"xlsx": "^0.18.5"
"@ckeditor/ckeditor5-vue": "^7.2.0",
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.7.2",
"ckeditor5": "^43.2.0",
"codemirror": "5.65.5",
"core-js": "3.29.0",
"cropperjs": "1.5.13",
"crypto-js": "4.1.1",
"echarts": "5.4.1",
"element-plus": "2.8.4",
"nprogress": "0.2.0",
"pinyin-match": "^1.2.4",
"qr-code-styling": "^1.9.1",
"qrcodejs2": "0.0.2",
"sortablejs": "1.15.0",
"vue": "^3.4.21",
"vue-i18n": "^9.13.1",
"vue-router": "^4.3.2",
"vuedraggable": "^4.0.3",
"vuex": "^4.1.0",
"xgplayer": "2.32.2",
"xgplayer-hls": "2.5.2",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"sass": "1.77.2",
"terser": "^5.31.0",
"vite": "^5.2.0"
"@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.0.0",
"postcss": "^8.0.0",
"rollup-plugin-postcss": "^4.0.2",
"sass": "1.77.2",
"tailwindcss": "^3.0.0",
"terser": "^5.31.0",
"vite": "^5.2.0"
}
}
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
\ No newline at end of file
import config from "@/config"
import http from "@/utils/request"
export default {
cart: {
list:{
url: `${config.API_URL}order/cashier/index`,
name: "购物车列表",
get: async function(data){
return await http.get(this.url, data);
}
},
edit: {
url: `${config.API_URL}order/cashier/edit`,
name: "修改购物车",
post: async function(params){
return await http.put(this.url, params);
}
},
delete: {
url: `${config.API_URL}order/cashier/delete`,
name: "删除购物车产品",
post: async function(params){
return await http.delete(this.url, params);
}
},
add: {
url: `${config.API_URL}order/cashier/add`,
name: "添加购物车",
post: async function(params){
return await http.post(this.url, params);
}
},
simple:{
url: `${config.API_URL}order/cashier/simple`,
name: "购物车结算",
post: async function(params){
return await http.post(this.url, params);
}
},
nativepc:{
url: `${config.API_URL_TWO}wechat/pay/nativepc`,
name: "支付订单",
post: async function(params){
return await http.post(this.url, params);
}
},
}
}
\ No newline at end of file
......@@ -92,6 +92,36 @@ export default{
}
}
},
polymer: {
list: {
url: `${config.API_URL}member/polymer/index`,
name: "获得聚物通列表",
get: async function(params){
return await http.get(this.url, params);
}
},
add: {
url: `${config.API_URL}member/polymer/add`,
name: "添加聚物通",
post: async function(params){
return await http.post(this.url, params);
}
},
edit: {
url: `${config.API_URL}member/polymer/edit`,
name: "编辑聚物通",
post: async function(params){
return await http.put(this.url, params);
}
},
delete: {
url: `${config.API_URL}member/polymer/delete`,
name: "删除积分",
post: async function(params){
return await http.delete(this.url, params);
}
}
},
account: {
list: {
url: `${config.API_URL}member/account/index`,
......@@ -120,6 +150,13 @@ export default{
post: async function(params){
return await http.delete(this.url, params);
}
},
withdraw:{
url: `${config.API_URL}member/account/withdraw`,
name: "通过提现",
post: async function(params){
return await http.post(this.url, params);
}
}
},
promoter: {
......
......@@ -68,5 +68,15 @@ export default{
return await http.put(this.url, params);
}
}
},
exchange: {
list: {
url: `${config.API_URL}order/exchange/index`,
name: "获得置换列表",
get: async function(params){
return await http.get(this.url, params);
}
},
}
}
@tailwind base;
@tailwind components;
@tailwind utilities;
\ No newline at end of file
......@@ -4,3 +4,6 @@
@import 'media.scss';
@import 'dark.scss';
@import 'diy.scss';
<template>
<div ref="qrcode" class="qrcodetags">
</div>
</template>
<script>
import QRCodeStyling from "qr-code-styling";
export default {
name: "QrCode",
props: {
value: {
type: String,
required: true
},
width: {
type: Number,
default: 200
}
},
data() {
return {
qrCode: null // 用于存储二维码实例
};
},
mounted() {
// this.initQRCode();
},
methods: {
initQRCode() {
console.info("initQRCode");
if (this.qrCode) {
this.qrCode.clear(); // 清除已存在的二维码
}
this.qrCode = new QRCodeStyling({
width: this.width,
data: this.value,
image: "", // 如果你想添加logo到二维码中间,可以在这里提供图片URL
dotsOptions: {
color: "#000000"
},
backgroundOptions: {
color: "#ffffff"
},
imageOptions: {
crossOrigin: "anonymous",
margin: 10
}
});
this.qrCode.append(this.$refs.qrcode);
},
updateQRCode(newValue) {
if (this.qrCode) {
this.qrCode.update({ data: newValue }); // 更新二维码的数据
} else {
this.initQRCode(); // 如果还没有初始化,则初始化
}
}
},
watch: {
value(newVal, oldVal) {
if (newVal !== oldVal) {
this.updateQRCode(newVal);
}
}
},
beforeDestroy() {
if (this.qrCode) {
this.qrCode.clear(); // 在组件销毁前清除二维码
}
}
};
</script>
<style scoped>
.qrcodetags{
margin: 0 auto;
width: 200px;
/* height: 200px; */
}
</style>
\ No newline at end of file
......@@ -52,7 +52,8 @@ export default {
{ name: 'price', type: 'input', label: '价格' },
{ name: 'integral', type: 'input', label: '积分' },
{ name: 'sales', type: 'input', label: '销量' },
{ name: 'stock', type: 'input', label: '库存' }
{ name: 'stock', type: 'input', label: '库存' },
{ name: 'goods_sn', type: 'input', label: '产品编号' },
]
},
// sku 字段分隔符
......
......@@ -12,8 +12,8 @@ const DEFAULT_CONFIG = {
CORE_VER: "1.6.6",
//接口地址
API_URL: 'https://juwu.xicheda.cn/admin/',
API_URL: "https://juwu.xicheda.cn/admin/",
API_URL_TWO: "https://juwu.xicheda.cn/api/",
//请求超时
TIMEOUT: 50000,
......
......@@ -5,7 +5,7 @@ import tool from '@/utils/tool'
export default {
successCode: 1, //请求完成代码
pageSize: 30, //表格每一页条数
pageSizes: [30, 100, 200, 500], //表格可设置的一页条数
pageSizes: [10,30, 100, 200, 500], //表格可设置的一页条数
paginationLayout: "total, sizes, prev, pager, next, jumper", //表格分页布局,可设置"total, sizes, prev, pager, next, jumper"
parseData: function (res) { //数据分析
return {
......
......@@ -132,7 +132,7 @@
<div v-if="!ismobile" class="aminui-side-split">
<div class="aminui-side-split-top">
<router-link :to="$CONFIG.DASHBOARD_URL">
<img class="logo" :title="$CONFIG.APP_NAME" :src="'/static/images/logo-r.png'">
<img class="logo" :title="$CONFIG.APP_NAME" :src="'./static/images/logo-r.png'">
</router-link>
</div>
<div class="adminui-side-split-scroll">
......
......@@ -8,8 +8,16 @@ import router from './router'
import store from './store'
import App from './App.vue'
import './assets/style/main.css'; // 假设 main.css 在 src/assets 目录下
import BarcodeScanner from '@/utils/barcode-scanner';
const app = createApp(App);
//扫码组件
app.use(BarcodeScanner);
app.use(i18n);
app.use(store);
app.use(router);
......
.sku_card {
.sku_card_title {
font-size: 15px;
line-height: 40px;
color: #222;
font-weight: bold;
}
.sku_card_main {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
.sku_card_item {
font-size: 12px;
line-height: 24px;
background-color: #f1f2f2;
color: #373737;
margin-right: 10px;
margin-bottom: 10px;
padding: 0 10px;
flex-shrink: 0;
border-radius: 3px;
cursor: pointer;
}
.sku_card_item_active {
background-color: #409eff !important;
color: #fff !important;
}
}
}
.card {
margin: 18px auto 0;
background-color: #fff;
.top {
display: flex;
justify-content: flex-start;
align-items: center;
height: 50px;
font-size: 16px;
line-height: 1;
.shop_name {
margin-left: 5px;
font-size: 15px;
font-weight: normal;
font-stretch: normal;
color: #222222;
}
}
.select_box {
width: 40px;
display: flex;
justify-content: center;
align-items: center;
flex-shrink: 0;
font-size: 16px;
.circle {
color: #666;
}
.checked {
color: #f64f15;
}
}
.main {
padding-bottom: 23px;
.card_wrap {
margin-top: 15px;
&:first-child {
margin-top: 0;
}
}
.card_item {
width: 100%;
box-sizing: border-box;
}
.card_item_wrap {
display: flex;
justify-content: flex-start;
align-items: center;
}
.img_wrap {
width: 70px;
height: 70px;
border-radius: 10px;
overflow: hidden;
flex-shrink: 0;
img {
display: block;
width: 70px;
height:70px;
}
}
.info {
margin-left: 20px;
padding-right: 20px;
width: calc(100% - 40px - 100px - 15px);
// height: 70px;
display: flex;
flex-direction: column;
justify-content: space-between;
.it {
.goods_title {
display: block;
width: 100%;
font-size: 12px;
font-weight: bold;
font-stretch: normal;
color: #222222;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.deleteicon{
margin: 6px 0;
display: flex;
justify-content: flex-end;
}
.delete{
cursor: pointer;
color: red;
}
.sku {
height: 26px;
border-radius: 5px;
margin-top: 11px;
font-size: 12px;
line-height: 26px;
font-stretch: normal;
color: #838383;
display: flex;
justify-content: flex-start;
align-items: center;
.text {
padding: 0 10px;
background-color: #f6f6f6;
}
.sku_arr {
display: block;
padding-left: 10px;
padding-right: 10px;
background-color: #f6f6f6;
}
}
}
.ib {
display: flex;
justify-content: space-between;
.pricebox{
display: flex;
align-items: center;
}
.jfprice{
margin-left: 8px;
.price_icon,.price_main{
font-size: 12px !important;
color: #a5a5a5 !important;
}
}
.price {
display: flex;
justify-content: flex-start;
align-items: baseline;
.price_icon {
font-size: 13px;
font-weight: bold;
font-stretch: normal;
color: #f64f15;
}
.price_main {
font-size: 16px;
font-weight: bold;
font-stretch: normal;
color: #f64f15;
.mini {
font-size: 15px;
}
}
.ori {
font-size: 12px;
font-stretch: normal;
color: #8a8a8a;
}
}
.num {
flex-shrink: 0;
--stepper-input-disabled-text-color: #323233;
}
}
}
}
}
.qrcodepup{
text-align: center;
}
This diff is collapsed.
.input {
position: fixed;
left: 0;
transform: translateX(-200%);
}
.pos_order {
background-color: #f9fafc;
border-right: 1px solid #c0ccda;
}
.pos_btn {
margin-top: 20px;
}
.often_title {
border-bottom: 1px solid #d3dce6;
background-color: #f9fafc;
padding: 10px;
text-align: left;
cursor: pointer;
}
.often_goodsList ul li {
list-style: none;
float: left;
border: 1px solid #d3dce6;
padding: 10px;
margin: 10px;
background-color: #ffffff;
cursor: pointer;
}
.often_price {
color: #63b8ff;
}
.goodsType {
clear: both;
height: auto;
overflow: hidden;
border-top: 1px solid #d3dce6;
}
.cookList li {
list-style: none;
width: 23%;
border: 1px solid #e5e9f2;
height: auot;
overflow: hidden;
background-color: #fff;
padding: 2px;
float: left;
margin: 2px;
cursor: pointer;
}
.cookList_div{
width: 60%;
display: inline-block;
float: left;
}
.cookList li span {
display: block;
float: left;
}
.foodImg {
width: 40%;
height: 120px;
}
.foodImg img{
/* width: 100%; */
width: 100%;
height: auto;
}
.foodName {
font-size: 16px;
padding-left: 10px;
color: brown;
}
.foodPrice {
font-size: 16px;
padding-left: 10px;
padding-top: 10px;
color: #F64F15;
}
.total {
background: #ffffff;
padding: 10px;
border-bottom: 1px solid #d3dce6;
color: red;
font-size: 18px;
}
.total small {
padding: 0 10px;
text-align: center;
}
.sku_card {
.sku_card_title {
font-size: 15px;
line-height: 40px;
color: #222;
font-weight: bold;
}
.sku_card_main {
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
.sku_card_item {
font-size: 12px;
line-height: 24px;
background-color: #f1f2f2;
color: #373737;
margin-right: 10px;
margin-bottom: 10px;
padding: 0 10px;
flex-shrink: 0;
border-radius: 3px;
cursor: pointer;
}
.sku_card_item_active {
background-color: #409eff !important;
color: #fff !important;
}
}
}
.card {
margin: 18px auto 0;
background-color: #fff;
.top {
display: flex;
justify-content: flex-start;
align-items: center;
height: 50px;
font-size: 16px;
line-height: 1;
.shop_name {
margin-left: 5px;
font-size: 15px;
font-weight: normal;
font-stretch: normal;
color: #222222;
}
}
.select_box {
width: 40px;
display: flex;
justify-content: center;
align-items: center;
flex-shrink: 0;
font-size: 16px;
.circle {
color: #666;
}
.checked {
color: #f64f15;
}
}
.main {
padding-bottom: 23px;
.card_wrap {
margin-top: 15px;
&:first-child {
margin-top: 0;
}
}
.card_item {
width: 100%;
box-sizing: border-box;
}
.card_item_wrap {
display: flex;
justify-content: flex-start;
align-items: center;
}
.img_wrap {
width: 70px;
height: 70px;
border-radius: 10px;
overflow: hidden;
flex-shrink: 0;
img {
display: block;
width: 70px;
height:70px;
}
}
.info {
margin-left: 20px;
padding-right: 20px;
width: calc(100% - 40px - 100px - 15px);
// height: 70px;
display: flex;
flex-direction: column;
justify-content: space-between;
.it {
.goods_title {
display: block;
width: 100%;
font-size: 12px;
font-weight: bold;
font-stretch: normal;
color: #222222;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.deleteicon{
margin: 6px 0;
display: flex;
justify-content: flex-end;
}
.delete{
cursor: pointer;
color: red;
}
.sku {
height: 26px;
border-radius: 5px;
margin-top: 11px;
font-size: 12px;
line-height: 26px;
font-stretch: normal;
color: #838383;
display: flex;
justify-content: flex-start;
align-items: center;
.text {
padding: 0 10px;
background-color: #f6f6f6;
}
.sku_arr {
display: block;
padding-left: 10px;
padding-right: 10px;
background-color: #f6f6f6;
}
}
}
.ib {
display: flex;
justify-content: space-between;
.pricebox{
display: flex;
align-items: center;
}
.jfprice{
margin-left: 8px;
.price_icon,.price_main{
font-size: 12px !important;
color: #a5a5a5 !important;
}
}
.price {
display: flex;
justify-content: flex-start;
align-items: baseline;
.price_icon {
font-size: 13px;
font-weight: bold;
font-stretch: normal;
color: #f64f15;
}
.price_main {
font-size: 16px;
font-weight: bold;
font-stretch: normal;
color: #f64f15;
.mini {
font-size: 15px;
}
}
.ori {
font-size: 12px;
font-stretch: normal;
color: #8a8a8a;
}
}
.num {
flex-shrink: 0;
--stepper-input-disabled-text-color: #323233;
}
}
}
}
}
.qrcodepup{
text-align: center;
}
This diff is collapsed.
......@@ -26,11 +26,11 @@
<template #default="scope">
<el-button-group>
<el-button type="primary" @click="table_edit(scope.row, scope.$index)">编辑</el-button>
<el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
<!-- <el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
<template #reference>
<el-button type="danger">删除</el-button>
</template>
</el-popconfirm>
</el-popconfirm> -->
</el-button-group>
</template>
</el-table-column>
......
......@@ -30,11 +30,11 @@
<template #default="scope">
<el-button-group>
<el-button type="primary" @click="table_edit(scope.row, scope.$index)">编辑</el-button>
<el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
<!-- <el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
<template #reference>
<el-button type="danger">删除</el-button>
</template>
</el-popconfirm>
</el-popconfirm> -->
</el-button-group>
</template>
</el-table-column>
......@@ -60,6 +60,7 @@ export default{
apiObj: this.$API.goods.lists.list,
column: [
{prop: 'id', label: 'ID', width: 80},
{prop: 'goods_sn', label: '商品编号'},
{prop: 'title', label: '商品名称'},
{prop: 'cover', label: '封面图', width: 120},
{prop: 'price', label: '售价', width: 120},
......
......@@ -19,6 +19,9 @@
<el-form-item label="标签" prop="tags">
<sc-tag-input v-model="form.tags" placeholder="请输入标签"/>
</el-form-item>
<el-form-item label="产品编码" prop="goods_sn">
<el-input v-model="form.goods_sn" placeholder="请输入产品编码" clearable />
</el-form-item>
<el-form-item label="简述" prop="description">
<el-input type="textarea" v-model="form.description" placeholder="请输入简述" clearable />
</el-form-item>
......
......@@ -25,7 +25,7 @@
<div class="login-form">
<div class="login-header">
<div class="logo">
<img :alt="$CONFIG.APP_NAME" :src="'/static/images/logo.png'">
<img :alt="$CONFIG.APP_NAME" :src="'./static/images/logo.png'">
<label>{{$CONFIG.APP_NAME}}</label>
</div>
</div>
......
<template>
<el-container>
<!-- 大使账单 -->
<el-header>
<div class="left-panel">
<el-select v-model="search.type" placeholder="请选择类型" style="width: 180px; margin-right: 10px;" clearable>
......@@ -8,7 +9,7 @@
<el-input v-model="search.store_title" placeholder="请输入店铺名称" style="width: 180px; margin-right: 10px;" clearable />
<el-input v-model="search.username" placeholder="请输入用户名" style="width: 180px; margin-right: 10px;" clearable />
<el-select v-model="search.status" placeholder="请选择状态" style="width: 180px;" clearable v-if="search.type == 'withdraw'">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in [{label: '已提现', value: 1}, {label: '待提现', value: 0}, {label: '已拒绝', value: 2}]" :key="index"></el-option>
<el-option :label="item.label" :value="item.value" v-for="(item, index) in [{label: '已提现', value: 1}, {label: '待提现', value: 0}, {label: '已拒绝', value: 2},{label: '提现失败', value: -2}]" :key="index"></el-option>
</el-select>
<el-select v-model="search.status" placeholder="请选择状态" style="width: 180px;" clearable v-if="search.type == 'income'">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in [{label: '已到账', value: 1}, {label: '未入账', value: 0}]" :key="index"></el-option>
......@@ -43,7 +44,13 @@
</template>
<template #status="scope">
<el-tag v-if="scope.row.type == 'income'" :type="scope.row.status == 1 ? 'success' : 'danger'">{{ scope.row.status == 1 ? '已到账' : '未入账' }}</el-tag>
<el-tag v-else :type="scope.row.status == 1 ? 'success' : 'danger'">{{ scope.row.status == 1 ? '已提现' : '待确认' }}</el-tag>
<el-tag v-else :type="scope.row.status == 1 ? 'success' : 'danger'">
<span v-show="scope.row.status == 0">待提现</span>
<span v-show="scope.row.status == 1">已提现</span>
<span v-show="scope.row.status == 2">已拒绝</span>
<span v-show="scope.row.status == -2">提现失败</span>
</el-tag>
</template>
<el-table-column label="操作" fixed="right" align="center" width="100">
<template #default="scope">
......@@ -76,10 +83,12 @@ export default{
column: [
{prop: 'member', label: '头像'},
{prop: 'mobile', label: '手机号码', width: 120},
{prop: 'bank_realname', label: '真实姓名', width: 50},
{prop: 'type', label: '类型', width: 120, align: 'center'},
{prop: 'amount', label: '额度', width: 120},
{prop: 'af_amount', label: '余额', width: 120},
{prop: 'remark', label: '备注', width: 120},
{prop: 'reason', label: '失败理由', width: 60},
{prop: 'status', label: '状态', width: 120},
{prop: 'created_at', label: '添加时间', width: 140},
{prop: 'updated_at', label: '更新时间', width: 140},
......
......@@ -24,11 +24,11 @@
<template #default="scope">
<el-button-group>
<el-button type="primary" size="small" @click="table_edit(scope.row, scope.$index)">编辑</el-button>
<el-popconfirm title="您确定删除该数据" @confirm="table_del(scope.row, scope.$index)">
<!-- <el-popconfirm title="您确定删除该数据" @confirm="table_del(scope.row, scope.$index)">
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</el-popconfirm> -->
</el-button-group>
</template>
</el-table-column>
......
<template>
<el-container>
<el-header>
<div class="left-panel">
<!-- <el-select v-model="search.type" placeholder="请选择" style="width: 180px; margin-right: 10px;" clearable>
<el-option :label="item.label" :value="item.value" v-for="(item, index) in typeList"></el-option>
</el-select> -->
<el-input v-model="search.store_title" placeholder="请输入店铺名称" style="width: 180px; margin-right: 10px;" clearable />
<el-input v-model="search.username" placeholder="请输入用户名" style="width: 180px; margin-right: 10px;" clearable />
<el-button-group style="margin-left: 10px;">
<el-button type="primary" icon="el-icon-search" @click="upsearch">搜索</el-button>
</el-button-group>
</div>
<div class="right-panel">
<el-button-group>
<el-button type="danger" icon="el-icon-plus" @click="add">添加</el-button>
</el-button-group>
</div>
</el-header>
<el-main class="nopadding">
<scTable tableName="member" ref="table" :apiObj="list.apiObj" :column="list.column" row-key="id" @selection-change="selectionChange" border stripe size="small">
<el-table-column type="selection" width="50"></el-table-column>
<template #member="scope">
<div style="display: flex; gap: 8px; align-items: center;">
<el-image :src="scope.row.member?.avatar" style="width: 40px; height: 40px;" />
<div style="display: flex; flex-direction: column;">
<span>{{ scope.row.member?.nickname }}</span>
<span>{{ scope.row.member?.username }}</span>
</div>
</div>
</template>
<template #mobile="scope">
{{ scope.row.member?.mobile }}
</template>
</scTable>
</el-main>
</el-container>
<save v-if="dialog.save" ref="saveBox" @success="upsearch" @closed="dialog.save=false" />
</template>
<script>
import save from './save.vue'
export default{
name: 'memberpolymer',
components:{
save
},
data(){
return {
dialog: {search: false, import: false, save: false},
list: {
apiObj: this.$API.member.polymer.list,
column: [
{prop: 'id', label: 'ID', width: 80},
{prop: 'member', label: '用户'},
{prop: 'member_id', label: '用户id'},
{prop: 'mobile', label: '手机号码', width: 120},
{prop: 'amount', label: '额度', width: 120},
{prop: 'af_amount', label: '余额', width: 120},
{prop: 'remark', label: '备注', width: 120},
{prop: 'created_at', label: '添加时间', width: 140},
{prop: 'updated_at', label: '更新时间', width: 140},
],
},
selection: [],
typeList: [{label: '分享', value: 'share'}, {label: '排队', value: 'queue'},{label: '合伙人', value: 'partner'},{label: '货款', value: 'sale'}],
search: {},
}
},
methods: {
upsearch(){
this.$refs.table.reload(this.search);
},
moreUpsearch(search){
this.search = search;
this.upsearch();
},
moreSearch(){
this.dialog.search = true
this.$nextTick(() => {
this.$refs.searchBox.open().setData(this.search)
})
},
//表格选择后回调事件
selectionChange(selection){
this.selection = selection;
},
add(){
this.dialog.save = true
this.$nextTick(() => {
this.$refs.saveBox.open().setData({})
})
}
}
}
</script>
\ No newline at end of file
<template>
<el-dialog :title="titleMap[mode]" v-model="visible" :width="500" destroy-on-close :close-on-click-modal="false" @closed="$emit('closed')">
<el-form :model="form" :rules="rules" :disabled="mode=='show'" ref="dialogForm" label-width="100px" label-position="left">
<el-form-item label="聚物通额度" prop="amount">
<el-input v-model="form.amount" placeholder="聚物通额度" clearable />
</el-form-item>
<el-form-item label="用户" prop="member_id">
<el-input v-model="form.member_id" placeholder="用户" clearable />
</el-form-item>
<el-form-item label="聚物通类型" prop="type">
<el-select v-model="form.type" placeholder="聚物通类型" clearable>
<el-option label="增加" value="income" />
<el-option label="减少" value="pay" />
</el-select>
</el-form-item>
<el-form-item label="聚物通描述" prop="remark">
<el-input type="textarea" v-model="form.remark" placeholder="聚物通描述" clearable />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="visible=false" >取 消</el-button>
<el-button v-if="mode!='show'" type="primary" :loading="isSaveing" @click="submit()">提 交</el-button>
</template>
</el-dialog>
</template>
<script>
export default {
emits: ['success', 'closed'],
data() {
return {
mode: "add",
titleMap: {
add: '聚物通',
edit: '编辑等级',
show: '查看'
},
visible: false,
isSaveing: false,
//表单数据
form: { title: '', name: ''},
//验证规则
rules: {
amount: [{required: true, message: '请输入聚物通额度'}],
member_id: [{required: true, message: '请输入用户UID'}],
type: [{required: true, message: '请选择聚物通类型'}],
remark: [{required: true, message: '请输入聚物通描述'}]
}
}
},
mounted() {
},
methods: {
//显示
open(mode='add'){
this.mode = mode;
this.visible = true;
return this
},
//表单提交方法
submit(){
this.$refs.dialogForm.validate(async (valid) => {
if (valid) {
this.isSaveing = true;
var res = {};
if(this.mode == 'add'){
res = await this.$API.member.polymer.add.post(this.form);
}else{
res = await this.$API.member.polymer.edit.post(this.form);
}
this.isSaveing = false;
if(res.code == 1){
this.$emit('success', this.form, this.mode)
this.visible = false;
this.$message.success("操作成功")
}else{
this.$alert(res.message, "提示", {type: 'error'})
}
}else{
return false;
}
})
},
//表单注入数据
setData(data){
this.form = data
}
}
}
</script>
......@@ -19,7 +19,7 @@
</el-form>
<template #footer>
<el-button @click="visible=false" >取 消</el-button>
<el-button v-if="mode!='show'" type="primary" :loading="isSaveing" @click="submit()">保 存</el-button>
<el-button v-if="mode!='show'" type="primary" :loading="isSaveing" @click="submit()">提 交</el-button>
</template>
</el-dialog>
</template>
......@@ -31,7 +31,7 @@ export default {
return {
mode: "add",
titleMap: {
add: '新增等级',
add: '积分',
edit: '编辑等级',
show: '查看'
},
......
<template>
<el-container>
<el-header>
<div class="left-panel">
<el-input v-model="search.keyword" placeholder="关键词" style="width:150px; margin-right: 10px;" clearable></el-input>
<el-button-group style="margin-left: 10px;">
<el-button type="primary" icon="el-icon-search" @click="upsearch">搜索</el-button>
</el-button-group>
</div>
<div class="right-panel">
<el-button-group>
<el-button type="danger" icon="el-icon-plus" @click="add">添加</el-button>
</el-button-group>
</div>
</el-header>
<el-main class="nopadding">
<scTable tableName="member" ref="table" :apiObj="list.apiObj" :column="list.column" row-key="id" @selection-change="selectionChange" border stripe>
<el-table-column type="selection" width="50"></el-table-column>
<template #order_no="scope">
{{ scope.row.order?.order_no }}
</template>
<template #member="scope">
{{ scope.row.member?.nickname }}{{ scope.row.member?.username }}
</template>
<template #status="scope">
<el-tag :type="status[scope.row.status]?.type">{{ status[scope.row.status]?.label ?? '未知'}}</el-tag>
</template>
<el-table-column label="操作" fixed="right" align="center" width="140">
<template #default="scope">
<el-button-group>
<el-button type="primary" @click="table_audit(scope.row, scope.$index)" v-if="scope.row.status == 0">审核</el-button>
</el-button-group>
</template>
</el-table-column>
</scTable>
</el-main>
<save v-if="dialog.save" ref="saveBox" @success="upsearch" @closed="dialog.save=false" />
</el-container>
<el-container>
<el-header>
<div class="left-panel">
<el-input v-model="search.keyword" placeholder="关键词" style="width:150px; margin-right: 10px;" clearable></el-input>
<el-input v-model="search.name" placeholder="申请人" style="width:150px; margin-right: 10px;" clearable />
<el-input v-model="search.mobile" placeholder="手机号码" style="width:150px; margin-right: 10px;" clearable />
<el-button-group style="margin-left: 10px;">
<el-button type="primary" icon="el-icon-search" @click="upsearch">搜索</el-button>
</el-button-group>
</div>
</el-header>
<el-main class="nopadding">
<scTable tableName="member" ref="table" :apiObj="list.apiObj" :column="list.column" row-key="id" @selection-change="selectionChange" border stripe>
<el-table-column type="selection" width="50"></el-table-column>
<el-table-column label="操作" fixed="right" align="center" width="140">
</el-table-column>
</scTable>
</el-main>
</el-container>
</template>
<script>
import save from './save.vue'
export default{
name: 'order.exchange',
components:{
save,
},
data(){
return {
dialog: {search: false, import: false, print: false},
status: {0: {label: '待审核', type: 'primary'}, 1: {label: '已通过', type: 'success'}, 2: {label: '已拒绝', type: 'danger'}, 3: {label: '已完成', type: 'warning'}},
list: {
apiObj: this.$API.order.refund.list,
column: [
{prop: 'id', label: 'ID', width: 80},
{prop: 'order_id', label: '订单ID', width: 120},
{prop: 'order_no', label: '订单号', width: 240},
{prop: 'member', label: '申请人'},
{prop: 'amount', label: '退款金额', width: 120},
{prop: 'reason', label: '退款原因', width: 120},
{prop: 'status', label: '退款状态', width: 120},
{prop: 'created_at', label: '添加时间', width: 140},
{prop: 'updated_at', label: '更新时间', width: 140},
],
},
selection: [],
search: {},
}
},
methods:{
upsearch(){
this.$refs.table.reload(this.search);
},
moreUpsearch(search){
this.search = search;
this.upsearch();
},
moreSearch(){
this.dialog.search = true
this.$nextTick(() => {
this.$refs.searchBox.open().setData(this.search)
})
},
//表格选择后回调事件
selectionChange(selection){
this.selection = selection;
},
batch_del(){
name: 'order.exchange',
components:{
},
table_show(row){
this.dialog.detail = true
this.$nextTick(() => {
this.$refs.detailBox.open().setData(row)
})
},
add(){
this.dialog.save = true
this.$nextTick(() => {
this.$refs.saveBox.open()
})
},
table_edit(row){
this.dialog.save = true
this.$nextTick(() => {
this.$refs.saveBox.open('edit').setData(row)
})
},
table_audit(row){
this.dialog.save = true
this.$nextTick(() => {
this.$refs.saveBox.open('audit').setData(row)
})
},
async table_del(row){
var reqData = {id: row.id}
var res = await this.$API.order.refund.delete.post(reqData);
if(res.code == 1){
//这里选择刷新整个表格 OR 插入/编辑现有表格数据
this.upsearch()
this.$message.success("删除成功")
}else{
this.$alert(res.message, "提示", {type: 'error'})
}
}
}
},
data(){
return {
dialog: {search: false, import: false, print: false},
list: {
apiObj: this.$API.order.exchange.list,
column: [
{prop: 'id', label: 'ID', width: 80},
{prop: 'name', label: '置换申请人', width: 120},
{prop: 'mobile', label: '手机号', width: 120},
{prop: 'address', label: '地址'},
{prop: 'remark', label: '行业备注'},
{prop: 'status', label: '状态', width: 120},
{prop: 'created_at', label: '添加时间', width: 140},
],
},
selection: [],
search: {},
}
},
methods:{
upsearch(){
this.$refs.table.reload(this.search);
},
moreUpsearch(search){
this.search = search;
this.upsearch();
},
moreSearch(){
this.dialog.search = true
this.$nextTick(() => {
this.$refs.searchBox.open().setData(this.search)
})
},
//表格选择后回调事件
selectionChange(selection){
this.selection = selection;
}
}
}
</script>
\ No newline at end of file
......@@ -38,11 +38,11 @@
<template #default="scope">
<el-button-group>
<el-button type="primary" @click="table_show(scope.row, scope.$index)">详情</el-button>
<el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
<!-- <el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
<template #reference>
<el-button type="danger">删除</el-button>
</template>
</el-popconfirm>
</el-popconfirm> -->
</el-button-group>
</template>
</el-table-column>
......
<template>
<el-container>
<!-- 我的收益 -->
<el-header>
<div class="left-panel">
<el-select v-model="search.type" placeholder="请选择类型" style="width: 180px; margin-right: 10px;" clearable>
......@@ -8,7 +9,7 @@
<el-input v-model="search.store_title" placeholder="请输入店铺名称" style="width: 180px; margin-right: 10px;" clearable />
<el-input v-model="search.username" placeholder="请输入用户名" style="width: 180px; margin-right: 10px;" clearable />
<el-select v-model="search.status" placeholder="请选择状态" style="width: 180px;" clearable v-if="search.type == 'withdraw'">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in [{label: '已提现', value: 1}, {label: '待提现', value: 0}, {label: '已拒绝', value: 2}]" :key="index"></el-option>
<el-option :label="item.label" :value="item.value" v-for="(item, index) in [{label: '已提现', value: 1}, {label: '待提现', value: 0}, {label: '已拒绝', value: 2},{label: '提现失败', value: -2}]" :key="index"></el-option>
</el-select>
<el-select v-model="search.status" placeholder="请选择状态" style="width: 180px;" clearable v-if="search.type == 'income'">
<el-option :label="item.label" :value="item.value" v-for="(item, index) in [{label: '已到账', value: 1}, {label: '未入账', value: 0}]" :key="index"></el-option>
......@@ -37,7 +38,14 @@
</template>
<template #status="scope">
<el-tag v-if="scope.row.type == 'service_income'" :type="scope.row.status == 1 ? 'success' : 'danger'">{{ scope.row.status == 1 ? '已到账' : '未入账' }}</el-tag>
<el-tag v-else :type="scope.row.status == 1 ? 'success' : 'danger'">{{ scope.row.status == 1 ? '已提现' : '待确认' }}</el-tag>
<!-- <el-tag v-else :type="scope.row.status == 1 ? 'success' : 'danger'">{{ scope.row.status == 1 ? '已提现' : '待确认' }}</el-tag> -->
<el-tag v-else :type="scope.row.status == 1 ? 'success' : 'danger'">
<span v-show="scope.row.status == 0">待提现</span>
<span v-show="scope.row.status == 1">已提现</span>
<span v-show="scope.row.status == 2">已拒绝</span>
<span v-show="scope.row.status == -2">提现失败</span>
</el-tag>
</template>
<el-table-column label="操作" fixed="right" align="center" width="100">
<template #default="scope">
......@@ -71,6 +79,7 @@ export default{
{prop: 'af_amount', label: '余额', width: 120},
{prop: 'remark', label: '备注', width: 120},
{prop: 'status', label: '状态', width: 120},
{prop: 'reason', label: '提败理由', width: 120},
{prop: 'created_at', label: '添加时间', width: 140},
{prop: 'updated_at', label: '更新时间', width: 140},
],
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment