2 changed files with 736 additions and 0 deletions
@ -0,0 +1,597 @@ |
|||
<template> |
|||
<el-dialog |
|||
v-model="visible" |
|||
title="学员详情" |
|||
width="800px" |
|||
class="student-detail-dialog" |
|||
:destroy-on-close="true" |
|||
> |
|||
<div v-loading="loading" class="student-detail-container"> |
|||
<!-- 学员基本信息 --> |
|||
<el-card class="info-card" shadow="never"> |
|||
<template #header> |
|||
<div class="card-header"> |
|||
<span class="card-title">基本信息</span> |
|||
<el-button |
|||
v-if="!editMode" |
|||
type="primary" |
|||
size="small" |
|||
@click="enterEditMode" |
|||
> |
|||
编辑 |
|||
</el-button> |
|||
<div v-else class="edit-actions"> |
|||
<el-button size="small" @click="cancelEdit">取消</el-button> |
|||
<el-button |
|||
type="primary" |
|||
size="small" |
|||
:loading="saving" |
|||
@click="saveChanges" |
|||
> |
|||
保存 |
|||
</el-button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<el-form |
|||
ref="studentFormRef" |
|||
:model="formData" |
|||
:rules="formRules" |
|||
label-width="120px" |
|||
class="student-form" |
|||
> |
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="姓名" prop="name"> |
|||
<el-input |
|||
v-model="formData.name" |
|||
:disabled="!editMode" |
|||
placeholder="请输入学员姓名" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<el-form-item label="性别" prop="gender"> |
|||
<el-select |
|||
v-model="formData.gender" |
|||
:disabled="!editMode" |
|||
placeholder="请选择性别" |
|||
style="width: 100%" |
|||
> |
|||
<el-option label="男" :value="1" /> |
|||
<el-option label="女" :value="2" /> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="年龄" prop="age"> |
|||
<el-input-number |
|||
v-model="formData.age" |
|||
:disabled="!editMode" |
|||
:min="0" |
|||
:max="150" |
|||
:precision="0" |
|||
placeholder="年龄" |
|||
style="width: 100%" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<el-form-item label="生日" prop="birthday"> |
|||
<el-date-picker |
|||
v-model="formData.birthday" |
|||
:disabled="!editMode" |
|||
type="date" |
|||
placeholder="请选择生日" |
|||
style="width: 100%" |
|||
format="YYYY-MM-DD" |
|||
value-format="YYYY-MM-DD" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="联系电话" prop="contact_phone"> |
|||
<el-input |
|||
v-model="formData.contact_phone" |
|||
:disabled="!editMode" |
|||
placeholder="请输入联系电话" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<el-form-item label="紧急联系人" prop="emergency_contact"> |
|||
<el-input |
|||
v-model="formData.emergency_contact" |
|||
:disabled="!editMode" |
|||
placeholder="请输入紧急联系人" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="校区" prop="campus_id"> |
|||
<el-select |
|||
v-model="formData.campus_id" |
|||
:disabled="!editMode" |
|||
placeholder="请选择校区" |
|||
style="width: 100%" |
|||
@change="handleCampusChange" |
|||
> |
|||
<el-option |
|||
v-for="campus in campusList" |
|||
:key="campus.id" |
|||
:label="campus.name" |
|||
:value="campus.id" |
|||
/> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<el-form-item label="班级" prop="class_id"> |
|||
<el-select |
|||
v-model="formData.class_id" |
|||
:disabled="!editMode" |
|||
placeholder="请选择班级" |
|||
style="width: 100%" |
|||
> |
|||
<el-option |
|||
v-for="classItem in classList" |
|||
:key="classItem.id" |
|||
:label="classItem.name" |
|||
:value="classItem.id" |
|||
/> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="顾问" prop="consultant_id"> |
|||
<el-select |
|||
v-model="formData.consultant_id" |
|||
:disabled="!editMode" |
|||
placeholder="请选择顾问" |
|||
style="width: 100%" |
|||
> |
|||
<el-option |
|||
v-for="consultant in consultantList" |
|||
:key="consultant.id" |
|||
:label="consultant.name" |
|||
:value="consultant.id" |
|||
/> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<el-form-item label="教练" prop="coach_id"> |
|||
<el-select |
|||
v-model="formData.coach_id" |
|||
:disabled="!editMode" |
|||
placeholder="请选择教练" |
|||
style="width: 100%" |
|||
> |
|||
<el-option |
|||
v-for="coach in coachList" |
|||
:key="coach.id" |
|||
:label="coach.name" |
|||
:value="coach.id" |
|||
/> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="会员标签" prop="member_label"> |
|||
<el-input |
|||
v-model="formData.member_label" |
|||
:disabled="!editMode" |
|||
placeholder="请输入会员标签" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<el-form-item label="试听次数" prop="trial_class_count"> |
|||
<el-input-number |
|||
v-model="formData.trial_class_count" |
|||
:disabled="!editMode" |
|||
:min="0" |
|||
placeholder="试听次数" |
|||
style="width: 100%" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<el-row :gutter="20"> |
|||
<el-col :span="12"> |
|||
<el-form-item label="状态" prop="status"> |
|||
<el-select |
|||
v-model="formData.status" |
|||
:disabled="!editMode" |
|||
placeholder="请选择状态" |
|||
style="width: 100%" |
|||
> |
|||
<el-option label="正常" :value="1" /> |
|||
<el-option label="暂停" :value="0" /> |
|||
<el-option label="其他" :value="2" /> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="12"> |
|||
<el-form-item label="创建时间"> |
|||
<el-input |
|||
:value="formatDateTime(formData.created_at)" |
|||
disabled |
|||
placeholder="创建时间" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
|
|||
<el-row> |
|||
<el-col :span="24"> |
|||
<el-form-item label="备注" prop="note"> |
|||
<el-input |
|||
v-model="formData.note" |
|||
:disabled="!editMode" |
|||
type="textarea" |
|||
:rows="3" |
|||
placeholder="请输入备注信息" |
|||
/> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
</el-form> |
|||
</el-card> |
|||
|
|||
<!-- 学员记录信息 --> |
|||
<el-card class="info-card" shadow="never"> |
|||
<template #header> |
|||
<span class="card-title">记录信息</span> |
|||
</template> |
|||
|
|||
<el-descriptions :column="2" border> |
|||
<el-descriptions-item label="用户ID"> |
|||
{{ formData.user_id || '-' }} |
|||
</el-descriptions-item> |
|||
<el-descriptions-item label="学员ID"> |
|||
{{ formData.id || '-' }} |
|||
</el-descriptions-item> |
|||
<el-descriptions-item label="首次到店"> |
|||
{{ formatDateTime(formData.first_come) || '-' }} |
|||
</el-descriptions-item> |
|||
<el-descriptions-item label="二次到店"> |
|||
{{ formatDateTime(formData.second_come) || '-' }} |
|||
</el-descriptions-item> |
|||
<el-descriptions-item label="创建人ID"> |
|||
{{ formData.created_person_id || '-' }} |
|||
</el-descriptions-item> |
|||
<el-descriptions-item label="最后更新"> |
|||
{{ formatDateTime(formData.updated_at) || '-' }} |
|||
</el-descriptions-item> |
|||
</el-descriptions> |
|||
</el-card> |
|||
</div> |
|||
|
|||
<template #footer> |
|||
<div class="dialog-footer"> |
|||
<el-button @click="visible = false">关闭</el-button> |
|||
<el-button |
|||
v-if="!editMode" |
|||
type="primary" |
|||
@click="enterEditMode" |
|||
> |
|||
编辑学员信息 |
|||
</el-button> |
|||
</div> |
|||
</template> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script lang="ts" setup> |
|||
import { ref, reactive, nextTick } from 'vue' |
|||
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus' |
|||
import { getStudentInfo, editStudent } from '@/app/api/student' |
|||
import { getWithCampusList, getWithClassGradeList } from '@/app/api/student' |
|||
|
|||
// 学员数据接口 |
|||
interface StudentDetailInfo { |
|||
id: number |
|||
name: string |
|||
gender: number |
|||
age: number |
|||
birthday: string |
|||
user_id: number |
|||
campus_id: number |
|||
class_id: number |
|||
note: string |
|||
status: number |
|||
emergency_contact: string |
|||
contact_phone: string |
|||
member_label: string |
|||
consultant_id: string |
|||
coach_id: string |
|||
trial_class_count: number |
|||
headimg: string |
|||
first_come: string |
|||
second_come: string |
|||
created_person_id: number |
|||
created_at: string |
|||
updated_at: string |
|||
} |
|||
|
|||
// 选项数据接口 |
|||
interface OptionItem { |
|||
id: number |
|||
name: string |
|||
} |
|||
|
|||
// 响应式数据 |
|||
const visible = ref(false) |
|||
const loading = ref(false) |
|||
const saving = ref(false) |
|||
const editMode = ref(false) |
|||
const studentFormRef = ref<FormInstance>() |
|||
|
|||
// 表单数据 |
|||
const formData = reactive<Partial<StudentDetailInfo>>({}) |
|||
const originalData = reactive<Partial<StudentDetailInfo>>({}) |
|||
|
|||
// 选项数据 |
|||
const campusList = ref<OptionItem[]>([]) |
|||
const classList = ref<OptionItem[]>([]) |
|||
const consultantList = ref<OptionItem[]>([]) |
|||
const coachList = ref<OptionItem[]>([]) |
|||
|
|||
// 表单验证规则 |
|||
const formRules: FormRules = { |
|||
name: [ |
|||
{ required: true, message: '请输入学员姓名', trigger: 'blur' }, |
|||
{ min: 2, max: 50, message: '姓名长度在 2 到 50 个字符', trigger: 'blur' } |
|||
], |
|||
gender: [ |
|||
{ required: true, message: '请选择性别', trigger: 'change' } |
|||
], |
|||
contact_phone: [ |
|||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' } |
|||
] |
|||
} |
|||
|
|||
// 打开弹窗 |
|||
const open = async (studentId: number) => { |
|||
if (!studentId) { |
|||
ElMessage.error('学员ID不能为空') |
|||
return |
|||
} |
|||
|
|||
visible.value = true |
|||
editMode.value = false |
|||
await loadStudentDetail(studentId) |
|||
} |
|||
|
|||
// 加载学员详情 |
|||
const loadStudentDetail = async (studentId: number) => { |
|||
try { |
|||
loading.value = true |
|||
|
|||
// 并行加载学员详情和选项数据 |
|||
const [studentResponse, campusResponse, classResponse] = await Promise.all([ |
|||
getStudentInfo(studentId), |
|||
getWithCampusList({}), |
|||
getWithClassGradeList({}) |
|||
]) |
|||
|
|||
if (studentResponse.code === 1 && studentResponse.data) { |
|||
// 更新表单数据 |
|||
Object.assign(formData, studentResponse.data) |
|||
Object.assign(originalData, studentResponse.data) |
|||
|
|||
console.log('学员详情加载成功:', studentResponse.data) |
|||
} else { |
|||
ElMessage.error(studentResponse.msg || '获取学员详情失败') |
|||
return |
|||
} |
|||
|
|||
// 更新选项数据 |
|||
if (campusResponse.code === 1) { |
|||
campusList.value = campusResponse.data || [] |
|||
} |
|||
|
|||
if (classResponse.code === 1) { |
|||
classList.value = classResponse.data || [] |
|||
} |
|||
|
|||
// 加载顾问和教练数据 |
|||
await loadPersonnelData() |
|||
|
|||
} catch (error) { |
|||
console.error('加载学员详情失败:', error) |
|||
ElMessage.error('加载学员详情失败') |
|||
} finally { |
|||
loading.value = false |
|||
} |
|||
} |
|||
|
|||
// 加载人员数据(顾问、教练) |
|||
const loadPersonnelData = async () => { |
|||
try { |
|||
// 根据当前学员的校区加载对应的顾问和教练 |
|||
const campusId = formData.campus_id |
|||
|
|||
// 模拟API调用 - 实际项目中需要调用真实的API |
|||
// 可以根据实际的API接口进行调整 |
|||
consultantList.value = [ |
|||
{ id: 1, name: '张顾问' }, |
|||
{ id: 2, name: '李顾问' }, |
|||
{ id: 3, name: '王顾问' } |
|||
] |
|||
|
|||
coachList.value = [ |
|||
{ id: 1, name: '赵教练' }, |
|||
{ id: 2, name: '钱教练' }, |
|||
{ id: 3, name: '孙教练' } |
|||
] |
|||
|
|||
// 如果有获取人员的API,可以这样调用: |
|||
// const personnelResponse = await getPersonnelByDept(campusId, [1, 24]) // 1:市场部门(顾问), 24:教练部门 |
|||
// if (personnelResponse.code === 1 && personnelResponse.data) { |
|||
// const personnel = personnelResponse.data |
|||
// consultantList.value = personnel.filter(p => p.dept_id === 1) // 市场部门为顾问 |
|||
// coachList.value = personnel.filter(p => p.dept_id === 24) // 教练部门为教练 |
|||
// } |
|||
} catch (error) { |
|||
console.error('加载人员数据失败:', error) |
|||
} |
|||
} |
|||
|
|||
// 处理校区变化 |
|||
const handleCampusChange = (campusId: number) => { |
|||
// 校区变化时清空班级选择 |
|||
formData.class_id = undefined |
|||
|
|||
// 根据校区筛选班级 |
|||
// 这里可以根据实际需求调用相关API |
|||
console.log('校区变化:', campusId) |
|||
} |
|||
|
|||
// 进入编辑模式 |
|||
const enterEditMode = () => { |
|||
editMode.value = true |
|||
// 备份原始数据 |
|||
Object.assign(originalData, formData) |
|||
} |
|||
|
|||
// 取消编辑 |
|||
const cancelEdit = () => { |
|||
editMode.value = false |
|||
// 恢复原始数据 |
|||
Object.assign(formData, originalData) |
|||
} |
|||
|
|||
// 保存修改 |
|||
const saveChanges = async () => { |
|||
if (!studentFormRef.value) return |
|||
|
|||
try { |
|||
// 表单验证 |
|||
const valid = await studentFormRef.value.validate() |
|||
if (!valid) return |
|||
|
|||
saving.value = true |
|||
|
|||
const response = await editStudent({ |
|||
id: formData.id, |
|||
...formData |
|||
}) |
|||
|
|||
if (response.code === 1) { |
|||
ElMessage.success('学员信息更新成功') |
|||
editMode.value = false |
|||
// 更新原始数据 |
|||
Object.assign(originalData, formData) |
|||
} else { |
|||
ElMessage.error(response.msg || '更新失败') |
|||
} |
|||
} catch (error) { |
|||
console.error('保存学员信息失败:', error) |
|||
ElMessage.error('保存失败') |
|||
} finally { |
|||
saving.value = false |
|||
} |
|||
} |
|||
|
|||
// 格式化日期时间 |
|||
const formatDateTime = (dateTime: string) => { |
|||
if (!dateTime) return '' |
|||
try { |
|||
return new Date(dateTime).toLocaleString('zh-CN') |
|||
} catch { |
|||
return dateTime |
|||
} |
|||
} |
|||
|
|||
// 暴露方法给父组件 |
|||
defineExpose({ |
|||
open |
|||
}) |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.student-detail-dialog { |
|||
.student-detail-container { |
|||
max-height: 70vh; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
.info-card { |
|||
margin-bottom: 20px; |
|||
|
|||
&:last-child { |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
.card-header { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
|
|||
.card-title { |
|||
font-size: 16px; |
|||
font-weight: 600; |
|||
color: #303133; |
|||
} |
|||
|
|||
.edit-actions { |
|||
display: flex; |
|||
gap: 8px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.student-form { |
|||
.el-form-item { |
|||
margin-bottom: 20px; |
|||
} |
|||
} |
|||
|
|||
.dialog-footer { |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
gap: 12px; |
|||
} |
|||
} |
|||
|
|||
:deep(.el-dialog__body) { |
|||
padding: 20px; |
|||
} |
|||
|
|||
:deep(.el-card__header) { |
|||
padding: 16px 20px; |
|||
border-bottom: 1px solid #f0f0f0; |
|||
} |
|||
|
|||
:deep(.el-card__body) { |
|||
padding: 20px; |
|||
} |
|||
|
|||
:deep(.el-descriptions__label) { |
|||
font-weight: 600; |
|||
color: #606266; |
|||
} |
|||
|
|||
:deep(.el-descriptions__content) { |
|||
color: #303133; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,139 @@ |
|||
<?php |
|||
// +---------------------------------------------------------------------- |
|||
// | Niucloud-admin 企业快速开发的多应用管理平台 |
|||
// +---------------------------------------------------------------------- |
|||
// | 官方网址:https://www.niucloud.com |
|||
// +---------------------------------------------------------------------- |
|||
// | niucloud团队 版权所有 开源版本可自由商用 |
|||
// +---------------------------------------------------------------------- |
|||
// | Author: Niucloud Team |
|||
// +---------------------------------------------------------------------- |
|||
|
|||
namespace app\adminapi\controller\upload; |
|||
|
|||
use core\base\BaseAdminController; |
|||
use core\exception\AdminException; |
|||
|
|||
/** |
|||
* 腾讯云COS代理上传(临时开发环境解决方案) |
|||
* 注意:生产环境应该直接配置COS的CORS规则而不是使用代理 |
|||
*/ |
|||
class CosProxy extends BaseAdminController |
|||
{ |
|||
/** |
|||
* 代理上传到腾讯云COS |
|||
* @return \think\Response |
|||
*/ |
|||
public function proxyUpload() |
|||
{ |
|||
try { |
|||
// 从表单或JSON中获取数据 |
|||
$upload_url = $this->request->post('upload_url'); |
|||
|
|||
// 尝试多种方式获取表单数据 |
|||
$form_data = []; |
|||
|
|||
// 方式1: 从form_data字段获取JSON字符串 |
|||
$form_data_json = $this->request->post('form_data', ''); |
|||
if (!empty($form_data_json)) { |
|||
$form_data = json_decode($form_data_json, true); |
|||
if (json_last_error() === JSON_ERROR_NONE) { |
|||
// JSON解析成功 |
|||
} else { |
|||
$form_data = []; |
|||
} |
|||
} |
|||
|
|||
// 如果JSON解析失败,检查是否有独立的字段 |
|||
if (empty($form_data)) { |
|||
$possible_fields = ['key', 'policy', 'q-sign-algorithm', 'q-ak', 'q-key-time', 'q-signature', 'domain']; |
|||
foreach ($possible_fields as $field) { |
|||
$value = $this->request->post($field); |
|||
if (!empty($value)) { |
|||
$form_data[$field] = $value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (empty($upload_url)) { |
|||
throw new AdminException('缺少上传地址'); |
|||
} |
|||
|
|||
// 处理文件上传 |
|||
$file = $this->request->file('file'); |
|||
if (empty($file)) { |
|||
throw new AdminException('缺少上传文件'); |
|||
} |
|||
|
|||
// 添加调试模式 - 如果upload_url包含debug,则返回解析的数据不执行实际上传 |
|||
if (strpos($upload_url, 'debug') !== false) { |
|||
return success([ |
|||
'debug' => true, |
|||
'upload_url' => $upload_url, |
|||
'form_data' => $form_data, |
|||
'form_data_count' => count($form_data), |
|||
'file_info' => [ |
|||
'name' => $file->getOriginalName(), |
|||
'size' => $file->getSize(), |
|||
'mime' => $file->getMime() |
|||
] |
|||
]); |
|||
} |
|||
|
|||
// 腾讯云COS要求特定的字段顺序 |
|||
$post_data = []; |
|||
|
|||
// 添加所有表单字段,确保file在最后 |
|||
foreach ($form_data as $key => $value) { |
|||
$post_data[$key] = $value; |
|||
} |
|||
|
|||
// 最后添加文件(腾讯云COS要求file字段在最后) |
|||
$curl_file = new \CURLFile($file->getPathname(), $file->getMime(), $file->getOriginalName()); |
|||
$post_data['file'] = $curl_file; |
|||
|
|||
// 发送请求到腾讯云COS |
|||
$ch = curl_init(); |
|||
curl_setopt($ch, CURLOPT_URL, $upload_url); |
|||
curl_setopt($ch, CURLOPT_POST, true); |
|||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); |
|||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
|||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); |
|||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
|||
curl_setopt($ch, CURLOPT_TIMEOUT, 60); |
|||
curl_setopt($ch, CURLOPT_HEADER, true); |
|||
|
|||
$full_response = curl_exec($ch); |
|||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
|||
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); |
|||
$error = curl_error($ch); |
|||
curl_close($ch); |
|||
|
|||
if ($error) { |
|||
throw new AdminException('上传失败: ' . $error); |
|||
} |
|||
|
|||
// 解析响应头和内容 |
|||
$header = substr($full_response, 0, $header_size); |
|||
$body = substr($full_response, $header_size); |
|||
|
|||
if ($http_code === 204 || $http_code === 200) { |
|||
// 上传成功 |
|||
$domain = rtrim($form_data['domain'] ?? '', '/'); |
|||
$key = $form_data['key'] ?? ''; |
|||
$file_url = $domain . '/' . $key; |
|||
|
|||
return success([ |
|||
'url' => $file_url, |
|||
'http_code' => $http_code, |
|||
'response_body' => substr($body, 0, 100) // 调试信息 |
|||
]); |
|||
} else { |
|||
throw new AdminException("上传失败,HTTP状态码: {$http_code}, 响应: " . substr($body, 0, 200)); |
|||
} |
|||
|
|||
} catch (\Exception $e) { |
|||
return fail($e->getMessage()); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue