初始版本

This commit is contained in:
贾祥聪
2025-08-19 14:16:51 +08:00
commit f937a1f9b9
4373 changed files with 359728 additions and 0 deletions

View File

@@ -0,0 +1,285 @@
<?php
namespace app\coachapi\logic;
use app\common\model\city\City;
use app\common\model\Region;
use app\common\service\ConfigService;
use app\common\service\TencentMapKeyService;
use Exception;
class CityLogic
{
/**
* @notes 获取城市列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author cjhao
* @date 2024/10/6 17:49
*/
public function getCityLists()
{
$lists = City::where(['level'=>2])->select()->toArray();
$cityLists = [];
foreach ($lists as $city){
$parent = $cityLists[$city['parent_id']] ?? [];
if($parent){
$parent['sons'][] =[
'id' => $city['city_id'],
'name' => $city['name'],
];
}else{
$parent = [
'id' => $city['parent_id'],
'name' => $city['parent_name'],
'sons' => [
[
'id' => $city['city_id'],
'name' => $city['name'],
],
],
];
}
$cityLists[$city['parent_id']] = $parent;
}
return array_values($cityLists);
}
/**
* @notes 搜索附近地址
* @param $params
* @return array|mixed
* @author ljj
* @date 2024/7/23 上午11:20
*/
public function getNearbyLocation($params)
{
$longitude = $params['longitude'] ?? '';
$latitude = $params['latitude'] ?? '';
if(empty($longitude) || empty($latitude)){
throw new Exception('请授权获取位置');
}
//开发秘钥
$data['key'] = (new TencentMapKeyService())->getTencentMapKey();
if (empty($data['key'])) {
return ['status'=>1,'message'=>'腾讯地图开发密钥不能为空'];
}
//排序,按距离由近到远排序
$data['orderby'] = '_distance';
//排序,按距离由近到远排序
$data['boundary'] = "nearby(" . $params['latitude'] . "," . $params['longitude'] . ",1000,1)";
//搜索关键字
$keyword = $params['keyword'] ?? '';
//api地址
//未输入搜索关键词时默认使用周边推荐api
$url = 'https://apis.map.qq.com/ws/place/v1/explore';
if (!empty($keyword)) {
$data['keyword'] = $keyword;
//输入搜索关键词时使用周边搜索api
$url = 'https://apis.map.qq.com/ws/place/v1/search';
}
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
if ($result['status'] !== 0) {
$check = (new TencentMapKeyService())->checkResult($result);
while (!$check) {
$data['key'] = (new TencentMapKeyService())->getTencentMapKey(true);
if (empty($data['key'])) {
break;
}
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
$check = (new TencentMapKeyService())->checkResult($result);
}
}
return $result;
}
/**
* @notes 地级市列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author ljj
* @date 2022/4/6 2:41 下午
*/
public function city($params)
{
$where = [];
$where[] = ['level','=',2];
if(isset($params['keyword']) && $params['keyword']){
$where[] = ['name','like','%'.$params['keyword'].'%'];
}
$lists = City::where($where)
->field('id,parent_id,level,name,gcj02_lng,gcj02_lat,db09_lng,db09_lat')
->select()
->toArray();
$lists = self::groupByInitials($lists);
unset($lists[null]);
return $lists;
}
/**
* 二维数组根据首字母分组排序
* @param array $data 二维数组
* @param string $targetKey 首字母的键名
* @return array 根据首字母关联的二维数组
*/
public function groupByInitials(array $data, $targetKey = 'name')
{
$data = array_map(function ($item) use ($targetKey) {
return array_merge($item, [
'initials' => $this->getInitials($item[$targetKey]),
]);
}, $data);
$data = $this->sortInitials($data);
return $data;
}
/**
* 按字母排序
* @param array $data
* @return array
*/
public function sortInitials(array $data)
{
$sortData = [];
foreach ($data as $key => $value) {
$sortData[$value['initials']][] = $value;
}
ksort($sortData);
return $sortData;
}
/**
* 获取首字母
* @param string $str 汉字字符串
* @return string 首字母
*/
public function getInitials($str)
{
if (empty($str)) {return '';}
$fchar = ord($str[0]);
if ($fchar >= ord('A') && $fchar <= ord('z')) {
return strtoupper($str[0]);
}
$s1 = iconv('UTF-8', 'GBK', $str);
$s2 = iconv('GBK', 'UTF-8', $s1);
$s = $s2 == $str ? $s1 : $str;
$asc = ord($s[0]) * 256 + ord($s[1]) - 65536;
if ($asc >= -20319 && $asc <= -20284) {
return 'A';
}
if ($asc >= -20283 && $asc <= -19776) {
return 'B';
}
if ($asc >= -19775 && $asc <= -19219) {
return 'C';
}
if ($asc >= -19218 && $asc <= -18711) {
return 'D';
}
if ($asc >= -18710 && $asc <= -18527) {
return 'E';
}
if ($asc >= -18526 && $asc <= -18240) {
return 'F';
}
if ($asc >= -18239 && $asc <= -17923) {
return 'G';
}
if ($asc >= -17922 && $asc <= -17418) {
return 'H';
}
if ($asc >= -17417 && $asc <= -16475) {
return 'J';
}
if ($asc >= -16474 && $asc <= -16213) {
return 'K';
}
if ($asc >= -16212 && $asc <= -15641) {
return 'L';
}
if ($asc >= -15640 && $asc <= -15166) {
return 'M';
}
if ($asc >= -15165 && $asc <= -14923) {
return 'N';
}
if ($asc >= -14922 && $asc <= -14915) {
return 'O';
}
if ($asc >= -14914 && $asc <= -14631) {
return 'P';
}
if ($asc >= -14630 && $asc <= -14150) {
return 'Q';
}
if ($asc >= -14149 && $asc <= -14091) {
return 'R';
}
if ($asc >= -14090 && $asc <= -13319) {
return 'S';
}
if ($asc >= -13318 && $asc <= -12839) {
return 'T';
}
if ($asc >= -12838 && $asc <= -12557) {
return 'W';
}
if ($asc >= -12556 && $asc <= -11848) {
return 'X';
}
if ($asc >= -11847 && $asc <= -11056) {
return 'Y';
}
if ($asc >= -11055 && $asc <= -10247) {
return 'Z';
}
return null;
}
/**
* @notes 逆地址解析(坐标位置描述)
* @param $get
* @return array|mixed
* @author ljj
* @date 2022/10/13 2:44 下午
* 本接口提供由经纬度到文字地址及相关位置信息的转换能力
*/
public static function geocoderCoordinate($get)
{
$get['key'] = (new TencentMapKeyService())->getTencentMapKey();
if (empty($get['key'])) {
return ['status'=>1,'message'=>'腾讯地图开发密钥不能为空'];
}
$query = http_build_query($get);
$url = 'https://apis.map.qq.com/ws/geocoder/v1/';
$result = json_decode(file_get_contents($url.'?'.$query),true);
if ($result['status'] !== 0) {
$check = (new TencentMapKeyService())->checkResult($result);
while (!$check) {
$data['key'] = (new TencentMapKeyService())->getTencentMapKey(true);
if (empty($data['key'])) {
break;
}
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
$check = (new TencentMapKeyService())->checkResult($result);
}
}
return $result;
}
}

View File

