* @Date: 2026-07-21 13:36:46 * @LastEditors: YwxApp * @LastEditTime: 2026-08-04 22:21:46 * @Description: 应用市场统一路由(业务路由 + 对外 API) * @FilePath: \ywxapp_dev\app\appmall\route\app.php * @CustomString: Copyright (c) 2026 YwxApp */ // ============================================================ // 应用市场「统一路由入口」(业务路由 + 对外 API)。 // // appmall 已由插件(addon/appmall)迁移为普通应用(app/appmall),对外前缀 /appmall 不变: // think-multi-app 的 MultiApp 中间件按目录名解析 URL 首段 appmall → 命中 app/appmall/, // 并将 pathinfo 剥离首段(→ backend/xxx、developer/xxx、api/addon/*、store 等), // 再由框架自动加载本目录(app/appmall/route/*.php)。 // // 因此本文件内的路由一律写成「相对组名」,与剥离首段后的 pathinfo 直接对齐: // backend/... → /appmall/backend/... // developer/... → /appmall/developer/... // api/... → /appmall/api/... // 本文件【不要】自行写 /appmall 前缀(会双重前缀,恒 404)。 // ============================================================ use think\facade\Route; use app\appmall\controller\api\Market; use app\appmall\controller\backend\AddonReview; use app\appmall\controller\backend\Developer; use app\appmall\controller\backend\Revenue as BackendRevenue; use app\appmall\controller\Developer as DeveloperCenter; use app\appmall\controller\backend\Framework; use app\appmall\controller\api\Framework as ApiFramework; use app\appmall\controller\Framework as FrontendFramework; use app\appmall\controller\Store; use app\backend\controller\Rule; // ===================== 业务路由 + 对外 API(/appmall/*) ===================== // 前缀 /appmall 由 MultiApp 解析并剥离首段,本文件只写相对组名(见文件头说明)。 // ---------- 后台:插件审核 / 开发者管理 / 收益与结算(统一前缀 /appmall/backend) ---------- Route::group('backend', function () { // 插件审核 Route::get('addonreview', [AddonReview::class, 'index']); Route::get('addonreview/index', [AddonReview::class, 'index']); Route::post('addonreview/approve', [AddonReview::class, 'approve']); Route::post('addonreview/reject', [AddonReview::class, 'reject']); Route::post('addonreview/updatePrice', [AddonReview::class, 'updatePrice']); Route::get('addonreview/download', [AddonReview::class, 'download']); Route::get('addonreview/detail', [AddonReview::class, 'detail']); Route::get('addonreview/detailview', [AddonReview::class, 'detailview']); Route::get('addonreview/history', [AddonReview::class, 'history']); // 用户评价审核(appmall_addon_reviews,区别于 submissions 的上架审核) Route::get('commentreview', [AddonReview::class, 'comments']); Route::get('commentreview/index', [AddonReview::class, 'comments']); Route::post('commentreview/approve', [AddonReview::class, 'approveComment']); Route::post('commentreview/reject', [AddonReview::class, 'rejectComment']); Route::post('commentreview/delete', [AddonReview::class, 'deleteComment']); // 开发者管理 Route::get('developer', [Developer::class, 'index']); Route::get('developer/index', [Developer::class, 'index']); Route::post('developer/approve', [Developer::class, 'approve']); Route::post('developer/disable', [Developer::class, 'disable']); Route::post('developer/resend', [Developer::class, 'resend']); Route::post('developer/reset', [Developer::class, 'reset']); // 收益与结算 Route::get('revenue', [BackendRevenue::class, 'index']); Route::get('revenue/index', [BackendRevenue::class, 'index']); Route::get('revenue/withdrawals', [BackendRevenue::class, 'withdrawals']); Route::post('revenue/settle', [BackendRevenue::class, 'settle']); Route::post('revenue/reject', [BackendRevenue::class, 'rejectWithdrawal']); // 主框架升级(原 upgrade 插件,已合并进 market) Route::get('framework', [Framework::class, 'index']); Route::get('framework/index', [Framework::class, 'index']); Route::post('framework/upload', [Framework::class, 'upload']); Route::post('framework/publish', [Framework::class, 'publish']); Route::post('framework/delete', [Framework::class, 'delete']); Route::get('framework/download', [Framework::class, 'download']); }); // ---------- 开发者中心(独立前台应用,公开注册/令牌/收益/提现,非会员中心):统一前缀 /appmall/developer ---------- // 仅【中心站】暴露:开发者自助注册/收益/提现依赖 appmall_developers / appmall_addon_revenues / appmall_addon_withdrawals 等 // 运营表,客户机(ywxapp.api_url 指向其他服务器,见 is_market_client())作为中心站客户端不持有这些表,故不在路由层注册, // 访问即 404。配合 Developer 控制器 initialize() 的运行时兜底(即便路由缓存陈旧或被直连也能拦截)。 // ---------- 开发者中心(独立前台,令牌认证):/appmall/Developer/* ---------- Route::get('developer/index', [DeveloperCenter::class, 'index']); Route::post('developer/save', [DeveloperCenter::class, 'save']); Route::get('developer/mine', [DeveloperCenter::class, 'mine']); Route::post('developer/lookup', [DeveloperCenter::class, 'lookup']); Route::get('developer/dashboard', [DeveloperCenter::class, 'dashboard']); Route::get('developer/console', [DeveloperCenter::class, 'console']); Route::post('developer/overview', [DeveloperCenter::class, 'overview']); Route::post('developer/apps', [DeveloperCenter::class, 'apps']); Route::post('developer/price', [DeveloperCenter::class, 'price']); Route::post('developer/earnings', [DeveloperCenter::class, 'earnings']); Route::post('developer/withdraw', [DeveloperCenter::class, 'withdraw']); // ---------- 对外 API(统一前缀 /appmall/api):远程客户机经 Remote/Addon/FrameworkService 调用 ---------- // 由 MultiApp 剥离首段 appmall 后与本文件的 api 组对齐 → /appmall/api/* //(与 /appmall/backend、/appmall/developer 同构,均为「应用名开头」约定)。 // 调用方契约(勿单侧改动): // RemoteAppmallService → /appmall/api/addon/*、/appmall/api/index // AddonService → /appmall/api/addon/valid、/appmall/api/index/index // FrameworkService → /appmall/api/framework/version、/appmall/api/framework/download Route::group('api', function () { Route::get('addon/lists', [Market::class, 'lists']); Route::get('addon/info', [Market::class, 'info']); Route::post('addon/valid', [Market::class, 'valid']); Route::post('addon/submit', [Market::class, 'submit']); Route::post('addon/buy', [Market::class, 'buy']); Route::get('addon/orderStatus', [Market::class, 'orderStatus']); Route::post('addon/notify', [Market::class, 'notify']); Route::get('addon/payResult', [Market::class, 'payResult']); Route::post('addon/refund', [Market::class, 'refund']); Route::get('addon/my', [Market::class, 'my']); // 免费试用:商品配置 trial_days 后可用,一个用户对同一插件一次 Route::post('addon/trial', [Market::class, 'trial']); // 插件评价:列表(公开已审核)+ 提交(待审) Route::get('addon/reviews', [Market::class, 'reviews']); Route::post('addon/review', [Market::class, 'review']); // 插件 zip 下载(RemoteAppmallService 走 /appmall/api/index,AddonService 走 /appmall/api/index/index) Route::get('index', [Market::class, 'index']); Route::get('index/index', [Market::class, 'index']); // 主框架升级分发(FrameworkService 走 /appmall/api/framework/*) Route::get('framework/version', [ApiFramework::class, 'version']); Route::get('framework/download', [ApiFramework::class, 'download']); }); // ---------- 前台展示(公开,仅中心站):主框架发布/下载页 + 应用商店 ---------- // 前台控制器直接置于 app\appmall\controller 下(如 ForumFrontend 惯例), // 不套 frontend 子目录;URL 前缀为 /appmall/framework、/appmall/store。 Route::get('framework', [FrontendFramework::class, 'index']); Route::get('framework/index', [FrontendFramework::class, 'index']); // 应用商店:上线插件列表(/appmall/store) Route::get('store', [Store::class, 'index'])->completeMatch(); Route::get('store/index', [Store::class, 'index'])->completeMatch(); // 裸访问 /appmall:本应用无 Index 控制器,落地到应用商店列表页,避免 404 Route::get('/', [Store::class, 'index']); // 插件详情页(/appmall/store/detail/) Route::get('store/detail/:name', [Store::class, 'detail']) ->pattern(['name' => '[\w\-]+']); // 详情页购买 / 试用(买断、订阅续费、跨大版本升级均走 buy,服务端按授权状态判定金额) Route::post('store/buy', [Store::class, 'buy']); Route::post('store/trial', [Store::class, 'trial']); Route::rule('store/:action', 'Store/:action', 'GET');