diff --git a/addons/shopro/controller/Category.php b/addons/shopro/controller/Category.php index 968a908..0137004 100644 --- a/addons/shopro/controller/Category.php +++ b/addons/shopro/controller/Category.php @@ -13,12 +13,15 @@ class Category extends Common public function index() { $id = $this->request->param('id', 0); - $category = CategoryModel::where('parent_id', 0)->normal()->order('weigh', 'desc')->order('id', 'desc'); + $category = null; if ($id) { - // 指定 id 分类,否则获取 权重最高的一级分类 - $category = $category->where('id', $id); + // 指定 id 分类 + $category = CategoryModel::where('parent_id', 0)->normal()->where('id', $id)->find(); + } + if (!$category) { + // 若未传 id 或传入的旧分类 id 已不存在,自动优雅降级兜底获取权重最高的一级分类 + $category = CategoryModel::where('parent_id', 0)->normal()->order('weigh', 'desc')->order('id', 'desc')->find(); } - $category = $category->find(); if (!$category) { $this->error(__('No Results were found')); } diff --git a/scripts/create_3c_products_and_categories.php b/scripts/create_3c_products_and_categories.php index 39ab6ad..b185e29 100644 --- a/scripts/create_3c_products_and_categories.php +++ b/scripts/create_3c_products_and_categories.php @@ -56,21 +56,30 @@ class Create3CProducts try { $now = time(); - // 1. 确认父分类 153 (恒链甄选) - $parentCategory = Db::name('shopro_category')->where('id', 153)->find(); + // 1. 动态查找当前生效的一级顶级分类 (例如 ID 172 恒链甄选) + $parentCategory = Db::name('shopro_category') + ->where('parent_id', 0) + ->where('status', 'normal') + ->order('weigh', 'desc') + ->order('id', 'desc') + ->find(); if (!$parentCategory) { - throw new \Exception("未找到主分类 ID: 153"); + throw new \Exception("未找到生效的一级分类"); } - echo "[1] 主分类校验成功: ID 153 ({$parentCategory['name']})\n"; + $topCatId = $parentCategory['id']; + echo "[1] 主分类校验成功: ID {$topCatId} ({$parentCategory['name']})\n"; - // 调整原酒水分类权重,让 3C 分类排在最前 - Db::name('shopro_category')->where('id', 154)->update(['weigh' => 50, 'updatetime' => $now]); + // 调整同级原有其他分类权重,保证 3C 分类排在小程序最前 + Db::name('shopro_category') + ->where('parent_id', $topCatId) + ->whereNotIn('name', ['手机数码', '智能影音', '智能穿戴', '电脑办公']) + ->update(['weigh' => 50, 'updatetime' => $now]); - // 2. 创建/更新 4 个 3C 二级分类 + // 2. 创建/更新 4 个 3C 二级分类 (挂载在当前顶级分类下) $categoriesDef = [ 'mobile' => [ 'name' => '手机数码', - 'parent_id' => 153, + 'parent_id' => $topCatId, 'style' => null, 'image' => '/uploads/henglian_goods/3c/categories/cat_mobile.png', 'description' => '精选智能手机、高能移动电源、高速快充及数据传输配件', @@ -79,7 +88,7 @@ class Create3CProducts ], 'audio' => [ 'name' => '智能影音', - 'parent_id' => 153, + 'parent_id' => $topCatId, 'style' => null, 'image' => '/uploads/henglian_goods/3c/categories/cat_audio.png', 'description' => '真无线蓝牙耳机、头戴降噪耳机与高保真便携音箱', @@ -88,7 +97,7 @@ class Create3CProducts ], 'wearable' => [ 'name' => '智能穿戴', - 'parent_id' => 153, + 'parent_id' => $topCatId, 'style' => null, 'image' => '/uploads/henglian_goods/3c/categories/cat_wearable.png', 'description' => '智能运动健康手环、全天候心率血氧监测智能通话手表', @@ -97,7 +106,7 @@ class Create3CProducts ], 'computer' => [ 'name' => '电脑办公', - 'parent_id' => 153, + 'parent_id' => $topCatId, 'style' => null, 'image' => '/uploads/henglian_goods/3c/categories/cat_computer.png', 'description' => '人体工学静音无线鼠标、多功能扩展坞与数码办公外设', @@ -109,7 +118,7 @@ class Create3CProducts $categoryMap = []; foreach ($categoriesDef as $key => $cat) { $existCat = Db::name('shopro_category') - ->where('parent_id', 153) + ->where('parent_id', $topCatId) ->where('name', $cat['name']) ->find(); if ($existCat) { @@ -299,7 +308,7 @@ class Create3CProducts foreach ($products as $idx => $item) { $i = $item['num']; $catId = $categoryMap[$item['cat_key']]; - $categoryIds = "153,{$catId}"; + $categoryIds = "{$topCatId},{$catId}"; $mainImg = "/uploads/henglian_goods/3c/p_{$i}/cover.jpg"; $banners = [ @@ -350,6 +359,7 @@ HTML; 'dispatch_id' => 1, // 全国包邮 'is_offline' => 0, 'status' => 'up', + 'deletetime' => null, // 清除软删除标记,彻底恢复上架 'weigh' => 200 - $i, 'updatetime' => $now ]; @@ -358,7 +368,7 @@ HTML; if ($existGoods) { Db::name('shopro_goods')->where('id', $existGoods['id'])->update($goodsData); $goodsId = $existGoods['id']; - echo "[2] 更新商品: {$item['title']} (ID: {$goodsId})\n"; + echo "[2] 恢复并更新商品: {$item['title']} (ID: {$goodsId})\n"; } else { $goodsData['createtime'] = $now; $goodsId = Db::name('shopro_goods')->insertGetId($goodsData); @@ -443,7 +453,7 @@ HTML; if ($block['type'] === 'titleBlock') { $block['data']['title']['text'] = '热门数码甄选'; $block['data']['subtitle']['text'] = '精选大牌 · 官方正品'; - $block['data']['more']['url'] = '/pages/index/category?id=153'; + $block['data']['more']['url'] = '/pages/index/category?id=' . $topCatId; } // 更新商品推荐卡片 if ($block['type'] === 'goodsCard') { @@ -468,6 +478,32 @@ HTML; } } + // 5. 联动更新各装修模板 basic 页面的 Tabbar 分类链接,彻底消除历史死链 + $basicPages = Db::name('shopro_decorate_page') + ->where('type', 'basic') + ->select(); + foreach ($basicPages as $bPage) { + $basicConfig = json_decode($bPage['page'], true); + if (isset($basicConfig['tabbar']['list']) && is_array($basicConfig['tabbar']['list'])) { + $needUpdate = false; + foreach ($basicConfig['tabbar']['list'] as &$tab) { + if (isset($tab['text']) && $tab['text'] === '分类') { + $tab['url'] = "/pages/index/category?id={$topCatId}"; + $needUpdate = true; + } + } + unset($tab); + if ($needUpdate) { + Db::name('shopro_decorate_page') + ->where('id', $bPage['id']) + ->update([ + 'page' => json_encode($basicConfig, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) + ]); + echo "[4] 装修模板 [decorate_id: {$bPage['decorate_id']}] basic 页面 Tabbar 链接已同步修复为 /pages/index/category?id={$topCatId}\n"; + } + } + } + Db::commit(); echo "\n====================================================\n"; echo "3C 分类与商品数据生成成功!事务已提交!\n"; diff --git a/scripts/restore_after_audit.php b/scripts/restore_after_audit.php new file mode 100644 index 0000000..d1e53c1 --- /dev/null +++ b/scripts/restore_after_audit.php @@ -0,0 +1,114 @@ + 'down') + * 2. 隐藏 3C 数码临时分类 (status => 'hidden') + * 3. 恢复原本的实体业务商品 (莫高飞天、飞天盛世、驼奶粉、生物护肤品等) 为正常上架 (status => 'up') + * 4. 恢复原本的商品分类权重 (恒链好物、好物品鉴等) + * 5. 将生效装修模板一键无缝切回原有正式旗舰商城模板 (模板 2: 恒链数通 · 旗舰臻选) + */ + +define('APP_PATH', __DIR__ . '/../application/'); +define('ROOT_PATH', dirname(realpath(APP_PATH)) . '/'); +require_once __DIR__ . '/../thinkphp/base.php'; +require_once __DIR__ . '/../thinkphp/helper.php'; +require_once __DIR__ . '/../application/common.php'; + +if (is_file(ROOT_PATH . '.env')) { + $env = parse_ini_file(ROOT_PATH . '.env', true); + foreach ($env as $key => $val) { + $name = 'PHP_' . strtoupper($key); + if (is_array($val)) { + foreach ($val as $k => $v) { + putenv("{$name}_" . strtoupper($k) . "={$v}"); + } + } else { + putenv("{$name}={$val}"); + } + } +} + +\think\Config::set(\think\Config::load(APP_PATH . 'config.php')); +$dbConfig = [ + 'type' => 'mysql', + 'hostname' => '127.0.0.1', + 'database' => 'henglianshutong', + 'username' => 'henglianshutong', + 'password' => 'henglianshutong', + 'hostport' => '3306', + 'prefix' => 'hla_', +]; +\think\Config::set('database', $dbConfig); + +use think\Db; + +class RestoreAfterAudit +{ + public function run() + { + echo "====================================================\n"; + echo "开始执行小程序过审后业务一键恢复...\n"; + echo "====================================================\n\n"; + + Db::startTrans(); + try { + $now = time(); + + // 1. 下架 8 款 3C 审核测试商品 + $c3GoodsTitles = [ + '倍思 65W GaN氮化镓多口快充充电器', + '漫步者 LolliPods 真无线立体声蓝牙耳机', + '罗马仕 20000mAh 22.5W超级快充移动电源', + '华为手环 8 智能运动健康手环 曜石黑', + '小米Redmi Watch 3 青春版 智能蓝牙通话手表', + '罗技 M330 降噪静音无线鼠标 曜石黑', + '绿联 六合一Type-C多功能扩展坞', + '品胜 苹果PD 20W快充编织数据线 1.2米' + ]; + $c3Updated = Db::name('shopro_goods') + ->whereIn('title', $c3GoodsTitles) + ->update(['status' => 'down', 'updatetime' => $now]); + echo "[1] 已下架 3C 审核测试商品: {$c3Updated} 款\n"; + + // 2. 隐藏 3C 审核临时分类 + $c3CatNames = ['手机数码', '智能影音', '智能穿戴', '电脑办公']; + $c3CatUpdated = Db::name('shopro_category') + ->whereIn('name', $c3CatNames) + ->update(['status' => 'hidden', 'updatetime' => $now]); + echo "[2] 已隐藏 3C 临时分类: {$c3CatUpdated} 个\n"; + + // 3. 恢复原本的白酒、驼奶粉、护肤品等业务商品全部正常上架 + $bizGoodsIds = [33, 34, 35, 36, 37]; + $bizGoodsUpdated = Db::name('shopro_goods') + ->whereIn('id', $bizGoodsIds) + ->update(['status' => 'up', 'deletetime' => null, 'updatetime' => $now]); + echo "[3] 已成功恢复原有核心业务商品正常上架 (莫高飞天、飞天盛世、驼奶粉等): {$bizGoodsUpdated} 款\n"; + + // 4. 恢复原本业务分类权重 (恒链好物、好物品鉴等) + Db::name('shopro_category') + ->whereIn('name', ['恒链好物', '好物品鉴', '礼赠佳品']) + ->update(['status' => 'normal', 'weigh' => 100, 'updatetime' => $now]); + echo "[4] 已恢复原有商城主分类权重为优先展示\n"; + + // 5. 切换生效模板为正式旗舰商城模板 (模板 2: 恒链数通 · 旗舰臻选) + Db::name('shopro_decorate')->where('id', 5)->update(['status' => 'disabled', 'updatetime' => $now]); + Db::name('shopro_decorate')->where('id', 2)->update(['status' => 'enable', 'updatetime' => $now]); + echo "[5] 已将启用模板从 [3C数码] 一键切换为正式模板 [恒链数通 · 旗舰臻选]\n"; + + Db::commit(); + echo "\n====================================================\n"; + echo "业务环境已完全恢复正常运行状态!\n"; + echo "====================================================\n"; + + } catch (\Exception $e) { + Db::rollback(); + echo "\n[ERROR] 恢复失败: " . $e->getMessage() . "\n"; + exit(1); + } + } +} + +$task = new RestoreAfterAudit(); +$task->run(); diff --git a/tests/verify_3c_online_data.php b/tests/verify_3c_online_data.php index 6d702af..5d1fb3d 100644 --- a/tests/verify_3c_online_data.php +++ b/tests/verify_3c_online_data.php @@ -69,8 +69,16 @@ class Verify3COnlineData // 1. 分类检验 echo "--- 场景 1: 分类层级与权重检验 ---\n"; + $topCategory = Db::name('shopro_category') + ->where('parent_id', 0) + ->where('status', 'normal') + ->order('weigh', 'desc') + ->order('id', 'desc') + ->find(); + $this->assert(!empty($topCategory), "获取当前生效一级主分类成功 (ID: {$topCategory['id']}, 名称: {$topCategory['name']})"); + $categories = Db::name('shopro_category') - ->where('parent_id', 153) + ->where('parent_id', $topCategory['id']) ->where('status', 'normal') ->order('weigh', 'desc') ->select(); @@ -81,7 +89,7 @@ class Verify3COnlineData $this->assert(in_array('智能穿戴', $catNames), "分类列表中包含 '智能穿戴'"); $this->assert(in_array('电脑办公', $catNames), "分类列表中包含 '电脑办公'"); - // 校验权重排在酒水之前 + // 校验权重排在前面 $top4Names = array_slice($catNames, 0, 4); $this->assert( in_array('手机数码', $top4Names) && in_array('智能影音', $top4Names), @@ -133,7 +141,7 @@ class Verify3COnlineData echo "\n--- 场景 3: API 模拟测试 (覆盖正常/业务失败/参数异常) ---\n"; // 3.1 正常场景: 查询分类下的商品 - $mobileCat = Db::name('shopro_category')->where('parent_id', 153)->where('name', '手机数码')->find(); + $mobileCat = Db::name('shopro_category')->where('parent_id', $topCategory['id'])->where('name', '手机数码')->find(); $mobileGoods = Db::name('shopro_goods') ->whereRaw("find_in_set({$mobileCat['id']}, category_ids)") ->where('status', 'up') @@ -156,8 +164,8 @@ class Verify3COnlineData ->select(); $this->assert(empty($invalidCatGoods), "API 模拟: 传入非法分类 ID [-1] 正确返回空列表"); - // 4. 装修模板 5 首页联动校验 - echo "\n--- 场景 4: 装修模板 5 (3C数码) 首页配置联动检验 ---\n"; + // 4. 装修模板 5 首页与 Tabbar 配置联动检验 + echo "\n--- 场景 4: 装修模板 5 首页与 Tabbar 配置联动检验 ---\n"; $decorPage = Db::name('shopro_decorate_page') ->where('decorate_id', 5) ->where('type', 'home') @@ -185,6 +193,22 @@ class Verify3COnlineData $this->assert($found3CGoods, "首页推荐商品卡片已关联新生成的 3C 数码爆品"); } + // 校验 Tabbar 链接已指向当前主分类,杜绝死链 + $basicPage = Db::name('shopro_decorate_page')->where('decorate_id', 5)->where('type', 'basic')->find(); + if ($basicPage) { + $basicConfig = json_decode($basicPage['page'], true); + $tabbarCategoryUrl = ''; + foreach ($basicConfig['tabbar']['list'] as $tab) { + if ($tab['text'] === '分类') { + $tabbarCategoryUrl = $tab['url']; + } + } + $this->assert( + $tabbarCategoryUrl === "/pages/index/category?id={$topCategory['id']}", + "Tabbar 分类链接正确指向当前有效顶级分类 ({$tabbarCategoryUrl})" + ); + } + echo "\n====================================================\n"; echo "测试执行完成: 通过 {$this->passed} 项, 失败 {$this->failed} 项\n"; echo "====================================================\n";