@@ -0,0 +1,710 @@
<?php
namespace app\coachapi\logic;
use app\common\enum\coach\CoachEnum;
use app\common\enum\coach\CoachUserEnum;
use app\common\enum\DefaultEnum;
use app\common\enum\notice\NoticeEnum;
use app\common\enum\OrderEnum;
use app\common\enum\PayEnum;
use app\common\enum\shop\ShopEnum;
use app\common\model\coach\Coach;
use app\common\model\coach\CoachGoodsIndex;
use app\common\model\coach\CoachLifePhoto;
use app\common\model\coach\CoachServerTime;
use app\common\model\coach\CoachUpdate;
use app\common\model\coach\CoachUser;
use app\common\model\goods\Goods;
use app\common\model\order\Order;
use app\common\model\shop\ShopCoachApply;
use app\common\model\skill\Skill;
use app\common\service\ConfigService;
use app\common\service\FileService;
use app\common\service\sms\SmsDriver;
use app\common\service\TencentMapKeyService;
use Exception;
use think\facade\Db;
/**
* 技师逻辑类
* Class CoachLogic
* @package app\coachapi\logic
*/
class CoachLogic
{
/**
* @notes 个人中心
* @return array
* @author cjhao
* @date 2024/8/23 16:09
*/
public function center($coachInfo)
{
$coachUser = CoachUser::where(['id'=>$coachInfo['coach_user_id']])->field('sn,avatar')->findOrEmpty();
$coachUser->location = '';
$coachUser->work_status = '';
$coach = Coach::where(['coach_user_id'=>$coachInfo['coach_user_id']])
->order('id desc')
->append(['province_name','city_name','region_name','region_desc'])
->field('id,shop_id,province_id,city_id,region_id,longitude,latitude,longitude_location,latitude_location,name,sn,work_photo,money,deposit,work_status,location,work_photo,audit_status,audit_remark')
->findOrEmpty();
$coachUser->audit_status = $coach->audit_status;
$coachUser->audit_remark = $coach->audit_remark;
$coachUser->avatar = $coach->work_photo ? : $coachUser->avatar;
$todayDate = date('Y-m-d',time());
//今天的时间戳
$todayStart = strtotime($todayDate);
$todayEnd = strtotime($todayDate . ' 23:59:59');
//明天的时间戳
$tomorrowStart = strtotime('+1 day',$todayStart);
$tomorrowEnd = strtotime('+1 day',$todayEnd);
//后天的时间戳
$dayAfterTomorrowStart = strtotime('+2 day',$todayStart);
$dayAfterTomorrowEnd = strtotime('+2 day',$todayEnd);
$todayOrderCount = Order::where(['coach_id'=>$coachInfo['coach_id'],'pay_status'=>PayEnum::ISPAID])
->whereNotIn('order_status',[OrderEnum::ORDER_STATUS_WAIT_PAY,OrderEnum::ORDER_STATUS_WAIT_RECEIVING,OrderEnum::ORDER_STATUS_CLOSE,OrderEnum::ORDER_STATUS_SERVER_FINISH])
->whereBetweenTime('appoint_time',$todayStart,$todayEnd)
->count();
$tomorrowOrderCount = Order::where(['coach_id'=>$coachInfo['coach_id'],'pay_status'=>PayEnum::ISPAID])
->whereNotIn('order_status',[OrderEnum::ORDER_STATUS_WAIT_PAY,OrderEnum::ORDER_STATUS_WAIT_RECEIVING,OrderEnum::ORDER_STATUS_CLOSE,OrderEnum::ORDER_STATUS_SERVER_FINISH])
->whereBetweenTime('appoint_time',$tomorrowStart,$tomorrowEnd)
->count();
$afterTomorrowOrderCount = Order::where(['coach_id'=>$coachInfo['coach_id'],'pay_status'=>PayEnum::ISPAID])
->whereNotIn('order_status',[OrderEnum::ORDER_STATUS_WAIT_PAY,OrderEnum::ORDER_STATUS_WAIT_RECEIVING,OrderEnum::ORDER_STATUS_CLOSE,OrderEnum::ORDER_STATUS_SERVER_FINISH])
->whereBetweenTime('appoint_time',$dayAfterTomorrowStart,$dayAfterTomorrowEnd)
->count();
$location = $coach->location;
$location['longitude'] = $coach->longitude_location;
$location['latitude'] = $coach->latitude_location;
if(CoachEnum::AUDIT_STATUS_PASS == $coach->audit_status){
$coachUser->work_status = $coach->work_status;
$coachUser->work_photo = $coach->work_photo;
$coachUser->location = $location;
}
$coachUser->today_order_count = $todayOrderCount;
$coachUser->tomoroow_order_count = $tomorrowOrderCount;
$coachUser->after_tomoroow_order_count = $afterTomorrowOrderCount;
if(!$coach->isEmpty()){
$coachUser->name = $coach->name;
$coachUser->sn = $coach->sn;
}
$coachUser->money = $coach->money;
$coachUser->deposit = $coach->deposit;
$coachUser->province_id = $coach->province_id;
$coachUser->city_id = $coach->city_id;
$coachUser->region_id = $coach->region_id;
$coachUser->province_name = $coach->province_name;
$coachUser->city_name = $coach->city_name;
$coachUser->region_name = $coach->region_name;
$coachUser->region_desc = $coach->region_desc;
$coachUser->longitude = $coach->longitude;
$coachUser->latitude = $coach->latitude;
$coachUser->id = $coach->id;
$coachUser->shop_id = $coach->shop_id;
if(!$coach->shop_id){
$apply = ShopCoachApply::where(['coach_id'=>$coach['id']])
->order('id desc')
->field('shop_id,id,type,audit_status')
->findOrEmpty();
if(!$apply->isEmpty()){
$shopId = $apply['shop_id'];
//申请商家取消;退出商家同意;退出商家取消
if((1 == $apply['type'] && 3 == $apply['audit_status']) || (2 == $apply['type'] && 1 == $apply['audit_status']) || (2 == $apply['type'] && 1 == $apply['audit_status'])){
$shopId = 0;
}
$coachUser->shop_id = $shopId;
}
}
//服务项目
$coachUser->server_count = CoachGoodsIndex::where(['coach_id'=>$coachInfo['coach_id']])->count();
return $coachUser->toArray();
}
/**
* @notes 获取详情接口
* @param $coachId
* @return Coach|array|\think\Model
* @author cjhao
* @date 2024/11/23 18:15
*/
public function info($coachId)
{
$detail = Coach::where(['id'=>$coachId,'audit_status'=>CoachEnum::AUDIT_STATUS_PASS])
->field('id,name,id_card,id_card_front,portrait_shooting,id_card_back,work_photo')
->findOrEmpty()->toArray();
if(empty($detail)){
$detail = [
'id' => $coachId,
'name' => '',
'id_card' => '',
'id_card_back' => '',
'id_card_front' => '',
'work_photo' => ''
];
}
return $detail;
}
/**
* @notes 技能列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author cjhao
* @date 2024/8/20 18:02
*/
public function skillLists()
{
$skillLists = Skill::field('name,id')->select()->toArray();
// $goodsLists = Goods::alias('G')
// ->where(['G.status'=>1])
// ->append(['category_desc','skill_desc'])
// ->join('goods_skill_index GSI','G.id = GSI.goods_id')
// ->field('G.id,G.price,G.name,G.category_id,G.image,GSI.skill_id')
// ->select()->toArray();
// foreach ($skillLists as $key => $skill){
// $skillGoodsLists = [];
// foreach ($goodsLists as $goods){
// if($skill['id'] == $goods['skill_id']){
// $skillGoodsLists[] = $goods;
// }
// }
// $skillLists[$key]['goods_list'] = $skillGoodsLists;
// }
return $skillLists;
}
public function goodsLists(int $id)
{
$where[] = ['status','=',1];
if($id){
$goodsIds = CoachGoodsIndex::where(['skill_id'=>$id])->column('goods_id');
empty($goodsIds) && $goodsIds = [];
$where[] = ['id','in',implode(',',$goodsIds)];
}
$lists = Goods::where($where)
->field('id,name,price,image')
->select()
->toArray();
return $lists;
}
/**
* @notes 其他数据
* @return array
* @author cjhao
* @date 2024/8/21 18:16
*/
public function otherLists()
{
$educationLists = DefaultEnum::getEducationLists();
$nationLists = DefaultEnum::getNationLists();
return [
'education_lists' => $educationLists,
'nation_lists' => $nationLists,
];
}
/**
* @notes 申请技师
* @param array $params
* @return string|true
* @author cjhao
* @date 2024/8/23 17:24
*/
public function apply(array $params)
{
try {
Db::startTrans();
$coach = Coach::where(['coach_user_id'=>$params['coach_user_id']])
->order('id desc')
->findOrEmpty();
if( !$coach->isEmpty() && CoachEnum::AUDIT_STATUS_PASS == $coach->audit_status ){
return '当前账号已经入驻成功,请勿重复申请';
}
if( !$coach->isEmpty() && CoachEnum::AUDIT_STATUS_WAIT == $coach->audit_status ){
return '当前账号申请正在审核中,请耐心等待';
}
$coachUser = CoachUser::where(['id'=>$params['coach_user_id']])->findOrEmpty();
$coach = (new Coach());
$coach->name = $params['name'];
$coach->sn = $coachUser->sn;
$coach->gender = $params['gender'];
$coach->age = $params['age'];
$coach->id_card = $params['id_card'];
$coach->mobile = $coachUser['account'];
$coach->education = $params['education'];
$coach->nation = $params['nation'];
$coach->province_id = $params['province_id'];
$coach->city_id = $params['city_id'];
$coach->region_id = $params['region_id'];
$coach->address_detail = $params['address_detail'];
$coach->coach_user_id = $params['coach_user_id'];
$coach->skill_id = $params['skill_id'];
$coach->id_card_front = $params['id_card_front'];
$coach->id_card_back = $params['id_card_back'];
$coach->portrait_shooting = $params['portrait_shooting'];
$coach->work_photo = $params['work_photo'];
$coach->certification = $params['certification'] ?? '';
$coach->health_certificate = $params['health_certificate'] ?? '';
$coach->work_status = $params['work_status'];
$coach->server_status = $params['server_status'];
$coach->longitude = $params['longitude'] ?? '';
$coach->latitude = $params['latitude'] ?? '';
$coach->save();
//生活照
$lifePhoto = $params['life_photo'] ?? [];
$lifePhotoLists = [];
foreach ($lifePhoto as $photo){
$lifePhotoLists[] = [
'uri' => $photo,
'coach_id' => $coach->id
];
}
(new CoachLifePhoto())->saveAll($lifePhotoLists);
//关联服务
$goodsIds = $params['goods_ids'] ?? [];
$goodsLists = [];
foreach ($goodsIds as $goodsId)
{
$goodsLists[] = [
'goods_id' => $goodsId,
'coach_id' => $coach->id,
];
}
(new CoachGoodsIndex())->saveAll($goodsLists);
$mobile = ConfigService::get('platform', 'mobile','');
if($mobile){
//入驻申请通知-平台
event('Notice', [
'scene_id' => NoticeEnum::STAFF_APPLY_NOTICE_PLATFORM,
'params' => [
'coach_id' => $coach['id'],
'mobile' => $mobile
]
]);
}
Db::commit();
return true;
}catch (Exception $e){
Db::rollback();
return $e->getMessage();
}
}
/**
* @notes 详情
* @param int $id
* @return array
* @author cjhao
* @date 2024/8/21 15:30
*/
public function detail(int $id)
{
$coach = (new Coach())
->where(['coach_user_id'=>$id])
->append(['life_photo','region_desc','province_name','city_name','region_name'])
->withoutField('create_time,update_time,delete_time')
->order('id desc')
->findOrEmpty()
->toArray();
if($coach){
$coach['skill_name'] = Skill::where(['id'=>$coach['skill_id']])->value('name');
$goodsLists = Goods::alias('G')
->where(['CGI.coach_id'=>$coach['id']])
->join('coach_goods_index CGI','G.id=CGI.goods_id')
->field('G.id,G.name,G.image')
->select()->toArray();
$coach['goods_lists'] = $goodsLists;
}else{
$coach['audit_status'] = '';
}
return $coach;
}
/**
* @notes 获取更新资料接口
* @param $id
* @return array
* @author cjhao
* @date 2024/11/26 17:36
*/
public function updateInfoDetail($coachUserId)
{
$detail = CoachUpdate::where(['coach_user_id'=>$coachUserId])
->append(['province_name','city_name','region_name','region_desc','goods_lists'])
->order('id desc')->findOrEmpty()->toArray();
if(empty($detail)){
$detail = $this->detail($coachUserId);
$detail['audit_status'] = '';
$detail['audit_remark'] = '';
$goodsLists = $detail['goods_lists'] ?? [];
$lifePhoto = $detail['life_photo']->toArray() ?? [];
if($goodsLists) {
$detail['goods_ids'] = array_column($goodsLists,'id');
}
if($lifePhoto) {
$detail['life_photo'] = array_column($lifePhoto,'uri');
}
}
if($detail['goods_ids']){
foreach ($detail['goods_ids'] as $key => $val){
$detail['goods_ids'][$key] = intval($val);
}
}
return $detail;
}
/**
* @notes 技师资料更新
* @param array $params
* @return string|true
* @author cjhao
* @date 2024/8/28 10:16
*/
public function updateInfo(array $params)
{
try {
if(empty($params['coach_user_id'])){
throw new Exception('您技师申请在审核中,暂时不允许修改资料');
}
// Db::startTrans();
$coachUpdate = CoachUpdate::where(['coach_id'=>$params['coach_id'],'audit_status'=>CoachEnum::AUDIT_STATUS_WAIT])
->findOrEmpty();
if(!$coachUpdate->isEmpty()){
throw new Exception( '您提交资料正在审核中,请勿重复提交');
}
$coachUpdate = (new CoachUpdate());
$coachUpdate->coach_id = $params['coach_id'];
$coachUpdate->coach_user_id = $params['coach_user_id'];
$coachUpdate->name = $params['name'];
$coachUpdate->gender = $params['gender'];
$coachUpdate->age = $params['age'];
$coachUpdate->id_card = $params['id_card'];
$coachUpdate->mobile = $params['mobile'];
$coachUpdate->education = $params['education'];
$coachUpdate->nation = $params['nation'];
$coachUpdate->province_id = $params['province_id'];
$coachUpdate->city_id = $params['city_id'];
$coachUpdate->region_id = $params['region_id'];
$coachUpdate->longitude = $params['longitude'];
$coachUpdate->latitude = $params['latitude'];
$coachUpdate->address_detail = $params['address_detail'];
$coachUpdate->skill_id = $params['skill_id'];
$coachUpdate->id_card_front = $params['id_card_front'];
$coachUpdate->id_card_back = $params['id_card_back'];
$coachUpdate->portrait_shooting = $params['portrait_shooting'];
$coachUpdate->work_photo = $params['work_photo'];
$coachUpdate->certification = $params['certification'] ?? '';
$coachUpdate->health_certificate = $params['health_certificate'] ?? '';
// $coachUpdate->work_status = $params['work_status'];
// $coachUpdate->server_status = $params['server_status'];
$lifePhoto = $params['life_photo'] ?? [];
foreach ($lifePhoto as $key => $photo){
$lifePhoto[$key] = FileService::setFileUrl($photo);
}
$lifePhoto = implode(',',$lifePhoto);
$goodsIds = $params['goods_ids'] ?? [];
$goodsIds = implode(',',$goodsIds);
$coachUpdate->life_photo = $lifePhoto;
$coachUpdate->goods_ids = $goodsIds;
$coachUpdate->save();
// Db::commit();
return true;
} catch (Exception $e) {
// Db::rollback();
return $e->getMessage();
}
}
/**
* @notes 地址解析(地址转坐标)
* @param $get
* @return array|mixed
* @author ljj
* @date 2022/10/13 12:06 下午
* 本接口提供由文字地址到经纬度的转换能力,并同时提供结构化的省市区地址信息。
*/
public static function updateLocation($get,$coachId)
{
try {
$coach = Coach::where(['id'=>$coachId])->findOrEmpty();
if($coach->isEmpty()){
return true;
// throw new Exception('请先申请成为技师');
}
$key = (new TencentMapKeyService())->getTencentMapKey();
if ($key == '') {
throw new Exception('请联系管理员检查腾讯地图配置');
}
$data = [
'key' => $key,
'location' => $get['latitude'].','.$get['longitude']
];
$query = http_build_query($data);
$url = 'https://apis.map.qq.com/ws/geocoder/v1/';
$result = json_decode(file_get_contents($url.'?'.$query),true);
if ($result['status'] !== 0) {
$check = (new TencentMapKeyService())->checkResult($result);
while (!$check) {
$data['key'] = (new TencentMapKeyService())->getTencentMapKey(true);
if (empty($data['key'])) {
break;
}
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
$check = (new TencentMapKeyService())->checkResult($result);
}
}
$data = $result['result']['address_component'];
$coach->longitude_location = $get['longitude'];
$coach->latitude_location = $get['latitude'];
$coach->location = $data;
$coach->save();
return true;
}catch (\Exception $e){
return $e->getMessage();
}
}
/**
* @notes 更新工作状态
* @param $coachId
* @return true
* @author cjhao
* @date 2024/8/29 16:33
*/
public function updateWorkStatus($coachId)
{
$coach = Coach::where(['id'=>$coachId])->findOrEmpty();
$coach->work_status = $coach->work_status ? 0 : 1;
$coach->save();
return true;
}
/**
* @notes 获取技师服务时间
* @param $coachId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author cjhao
* @date 2024/9/2 16:15
*/
public function getServerTime($coachId)
{
$advanceAppoint = ConfigService::get('server_setting', 'advance_appoint');
$timestampLists[date('m-d',time())] = time()+60*60;
//现在的时间戳和明天,后天零点的时间戳
for ($i = 1;$i < $advanceAppoint;$i++){
$timestampLists[date('m-d',strtotime('+ '.$i.' days'))] = strtotime('+ '.$i.' days midnight');
}
$intervalsLists = [];
foreach ($timestampLists as $date => $timestamp){
$intervalsLists[$date] = get_hour_to_midnight($timestamp);
}
//订单预约时间
$orderAppointLists = \app\common\logic\CoachLogic::getCoachOrderAppoint($coachId);
//师傅空闲时间
$serverTimeLists = [];
//师傅忙碌时间
$serverTimeBusyLists = [];
$coachServerTime = CoachServerTime::where(['coach_id'=>$coachId])
->field('date,time,status')
->select();
foreach ($coachServerTime as $time)
{
if(1 == $time['status']){
$serverTimeLists[$time['date']][] = $time['time'];
}else{
$serverTimeBusyLists[$time['date']][] = $time['time'];
}
}
// 获取当前日期的时间戳
$currentDate = strtotime(date('Y-m-d'));
// 获取明天和后天的时间戳
$tomorrowDate = strtotime('tomorrow');
$afterTomorrowDate = strtotime('+2 days',$currentDate);
foreach ($intervalsLists as $date => $intervals){
$timeTips = '';
$timestamp = strtotime(date('Y-'.$date));
if ($timestamp >=$currentDate && $timestamp <$tomorrowDate) {
$timeTips = '今天';
} elseif ($timestamp >=$tomorrowDate && $timestamp <$afterTomorrowDate) {
$timeTips = '明天';
} elseif ($timestamp >=$afterTomorrowDate && $timestamp < strtotime('+3 days',$currentDate)) {
$timeTips = '后天';
} else {
$weekdays = array('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六');
$weekdayIndex = date('w',$timestamp);
$timeTips = $weekdays[$weekdayIndex];
}
foreach ($intervals as $key => $interval){
$orderAppoint = $orderAppointLists[$date] ?? [];
$serverTime = $serverTimeLists[$date] ?? [];
$serverTimeBusy = $serverTimeBusyLists[$date]?? [];
// $intervalsLists[$date][$key]['status'] = 0;
//空闲时间
if(in_array($interval['time'],$serverTime) || empty($serverTime)){
$intervals[$key]['status'] = 1;
}
//忙
if(in_array($interval['time'],$serverTimeBusy)){
$intervals[$key]['status'] = 2;
}
//已预约
if(in_array($interval['time'],$orderAppoint)){
$intervals[$key]['status'] = 3;
}
}
$timeLists[] = [
'time_date' => $date,
'time_tips' => $timeTips,
'time_lists' => $intervals
];
}
return $timeLists;
}
/**
* @notes 设置服务时间
* @param $params
* @param $coachId
* @return string|true
* @author cjhao
* @date 2024/9/3 16:39
*/
public function setServerTime($params,$coachId)
{
try {
Db::startTrans();
$serverTime = [];
foreach ($params['server_time'] as $key => $time){
$times = [];
foreach ($time['time_lists'] as $timeList){
if(in_array($timeList['time'],$times)){
continue;
}
$serverTime[] = [
'coach_id' => $coachId,
'date' => $time['time_date'],
'time' => $timeList['time'],
'status' => $timeList['status']
];
$times[] = $timeList['time'];
}
}
CoachServerTime::where(['coach_id'=>$coachId])->delete();
(new CoachServerTime())->saveAll($serverTime);
Db::commit();
return true;
} catch (Exception $e) {
Db::rollback();
return $e->getMessage();
}
}
/**
* @notes 个人资料
* @param $coachId
* @return array
* @author ljj
* @date 2024/12/3 下午3:47
*/
public function personalData($coachId)
{
$detail = Coach::alias('c')
->join('coach_user cu', 'cu.id = c.coach_user_id')
->where(['c.id'=>$coachId])
->field('c.id,cu.sn,c.work_photo,c.name,c.gender,c.age,c.mobile,c.introduction')
->findOrEmpty()
->toArray();
$detail['gender_desc'] = CoachUserEnum::getSexDesc($detail['gender']);
return $detail;
}
/**
* @notes 设置个人资料
* @param $params
* @return bool
* @author ljj
* @date 2024/12/3 下午3:57
*/
public static function setPersonalData($params): bool
{
Coach::update(['id' => $params['coach_id'], $params['field'] => $params['value']]);
return true;
}
/**
* @notes 绑定手机号
* @param $params
* @return bool
* @author Tab
* @date 2021/8/25 17:55
*/
public static function bindMobile($params)
{
try {
if (empty($params['mobile']) || empty($params['code'])) {
throw new \Exception('请输入手机号和验证码');
}
$smsDriver = new SmsDriver();
$result = $smsDriver->verify($params['mobile'], $params['code']);
if(!$result) {
throw new \Exception('验证码错误');
}
$user = Coach::where(['mobile'=>$params['mobile']])->where('id','<>',$params['coach_id'])->findOrEmpty();
if(!$user->isEmpty()) {
throw new \Exception('该手机号已被其他账号绑定');
}
$user = CoachUpdate::where(['coach_id'=>$params['coach_id']])->where(['mobile'=>$params['mobile'],'audit_status'=>ShopEnum::AUDIT_STATUS_WAIT])->where('id','<>',$params['coach_id'])->findOrEmpty();
if(!$user->isEmpty()) {
throw new \Exception('该手机号已被其他账号绑定');
}
unset($params['code']);
$coach = Coach::findOrEmpty($params['coach_id'])->toArray();
Coach::update(['mobile'=>$params['mobile'],'id'=>$params['coach_id']]);
CoachUser::update(['account'=>$params['mobile'],'id'=>$coach['coach_user_id']]);
return true;
} catch (\Exception $e) {
return $e->getMessage();
}
}
}

