|
@@ -4317,5 +4317,253 @@ class AnimeService
|
|
|
Utils::throwError('20003:' . $e->getMessage());
|
|
Utils::throwError('20003:' . $e->getMessage());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ public function globalRoles($data) {
|
|
|
|
|
+ $role = getProp($data, 'role');
|
|
|
|
|
+ $query = DB::table('mp_roles')->where('is_deleted', 0)->select('id', 'role', 'url', 'pic_prompt', 'three_view_image_url', 'created_at');
|
|
|
|
|
+ if ($role) $query->where('role', 'like', "%{$role}%");
|
|
|
|
|
+ $result = $query->orderBy('id', 'desc')->get()->map(function($value) {
|
|
|
|
|
+ $value = (array)$value;
|
|
|
|
|
+ $value['created_at'] = transDate($value['created_at'], 'Y-m-d');
|
|
|
|
|
+ return $value;
|
|
|
|
|
+ })->toArray();
|
|
|
|
|
+
|
|
|
|
|
+ return $result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function createRole($data) {
|
|
|
|
|
+ $uid = Site::getUid();
|
|
|
|
|
+ $role = trim(getProp($data, 'role'));
|
|
|
|
|
+ if (!$role) Utils::throwError('20003:角色名不能为空');
|
|
|
|
|
+ $url = trim(getProp($data, 'url'));
|
|
|
|
|
+ if (!$url) Utils::throwError('20003:图片地址不能为空');
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否是正确的图片格式
|
|
|
|
|
+ $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
|
|
|
|
|
+ $urlPath = parse_url($url, PHP_URL_PATH);
|
|
|
|
|
+ $extension = strtolower(pathinfo($urlPath, PATHINFO_EXTENSION));
|
|
|
|
|
+
|
|
|
|
|
+ if (!in_array($extension, $allowedExtensions)) {
|
|
|
|
|
+ Utils::throwError('20003:图片格式不正确,仅支持 jpg、jpeg、png、gif、webp、bmp 格式');
|
|
|
|
|
+ }
|
|
|
|
|
+ $pic_prompt = trim(getProp($data, 'pic_prompt'));
|
|
|
|
|
+ if (!$pic_prompt) Utils::throwError('20003:角色提示词不能为空');
|
|
|
|
|
+
|
|
|
|
|
+ $id = DB::table('mp_roles')->insertGetId([
|
|
|
|
|
+ 'user_id' => $uid,
|
|
|
|
|
+ 'role' => $role,
|
|
|
|
|
+ 'url' => $url,
|
|
|
|
|
+ 'pic_prompt' => $pic_prompt,
|
|
|
|
|
+ 'created_at' => date('Y-m-d H:i:s'),
|
|
|
|
|
+ 'updated_at' => date('Y-m-d H:i:s')
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ if (!$id) Utils::throwError('20003:创建角色失败');
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'id' => $id,
|
|
|
|
|
+ 'role' => $role,
|
|
|
|
|
+ 'url' => $url,
|
|
|
|
|
+ 'pic_prompt' => $pic_prompt
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function editRole($data) {
|
|
|
|
|
+ $uid = Site::getUid();
|
|
|
|
|
+ $id = getProp($data, 'id');
|
|
|
|
|
+ if (!$id) Utils::throwError('20003:角色ID不能为空');
|
|
|
|
|
+
|
|
|
|
|
+ // 检查角色是否存在且属于当前用户
|
|
|
|
|
+ $role = DB::table('mp_roles')
|
|
|
|
|
+ // ->where('user_id', $uid)
|
|
|
|
|
+ ->where('id', $id)->first();
|
|
|
|
|
+ if (!$role) Utils::throwError('20003:角色不存在或无权限操作');
|
|
|
|
|
+
|
|
|
|
|
+ $updateData = [];
|
|
|
|
|
+
|
|
|
|
|
+ // 角色名
|
|
|
|
|
+ $roleName = trim(getProp($data, 'role'));
|
|
|
|
|
+ if ($roleName) {
|
|
|
|
|
+ $updateData['role'] = $roleName;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 图片地址
|
|
|
|
|
+ $url = trim(getProp($data, 'url'));
|
|
|
|
|
+ if ($url) {
|
|
|
|
|
+ // 检查是否是正确的图片格式
|
|
|
|
|
+ $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
|
|
|
|
|
+ $urlPath = parse_url($url, PHP_URL_PATH);
|
|
|
|
|
+ $extension = strtolower(pathinfo($urlPath, PATHINFO_EXTENSION));
|
|
|
|
|
+
|
|
|
|
|
+ if (!in_array($extension, $allowedExtensions)) {
|
|
|
|
|
+ Utils::throwError('20003:图片格式不正确,仅支持 jpg、jpeg、png、gif、webp、bmp 格式');
|
|
|
|
|
+ }
|
|
|
|
|
+ $updateData['url'] = $url;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 角色提示词
|
|
|
|
|
+ $pic_prompt = trim(getProp($data, 'pic_prompt'));
|
|
|
|
|
+ if ($pic_prompt) {
|
|
|
|
|
+ $updateData['pic_prompt'] = $pic_prompt;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (empty($updateData)) {
|
|
|
|
|
+ Utils::throwError('20003:没有需要更新的数据');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $updateData['updated_at'] = date('Y-m-d H:i:s');
|
|
|
|
|
+
|
|
|
|
|
+ return DB::table('mp_roles')
|
|
|
|
|
+ // ->where('user_id', $uid)
|
|
|
|
|
+ ->where('id', $id)->update($updateData);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function deleteRole($data) {
|
|
|
|
|
+ $uid = Site::getUid();
|
|
|
|
|
+ $id = getProp($data, 'id');
|
|
|
|
|
+ if (!$id) Utils::throwError('20003:角色ID不能为空');
|
|
|
|
|
+
|
|
|
|
|
+ // 检查角色是否存在且属于当前用户
|
|
|
|
|
+ $role = DB::table('mp_roles')
|
|
|
|
|
+ // ->where('user_id', $uid)
|
|
|
|
|
+ ->where('id', $id)->first();
|
|
|
|
|
+ if (!$role) Utils::throwError('20003:角色不存在或无权限操作');
|
|
|
|
|
+
|
|
|
|
|
+ return DB::table('mp_roles')
|
|
|
|
|
+ // ->where('user_id', $uid)
|
|
|
|
|
+ ->where('id', $id)->delete();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function generateThreeView($data) {
|
|
|
|
|
+ $uid = Site::getUid();
|
|
|
|
|
+ $id = getProp($data, 'id');
|
|
|
|
|
+ if (!$id) Utils::throwError('20003:角色ID不能为空');
|
|
|
|
|
+
|
|
|
|
|
+ // 检查角色是否存在且属于当前用户
|
|
|
|
|
+ $role = DB::table('mp_roles')
|
|
|
|
|
+ // ->where('user_id', $uid)
|
|
|
|
|
+ ->where('id', $id)->first();
|
|
|
|
|
+ if (!$role) Utils::throwError('20003:角色不存在或无权限操作');
|
|
|
|
|
+
|
|
|
|
|
+ $prompt = trim(getProp($data, 'prompt', '基于参考图生成主体的标准正面、侧面、后面三视图,主体完整。在最左侧添加主体正视图的特写,主体清晰完整。背景修改成纯白色,整体保持与参考图一致的美术风格和色彩搭配。画面无说明文字'));
|
|
|
|
|
+ $ref_img_url = trim(getProp($data, 'ref_img_url'));
|
|
|
|
|
+ if (!$ref_img_url) {
|
|
|
|
|
+ // 如果没有传入参考图,使用角色表中的图片
|
|
|
|
|
+ $ref_img_url = $role->url ?? '';
|
|
|
|
|
+ if (!$ref_img_url) {
|
|
|
|
|
+ Utils::throwError('20003:参考图不能为空');
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查参考图是否是正确的图片格式
|
|
|
|
|
+ $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
|
|
|
|
|
+ $urlPath = parse_url($ref_img_url, PHP_URL_PATH);
|
|
|
|
|
+ $extension = strtolower(pathinfo($urlPath, PATHINFO_EXTENSION));
|
|
|
|
|
+
|
|
|
|
|
+ if (!in_array($extension, $allowedExtensions)) {
|
|
|
|
|
+ Utils::throwError('20003:参考图格式不正确,仅支持 jpg、jpeg、png、gif、webp、bmp 格式');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 处理图片模型
|
|
|
|
|
+ $model = getProp($data, 'model');
|
|
|
|
|
+ if (!$model) {
|
|
|
|
|
+ // 使用默认模型
|
|
|
|
|
+ $model = 'doubao-seedream-5-0-lite-260128';
|
|
|
|
|
+ }
|
|
|
|
|
+ // 验证模型是否在可用模型表中
|
|
|
|
|
+ if (!DB::table('mp_image_models')->where('model', $model)->where('is_enabled', 1)->exists()) {
|
|
|
|
|
+ Utils::throwError('20003:该模型已不可用,请更换!');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 创建图片生成任务
|
|
|
|
|
+ $params = [
|
|
|
|
|
+ 'prompt' => $prompt,
|
|
|
|
|
+ 'model' => $model,
|
|
|
|
|
+ 'ref_img_urls' => [$ref_img_url],
|
|
|
|
|
+ 'width' => 1600,
|
|
|
|
|
+ 'height' => 2848
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ $task = $this->aiImageGenerationService->createImageGenerationTask($params);
|
|
|
|
|
+ $task_id = $task->id;
|
|
|
|
|
+
|
|
|
|
|
+ if (!$task_id) {
|
|
|
|
|
+ Utils::throwError('20003:创建图片生成任务失败');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查任务模型类型
|
|
|
|
|
+ $isVolcModel = in_array($model, \App\Consts\BaseConst::VOLC_PIC_MODELS);
|
|
|
|
|
+ $isGptModel = in_array($model, \App\Consts\BaseConst::GPT_IMAGE2_MODELS);
|
|
|
|
|
+ $isSyncModel = $isVolcModel || $isGptModel;
|
|
|
|
|
+
|
|
|
|
|
+ // 轮询获取结果(5分钟超时,每3秒查询一次)
|
|
|
|
|
+ $start_time = time();
|
|
|
|
|
+ $timeout = 300; // 5分钟
|
|
|
|
|
+ $img_url = '';
|
|
|
|
|
+
|
|
|
|
|
+ while (time() - $start_time < $timeout) {
|
|
|
|
|
+ sleep(3);
|
|
|
|
|
+
|
|
|
|
|
+ // 火山API和GPT-Image2 API是同步返回结果的,直接检查任务状态
|
|
|
|
|
+ if ($isSyncModel) {
|
|
|
|
|
+ // 刷新任务状态
|
|
|
|
|
+ $task = MpGeneratePicTask::where('id', $task_id)->first();
|
|
|
|
|
+
|
|
|
|
|
+ if ($task->status === 'success' && $task->result_url) {
|
|
|
|
|
+ $result_urls = is_array($task->result_url) ? $task->result_url : json_decode($task->result_url, true);
|
|
|
|
|
+ $img_url = is_array($result_urls) ? $result_urls[0] : $task->result_url;
|
|
|
|
|
+ break;
|
|
|
|
|
+ } elseif ($task->status === 'failed') {
|
|
|
|
|
+ Utils::throwError('20003:三视图生成失败,' . ($task->error_message ?? '未知错误'));
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $task = MpGeneratePicTask::where('id', $task_id)->first();
|
|
|
|
|
+ $statusInfo = $this->aiImageGenerationService->queryTaskStatus($task);
|
|
|
|
|
+
|
|
|
|
|
+ if ($statusInfo['status'] === 'success') {
|
|
|
|
|
+ $task->updateStatus('success', [
|
|
|
|
|
+ 'result_url' => $statusInfo['result_url'],
|
|
|
|
|
+ 'result_json' => $statusInfo['result_json'] ?? []
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ $img_url = $statusInfo['result_url'][0];
|
|
|
|
|
+ break;
|
|
|
|
|
+ } elseif ($statusInfo['status'] === 'failed') {
|
|
|
|
|
+ $task->updateStatus('failed', [
|
|
|
|
|
+ 'error_message' => $statusInfo['error_message'],
|
|
|
|
|
+ 'result_json' => $statusInfo['result_json'] ?? []
|
|
|
|
|
+ ]);
|
|
|
|
|
+ dLog('anime')->error('三视图生成失败', [
|
|
|
|
|
+ 'error' => $statusInfo['error_message'] ?? '未知错误'
|
|
|
|
|
+ ]);
|
|
|
|
|
+ Utils::throwError('20003:三视图生成失败,' . ($statusInfo['error_message'] ?? '未知错误'));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (empty($img_url)) {
|
|
|
|
|
+ Utils::throwError('20003:三视图生成超时,请稍后重试');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 保存三视图到 mp_roles 表
|
|
|
|
|
+ DB::table('mp_roles')
|
|
|
|
|
+ ->where('id', $id)
|
|
|
|
|
+ // ->where('user_id', $uid)
|
|
|
|
|
+ ->update([
|
|
|
|
|
+ 'three_view_image_url' => $img_url,
|
|
|
|
|
+ 'updated_at' => date('Y-m-d H:i:s')
|
|
|
|
|
+ ]);
|
|
|
|
|
+
|
|
|
|
|
+ return ['three_view_image_url' => $img_url];
|
|
|
|
|
+
|
|
|
|
|
+ } catch (\Exception $e) {
|
|
|
|
|
+ dLog('anime')->error('生成三视图失败', [
|
|
|
|
|
+ 'error' => $e->getMessage()
|
|
|
|
|
+ ]);
|
|
|
|
|
+ logDB('anime', 'error', '生成三视图失败', ['error' => $e->getMessage()]);
|
|
|
|
|
+
|
|
|
|
|
+ Utils::throwError('20003:' . $e->getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|