chore: 优化上传分类规则并新增分享功能

- 新增上传分类归一化处理,统一白名单校验规则
- 新增COS存储记录同步逻辑
- 新增分享功能支持,配置多页面分享参数
- 新增订单案例分享按钮
- 新增订单自动校验和回收命令
- 新增测试脚本和图片同步脚本
- 优化后台上传分类配置,统一分类映射
这个提交包含在:
YuanWen
2026-11-07 09:54:41 +08:00
父节点 a3ff0a3d46
当前提交 68ac7876fd
共有 113 个文件被更改,包括 4126 次插入 和 1512 次删除

查看文件

@@ -123,17 +123,31 @@ class Home extends Base
$appoint = (int)$or['appoint_time'];
$finishTime = !empty($or['finish_time']) ? (int)$or['finish_time'] : (!empty($or['verify_time']) ? (int)$or['verify_time'] : (int)$or['createtime']);
// 图片优先级:订单快照服务图 > 服务表图 > 现场照片第一张 > 类目图标
// 图片优先级:订单快照服务图 > 现场照片第一张 > 服务表大图 > 同类目真实商品图(杜绝使用矢量图标)
$img = '';
if (!empty($or['service_image'])) {
if (!empty($or['service_image']) && substr($or['service_image'], -4) !== '.svg') {
$img = $or['service_image'];
} elseif (!empty($or['s_image'])) {
$img = $or['s_image'];
} elseif (!empty($or['goods_images'])) {
$gImgs = is_array($or['goods_images']) ? $or['goods_images'] : explode(',', (string)$or['goods_images']);
$img = reset($gImgs);
} elseif (!empty($or['cat_icon'])) {
$img = $or['cat_icon'];
$firstG = reset($gImgs);
if ($firstG && substr($firstG, -4) !== '.svg') {
$img = $firstG;
}
} elseif (!empty($or['s_image']) && substr($or['s_image'], -4) !== '.svg') {
$img = $or['s_image'];
}
// 若仍无实物图片,从同类目服务中获取真实高质量商品图,坚决不用矢量小图标
if (empty($img) || substr($img, -4) === '.svg') {
$fallbackImg = Db::name('service')
->where('cat_id', (int)$or['cat_id'])
->where('image', '<>', '')
->where('image', 'not like', '%.svg%')
->order('weigh desc, id asc')
->value('image');
if ($fallbackImg) {
$img = $fallbackImg;
}
}
$imageUrl = $img ? cdnurl($img, true) : '';
@@ -419,6 +433,11 @@ class Home extends Base
// 用户自主定价:出价即订单总价,已包含楼层费/加急费,师傅按此价接单
$base = max(0, round((float)$userPrice, 2));
$total = $base;
} elseif ($type === 'quote') {
// 师傅报价模式:金额由师傅后续竞价给出,下单时总价与应付为 0
$total = 0;
$floorAmount = 0;
$urgentAmount = 0;
} else {
$floor = max(0, (int)$params['floor']);
$freeFloor = $service ? (int)$service['free_floor'] : 2;
@@ -452,7 +471,7 @@ class Home extends Base
return [
'price_type' => $type,
'user_price' => $type === 'custom' ? round($base, 2) : 0,
'base_amount' => round($base, 2),
'base_amount' => $type === 'quote' ? 0 : round($base, 2),
'floor_amount' => round($floorAmount, 2),
'urgent_amount' => round($urgentAmount, 2),
'total_amount' => $total,
@@ -655,9 +674,6 @@ class Home extends Base
{
if (empty($cats)) return [];
foreach ($cats as &$c) {
if ((int)$c['id'] === 15 || $c['name'] === '其它' || $c['name'] === '其他') {
$c['name'] = '全部分类';
}
$icon = (string)$c['icon'];
if ($icon !== '') {
if (strpos($icon, 'http') === 0) {
@@ -793,17 +809,31 @@ class Home extends Base
$st = (int)$order['status'];
$statusText = isset($statusMap[$st]) ? $statusMap[$st] : '已完成';
// 封面图提取
// 封面图提取(优先非矢量真实图片)
$img = '';
if ($service && !empty($service['image'])) {
if (!empty($order['service_image']) && substr($order['service_image'], -4) !== '.svg') {
$img = $order['service_image'];
} elseif (!empty($order['goods_images'])) {
$gImgs = is_array($order['goods_images']) ? $order['goods_images'] : explode(',', (string)$order['goods_images']);
$firstG = reset($gImgs);
if ($firstG && substr($firstG, -4) !== '.svg') {
$img = $firstG;
}
} elseif ($service && !empty($service['image']) && substr($service['image'], -4) !== '.svg') {
$img = $service['image'];
} elseif (!empty($order['goods_image'])) {
$img = $order['goods_image'];
} elseif (!empty($order['repair_images'])) {
$repArr = is_string($order['repair_images']) ? explode(',', $order['repair_images']) : [];
$img = !empty($repArr[0]) ? $repArr[0] : '';
} elseif ($cat && !empty($cat['icon'])) {
$img = $cat['icon'];
}
if (empty($img) || substr($img, -4) === '.svg') {
$fallbackImg = Db::name('service')
->where('cat_id', (int)$order['cat_id'])
->where('image', '<>', '')
->where('image', 'not like', '%.svg%')
->order('weigh desc, id asc')
->value('image');
if ($fallbackImg) {
$img = $fallbackImg;
} elseif ($cat && !empty($cat['icon'])) {
$img = $cat['icon'];
}
}
$imageUrl = $img ? cdnurl($img, true) : '';