View File

@@ -0,0 +1,138 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\coachapi\logic;
use app\common\logic\BaseLogic;
use app\common\model\TextList;
use app\common\service\ConfigService;
use app\common\service\FileService;
class ConfigLogic extends BaseLogic
{
/**
* @notes 基础配置信息
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author ljj
* @date 2022/2/23 10:30 上午
*/
public function config()
{
$config = [
// 登录方式
'login_way' => ConfigService::get('login', 'login_way', config('project.login.login_way')),
// 注册强制绑定手机
'coerce_mobile' => ConfigService::get('login', 'coerce_mobile', config('project.login.coerce_mobile')),
// 政策协议
'login_agreement' => ConfigService::get('login', 'login_agreement', config('project.login.login_agreement')),
// 第三方登录 开关
'third_auth' => ConfigService::get('login', 'third_auth', config('project.login.third_auth')),
// 微信授权登录
'wechat_auth' => ConfigService::get('login', 'wechat_auth', config('project.login.wechat_auth')),
// qq授权登录
// 'qq_auth' => ConfigService::get('login', 'qq_auth', config('project.login.qq_auth')),
//版权信息
'info' => ConfigService::get('copyright', 'info'),
//ICP备案号
'icp_number' => ConfigService::get('copyright', 'icp_number'),
//ICP备案链接
'icp_link' => ConfigService::get('copyright', 'icp_link'),
//名称
'name' => ConfigService::get('coach', 'name',''),
//logo
'logo' => FileService::getFileUrl(ConfigService::get('coach', 'logo','')),
//地图key
'tencent_map_key' => ConfigService::get('map','tencent_map_key',''),
//版本号
'version' => request()->header('version'),
//默认头像
'default_avatar' => ConfigService::get('config', 'default_coach_avatar', FileService::getFileUrl(config('project.default_image.user_avatar'))),
//文件域名
'domain' => request()->domain().'/',
//联系客服
'service_mobile' => ConfigService::get('platform', 'service_mobile',''),
//网站名称
'web_name' => ConfigService::get('platform_logo', 'platform_name',''),
//网站logo
'web_logo' => FileService::getFileUrl(ConfigService::get('platform_logo', 'platform_logo')),
//商城名称
'shop_name' => ConfigService::get('coach', 'coach_name',''),
//商城logo
'shop_logo' => FileService::getFileUrl(ConfigService::get('coach', 'coach_logo','')),
];
return $config;
}
/**
* @notes 政策协议
* @return array
* @author ljj
* @date 2022/2/23 11:42 上午
*/
public function agreement()
{
$service = TextList::where(['id'=>3])->field('title,content')->findOrEmpty();
$privacy = TextList::where(['id'=>4])->field('title,content')->findOrEmpty();
$config = [
//隐私协议
'service_title' => $service['title'],
'service_agreement' => $service['content'],
//服务协议
'privacy_title' => $privacy['title'],
'privacy_agreement' => $privacy['content'],
];
return $config;
}
/**
* @notes 获取客服配置
* @return array
* @author ljj
* @date 2024/8/28 下午4:06
*/
public function getKefuConfig()
{
$defaultData = [
'way' => 1,
'name' => '',
'remarks' => '',
'phone' => '',
'business_time' => '',
'qr_code' => '',
'enterprise_id' => '',
'kefu_link' => ''
];
$config = [
'mnp' => ConfigService::get('kefu_config', 'mnp', $defaultData),
'oa' => ConfigService::get('kefu_config', 'oa', $defaultData),
'h5' => ConfigService::get('kefu_config', 'h5', $defaultData),
];
if (!empty($config['mnp']['qr_code'])) $config['mnp']['qr_code'] = FileService::getFileUrl($config['mnp']['qr_code']);
if (!empty($config['oa']['qr_code'])) $config['oa']['qr_code'] = FileService::getFileUrl($config['oa']['qr_code']);
if (!empty($config['h5']['qr_code'])) $config['h5']['qr_code'] = FileService::getFileUrl($config['h5']['qr_code']);
return $config;
}
}

