李帅

1.会员模板页面完成。

2.订单还在构思。
Showing 38 changed files with 1244 additions and 88 deletions
......@@ -2,14 +2,18 @@
namespace App\Admin\Controllers;
use App\Admin\Renderable\MembershipGoodsTable;
use App\Admin\Repositories\Membership;
use App\Models\MembershipGood;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Show;
use Dcat\Admin\Http\Controllers\AdminController;
use Dcat\Admin\Form\NestedForm;
class MembershipController extends AdminController
{
protected $title = '会员';
/**
* Make a grid builder.
*
......@@ -18,14 +22,28 @@ class MembershipController extends AdminController
protected function grid()
{
return Grid::make(new Membership(), function (Grid $grid) {
$grid->column('id')->sortable();
// 设置自定义视图
$grid->setActionClass(Grid\Displayers\Actions::class);
$grid->column('id',__('ID'))->sortable();
$grid->column('name');
$grid->column('price');
$grid->column('origin_price');
$grid->column('line_price');
$grid->column('limited_days');
$grid->column('limit_unit');
$grid->column('intro');
$grid->column('state');
$grid->column('sn');
$grid->column('video_url');
$grid->column('video_cover');
$grid->column('bg_images');
$grid->column('visits');
$grid->column('virtual_sales');
$grid->column('sales');
$grid->column('created_at');
$grid->column('updated_at')->sortable();
......@@ -49,13 +67,23 @@ class MembershipController extends AdminController
$show->field('id');
$show->field('name');
$show->field('price');
$show->field('origin_price');
$show->field('line_price');
$show->field('limited_days');
$show->field('limit_unit');
$show->field('intro');
$show->field('state');
$show->field('sn');
$show->field('is_video');
$show->field('video_url');
$show->field('video_cover');
$show->field('bg_images');
$show->field('visits');
$show->field('virtual_sales');
$show->field('sales');
$show->field('created_at');
$show->field('updated_at');
});
}
......@@ -68,14 +96,67 @@ class MembershipController extends AdminController
{
return Form::make(new Membership(), function (Form $form) {
$form->display('id');
$form->text('name');
$form->text('price');
$form->text('origin_price');
$form->text('limited_days');
$form->text('intro');
$form->text('state');
$form->text('sn');
$form->block(12, function (Form\BlockForm $form) {
// 设置标题
$form->title('基本设置');
// 显示底部提交按钮
$form->showFooter();
// 设置字段宽度
$form->width(8, 2);
$form->radio('terminal')->addElementClass('terminal')
->options([1 => 'Android', 2 => 'IOS'])->default(2);
$form->text('title')->addElementClass('name');
$form->textarea('intro')->addElementClass('intro');
$form->radio('bg_type')->addElementClass('bg_type')
->options([1 => '单图', 2 => '轮播图', 3 => '视频'])->default(1)
->when([1,2],function (Form\BlockForm $form){
$form->multipleImage('bg_images')
->limit(5)
->uniqueName()
->addElementClass('bg_images');
})
->when(3,function (Form\BlockForm $form){
$form->file('video_url')
->accept('mp4')
->autoUpload()
->uniqueName()
->addElementClass('video_url');
$form->image('video_cover')
->uniqueName()
->addElementClass('video_cover');
});
$form->radio('state')->options(['不显示', '显示'])->default(0);
$form->radio('is_bind_old')->options(['新增会员商品', '选择已有商品'])->default(0)
->when(0,function (Form\BlockForm $form){
$form->table('membership_goods','新赠会员商品', function (NestedForm $table) {
$table->currency('price')->symbol('¥')->addElementClass('price');
$table->currency('line_price')->symbol('¥')->addElementClass('line_price');
$table->text('limited_days')->addElementClass('limited_days');
$table->text('limit_unit')->addElementClass('limit_unit');
});
})
->when(1,function (Form\BlockForm $form){
$form->selectTable('membership_goods')
->title('会员商品')
->from(MembershipGoodsTable::make())
->model(MembershipGood::class, 'id', 'price');
});
});
// $form->block(4, function (Form\BlockForm $form) {
// $form->width(9, 1);
// $form->html(view('admin.form.phone'));
// });
$form->display('created_at');
$form->display('updated_at');
});
......
<?php
namespace App\Admin\Controllers;
use App\Admin\Repositories\MembershipGood;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Show;
use Dcat\Admin\Http\Controllers\AdminController;
class MembershipGoodController extends AdminController
{
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Grid::make(new MembershipGood(), function (Grid $grid) {
$grid->column('id')->sortable();
$grid->column('price');
$grid->column('line_price');
$grid->column('limit_days');
$grid->column('limit_unit');
$grid->column('sale_terminal');
$grid->column('state');
$grid->column('sn');
$grid->column('visits');
$grid->column('virtual_sales');
$grid->column('sales');
$grid->column('stocks');
$grid->column('created_at');
$grid->column('updated_at')->sortable();
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('id');
});
});
}
/**
* Make a show builder.
*
* @param mixed $id
*
* @return Show
*/
protected function detail($id)
{
return Show::make($id, new MembershipGood(), function (Show $show) {
$show->field('id');
$show->field('price');
$show->field('line_price');
$show->field('limit_days');
$show->field('limit_unit');
$show->field('sale_terminal');
$show->field('state');
$show->field('sn');
$show->field('visits');
$show->field('virtual_sales');
$show->field('sales');
$show->field('stocks');
$show->field('created_at');
$show->field('updated_at');
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Form::make(new MembershipGood(), function (Form $form) {
$form->display('id');
$form->text('price');
$form->text('line_price');
$form->text('limit_days');
$form->text('limit_unit');
$form->text('sale_terminal');
$form->text('state');
$form->text('sn');
$form->text('visits');
$form->text('virtual_sales');
$form->text('sales');
$form->text('stocks');
$form->display('created_at');
$form->display('updated_at');
});
}
}
<?php
namespace App\Admin\Controllers;
use App\Admin\Repositories\OrderGood;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Show;
use Dcat\Admin\Http\Controllers\AdminController;
class OrderGoodController extends AdminController
{
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Grid::make(new OrderGood(), function (Grid $grid) {
$grid->column('id')->sortable();
$grid->column('order_sn');
$grid->column('goods_id');
$grid->column('goods_name');
$grid->column('goods_image');
$grid->column('goods_price');
$grid->column('goods_number');
$grid->column('after_sales');
$grid->column('created_at');
$grid->column('updated_at')->sortable();
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('id');
});
});
}
/**
* Make a show builder.
*
* @param mixed $id
*
* @return Show
*/
protected function detail($id)
{
return Show::make($id, new OrderGood(), function (Show $show) {
$show->field('id');
$show->field('order_sn');
$show->field('goods_id');
$show->field('goods_name');
$show->field('goods_image');
$show->field('goods_price');
$show->field('goods_number');
$show->field('after_sales');
$show->field('created_at');
$show->field('updated_at');
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Form::make(new OrderGood(), function (Form $form) {
$form->display('id');
$form->text('order_sn');
$form->text('goods_id');
$form->text('goods_name');
$form->text('goods_image');
$form->text('goods_price');
$form->text('goods_number');
$form->text('after_sales');
$form->display('created_at');
$form->display('updated_at');
});
}
}
......@@ -10,6 +10,8 @@ use Dcat\Admin\Http\Controllers\AdminController;
class PickPoetryVerseController extends AdminController
{
protected $title = '推送服务';
/**
* Make a grid builder.
*
......@@ -71,14 +73,16 @@ class PickPoetryVerseController extends AdminController
$form->radio('plant')->addElementClass('plant')
->options([1 => 'Android', 2 => 'IOS'])->default(2);
$form->text('title');
$form->textarea('content');
$form->text('title')->addElementClass('title');
$form->textarea('content')->addElementClass('push_content');
$form->radio('push_type', '发送时间')->options([1 => '立即', 2 => '定时'])->default(1)
$form->radio('push_type', '发送时间')->addElementClass('push_type')
->options([1 => '立即', 2 => '定时'])->default(1)
->when(2, function (Form\BlockForm $form) {
$form->datetime('push_time');
});
$form->select('action_type')->options(['打开应用', '临境', '会员介绍页', '众妙页']);
$form->select('action_type')->addElementClass('action_type')
->options(['打开应用', '临境', '会员介绍页', '众妙页']);
$form->radio('user_type', '目标人群')->options([1 => '所有人', 2 => '指定用户'])->default(1)
->when(2, function (Form\BlockForm $form) {
......@@ -87,6 +91,7 @@ class PickPoetryVerseController extends AdminController
});
$form->block(4, function (Form\BlockForm $form) {
$form->width(9, 1);
$form->html(view('admin.form.push'));
});
......
<?php
/**
* Created by PhpStorm.
* User: lishuai
* Date: 2022/1/10
* Time: 5:57 PM
*/
namespace App\Admin\Renderable;
use App\Models\MembershipGood;
use Dcat\Admin\Grid;
use Dcat\Admin\Grid\LazyRenderable;
class MembershipGoodsTable extends LazyRenderable
{
public function grid(): Grid
{
return Grid::make(new MembershipGood(), function (Grid $grid) {
$grid->column('id', 'ID')->sortable();
$grid->column('membership_id');
$grid->column('price');
$grid->column('line_price');
$grid->column('limit_days');
$grid->column('limit_unit');
$grid->column('terminal');
$grid->quickSearch(['price', 'line_price', 'terminal']);
$grid->paginate(10);
$grid->disableActions();
$grid->filter(function (Grid\Filter $filter) {
$filter->like('price')->width(4);
$filter->like('terminal')->width(4);
});
});
}
}
\ No newline at end of file
......@@ -30,6 +30,10 @@ Route::group([
/** 订单*/
$router->resource('/order', 'OrderController');
/** 会员*/
$router->resource('/membership', 'MembershipController');
$router->group(['prefix'=>'/tool'],function (Router $router){
/** 每日一言*/
$router->resource('/every-poem', 'EverydayPoemController');
......
<?php
namespace App\Console\Commands;
use App\Models\OnePoem;
use App\Models\PackPoem;
use App\Models\VideoTemp;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
class InitTemplateData extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'init:temp';
/**
* The console command description.
*
* @var string
*/
protected $description = '初始化模板数据';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// 一言表
OnePoem::query()->truncate();
$one_poem = new OnePoem();
$one_poem->id = 1;
$one_poem->title = '诉衷情2';
$one_poem->author = '欧阳修';
$one_poem->content = '清晨帘幕卷轻霜。';
$one_poem->annotate = '诉衷情 --清晨帘幕卷轻霜。';
$one_poem->spelling = 'qing chen lian mu juan qing shuang';
$one_poem->en = 'morning ...';
$one_poem->state = 0;
$one_poem->created_at = Carbon::now();
$one_poem->updated_at = Carbon::now();
$one_poem->save();
// 众妙表
PackPoem::query()->truncate();
$pack_poem = new PackPoem();
$pack_poem->id = 1;
$pack_poem->title = '辛丑年 庚子月 已酉时 巳时';
$pack_poem->subtitle = '2022年01月12日13点22分';
$pack_poem->left_text = '欧阳修';
$pack_poem->right_text = '冬';
$pack_poem->poem_id = 1;
$pack_poem->state = 0;
$pack_poem->created_at = Carbon::now();
$pack_poem->updated_at = Carbon::now();
$pack_poem->save();
// 模板表
VideoTemp::query()->truncate();
$video_temp = new VideoTemp();
$video_temp->title = 'test';
$video_temp->type = 1;
$video_temp->bg_type = 2;
$video_temp->bg_url = 'files/ce1f0f0a995f93ff2e6d68451ab0873e.png';
$video_temp->bg_music = 0;
$video_temp->text_color = '#FAF1F3';
$video_temp->text_bg_color = '#21415E';
$video_temp->opacity = 100;
$video_temp->sn = 1;
$video_temp->top = 120;
$video_temp->left = 70;
$video_temp->font_size = 4;
$video_temp->state = 0;
$video_temp->save();
// 菜单初始化
\Dcat\Admin\Models\Menu::query()->truncate();
$admin_menu = json_decode(Storage::disk('public')->get('PoemData/admin_menu.json'), true);
$data = $admin_menu['RECORDS'];
foreach ($data as $item){
$item['created_at'] = Carbon::now();
$item['updated_at'] = Carbon::now();
\Dcat\Admin\Models\Menu::query()->create($item);
}
return 0;
}
}
<?php
namespace App\Http\Controllers\V1;
use App\Http\Controllers\Controller;
use App\Models\OneUser;
use App\Models\User;
use App\Models\UserProfile;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Jiannei\Response\Laravel\Support\Facades\Response;
use Laravel\Socialite\Facades\Socialite;
class AuthController extends Controller
{
/**
* web用户先访问这里进行重定向
* @param Request $request
* @param $service
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\RedirectResponse
*/
public function redirectToProvider(Request $request, $service)
{
return Socialite::driver($service)->redirect();
}
/**
* web用户客户端授权后直接到这里
* @param Request $request
* @param $service
*/
public function handleProviderCallback(Request $request, $service)
{
$socialUser = Socialite::driver($service)->stateless()->user();
dd($socialUser);
// //据说apple有问题需要用这种办法
// if ($service === 'apple'){
// // apple 登录
// try {
// if ($code = $request->code) {
// $response = http('https://appleid.apple.com/auth/token', [
// 'grant_type' => 'authorization_code',
// 'code' => $code,
// 'redirect_uri' => config('services.apple.redirect') ,
// 'client_id' => config('services.apple.client_id') ,
// 'client_secret' => config('services.apple.client_secret') ,
// ]);
// $id_token = $response->id_token;
// } else {
// $id_token = $request->access_token;
// }
// $oauthUser = json_decode(base64_decode(explode('.', $id_token) [1]));
// }
// catch(\Exception $e) {
// return $this->failed('apple 参数错误');
// }
// }
// function http($url, $params = false)
// {
// $ch = curl_init($url);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// if ($params) {
// curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
// } curl_setopt($ch, CURLOPT_HTTPHEADER, [
// 'Accept: application/json',
// 'User-Agent: curl', # Apple requires a user agent header at the token endpoint
// ]);
// $response = curl_exec($ch);
// return json_decode($response);
// }
}
/**
* 移动端微信用户
* @param Request $request
* @param $service
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Resources\Json\JsonResource
*/
public function apiHandleProviderCallback(Request $request, $service)
{
$code = $request->get('code');
if (!$code) return Response::fail('code miss');
$driver = Socialite::driver($service);
$response = $driver->getAccessTokenResponse($code);
if (isset($response['errcode'])) return Response::fail($response['errmsg']);
$driver->setOpenId($response['openid']);
$oauthUser = $driver->getUserByToken($response['access_token']);
// //另一种写法
// $user = User::query()->firstOrCreate([
// 'provider_id' => $oauthUser->id,
// 'provider' => $service,
// ],[
// 'nickname' => $oauthUser->nickname,
// 'avatar' => $oauthUser->avatar,
// 'provider' => $service,
// 'provider_id' => $oauthUser->id,
// ]);
//
// UserProfile::query()->firstOrCreate([
// 'user_id' => $user->id,
// 'unionid' => $oauthUser->unionid,
// ]);
$user = User::query()->where( 'provider_id', '=', $oauthUser->id )
->where( 'provider', '=', $service )
->first();
if ($user == null){
// 如果该用户不存在则将其保存到 users 表
$newUser = new User();
$newUser->nickname = $oauthUser->nickname;
$newUser->avatar = $oauthUser->avatar;
$newUser->provider = $service;
$newUser->provider_id = $oauthUser->id;
$newUser->save();
$user = $newUser;
// user_profile 保存
$userProfile = new UserProfile();
$userProfile->user_id = $user->id;
$userProfile->unionid = $oauthUser->unionid;
$userProfile->save();
}
Auth::guard('api')->login($user);
return Response::success([
'user_id' => $user->id,
'nickname' => $user->nickname,
'mobile' => $user->mobile,
'gender' => $user->gender,
'avatar' => $user->avatar,
'token' => $user->createToken($user->id)->plainTextToken
]);
}
}
<?php
namespace App\Http\Controllers\V1;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Jiannei\Response\Laravel\Support\Facades\Response;
class OrderController extends Controller
{
public function index(Request $request)
{
$validator = Validator::make($request->all(),[
'goods_id' => 'required|integer',
'source' => 'required|string',
]);
if ($validator->fails()){
return Response::fail('缺少参数',500,$validator->errors());
}
}
public function store(Request $request)
{
$validator = Validator::make($request->all(),[
'goods_id' => 'required|integer',
'source' => 'required|string',
]);
if ($validator->fails()){
return Response::fail('',500,$validator->errors());
}
}
}
......@@ -3,6 +3,7 @@
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Jiannei\Response\Laravel\Support\Facades\Response;
class Authenticate extends Middleware
{
......@@ -17,5 +18,7 @@ class Authenticate extends Middleware
if (! $request->expectsJson()) {
return route('login');
}
Response::errorUnauthorized(); // 授权失败 401
}
}
......
......@@ -13,5 +13,6 @@ class EncryptCookies extends Middleware
*/
protected $except = [
//
'api/*'
];
}
......
<?php
namespace App\Http\Middleware;
use App\Models\OperationLog;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Jiannei\Response\Laravel\Support\Facades\Response;
class LogOperation
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if ($this->shouldLogOperation($request)) {
$user = Auth::user();
$log = [
'user_id' => $user ? $user->getAuthIdentifier() : 0,
'path' => substr($request->path(), 0, 255),
'method' => $request->method(),
'ip' => $request->getClientIp(),
'input' => $this->formatInput($request->input()),
];
try {
OperationLog::query()->create($log);
} catch (\Exception $exception) {
// pass
Response::fail($exception->getMessage());
}
}
// 跨域
$response = $next($request);
$IlluminateResponse = 'Illuminate\Http\Response';
$SymfonyResopnse = 'Symfony\Component\HttpFoundation\Response';
$headers = [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS, PUT, PATCH, DELETE',
'Access-Control-Allow-Headers' => 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Authorization , Access-Control-Request-Headers, X-CSRF-TOKEN'
];
if ($response instanceof $IlluminateResponse) {
foreach ($headers as $key => $value) {
$response->header($key, $value);
}
return $response;
}
if ($response instanceof $SymfonyResopnse) {
foreach ($headers as $key => $value) {
$response->headers->set($key, $value);
}
return $response;
}
return $response;
}
protected function formatInput(array $input)
{
foreach (['password', 'password_confirmation',] as $field) {
if ($field && ! empty($input[$field])) {
$input[$field] = Str::limit($input[$field], 3, '******');
}
}
return json_encode($input);
}
protected function shouldLogOperation(Request $request)
{
return ! $this->inExceptArray($request)
&& $this->inAllowedMethods($request->method());
}
protected function inAllowedMethods($method)
{
$allowedMethods = collect(['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'])->filter();
if ($allowedMethods->isEmpty()) {
return true;
}
return $allowedMethods->map(function ($method) {
return strtoupper($method);
})->contains($method);
}
protected function inExceptArray(Request $request)
{
$except = [
];
$path = Str::replaceFirst('api','',$request->path());
if (in_array($path,$except)){
return true;
}
return false;
}
}
......@@ -10,5 +10,15 @@ class Membership extends Model
{
use HasDateTimeFormatter;
protected $table = 'membership';
public function getBgImagesAttribute($value)
{
return explode(',', $value);
}
public function getSingleImgAttribute()
{
$array = explode(',', $this->bg_images);
return $array[0];
}
}
......
<?php
namespace App\Models;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
class MembershipGood extends Model
{
use HasDateTimeFormatter;
protected $table = 'membership_goods';
}
......@@ -5,6 +5,7 @@ namespace App\Models;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Auth;
class Order extends Model
{
......@@ -12,5 +13,57 @@ class Order extends Model
use SoftDeletes;
protected $table = 'order';
}
public function order_goods()
{
return $this->hasOne('App\Models\OrderGood','order_sn');
}
/**
* 预创建订单
* @param $member_id
* @param $source
*/
public function build($member_id,$source)
{
// 获取商品信息
$membership = Membership::query()->where('id',$member_id)->first();
// 实付金额 = 商品金额
$pay_amount = $membership->price;
// 创建订单
$order = new Order();
$order_sn = $this->get_sn('osn');
$order->order_sn = $order_sn;
$order->user_id = Auth::user()->getAuthIdentifier();
$order->pay_amount = $pay_amount;
$order->goods_amount = $membership->price;
$order->status = 100;
$order->source = $source;
$order->save();
$order_good = new OrderGood();
$order_good->order_sn = $order_sn;
$order_good->goods_id = $member_id;
$order_good->goods_name = $membership->name;
$order_good->goods_image = $membership->getSingleImg();
$order_good->goods_price = $membership->price;
$order_good->goods_number = 1;
$order_good->save();
}
/**
* 获取SN唯一编号
* @param string $prefix
* @return string
*/
public function get_sn($prefix = '')
{
$Sn = $prefix . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
return $Sn;
}
}
\ No newline at end of file
......
<?php
namespace App\Models;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
class OrderGood extends Model
{
use HasDateTimeFormatter;
protected $table = 'order_goods';
}
......@@ -2,7 +2,6 @@
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
......@@ -18,9 +17,13 @@ class User extends Authenticatable
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'nickname',
'mobile',
'password',
'avatar',
'gender',
'provider',
'provider_id',
];
/**
......@@ -32,13 +35,4 @@ class User extends Authenticatable
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
......
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
class UserProfile extends Model
{
use HasFactory,HasDateTimeFormatter;
protected $table = 'user_profiles';
}
......@@ -18,6 +18,13 @@ class EventServiceProvider extends ServiceProvider
Registered::class => [
SendEmailVerificationNotification::class,
],
\SocialiteProviders\Manager\SocialiteWasCalled::class => [
// ... other providers
\SocialiteProviders\Weixin\WeixinExtendSocialite::class.'@handle',
\SocialiteProviders\Apple\AppleExtendSocialite::class.'@handle',
],
];
/**
......
......@@ -15,7 +15,9 @@
"laravel/framework": "^8.75",
"laravel/sanctum": "^2.11",
"laravel/socialite": "^5.2",
"laravel/tinker": "^2.5"
"laravel/tinker": "^2.5",
"socialiteproviders/apple": "^5.0",
"socialiteproviders/weixin": "^4.1"
},
"require-dev": {
"facade/ignition": "^2.5",
......
This diff is collapsed. Click to expand it.
......@@ -175,6 +175,9 @@ return [
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
// 社会化登录
// Laravel\Socialite\SocialiteServiceProvider::class,
SocialiteProviders\Manager\ServiceProvider::class,
],
/*
......@@ -230,6 +233,8 @@ return [
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
// 社会化登录
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
],
];
......
......@@ -42,7 +42,7 @@ return [
],
'api' => [
'driver' => 'token',
'provider' => 'one_users',
'provider' => 'users',
]
],
......@@ -67,15 +67,6 @@ return [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
'one_users' => [
'driver' => 'eloquent',
'model' => App\Models\OneUser::class,
]
],
......
......@@ -30,4 +30,21 @@ return [
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'github' => [
'client_id' => env('GITHUB_APPID'),
'client_secret' => env('GITHUB_SECRET'),
'redirect' => env('GITHUB_REDIRECT'),
],
'weixin' => [
'client_id' => env('WECHAT_APPID'),
'client_secret' => env('WECHAT_SECRET'),
'redirect' => env('WECHAT_REDIRECT'),
],
'apple' => [
'client_id' => env('APPLE_CLIENT_ID'),
'client_secret' => env('APPLE_CLIENT_SECRET'),
'redirect' => env('APPLE_REDIRECT_URI')
],
];
......
......@@ -15,11 +15,14 @@ class CreateUsersTable extends Migration
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->string('nickname')->nullable()->comment('昵称');
$table->string('mobile')->unique()->nullable()->comment('手机号');
$table->string('password')->default('')->comment('密码');
$table->string('avatar')->comment('头像');
$table->string('gender')->default('')->comment('性别');
$table->string('provider')->nullable()->comment('登录提供方');
$table->string('provider_id')->nullable()->comment('第三方用户ID');
$table->unsignedTinyInteger('state')->comment('状态');
$table->timestamps();
});
}
......
......@@ -15,16 +15,19 @@ class CreateMembershipTable extends Migration
{
Schema::create('membership', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->default('')->comment('会员名称');
$table->decimal('price')->comment('价格(分)');
$table->decimal('origin_price')->comment('原价(分)');
$table->integer('limit_days')->comment('有效天数');
$table->string('limit_unit')->comment('有效期单位');
$table->string('title')->default('')->comment('标题');
$table->string('intro')->default('')->comment('简介');
$table->string('image')->default('')->comment('介绍图');
$table->unsignedTinyInteger('sale_term')->default('')->comment('上架终端');
$table->unsignedTinyInteger('state')->comment('状态:1=售卖中');
$table->unsignedTinyInteger('sn')->comment('SN顺序');
$table->unsignedTinyInteger('bg_type')->default(0)->comment('背景类型,1=单图,2=轮播图,3=视频');
$table->string('bg_images')->default('')->comment('介绍图');
$table->unsignedTinyInteger('is_video')->default(0)->comment('视频开关');
$table->string('video_url')->default('')->comment('视频地址');
$table->string('video_cover')->default('')->comment('视频封面');
$table->unsignedTinyInteger('terminal')->default(0)->comment('终端,1=Android,2=IOS');
$table->unsignedTinyInteger('state')->default(0)->comment('显示0=不显示,1=显示');
$table->timestamps();
});
}
......
......@@ -20,14 +20,12 @@ class CreateOrderTable extends Migration
$table->decimal('pay_amount')->comment('实付金额');
$table->decimal('goods_amount')->comment('商品金额');
$table->unsignedSmallInteger('status')->comment('订单状态:100待付款 101用户取消 102超时取消 103商户取消 201已付款 204已完成');
$table->timestamp('cancel_time')->comment('关闭时间');
$table->timestamp('cancel_time')->nullable()->comment('关闭时间');
$table->string('source')->comment('来源');
$table->string('pay_number')->default('')->comment('支付交易号');
$table->string('pay_type')->default('')->comment('支付类型');
$table->timestamp('pay_time')->comment('支付时间');
$table->timestamp('pay_time')->nullable()->comment('支付时间');
$table->timestamps();
$table->softDeletes();
$table->unsignedTinyInteger('is_deleted')->comment('是否删除');
});
}
......
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUserProfilesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_profiles', function (Blueprint $table) {
$table->id();
$table->string('unionid')->default('')->comment('唯一标识');
$table->string('last_visit_path')->default('')->comment('上次访问路径');
$table->timestamp('last_visit_time')->nullable()->comment('上次访问时间');
$table->string('registration_id')->default('')->comment('极光注册id');
$table->string('alias_id')->default('')->comment('极光推送别名');
$table->string('buy_number')->default(0)->comment('购买次数');
$table->string('buy_amount')->default(0)->comment('消费金额');
$table->timestamp('last_buy_time')->nullable()->comment('上次购买时间');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_profiles');
}
}
......@@ -4,7 +4,7 @@ use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateOneUsersTable extends Migration
class CreateOrderGoodsTable extends Migration
{
/**
* Run the migrations.
......@@ -13,17 +13,14 @@ class CreateOneUsersTable extends Migration
*/
public function up()
{
Schema::create('one_users', function (Blueprint $table) {
Schema::create('order_goods', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->default('')->comment('昵称');
$table->string('phone')->default('')->comment('手机号');
$table->string('password')->default('')->comment('密码');
$table->text('avatar')->comment('头像');
$table->string('gender')->default('')->comment('性别');
$table->string('remember_token')->nullable()->comment('认证令牌');
$table->string('provider')->nullable()->comment('登录提供方');
$table->string('provider_id')->nullable()->comment('第三方用户ID');
$table->unsignedTinyInteger('state')->comment('状态');
$table->string('order_sn')->comment('订单编号');
$table->unsignedInteger('goods_id')->comment('商品id');
$table->string('goods_name')->default('')->comment('商品名称');
$table->string('goods_image')->default('')->comment('商品封面');
$table->decimal('goods_price')->default('0.00')->comment('商品价格');
$table->unsignedInteger('goods_number')->default('0')->comment('商品数量');
$table->timestamps();
});
}
......@@ -35,6 +32,6 @@ class CreateOneUsersTable extends Migration
*/
public function down()
{
Schema::dropIfExists('one_users');
Schema::dropIfExists('order_goods');
}
}
......
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateMembershipGoodsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('membership_goods', function (Blueprint $table) {
$table->increments('id');
$table->integer('membership_id')->comment('会员id');
$table->decimal('price')->comment('价格');
$table->decimal('line_price')->comment('划线价格');
$table->integer('limit_days')->comment('有效天数');
$table->string('limit_unit')->default('')->comment('有效期单位');
$table->unsignedTinyInteger('terminal')->comment('1=Android,2=IOS');
$table->unsignedTinyInteger('state')->comment('0=下架,1=售卖中');
$table->unsignedTinyInteger('sn')->comment('SN顺序');
$table->unsignedInteger('visits')->comment('访问量');
$table->unsignedInteger('virtual_sales')->comment('虚拟销售量');
$table->unsignedInteger('sales')->comment('销售量');
$table->unsignedInteger('stocks')->comment('库存数量');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('membership_goods');
}
}
This diff is collapsed. Click to expand it.
<?php
return [
'labels' => [
'MembershipGood' => 'MembershipGood',
'membership-good' => 'MembershipGood',
],
'fields' => [
'price' => '价格',
'line_price' => '划线价格',
'limit_days' => '有效天数',
'limit_unit' => '有效期单位',
'sale_terminal' => '上架终端',
'state' => '状态',
'sn' => '顺序',
'visits' => '访问量',
'virtual_sales' => '虚拟销售量',
'sales' => '销售量',
'stocks' => '库存数量',
],
'options' => [
],
];
......@@ -6,12 +6,27 @@ return [
],
'fields' => [
'name' => '会员名称',
'price' => '价格(分)',
'origin_price' => '原价(分)',
'limited_days' => '有效天数',
'intro' => '简介',
'state' => '状态',
'sn' => 'SN顺序',
'membership_id' => '会员id',
'price' => '价格',
'line_price' => '划线价格',
'limit_days' => '有效天数',
'limit_unit' => '有效期单位',
'terminal' => '上架终端',
'sn' => '顺序',
'visits' => '访问量',
'virtual_sales' => '虚拟销售量',
'sales' => '销售量',
'stocks' => '库存数量',
'title' => '标题',
'bg_type' => '背景类型',
'bg_images' => '背景图',
'video_url' => '视频',
'video_cover' => '视频封面',
'is_bind_old' => '是否新增',
],
'options' => [
],
......
<?php
return [
'labels' => [
'OrderGood' => 'OrderGood',
'order-good' => 'OrderGood',
],
'fields' => [
'order_sn' => '订单编号',
'goods_id' => '商品id',
'goods_name' => '商品名称',
'goods_image' => '商品封面',
'goods_price' => '商品价格',
'goods_number' => '商品数量',
'after_sales' => '后续',
],
'options' => [
],
];
......@@ -7,6 +7,11 @@ return [
'fields' => [
'pick_id' => '一言id',
'verse_id' => '重新打包的诗句(节)id',
'plant' => '平台',
'title' => '标题',
'content' => '内容',
'action_type' => '点击后打开',
'user_id' => '用户id'
],
'options' => [
],
......
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, dashes and underscores.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => '参数 :attribute 必须是一个数组.',
'before' => 'The :attribute must be a date before :date.',
'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => '参数 :attribute 确认不匹配.',
'date' => 'The :attribute is not a valid date.',
'date_equals' => 'The :attribute must be a date equal to :date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'email' => 'The :attribute must be a valid email address.',
'ends_with' => 'The :attribute must end with one of the following: :values.',
'exists' => 'The selected :attribute is invalid.',
'file' => 'The :attribute must be a file.',
'filled' => 'The :attribute field must have a value.',
'gt' => [
'numeric' => 'The :attribute must be greater than :value.',
'file' => 'The :attribute must be greater than :value kilobytes.',
'string' => 'The :attribute must be greater than :value characters.',
'array' => 'The :attribute must have more than :value items.',
],
'gte' => [
'numeric' => 'The :attribute must be greater than or equal :value.',
'file' => 'The :attribute must be greater than or equal :value kilobytes.',
'string' => 'The :attribute must be greater than or equal :value characters.',
'array' => 'The :attribute must have :value items or more.',
],
'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => '参数 :attribute 必须是一个整形.',
'ip' => 'The :attribute must be a valid IP address.',
'ipv4' => 'The :attribute must be a valid IPv4 address.',
'ipv6' => 'The :attribute must be a valid IPv6 address.',
'json' => 'The :attribute must be a valid JSON string.',
'lt' => [
'numeric' => 'The :attribute must be less than :value.',
'file' => 'The :attribute must be less than :value kilobytes.',
'string' => 'The :attribute must be less than :value characters.',
'array' => 'The :attribute must have less than :value items.',
],
'lte' => [
'numeric' => 'The :attribute must be less than or equal :value.',
'file' => 'The :attribute must be less than or equal :value kilobytes.',
'string' => 'The :attribute must be less than or equal :value characters.',
'array' => 'The :attribute must not have more than :value items.',
],
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => '参数 :attribute 最大长度不可超过 :max 个字符.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'mimetypes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => '参数 :attribute 必须至少满足 :min 个字符.',
'array' => 'The :attribute must have at least :min items.',
],
'multiple_of' => 'The :attribute must be a multiple of :value.',
'not_in' => 'The selected :attribute is invalid.',
'not_regex' => 'The :attribute format is invalid.',
'numeric' => 'The :attribute must be a number.',
'password' => 'The password is incorrect.',
'present' => 'The :attribute field must be present.',
'regex' => 'The :attribute format is invalid.',
'required' => '参数 :attribute 字段是必选项.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values are present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => '参数 :attribute 和 :other 必须一致.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'starts_with' => 'The :attribute must start with one of the following: :values.',
'string' => '参数 :attribute 必须是一个字符串.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'uploaded' => 'The :attribute failed to upload.',
'url' => 'The :attribute format is invalid.',
'uuid' => 'The :attribute must be a valid UUID.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap our attribute placeholder
| with something more reader friendly such as "E-Mail Address" instead
| of "email". This simply helps us make our message more expressive.
|
*/
'attributes' => [],
];
<style>
.box-card {
width: 380px;
width: 400px;
border: 1px solid rgb(220, 223, 230);
border-radius: 40px;
margin-right: 24px;
......@@ -26,21 +26,21 @@
.notification-app-name{
width: 160px;
font-size: 12px;
font-size: 13px;
top: 222px;
left: 90px;
left: 92px;
}
.notification-title{
width: 210px;
font-size: 14px;
top: 242px;
left: 65px;
left: 67px;
}
.notification-detail{
width: 210px;
width: 230px;
font-size: 13px;
top: 265px;
left: 65px;
left: 67px;
word-break: break-all;
white-space: nowrap;
text-overflow: ellipsis;
......@@ -50,9 +50,9 @@
<hr>
<div class="box-card">
<div class="phone-content">
<img src="{{asset('storage/image/ios1-2.png')}}" alt="" width="338" height="625" id="bg_img">
<img src="{{asset('storage/image/ios1-2.png')}}" alt="" width="358" height="625" id="bg_img">
<div class="notification-app-name"> 一言-临境 </div>
<div class="notification-title"> demo 标题 </div>
<div class="notification-title"> Demo 标题 </div>
<div class="notification-detail"> 开发者249d42a097c1944e进行了广播推送,这是一条广播 </div>
</div>
</div>
......@@ -66,13 +66,21 @@
if (plant === 1) {
$('#bg_img').attr('src', asset + '/image/android-2.png');
$('.notification-app-name').css('top','244px').css('left','80px');
$('.notification-title').css('top','264px').css('left','55px');
$('.notification-detail').css('top','287px').css('left','55px');
$('.notification-title').css('top','264px').css('left','57px');
$('.notification-detail').css('top','287px').css('left','57px');
}else{
$('#bg_img').attr('src', asset + '/image/ios1-2.png');
$('.notification-app-name').css('top','222px').css('left','90px');
$('.notification-title').css('top','242px').css('left','65px');
$('.notification-detail').css('top','265px').css('left','65px');
$('.notification-app-name').css('top','222px').css('left','92px');
$('.notification-title').css('top','242px').css('left','67px');
$('.notification-detail').css('top','265px').css('left','67px');
}
if ($('.title').val()) {
$('.notification-title').html($('.title').val());
}
if ($('.push_content').val()) {
$('.notification-detail').html($('.push_content').val());
}
......
......@@ -14,8 +14,17 @@ use Illuminate\Routing\Router;
|
*/
//Route::prefix('v1')->middleware('auth:sanctum')->group(function ($api){
Route::prefix('v1')->namespace('App\Http\Controllers\V1')->group(function (Router $api){
/** web用户跳转登录*/
$api->get('auth/{service}', 'AuthController@redirectToProvider');
$api->get('auth/{service}/callback', 'AuthController@handleProviderCallback');
/** 移动端微信用户登录*/
$api->get('login/{service}/callback', 'AuthController@apiHandleProviderCallback');
});
//Route::prefix('v1')->middleware('auth:sanctum')->group(function ($api){
Route::prefix('v1')->namespace('App\Http\Controllers\V1')->group(function (Router $api) {
/**首页*/
......@@ -24,5 +33,6 @@ Route::prefix('v1')->namespace('App\Http\Controllers\V1')->group(function (Route
/** 临境 */
$api->apiResource('/immersive', 'ImmerseController');
/** 创建订单 */
$api->apiResource('/order', 'OrderController');
});
\ No newline at end of file
......