From 6d5572108d883649980ef421cd120b4733e943b0 Mon Sep 17 00:00:00 2001 From: Ghost <106998207@qq.com> Date: Mon, 27 Apr 2026 11:07:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A1=E6=A0=B8=E6=A8=A1=E5=BC=8F=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/common.php | 395 +++++++++++---------- api/app/common/service/MpTabbarService.php | 4 +- api/app/controller/api/Gaokao.php | 28 ++ api/app/controller/api/Test.php | 12 +- miniprogram/app.js | 4 +- miniprogram/custom-tab-bar/index.js | 4 +- miniprogram/pages/gaokao/form.js | 15 +- miniprogram/pages/gaokao/index.js | 15 +- miniprogram/pages/gaokao/report.js | 98 ++--- miniprogram/pages/history/index.js | 6 +- miniprogram/pages/test-select/index.js | 11 +- miniprogram/pages/test-select/index.wxml | 3 +- miniprogram/utils/miniprogramAuditGate.js | 1 + 13 files changed, 350 insertions(+), 246 deletions(-) diff --git a/api/app/common.php b/api/app/common.php index 5a65724..9c4672b 100644 --- a/api/app/common.php +++ b/api/app/common.php @@ -1,185 +1,210 @@ - $code, - 'message' => $message, - 'data' => $data - ]); -} - -/** - * 成功响应 - * @param mixed $data 数据 - * @param string $message 消息 - * @return \think\response\Json - */ -function success($data = null, $message = 'success') -{ - return json_response(200, $message, $data); -} - -/** - * 错误响应 - * @param string $message 错误消息 - * @param int $code 错误码 - * @return \think\response\Json - */ -function error($message = 'error', $code = 400) -{ - return json_response($code, $message, null); -} - -/** - * 分页响应 - * @param array $list 列表数据 - * @param int $total 总数 - * @param int $page 当前页 - * @param int $pageSize 每页数量 - * @return \think\response\Json - */ -function paginate_response($list, $total, $page = 1, $pageSize = 10) -{ - return success([ - 'list' => $list, - 'total' => $total, - 'page' => $page, - 'pageSize' => $pageSize, - 'hasMore' => ($page * $pageSize) < $total - ]); -} - -if (!function_exists('requestCurl')) { - /** - * @param string $url 请求的链接 - * @param array $params 请求附带的参数 - * @param string $method 请求的方式, 支持GET, POST, PUT, DELETE等 - * @param array $header 头部 - * @param string $type 数据类型,支持dataBuild、json等 - * @return bool|string - */ - function requestCurl($url, $params = [], $method = 'GET', $header = [], $type = 'dataBuild') - { - $str = ''; - if (!empty($url)) { - try { - $ch = curl_init(); - - // 处理GET请求的参数 - if (strtoupper($method) == 'GET' && !empty($params)) { - $url = $url . '?' . dataBuild($params); - } - - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_TIMEOUT, 30); //30秒超时 - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); - curl_setopt($ch, CURLOPT_HTTPHEADER, $header); - - // 处理不同的请求方法 - if (strtoupper($method) != 'GET') { - // 设置请求方法 - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method)); - - // 处理参数格式 - if ($type == 'dataBuild') { - $params = dataBuild($params); - } elseif ($type == 'json') { - $params = json_encode($params); - } else { - $params = dataBuild($params); - } - - // 设置请求体 - curl_setopt($ch, CURLOPT_POSTFIELDS, $params); - } - - curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //是否验证对等证书,1则验证,0则不验证 - curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); - $str = curl_exec($ch); - curl_close($ch); - } catch (Exception $e) { - $str = ''; - } - } - return $str; - } -} - - -if (!function_exists('dataBuild')) { - function dataBuild($array) - { - if (!is_array($array)) { - return $array; - } - - // 处理嵌套数组 - foreach ($array as $key => $value) { - if (is_array($value)) { - $array[$key] = json_encode($value); - } - } - - return http_build_query($array); - } -} - - -if (!function_exists('setHeader')) { - /** - * 设置头部 - * - * @param array $headerData 头部数组 - * @param string $authorization - * @param string $type 类型 默认json (json,plain) - * @return array - */ - function setHeader($headerData = [], $authorization = '', $type = '') - { - $header = $headerData; - - switch ($type) { - case 'json': - $header[] = 'Content-Type:application/json'; - break; - case 'html' : - $header[] = 'Content-Type:text/html'; - break; - case 'plain' : - $header[] = 'Content-Type:text/plain'; - break; - default: - $header[] = 'Content-Type:application/json'; - } -// $header[] = $type == 'plain' ? 'Content-Type:text/plain' : 'Content-Type: application/json'; - if ($authorization !== "") $header[] = 'Authorization:Bearer ' . $authorization; - return $header; - } -} - -/** - * 小程序提审模式是否开启(读 system_config.system JSON 的 miniprogramAuditMode)。 - * 正式环境若未部署 MiniprogramAuditMode.php,视为未开启,避免 Class not found 致命错误。 - */ -if (!function_exists('miniprogram_audit_mode_on')) { - function miniprogram_audit_mode_on(): bool - { - if (!class_exists(\app\common\service\MiniprogramAuditMode::class, true)) { - return false; - } - - return \app\common\service\MiniprogramAuditMode::isOn(); - } -} - + $code, + 'message' => $message, + 'data' => $data + ]); +} + +/** + * 成功响应 + * @param mixed $data 数据 + * @param string $message 消息 + * @return \think\response\Json + */ +function success($data = null, $message = 'success') +{ + return json_response(200, $message, $data); +} + +/** + * 错误响应 + * @param string $message 错误消息 + * @param int $code 错误码 + * @return \think\response\Json + */ +function error($message = 'error', $code = 400) +{ + return json_response($code, $message, null); +} + +/** + * 分页响应 + * @param array $list 列表数据 + * @param int $total 总数 + * @param int $page 当前页 + * @param int $pageSize 每页数量 + * @return \think\response\Json + */ +function paginate_response($list, $total, $page = 1, $pageSize = 10) +{ + return success([ + 'list' => $list, + 'total' => $total, + 'page' => $page, + 'pageSize' => $pageSize, + 'hasMore' => ($page * $pageSize) < $total + ]); +} + +if (!function_exists('requestCurl')) { + /** + * @param string $url 请求的链接 + * @param array $params 请求附带的参数 + * @param string $method 请求的方式, 支持GET, POST, PUT, DELETE等 + * @param array $header 头部 + * @param string $type 数据类型,支持dataBuild、json等 + * @return bool|string + */ + function requestCurl($url, $params = [], $method = 'GET', $header = [], $type = 'dataBuild') + { + $str = ''; + if (!empty($url)) { + try { + $ch = curl_init(); + + // 处理GET请求的参数 + if (strtoupper($method) == 'GET' && !empty($params)) { + $url = $url . '?' . dataBuild($params); + } + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); //30秒超时 + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); + + // 处理不同的请求方法 + if (strtoupper($method) != 'GET') { + // 设置请求方法 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method)); + + // 处理参数格式 + if ($type == 'dataBuild') { + $params = dataBuild($params); + } elseif ($type == 'json') { + $params = json_encode($params); + } else { + $params = dataBuild($params); + } + + // 设置请求体 + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + } + + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); //是否验证对等证书,1则验证,0则不验证 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + $str = curl_exec($ch); + curl_close($ch); + } catch (Exception $e) { + $str = ''; + } + } + return $str; + } +} + + +if (!function_exists('dataBuild')) { + function dataBuild($array) + { + if (!is_array($array)) { + return $array; + } + + // 处理嵌套数组 + foreach ($array as $key => $value) { + if (is_array($value)) { + $array[$key] = json_encode($value); + } + } + + return http_build_query($array); + } +} + + +if (!function_exists('setHeader')) { + /** + * 设置头部 + * + * @param array $headerData 头部数组 + * @param string $authorization + * @param string $type 类型 默认json (json,plain) + * @return array + */ + function setHeader($headerData = [], $authorization = '', $type = '') + { + $header = $headerData; + + switch ($type) { + case 'json': + $header[] = 'Content-Type:application/json'; + break; + case 'html' : + $header[] = 'Content-Type:text/html'; + break; + case 'plain' : + $header[] = 'Content-Type:text/plain'; + break; + default: + $header[] = 'Content-Type:application/json'; + } +// $header[] = $type == 'plain' ? 'Content-Type:text/plain' : 'Content-Type: application/json'; + if ($authorization !== "") $header[] = 'Authorization:Bearer ' . $authorization; + return $header; + } +} + +/** + * 小程序提审模式是否开启(读 system_config.system JSON 的 miniprogramAuditMode)。 + * 正式环境若未部署 MiniprogramAuditMode.php,视为未开启,避免 Class not found 致命错误。 + */ +if (!function_exists('miniprogram_audit_mode_on')) { + function miniprogram_audit_mode_on(): bool + { + if (!class_exists(\app\common\service\MiniprogramAuditMode::class, true)) { + return false; + } + + return \app\common\service\MiniprogramAuditMode::isOn(); + } +} + +/** + * 提审模式或面相审核(system.maintenanceMode)时隐藏高考志愿相关能力(与小程序 isAuditHideAiMode 对齐) + */ +if (!function_exists('audit_mode_blocks_gaokao_api')) { + function audit_mode_blocks_gaokao_api(): bool + { + if (miniprogram_audit_mode_on()) { + return true; + } + try { + $row = \think\facade\Db::name('system_config')->where('key', 'system')->find(); + if ($row && !empty($row['value'])) { + $v = is_string($row['value']) ? json_decode($row['value'], true) : $row['value']; + if (is_array($v) && !empty($v['maintenanceMode'])) { + return true; + } + } + } catch (\Throwable $e) { + return false; + } + + return false; + } +} + diff --git a/api/app/common/service/MpTabbarService.php b/api/app/common/service/MpTabbarService.php index 61619c6..6f4473c 100644 --- a/api/app/common/service/MpTabbarService.php +++ b/api/app/common/service/MpTabbarService.php @@ -57,11 +57,9 @@ class MpTabbarService } if (empty($list)) { - // 顺序:首页 · 第2项凸起拍摄 · 神仙AI · 我(与小程序 app.json tabBar.list 一致) + // 无库内配置时:仅首页 + 我;拍摄 / 神仙 AI 需在超管 TabBar 中配置 visible 后才会下发 $list = [ ['id' => 0, 'pagePath' => 'pages/index/index', 'text' => '首页', 'iconKey' => 'home', 'iconUrl' => null, 'highlight' => false, 'badgeKey' => null], - ['id' => 0, 'pagePath' => 'pages/index/camera', 'text' => '拍摄', 'iconKey' => 'camera', 'iconUrl' => null, 'highlight' => true, 'badgeKey' => null], - ['id' => 0, 'pagePath' => 'pages/ai-chat/index', 'text' => '神仙AI', 'iconKey' => 'ai', 'iconUrl' => null, 'highlight' => false, 'badgeKey' => null], ['id' => 0, 'pagePath' => 'pages/profile/index', 'text' => '我', 'iconKey' => 'profile', 'iconUrl' => null, 'highlight' => false, 'badgeKey' => null], ]; } diff --git a/api/app/controller/api/Gaokao.php b/api/app/controller/api/Gaokao.php index 4d9e9ff..3f1341c 100644 --- a/api/app/controller/api/Gaokao.php +++ b/api/app/controller/api/Gaokao.php @@ -19,12 +19,25 @@ class Gaokao extends BaseController return (int) ($user['user_id'] ?? $user['userId'] ?? 0); } + /** 与小程序审核/面相审核隐藏高考入口一致 */ + private function rejectGaokaoIfAuditMode() + { + if (audit_mode_blocks_gaokao_api()) { + return error('版本审核中暂不可用', 503); + } + + return null; + } + public function taskStatus() { $uid = $this->wechatUserId(); if ($uid <= 0) { return error('未登录', 401); } + if ($r = $this->rejectGaokaoIfAuditMode()) { + return $r; + } $entry = [ 'referrerId' => (int) Request::param('referrerId', 0), 'channelCode' => (string) Request::param('channelCode', ''), @@ -47,6 +60,9 @@ class Gaokao extends BaseController if ($uid <= 0) { return error('未登录', 401); } + if ($r = $this->rejectGaokaoIfAuditMode()) { + return $r; + } $form = Request::post(); if (!is_array($form)) { $form = []; @@ -61,6 +77,9 @@ class Gaokao extends BaseController if ($uid <= 0) { return error('未登录', 401); } + if ($r = $this->rejectGaokaoIfAuditMode()) { + return $r; + } $profile = GaokaoService::getOrInitProfile($uid); return success([ 'form' => GaokaoService::formJsonAsArray($profile), @@ -74,6 +93,9 @@ class Gaokao extends BaseController if ($uid <= 0) { return error('未登录', 401); } + if ($r = $this->rejectGaokaoIfAuditMode()) { + return $r; + } $pricingScope = trim((string) Request::param('pricingScope', 'personal')); $eidParam = (int) Request::param('enterpriseId', 0); $res = GaokaoService::createAnalysis( @@ -93,6 +115,9 @@ class Gaokao extends BaseController if ($uid <= 0) { return error('未登录', 401); } + if ($r = $this->rejectGaokaoIfAuditMode()) { + return $r; + } $row = GaokaoService::myLatestReport($uid); if (!$row) { return error('暂无报告', 404); @@ -106,6 +131,9 @@ class Gaokao extends BaseController if ($uid <= 0) { return error('未登录', 401); } + if ($r = $this->rejectGaokaoIfAuditMode()) { + return $r; + } $productCode = trim((string) Request::param('productCode', 'gaokao_single_report')); $pricingScope = trim((string) Request::param('pricingScope', 'personal')); $eidParam = (int) Request::param('enterpriseId', 0); diff --git a/api/app/controller/api/Test.php b/api/app/controller/api/Test.php index 6fd7635..579d3c5 100644 --- a/api/app/controller/api/Test.php +++ b/api/app/controller/api/Test.php @@ -399,7 +399,9 @@ class Test extends BaseController if ($boundEnterpriseId > 0) { $allowed[] = 'resume'; } - if (!in_array('gaokao', $allowed, true)) { + // 提审 / 面相审核:与小程序隐藏高考入口一致,历史接口不再返回 gaokao + $hideGaokao = miniprogram_audit_mode_on() || $reviewMode; + if (!$hideGaokao && !in_array('gaokao', $allowed, true)) { $allowed[] = 'gaokao'; } @@ -616,6 +618,10 @@ class Test extends BaseController return error('记录不存在', 404); } + if (($row['testType'] ?? '') === 'gaokao' && audit_mode_blocks_gaokao_api()) { + return error('版本审核中暂不可用', 503); + } + if (($row['testType'] ?? '') === 'gaokao' && (int) ($row['isPaid'] ?? 0) === 0) { $ps = trim((string) Request::param('pricingScope', 'personal')); $eid = (int) Request::param('enterpriseId', 0); @@ -662,6 +668,10 @@ class Test extends BaseController } $rowTestType = (string) ($row['testType'] ?? ''); + if ($rowTestType === 'gaokao' && audit_mode_blocks_gaokao_api()) { + return error('版本审核中暂不可用', 503); + } + if ($rowTestType === 'resume') { return error('该类型不支持分享查看', 403); } diff --git a/miniprogram/app.js b/miniprogram/app.js index 67c3e23..77e1cb4 100644 --- a/miniprogram/app.js +++ b/miniprogram/app.js @@ -58,8 +58,8 @@ App({ defaultEnterpriseId: null, // API 基础地址:默认走线上;本机/内网调试可在开发者工具执行 // wx.setStorageSync('apiBaseOverride', 'https://你的调试域名') 后重启小程序 - //apiBase: 'https://mbtiapi.quwanzhi.com', - apiBase: 'http://mbti.com', + apiBase: 'https://mbtiapi.quwanzhi.com', + //apiBase: 'http://mbti.com', // VIP信息 vipInfo: null, // 测试次数 diff --git a/miniprogram/custom-tab-bar/index.js b/miniprogram/custom-tab-bar/index.js index 7ed7b40..6b1b16e 100644 --- a/miniprogram/custom-tab-bar/index.js +++ b/miniprogram/custom-tab-bar/index.js @@ -1,13 +1,11 @@ // 自定义 TabBar:完全由后台配置驱动 // 数据来源:app.globalData.tabBar.items(GET /api/mp/tabbar) -// 兜底:首页 · 拍摄(第2项凸起) · 神仙AI · 我 +// 兜底(无后台配置或不足 2 项时):仅首页 + 我;拍摄 / 神仙 AI 默认不展示,由超管 TabBar 配置显式开启 const { isAuditHideAiMode, shouldHideTabBarHighlightFab } = require('../utils/miniprogramAuditGate.js') const DEFAULT_ITEMS = [ { pagePath: 'pages/index/index', text: '首页', iconKey: 'home', iconUrl: '', highlight: false }, - { pagePath: 'pages/index/camera', text: '拍摄', iconKey: 'camera', iconUrl: '', highlight: true }, - { pagePath: 'pages/ai-chat/index', text: '神仙AI', iconKey: 'ai', iconUrl: '', iconUrlActive: '', highlight: false }, { pagePath: 'pages/profile/index', text: '我', iconKey: 'profile', iconUrl: '', highlight: false } ] diff --git a/miniprogram/pages/gaokao/form.js b/miniprogram/pages/gaokao/form.js index 37a9fed..3c26915 100644 --- a/miniprogram/pages/gaokao/form.js +++ b/miniprogram/pages/gaokao/form.js @@ -1,4 +1,6 @@ const gaokaoApi = require('../../utils/gaokao') +const app = getApp() +const { isAuditHideAiMode, redirectIfMiniprogramAudit } = require('../../utils/miniprogramAuditGate.js') /** 科类/选科备选项:首项为占位,不可作为有效保存值 */ const SUBJECT_PLACEHOLDER = '请选择科类/选科' @@ -119,7 +121,18 @@ Page({ /** 每次页面展示拉取(含从上级页返回),避免栈内页面不触发 onLoad 时看不到已保存内容 */ onShow() { - this.loadFormFromServer() + const run = () => { + if (isAuditHideAiMode(app.globalData)) { + redirectIfMiniprogramAudit('版本审核中暂不可用') + return + } + this.loadFormFromServer() + } + if (app.getRuntimeConfig) { + app.getRuntimeConfig().finally(run) + } else { + run() + } }, loadFormFromServer() { diff --git a/miniprogram/pages/gaokao/index.js b/miniprogram/pages/gaokao/index.js index c619680..e586867 100644 --- a/miniprogram/pages/gaokao/index.js +++ b/miniprogram/pages/gaokao/index.js @@ -1,4 +1,6 @@ const gaokaoApi = require('../../utils/gaokao') +const app = getApp() +const { isAuditHideAiMode, redirectIfMiniprogramAudit } = require('../../utils/miniprogramAuditGate.js') Page({ data: { @@ -16,7 +18,18 @@ Page({ }, onShow() { - this.refreshStatus() + const run = () => { + if (isAuditHideAiMode(app.globalData)) { + redirectIfMiniprogramAudit('版本审核中暂不可用') + return + } + this.refreshStatus() + } + if (app.getRuntimeConfig) { + app.getRuntimeConfig().finally(run) + } else { + run() + } }, refreshStatus() { diff --git a/miniprogram/pages/gaokao/report.js b/miniprogram/pages/gaokao/report.js index 80d07b3..9dbda3b 100644 --- a/miniprogram/pages/gaokao/report.js +++ b/miniprogram/pages/gaokao/report.js @@ -13,6 +13,7 @@ const inviteCodeGate = require('../../utils/inviteCodeGate.js') const { openTimelineShareHint } = require('../../utils/resultProfileGate.js') const { computeJourney, markShared } = require('../../utils/gaokaoJourneyState.js') const { getEnterpriseIdForApiPayload } = require('../../utils/enterpriseContext.js') +const { isAuditHideAiMode, redirectIfMiniprogramAudit } = require('../../utils/miniprogramAuditGate.js') /** GET /api/test/detail | share-detail 返回体 -> mergeApiReport 入参 */ function mapTestDetailToReportPayload(detail) { @@ -241,55 +242,60 @@ Page({ }, onLoad(options) { - try { - wx.showShareMenu({ withShareTicket: true, menus: ['shareAppMessage', 'shareTimeline'] }) - } catch (e) {} + const bootstrap = () => { + if (isAuditHideAiMode(app.globalData)) { + redirectIfMiniprogramAudit('版本审核中暂不可用') + return + } + try { + wx.showShareMenu({ withShareTicket: true, menus: ['shareAppMessage', 'shareTimeline'] }) + } catch (e) {} - const fromShareFs = options && (String(options.fs) === '1' || options.from === 'share') - const sid = options && options.id != null && options.id !== '' ? String(options.id) : '' - const st = options && options.st ? String(options.st).trim() : '' + const fromShareFs = options && (String(options.fs) === '1' || options.from === 'share') + const sid = options && options.id != null && options.id !== '' ? String(options.id) : '' + const st = options && options.st ? String(options.st).trim() : '' - if (sid && st) { - this.setData({ fromShare: true }) - this.loadShareDetail(sid, st) - return + if (sid && st) { + this.setData({ fromShare: true }) + this.loadShareDetail(sid, st) + return + } + + const ec = + typeof this.getOpenerEventChannel === 'function' ? this.getOpenerEventChannel() : null + if (ec && typeof ec.once === 'function') { + ec.once('gaokaoAnalyzeReport', (payload) => { + if (payload && payload.report) { + this.applyPayloadOnly({ + id: payload.id, + createdAt: payload.createdAt || 0, + overview: payload.overview || '', + report: payload.report + }) + } + }) + } + + const pendingAnalyze = options && String(options.pendingAnalyze) === '1' + if (pendingAnalyze) { + // 等 runtime 后再跑;用微任务启动分析,避免原 onReady 与异步 onLoad 竞态 + setTimeout(() => this.beginAnalyzeFlow(), 0) + return + } + + const rid = options && options.id != null ? parseInt(String(options.id), 10) : 0 + this._detailReportId = rid > 0 && !Number.isNaN(rid) ? rid : 0 + if (fromShareFs) { + this.setData({ fromShare: true }) + } + + const delay = options && options.fromAnalyze === '1' ? 400 : 0 + setTimeout(() => this.load(), delay) } - - const ec = - typeof this.getOpenerEventChannel === 'function' ? this.getOpenerEventChannel() : null - if (ec && typeof ec.once === 'function') { - ec.once('gaokaoAnalyzeReport', (payload) => { - if (payload && payload.report) { - this.applyPayloadOnly({ - id: payload.id, - createdAt: payload.createdAt || 0, - overview: payload.overview || '', - report: payload.report - }) - } - }) - } - - const pendingAnalyze = options && String(options.pendingAnalyze) === '1' - if (pendingAnalyze) { - this._pendingAnalyze = true - return - } - - const rid = options && options.id != null ? parseInt(String(options.id), 10) : 0 - this._detailReportId = rid > 0 && !Number.isNaN(rid) ? rid : 0 - if (fromShareFs) { - this.setData({ fromShare: true }) - } - - const delay = options && options.fromAnalyze === '1' ? 400 : 0 - setTimeout(() => this.load(), delay) - }, - - onReady() { - if (this._pendingAnalyze) { - this._pendingAnalyze = false - this.beginAnalyzeFlow() + if (app.getRuntimeConfig) { + app.getRuntimeConfig().then(bootstrap).catch(bootstrap) + } else { + bootstrap() } }, diff --git a/miniprogram/pages/history/index.js b/miniprogram/pages/history/index.js index 492276a..2580c84 100644 --- a/miniprogram/pages/history/index.js +++ b/miniprogram/pages/history/index.js @@ -1,6 +1,7 @@ // pages/history/index.js - 测试历史记录(一次拉取全部,时间行右侧展示企业名) const app = getApp() const { getEffectiveEnterpriseId } = require('../../utils/enterpriseContext.js') +const { isAuditHideAiMode } = require('../../utils/miniprogramAuditGate.js') Page({ data: { @@ -106,7 +107,10 @@ Page({ if (res.statusCode === 200 && res.data && res.data.data) { const payload = res.data.data const rawList = payload.list || [] - const formatted = this.formatList(rawList) + let formatted = this.formatList(rawList) + if (isAuditHideAiMode(app.globalData)) { + formatted = formatted.filter((it) => String(it.type || it.testType || '').toLowerCase() !== 'gaokao') + } const total = typeof payload.total === 'number' ? payload.total : formatted.length const hasMore = !!payload.hasMore if (append) { diff --git a/miniprogram/pages/test-select/index.js b/miniprogram/pages/test-select/index.js index 8635ea5..24aed6c 100644 --- a/miniprogram/pages/test-select/index.js +++ b/miniprogram/pages/test-select/index.js @@ -9,8 +9,10 @@ Page({ permSbti: true, permPdp: true, permDisc: true, - /** 高考志愿任务中心;企业关闭 gaokao 时隐藏 */ + /** 高考志愿任务中心;企业关闭 gaokao 或审核/提审时隐藏 */ permGaokao: true, + /** 与 permAiHub 同源:用于简介文案不提及高考/神仙 AI */ + auditHideAiFeatures: false, /** AI 对话(神仙 AI);企业关闭 aiHub 时隐藏 */ permAiHub: true, /** 四类问卷入口均被企业权限关闭时提示 */ @@ -45,7 +47,7 @@ Page({ const permSbti = !p || p.sbti !== false const permPdp = !p || p.pdp !== false const permDisc = !p || p.disc !== false - const permGaokao = !p || p.gaokao !== false + const permGaokao = (!p || p.gaokao !== false) && !hideAi const permAiHub = (!p || p.aiHub !== false) && !hideAi this.setData({ permFace, @@ -55,6 +57,7 @@ Page({ permDisc, permGaokao, permAiHub, + auditHideAiFeatures: hideAi, allTestsDisabled: p && !permMbti && !permSbti && !permPdp && !permDisc && !permGaokao }) }, @@ -84,6 +87,10 @@ Page({ }, goGaokaoHub() { + if (isAuditHideAiMode(app.globalData)) { + wx.showToast({ title: '版本审核中暂不可用', icon: 'none' }) + return + } if (!this.data.permGaokao) { wx.showToast({ title: '当前企业未开放高考志愿功能', icon: 'none' }) return diff --git a/miniprogram/pages/test-select/index.wxml b/miniprogram/pages/test-select/index.wxml index faf4a2c..600d18e 100644 --- a/miniprogram/pages/test-select/index.wxml +++ b/miniprogram/pages/test-select/index.wxml @@ -2,7 +2,8 @@ 选择一项详细性格测试 - 问卷测评、高考志愿规划与 AI 对话 / 拍照面相分项进入,完成后可获得对应报告 + 问卷测评与拍照面相分项进入,完成后可获得对应报告 + 问卷测评、高考志愿规划与 AI 对话 / 拍照面相分项进入,完成后可获得对应报告 diff --git a/miniprogram/utils/miniprogramAuditGate.js b/miniprogram/utils/miniprogramAuditGate.js index b1f1459..19d3cc1 100644 --- a/miniprogram/utils/miniprogramAuditGate.js +++ b/miniprogram/utils/miniprogramAuditGate.js @@ -2,6 +2,7 @@ * 超管审核相关:隐藏神仙 AI Tab/入口;提审模式下另由后端/各页关闭虚拟商品与「了解自己」深度套餐。 * - miniprogramAuditMode:提审专用(含虚拟支付合规) * - maintenanceMode / reviewMode:面相审核(用户口语「审核模式」常指其一) + * - 高考志愿:与 isAuditHideAiMode 一致时在 test-select 隐藏入口,高考各页跳转回首页;后端见 audit_mode_blocks_gaokao_api */ /** 临时:为 true 时在客户端忽略审核/提审隐藏逻辑。平时必须为 false,由 runtime 与后端 miniprogramAuditMode 等决定展示 */