Merge branch 'long-0507'
This commit is contained in:
@@ -211,6 +211,7 @@ const handleDeleteImage = async (noteId: number, imageType: 'tongue_images' | 'r
|
||||
<style scoped lang="scss">
|
||||
.timeline-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 12px;
|
||||
|
||||
@@ -74,9 +74,13 @@ const { pager, getLists, resetPage } = usePaging({
|
||||
|
||||
const buildParams = () => {
|
||||
Object.keys(queryParams).forEach((k) => delete queryParams[k])
|
||||
if (props.diagnosisId > 0) {
|
||||
queryParams.context_diagnosis_id = props.diagnosisId
|
||||
}
|
||||
if (patientIdAvailable.value) {
|
||||
queryParams.patient_id = patientIdNum.value
|
||||
}
|
||||
queryParams.scene = 'diagnosis_edit'
|
||||
}
|
||||
|
||||
const formatAmount = (value: unknown) => {
|
||||
|
||||
@@ -27,6 +27,8 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
||||
{
|
||||
use HasDataScopeFilter;
|
||||
|
||||
private const SCENE_DIAGNOSIS_EDIT = 'diagnosis_edit';
|
||||
|
||||
public function setSearch(): array
|
||||
{
|
||||
return [
|
||||
@@ -101,9 +103,11 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
||||
$this->applyExpressCompanyFilter($query);
|
||||
$this->applyExpressKeywordFilter($query);
|
||||
$this->applySupplyModeFilter($query);
|
||||
$this->applyCreatorOrOwnPrescriptionVisibility($query);
|
||||
$this->applyDataScopeForPrescriptionOrder($query);
|
||||
// 业绩看板侧栏等:不展示履约已取消(4),与看板合计业绩 NULL 安全口径一致
|
||||
if (!$this->shouldBypassListVisibilityForDiagnosisEdit()) {
|
||||
$this->applyCreatorOrOwnPrescriptionVisibility($query);
|
||||
$this->applyDataScopeForPrescriptionOrder($query);
|
||||
}
|
||||
// 业绩看板侧栏等:不展示履约已取消(4),与 stats 业绩统计口径一致
|
||||
if ((int) ($this->params['exclude_fulfillment_cancelled'] ?? 0) === 1) {
|
||||
YejiStatsLogic::applyPrescriptionOrderNotCancelledForPerformanceQuery($query, '');
|
||||
}
|
||||
@@ -269,6 +273,29 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅诊单编辑页内的患者订单查询可跳过列表页权限,但必须显式带场景且保留患者/诊单范围收敛。
|
||||
*/
|
||||
private function shouldBypassListVisibilityForDiagnosisEdit(): bool
|
||||
{
|
||||
$scene = trim((string) ($this->params['scene'] ?? ''));
|
||||
if ($scene !== self::SCENE_DIAGNOSIS_EDIT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$patientId = (int) ($this->params['patient_id'] ?? 0);
|
||||
$contextDiagnosisId = (int) ($this->params['context_diagnosis_id'] ?? 0);
|
||||
if ($patientId <= 0 || $contextDiagnosisId <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$diagnosisPatientId = (int) Diagnosis::where('id', $contextDiagnosisId)
|
||||
->whereNull('delete_time')
|
||||
->value('patient_id');
|
||||
|
||||
return $diagnosisPatientId > 0 && $diagnosisPatientId === $patientId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 医助:仅「诊单医助=本人」的订单计业绩
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
namespace app\adminapi\logic\tcm;
|
||||
|
||||
use app\common\logic\BaseLogic;
|
||||
use app\common\enum\FileEnum;
|
||||
use app\common\model\file\File as FileModel;
|
||||
use app\common\model\tcm\Diagnosis;
|
||||
use app\common\model\tcm\DiagnosisGuahaoLog;
|
||||
use app\common\model\tcm\DiagnosisAssignLog;
|
||||
@@ -29,8 +31,10 @@ use app\common\model\auth\AdminRole;
|
||||
use app\adminapi\logic\doctor\DoctorNoteLogic;
|
||||
use app\adminapi\logic\doctor\AppointmentLogic;
|
||||
use app\adminapi\logic\tcm\TrackingNoteLogic;
|
||||
use app\common\service\ConfigService;
|
||||
use app\common\service\FileService;
|
||||
use app\common\service\DataScope\DataScopeService;
|
||||
use app\common\service\storage\Driver as StorageDriver;
|
||||
use think\facade\Db;
|
||||
/**
|
||||
* 中医辨房病因诊单逻辑
|
||||
@@ -975,10 +979,29 @@ class DiagnosisLogic extends BaseLogic
|
||||
if (empty($doctorAccounts)) {
|
||||
return [];
|
||||
}
|
||||
$diagnosisId = (int)($diag['id'] ?? 0);
|
||||
// 增量优化:按 doctor_peer_account 维度取归档表最大时间作为 MinTime 起点,
|
||||
// 避免每次都从头拉取已归档的历史消息(节约腾讯云 admin_getroammsg 调用配额)
|
||||
$minTimeMap = [];
|
||||
if ($diagnosisId > 0) {
|
||||
$rows = ImChatMessage::field('doctor_peer_account, MAX(msg_time) AS max_time')
|
||||
->where('diagnosis_id', $diagnosisId)
|
||||
->group('doctor_peer_account')
|
||||
->select()
|
||||
->toArray();
|
||||
foreach ($rows as $r) {
|
||||
$acct = (string)($r['doctor_peer_account'] ?? '');
|
||||
if ($acct !== '') {
|
||||
$minTimeMap[$acct] = (int)($r['max_time'] ?? 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
$imService = new \app\common\service\TencentImService();
|
||||
$merged = [];
|
||||
foreach ($doctorAccounts as $docAccount) {
|
||||
$batch = self::pullAllRoamMessages($imService, $docAccount, $patientImId);
|
||||
// 已归档过:从最大已知 msg_time 起拉(含等于以兜底边界,配合 INSERT IGNORE 去重)
|
||||
$minTime = isset($minTimeMap[$docAccount]) ? max(0, $minTimeMap[$docAccount]) : 0;
|
||||
$batch = self::pullAllRoamMessages($imService, $docAccount, $patientImId, $minTime);
|
||||
foreach ($batch as $row) {
|
||||
$merged[] = $row;
|
||||
}
|
||||
@@ -1096,23 +1119,44 @@ class DiagnosisLogic extends BaseLogic
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private static function pullAllRoamMessages(\app\common\service\TencentImService $svc, string $operator, string $peer): array
|
||||
private static function pullAllRoamMessages(\app\common\service\TencentImService $svc, string $operator, string $peer, int $minTime = 0): array
|
||||
{
|
||||
$out = [];
|
||||
$lastKey = null;
|
||||
$lastTime = null;
|
||||
$guard = 0;
|
||||
$maxPages = 80;
|
||||
do {
|
||||
$res = $svc->adminGetRoamMsg($operator, $peer, 100, 0, 4294967295, $lastKey, $lastTime);
|
||||
if (!$res['success']) {
|
||||
if (!empty($res['error'])) {
|
||||
\think\facade\Log::warning('IM漫游消息拉取失败', [
|
||||
'operator' => $operator,
|
||||
'peer' => $peer,
|
||||
'error' => $res['error'],
|
||||
'code' => $res['rawErrorCode'] ?? 0,
|
||||
]);
|
||||
// 单页失败重试:避免网络抖动 / 限频导致整段会话被丢弃
|
||||
$res = null;
|
||||
$attempt = 0;
|
||||
while ($attempt < 3) {
|
||||
$res = $svc->adminGetRoamMsg($operator, $peer, 100, $minTime, 4294967295, $lastKey, $lastTime);
|
||||
if (!empty($res['success'])) {
|
||||
break;
|
||||
}
|
||||
$attempt++;
|
||||
\think\facade\Log::warning('IM漫游消息拉取失败(待重试)', [
|
||||
'operator' => $operator,
|
||||
'peer' => $peer,
|
||||
'attempt' => $attempt,
|
||||
'error' => $res['error'] ?? '',
|
||||
'code' => $res['rawErrorCode'] ?? 0,
|
||||
'page' => $guard + 1,
|
||||
]);
|
||||
if ($attempt < 3) {
|
||||
usleep(300000); // 300ms 退避
|
||||
}
|
||||
}
|
||||
if (empty($res['success'])) {
|
||||
\think\facade\Log::error('IM漫游消息拉取失败(重试耗尽,本轮中断)', [
|
||||
'operator' => $operator,
|
||||
'peer' => $peer,
|
||||
'page' => $guard + 1,
|
||||
'fetched_so_far' => count($out),
|
||||
'error' => $res['error'] ?? '',
|
||||
'code' => $res['rawErrorCode'] ?? 0,
|
||||
]);
|
||||
break;
|
||||
}
|
||||
foreach ($res['msgList'] as $raw) {
|
||||
@@ -1133,7 +1177,16 @@ class DiagnosisLogic extends BaseLogic
|
||||
break;
|
||||
}
|
||||
$guard++;
|
||||
if ($guard > 80) {
|
||||
if ($guard >= $maxPages) {
|
||||
// 触顶安全网:增量优化后通常拉不满 80 页,触顶意味着首次全量或会话异常多
|
||||
\think\facade\Log::warning('IM漫游消息拉取触发分页上限(可能未拉完)', [
|
||||
'operator' => $operator,
|
||||
'peer' => $peer,
|
||||
'min_time' => $minTime,
|
||||
'pages_fetched' => $guard,
|
||||
'fetched_so_far' => count($out),
|
||||
'last_msg_time' => $lastTime,
|
||||
]);
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
@@ -1732,22 +1785,14 @@ class DiagnosisLogic extends BaseLogic
|
||||
$diagnosisId = (int)($params['diagnosis_id'] ?? 0);
|
||||
$adminId = (int)($params['admin_id'] ?? 0);
|
||||
$fileUrl = trim((string)($params['file_url'] ?? ''));
|
||||
$callRecordId = (int)($params['call_record_id'] ?? 0);
|
||||
if ($diagnosisId <= 0 || $adminId <= 0 || $fileUrl === '') {
|
||||
self::setError('参数错误');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$record = \app\common\model\tcm\CallRecord::where('diagnosis_id', $diagnosisId)
|
||||
->where('caller_id', $adminId)
|
||||
->order('id', 'desc')
|
||||
->find();
|
||||
// 与 startCall 的 caller_id 不一致或竞态时,回退到该诊单最新一条通话记录
|
||||
if (!$record) {
|
||||
$record = \app\common\model\tcm\CallRecord::where('diagnosis_id', $diagnosisId)
|
||||
->order('id', 'desc')
|
||||
->find();
|
||||
}
|
||||
$record = self::resolveCallRecordForAttachment($diagnosisId, $adminId, $callRecordId);
|
||||
if (!$record) {
|
||||
self::setError('未找到通话记录');
|
||||
|
||||
@@ -1777,6 +1822,158 @@ class DiagnosisLogic extends BaseLogic
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 诊单回放视频分片上传,完成后显式关联到指定通话记录
|
||||
* @param array $params
|
||||
* @return array|false
|
||||
*/
|
||||
public static function uploadCallRecording(array $params)
|
||||
{
|
||||
$uploadDir = '';
|
||||
$mergedPath = '';
|
||||
try {
|
||||
$diagnosisId = (int)($params['diagnosis_id'] ?? 0);
|
||||
$callRecordId = (int)($params['call_record_id'] ?? 0);
|
||||
$adminId = (int)($params['admin_id'] ?? 0);
|
||||
$uploadId = trim((string)($params['upload_id'] ?? ''));
|
||||
$fileName = trim((string)($params['file_name'] ?? ''));
|
||||
$fileSize = (int)($params['file_size'] ?? 0);
|
||||
$chunkIndex = (int)($params['chunk_index'] ?? -1);
|
||||
$chunkTotal = (int)($params['chunk_total'] ?? 0);
|
||||
|
||||
if (
|
||||
$diagnosisId <= 0 ||
|
||||
$adminId <= 0 ||
|
||||
$uploadId === '' ||
|
||||
$fileName === '' ||
|
||||
$fileSize <= 0 ||
|
||||
$chunkIndex < 0 ||
|
||||
$chunkTotal <= 0
|
||||
) {
|
||||
self::setError('上传参数不完整');
|
||||
return false;
|
||||
}
|
||||
|
||||
$ext = strtolower((string)pathinfo($fileName, PATHINFO_EXTENSION));
|
||||
if ($ext === '' || !in_array($ext, config('project.file_video'), true)) {
|
||||
self::setError('视频格式不支持');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($callRecordId <= 0) {
|
||||
$record = self::createSyntheticCallRecord($diagnosisId, $adminId, $fileName);
|
||||
$callRecordId = (int)($record['id'] ?? 0);
|
||||
} else {
|
||||
$record = self::resolveCallRecordForAttachment($diagnosisId, $adminId, $callRecordId, false);
|
||||
}
|
||||
if (!$record) {
|
||||
self::setError('通话记录不存在');
|
||||
return false;
|
||||
}
|
||||
|
||||
$chunkFile = request()->file('file');
|
||||
if (!$chunkFile) {
|
||||
self::setError('未找到上传分片');
|
||||
return false;
|
||||
}
|
||||
|
||||
$uploadDir = self::callRecordingChunkDir($uploadId);
|
||||
if (!is_dir($uploadDir) && !mkdir($uploadDir, 0777, true) && !is_dir($uploadDir)) {
|
||||
self::setError('创建上传目录失败');
|
||||
return false;
|
||||
}
|
||||
|
||||
file_put_contents($uploadDir . DIRECTORY_SEPARATOR . 'meta.json', json_encode([
|
||||
'diagnosis_id' => $diagnosisId,
|
||||
'call_record_id' => $callRecordId,
|
||||
'admin_id' => $adminId,
|
||||
'file_name' => $fileName,
|
||||
'file_size' => $fileSize,
|
||||
'chunk_total' => $chunkTotal,
|
||||
], JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$chunkPath = $uploadDir . DIRECTORY_SEPARATOR . self::callRecordingChunkName($chunkIndex);
|
||||
$moved = $chunkFile->move($uploadDir, basename($chunkPath));
|
||||
if (!$moved) {
|
||||
self::setError($chunkFile->getError() ?: '保存分片失败');
|
||||
return false;
|
||||
}
|
||||
|
||||
$uploadedCount = self::countUploadedCallRecordingChunks($uploadDir);
|
||||
if ($uploadedCount < $chunkTotal) {
|
||||
return [
|
||||
'completed' => false,
|
||||
'uploaded_chunks' => $uploadedCount,
|
||||
'chunk_total' => $chunkTotal,
|
||||
'call_record_id' => $callRecordId,
|
||||
];
|
||||
}
|
||||
|
||||
$mergedPath = $uploadDir . DIRECTORY_SEPARATOR . 'merged.' . $ext;
|
||||
self::mergeCallRecordingChunks($uploadDir, $mergedPath, $chunkTotal);
|
||||
|
||||
if (!is_file($mergedPath) || filesize($mergedPath) <= 0) {
|
||||
self::setError('合并后的文件无效');
|
||||
return false;
|
||||
}
|
||||
|
||||
$uploadResult = self::storeMergedCallRecording($mergedPath, $fileName, $adminId);
|
||||
if (empty($uploadResult['uri'])) {
|
||||
self::setError('保存视频失败');
|
||||
return false;
|
||||
}
|
||||
|
||||
$attached = self::attachLocalCallRecording([
|
||||
'diagnosis_id' => $diagnosisId,
|
||||
'call_record_id' => $callRecordId,
|
||||
'admin_id' => $adminId,
|
||||
'file_url' => (string)$uploadResult['uri'],
|
||||
]);
|
||||
if (!$attached) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::cleanupCallRecordingChunkDir($uploadDir);
|
||||
|
||||
return [
|
||||
'completed' => true,
|
||||
'uploaded_chunks' => $chunkTotal,
|
||||
'chunk_total' => $chunkTotal,
|
||||
'call_record_id' => $callRecordId,
|
||||
'file_id' => $uploadResult['id'] ?? 0,
|
||||
'file_url' => $uploadResult['uri'] ?? '',
|
||||
'recording_status' => 2,
|
||||
];
|
||||
} catch (\Throwable $e) {
|
||||
if ($mergedPath !== '' && is_file($mergedPath)) {
|
||||
@unlink($mergedPath);
|
||||
}
|
||||
self::setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function createManualCallRecord(array $params)
|
||||
{
|
||||
$diagnosisId = (int)($params['diagnosis_id'] ?? 0);
|
||||
$adminId = (int)($params['admin_id'] ?? 0);
|
||||
if ($diagnosisId <= 0 || $adminId <= 0) {
|
||||
self::setError('参数错误');
|
||||
return false;
|
||||
}
|
||||
|
||||
$record = self::createSyntheticCallRecord($diagnosisId, $adminId, 'manual-upload');
|
||||
if (!$record) {
|
||||
self::setError(self::getError() ?: '创建通话记录失败');
|
||||
return false;
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => (int)($record['id'] ?? 0),
|
||||
'diagnosis_id' => $diagnosisId,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @notes 医助进入当前诊单 TRTC 房间旁观(仅拉流,与医生端 doctor_{id} 账号体系一致)
|
||||
* @param array $params diagnosis_id、admin_id(当前登录后台用户)
|
||||
@@ -3611,4 +3808,152 @@ class DiagnosisLogic extends BaseLogic
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private static function resolveCallRecordForAttachment(
|
||||
int $diagnosisId,
|
||||
int $adminId,
|
||||
int $callRecordId = 0,
|
||||
bool $allowFallback = true
|
||||
)
|
||||
{
|
||||
if ($callRecordId > 0) {
|
||||
$record = \app\common\model\tcm\CallRecord::where('id', $callRecordId)
|
||||
->where('diagnosis_id', $diagnosisId)
|
||||
->find();
|
||||
if ($record) {
|
||||
return $record;
|
||||
}
|
||||
if (!$allowFallback) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
$record = \app\common\model\tcm\CallRecord::where('diagnosis_id', $diagnosisId)
|
||||
->where('caller_id', $adminId)
|
||||
->order('id', 'desc')
|
||||
->find();
|
||||
if ($record || !$allowFallback) {
|
||||
return $record;
|
||||
}
|
||||
|
||||
return \app\common\model\tcm\CallRecord::where('diagnosis_id', $diagnosisId)
|
||||
->order('id', 'desc')
|
||||
->find();
|
||||
}
|
||||
|
||||
private static function createSyntheticCallRecord(int $diagnosisId, int $adminId, string $fileName = '')
|
||||
{
|
||||
$diagnosis = Diagnosis::where('id', $diagnosisId)->find();
|
||||
if (!$diagnosis) {
|
||||
self::setError('诊单不存在');
|
||||
return null;
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$roomSeed = substr(md5($diagnosisId . '-' . $adminId . '-' . $fileName . '-' . $now), 0, 8);
|
||||
|
||||
return \app\common\model\tcm\CallRecord::create([
|
||||
'diagnosis_id' => $diagnosisId,
|
||||
'caller_id' => $adminId,
|
||||
'caller_type' => 'doctor',
|
||||
'callee_id' => (int)($diagnosis['patient_id'] ?? 0),
|
||||
'callee_type' => 'patient',
|
||||
'call_type' => 2,
|
||||
'status' => 2,
|
||||
'start_time' => $now,
|
||||
'end_time' => $now,
|
||||
'duration' => 0,
|
||||
'room_id' => 'manual_upload_' . $roomSeed,
|
||||
'recording_status' => 0,
|
||||
'create_time' => $now,
|
||||
'update_time' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
private static function callRecordingChunkDir(string $uploadId): string
|
||||
{
|
||||
$safeId = preg_replace('/[^a-zA-Z0-9_-]/', '', $uploadId);
|
||||
return runtime_path() . 'call_recording_chunks' . DIRECTORY_SEPARATOR . $safeId;
|
||||
}
|
||||
|
||||
private static function callRecordingChunkName(int $chunkIndex): string
|
||||
{
|
||||
return sprintf('chunk_%06d.part', $chunkIndex);
|
||||
}
|
||||
|
||||
private static function countUploadedCallRecordingChunks(string $uploadDir): int
|
||||
{
|
||||
$files = glob($uploadDir . DIRECTORY_SEPARATOR . 'chunk_*.part');
|
||||
return is_array($files) ? count($files) : 0;
|
||||
}
|
||||
|
||||
private static function mergeCallRecordingChunks(string $uploadDir, string $mergedPath, int $chunkTotal): void
|
||||
{
|
||||
$out = fopen($mergedPath, 'wb');
|
||||
if ($out === false) {
|
||||
throw new \RuntimeException('创建合并文件失败');
|
||||
}
|
||||
|
||||
try {
|
||||
for ($i = 0; $i < $chunkTotal; $i++) {
|
||||
$chunkPath = $uploadDir . DIRECTORY_SEPARATOR . self::callRecordingChunkName($i);
|
||||
if (!is_file($chunkPath)) {
|
||||
throw new \RuntimeException('上传分片缺失,无法合并');
|
||||
}
|
||||
$in = fopen($chunkPath, 'rb');
|
||||
if ($in === false) {
|
||||
throw new \RuntimeException('读取上传分片失败');
|
||||
}
|
||||
stream_copy_to_stream($in, $out);
|
||||
fclose($in);
|
||||
}
|
||||
} finally {
|
||||
fclose($out);
|
||||
}
|
||||
}
|
||||
|
||||
private static function storeMergedCallRecording(string $mergedPath, string $fileName, int $adminId): array
|
||||
{
|
||||
$config = [
|
||||
'default' => ConfigService::get('storage', 'default', 'local'),
|
||||
'engine' => ConfigService::get('storage') ?? ['local' => []],
|
||||
];
|
||||
|
||||
$storageDriver = new StorageDriver($config);
|
||||
$storageDriver->setUploadFileByReal($mergedPath);
|
||||
$saveDir = 'uploads/video/' . date('Ymd');
|
||||
if (!$storageDriver->upload($saveDir)) {
|
||||
throw new \RuntimeException($storageDriver->getError() ?: '上传视频到存储失败');
|
||||
}
|
||||
|
||||
$relativePath = $saveDir . '/' . str_replace('\\', '/', $storageDriver->getFileName());
|
||||
$storedFile = FileModel::create([
|
||||
'cid' => 0,
|
||||
'type' => FileEnum::VIDEO_TYPE,
|
||||
'name' => mb_substr($fileName, 0, 128),
|
||||
'uri' => $relativePath,
|
||||
'source' => FileEnum::SOURCE_ADMIN,
|
||||
'source_id' => $adminId,
|
||||
'create_time' => time(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'id' => (int)($storedFile['id'] ?? 0),
|
||||
'uri' => FileService::getFileUrl($relativePath),
|
||||
'url' => $relativePath,
|
||||
];
|
||||
}
|
||||
|
||||
private static function cleanupCallRecordingChunkDir(string $uploadDir): void
|
||||
{
|
||||
if ($uploadDir === '' || !is_dir($uploadDir)) {
|
||||
return;
|
||||
}
|
||||
foreach ((array)glob($uploadDir . DIRECTORY_SEPARATOR . '*') as $item) {
|
||||
if (is_file($item)) {
|
||||
@unlink($item);
|
||||
}
|
||||
}
|
||||
@rmdir($uploadDir);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user