Commit 3a9b6798 authored by 刘小敏's avatar 刘小敏

AI试戴商品列表接口,AI试戴生成图片接口

parent aa7a16b9
...@@ -5,9 +5,12 @@ namespace addons\shopro\controller\user; ...@@ -5,9 +5,12 @@ namespace addons\shopro\controller\user;
use addons\shopro\controller\Common; use addons\shopro\controller\Common;
use app\admin\model\shopro\AiTryon as AiTryOnModel; use app\admin\model\shopro\AiTryon as AiTryOnModel;
use app\admin\model\shopro\user\User as UserModel; use app\admin\model\shopro\user\User as UserModel;
use app\common\library\Upload;
use think\Db; use think\Db;
use think\helper\Time; use think\helper\Time;
use addons\shopro\service\goods\GoodsService; use addons\shopro\service\goods\GoodsService;
use addons\shopro\service\user\User;
use addons\shopro\service\user\Ai;
class AiTryon extends Common class AiTryon extends Common
...@@ -68,18 +71,13 @@ class AiTryon extends Common ...@@ -68,18 +71,13 @@ class AiTryon extends Common
public function isTryon() public function isTryon()
{ {
$user = auth_user(); $user = auth_user();
// 查询我的试戴列表
$res = userModel::where('id', $user->id) $userService = new User();
->find(); $res = $userService->isTry($user->id);
if ($res->ai_count > 4 && $res->ai_time > Time::today()[0]) {
if ($res === 0) {
$this->success('不可以试戴', 0); $this->success('不可以试戴', 0);
} else { } else {
if($res->ai_time < Time::today()[0]) {
$ai_count = 1;
} else {
$ai_count = intval($res->ai_count)+1;
}
userModel::where('id', $user->id)->update(['ai_count' => $ai_count, 'ai_time' => time()]);
$this->success('可以试戴', 1); $this->success('可以试戴', 1);
} }
} }
...@@ -92,7 +90,6 @@ class AiTryon extends Common ...@@ -92,7 +90,6 @@ class AiTryon extends Common
auth_user(); auth_user();
// 查询AI试戴饰品列表 // 查询AI试戴饰品列表
// $params = $this->request->param();
$service = new GoodsService(); $service = new GoodsService();
$service->category(4, true); $service->category(4, true);
$goods = $service->jewelryPaginate(); $goods = $service->jewelryPaginate();
...@@ -100,5 +97,87 @@ class AiTryon extends Common ...@@ -100,5 +97,87 @@ class AiTryon extends Common
$this->success('饰品列表', $goods); $this->success('饰品列表', $goods);
} }
/**
* AI试戴 生成图片
*/
public function genImage()
{
if (!$this->request->isPost()) {
$this->error('');
}
$params = $this->request->only([
'person_image', 'jewelry_image','goods_id','goods_title','goods_subtitle','goods_image'
]);
$this->svalidate($params, ".aiadd");
$user = auth_user();
$userService = new User();
$res = $userService->isTry($user->id);
if ($res === 0) {
$this->success('今日免费试戴次数已用完', 0);
} else {
// 合成AI图
$ai = new Ai();
$res = $ai->generateImage($params, $user->id);
if ($res['code'] === 0) {
$this->error($res['msg']);
} else {
// 保存图片到本服务器
$upload = new Upload();
$attachment = $upload->uploadBase64($res['data']);
if($attachment['code'] == 0){
$this->error('图片上传失败');
}
$userAddress = new AiTryOnModel();
$userAddress->save([
'ai_url' => config('shopro.api_host') . $attachment['data'],
'user_id' => $user->id,
'goods_id' => $params['goods_id'],
'goods_title' => $params['goods_title'],
'goods_subtitle' => $params['goods_subtitle'],
'goods_image' => $params['goods_image'],
'ai_status' => 1,
'ai_task_id' => 0,
'ai_type' => 0,
]);
$this->success($res['msg'], config('shopro.api_host') . $attachment['data']);
}
}
}
/**
* AI试戴 生成视频
*/
public function genVideo()
{
if (!$this->request->isPost()) {
$this->error('');
}
$params = $this->request->only([
'person_image', 'jewelry_image'
]);
$this->svalidate($params, ".aiadd");
$user = auth_user();
$userService = new User();
$res = $userService->isTry($user->id);
if ($res === 0) {
$this->success('今日免费试戴次数已用完', 0);
} else {
$ai = new Ai();
$res = $ai->generateVideo($params);
$this->success('视频生成成功', $res);
}
}
} }
...@@ -275,9 +275,9 @@ class GoodsService ...@@ -275,9 +275,9 @@ class GoodsService
$this->md5s[] = 'paginate'; $this->md5s[] = 'paginate';
// 默认排序 // 默认排序
$this->order(); $this->with('skus')->order();
$goods = $this->query->field('id,title,subtitle,image') $goods = $this->query->field('id,title,subtitle,image as sku_name,image as sku_image')
->cache($this->getCacheKey($is_cache), (200 + mt_rand(0, 100))) ->cache($this->getCacheKey($is_cache), (200 + mt_rand(0, 100)))
->paginate(request()->param('list_rows', 10)) ->paginate(request()->param('list_rows', 10))
->toArray(); ->toArray();
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace addons\shopro\service\user; namespace addons\shopro\service\user;
use app\admin\model\shopro\user\User as UserModel; use app\admin\model\shopro\user\User as UserModel;
use think\helper\Time;
class User class User
{ {
...@@ -33,4 +34,28 @@ class User ...@@ -33,4 +34,28 @@ class User
return true; return true;
} }
/**
* @name 今日是否可以试戴
* @param int|object $user 会员对象或会员ID
* @return int
*/
public function isTry($user_id)
{
// 查询我的试戴列表
$res = userModel::where('id', $user_id)
->find();
if ($res->ai_count > 4 && $res->ai_time > Time::today()[0]) {
return 0; // 不可以试戴
} else {
if($res->ai_time < Time::today()[0]) {
$ai_count = 1;
} else {
$ai_count = intval($res->ai_count)+1;
}
userModel::where('id', $user_id)->update(['ai_count' => $ai_count, 'ai_time' => time()]);
return 1; // 可以试戴
}
}
} }
...@@ -14,6 +14,8 @@ class AiTryon extends Validate ...@@ -14,6 +14,8 @@ class AiTryon extends Validate
'goods_title' => 'require|length:0,255', 'goods_title' => 'require|length:0,255',
'goods_sku_name' => 'require|length:0,255', 'goods_sku_name' => 'require|length:0,255',
'goods_sku_image' => 'require|length:0,255', 'goods_sku_image' => 'require|length:0,255',
'person_image' => 'require',
'jewelry_image' => 'require',
]; ];
/** /**
* 提示消息 * 提示消息
...@@ -29,7 +31,10 @@ class AiTryon extends Validate ...@@ -29,7 +31,10 @@ class AiTryon extends Validate
'goods_sku_name.length' => '商品型号名称长度必须在 0-255 位', 'goods_sku_name.length' => '商品型号名称长度必须在 0-255 位',
'goods_sku_image.require' => '商品型号图片缺失', 'goods_sku_image.require' => '商品型号图片缺失',
'goods_sku_image.length' => '商品型号图片长度必须在 0-255 位' 'goods_sku_image.length' => '商品型号图片长度必须在 0-255 位',
'person_image.require' => '人物图片缺失',
'jewelry_image.require' => '饰品图片缺失',
]; ];
/** /**
* 验证场景 * 验证场景
...@@ -37,6 +42,7 @@ class AiTryon extends Validate ...@@ -37,6 +42,7 @@ class AiTryon extends Validate
protected $scene = [ protected $scene = [
'add' => ['url', 'goods_id', 'goods_title', 'goods_sku_id', 'goods_sku_name', 'goods_sku_image'], 'add' => ['url', 'goods_id', 'goods_title', 'goods_sku_id', 'goods_sku_name', 'goods_sku_image'],
'edit' => [], 'edit' => [],
'aiadd' => ['person_image', 'jewelry_image']
]; ];
} }
...@@ -3,11 +3,14 @@ ...@@ -3,11 +3,14 @@
namespace app\admin\model\shopro; namespace app\admin\model\shopro;
use think\Model; use think\Model;
use traits\model\SoftDelete;
class AiTryon extends Model class AiTryon extends Model
{ {
use SoftDelete;
// 表名 // 表名
protected $name = 'ai_tryon'; protected $name = 'ai_tryon';
...@@ -17,7 +20,7 @@ class AiTryon extends Model ...@@ -17,7 +20,7 @@ class AiTryon extends Model
// 定义时间戳字段名 // 定义时间戳字段名
protected $createTime = 'createtime'; protected $createTime = 'createtime';
protected $updateTime = 'updatetime'; protected $updateTime = 'updatetime';
protected $deleteTime = false; protected $deleteTime = 'deletetime';
// 追加属性 // 追加属性
protected $append = [ protected $append = [
......
...@@ -95,6 +95,10 @@ class Goods extends Common ...@@ -95,6 +95,10 @@ class Goods extends Common
]; ];
} }
public function skus()
{
return $this->hasMany(Sku::class, 'goods_id', 'id');
}
/** /**
* 修改器 service_ids * 修改器 service_ids
......
...@@ -7,6 +7,7 @@ use app\common\model\Attachment; ...@@ -7,6 +7,7 @@ use app\common\model\Attachment;
use fast\Random; use fast\Random;
use FilesystemIterator; use FilesystemIterator;
use think\Config; use think\Config;
use think\Exception;
use think\File; use think\File;
use think\Hook; use think\Hook;
...@@ -352,6 +353,53 @@ class Upload ...@@ -352,6 +353,53 @@ class Upload
} }
/** /**
* AI base64文件上传
*/
public function uploadBase64($base64_str = '')
{
try {
// 1. 去除base64头部多余字符(防止报错)
if (strpos($base64_str, 'data:image') !== false) {
$base64_str = preg_replace('/^data:image.*base64,/', '', $base64_str);
}
// 2. 解码图片流
$image_data = base64_decode($base64_str);
if (!$image_data) {
return [
'code' => 0,
'msg' => '非法图片流数据'
];
}
// 3. 生成存储目录(fastadmin标准uploads目录)
$dir = ROOT_PATH . 'public/uploads/ai_images/' . date('Ymd') . '/';
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
// 4. 生成唯一文件名
$filename = md5(time() . uniqid()) . '.jpg';
$full_path = $dir . $filename;
// 5. 写入本地保存
file_put_contents($full_path, $image_data);
// 6. 返回前端能直接用的路径(可存数据库)
return [
'code' => 1,
'msg' => '图片上传成功',
'data' => '/uploads/ai_images/' . date('Ymd') . '/' . $filename
];
} catch (\Exception $e){
return [
'code' => 0,
'msg' => $e->getMessage()
];
}
}
/**
* 普通上传 * 普通上传
* @return \app\common\model\attachment|\think\Model * @return \app\common\model\attachment|\think\Model
* @throws UploadException * @throws UploadException
......
...@@ -265,7 +265,9 @@ return [ ...@@ -265,7 +265,9 @@ return [
// 缓存有效期 0表示永久缓存 // 缓存有效期 0表示永久缓存
'expire' => 0, 'expire' => 0,
], ],
//FastAdmin配置 // +----------------------------------------------------------------------
// | FastAdmin配置
// +----------------------------------------------------------------------
'fastadmin' => [ 'fastadmin' => [
//是否开启前台会员中心 //是否开启前台会员中心
'usercenter' => true, 'usercenter' => true,
...@@ -306,4 +308,14 @@ return [ ...@@ -306,4 +308,14 @@ return [
//API接口地址 //API接口地址
'api_url' => 'https://api.fastadmin.net', 'api_url' => 'https://api.fastadmin.net',
], ],
// +----------------------------------------------------------------------
// | Shopro配置
// +----------------------------------------------------------------------
'shopro' => [
// 火山引擎
'ai_api_key' => Env::get('ai.api_key', ''),
// 接口域名
'api_host' => Env::get('app.api_host', ''),
],
]; ];
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment