feat: 初始化雄戈商城服务端代码与Webhook自动部署配置
这个提交包含在:
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* 清理图片空间中「数据库有记录但物理文件不存在」的附件
|
||||
*
|
||||
* 用法(在项目根目录执行):
|
||||
* php addons/shopro/cleanup_missing_attachments.php --dry-run # 仅预览
|
||||
* php addons/shopro/cleanup_missing_attachments.php # 硬删除无效记录
|
||||
* php addons/shopro/cleanup_missing_attachments.php --soft # 移入回收站(is_del=1)
|
||||
*/
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
http_response_code(403);
|
||||
exit("请通过命令行运行:php addons/shopro/cleanup_missing_attachments.php [--dry-run] [--soft]\n");
|
||||
}
|
||||
|
||||
define('APP_PATH', __DIR__ . '/../../application/');
|
||||
define('ROOT_PATH', __DIR__ . '/../../');
|
||||
|
||||
if (!is_file(APP_PATH . 'admin/command/Install/install.lock')) {
|
||||
fwrite(STDERR, "项目未安装,无法执行。\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require ROOT_PATH . 'thinkphp/base.php';
|
||||
|
||||
\think\App::initCommon();
|
||||
|
||||
use think\Db;
|
||||
|
||||
$argv = $GLOBALS['argv'] ?? [];
|
||||
$dryRun = in_array('--dry-run', $argv, true);
|
||||
$softDelete = in_array('--soft', $argv, true);
|
||||
|
||||
$publicPath = rtrim(ROOT_PATH, '/\\') . DIRECTORY_SEPARATOR . 'public';
|
||||
$batchSize = 500;
|
||||
$lastId = 0;
|
||||
$checked = 0;
|
||||
$missing = 0;
|
||||
$now = time();
|
||||
|
||||
echo "扫描目录:{$publicPath}\n";
|
||||
echo '模式:' . ($dryRun ? '预览(不写入)' : ($softDelete ? '软删除(回收站)' : '硬删除(直接删记录)')) . "\n\n";
|
||||
|
||||
while (true) {
|
||||
$rows = Db::name('attachment')
|
||||
->where('id', '>', $lastId)
|
||||
->where('storage', 'local')
|
||||
->order('id asc')
|
||||
->limit($batchSize)
|
||||
->field('id,url,filename,is_del,mimetype')
|
||||
->select();
|
||||
|
||||
if (empty($rows)) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$row = is_array($row) ? $row : $row->toArray();
|
||||
$lastId = (int)$row['id'];
|
||||
$checked++;
|
||||
|
||||
$url = trim((string)($row['url'] ?? ''));
|
||||
if ($url === '') {
|
||||
$exists = false;
|
||||
} elseif (preg_match('#^https?://#i', $url)) {
|
||||
// 外链不做本地存在性检查
|
||||
continue;
|
||||
} else {
|
||||
$relative = '/' . ltrim(str_replace('\\', '/', $url), '/');
|
||||
$file = $publicPath . str_replace('/', DIRECTORY_SEPARATOR, $relative);
|
||||
$exists = is_file($file);
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$missing++;
|
||||
$name = $row['filename'] ?? '';
|
||||
$delFlag = !empty($row['is_del']) ? ' [已在回收站]' : '';
|
||||
echo "[缺失] id={$row['id']} url={$url} filename={$name}{$delFlag}\n";
|
||||
|
||||
if ($dryRun) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($softDelete) {
|
||||
Db::name('attachment')->where('id', $row['id'])->update([
|
||||
'is_del' => 1,
|
||||
'updatetime' => $now,
|
||||
]);
|
||||
} else {
|
||||
Db::name('attachment')->where('id', $row['id'])->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n完成:共检查 {$checked} 条本地附件,发现缺失 {$missing} 条";
|
||||
echo $dryRun ? '(预览,未修改数据库)' : '(已清理)';
|
||||
echo "\n";
|
||||
在新工单中引用
屏蔽一个用户