View File

@@ -0,0 +1,54 @@
<?php
namespace app\coachapi\logic;
use app\common\model\decorate\DecoratePage;
use app\common\model\decorate\DecorateStyle;
use app\common\model\decorate\DecorateTabbar;
/**
* 装修逻辑类
* Class DecorateLogic
* @package app\api\logic
*/
class DecorateLogic
{
/**
* @notes 获取装修页面
* @param int $type
* @return array
* @author cjhao
* @date 2024/10/8 15:11
*/
public function page(int $type)
{
$detail = DecoratePage::where(['type'=>$type,'source'=>2])->findOrEmpty()->toArray();
return $detail;
}
/**
* @notes 获取装修风格
* @return array
* @author cjhao
* @date 2024/10/8 15:13
*/
public function style()
{
$detail = DecorateStyle::where(['source'=>2])->findOrEmpty()->toArray();
return $detail;
}
/**
* @notes 底部菜单
* @return array
* @author cjhao
* @date 2024/10/8 15:59
*/
public function tabbar()
{
$detail = DecorateTabbar::where(['source'=>2])->findOrEmpty()->toArray();
return $detail;
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace app\coachapi\logic;
use app\common\enum\coach\CoachEnum;
use app\common\logic\BaseLogic;
use app\common\model\coach\Coach;
use app\common\model\deposit\DepositOrder;
use app\common\model\deposit\DepositPackage;
use app\common\model\order\OrderAppend;
use app\common\model\shop\Shop;
use think\Exception;
/**
* 保证金套餐逻辑类
* Class DepositLogic
* @package app\coachapi\logic
*/
class DepositLogic extends BaseLogic
{
/**
* @notes 套餐列表
* @param $coachId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author cjhao
* @date 2024/8/27 18:25
*/
public function depositPackage($coachUserId)
{
$deposit = Coach::where(['coach_user_id'=>$coachUserId,'audit_status'=>CoachEnum::AUDIT_STATUS_PASS])->order('id desc')->value('deposit');
$packageLists = DepositPackage::where(['type'=>1])
->withoutField('is_show,create_time,update_time,delete_time')
->order('id desc')
->select();
return [
'deposit' => $deposit,
'package_list' => $packageLists,
];
}
/**
* @notes 提交订单
* @param array $params
* @param int $coachId
* @return array|bool
* @author cjhao
* @date 2024/8/27 18:52
*/
public function sumbitOrder(array $params,int $coachId)
{
try {
$money = $params['money'] ?? 0;
$payWay = $params['pay_way'] ?? 0;
if(empty($coachId)){
return '请先申请成为技师';
}
if($money <= 0){
throw new Exception('充值金额不能小于零');
}
if(empty($payWay)){
throw new Exception('请选择支付方式');
}
$depositOrder = DepositOrder::create([
'sn' => generate_sn((new DepositOrder()), 'sn'),
'order_amount' => $money,
'relation_id' => $coachId,
'pay_way' => $payWay,
]);
return [
'id' => $depositOrder->id,
'sn' => $depositOrder->sn,
'type' => 'deposit'
];
}catch (Exception $e) {
self::$error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace app\coachapi\logic;
use app\common\model\goods\GoodsComment;
class GoodsCommentLogic
{
public function commentCategory(int $coachId)
{
$all_count = GoodsComment::where('coach_id', $coachId)->count();
$image_count = GoodsComment::alias('gc')->where('coach_id',$coachId)->join('goods_comment_image gci', 'gc.id = gci.comment_id')->group('gci.comment_id')->count();
$good_count = GoodsComment::where('coach_id', $coachId)->where('service_comment','>',3)->count();
$medium_bad_count = GoodsComment::where('coach_id', $coachId)->where('service_comment','<=',3)->count();
if($all_count == 0) {
$percentStr = '100%';
$star = 5;
}else {
$percent = round((($good_count / $all_count) * 100));
$percentStr = round((($good_count / $all_count) * 100)).'%';
if ($percent >= 100) {
$star = 5;
} else if ($percent >= 80) {
$star = 4;
} else if ($percent >= 60) {
$star = 3;
} else if ($percent >= 40) {
$star = 2;
} else if ($percent >= 20) {
$star = 1;
} else {
$star = 0;
}
}
return ['comment'=>
[
[
'id' => 0,
'name' => '全部',
'count' => $all_count
],
[
'id' => 1,
'name' => '有图',
'count' => $image_count
],
[
'id' => 2,
'name' => '好评',
'count' => $good_count
],
[
'id' => 3,
'name' => '中差评',
'count' => $medium_bad_count
]
] ,
'percent' => $percentStr,
'star' => $star,
];
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace app\coachapi\logic;
use app\common\model\goods\Goods;
use app\common\model\goods\GoodsCityIndex;
use app\common\model\goods\GoodsSkillIndex;
use app\common\model\skill\Skill;
/**
* 服务逻辑类
* Class GoodsLogic
* @package app\coachapi\logic
*/
class GoodsLogic
{
/**
* @notes 获取技能列表
* @return mixed
* @author cjhao
* @date 2024/10/13 00:25
*/
public function skillLists($coachId)
{
$lists = Skill::alias('S')
->join('coach C','S.id = C.skill_id')
->where(['C.id'=>$coachId])
->field('S.id,S.name')
->select()->toArray();
array_unshift($lists,['id'=>0,'name'=>'全部']);
return $lists;
}
/**
* @notes 商品详情
* @param $id
* @return array
* @author cjhao
* @date 2024/11/27 14:41
*/
public function detail($id)
{
$result = Goods::where('id',$id)
->withoutField('update_time,delete_time')
->append(['category_desc','goods_image'])
->findOrEmpty()
->toArray();
$result['virtual_order_num'] = $result['virtual_order_num'] + $result['order_num'];
$goods_image = [];
foreach ($result['goods_image'] as &$image) {
$goods_image[] = $image['uri'];
}
$result['goods_image'] = $goods_image;
$result['skill_id'] = GoodsSkillIndex::where(['goods_id'=>$id])->column('skill_id');
return $result;
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace app\coachapi\logic;
use app\common\logic\BaseLogic;
use app\common\model\coach\Coach;
use app\common\service\ConfigService;
use think\Exception;
class IndexLogic extends BaseLogic
{
}

View File

@@ -0,0 +1,445 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\coachapi\logic;
use app\coachapi\service\CoachUserTokenService;
use app\coachapi\service\ShopUserTokenService;
use app\common\enum\coach\CoachEnum;
use app\common\enum\notice\NoticeEnum;
use app\common\logic\BaseLogic;
use app\common\model\coach\Coach;
use app\common\model\coach\CoachUser;
use app\common\service\{ConfigService, FileService, sms\SmsDriver, WeChatService};
use think\facade\{Db, Config};
use Exception;
/**
* 登录逻辑
* Class LoginLogic
* @package app\coachapi\logic
*/
class LoginLogic extends BaseLogic
{
/**
* @notes 账号密码注册
* @param array $params
* @return bool
* @author 段誉
* @date 2022/9/7 15:37
*/
public static function register(array $params)
{
try {
$smsDriver = new SmsDriver();
$result = $smsDriver->verify($params['account'], $params['code'], NoticeEnum::REGISTER_CAPTCHA_STAFF);
if (!$result) {
throw new Exception('验证码错误');
}
$number = CoachUser::count()+1;
$sn = sprintf("%03d", $number);
$passwordSalt = Config::get('project.unique_identification');
$password = create_password($params['password'], $passwordSalt);
$avatar = ConfigService::get('default_image', 'user_avatar');
CoachUser::create([
'sn' => $sn,
'avatar' => $avatar,
'account' => $params['account'],
'password' => $password,
// 'channel' => $params['channel'],
]);
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 账号/手机号登录,手机号验证码
* @param $params
* @return array|false
* @author 段誉
* @date 2022/9/6 19:26
*/
public static function login($params)
{
try {
$where = ['account' => $params['account']];
$coachUser = CoachUser::where($where)->findOrEmpty();
if ($coachUser->isEmpty()) {
throw new \Exception('账号不存在');
}
//更新登录信息
$coachUser->login_time = time();
$coachUser->login_ip = request()->ip();
$coachUser->save();
//设置token
$coachUserInfo = CoachUserTokenService::setToken($coachUser->id, $params['terminal']);
//返回登录信息
$avatar = $coachUser->avatar ?: Config::get('project.default_image.user_avatar');
$avatar = FileService::getFileUrl($avatar);
// $coach = Coach::where(['coach_user_id'=>$coachUser->id])->order('id desc')->findOrEmpty();
// if(!$coach->isEmpty()){
// $avatar = $coach->work_photo;
// }
return [
'sn' => $coachUserInfo['sn'],
'account' => $coachUserInfo['account'],
'avatar' => $avatar,
'token' => $coachUserInfo['token'],
];
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 退出登录
* @param $userInfo
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author 段誉
* @date 2022/9/16 17:56
*/
public static function logout($coachInfo)
{
//token不存在不注销
if (!isset($coachInfo['token'])) {
return false;
}
//设置token过期
return CoachUserTokenService::expireToken($coachInfo['token']);
}
/**
* @notes 获取微信请求code的链接
* @param string $url
* @return string
* @author 段誉
* @date 2022/9/20 19:47
*/
public static function codeUrl(string $url)
{
return WeChatService::getCodeUrl($url);
}
/**
* @notes 公众号登录
* @param array $params
* @return array|false
* @throws \GuzzleHttp\Exception\GuzzleException
* @author 段誉
* @date 2022/9/20 19:47
*/
public static function oaLogin(array $params)
{
Db::startTrans();
try {
//通过code获取微信 openid
$response = WeChatService::getOaResByCode($params);
$userServer = new WechatUserService($response, UserTerminalEnum::WECHAT_OA);
$userInfo = $userServer->getResopnseByUserInfo()->authUserLogin()->getUserInfo();
// 更新登录信息
self::updateLoginInfo($userInfo['id']);
Db::commit();
return $userInfo;
} catch (\Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 小程序-静默登录
* @param array $params
* @return array|false
* @author 段誉
* @date 2022/9/20 19:47
*/
public static function silentLogin(array $params)
{
try {
//通过code获取微信 openid
$response = WeChatService::getMnpResByCode($params);
$userServer = new WechatUserService($response, UserTerminalEnum::WECHAT_MMP);
$userInfo = $userServer->getResopnseByUserInfo('silent')->getUserInfo();
if (!empty($userInfo)) {
// 更新登录信息
self::updateLoginInfo($userInfo['id']);
}
return $userInfo;
} catch (\Exception $e) {
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 小程序-授权登录
* @param array $params
* @return array|false
* @author 段誉
* @date 2022/9/20 19:47
*/
public static function mnpLogin(array $params)
{
Db::startTrans();
try {
//通过code获取微信 openid
$response = WeChatService::getMnpResByCode($params);
$userServer = new WechatUserService($response, UserTerminalEnum::WECHAT_MMP);
$userInfo = $userServer->getResopnseByUserInfo()->authUserLogin()->getUserInfo();
// 更新登录信息
self::updateLoginInfo($userInfo['id']);
Db::commit();
return $userInfo;
} catch (\Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 更新登录信息
* @param $userId
* @throws \Exception
* @author 段誉
* @date 2022/9/20 19:46
*/
public static function updateLoginInfo($userId)
{
$user = User::findOrEmpty($userId);
if ($user->isEmpty()) {
throw new \Exception('用户不存在');
}
$time = time();
$user->login_time = $time;
$user->login_ip = request()->ip();
$user->update_time = $time;
$user->save();
}
/**
* @notes 小程序端绑定微信
* @param array $params
* @return bool
* @author 段誉
* @date 2022/9/20 19:46
*/
public static function mnpAuthLogin(array $params)
{
try {
//通过code获取微信openid
$response = WeChatService::getMnpResByCode($params);
$response['user_id'] = $params['user_id'];
$response['terminal'] = UserTerminalEnum::WECHAT_MMP;
return self::createAuth($response);
} catch (\Exception $e) {
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 公众号端绑定微信
* @param array $params
* @return bool
* @throws \GuzzleHttp\Exception\GuzzleException
* @author 段誉
* @date 2022/9/16 10:43
*/
public static function oaAuthLogin(array $params)
{
try {
//通过code获取微信openid
$response = WeChatService::getOaResByCode($params);
$response['user_id'] = $params['user_id'];
$response['terminal'] = UserTerminalEnum::WECHAT_OA;
return self::createAuth($response);
} catch (\Exception $e) {
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 生成授权记录
* @param $response
* @return bool
* @throws \Exception
* @author 段誉
* @date 2022/9/16 10:43
*/
public static function createAuth($response)
{
//先检查openid是否有记录
$isAuth = UserAuth::where('openid', '=', $response['openid'])->findOrEmpty();
if (!$isAuth->isEmpty()) {
throw new \Exception('该微信已经绑定其他账号');
}
if (isset($response['unionid']) && !empty($response['unionid'])) {
//在用unionid找记录防止生成两个账号同个unionid的问题
$userAuth = UserAuth::where(['unionid' => $response['unionid']])
->findOrEmpty();
if (!$userAuth->isEmpty() && $userAuth->user_id != $response['user_id']) {
throw new \Exception('该微信已经绑定其他账号');
}
}
//如果没有授权,直接生成一条微信授权记录
UserAuth::create([
'user_id' => $response['user_id'],
'openid' => $response['openid'],
'unionid' => $response['unionid'] ?? '',
'terminal' => $response['terminal'],
]);
return true;
}
/**
* @notes 解绑微信(测试用)
* @param $user_id
* @return bool
* @author ljj
* @date 2023/1/11 10:35 上午
*/
public static function unbinding($user_id)
{
$session = UserSession::where(['user_id'=>$user_id])->findOrEmpty()->toArray();
UserAuth::where(['user_id'=>$user_id,'terminal'=>$session['terminal']])->delete();
return true;
}
/**
* @notes 更新用户头像昵称
* @param $post
* @param $user_id
* @return bool
* @throws \think\db\exception\DbException
* @author ljj
* @date 2023/2/2 6:36 下午
*/
public static function updateUser($post,$user_id)
{
Db::name('user')->where(['id'=>$user_id])->update(['nickname'=>$post['nickname'],'avatar'=>FileService::setFileUrl($post['avatar']),'is_new_user'=>0]);
return true;
}
/**
* @notes 重置登录密码
* @param $params
* @return bool
* @author 段誉
* @date 2022/9/16 18:06
*/
public function resetPassword(array $params): bool
{
try {
// Db::startTrans();
// 校验验证码
$smsDriver = new SmsDriver();
if (!$smsDriver->verify($params['mobile'], $params['code'], NoticeEnum::RESET_PASSWORD_CAPTCHA_STAFF)) {
throw new \Exception('验证码错误');
}
// 重置密码
$passwordSalt = Config::get('project.unique_identification');
$password = create_password($params['password'], $passwordSalt);
$coachUser = CoachUser::where(['account'=>$params['mobile']])->findOrEmpty();
if($coachUser->isEmpty()){
throw new \Exception('账号不存在');
}
// 更新
$coachUser->password = $password;
$coachUser->save();
// Coach::where(['coach_user_id'=>$coachUser->id,'audit_status'=>CoachEnum::AUDIT_STATUS_PASS])->update([
// 'mobile' => $params['mobile']
// ]);
// Db::commit();
return true;
} catch (\Exception $e) {
// Db::rollback();
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 重置登录密码
* @param $params
* @return bool
* @author 段誉
* @date 2022/9/16 18:06
*/
public function changePassword(array $params): bool
{
try {
// Db::startTrans();
// 重置密码
$passwordSalt = Config::get('project.unique_identification');
$password = create_password($params['password'], $passwordSalt);
$coachUser = CoachUser::where(['id'=>$params['coach_info']['coach_user_id']])->findOrEmpty();
// if($coachUser->isEmpty()){
// throw new \Exception('账号不存在');
// }
// 更新
$coachUser->password = $password;
$coachUser->save();
// Db::commit();
return true;
} catch (\Exception $e) {
// Db::rollback();
self::setError($e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,366 @@
<?php
namespace app\coachapi\logic;
use app\common\enum\notice\NoticeEnum;
use app\common\enum\OrderEnum;
use app\common\enum\OrderLogEnum;
use app\common\logic\BaseLogic;
use app\common\logic\OrderLogLogic;
use app\common\model\coach\Coach;
use app\common\model\order\Order;
use app\common\model\order\OrderLog;
use app\common\model\settle\SettleOrder;
use app\common\service\ConfigService;
use app\common\service\FileService;
use app\common\service\TencentMapKeyService;
use think\Exception;
use think\facade\Db;
class OrderLogic extends BaseLogic
{
/**
* @notes 订单详情
* @param int $id
* @return array
* @author cjhao
* @date 2024/9/20 02:19
*/
public function detail(int $id)
{
$detail = Order::field('id,sn,order_status,total_order_amount,user_remark,pay_status,pay_way,total_refund_amount,goods_price,order_amount,total_order_amount,total_amount,total_gap_amount,total_append_amount,appoint_time,order_amount,user_remark,address_snap,is_settle,server_finish_time,create_time,refund_amount,coach_id,car_amount,order_distance,update_time,true_server_finish_time')
->order('id','desc')
->append(['order_distance_desc','pay_way_desc','appoint_time','appoint_date','order_status_desc','take_order_btn','depart_btn','arrive_btn','server_start_btn','server_finish_btn','order_cancel_time'])
->with(['order_goods' => function($query){
$query->field('order_id,goods_id,goods_snap,goods_num,duration,goods_image,goods_name,goods_price')->hidden(['goods_snap']);
},'order_gap','order_append'])
->where(['id'=>$id])
->findOrEmpty()
->toArray();
if(!isset($detail['address_snap']['house_number'])){
$detail['address_snap']['house_number'] = '';
}
$orderLog = OrderLog::where(['order_id'=>$id,'type'=>OrderLogEnum::TYPE_COACH])
->field('content,location,extra,create_time')
->order('id asc')
->select()->toArray();
$logLists = [];
foreach ($orderLog as $key => $log){
$date = date('Y-m-d',strtotime($log['create_time']));
if($log['extra']){
foreach ($log['extra'] as $key => $extra){
$log['extra'][$key] = FileService::getFileUrl($extra);
}
}
$logLists[$date][] = $log;
}
// $logLists = $orderLog;
$settleOrder = [];
if($detail['is_settle']){
$settleOrder = SettleOrder::where(['order_id'=>$detail['id']])->findOrEmpty();
}
$coachCommission = $settleOrder['coach_commission'] ?? 0;
$coachCarCommission = $settleOrder['coach_car_amount'] ?? 0;
// $totalOrderAmount = $settleOrder['order_amount'] ?? 0;
// $carAmount = $settleOrder['car_amount'] ?? 0;
$detail['settle_info'] = [
'status' => $detail['is_settle'],
'refund_amount' => $detail['total_refund_amount'],
'order_amount' => $settleOrder['order_amount'] ?? 0,
'settle_car' => $settleOrder['car_amount'] ?? 0 ,
'settle_amount' => $settleOrder['total_commission'] ?? 0 ,
'coach_settle' => $settleOrder['coach_commission'] ?? 0,
'shop_settle' => 0,
// 'total_settle_amount'=> round($totalOrderAmount + $carAmount ,2),
];
$detail['server_log_lists'] = $logLists;
return $detail;
}
/**
* @notes 接单操作
* @param $params
* @return bool
* @author cjhao
* @date 2024/9/13 17:21
*/
public function take($params)
{
try {
Db::startTrans();
$order = Order::where(['id'=>$params['id'],'coach_id'=>$params['coach_id']])
->findOrEmpty();
if($order->isEmpty()){
throw new Exception('订单不存在');
}
if(OrderEnum::ORDER_STATUS_WAIT_RECEIVING != $order->order_status){
throw new Exception('订单状态已改变,请刷新页面');
}
$coach = Coach::where(['id'=>$params['coach_id']])->findOrEmpty();
//验证接单数量
\app\common\logic\CoachLogic::ckechCoachTakeOrderNum($coach);
$order->order_status = OrderEnum::ORDER_STATUS_WAIT_DEPART;
$order->save();
//订单日志
(new OrderLogLogic())->record(OrderLogEnum::TYPE_COACH,OrderLogEnum::COACH_TAKE_ORDER,$order['id'],$params['coach_id']);
event('Notice', [
'scene_id' => NoticeEnum::ACCEPT_ORDER_NOTICE,
'params' => [
'user_id' => $order['user_id'],
'order_id' => $order['id']
]
]);
//提交事务
Db::commit();
return true;
}catch (Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 出发操作
* @param $params
* @return bool
* @author cjhao
* @date 2024/9/13 17:21
*/
public function depart($params)
{
try {
Db::startTrans();
$order = Order::where(['id'=>$params['id'],'coach_id'=>$params['coach_id']])
->findOrEmpty();
if($order->isEmpty()){
throw new Exception('订单不存在');
}
if(OrderEnum::ORDER_STATUS_WAIT_DEPART != $order->order_status){
throw new Exception('订单状态已改变,请刷新页面');
}
$order->order_status = OrderEnum::ORDER_STATUS_DEPART;
$order->save();
//订单日志
(new OrderLogLogic())->record(OrderLogEnum::TYPE_COACH,OrderLogEnum::COACH_DEPART,$order['id'],$params['coach_id']);
//提交事务
Db::commit();
return true;
}catch (Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 达到操作
* @param $params
* @return bool
* @author cjhao
* @date 2024/9/13 17:21
*/
public function arrive($params)
{
try {
$imageLists = $params['image_lists'] ?? [];
if(empty($imageLists)){
throw new Exception('请上传图片');
}
Db::startTrans();
if (!isset($params['latitude']) || $params['longitude'] == '') {
throw new Exception('请上传位置');
}
$order = Order::where(['id'=>$params['id'],'coach_id'=>$params['coach_id']])
->findOrEmpty();
if($order->isEmpty()){
throw new Exception('订单不存在');
}
if(OrderEnum::ORDER_STATUS_DEPART != $order->order_status){
throw new Exception('订单状态已改变,请刷新页面');
}
$order->order_status = OrderEnum::ORDER_STATUS_ARRIVE;
$order->save();
$key = (new TencentMapKeyService())->getTencentMapKey();
if (empty($key)) {
throw new Exception('请联系管理员检查腾讯地图配置');
}
$data['location'] = $params['latitude'].','.$params['longitude'];
$data['key'] = $key;
$url = 'https://apis.map.qq.com/ws/geocoder/v1/';
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
if ($result['status'] !== 0) {
$check = (new TencentMapKeyService())->checkResult($result);
while (!$check) {
$data['key'] = (new TencentMapKeyService())->getTencentMapKey(true);
if (empty($data['key'])) {
break;
}
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
$check = (new TencentMapKeyService())->checkResult($result);
}
}
$data = [];
$data = $result['result']['address_component'];
$data['longitude'] = $params['longitude'];
$data['latitude'] = $params['latitude'];
foreach($imageLists as $key => $image){
$imageLists[$key] = FileService::setFileUrl($image);
}
//订单日志
(new OrderLogLogic())->record(OrderLogEnum::TYPE_COACH,OrderLogEnum::COACH_ARRIVE,$order['id'],$params['coach_id'],'',$data,$imageLists);
//提交事务
Db::commit();
return true;
}catch (Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 服务开始操作
* @param $params
* @return bool
* @author cjhao
* @date 2024/9/13 17:21
*/
public function startServer($params)
{
try {
Db::startTrans();
$order = Order::where(['id'=>$params['id'],'coach_id'=>$params['coach_id']])
->findOrEmpty();
if($order->isEmpty()){
throw new Exception('订单不存在');
}
if(OrderEnum::ORDER_STATUS_ARRIVE != $order->order_status){
throw new Exception('订单状态已改变,请刷新页面');
}
$order->order_status = OrderEnum::ORDER_STATUS_START_SERVER;
$order->save();
//订单日志
(new OrderLogLogic())->record(OrderLogEnum::TYPE_COACH,OrderLogEnum::COACH_START_SERVER,$order['id'],$params['coach_id']);
//开始服务通知用户
event('Notice', [
'scene_id' => NoticeEnum::START_SERVICE_NOTICE,
'params' => [
'user_id' => $order['user_id'],
'order_id' => $order['id']
]
]);
//开始服务通知师傅
event('Notice', [
'scene_id' => NoticeEnum::START_SERVICE_NOTICE_STAFF,
'params' => [
'coach_id' => $order['coach_id'],
'order_id' => $order['id']
]
]);
//提交事务
Db::commit();
return true;
}catch (Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 服务完成
* @param $params
* @return bool
* @author cjhao
* @date 2024/9/14 14:52
*/
public function finishServer($params)
{
try {
$order = Order::where(['id'=>$params['id'],'coach_id'=>$params['coach_id']])
->findOrEmpty();
Coach::update(['order_num'=>['inc',1]],['id'=>$order['coach_id']]);
Db::startTrans();
$imageLists = $params['image_lists'] ?? [];
if(empty($imageLists)){
throw new Exception('请上传图片');
}
if($order->isEmpty()){
throw new Exception('订单不存在');
}
if(OrderEnum::ORDER_STATUS_START_SERVER != $order->order_status){
throw new Exception('订单状态已改变,请刷新页面');
}
$order->order_status = OrderEnum::ORDER_STATUS_SERVER_FINISH;
$order->true_server_finish_time = time();
$order->save();
$key = (new TencentMapKeyService())->getTencentMapKey();
if (empty($key)) {
throw new Exception('请联系管理员检查腾讯地图配置');
}
$data['location'] = $params['latitude'].','.$params['longitude'];
$data['key'] = $key;
$url = 'https://apis.map.qq.com/ws/geocoder/v1/';
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
if ($result['status'] !== 0) {
$check = (new TencentMapKeyService())->checkResult($result);
while (!$check) {
$data['key'] = (new TencentMapKeyService())->getTencentMapKey(true);
if (empty($data['key'])) {
break;
}
$query = http_build_query($data);
$result = json_decode(file_get_contents($url . '?' . $query), true);
$check = (new TencentMapKeyService())->checkResult($result);
}
}
$data = [];
$data = $result['result']['address_component'];
$data['longitude'] = $params['longitude'];
$data['latitude'] = $params['latitude'];
foreach($imageLists as $key => $image){
$imageLists[$key] = FileService::setFileUrl($image);
}
(new OrderLogLogic())->record(OrderLogEnum::TYPE_COACH,OrderLogEnum::COACH_SERVER_FINISH,$order['id'],$params['coach_id'],'',$data,$imageLists);
//完成服务-用户
event('Notice', [
'scene_id' => NoticeEnum::FINISH_SERVICE_NOTICE,
'params' => [
'user_id' => $order['user_id'],
'order_id' => $order['id']
]
]);
//完成服务-师傅
event('Notice', [
'scene_id' => NoticeEnum::END_SERVICE_NOTICE_STAFF,
'params' => [
'coach_id' => $order['coach_id'],
'order_id' => $order['id']
]
]);
Coach::update(['order_num'=>['inc',1]],['id'=>$order['coach_id']]);
//提交事务
Db::commit();
return true;
}catch (Exception $e) {
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,245 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\coachapi\logic;
use app\common\enum\PayEnum;
use app\common\enum\user\UserTerminalEnum;
use app\common\enum\YesNoEnum;
use app\common\logic\BaseLogic;
use app\common\logic\CoachPayNotifyLogic;
use app\common\model\deposit\DepositOrder;
use app\common\model\pay\PayWay;
use app\common\model\user\User;
use app\common\service\AliPayService;
use app\common\service\BalancePayService;
use app\common\service\CoachBalancePayService;
use app\common\service\ConfigService;
use app\common\service\WeChatPayService;
use app\common\service\WeChatService;
class PayLogic extends BaseLogic
{
/**
* @notes 支付方式
* @param $params
* @return array|false
* @author ljj
* @date 2022/2/28 2:56 下午
*/
public static function payWay($params)
{
try {
$order = [];
// 获取待支付金额
// if ($params['from'] == 'deposit') {
// // 订单
// $order = DepositOrder::findOrEmpty($params['order_id'])->toArray();
// }
//
// if (empty($order)) {
// throw new \Exception('订单不存在');
// }
// 获取订单剩余支付时间
// $cancelUnpaidOrders = ConfigService::get('transaction', 'cancel_unpaid_orders',1);
// $cancelUnpaidOrdersTimes = ConfigService::get('transaction', 'cancel_unpaid_orders_times',30);
// $cancelTime = 0;
// if(!in_array($params['from'],['deposit'])){
// if (empty($cancelUnpaidOrders)) {
// // 不自动取消待支付订单
// $cancelTime = 0;
// } else {
// // 指定时间内取消待支付订单
// $cancelTime = strtotime($order['create_time']) + intval($cancelUnpaidOrdersTimes) * 60;
// }
// }
$pay_way = PayWay::alias('pw')
->join('dev_pay dp', 'pw.pay_id = dp.id')
->where(['pw.scene'=>$params['scene'],'pw.status'=>YesNoEnum::YES])
->field('dp.id,dp.name,dp.pay_way,dp.image,pw.is_default')
->order(['sort'=>'asc','id'=>'desc'])
->select()
->toArray();
foreach ($pay_way as $k=>&$item) {
if ($item['pay_way'] == PayEnum::WECHAT_PAY) {
$item['extra'] = '微信支付';
}
if ($item['pay_way'] == PayEnum::ALI_PAY) {
$item['extra'] = '支付宝支付';
}
// if ($item['pay_way'] == PayEnum::BALANCE_PAY) {
// $user_money = User::where(['id' => $params['user_id']])->value('user_money');
// $item['extra'] = '可用余额:'.$user_money;
// }
// 充值时去除余额支付
if ( $item['pay_way'] == PayEnum::BALANCE_PAY) {
unset($pay_way[$k]);
}
// 充值时去除微信支付
if ( $item['pay_way'] == PayEnum::WECHAT_PAY) {
unset($pay_way[$k]);
}
}
return [
'lists' => array_values($pay_way),
// 'order_amount' => $order['order_amount'],
// 'cancel_time' => $cancelTime,
];
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 支付
* @param $payWay // 支付方式
* @param $from //订单来源(商品订单?充值订单?其他订单?)
* @param $order_id //订单id
* @param $terminal //终端
* @param $wechatCode //终端
* @return array|bool|string|void
* @throws \Exception
* @author 段誉
* @date 2021/7/29 14:49
*/
public static function pay($payWay, $from, $order_id, $terminal,$wechatCode = '')
{
$order = [];
//更新支付方式
switch ($from) {
case 'deposit':
DepositOrder::update(['pay_way' => $payWay], ['id' => $order_id]);
$order = DepositOrder::where('id',$order_id)->findOrEmpty()->toArray();
break;
}
if (empty($order)) {
self::setError('订单错误');
}
if($order['order_amount'] == 0) {
CoachPayNotifyLogic::handle($from, $order['sn']);
return ['pay_way'=>$payWay];
}
switch ($payWay) {
case PayEnum::WECHAT_PAY:
if (isset($wechatCode) && $wechatCode != '') {
switch ($terminal) {
case UserTerminalEnum::WECHAT_MMP:
$response = (new WeChatService())->getMnpResByCode($wechatCode);
$order['openid'] = $response['openid'];
break;
case UserTerminalEnum::WECHAT_OA:
$response = (new WeChatService())->getOaResByCode($wechatCode);
$order['openid'] = $response['openid'];
break;
}
DepositOrder::update(['openid' => $order['openid']], ['id' => $order_id]);
}
$payService = (new WeChatPayService($terminal, null));
$result = $payService->pay($from, $order);
break;
case PayEnum::BALANCE_PAY:
//余额支付
$payService = (new CoachBalancePayService());
$result = $payService->pay($from, $order);
if (false !== $result) {
CoachPayNotifyLogic::handle($from, $order['sn']);
}
break;
case PayEnum::ALI_PAY:
$payService = (new AliPayService($terminal));
$result = $payService->pay($from, $order);
break;
default:
self::$error = '订单异常';
$result = false;
}
//支付成功, 执行支付回调
if (false === $result && !self::hasError()) {
self::setError($payService->getError());
}
return $result;
}
/**
* @notes 获取支付结果
* @param $params
* @return array
* @author ljj
* @date 2024/3/21 5:48 下午
*/
public static function getPayResult($params)
{
switch ($params['from']) {
case 'deposit' :
$result = DepositOrder::where(['id' => $params['order_id']])
->field(['id', 'sn', 'pay_time', 'pay_way', 'order_amount', 'pay_status'])
->findOrEmpty()
->toArray();
$result['total_amount'] = '¥' . $result['order_amount'];
break;
default :
$result = [];
}
if (empty($result)) {
self::$error = '订单信息不存在';
}
$result['pay_way_desc'] = PayEnum::getPayTypeDesc($result['pay_way']);
$result['pay_time'] = empty($result['pay_time']) ? '-' : date('Y-m-d H:i:s', $result['pay_time']);
return $result;
}
/**
* @notes 获取支付方式
* @param int $scene
* @param int $userId
* @return array
* @author cjhao
* @date 2024/10/11 22:49
*/
public static function getPayWayList(int $scene,int $userId){
$pay_way = PayWay::alias('pw')
->join('dev_pay dp', 'pw.pay_id = dp.id')
->where(['pw.scene'=>$scene,'pw.status'=>YesNoEnum::YES])
->field('dp.id,dp.name,dp.pay_way,dp.image,pw.is_default')
->order(['sort'=>'asc','id'=>'desc'])
->select()
->toArray();
foreach ($pay_way as $k=>&$item) {
if ($item['pay_way'] == PayEnum::WECHAT_PAY) {
$item['extra'] = '微信快捷支付';
}
// if ($item['pay_way'] == PayEnum::BALANCE_PAY) {
// $user_money = User::where(['id' => $userId])->value('user_money');
// $item['extra'] = '可用余额:'.$user_money;
// }
}
return $pay_way;
}
}

View File

@@ -0,0 +1,207 @@
<?php
namespace app\coachapi\logic;
use app\common\enum\notice\NoticeEnum;
use app\common\enum\shop\ShopEnum;
use app\common\logic\BaseLogic;
use app\common\model\coach\Coach;
use app\common\model\shop\Shop;
use app\common\model\shop\ShopCategoryIndex;
use app\common\model\shop\ShopCoachApply;
use app\common\service\sms\SmsDriver;
use Exception;
use think\facade\Config;
use think\facade\Db;
class ShopLogic extends BaseLogic
{
/**
* @notes 服务详情
* @param int $id
* @return array
* @author cjhao
* @date 2024/10/12 00:27
*/
public function detail(array $params){
$detail = Shop::where(['id'=>$params['id'],'audit_status'=>ShopEnum::AUDIT_STATUS_PASS,'server_status'=>ShopEnum::SERVERSTATUSOPEN])
->append(['shop_image','category_ids','business_time_desc','province_name','city_name','region_name'])
->field('*,round(st_distance_sphere(point('.$params['longitude'].','.$params['latitude'].'),
point(longitude, latitude))/1000,2) as distance')
->findOrEmpty()
->toArray();
$detail['distance'] = $detail['distance'].'km';
$categoryLists = ShopCategoryIndex::alias('SC')
->where(['shop_id'=>$params['id'],'is_show'=>1])
->join('goods_category GC','SC.category_id = GC.id')
->column('GC.name');
$detail['category_name'] = implode('|',$categoryLists);
return $detail;
}
/**
* @notes 门店申请列表
* @param array $params
* @return bool
* @author cjhao
* @date 2024/10/14 12:41
*/
public function applyJoin(array $params)
{
try{
$id = $params['id'] ?? '';
if(empty($id)){
throw new Exception('请选择门店');
}
if(empty($params['coach_id'])){
throw new Exception('请先申请成为技师');
}
// Db::startTrans();
$coach = Coach::where(['id'=>$params['coach_id']])->findOrEmpty();
if($coach->shop_id){
throw new Exception('您已加入了门店,请勿再申请');
}
$shopCoachApply = ShopCoachApply::where(['coach_id'=>$params['coach_id'],'audit_status'=>ShopEnum::AUDIT_STATUS_WAIT])
->findOrEmpty();
if(!$shopCoachApply->isEmpty()){
throw new Exception('您的门店申请正在审核中,请勿再申请');
}
$shop = Shop::where(['id'=>$params['id']])->findOrEmpty();
if($coach['city_id'] != $shop['city_id']){
throw new Exception('抱歉,只能添加本地的商家哦');
}
$shopCoachApply = new ShopCoachApply();
$shopCoachApply->coach_id = $params['coach_id'];
$shopCoachApply->shop_id = $params['id'];
$shopCoachApply->type = 1;
$shopCoachApply->audit_status = ShopEnum::AUDIT_STATUS_WAIT;
$shopCoachApply->save();
//提交事务
// Db::commit();
return true;
}catch (Exception $e) {
// Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 申请详情
* @param $params
* @return array
* @author cjhao
* @date 2024/10/20 03:43
*/
public function applyDetail($params)
{
$coachShopId = Coach::where(['id'=>$params['coach_id']])->value('shop_id');
$shop = Shop::where(['id'=>$params['id']])
->append(['shop_image','category_ids','region_desc','business_time_desc'])
->withoutField('update_time,delete_time')
->findOrEmpty()->toArray();
$shop['type'] = '';
$shop['audit_remark'] = '';
$shop['audit_status'] = '';
//分为已经加入商家
if($coachShopId){
$shopApply = ShopCoachApply::where(['coach_id'=>$params['coach_id'],'shop_id'=>$coachShopId])
->order('id desc')
->field('shop_id,type,audit_status,audit_remark')
->findOrEmpty()
->toArray();
$shop['audit_status'] = $shopApply['audit_status'];
$shop['audit_remark'] = $shopApply['audit_remark'];
$shop['type'] = $shopApply['type'];
}else{
//没有加入商家
$shopApply = ShopCoachApply::where(['coach_id'=>$params['coach_id'],'shop_id'=>$params['id']])
->order('id desc')
->field('id,shop_id,type,audit_status,audit_remark')
->findOrEmpty()
->toArray();
$shop['type'] = 1;
$shop['audit_status'] = '';
$shop['audit_remark'] = '';
if($shopApply && 1 == $shopApply['type'] && (ShopEnum::AUDIT_STATUS_REFUSE == $shopApply['audit_status'] || ShopEnum::AUDIT_STATUS_WAIT == $shopApply['audit_status'])){
$shop['audit_status'] = $shopApply['audit_status'];
$shop['audit_remark'] = $shopApply['audit_remark'];
}
}
return $shop;
}
/**
* @notes 取消
* @param array $params
* @return bool|string
* @author cjhao
* @date 2024/10/20 23:09
*/
public function cancel($params){
$id = $params['id'] ?? '';
if(empty($id)){
return '请选择商家';
}
$shopCoachApply = ShopCoachApply::where(['coach_id'=>$params['coach_id'],'shop_id'=>$params['id']])
->order('id desc')
->findOrEmpty();
if($shopCoachApply->isEmpty()){
return '你未申请该商家';
}
if(ShopEnum::AUDIT_STATUS_WAIT != $shopCoachApply->audit_status){
return '商家审核状态已改变';
}
$shopCoachApply->audit_status = ShopEnum::AUDIT_STATUS_CANCEL;
$shopCoachApply->save();
return true;
}
/**
* @notes 申请退出
* @param int $coachId
* @return bool
* @author cjhao
* @date 2024/11/17 12:57
*/
public function applyQuit(int $coachId){
try{
// Db::startTrans();
$coach = Coach::where(['id'=>$coachId])->findOrEmpty();
if(0 == $coach->shop_id){
throw new Exception('您未申请门店');
}
$shopCoachApply = ShopCoachApply::where(['coach_id'=>$coachId,'audit_status'=>ShopEnum::AUDIT_STATUS_WAIT,'type'=>2])
->findOrEmpty();
if(!$shopCoachApply->isEmpty()){
throw new Exception('您的退出请求正在审核中,请勿再申请');
}
$shopCoachApply = new ShopCoachApply();
$shopCoachApply->coach_id = $coachId;
$shopCoachApply->shop_id = $coach->shop_id;
$shopCoachApply->type = 2;
$shopCoachApply->audit_status = ShopEnum::AUDIT_STATUS_WAIT;
$shopCoachApply->save();
//提交事务
// Db::commit();
return true;
}catch (Exception $e) {
// Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,60 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\coachapi\logic;
use app\common\enum\notice\NoticeEnum;
use app\common\logic\BaseLogic;
/**
* 短信逻辑
* Class SmsLogic
* @package app\coachapi\logic
*/
class SmsLogic extends BaseLogic
{
/**
* @notes 发送验证码
* @param $params
* @return false|mixed
* @author 段誉
* @date 2022/9/15 16:17
*/
public static function sendCode($params)
{
try {
$scene = NoticeEnum::getSceneByCoachTag($params['scene']);
if (empty($scene)) {
throw new \Exception('场景值异常');
}
$result = event('Notice', [
'scene_id' => $scene,
'params' => [
'mobile' => $params['mobile'],
'code' => mt_rand(1000, 9999),
]
]);
return $result[0];
} catch (\Exception $e) {
self::$error = $e->getMessage();
return false;
}
}
}

View File

@@ -0,0 +1,78 @@
<?php
// +----------------------------------------------------------------------
// | LikeShop有特色的全开源社交分销电商系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 商业用途务必购买系统授权,以免引起不必要的法律纠纷
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | 微信公众号:好象科技
// | 访问官网http://www.likemarket.net
// | 访问社区http://bbs.likemarket.net
// | 访问手册http://doc.likemarket.net
// | 好象科技开发团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | Author: LikeShopTeam
// +----------------------------------------------------------------------
namespace app\coachapi\logic;
use app\common\logic\BaseLogic;
use app\common\service\WeChatConfigService;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Exceptions\Exception;
/**
* 微信逻辑层
* Class WechatLogic
* @package app\api\logic
*/
class WechatLogic extends BaseLogic
{
/**
* @notes 微信JSSDK授权接口
* @param $params
* @return array|false|string
* @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
* @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
* @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws \Psr\SimpleCache\InvalidArgumentException
* @author Tab
* @date 2021/8/30 19:20
*/
public static function jsConfig($params)
{
try {
// $config = [
// 'app_id' => ConfigService::get('official_account','app_id'),
// 'secret' => ConfigService::get('official_account','app_secret')
// ];
$config = WeChatConfigService::getOaConfig();
$app = Factory::officialAccount($config);
$url = urldecode($params['url']);
$app->jssdk->setUrl($url);
$apis = [
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone',
'openLocation',
'getLocation',
'chooseWXPay',
'updateAppMessageShareData',
'updateTimelineShareData',
'openAddress',
'scanQRCode'
];
$data = $app->jssdk->getConfigArray($apis, $debug = false, $beta = false);
return $data;
} catch (Exception |\think\Exception $e) {
self::setError('公众号配置出错:' . $e->getMessage());
return false;
}
}
}

View File

@@ -0,0 +1,425 @@
<?php
namespace app\coachapi\logic;
use app\common\enum\accountLog\CoachAccountLogEnum;
use app\common\logic\BaseLogic;
use app\common\logic\CoachAccountLogLogic;
use app\common\model\coach\Coach;
use app\common\model\withdraw\WithdrawApply;
use app\common\model\withdraw\WithdrawConfig;
use app\common\service\ConfigService;
use DateTime;
use think\Exception;
use think\facade\Db;
/**
* 提现逻辑类
* Class WithdrawLogic
* @package app\coachapi\logic
*/
class WithdrawLogic extends BaseLogic
{
public function configLists(int $coachId)
{
$lists = WithdrawConfig::where(['relation_id'=>$coachId,'source'=>1])
->column('type,config','type');
$configDefault = [
[
'type' => 1,
],
[
'type' => 2,
],
[
'type' => 3,
],
];
foreach ($configDefault as $default){
$config = $lists[$default['type']] ?? [];
if(empty($config)){
$lists[$default['type']] = [
'type' => $default['type'],
'config' => [],
];
}
}
if(empty($lists)){
$lists = [];
}
$wayLists = ConfigService::get('withdraw', 'way_list');
foreach ($lists as $key => $config)
{
if(!in_array($config['type'],$wayLists)){
unset($lists[$key]);
}
}
return array_values($lists);
}
/**
* @notes 获取提现方式配置
* @param $coachId
* @param $type
* @return WithdrawConfig|array|\think\Model
* @author cjhao
* @date 2024/9/26 00:22
*/
public function getWithDrawWay($coachId,$type)
{
$detail = WithdrawConfig::where(['relation_id'=>$coachId,'type'=>$type,'source'=>1])
->findOrEmpty()->toArray();
if(empty($detail)){
$detail = [
'type' => $type,
'config' => [],
];
}
switch ($type){
case 1:
$detail['config']['name'] = $detail['config']['name'] ?? '';
$detail['config']['mobile'] = $detail['config']['mobile'] ?? '';
break;
case 2:
$detail['config']['name'] = $detail['config']['name'] ?? '';
$detail['config']['account'] = $detail['config']['account'] ?? '';
break;
case 3:
$detail['config']['name'] = $detail['config']['name'] ?? '';
$detail['config']['bank'] = $detail['config']['bank'] ?? '';
$detail['config']['bank_card'] = $detail['config']['bank_card'] ?? '';
break;
}
return $detail;
}
/**
* @notes 设置提现方式
* @param $coachId
* @param $post
* @return string|true
* @author cjhao
* @date 2024/9/26 11:36
*/
public function setWithDrawWay($coachId,$post)
{
$type = $post['type'] ?? '';
if(empty($type)){
return '提现配置错误';
}
switch ($type){
case 1:
$name = $post['config']['name'] ?? '';
$mobile = $post['config']['mobile'] ?? '';
if(empty($name)){
return '请输入名称';
}
if(empty($mobile)){
return '请输入手机号码';
}
break;
case 2:
$name = $post['config']['name'] ?? '';
$account = $post['config']['account'] ?? '';
if(empty($name)){
return '请输入名称';
}
if(empty($account)){
return '请输入账号';
}
break;
case 3:
$name = $post['config']['name'] ?? '';
$bank = $post['config']['bank'] ?? '';
$bankCard = $post['config']['bank_card'] ?? '';
if(empty($name)){
return '请输入名称';
}
if(empty($bank)){
return '请输入开户名';
}
if(empty($bankCard)){
return '请输入银行卡号';
}
break;
}
$post['coach_id'] = $coachId;
$config = WithdrawConfig::where(['type'=>$type,'relation_id'=>$coachId,'source'=>1])->findOrEmpty();
if($config->isEmpty()){
WithdrawConfig::create([
'relation_id' => $coachId,
'source' => 1,
'type' => $type,
'config' => $post['config'],
]);
}else{
$config->config = $post['config'];
$config->save();
}
return true;
}
/**
* @notes 提现申请
* @param $params
* @return bool
* @author cjhao
* @date 2024/9/26 15:15
*/
public function withdrawalApply($params)
{
try {
Db::startTrans();
$cycleType = ConfigService::get('withdraw', 'withdraw_cycle_type');
$cycleDate = ConfigService::get('withdraw', 'withdraw_cycle_date');
$date = new DateTime();
if(1 == $cycleType){
$dayOfWeek =$date->format('N'); // 1表示星期一到 7表示星期日
if($cycleDate != $dayOfWeek){
throw new Exception('提现仅在每周'.getWeekdayByNumber($cycleDate).'可提现');
}
}else{
$dayOfMonth =$date->format('j'); // 1 到 31
if($cycleDate != $dayOfMonth){
throw new Exception('提现仅在每月'.$cycleDate.'号可提现');
}
}
$coach = Coach::where(['id'=>$params['coach_id']])->findOrEmpty();
if($coach->money < $params['money']){
throw new Exception('当前可提现金额仅剩:'.$coach->money.'元');
}
$minMoney = ConfigService::get('withdraw', 'min_money');
$maxMoney = ConfigService::get('withdraw', 'max_money');
$serviceCharge = ConfigService::get('withdraw', 'service_charge');
if($maxMoney < $params['money']){
throw new Exception('最高可提现'.$maxMoney.'元');
}
if($minMoney > $params['money']){
throw new Exception('最低提现'.$minMoney.'元');
}
$applyType = $params['apply_type'];
$config = WithdrawConfig::where(['type'=>$applyType,'coach_id'=>$params['coach_id']])->findOrEmpty();
if($config->isEmpty()){
throw new Exception('请配置提现账户');
}
$coach->money = round($coach->money - $params['money']);
$coach->save();
$handlingFee = round( ($params['money'] * $serviceCharge/100),2);
(new WithdrawApply())->save([
'sn' => generate_sn((new WithdrawApply()), 'sn'),
'coach_id' => $params['coach_id'],
'type' => $params['apply_type'],
'money' => $params['money'],
'left_money' => $coach->money,
'handling_fee' => $handlingFee,
'service_charge' => $serviceCharge,
'withdraw_config_snap' => $config
]);
//提交事务
Db::commit();
return true;
}catch (Exception $e) {
Db::rollback();
return $e->getMessage();
}
}
/**
* @notes 提现信息
* @param int $coachId
* @return array
* @author cjhao
* @date 2024/10/29 17:54
*/
public function getWithdrawInfo(int $coachId){
$lists = WithdrawConfig::where(['relation_id'=>$coachId,'source'=>1])
->column('type,config','type');
$configDefault = [
[
'type' => 1,
],
[
'type' => 2,
],
[
'type' => 3,
],
];
foreach ($configDefault as $default){
$config = $lists[$default['type']] ?? [];
if(empty($config)){
$lists[$default['type']] = [
'type' => $default['type'],
'config' => [],
];
}
}
if(empty($lists)){
$lists = [];
}
$wayLists = ConfigService::get('withdraw', 'way_list');
foreach ($lists as $key => $config)
{
if(!in_array($config['type'],$wayLists)){
unset($lists[$key]);
}
}
$coach = Coach::where(['id'=>$coachId])->field('money,deposit')->findOrEmpty();
$config = [
'way_list' => array_values($lists),
'min_money' => ConfigService::get('withdraw', 'min_money'),
'max_money' => ConfigService::get('withdraw', 'max_money'),
'service_charge' => ConfigService::get('withdraw', 'service_charge'),
'money' => $coach['money'],
'deposit' => $coach['deposit'],
'withdraw_cycle_type' => ConfigService::get('withdraw', 'withdraw_cycle_type'),
'withdraw_cycle_date' => ConfigService::get('withdraw', 'withdraw_cycle_date'),
];
$tips = '';
if($config['withdraw_cycle_type']){
// $dayOfWeek = date('w'); // 注意:'w'返回的是数字其中0表示周日6表示周六
// $dayOfWeek = $dayOfWeek === 0 ? 7 : $dayOfWeek;
$weekDay = getWeekdayByNumber($config['withdraw_cycle_date']);
$tips = "平台设置每".$weekDay."可提现";
}else{
// 获取今天的日期(几号)
// $dayOfMonth = date('j'); // 'j'返回不带前导零的日期
$tips = "平台设置每月".$config['withdraw_cycle_date']."号可提现";
}
$config['tips'] = $tips;
return $config;
}
/**
* @notes 提现接口
* @param $params
* @return string|true
* @throws \Exception
* @author cjhao
* @date 2024/10/30 15:05
*/
public function apply($params)
{
try {
Db::startTrans();
$money = $params['money'] ?? 0;
$type = $params['type'] ?? '';
$applyType = $params['apply_type'] ?? 1;
if(empty($type)){
throw new Exception('请选择提现账号');
}
$config = [
'min_money' => ConfigService::get('withdraw', 'min_money'),
'max_money' => ConfigService::get('withdraw', 'max_money'),
'service_charge' => ConfigService::get('withdraw', 'service_charge'),
'withdraw_cycle_type' => ConfigService::get('withdraw', 'withdraw_cycle_type'),
'withdraw_cycle_date' => ConfigService::get('withdraw', 'withdraw_cycle_date'),
];
$withdrawConfig = WithdrawConfig::where(['relation_id'=>$params['coach_id'],'source'=>1,'type'=>$type])
->value('config');
if(empty($withdrawConfig)){
throw new Exception('请先配置提现账号信息');
}
if($config['withdraw_cycle_type']){
$dayOfWeek = date('w'); // 注意:'w'返回的是数字其中0表示周日6表示周六
if($config['withdraw_cycle_date'] != $dayOfWeek){
// $dayOfWeek = $dayOfWeek === 0 ? 7 : $dayOfWeek;
$weekDay = getWeekdayByNumber($config['withdraw_cycle_date']);
throw new Exception('请在每'.$weekDay.'来申请提现');
}
}else{
// 获取今天的日期(几号)
$dayOfMonth = date('j'); // 'j'返回不带前导零的日期
if($config['withdraw_cycle_date'] != $dayOfMonth){
throw new Exception('请在每月'.$config['withdraw_cycle_date'].'号来申请提现');
}
}
$coach = Coach::where(['id'=> $params['coach_id']])->findOrEmpty();
$coachMoney = $coach->money;
if(2 == $applyType){
$coachMoney = $coach->deposit;
}
if($coachMoney < $money){
throw new Exception('当前可提现余额仅剩'.$coachMoney);
}
if($money < $config['min_money']){
throw new Exception('最小提现额度不能小于'.$config['min_money']);
}
if($money > $config['max_money']){
throw new Exception('最大提现额度不能大于'.$config['max_money']);
}
$serviceFree = 0;
if(1 == $applyType){
//手续费
$serviceFree = round($money*($config['service_charge']/100),2);
}
//提现操作
$withdrawApply = WithdrawApply::create([
'sn' => generate_sn((new WithdrawApply()), 'sn'),
'relation_id' => $params['coach_id'],
'source' => 1,
'type' => $type,
'apply_type' => $applyType,
'money' => $money,
'left_money' => round($money - $serviceFree,2),
'handling_fee' => $serviceFree,
'service_charge' => $config['service_charge'],
'withdraw_config_snap' => $withdrawConfig,
]);
if(1 == $applyType){
$coach->money = round($coach->money - $money,2);
$coach->save();
CoachAccountLogLogic::add(
$coach->id,
CoachAccountLogEnum::MONEY,
CoachAccountLogEnum::WITHDRAW_DEC_MONEY,
2,
$money,
$withdrawApply['sn'],
);
}else{
$coach->deposit = round($coach->deposit - $money,2);
$coach->save();
CoachAccountLogLogic::add(
$coach->id,
CoachAccountLogEnum::DEPOSIT,
CoachAccountLogEnum::WITHDRAW_DEC_DEPOSIT,
2,
$money,
$withdrawApply['sn'],
);
}
Db::commit();
return true;
}catch (Exception $e){
Db::rollback();
self::$error = $e->getMessage();
return false;
}
}
/**
* @notes 详情
* @param $id
* @return WithdrawApply|array|\think\Model
* @author cjhao
* @date 2024/10/31 09:08
*/
public function detail($id,$coachId)
{
$detail = WithdrawApply::where(['id'=>$id,'relation_id'=>$coachId,'source'=>1])
->append(['status_desc','type_desc'])
->withoutField('delete_time')
->findOrEmpty()->toArray();
return $detail;
}
}