master
lion 1 day ago
parent 8b2102696d
commit 26d68ac730

@ -306,17 +306,29 @@ class CourseController extends BaseController
$model->fill($all);
$model->save();
DB::commit();
// 更改状态
} catch (\Exception $exception) {
DB::rollBack();
return $this->fail([$exception->getCode(), $exception->getMessage()]);
}
// 提交后再更新状态;微信小程序码失败不应影响保存成功
try {
$model = Course::updateSignStatus($model->id);
$model = Course::updateStatus($model->id);
if ($model->status == 1 && $model->start_date) {
CourseAppointmentTotal::addByCourse($model->id);
}
return $this->success($model);
} catch (\Exception $exception) {
DB::rollBack();
return $this->fail([$exception->getCode(), $exception->getMessage()]);
} catch (\Throwable $e) {
\Log::warning('course save post-process failed', [
'course_id' => $model->id ?? null,
'message' => $e->getMessage(),
]);
}
$model = Course::find($model->id);
// 保存接口不强制生成小程序码,避免 Failed to cache access token 误报为保存失败
$model->setAppends(array_values(array_diff($model->getAppends(), ['qrcode'])));
return $this->success($model);
}
/**

@ -5,7 +5,9 @@ namespace App\Models;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Http\StreamResponse;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\Log;
class Course extends SoftDeletesModel
{
@ -30,59 +32,70 @@ class Course extends SoftDeletesModel
public function getStatusTextAttribute()
{
$array = [0 => '待发布', 1 => '已发布'];
return $array[$this->attributes['status']];
return $array[$this->attributes['status'] ?? 0] ?? '';
}
public function getIsFeeTextAttribute()
{
$array = [0 => '免费', 1 => '收费'];
return $array[$this->attributes['is_fee']];
return $array[$this->attributes['is_fee'] ?? 0] ?? '';
}
public function getIsArrangeTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['is_arrange']];
return $array[$this->attributes['is_arrange'] ?? 0] ?? '';
}
public function getShowTxlTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['show_txl']];
return $array[$this->attributes['show_txl'] ?? 0] ?? '';
}
public function getShowMobileTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['show_mobile']];
return $array[$this->attributes['show_mobile'] ?? 0] ?? '';
}
public function getAutoSchoolmateTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['auto_schoolmate']];
return $array[$this->attributes['auto_schoolmate'] ?? 0] ?? '';
}
public function getFreeEnterSchoolmateTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['free_enter_schoolmate'] ?? 0];
return $array[$this->attributes['free_enter_schoolmate'] ?? 0] ?? '';
}
public function getIsVirtualTextAttribute()
{
$array = [0 => '否', 1 => '是'];
return $array[$this->attributes['is_virtual']];
return $array[$this->attributes['is_virtual'] ?? 0] ?? '';
}
public function getQrcodeAttribute($value)
{
return $this->getCourseQrcode($this->attributes['id']);
try {
return $this->getCourseQrcode($this->attributes['id']);
} catch (\Throwable $e) {
Log::warning('course qrcode append failed', [
'course_id' => $this->attributes['id'] ?? null,
'message' => $e->getMessage(),
]);
return '';
}
}
public function getTeacherDetailAttribute($value)
{
if (empty($this->teacher_id)) {
return collect();
}
$teacherIds = explode(',', $this->teacher_id);
return Teacher::whereIn('id', $teacherIds)->get();
}
@ -228,25 +241,14 @@ class Course extends SoftDeletesModel
public function getCourseQrcode($courseId)
{
$course = Course::find($courseId);
$path = config('filesystems.disks.public.root') . '/course_qrcode/' . $course->id . '.png';
$url = config('filesystems.disks.public.url') . '/course_qrcode/' . $course->id . '.png';
$fileSys = new Filesystem();
if ($fileSys->exists($path)) {
return $url;
if (empty($course)) {
return '';
}
$config = [
'app_id' => \config('app.applet_appid'),
'secret' => \config('app.applet_secret')
];
$app = Factory::miniProgram($config);
$tmp = $app->app_code->get('packages/course/detail?' . 'id=' . $courseId, [
'env_version' => "release" // 正式版
// 'env_version' => "trial" // 体验版
]);
$dir = dirname($path);
$fileSys->ensureDirectoryExists($dir, 0755, true);
$fileSys->put($path, $tmp);
return $url;
return $this->resolveMiniProgramQrcode(
'course_qrcode/' . $course->id . '.png',
'packages/course/detail?id=' . $courseId,
['course_id' => $courseId]
);
}
/**
@ -255,24 +257,14 @@ class Course extends SoftDeletesModel
public function getCourseCheckQrcode($courseId)
{
$course = Course::find($courseId);
$path = config('filesystems.disks.public.root') . '/course_check_qrcode/' . $course->id . '.png';
$url = config('filesystems.disks.public.url') . '/course_check_qrcode/' . $course->id . '.png';
$fileSys = new Filesystem();
if ($fileSys->exists($path)) {
return $url;
if (empty($course)) {
return '';
}
$config = [
'app_id' => \config('app.applet_appid'),
'secret' => \config('app.applet_secret')
];
$app = Factory::miniProgram($config);
$tmp = $app->app_code->get('packages/sign/course?course_id=' . $courseId, [
'env_version' => "release" // 正式版
]);
$dir = dirname($path);
$fileSys->ensureDirectoryExists($dir, 0755, true);
$fileSys->put($path, $tmp);
return $url;
return $this->resolveMiniProgramQrcode(
'course_check_qrcode/' . $course->id . '.png',
'packages/sign/course?course_id=' . $courseId,
['course_id' => $courseId]
);
}
/**
@ -281,26 +273,59 @@ class Course extends SoftDeletesModel
public function getEvaluationQrcode($id)
{
$courseContentEvaluation = CourseContentEvaluation::find($id);
$path = config('filesystems.disks.public.root') . '/course_evaluation_qrcode/' . $courseContentEvaluation->id . '.png';
$url = config('filesystems.disks.public.url') . '/course_evaluation_qrcode/' . $courseContentEvaluation->id . '.png';
if (empty($courseContentEvaluation)) {
return '';
}
return $this->resolveMiniProgramQrcode(
'course_evaluation_qrcode/' . $courseContentEvaluation->id . '.png',
'packages/surveyFill/index?id=' . $id,
['evaluation_id' => $id]
);
}
/**
* 读取或生成小程序码;微信/缓存失败时返回空字符串,避免列表接口 500
*/
protected function resolveMiniProgramQrcode(string $relativePath, string $page, array $context = []): string
{
$path = config('filesystems.disks.public.root') . '/' . $relativePath;
$url = config('filesystems.disks.public.url') . '/' . $relativePath;
$fileSys = new Filesystem();
if ($fileSys->exists($path)) {
return $url;
}
$config = [
'app_id' => \config('app.applet_appid'),
'secret' => \config('app.applet_secret')
];
$app = Factory::miniProgram($config);
$tmp = $app->app_code->get('packages/surveyFill/index?id=' . $id, [
// todo:: 版本切换
'env_version' => "release" // 正式版
// 'env_version' => "trial" // 体验版
]);
$dir = dirname($path);
$fileSys->ensureDirectoryExists($dir, 0755, true);
$fileSys->put($path, $tmp);
return $url;
$appId = (string) config('app.applet_appid');
$secret = (string) config('app.applet_secret');
if ($appId === '' || $secret === '') {
Log::warning('mini program qrcode skipped: missing appid/secret', $context);
return '';
}
try {
$app = Factory::miniProgram([
'app_id' => $appId,
'secret' => $secret,
]);
$tmp = $app->app_code->get($page, [
'env_version' => 'release',
]);
$content = $tmp instanceof StreamResponse ? $tmp->getBodyContents() : (string) $tmp;
if ($content === '' || str_starts_with(ltrim($content), '{')) {
Log::warning('mini program qrcode invalid response', $context + [
'body' => substr($content, 0, 300),
]);
return '';
}
$fileSys->ensureDirectoryExists(dirname($path), 0755, true);
$fileSys->put($path, $content);
return $url;
} catch (\Throwable $e) {
Log::warning('mini program qrcode failed', $context + [
'message' => $e->getMessage(),
]);
return '';
}
}
/**

Loading…
Cancel
Save