李帅

1.会员模板页面完成。

2.订单还在构思。
......@@ -2,14 +2,18 @@
namespace App\Admin\Controllers;
use App\Admin\Renderable\MembershipGoodsEasyTable;
use App\Admin\Renderable\MembershipGoodsTable;
use App\Admin\Repositories\Membership;
use App\Models\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;
use Illuminate\Support\Facades\DB;
use Dcat\Admin\Widgets\Table;
class MembershipController extends AdminController
{
......@@ -27,28 +31,27 @@ class MembershipController extends AdminController
$grid->setActionClass(Grid\Displayers\Actions::class);
$grid->column('id',__('ID'))->sortable();
$grid->column('name');
$grid->column('price');
$grid->column('line_price');
$grid->column('limited_days');
$grid->column('limit_unit');
$grid->column('title');
$grid->column('intro');
$grid->column('state');
$grid->column('sn');
$grid->column('expand','展开')
->display('会员商品')
->expand(function (){
$th = ['id','price','line_price','limit_days','limit_unit'];
$data = MembershipGood::query()->where('membership_id',$this->id)->get($th)->toArray();
return Table::make($th, $data);
});
$grid->column('video_url');
$grid->column('video_cover');
$grid->column('bg_images');
$grid->column('visits');
$grid->column('virtual_sales');
$grid->column('sales');
$grid->column('video_cover')->image('/storage/');
$grid->column('bg_images')->gallery('/storage/');
$grid->column('terminal')->using([1 => '安卓', 2 => 'iOS'], '未知');
$grid->column('state','线上展示')->switch();
$grid->column('created_at');
$grid->column('updated_at')->sortable();
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('id');
$filter->equal('id')->width(2);
$filter->like('terminal')->width(3);
$filter->panel();
});
});
......@@ -94,16 +97,29 @@ class MembershipController extends AdminController
*/
protected function form()
{
$css = <<<CSS
.table tr td:first-child{
padding-left: 0 ;
}
.table tr td{
padding-left: 0 ;
}
.form-field .input-group .price{
width: 1% !important;
}
CSS;
\Admin::style($css);
return Form::make(new Membership(), function (Form $form) {
$form->display('id');
$form->block(12, function (Form\BlockForm $form) {
$form->block(8, function (Form\BlockForm $form) {
// 设置标题
$form->title('基本设置');
// 显示底部提交按钮
$form->showFooter();
// 设置字段宽度
$form->width(8, 2);
$form->width(9, 2);
$form->radio('terminal')->addElementClass('terminal')
->options([1 => 'Android', 2 => 'IOS'])->default(2);
......@@ -112,7 +128,7 @@ class MembershipController extends AdminController
$form->textarea('intro')->addElementClass('intro');
$form->radio('bg_type')->addElementClass('bg_type')
->options([1 => '单图', 2 => '轮播图', 3 => '视频'])->default(1)
->options([1 => '单图', 2 => '轮播图', 3 => '视频'])
->when([1,2],function (Form\BlockForm $form){
$form->multipleImage('bg_images')
->limit(5)
......@@ -129,36 +145,91 @@ class MembershipController extends AdminController
$form->image('video_cover')
->uniqueName()
->addElementClass('video_cover');
});
})->default(1);
$form->radio('state')->options(['不显示', '显示'])->default(0);
$form->radio('is_bind_old')->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');
$form->table('new','新增', function (NestedForm $table) {
$table->text('price')->addElementClass('price');
$table->text('line_price')->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')
$form->multipleSelectTable('old','已有')
->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->block(4, function (Form\BlockForm $form) {
$form->width(9, 1);
$form->html(view('admin.form.membership'));
});
$form->display('created_at');
$form->display('updated_at');
});
}
public function store()
{
$all = request()->all();
//
if (isset($all['upload_column'])) return $this->form()->store();
// 检测是否已经有该平台的数据
$membership = Membership::query()->where('terminal',$all['terminal'])->first();
if ($membership && $all['state'] == '1') return $this->form()->response()->error('状态为显示会覆盖线上的设置,请修改后重试');
try{
DB::transaction(function ()use ($all){
$membership = Membership::query()->create([
'title' => $all['title'],
'intro' => $all['intro'],
'bg_type' => $all['bg_type'],
'bg_images' => $all['bg_images'],
'video_url' => $all['video_url'] ?? '',
'video_cover' => $all['video_cover'] ?? '',
'terminal' => $all['terminal'],
'state' => $all['state'],
]);
if ($all['is_bind_old'] === '0'){
// 新增
foreach ($all['new'] as $item) {
if ($item['_remove_'] === '1') continue;
MembershipGood::query()->create([
'membership_id' => $membership->id,
'price' => $item['price'],
'line_price' => $item['line_price'],
'limited_days' => $item['limited_days'],
'limit_unit' => $item['limit_unit'] ?? '天',
'terminal' => $all['terminal'],
'state' => 1,
]);
}
}elseif ($all['is_bind_old'] === '1'){
$old_ids = explode(',',$all['old']);
$membership_goods = MembershipGood::query()->whereIn('id',$old_ids)->get();
foreach ($membership_goods as $membership_good){
$membership_good->membership_id = $membership->id;
$membership_good->state = 1;
$membership_good->save();
}
}
});
}catch (\Exception $exception){
return $this->form()->response()->error($exception->getMessage());
}
return $this->form()->response()->refresh()->success(trans('admin.save_succeeded'));
}
}
......
<?php
/**
* Created by PhpStorm.
* User: lishuai
* Date: 2022/2/11
* Time: 5:30 PM
*/
namespace App\Admin\Extensions;
use Dcat\Admin\Admin;
use Dcat\Admin\Grid\Displayers\AbstractDisplayer;
use Dcat\Admin\Support\Helper;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Facades\Storage;
class Gallery extends AbstractDisplayer
{
public function display($server = '', $width = 100, $height = 200)
{
Admin::js('@js/viewer.js');
Admin::css([
'@css/gallery.css',
'@css/viewer.css'
]);
$defaultArgs = [
'server' => $server,
'width' => $width,
'height' => $height,
];
['server' => $server, 'width' => $width, 'height' => $height] = $defaultArgs;
if ($this->value instanceof Arrayable) {
$this->value = $this->value->toArray();
}
$groupId = $this->grid->getTableId().'_'.$this->getKey().'_'.$this->column->getName().'_gallery_group';
$src = []; // 避免 $src 未定义
foreach (Helper::array($this->value) as $k => $v) {
if (url()->isValidUrl($v) || mb_strpos($v, 'data:image') === 0) {
$src[] = $v;
} elseif ($server) {
$src[] = rtrim($server, '/').'/'.ltrim($v, '/');
} else {
$src[] = Storage::disk(config('admin.upload.disk'))->url($v);
}
}
return Admin::view('admin.grid.gallery', ['src' => $src, 'width' => $width, 'height' => $height, 'id' => $groupId]);
}
}
<?php
/**
* Created by PhpStorm.
* User: lishuai
* Date: 2022/2/11
* Time: 5:30 PM
*/
namespace App\Admin\Extensions;
use Dcat\Admin\Admin;
use Dcat\Admin\Grid\Displayers\AbstractDisplayer;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Facades\Storage;
class Swiper extends AbstractDisplayer
{
public function display($server = '', $width = 200, $height = 200)
{
// todo
// if ($this->value instanceof Arrayable) {
// $this->value = $this->value->toArray();
// }
//
// return collect((array) $this->value)->filter()->map(function ($path) use ($server, $width, $height) {
// if (url()->isValidUrl($path) || mb_strpos($path, 'data:image') === 0) {
// $src = $path;
// } elseif ($server) {
// $src = rtrim($server, '/').'/'.ltrim($path, '/');
// } else {
// $src = Storage::disk(config('admin.upload.disk'))->url($path);
// }
//
// return "<img data-action='preview-img' src='$src' style='max-width:{$width}px;max-height:{$height}px;cursor:pointer' class='img img-thumbnail' />";
// })->implode('&nbsp;');
}
}
......@@ -17,6 +17,8 @@ class MembershipGoodsTable extends LazyRenderable
public function grid(): Grid
{
return Grid::make(new MembershipGood(), function (Grid $grid) {
$grid->model()->where('state',0);
$grid->column('id', 'ID')->sortable();
$grid->column('membership_id');
$grid->column('price');
......
<?php
namespace App\Admin\Repositories;
use App\Models\MembershipGood as Model;
use Dcat\Admin\Repositories\EloquentRepository;
class MembershipGood extends EloquentRepository
{
/**
* Model.
*
* @var string
*/
protected $eloquentClass = Model::class;
}
<?php
namespace App\Admin\Repositories;
use App\Models\OrderGood as Model;
use Dcat\Admin\Repositories\EloquentRepository;
class OrderGood extends EloquentRepository
{
/**
* Model.
*
* @var string
*/
protected $eloquentClass = Model::class;
}
<?php
namespace App\Admin\Repositories;
use App\Models\VideoTemp as Model;
use Dcat\Admin\Repositories\EloquentRepository;
class VideoTemp extends EloquentRepository
{
/**
* Model.
*
* @var string
*/
protected $eloquentClass = Model::class;
}
......@@ -5,6 +5,8 @@ use Dcat\Admin\Grid;
use Dcat\Admin\Form;
use Dcat\Admin\Grid\Filter;
use Dcat\Admin\Show;
use Dcat\Admin\Grid\Column;
use App\Admin\Extensions\Gallery;
/**
* Dcat-admin - admin builder based on Laravel.
......@@ -24,3 +26,7 @@ use Dcat\Admin\Show;
* Admin::js('/packages/prettydocs/js/main.js');
*
*/
Admin::asset()->alias('@js', '/asset/js');
Admin::asset()->alias('@css', '/asset/css');
Column::extend('gallery', Gallery::class); //grid列扩展 - 多图浏览
\ No newline at end of file
......
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
class DevFFmpeg extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'dev:ff';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
protected $ffmpeg = '/Users/lishuai/Documents/ffmpeg/ffmpeg';
protected $ffprobe = '/Users/lishuai/Documents/ffmpeg/ffprobe';
protected $ffplay = '/Users/lishuai/Documents/ffmpeg/ffplay';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// $file = Storage::disk('public')->path('ffmpeg') . "/qinghuaci.mp4";
// $font = Storage::disk('public')->path('ffmpeg') . "/arialuni.ttf";
// $signature = '题破山寺后禅院' . "\t" . ' -- 常建' . PHP_EOL .
// '清晨入古寺,初日照高林。' . PHP_EOL .
// '曲径通幽处,禅房花木深。' . PHP_EOL .
// '山光悦鸟性,潭影空人心。' . PHP_EOL .
// '万籁此都寂,但余钟磬音。' . PHP_EOL ;
//
//// $cmd = $this->ffplay . ' -i ' . escapeshellarg($file) .
//// ' -vf "'.
//// 'drawtext='.
//// 'fontfile=' . escapeshellarg($font) . ':'.
//// 'text=' . escapeshellarg($signature) . ':'.
//// 'fontsize=43:'.
//// 'fontcolor=white@1.0:'.
//// 'x=main_w/2' . '-260' . ':'.
//// 'y=main_h/2' . '-20' . ':'.
//// 'box=1:boxcolor=0xd0cdcc@0.5'.
//// '"';
// $video = $this->getTempPath();
// $cmd = $this->ffmpeg . ' -y -i ' . escapeshellarg($file) .
// ' -vf "'.
// 'drawtext='.
// 'fontfile=' . escapeshellarg($font) . ':'.
// 'text=' . escapeshellarg($signature) . ':'.
// 'fontsize=43:'.
// 'fontcolor=white@1.0:'.
// 'x=main_w/2' . '-260' . ':'.
// 'y=main_h/2' . '-20' . ':'.
// 'box=1:boxcolor=0xd0cdcc@0.5'.
// '" ' . escapeshellarg($video);
//
// $file = $this->execmd($cmd);
//
//dd($file);
$file = Storage::disk('public')->path('ffmpeg') . "/output_1646128658383.mp4";
$watermark = Storage::disk('public')->path('ffmpeg') . "/LOGO_eng.png";
$watermark_x = 20;
$watermark_y = 20;
$animate = Storage::disk('public')->path('ffmpeg') . "/output_16461288409938.mp4";
$video = $this->getTempPath();
$watermark_x = $watermark_x ? $watermark_x : 0;
$watermark_y = $watermark_y ? $watermark_y : 0;
$am_inp = ' -i ' . escapeshellarg($watermark);
$am_filter = "[2:v]overlay={$watermark_x}:{$watermark_y}[water];[water]";
$cmd = $this->ffmpeg . ' -y' .
' -i ' . escapeshellarg($file) .
' -i ' . escapeshellarg($animate) .
$am_inp .
// ' -filter_complex "[0:0]' . '' . $am_filter . 'setsar=sar=1/1[t];[t] [2:a] [1:0] [1:1] concat=n=2:v=1:a=1 [v] [a]"' .
' -filter_complex "[0:0]' . '' . $am_filter . '[0:1] [1:0] [1:1] concat=n=2:v=1:a=1 [v] [a]"' .
' -map [v] -map [a]';
$cmd .=
' -c:v libx264 -s 800x450 -bt 256k -r 25' .
// todo 没有libfdk_aac库
// ' -c:a libfdk_aac -ar 44100 -ac 2 -qmin 30 -qmax 60 -profile:v baseline -preset fast ' .
' -ar 44100 -ac 2 -qmin 30 -qmax 60 -profile:v baseline -preset fast ' .
escapeshellarg($video);
if ($this->execmd($cmd)) {
return $video;
} else {
return false;
}
// $file = Storage::disk('public')->path('ffmpeg') . "/20180403172057586426000359.mp4";
$end_wallpaper = Storage::disk('public')->path('ffmpeg') . "/end_wallpaper.png";
$thumbnail = Storage::disk('public')->path('ffmpeg') . "/thumbnail.png";
$font = Storage::disk('public')->path('ffmpeg') . "/arialuni.ttf";
$signature = "一个比较长的用户昵称";
$signature_x = 0;
$signature_y = -20;
$user_audio = Storage::disk('public')->path('ffmpeg') . "/20181128172555064722000590.aac";
$watermark = Storage::disk('public')->path('ffmpeg') . "/LOGO_eng.png";
$watermark_x = 20;
$watermark_y = 20;
// 生成贴纸和签名
$end_wallpaper = $this->wallpaperWithSignature($end_wallpaper, $thumbnail, $signature, $font);
// 截取最后一帧
$last_frame_video = $this->makeLastFrameVideo($file);
$animate = '';
if ($last_frame_video) {
$animate = $this->makeAnimate($last_frame_video, $end_wallpaper, '', $signature_x, $signature_y, $font);
}
dd($animate);
//
$mofunshow = $this->makeMofunshow($file, $user_audio, $animate, null, $watermark, $watermark_x, $watermark_y);
dd($mofunshow);
return 0;
}
/**
* 获取圆形头像
* @param $img
* @param int $dst_w
* @param int $dst_h
* @return resource
*/
public function getCircleAvatar($img, $dst_w = 96, $dst_h = 96)
{
$w = 130;
$h = 130;
$src = imagecreatetruecolor($dst_w, $dst_h);
imagecopyresized($src, $img, 0, 0, 0, 0, $dst_w, $dst_h, $w, $h);
$newpic = imagecreatetruecolor($dst_w, $dst_h);
imagealphablending($newpic, false);
imagecopyresampled($newpic, $img, 0, 0, 0, 0, $dst_w, $dst_h, $w, $h);
$mask = imagecreatetruecolor($dst_w, $dst_h);
$transparent = imagecolorallocate($mask, 255, 0, 0);
imagecolortransparent($mask,$transparent);
imagefilledellipse($mask, $dst_w / 2, $dst_h / 2, $dst_w, $dst_h, $transparent);
$red = imagecolorallocate($mask, 0, 0, 0);
imagecopymerge($newpic, $mask, 0, 0, 0, 0, $dst_w, $dst_h, 100);
imagecolortransparent($newpic,$red);
imagesavealpha($newpic,true);
imagefill($newpic, 0, 0, $red);
imagedestroy($mask);
return $newpic;
}
/**
* 制作最后一帧
* @param $file
* @return bool|string
*/
public function makeLastFrameVideo($file) {
$video = $this->getTempPath();
$width = $this->getVideoWith($file);
$height = $this->getVideoHeight($file);
$size = $width . 'x' . $height;
$time_length = 0.7;
$r = 24;
$frame_n = $this->getVideoFrameNum($file) - 2;
$cmd = $this->ffmpeg . ' -y -i ' . escapeshellarg($file) .
" -f lavfi -i nullsrc=s={$size}:d={$time_length}:r={$r} -f lavfi -i aevalsrc=0:duration={$time_length}" .
" -filter_complex \"[0:v]select='eq(n,{$frame_n})',setpts=PTS-STARTPTS[lastframe];[1:v][lastframe]overlay[v]\"" .
' -map [v] -map 2:a ' . escapeshellarg($video);
if ($this->execmd($cmd)) {
return $video;
} else {
return false;
}
}
/**
* 用最后一帧和贴纸制作动画
* @param $last_frame_video
* @param $end_wallpaper
* @param $signature
* @param $signature_x
* @param $signature_y
* @param $font
* @return bool|string
*/
public function makeAnimate($last_frame_video, $end_wallpaper, $signature, $signature_x, $signature_y, $font) {
$signature_x = $signature_x >= 0 ? '+' . $signature_x : '-' . abs($signature_x);
$signature_y = $signature_y >= 0 ? '+' . $signature_y : '-' . abs($signature_y);
$video = $this->getTempPath();
if ($signature !== '') {
$cmd = $this->ffmpeg . ' -y -i ' . escapeshellarg($last_frame_video) .
' -loop 1 -i ' . escapeshellarg($end_wallpaper) .
' -filter_complex "'.
'geq=lum=\'if(lte(T,0.6), 255*T*(1/0.6),255)\',format=gray[grad];'.
'[0:v]boxblur=8[blur];'.
'[blur][1:v]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 [lay];[lay]'.
'drawtext='.
'fontfile=' . escapeshellarg($font) . ':'.
'text=' . escapeshellarg($signature) . ':'.
'fontsize=23:'.
'fontcolor=white@1.0:'.
'x=main_w/2' . $signature_x . ':'.
'y=main_h/2' . $signature_y . '[text];[text]'.
'[grad]alphamerge[alpha];'.
'[0:v][alpha]overlay'.
'" ' . escapeshellarg($video);
} else {
$cmd = $this->ffmpeg . ' -y -i ' . escapeshellarg($last_frame_video) .
' -loop 1 -i ' . escapeshellarg($end_wallpaper) .
' -filter_complex "'.
'geq=lum=\'if(lte(T,0.6), 255*T*(1/0.6),255)\',format=gray[grad];'.
'[0:v]boxblur=8[blur];'.
'[blur][1:v]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2 [lay];'.
'[lay][grad]alphamerge[alpha];'.
'[0:v][alpha]overlay'.
'" ' . escapeshellarg($video);
}
if ($this->execmd($cmd)) {
return $video;
} else {
return false;
}
}
/**
* 获取视频宽度
* @param $file
* @param bool $cache
* @return int|null
*/
public function getVideoWith($file, $cache = true) {
$result = $this->getFirstVideoTrackOption($file, $option = 'width', $cache);
if ($result) {
return (int)$result;
} else {
return $result;
}
}
/**
* 获取视频高度
* @param $file
* @param bool $cache
* @return int|null
*/
public function getVideoHeight($file, $cache = true) {
$result = $this->getFirstVideoTrackOption($file, $option = 'height', $cache);
if ($result) {
return (int)$result;
} else {
return $result;
}
}
/**
* 获取视频帧数
* @param $file
* @param bool $cache
* @return null
*/
public function getVideoFrameNum($file, $cache = true) {
return $this->getFirstVideoTrackOption($file, $option = 'nb_frames', $cache);
}
public function getFirstVideoTrackOption($file, $option, $cache = true) {
return $this->getFirstTrackOption($file, $option, $codec_type = 'video', $cache = true);
}
public function getFirstTrackOption($file, $option, $codec_type = '', $cache = true) {
$result = $this->mediainfo($file, $cache);
if (!isset($result['streams'])) {
return null;
}
$_track = null;
foreach($result['streams'] as $track) {
if (empty($codec_type)) {
$_track = $track;
break;
} elseif ($track['codec_type'] == $codec_type) {
$_track = $track;
break;
}
}
if (isset($_track[$option])) {
return $_track[$option];
}
return null;
}
/***
* 获取视频信息(配合ffprobe)
* @param $file
* @param bool $cache
* @return mixed
*/
public function mediainfo($file, $cache = true) {
global $_mediainfo;
$cmd = $this->ffprobe . ' -v quiet -print_format json -show_format -show_streams ' . escapeshellarg($file);
if ($cache && isset($_mediainfo[$file])) {
return $_mediainfo[$file];
}
$output = $this->execmd($cmd);
$data = json_decode($output, true);
if (json_last_error() === JSON_ERROR_UTF8) {
$output = mb_convert_encoding($output, "UTF-8");
$data = json_decode($output, true);
}
if ($cache) {
$mediainfo[$file] = $data;
}
return $data;
}
/**
* 获取输出临时文件名
* @return string
*/
public function getTempPath() {
return Storage::disk('public')->path('ffmpeg') . "/output_" . time() . rand(0, 10000) . ".mp4";
}
/**
* 执行命令
* @param $cmd
* @param bool $update_progress
* @return string
*/
public function execmd($cmd, $update_progress = false) {
echo $cmd . "\n". "\n". "\n";
$descriptorspec = array(
1 => array("pipe", "w"), // 标准输出,子进程向此管道中写入数据
);
$process = proc_open("{$cmd} 2>&1", $descriptorspec, $pipes);
if (is_resource($process)) {
$error0 = '';
$error1 = '';
$stdout = '';
while (!feof($pipes[1])) {
$line = fgets($pipes[1], 150);
$stdout .= $line;
if ($line) {
//记录错误
$error0 = $error1;
$error1 = $line;
if ($update_progress &&
false !== strpos($line, 'size=') &&
false !== strpos($line, 'time=') &&
false !== strpos($line, 'bitrate='))
{
//记录进度 size= 3142kB time=00:00:47.22 bitrate= 545.1kbits/s
$line = explode(' ', $line);
$time = null;
foreach ($line as $item) {
$item = explode('=', $item);
if (isset($item[0]) && isset($item[1]) && $item[0] == 'time') {
$time = $item[1];
break;
}
}
}
}
}
// 切记:在调用 proc_close 之前关闭所有的管道以避免死锁。
fclose($pipes[1]);
$exitedcode = proc_close($process);
if ($exitedcode === 0) {
return $stdout;
} else {
$error = trim($error0,"\n") . ' '. trim($error1,"\n");
// LogUtil::write(array("cmd:{$cmd}", "errno:{$exitedcode}", "stdout:{$stdout}"), __CLASS__);
// ErrorUtil::triggerErrorMsg($error, $exitedcode);
}
} else {
// return ErrorUtil::triggerErrorMsg('proc_open error');
}
}
/**
* 贴纸和签名
* @param $end_wallpaper
* @param $thumbnail
* @param $signature
* @param $font
* @return string
*/
public function wallpaperWithSignature($end_wallpaper, $thumbnail, $signature, $font) {
$_imagetype = $this->getImageType($thumbnail);
$_img = null;
switch ($_imagetype) {
case 'gif':
if (function_exists('imagecreatefromgif')) {
$_img = imagecreatefromgif($thumbnail);
}
break;
case 'jpg':
case 'jpeg':
$_img = imagecreatefromjpeg($thumbnail);
break;
case 'png':
$_img = imagecreatefrompng($thumbnail);
break;
default:
$_img = imagecreatefromstring($thumbnail);
break;
}
$width = 130;
$height = 130;
$_width = 130;
$_height = 130;
if(is_resource($_img)){
$_width = imagesx($_img);
$_height = imagesy($_img);
}
$bite = $_width / $_height;
if($_width > $_height){
if($_width > $width){
$height = round($width / $bite);
}
}else{
if($_height > $height){
$width = round($height * $bite);
}
}
$tmpimg = imagecreatetruecolor($width,$height);
if(function_exists('imagecopyresampled')) {
imagecopyresampled($tmpimg, $_img, 0, 0, 0, 0, $width, $height, $_width, $_height);
} else {
imagecopyresized($tmpimg, $_img, 0, 0, 0, 0, $width, $height, $_width, $_height);
}
if(is_resource($_img)) imagedestroy($_img);
$_img = $this->getCircleAvatar($tmpimg);
if(is_resource($tmpimg)) imagedestroy($tmpimg);
$wp = $this->imagesMerge($end_wallpaper, $_img);
// $white = imagecolorallocate($wp, 0xd0, 0xcd, 0xcc);
$white = imagecolorallocate($wp, 0xDC, 0x14, 0x3C); //fixme 字体颜色
imagettftext($wp, 20, 0, 75, 240, $white, $font, $signature);
// $dst = "./output_new_end_wallpaper.png";
$dst = Storage::disk('public')->path('ffmpeg') . "/output_new_end_wallpaper.png";
imagepng($wp, $dst);
if(is_resource($end_wallpaper)) imagedestroy($end_wallpaper);
if(is_resource($_img)) imagedestroy($_img);
return $dst;
}
/**
* 获取图像文件类型
* @param $img_name
* @return string
*/
public function getImageType($img_name)
{
if (preg_match("/\.(jpg|jpeg|gif|png)$/i", $img_name, $matches)){
$type = strtolower($matches[1]);
}else{
$type = "string";
}
return $type;
}
/**
* 多图融合
* @param $end_wallpaper
* @param $thumbnail
* @return resource
*/
public function imagesMerge($end_wallpaper, $thumbnail) {
$end_wallpaper = imagecreatefrompng($end_wallpaper);
$background = imagecreatefrompng(Storage::disk('public')->path('ffmpeg/background.png'));
imagesavealpha($background,true);
$temp_wallpaper = imagecreatetruecolor(350, 204);
$color = imagecolorallocate($temp_wallpaper, 0xd0, 0xcd, 0xcc);
// $color = imagecolorallocate($temp_wallpaper, 0xDC, 0x14, 0x3C);
imagefill($temp_wallpaper, 0, 0, $color);
imageColorTransparent($temp_wallpaper, $color);
imagecopyresampled($temp_wallpaper, $end_wallpaper, 0, 0, 0, 0, imagesx($temp_wallpaper), imagesy($temp_wallpaper), imagesx($end_wallpaper), imagesy($end_wallpaper));
imagecopymerge($background, $temp_wallpaper, 0, 0, 0, 0, imagesx($temp_wallpaper), imagesy($temp_wallpaper), 60);
imagecopymerge($background, $thumbnail, 127, 26, 0, 0, imagesx($thumbnail), imagesy($thumbnail), 100);
return $background;
}
/**
* 合成视频秀
* @param $file
* @param $audio
* @param null $animate
* @param null $ass_file
* @param null $watermark
* @param null $watermark_x
* @param null $watermark_y
* @return bool|string
*/
public function makeMofunshow($file, $audio, $animate = null, $ass_file = null, $watermark = null, $watermark_x = null, $watermark_y = null)
{
$video = $this->getTempPath();
if ($animate) {
$ass_filter = $ass_file ? 'ass=' . escapeshellarg($ass_file) . '[ass];[ass]' : '';
if ($watermark && is_file($watermark) && getimagesize($watermark)) {
$watermark_x = $watermark_x ? $watermark_x : 0;
$watermark_y = $watermark_y ? $watermark_y : 0;
$am_inp = ' -i ' . escapeshellarg($watermark);
$am_filter = "[3:v]overlay={$watermark_x}:{$watermark_y}[water];[water]";
} else {
$am_inp = '';
$am_filter = '';
}
$cmd = $this->ffmpeg . ' -y' .
' -i ' . escapeshellarg($file) .
' -i ' . escapeshellarg($animate) .
' -i ' . escapeshellarg($audio) .
$am_inp .
' -filter_complex "[0:0]' . $ass_filter . $am_filter . 'setsar=sar=1/1[t];[t] [2:a] [1:0] [1:1] concat=n=2:v=1:a=1 [v] [a]"' .
' -map [v] -map [a]';
} else {
$ass_filter = $ass_file ? ' -vf ass=' . escapeshellarg($ass_file) : '';
$cmd = $this->ffmpeg . ' -y' .
' -i ' . escapeshellarg($file) .
' -i ' . escapeshellarg($audio) .
' -map 0:0' .
' -map 1:0' .
$ass_filter;
}
$cmd .=
' -c:v libx264 -s 800x450 -bt 256k -r 25' .
// todo 没有libfdk_aac库
// ' -c:a libfdk_aac -ar 44100 -ac 2 -qmin 30 -qmax 60 -profile:v baseline -preset fast ' .
' -ar 44100 -ac 2 -qmin 30 -qmax 60 -profile:v baseline -preset fast ' .
escapeshellarg($video);
if ($this->execmd($cmd)) {
return $video;
} else {
return false;
}
}
}
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Console\Commands\Pinyin;
class DevPinyin extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'dev:pinyin';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$arr = [
'胡的接班人' => '***',
'钦定接班人' => '***',
'政治局常委' => '***',
'中纪委' => '***',
'主席像' => '***',
'总书记' => '***',
'共一产一党' => '***',
'口交*' => '***',
'江泽民*' => '***',
'胡锦涛*' => '***',
'温家宝*' => '***',
'习近平*' => '***',
'习仲勋*' => '***',
'贺国强*' => '***',
'贺子珍*' => '***',
'周永康*' => '***',
'李长春*' => '***',
'李德生*' => '***',
'王岐山*' => '***',
'姚依林*' => '***',
'回良玉*' => '***',
'李源潮*' => '***',
'李干成*' => '***',
'戴秉国*' => '***',
'黄镇*' => '***',
'刘延东*' => '***',
'刘瑞龙*' => '***',
'俞正声*' => '***',
'黄敬*' => '***',
'薄熙*' => '***',
'薄一波*' => '***',
'周小川*' => '***',
'周建南*' => '***',
'温云松*' => '***',
'徐明*' => '***',
'江泽慧*' => '***',
'江绵恒*' => '***',
'江绵康*' => '***',
'李小鹏*' => '***',
'李小琳*' => '***',
'朱云来*' => '***',
'朱容基*' => '***',
'第二代身份证*' => '***',
'文化大革命**' => '***',
'胡海峰*' => '***',
'六四*' => '***',
'反共*' => '***',
'共产党*' => '***',
'陈良宇*' => '***',
'老丁*' => '***',
'莱仕德事件**' => '***',
'李洪志*' => '***',
'大纪元*' => '***',
'真善忍*' => '***',
'新唐人*' => '***',
'肉棍*' => '***',
'淫靡*' => '***',
'淫水*' => '***',
'六四事件*' => '***',
'迷昏药*' => '***',
'迷魂药*' => '***',
'窃听器*' => '***',
'六合彩*' => '***',
'买卖枪支*' => '***',
'三唑仑*' => '***',
'麻醉药*' => '***',
'麻醉乙醚*' => '***',
'短信群发器*' => '***',
'帝国之梦*' => '***',
'毛一鲜*' => '***',
'黎阳平*' => '***',
'对日强硬*' => '***',
'出售枪支*' => '***',
'迷药*' => '***',
'摇头丸*' => '***',
'西藏天葬*' => '***',
'军长发威*' => '***',
'PK黑社会*' => '***',
'枪决女犯*' => '***',
'投毒杀人*' => '***',
'强硬发言*' => '***',
'出售假币*' => '***',
'监听王*' => '***',
'昏药*' => '***',
'侦探设备*' => '***',
'麻醉钢枪*' => '***',
'反华*' => '***',
'官商勾结*' => '***',
'升达毕业证*' => '***',
'手机复制*' => '***',
'戴海静*' => '***',
'自杀指南*' => '***',
'自杀手册*' => '***',
'张小平*' => '***',
'佳静安定片*' => '***',
'蒙汗药粉*' => '***',
'古方迷香*' => '***',
'强效失意药*' => '***',
'迷奸药*' => '***',
'透视眼镜*' => '***',
'远程偷拍*' => '***',
'自制手枪*' => '***',
'激情小电影*' => '***',
'黄色小电影*' => '***',
'天鹅之旅*' => '***',
'盘古乐队*' => '***',
'高校暴乱*' => '***',
'高校群体事件*' => '***',
'大学骚乱*' => '***',
'高校骚乱*' => '***',
'催情药*' => '***',
'拍肩神药*' => '***',
'春药*' => '***',
'身份证生成器*' => '***',
'枪决现场*' => '***',
'出售手枪*' => '***',
'麻醉枪*' => '***',
'办理证件*' => '***',
'办理文凭*' => '***',
'疆独*' => '***',
'藏独*' => '***',
'高干子弟*' => '***',
'高干子女*' => '***',
'枪支弹药*' => '***',
'血腥图片*' => '***',
'反政府*' => '***',
'禁书*' => '***',
'无界浏览器*' => '***',
'特码*' => '***',
'成人*' => '***',
'换妻*' => '***',
'共匪共框非' => '***',
'国民党G·M·D' => '***',
'腐败F·B' => '***',
'贪污T·W' => '***',
'自慰Z·W' => '***',
'淫荡Y·D' => '***',
'骚妇S·F' => '***',
'台独台反文旁虫' => '***',
'法论功三点水去论工力' => '***',
'李宏志L·H·Z' => '***',
'江湖淫娘*' => '***',
'骆冰淫传*' => '***',
'夫妇乐园*' => '***',
'阿里布达年代记*' => '***',
'爱神之传奇*' => '***',
'不良少女日记*' => '***',
'沧澜曲*' => '***',
'创世之子猎艳之旅*' => '***',
'东北风情熟女之惑*' => '***',
'风骚侍女*' => '***',
'海盗的悠闲生活*' => '***',
'黑天使*' => '***',
'黑星女侠*' => '***',
'混蛋神风流史*' => '***',
'狡猾的风水相师*' => '***',
'俪影蝎心*' => '***',
'秦青的幸福生活*' => '***',
'四海龙女*' => '***',
'逃亡艳旅*' => '***',
'性启蒙*' => '***',
'现代艳帝传奇*' => '***',
'星光伴我淫*' => '***',
'倚天屠龙别记*' => '***',
'淫术炼金士*' => '***',
'十景缎*' => '***',
'往事追忆录*' => '***',
'舌战法庭*' => '***',
'少妇白洁*' => '***',
'风月大陆*' => '***',
'风尘劫*' => '***',
'美少妇的哀羞*' => '***',
'阿兵哥言语录*' => '***',
'遥想当年春衫薄*' => '***',
'王子淫传*' => '***',
'神雕外传之郭襄*' => '***',
'睡着的武神*' => '***',
'少年阿宾*' => '***',
'毛主席复活*' => '***',
'蒙汗药*' => '***',
'粗口歌*' => '***',
'激情电影*' => '***',
'AV*' => '***',
'十八禁*' => '***',
'a片*' => '***',
'性虐待*' => '***',
'女优*' => '***',
'18禁*' => '***',
'激情*' => '***',
'耽美*' => '***',
'金瓶梅*' => '***',
'丝袜*' => '***',
'美腿*' => '***',
'毛片*' => '***',
'少儿不宜*' => '***',
'藏春阁*' => '***',
'玉蒲团*' => '***',
'隐形喷剂*' => '***',
'反雷达测速*' => '***',
'假币*' => '***',
'代开发票*' => '***',
'假钞*' => '***',
'窃听*' => '***',
'电话拦截系统*' => '***',
'探测狗*' => '***',
'手机卡复制器*' => '***',
'手机跟踪定位器*' => '***',
'监听器*' => '***',
'针孔摄像*' => '***',
'监听宝*' => '***',
'迷幻药*' => '***',
'手拍肩*' => '***',
'迷魂香*' => '***',
'麻古*' => '***',
'共狗*' => '***',
'政治风波*' => '***',
'政府软弱*' => '***',
'政府无能*' => '***',
'九评*' => '***',
'十七大代表*' => '***',
'办证*' => '***',
'暴力拆迁*' => '***',
'轮暴致死*' => '***',
'人民报*' => '***',
'天葬*' => '***',
'轮奸*' => '***',
'暴力镇压*' => '***',
'陈水扁*' => '***',
'达赖*' => '***',
'共匪*' => '***',
'天安门事件*' => '***',
'高干子弟名单*' => '***',
'性免费电影*' => '***',
'全裸*' => '***',
'偷拍*' => '***',
'偷 拍*' => '***',
'台独*' => '***',
];
$keys = array_keys($arr);
$array = [];
foreach ($keys as $key){
$array[Pinyin::getPinyin($key)] = '***';
}
var_export($array);
dd(1);
//
// $array = array(
// 'taokaixin' => '***',
// 'wangcai' => '**',
// 'Qbi' => '**',
// 'jianzhi' => '**',
// 'zhifubao' => '***',
// 'mianfeizhuanqian' => '****',
// 'huafei' => '**',
// 'yuanjiao' => '**',
// 'selangjizhongying' => '*****',
// 'langkeyulewang' => '*****',
// 'AVzhongzi' => '****',
// 'rouman' => '**',
// 'shangmenfuwu' => '****',
// 'shangmenyuanjiao' => '****',
// 'naliyouxiaojie' => '*****',
// 'yezhushuju' => '****',
// 'diangoushuju' => '****',
// 'kuaidimiandanziliao' => '******',
// 'kuaidimiandanshuju' => '******',
// 'dianshigouwushuju' => '******',
// 'baojianpinshuju' => '*****',
// 'chezhushuju' => '****',
// 'yezhuziyuan' => '****',
// 'chezhuziyuan' => '****',
// 'wanggoushuju' => '****',
// 'guminshuju' => '****',
// 'chezhuziliao' => '****',
// );
// $keys = array_keys($array);
if (in_array(Pinyin::getPinyin('简直了'),$keys)) {
echo 1;
}else{
echo 2;
}
return 0;
}
}
This diff could not be displayed because it is too large.
......@@ -10,4 +10,21 @@ use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function isAppleClient()
{
$ua = request()->header('user-agent');
if (strpos($ua, 'iPhone') || strpos($ua, 'iPad') || strpos($ua,'Mac OS X')) {
return true;
}
return false;
}
public function getClientTerminal()
{
$ua = request()->header('user-agent');
return 'ios';
}
}
......
<?php
namespace App\Http\Controllers\V1;
use App\Http\Controllers\Controller;
use App\Models\Membership;
use Illuminate\Http\Request;
use Jiannei\Response\Laravel\Support\Facades\Response;
class MembershipController extends Controller
{
/**
* Display a listing of the resource.
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
$membership = Membership::query()->where('state',1);
// 获取会员介绍页内容
if ($this->isAppleClient()){
$membership = $membership->where('terminal',2);
}else{
$membership = $membership->where('terminal',1);
}
$membership = $membership->first();
$membership->bg_images = $membership->getImage();
$membership->goods_list = $membership->getMembershipGoods()->get();
return Response::success($membership);
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
......@@ -3,7 +3,13 @@
namespace App\Http\Controllers\V1;
use App\Http\Controllers\Controller;
use App\Models\MembershipGood;
use App\Models\Order;
use App\Models\OrderGood;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Jiannei\Response\Laravel\Support\Facades\Response;
......@@ -11,27 +17,104 @@ class OrderController extends Controller
{
public function index(Request $request)
{
$validator = Validator::make($request->all(),[
}
public function store(Request $request)
{
$data = $request->all();
$validator = Validator::make($data,[
'goods_id' => 'required|integer',
'source' => 'required|string',
]);
if ($validator->fails()){
return Response::fail('缺少参数',500,$validator->errors());
if ($validator->fails()) return Response::fail('缺少参数',500,$validator->errors());
$user_id = Auth::user()->getAuthIdentifier();
$order = $this->build($user_id, $data['goods_id'], $this->getClientTerminal());
return Response::success($order);
}
public function show($id)
{
}
public function store(Request $request)
/**
* 创建订单
* @param $user_id
* @param $member_id
* @param $source
* @param $number = 1
* @return string $order_sn
*/
public function build($user_id, $member_id, $source, $number = 1)
{
$validator = Validator::make($request->all(),[
'goods_id' => 'required|integer',
'source' => 'required|string',
]);
try{
return DB::transaction(function ()use ($user_id, $member_id, $source, $number){
// 获取商品信息
$membership_good = MembershipGood::query()->where('id',$member_id)->first();
$membership = $membership_good->membership()->first();
// 实付金额 = 商品金额
$pay_amount = $membership_good->price * $number;
// 创建订单
$order = new Order();
$order_sn = $order::get_sn('osn');
$order->order_sn = $order_sn;
$order->user_id = $user_id;
$order->pay_amount = $pay_amount;
$order->description = '一言会员' . $membership_good->limit_days . $membership_good->limit_unit;
$order->goods_amount = $membership_good->price;
$order->status = Order::UNPAID;
$order->source = $source;
if ($validator->fails()){
return Response::fail('',500,$validator->errors());
$order->save();
$order_good = new OrderGood();
$order_good->order_sn = $order_sn;
$order_good->goods_id = $member_id;
$order_good->goods_type = OrderGood::MemberShip;
$order_good->goods_name = $membership_good->limit_days . $membership_good->limit_unit;
$order_good->goods_image = $membership->getSingleImage();
$order_good->goods_price = $membership_good->price;
$order_good->goods_number = $number;
$order_good->save();
$order->goods = $order_good;
// todo 超时处理,建议给Job处理
// if ($pay_amount == 0) { //0元购就不执行回调了
// $this->freePay($order);
// }
return $order;
});
}catch (\Exception $exception){
return Response::fail('', 500, $exception->getMessage());
}
}
public function freePay($order)
{
$order = Order::query()->find($order->id);
if ($order->status < Order::PAID){
$order->status = Order::PAID;
$order->pay_type = '';
$order->pay_time = Carbon::now();
if ($order->save()){
// 执行一些本来属于回调的逻辑
return true;
}
}
return false;
}
}
......
<?php
namespace App\Http\Controllers\V1;
use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Payment\PaymentFactory;
use Illuminate\Http\Request;
use Jiannei\Response\Laravel\Support\Facades\Response;
class PayController extends Controller
{
public function index(Request $request,PaymentFactory $factory)
{
$order_sn = $request->get('order_sn');
$pay_type = $request->get('pay_type');
$order = Order::query()->where('order_sn', $order_sn)->first();
if ($order->status !== Order::UNPAID) return false;
// if ($order->pay_amount <= 0) return $this->paid($order_sn); 0元购应该单独写一套
$payment = $factory->init($pay_type)->prepare($order);
return Response::success($payment);
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
......@@ -5,20 +5,33 @@ namespace App\Models;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;
class Membership extends Model
{
use HasDateTimeFormatter;
protected $table = 'membership';
public function getBgImagesAttribute($value)
protected $guarded = [''];
public function getImage()
{
return explode(',', $value);
return collect(explode(',', $this->bg_images))->map(function ($item){
return Storage::disk('public')->url($item);
});
}
public function getSingleImgAttribute()
public function getSingleImage()
{
$array = explode(',', $this->bg_images);
return $array[0];
return Storage::disk('public')->url($array[0]);
}
public function getMembershipGoods()
{
return $this->hasMany('App\Models\MembershipGood','membership_id');
}
}
......
......@@ -5,10 +5,25 @@ namespace App\Models;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Illuminate\Database\Eloquent\Model;
use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;
class MembershipGood extends Model
class MembershipGood extends Model implements Sortable
{
use HasDateTimeFormatter;
protected $table = 'membership_goods';
protected $guarded = [''];
use SortableTrait;
public $sortable = [
'order_column_name' => 'sn',
'sort_when_creating' => true,
];
public function membership()
{
return $this->belongsTo(Membership::class);
}
}
......
......@@ -3,57 +3,36 @@
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
{
use HasDateTimeFormatter;
use SoftDeletes;
protected $table = 'order';
public function order_goods()
{
return $this->hasOne('App\Models\OrderGood','order_sn');
}
/** 未支付*/
const UNPAID = 100;
/**
* 预创建订单
* @param $member_id
* @param $source
*/
public function build($member_id,$source)
{
// 获取商品信息
$membership = Membership::query()->where('id',$member_id)->first();
/** 用户取消*/
const USER_CANCEL = 101;
// 实付金额 = 商品金额
$pay_amount = $membership->price;
/** 超时取消*/
const TIMEOUT_CANCEL = 102;
// 创建订单
$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;
/** 商户取消*/
const MERCHANT_CANCEL = 102;
$order->save();
/** 已支付*/ // 回调
const PAID = 201;
$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;
/** 已完成*/ // 回调并且业务逻辑(加天数、加销量)执行完毕
const DONE = 204;
$order_good->save();
public function order_goods()
{
return $this->hasOne('App\Models\OrderGood','order_sn');
}
/**
......@@ -61,7 +40,7 @@ class Order extends Model
* @param string $prefix
* @return string
*/
public function get_sn($prefix = '')
static 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;
......
......@@ -11,4 +11,5 @@ class OrderGood extends Model
use HasDateTimeFormatter;
protected $table = 'order_goods';
const MemberShip = 1001;
}
......
<?php
/**
* Created by PhpStorm.
* User: lishuai
* Date: 2022/2/15
* Time: 4:23 PM
*/
namespace App\Payment;
class AliPayment implements PaymentInterface
{
public function prepare()
{
// TODO: Implement prepare() method.
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: lishuai
* Date: 2022/2/15
* Time: 4:25 PM
*/
namespace App\Payment;
class PaymentFactory
{
public function init($pay_type)
{
switch ($pay_type){
case 'alipay':
return new AliPayment();
case 'wechat':
return new WechatPayment();
default:
throw new \Exception('未知的支付方式');
}
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: lishuai
* Date: 2022/2/15
* Time: 4:00 PM
*/
namespace App\Payment;
use App\Models\Order;
interface PaymentInterface
{
/**
* @param $order
* @return array
*/
public function prepare(Order $order);
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: lishuai
* Date: 2022/2/15
* Time: 4:23 PM
*/
namespace App\Payment;
use App\Models\Order;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
class WechatPayment implements PaymentInterface
{
/** 支付接口基础地址 */
const MCH_BASE_URL = 'https://api.mch.weixin.qq.com';
/** APP支付*/
const APP_URL = '/v3/pay/transactions/app';
/** H5支付*/
const H5_URL = '/v3/pay/transactions/h5';
/** App的应用id */
public $appid;
/** 商户身份ID */
public $mchid;
/** 商品描述*/
public $description;
/** 商户订单号*/
public $out_trade_no;
/** 支付回调*/
public $notify_url;
/** 订单金额*/
public $amount;
/** 证书序列号*/
public $serial_no;
/** 商户API私钥*/
// todo 待添加 file:///path/to/merchant/apiclient_key.pem'
public $mch_private_key = '';
public function prepare(Order $order)
{
$body = [
'appid' => env('WECHAT_APPID'),
'mchid' => env('WECHAT_PAY_MCH_ID'),
'description' => $order->description,
'out_trade_no' => $order->order_sn,
'notify_url' => env('WECHAT_PAY_NOTIFY'),
'amount' => [
'total' => $order->pay_amount * 100,
'currency' => 'CNY'
],
];
$timestamp = time();//时间戳
$nonce = self::nonce(32);//随机串
$sign = $this->sign('POST', self::APP_URL, $timestamp, $nonce, json_encode($body));
//设置HTTP头
$token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
env('WECHAT_PAY_MCH_ID'), $nonce, $timestamp, env('WECHAT_PAY_SERIAL_NO'), $sign);
$headers = [
'Accept' => 'application/json, text/plain, application/x-gzip, application/pdf, image/png, image/*;q=0.5',
'User-Agent' => '*/*',
'Content-Type' => 'application/json; charset=utf-8',
'Authorization' => $token,
];
$client = new Client([
'base_uri' => self::MCH_BASE_URL,
'timeout' => 0,
'allow_redirects' => false,
'headers' => $headers
]);
try {
$response = $client->request('POST', self::APP_URL, ['json' => $body]);
dd($prepayid = $response->getBody()->getContents());
} catch (GuzzleException $exception) {
dd($exception->getMessage());
}
return [
'appid' => env('WECHAT_APPID'),
'partnerid' => env('WECHAT_PAY_MCH_ID'),
'prepayid' => $prepayid,
'package' => 'Sign=WXPay',
'noncestr' => $nonce,
'timestamp' => $timestamp,
'sign' => $sign
];
}
public function notify()
{
}
/**
* @param string $http_method "GET"/"POST"
* @param string $url "/v3/certificates"
* @param string $timestamp
* @param string $nonce
* @param string $body "json_encode($body)"
* @return array
*/
public function sign($http_method, $url, $timestamp, $nonce, $body = '')
{
$mch_private_key = openssl_get_privatekey(file_get_contents($this->mch_private_key));//私钥
//构造签名串
$message = implode("\n", [$http_method, $url, $timestamp, $nonce, $body]);
//计算签名值
openssl_sign($message, $signature, $mch_private_key, OPENSSL_ALGO_SHA256);
return base64_encode($signature);
}
/**
* 生成32位随机字符串
* @param int $size - Nonce string length, default is 32.
* @return string - base62 random string.
* @throws
*/
public static function nonce(int $size = 32): string
{
if ($size < 1) {
throw new \InvalidArgumentException('Size must be a positive integer.');
}
return implode('', array_map(static function (string $c): string {
return '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'[ord($c) % 62];
}, str_split(random_bytes($size))));
}
}
......@@ -21,7 +21,6 @@ class CreateMembershipTable extends Migration
$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('视频封面');
......
......@@ -17,6 +17,7 @@ class CreateOrderTable extends Migration
$table->increments('id');
$table->string('order_sn')->index()->default('')->comment('订单号');
$table->unsignedBigInteger('user_id')->index()->comment('用户id');
$table->string('description')->default('')->comment('订单描述');
$table->decimal('pay_amount')->comment('实付金额');
$table->decimal('goods_amount')->comment('商品金额');
$table->unsignedSmallInteger('status')->comment('订单状态:100待付款 101用户取消 102超时取消 103商户取消 201已付款 204已完成');
......@@ -24,6 +25,7 @@ class CreateOrderTable extends Migration
$table->string('source')->comment('来源');
$table->string('pay_number')->default('')->comment('支付交易号');
$table->string('pay_type')->default('')->comment('支付类型');
$table->string('callback')->default('')->comment('回调参数');
$table->timestamp('pay_time')->nullable()->comment('支付时间');
$table->timestamps();
});
......
......@@ -17,6 +17,7 @@ class CreateOrderGoodsTable extends Migration
$table->increments('id');
$table->string('order_sn')->comment('订单编号');
$table->unsignedInteger('goods_id')->comment('商品id');
$table->unsignedInteger('goods_type')->comment('商品类型');
$table->string('goods_name')->default('')->comment('商品名称');
$table->string('goods_image')->default('')->comment('商品封面');
$table->decimal('goods_price')->default('0.00')->comment('商品价格');
......
......@@ -16,17 +16,17 @@ class CreateMembershipGoodsTable extends Migration
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->decimal('price')->default('0.00')->comment('价格');
$table->decimal('line_price')->default('0.00')->comment('划线价格');
$table->integer('limit_days')->default(0)->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->unsignedInteger('visits')->default(0)->comment('访问量');
$table->unsignedInteger('virtual_sales')->default(0)->comment('虚拟销售量');
$table->unsignedInteger('sales')->default(0)->comment('销售量');
$table->unsignedInteger('stocks')->default(0)->comment('库存数量');
$table->timestamps();
});
}
......
<?php
/**
* A helper file for Dcat Admin, to provide autocomplete information to your IDE
*
* This file should not be included in your code, only analyzed by your IDE!
*
* @author jqh <841324345@qq.com>
*/
namespace Dcat\Admin {
use Illuminate\Support\Collection;
/**
* @property Grid\Column|Collection created_at
* @property Grid\Column|Collection detail
* @property Grid\Column|Collection id
* @property Grid\Column|Collection name
* @property Grid\Column|Collection type
* @property Grid\Column|Collection updated_at
* @property Grid\Column|Collection version
* @property Grid\Column|Collection is_enabled
* @property Grid\Column|Collection extension
* @property Grid\Column|Collection icon
* @property Grid\Column|Collection order
* @property Grid\Column|Collection parent_id
* @property Grid\Column|Collection uri
* @property Grid\Column|Collection menu_id
* @property Grid\Column|Collection permission_id
* @property Grid\Column|Collection http_method
* @property Grid\Column|Collection http_path
* @property Grid\Column|Collection slug
* @property Grid\Column|Collection role_id
* @property Grid\Column|Collection user_id
* @property Grid\Column|Collection value
* @property Grid\Column|Collection avatar
* @property Grid\Column|Collection password
* @property Grid\Column|Collection remember_token
* @property Grid\Column|Collection username
* @property Grid\Column|Collection audio_size
* @property Grid\Column|Collection audio_time
* @property Grid\Column|Collection audio_url
* @property Grid\Column|Collection image_size
* @property Grid\Column|Collection image_url
* @property Grid\Column|Collection dynasty
* @property Grid\Column|Collection introduce
* @property Grid\Column|Collection state
* @property Grid\Column|Collection date
* @property Grid\Column|Collection poem_id
* @property Grid\Column|Collection should
* @property Grid\Column|Collection connection
* @property Grid\Column|Collection exception
* @property Grid\Column|Collection failed_at
* @property Grid\Column|Collection payload
* @property Grid\Column|Collection queue
* @property Grid\Column|Collection uuid
* @property Grid\Column|Collection collect
* @property Grid\Column|Collection comment
* @property Grid\Column|Collection content
* @property Grid\Column|Collection duration
* @property Grid\Column|Collection is_check
* @property Grid\Column|Collection is_publish
* @property Grid\Column|Collection is_self
* @property Grid\Column|Collection praise
* @property Grid\Column|Collection share
* @property Grid\Column|Collection size
* @property Grid\Column|Collection intro
* @property Grid\Column|Collection limited_days
* @property Grid\Column|Collection origin_price
* @property Grid\Column|Collection price
* @property Grid\Column|Collection sn
* @property Grid\Column|Collection annotate
* @property Grid\Column|Collection author
* @property Grid\Column|Collection en
* @property Grid\Column|Collection spelling
* @property Grid\Column|Collection gender
* @property Grid\Column|Collection phone
* @property Grid\Column|Collection provider
* @property Grid\Column|Collection provider_id
* @property Grid\Column|Collection cancel_time
* @property Grid\Column|Collection deleted_at
* @property Grid\Column|Collection goods_amount
* @property Grid\Column|Collection is_deleted
* @property Grid\Column|Collection order_sn
* @property Grid\Column|Collection pay_amount
* @property Grid\Column|Collection pay_number
* @property Grid\Column|Collection pay_time
* @property Grid\Column|Collection pay_type
* @property Grid\Column|Collection source
* @property Grid\Column|Collection status
* @property Grid\Column|Collection left_text
* @property Grid\Column|Collection right_text
* @property Grid\Column|Collection subtitle
* @property Grid\Column|Collection email
* @property Grid\Column|Collection token
* @property Grid\Column|Collection abilities
* @property Grid\Column|Collection last_used_at
* @property Grid\Column|Collection tokenable_id
* @property Grid\Column|Collection tokenable_type
* @property Grid\Column|Collection poetry_id
* @property Grid\Column|Collection use_num
* @property Grid\Column|Collection pick_id
* @property Grid\Column|Collection verse_id
* @property Grid\Column|Collection tag_id
* @property Grid\Column|Collection alias
* @property Grid\Column|Collection author_id
* @property Grid\Column|Collection subname
* @property Grid\Column|Collection show_id
* @property Grid\Column|Collection child_id
* @property Grid\Column|Collection comment_num
* @property Grid\Column|Collection fav_num
* @property Grid\Column|Collection praise_num
* @property Grid\Column|Collection view_num
* @property Grid\Column|Collection email_verified_at
* @property Grid\Column|Collection stanza
* @property Grid\Column|Collection is_horizontal
* @property Grid\Column|Collection video_size
* @property Grid\Column|Collection video_time
* @property Grid\Column|Collection video_url
* @property Grid\Column|Collection bg_music
* @property Grid\Column|Collection bg_type
* @property Grid\Column|Collection bg_url
* @property Grid\Column|Collection bgm_url
* @property Grid\Column|Collection font_size
* @property Grid\Column|Collection left
* @property Grid\Column|Collection opacity
* @property Grid\Column|Collection text_bg_color
* @property Grid\Column|Collection text_color
* @property Grid\Column|Collection top
*
* @method Grid\Column|Collection created_at(string $label = null)
* @method Grid\Column|Collection detail(string $label = null)
* @method Grid\Column|Collection id(string $label = null)
* @method Grid\Column|Collection name(string $label = null)
* @method Grid\Column|Collection type(string $label = null)
* @method Grid\Column|Collection updated_at(string $label = null)
* @method Grid\Column|Collection version(string $label = null)
* @method Grid\Column|Collection is_enabled(string $label = null)
* @method Grid\Column|Collection extension(string $label = null)
* @method Grid\Column|Collection icon(string $label = null)
* @method Grid\Column|Collection order(string $label = null)
* @method Grid\Column|Collection parent_id(string $label = null)
* @method Grid\Column|Collection uri(string $label = null)
* @method Grid\Column|Collection menu_id(string $label = null)
* @method Grid\Column|Collection permission_id(string $label = null)
* @method Grid\Column|Collection http_method(string $label = null)
* @method Grid\Column|Collection http_path(string $label = null)
* @method Grid\Column|Collection slug(string $label = null)
* @method Grid\Column|Collection role_id(string $label = null)
* @method Grid\Column|Collection user_id(string $label = null)
* @method Grid\Column|Collection value(string $label = null)
* @method Grid\Column|Collection avatar(string $label = null)
* @method Grid\Column|Collection password(string $label = null)
* @method Grid\Column|Collection remember_token(string $label = null)
* @method Grid\Column|Collection username(string $label = null)
* @method Grid\Column|Collection audio_size(string $label = null)
* @method Grid\Column|Collection audio_time(string $label = null)
* @method Grid\Column|Collection audio_url(string $label = null)
* @method Grid\Column|Collection image_size(string $label = null)
* @method Grid\Column|Collection image_url(string $label = null)
* @method Grid\Column|Collection dynasty(string $label = null)
* @method Grid\Column|Collection introduce(string $label = null)
* @method Grid\Column|Collection state(string $label = null)
* @method Grid\Column|Collection date(string $label = null)
* @method Grid\Column|Collection poem_id(string $label = null)
* @method Grid\Column|Collection should(string $label = null)
* @method Grid\Column|Collection connection(string $label = null)
* @method Grid\Column|Collection exception(string $label = null)
* @method Grid\Column|Collection failed_at(string $label = null)
* @method Grid\Column|Collection payload(string $label = null)
* @method Grid\Column|Collection queue(string $label = null)
* @method Grid\Column|Collection uuid(string $label = null)
* @method Grid\Column|Collection collect(string $label = null)
* @method Grid\Column|Collection comment(string $label = null)
* @method Grid\Column|Collection content(string $label = null)
* @method Grid\Column|Collection duration(string $label = null)
* @method Grid\Column|Collection is_check(string $label = null)
* @method Grid\Column|Collection is_publish(string $label = null)
* @method Grid\Column|Collection is_self(string $label = null)
* @method Grid\Column|Collection praise(string $label = null)
* @method Grid\Column|Collection share(string $label = null)
* @method Grid\Column|Collection size(string $label = null)
* @method Grid\Column|Collection intro(string $label = null)
* @method Grid\Column|Collection limited_days(string $label = null)
* @method Grid\Column|Collection origin_price(string $label = null)
* @method Grid\Column|Collection price(string $label = null)
* @method Grid\Column|Collection sn(string $label = null)
* @method Grid\Column|Collection annotate(string $label = null)
* @method Grid\Column|Collection author(string $label = null)
* @method Grid\Column|Collection en(string $label = null)
* @method Grid\Column|Collection spelling(string $label = null)
* @method Grid\Column|Collection gender(string $label = null)
* @method Grid\Column|Collection phone(string $label = null)
* @method Grid\Column|Collection provider(string $label = null)
* @method Grid\Column|Collection provider_id(string $label = null)
* @method Grid\Column|Collection cancel_time(string $label = null)
* @method Grid\Column|Collection deleted_at(string $label = null)
* @method Grid\Column|Collection goods_amount(string $label = null)
* @method Grid\Column|Collection is_deleted(string $label = null)
* @method Grid\Column|Collection order_sn(string $label = null)
* @method Grid\Column|Collection pay_amount(string $label = null)
* @method Grid\Column|Collection pay_number(string $label = null)
* @method Grid\Column|Collection pay_time(string $label = null)
* @method Grid\Column|Collection pay_type(string $label = null)
* @method Grid\Column|Collection source(string $label = null)
* @method Grid\Column|Collection status(string $label = null)
* @method Grid\Column|Collection left_text(string $label = null)
* @method Grid\Column|Collection right_text(string $label = null)
* @method Grid\Column|Collection subtitle(string $label = null)
* @method Grid\Column|Collection email(string $label = null)
* @method Grid\Column|Collection token(string $label = null)
* @method Grid\Column|Collection abilities(string $label = null)
* @method Grid\Column|Collection last_used_at(string $label = null)
* @method Grid\Column|Collection tokenable_id(string $label = null)
* @method Grid\Column|Collection tokenable_type(string $label = null)
* @method Grid\Column|Collection poetry_id(string $label = null)
* @method Grid\Column|Collection use_num(string $label = null)
* @method Grid\Column|Collection pick_id(string $label = null)
* @method Grid\Column|Collection verse_id(string $label = null)
* @method Grid\Column|Collection tag_id(string $label = null)
* @method Grid\Column|Collection alias(string $label = null)
* @method Grid\Column|Collection author_id(string $label = null)
* @method Grid\Column|Collection subname(string $label = null)
* @method Grid\Column|Collection show_id(string $label = null)
* @method Grid\Column|Collection child_id(string $label = null)
* @method Grid\Column|Collection comment_num(string $label = null)
* @method Grid\Column|Collection fav_num(string $label = null)
* @method Grid\Column|Collection praise_num(string $label = null)
* @method Grid\Column|Collection view_num(string $label = null)
* @method Grid\Column|Collection email_verified_at(string $label = null)
* @method Grid\Column|Collection stanza(string $label = null)
* @method Grid\Column|Collection is_horizontal(string $label = null)
* @method Grid\Column|Collection video_size(string $label = null)
* @method Grid\Column|Collection video_time(string $label = null)
* @method Grid\Column|Collection video_url(string $label = null)
* @method Grid\Column|Collection bg_music(string $label = null)
* @method Grid\Column|Collection bg_type(string $label = null)
* @method Grid\Column|Collection bg_url(string $label = null)
* @method Grid\Column|Collection bgm_url(string $label = null)
* @method Grid\Column|Collection font_size(string $label = null)
* @method Grid\Column|Collection left(string $label = null)
* @method Grid\Column|Collection opacity(string $label = null)
* @method Grid\Column|Collection text_bg_color(string $label = null)
* @method Grid\Column|Collection text_color(string $label = null)
* @method Grid\Column|Collection top(string $label = null)
*/
class Grid {}
class MiniGrid extends Grid {}
/**
* @property Show\Field|Collection created_at
* @property Show\Field|Collection detail
* @property Show\Field|Collection id
* @property Show\Field|Collection name
* @property Show\Field|Collection type
* @property Show\Field|Collection updated_at
* @property Show\Field|Collection version
* @property Show\Field|Collection is_enabled
* @property Show\Field|Collection extension
* @property Show\Field|Collection icon
* @property Show\Field|Collection order
* @property Show\Field|Collection parent_id
* @property Show\Field|Collection uri
* @property Show\Field|Collection menu_id
* @property Show\Field|Collection permission_id
* @property Show\Field|Collection http_method
* @property Show\Field|Collection http_path
* @property Show\Field|Collection slug
* @property Show\Field|Collection role_id
* @property Show\Field|Collection user_id
* @property Show\Field|Collection value
* @property Show\Field|Collection avatar
* @property Show\Field|Collection password
* @property Show\Field|Collection remember_token
* @property Show\Field|Collection username
* @property Show\Field|Collection audio_size
* @property Show\Field|Collection audio_time
* @property Show\Field|Collection audio_url
* @property Show\Field|Collection image_size
* @property Show\Field|Collection image_url
* @property Show\Field|Collection dynasty
* @property Show\Field|Collection introduce
* @property Show\Field|Collection state
* @property Show\Field|Collection date
* @property Show\Field|Collection poem_id
* @property Show\Field|Collection should
* @property Show\Field|Collection connection
* @property Show\Field|Collection exception
* @property Show\Field|Collection failed_at
* @property Show\Field|Collection payload
* @property Show\Field|Collection queue
* @property Show\Field|Collection uuid
* @property Show\Field|Collection collect
* @property Show\Field|Collection comment
* @property Show\Field|Collection content
* @property Show\Field|Collection duration
* @property Show\Field|Collection is_check
* @property Show\Field|Collection is_publish
* @property Show\Field|Collection is_self
* @property Show\Field|Collection praise
* @property Show\Field|Collection share
* @property Show\Field|Collection size
* @property Show\Field|Collection intro
* @property Show\Field|Collection limited_days
* @property Show\Field|Collection origin_price
* @property Show\Field|Collection price
* @property Show\Field|Collection sn
* @property Show\Field|Collection annotate
* @property Show\Field|Collection author
* @property Show\Field|Collection en
* @property Show\Field|Collection spelling
* @property Show\Field|Collection gender
* @property Show\Field|Collection phone
* @property Show\Field|Collection provider
* @property Show\Field|Collection provider_id
* @property Show\Field|Collection cancel_time
* @property Show\Field|Collection deleted_at
* @property Show\Field|Collection goods_amount
* @property Show\Field|Collection is_deleted
* @property Show\Field|Collection order_sn
* @property Show\Field|Collection pay_amount
* @property Show\Field|Collection pay_number
* @property Show\Field|Collection pay_time
* @property Show\Field|Collection pay_type
* @property Show\Field|Collection source
* @property Show\Field|Collection status
* @property Show\Field|Collection left_text
* @property Show\Field|Collection right_text
* @property Show\Field|Collection subtitle
* @property Show\Field|Collection email
* @property Show\Field|Collection token
* @property Show\Field|Collection abilities
* @property Show\Field|Collection last_used_at
* @property Show\Field|Collection tokenable_id
* @property Show\Field|Collection tokenable_type
* @property Show\Field|Collection poetry_id
* @property Show\Field|Collection use_num
* @property Show\Field|Collection pick_id
* @property Show\Field|Collection verse_id
* @property Show\Field|Collection tag_id
* @property Show\Field|Collection alias
* @property Show\Field|Collection author_id
* @property Show\Field|Collection subname
* @property Show\Field|Collection show_id
* @property Show\Field|Collection child_id
* @property Show\Field|Collection comment_num
* @property Show\Field|Collection fav_num
* @property Show\Field|Collection praise_num
* @property Show\Field|Collection view_num
* @property Show\Field|Collection email_verified_at
* @property Show\Field|Collection stanza
* @property Show\Field|Collection is_horizontal
* @property Show\Field|Collection video_size
* @property Show\Field|Collection video_time
* @property Show\Field|Collection video_url
* @property Show\Field|Collection bg_music
* @property Show\Field|Collection bg_type
* @property Show\Field|Collection bg_url
* @property Show\Field|Collection bgm_url
* @property Show\Field|Collection font_size
* @property Show\Field|Collection left
* @property Show\Field|Collection opacity
* @property Show\Field|Collection text_bg_color
* @property Show\Field|Collection text_color
* @property Show\Field|Collection top
*
* @method Show\Field|Collection created_at(string $label = null)
* @method Show\Field|Collection detail(string $label = null)
* @method Show\Field|Collection id(string $label = null)
* @method Show\Field|Collection name(string $label = null)
* @method Show\Field|Collection type(string $label = null)
* @method Show\Field|Collection updated_at(string $label = null)
* @method Show\Field|Collection version(string $label = null)
* @method Show\Field|Collection is_enabled(string $label = null)
* @method Show\Field|Collection extension(string $label = null)
* @method Show\Field|Collection icon(string $label = null)
* @method Show\Field|Collection order(string $label = null)
* @method Show\Field|Collection parent_id(string $label = null)
* @method Show\Field|Collection uri(string $label = null)
* @method Show\Field|Collection menu_id(string $label = null)
* @method Show\Field|Collection permission_id(string $label = null)
* @method Show\Field|Collection http_method(string $label = null)
* @method Show\Field|Collection http_path(string $label = null)
* @method Show\Field|Collection slug(string $label = null)
* @method Show\Field|Collection role_id(string $label = null)
* @method Show\Field|Collection user_id(string $label = null)
* @method Show\Field|Collection value(string $label = null)
* @method Show\Field|Collection avatar(string $label = null)
* @method Show\Field|Collection password(string $label = null)
* @method Show\Field|Collection remember_token(string $label = null)
* @method Show\Field|Collection username(string $label = null)
* @method Show\Field|Collection audio_size(string $label = null)
* @method Show\Field|Collection audio_time(string $label = null)
* @method Show\Field|Collection audio_url(string $label = null)
* @method Show\Field|Collection image_size(string $label = null)
* @method Show\Field|Collection image_url(string $label = null)
* @method Show\Field|Collection dynasty(string $label = null)
* @method Show\Field|Collection introduce(string $label = null)
* @method Show\Field|Collection state(string $label = null)
* @method Show\Field|Collection date(string $label = null)
* @method Show\Field|Collection poem_id(string $label = null)
* @method Show\Field|Collection should(string $label = null)
* @method Show\Field|Collection connection(string $label = null)
* @method Show\Field|Collection exception(string $label = null)
* @method Show\Field|Collection failed_at(string $label = null)
* @method Show\Field|Collection payload(string $label = null)
* @method Show\Field|Collection queue(string $label = null)
* @method Show\Field|Collection uuid(string $label = null)
* @method Show\Field|Collection collect(string $label = null)
* @method Show\Field|Collection comment(string $label = null)
* @method Show\Field|Collection content(string $label = null)
* @method Show\Field|Collection duration(string $label = null)
* @method Show\Field|Collection is_check(string $label = null)
* @method Show\Field|Collection is_publish(string $label = null)
* @method Show\Field|Collection is_self(string $label = null)
* @method Show\Field|Collection praise(string $label = null)
* @method Show\Field|Collection share(string $label = null)
* @method Show\Field|Collection size(string $label = null)
* @method Show\Field|Collection intro(string $label = null)
* @method Show\Field|Collection limited_days(string $label = null)
* @method Show\Field|Collection origin_price(string $label = null)
* @method Show\Field|Collection price(string $label = null)
* @method Show\Field|Collection sn(string $label = null)
* @method Show\Field|Collection annotate(string $label = null)
* @method Show\Field|Collection author(string $label = null)
* @method Show\Field|Collection en(string $label = null)
* @method Show\Field|Collection spelling(string $label = null)
* @method Show\Field|Collection gender(string $label = null)
* @method Show\Field|Collection phone(string $label = null)
* @method Show\Field|Collection provider(string $label = null)
* @method Show\Field|Collection provider_id(string $label = null)
* @method Show\Field|Collection cancel_time(string $label = null)
* @method Show\Field|Collection deleted_at(string $label = null)
* @method Show\Field|Collection goods_amount(string $label = null)
* @method Show\Field|Collection is_deleted(string $label = null)
* @method Show\Field|Collection order_sn(string $label = null)
* @method Show\Field|Collection pay_amount(string $label = null)
* @method Show\Field|Collection pay_number(string $label = null)
* @method Show\Field|Collection pay_time(string $label = null)
* @method Show\Field|Collection pay_type(string $label = null)
* @method Show\Field|Collection source(string $label = null)
* @method Show\Field|Collection status(string $label = null)
* @method Show\Field|Collection left_text(string $label = null)
* @method Show\Field|Collection right_text(string $label = null)
* @method Show\Field|Collection subtitle(string $label = null)
* @method Show\Field|Collection email(string $label = null)
* @method Show\Field|Collection token(string $label = null)
* @method Show\Field|Collection abilities(string $label = null)
* @method Show\Field|Collection last_used_at(string $label = null)
* @method Show\Field|Collection tokenable_id(string $label = null)
* @method Show\Field|Collection tokenable_type(string $label = null)
* @method Show\Field|Collection poetry_id(string $label = null)
* @method Show\Field|Collection use_num(string $label = null)
* @method Show\Field|Collection pick_id(string $label = null)
* @method Show\Field|Collection verse_id(string $label = null)
* @method Show\Field|Collection tag_id(string $label = null)
* @method Show\Field|Collection alias(string $label = null)
* @method Show\Field|Collection author_id(string $label = null)
* @method Show\Field|Collection subname(string $label = null)
* @method Show\Field|Collection show_id(string $label = null)
* @method Show\Field|Collection child_id(string $label = null)
* @method Show\Field|Collection comment_num(string $label = null)
* @method Show\Field|Collection fav_num(string $label = null)
* @method Show\Field|Collection praise_num(string $label = null)
* @method Show\Field|Collection view_num(string $label = null)
* @method Show\Field|Collection email_verified_at(string $label = null)
* @method Show\Field|Collection stanza(string $label = null)
* @method Show\Field|Collection is_horizontal(string $label = null)
* @method Show\Field|Collection video_size(string $label = null)
* @method Show\Field|Collection video_time(string $label = null)
* @method Show\Field|Collection video_url(string $label = null)
* @method Show\Field|Collection bg_music(string $label = null)
* @method Show\Field|Collection bg_type(string $label = null)
* @method Show\Field|Collection bg_url(string $label = null)
* @method Show\Field|Collection bgm_url(string $label = null)
* @method Show\Field|Collection font_size(string $label = null)
* @method Show\Field|Collection left(string $label = null)
* @method Show\Field|Collection opacity(string $label = null)
* @method Show\Field|Collection text_bg_color(string $label = null)
* @method Show\Field|Collection text_color(string $label = null)
* @method Show\Field|Collection top(string $label = null)
*/
class Show {}
/**
*/
class Form {}
}
namespace Dcat\Admin\Grid {
/**
*/
class Column {}
/**
*/
class Filter {}
}
namespace Dcat\Admin\Show {
/**
*/
class Field {}
}
.extension-demo {
font-size: 1.3rem;
cursor: pointer;
}
.dengje-gallery-group {
position: relative;
margin: 5%;
}
.dengje-gallery-group.multiple .gallery-img-wrapper.bg-left {
top: 5%;
left: -5%;
-webkit-transform: rotate(-5deg);
-moz-transform: rotate(-5deg);
-o-transform: rotate(-5deg);
-ms-transform: rotate(-5deg);
transform: rotate(-5deg);
}
.dengje-gallery-group.multiple .gallery-img-wrapper.bg-left:before {
content: "";
width: 100%;
height: 100%;
background: #eff4de;
display: block;
}
.dengje-gallery-group.multiple .gallery-img-wrapper.bg-right {
top: 5%;
left: 5%;
-webkit-transform: rotate(5deg);
-moz-transform: rotate(5deg);
-o-transform: rotate(5deg);
-ms-transform: rotate(5deg);
transform: rotate(5deg);
}
.dengje-gallery-group.multiple .gallery-img-wrapper.bg-right:before {
content: "";
width: 100%;
height: 100%;
background: #768590;
display: block;
}
.dengje-gallery-group .gallery-img-wrapper {
padding: 3%;
background: #fff;
height: 100%;
width: 100%;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
-webkit-box-shadow: .2em .2em .5em rgb(0 0 0 / 30%);
-moz-box-shadow: .2em .2em .5em rgba(0, 0, 0, 0.3);
box-shadow: .2em .2em .5em rgb(0 0 0 / 30%);
}
.dengje-gallery-group .gallery-img-wrapper > img {
max-width: 100%;
max-height: 100%;
}
.dengje-gallery-group .bg-multi {
display: none;
}
.dengje-gallery-group.multiple .bg-multi {
display: block;
}
.hide {
display: none;
}
/*!
* Viewer.js v1.5.0
* https://fengyuanchen.github.io/viewerjs
*
* Copyright 2015-present Chen Fengyuan
* Released under the MIT license
*
* Date: 2019-11-23T05:10:21.757Z
*/
.viewer-zoom-in::before,
.viewer-zoom-out::before,
.viewer-one-to-one::before,
.viewer-reset::before,
.viewer-prev::before,
.viewer-play::before,
.viewer-next::before,
.viewer-rotate-left::before,
.viewer-rotate-right::before,
.viewer-flip-horizontal::before,
.viewer-flip-vertical::before,
.viewer-fullscreen::before,
.viewer-fullscreen-exit::before,
.viewer-close::before {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAAAUCAYAAABWOyJDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAQPSURBVHic7Zs/iFxVFMa/0U2UaJGksUgnIVhYxVhpjDbZCBmLdAYECxsRFBTUamcXUiSNncgKQbSxsxH8gzAP3FU2jY0kKKJNiiiIghFlccnP4p3nPCdv3p9778vsLOcHB2bfveeb7955c3jvvNkBIMdxnD64a94GHMfZu3iBcRynN7zAOI7TG15gHCeeNUkr8zaxG2lbYDYsdgMbktBsP03jdQwljSXdtBhLOmtjowC9Mg9L+knSlcD8TNKpSA9lBpK2JF2VdDSR5n5J64m0qli399hNFMUlpshQii5jbXTbHGviB0nLNeNDSd9VO4A2UdB2fp+x0eCnaXxWXGA2X0au/3HgN9P4LFCjIANOJdrLr0zzZ+BEpNYDwKbpnQMeAw4m8HjQtM6Z9qa917zPQwFr3M5KgA6J5rTJCdFZJj9/lyvGhsDvwFNVuV2MhhjrK6b9bFiE+j1r87eBl4HDwCF7/U/k+ofAX5b/EXBv5JoLMuILzf3Ap6Z3EzgdqHMCuF7hcQf4HDgeoHnccncqdK/TvSDWffFXI/exICY/xZyqc6XLWF1UFZna4gJ7q8BsRvgd2/xXpo6P+D9dfT7PpECtA3cnWPM0GXGFZh/wgWltA+cDNC7X+AP4GzjZQe+k5dRxuYPeiuXU7e1qwLpDz7dFjXKRaSwuMLvAlG8zZlG+YmiK1HoFqT7wP2z+4Q45TfEGcMt01xLoNZEBTwRqD4BLpnMLeC1A41UmVxsXgXeBayV/Wx20rpTyrpnWRft7p6O/FdqzGrDukPNtkaMoMo3FBdBSQMOnYBCReyf05s126fU9ytfX98+mY54Kxnp7S9K3kj6U9KYdG0h6UdLbkh7poFXMfUnSOyVvL0h6VtIXHbS6nOP+s/Zm9mvyXW1uuC9ohZ72E9uDmXWLJOB1GxsH+DxPftsB8B6wlGDN02TAkxG6+4D3TWsbeC5CS8CDFce+AW500LhhOW2020TRjK3b21HEmgti9m0RonxbdMZeVzV+/4tF3cBpP7E9mKHNL5q8h5g0eYsCMQz0epq8gQrwMXAgcs0FGXGFRcB9wCemF9PkbYqM/Bas7fxLwNeJPdTdpo4itQti8lPMqTpXuozVRVXPpbHI3KkNTB1NfkL81j2mvhDp91HgV9MKuRIqrykj3WPq4rHyL+axj8/qGPmTqi6F9YDlHOvJU6oYcTsh/TYSzWmTE6JT19CtLTJt32D6CmHe0eQn1O8z5AXgT4sx4Vcu0/EQecMydB8z0hUWkTd2t4CrwNEePqMBcAR4mrBbwyXLPWJa8zrXmmLEhNBmfpkuY2102xxrih+pb+ieAb6vGhuA97UcJ5KR8gZ77K+99xxeYBzH6Q3/Z0fHcXrDC4zjOL3hBcZxnN74F+zlvXFWXF9PAAAAAElFTkSuQmCC');
background-repeat: no-repeat;
background-size: 280px;
color: transparent;
display: block;
font-size: 0;
height: 20px;
line-height: 0;
width: 20px;
}
.viewer-zoom-in::before {
background-position: 0 0;
content: 'Zoom In';
}
.viewer-zoom-out::before {
background-position: -20px 0;
content: 'Zoom Out';
}
.viewer-one-to-one::before {
background-position: -40px 0;
content: 'One to One';
}
.viewer-reset::before {
background-position: -60px 0;
content: 'Reset';
}
.viewer-prev::before {
background-position: -80px 0;
content: 'Previous';
}
.viewer-play::before {
background-position: -100px 0;
content: 'Play';
}
.viewer-next::before {
background-position: -120px 0;
content: 'Next';
}
.viewer-rotate-left::before {
background-position: -140px 0;
content: 'Rotate Left';
}
.viewer-rotate-right::before {
background-position: -160px 0;
content: 'Rotate Right';
}
.viewer-flip-horizontal::before {
background-position: -180px 0;
content: 'Flip Horizontal';
}
.viewer-flip-vertical::before {
background-position: -200px 0;
content: 'Flip Vertical';
}
.viewer-fullscreen::before {
background-position: -220px 0;
content: 'Enter Full Screen';
}
.viewer-fullscreen-exit::before {
background-position: -240px 0;
content: 'Exit Full Screen';
}
.viewer-close::before {
background-position: -260px 0;
content: 'Close';
}
.viewer-container {
bottom: 0;
direction: ltr;
font-size: 0;
left: 0;
line-height: 0;
overflow: hidden;
position: absolute;
right: 0;
-webkit-tap-highlight-color: transparent;
top: 0;
-ms-touch-action: none;
touch-action: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.viewer-container::-moz-selection,
.viewer-container *::-moz-selection {
background-color: transparent;
}
.viewer-container::selection,
.viewer-container *::selection {
background-color: transparent;
}
.viewer-container img {
display: block;
height: auto;
max-height: none !important;
max-width: none !important;
min-height: 0 !important;
min-width: 0 !important;
width: 100%;
}
.viewer-canvas {
bottom: 0;
left: 0;
overflow: hidden;
position: absolute;
right: 0;
top: 0;
}
.viewer-canvas > img {
height: auto;
margin: 15px auto;
max-width: 90% !important;
width: auto;
}
.viewer-footer {
bottom: 0;
left: 0;
overflow: hidden;
position: absolute;
right: 0;
text-align: center;
}
.viewer-navbar {
background-color: rgba(0, 0, 0, 0.5);
overflow: hidden;
}
.viewer-list {
-webkit-box-sizing: content-box;
box-sizing: content-box;
height: 50px;
margin: 0;
overflow: hidden;
padding: 1px 0;
}
.viewer-list > li {
color: transparent;
cursor: pointer;
float: left;
font-size: 0;
height: 50px;
line-height: 0;
opacity: 0.5;
overflow: hidden;
-webkit-transition: opacity 0.15s;
transition: opacity 0.15s;
width: 30px;
}
.viewer-list > li:hover {
opacity: 0.75;
}
.viewer-list > li + li {
margin-left: 1px;
}
.viewer-list > .viewer-loading {
position: relative;
}
.viewer-list > .viewer-loading::after {
border-width: 2px;
height: 20px;
margin-left: -10px;
margin-top: -10px;
width: 20px;
}
.viewer-list > .viewer-active,
.viewer-list > .viewer-active:hover {
opacity: 1;
}
.viewer-player {
background-color: #000;
bottom: 0;
cursor: none;
display: none;
left: 0;
position: absolute;
right: 0;
top: 0;
}
.viewer-player > img {
left: 0;
position: absolute;
top: 0;
}
.viewer-toolbar > ul {
display: inline-block;
margin: 0 auto 5px;
overflow: hidden;
padding: 3px 0;
}
.viewer-toolbar > ul > li {
background-color: rgba(0, 0, 0, 0.5);
border-radius: 50%;
cursor: pointer;
float: left;
height: 24px;
overflow: hidden;
-webkit-transition: background-color 0.15s;
transition: background-color 0.15s;
width: 24px;
}
.viewer-toolbar > ul > li:hover {
background-color: rgba(0, 0, 0, 0.8);
}
.viewer-toolbar > ul > li::before {
margin: 2px;
}
.viewer-toolbar > ul > li + li {
margin-left: 1px;
}
.viewer-toolbar > ul > .viewer-small {
height: 18px;
margin-bottom: 3px;
margin-top: 3px;
width: 18px;
}
.viewer-toolbar > ul > .viewer-small::before {
margin: -1px;
}
.viewer-toolbar > ul > .viewer-large {
height: 30px;
margin-bottom: -3px;
margin-top: -3px;
width: 30px;
}
.viewer-toolbar > ul > .viewer-large::before {
margin: 5px;
}
.viewer-tooltip {
background-color: rgba(0, 0, 0, 0.8);
border-radius: 10px;
color: #fff;
display: none;
font-size: 12px;
height: 20px;
left: 50%;
line-height: 20px;
margin-left: -25px;
margin-top: -10px;
position: absolute;
text-align: center;
top: 50%;
width: 50px;
}
.viewer-title {
color: #ccc;
display: inline-block;
font-size: 12px;
line-height: 1;
margin: 0 5% 5px;
max-width: 90%;
opacity: 0.8;
overflow: hidden;
text-overflow: ellipsis;
-webkit-transition: opacity 0.15s;
transition: opacity 0.15s;
white-space: nowrap;
}
.viewer-title:hover {
opacity: 1;
}
.viewer-button {
background-color: rgba(0, 0, 0, 0.5);
border-radius: 50%;
cursor: pointer;
height: 80px;
overflow: hidden;
position: absolute;
right: -40px;
top: -40px;
-webkit-transition: background-color 0.15s;
transition: background-color 0.15s;
width: 80px;
}
.viewer-button:focus,
.viewer-button:hover {
background-color: rgba(0, 0, 0, 0.8);
}
.viewer-button::before {
bottom: 15px;
left: 15px;
position: absolute;
}
.viewer-fixed {
position: fixed;
}
.viewer-open {
overflow: hidden;
}
.viewer-show {
display: block;
}
.viewer-hide {
display: none;
}
.viewer-backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
.viewer-invisible {
visibility: hidden;
}
.viewer-move {
cursor: move;
cursor: -webkit-grab;
cursor: grab;
}
.viewer-fade {
opacity: 0;
}
.viewer-in {
opacity: 1;
}
.viewer-transition {
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
@-webkit-keyframes viewer-spinner {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes viewer-spinner {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.viewer-loading::after {
-webkit-animation: viewer-spinner 1s linear infinite;
animation: viewer-spinner 1s linear infinite;
border: 4px solid rgba(255, 255, 255, 0.1);
border-left-color: rgba(255, 255, 255, 0.5);
border-radius: 50%;
content: '';
display: inline-block;
height: 40px;
left: 50%;
margin-left: -20px;
margin-top: -20px;
position: absolute;
top: 50%;
width: 40px;
z-index: 1;
}
@media (max-width: 767px) {
.viewer-hide-xs-down {
display: none;
}
}
@media (max-width: 991px) {
.viewer-hide-sm-down {
display: none;
}
}
@media (max-width: 1199px) {
.viewer-hide-md-down {
display: none;
}
}
This diff could not be displayed because it is too large.
......@@ -7,7 +7,6 @@ return [
'fields' => [
'name' => '会员名称',
'origin_price' => '原价(分)',
'limited_days' => '有效天数',
'intro' => '简介',
'state' => '状态',
'membership_id' => '会员id',
......
<style>
.box-card {
width: 380px;
border: 1px solid rgb(220, 223, 230);
border-radius: 40px;
margin-right: 24px;
padding: 37px 20px;
min-height: 779px;
}
.phone-content {
border: 1px solid rgb(220, 223, 230);
height: 705px;
overflow: hidden;
position: relative;
background: rgb(245, 245, 245);
}
.text {
font-size: 16px;
font-weight: 700;
color: rgb(38, 38, 38);
text-align: center;
position: absolute;
width: 100%;
top: 50px;
box-sizing: border-box;
}
.poem-block {
width: 315px;
height: 330px;
margin: 0;
padding: 0;
position: absolute;
text-align: center;
top: 200px;
left: 10px;
border-radius: 5px;
background: rgba(87, 78, 78, 0.6);
box-shadow: 2px 2px 4px 2px rgba(0, 0, 0, .3);
overflow: hidden;
display: flex;
flex-direction: column;
}
.poem-title {
color: #ffffff;
font-size: 14px;
font-weight: bold;
margin: 10px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.intro-title {
color: #ffffff;
font-size: 14px;
font-weight: bold;
margin: 10px;
text-align: start;
}
.price{
display: flex;
flex-direction: row;
justify-content: flex-start;
}
</style>
<div class="box-card">
<div class="phone-content">
<div class="text">会员页</div>
<img src="{{asset('storage/image/mobile-head.png')}}" alt="" width="338" height="80">
<div style="min-height: 625px;">
<img width="338" height="625" class="bg_img" src="{{asset('storage/images/a5fe2ba2bd71b543cbf4c6fb3968ab64.png')}}">
</div>
<div class="poem-block">
<div class="intro-title">开发者249d42a097c1944e进行了广播推送,这是一条广播</div>
<div class="poem-title">
<div> 连续包月 </div>
<div class="price">
<span> 29 元 </span>
<span> / 月</span>
</div>
<button type="button" class="btn btn-primary">开通</button>
</div>
<div class="poem-title">
<div> 连续包年 </div>
<div class="price">
<span> 299 元 </span>
<span> / 月</span>
</div>
<button type="button" class="btn btn-primary">开通</button>
</div>
<div class="intro-title" style="min-height: 100px">开发者249d42a097c1944e进行了广播推送,这是一条广播</div>
<div class="intro-title" style="text-align: center">服务协议 | 隐私政策 | 恢复购买</div>
</div>
</div>
</div>
<hr>
<button type="button" class="btn btn-primary sync"><i class="feather icon-repeat"></i> 同步基本设置</button>
<script>
Dcat.ready(function () {
var asset = "{{asset('/storage/')}}";
$(document).off('click', '.sync').on('click', '.sync', function () {
let ori_top = 80;
let top = parseInt($('.field_top').val()) + ori_top;
let left = $('.field_left').val();
let font = $('.field_font_size').val();
let content_size = 12 + parseInt(font);
let title_size = 14 + parseInt(font);
let text_color = $('.text_color').val() || 'whitesmoke';
let text_bg_color = $('.text_bg_color').val() || '#5c6bc6';
let opacity = parseInt($('.opacity').val()) / 100;
$('.poem-block').css('top', top + 'px').css('left', left + 'px')
.css('background-color', text_bg_color).css('opacity', opacity);
$('.poem-title').css('font-size', title_size + 'px').css('color', text_color);
$('.poem-content').css('font-size', content_size + 'px').css('color', text_color);
let bg_img_url = $('.bg_img_url').find("input[type='hidden'][name='bg_url']").val();
if (bg_img_url !== '') {
$('.bg_img').attr('src', asset + '/' + bg_img_url).css('display', 'block');
}
let bg_video_url = $('.bg_video_url').find("input[type='hidden'][name='bg_url']").val();
if (bg_video_url !== ''){
$('#bg_video').attr('src', asset + '/' + bg_video_url).css('display', 'block');
let bg_video = document.getElementById('bg_video');
bg_video.autoplay = true;
bg_video.loop = true;
}
let bgm_url = $('.bgm_url').find("input[type='hidden'][name='bgm_url']").val();
if (bgm_url !== ''){
$('#bg_audio').attr('src', asset + '/' + bgm_url);
let bg_audio = document.getElementById('bg_audio');
bg_audio.autoplay = true;
bg_audio.loop = true;
}
})
})
</script>
\ No newline at end of file
<style>
.dengje-gallery-group {
height: {{ $height }}px;
width: {{ $width }}px;
font-size: {{ $width / 12 }};
}
</style>
<div id="{{ $id }}" class="dengje-gallery-group {{ count($src) > 1 ? 'multiple' : '' }}">
<div class="gallery-img-wrapper bg-multi bg-left"></div>
<div class="gallery-img-wrapper bg-multi bg-right"></div>
<div class="gallery-img-wrapper">
@foreach ($src as $k => $v)
<img src="{{ $v }}" class="{{ $k >= 1 ? 'hide' : '' }}" alt="">
@endforeach
</div>
</div>
<script >
var image = new Viewer(document.getElementById('{{ $id }}'));
</script>
\ No newline at end of file
......@@ -35,4 +35,10 @@ Route::prefix('v1')->namespace('App\Http\Controllers\V1')->group(function (Route
/** 创建订单 */
$api->apiResource('/order', 'OrderController');
/** 调起支付 */
$api->apiResource('/pay', 'PayController');
/** 会员页 */
$api->apiResource('/membership', 'MembershipController');
});
\ No newline at end of file
......
......@@ -16,3 +16,22 @@ use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
Route::get('/create_overlay', function () {
header ('Content-Type: image/png');
$im = @imagecreatetruecolor(640, 1008) or die('Cannot Initialize new GD image stream');
$white = imagecolorallocate($im, 255, 255, 255); //创建颜色
imagefill($im,0,0,$white); //自定义画布的背景颜色
$text_color = imagecolorallocate($im, 233, 14, 91); // 文字颜色
$font = storage_path('app/public/ffmpeg/arialuni.ttf');
$text = 'A Simple Text String';
$box = imagettfbbox(40,0,$font,$text);
$x = (640 - ($box[2] - $box[0])) / 2;
$y = (1008 - ($box[7] - $box[1])) / 2;
imagettftext($im,40,0,$x,$y,$text_color,$font,$text);
imagepng($im);
imagedestroy($im);
dd($im);
});
\ No newline at end of file
......