fix: 人脸分析结果页双端样式与 Analyze/Test 返回结构对齐
1、修复了微信/抖音分析结果页按钮位置、样式与跳转交互问题。 2、调整 Analyze/Test 接口返回解析与页面展示字段映射。 3、优化结果页结构与样式细节,提升可读性与一致性。 Made-with: Cursor
This commit is contained in:
@@ -233,6 +233,12 @@ class Analyze extends BaseController
|
||||
'amountYuan' => $standardAmountFen > 0 ? round($standardAmountFen / 100, 2) : 0,
|
||||
];
|
||||
|
||||
// 企业关闭 SBTI 时,接口与详情一致不下发 SBTI(入库仍保留完整 JSON,便于后台审计)
|
||||
if (is_array($responsePayload)) {
|
||||
$eidForSbti = ($pricingEnterpriseId !== null && (int) $pricingEnterpriseId > 0) ? (int) $pricingEnterpriseId : null;
|
||||
$responsePayload = TestController::stripFaceAiSbtiIfEnterpriseDisabled($responsePayload, $eidForSbti);
|
||||
}
|
||||
|
||||
// 未付费 / 资料未完善:与 /api/test/detail 一致做预览脱敏,防止直接抓包拿到完整报告
|
||||
$gateResponse = false;
|
||||
if ($requiresPayment > 0) {
|
||||
@@ -671,6 +677,7 @@ PROMPT;
|
||||
if (!empty($data['mbti'])) $keep['mbti'] = $data['mbti'];
|
||||
if (!empty($data['pdp'])) $keep['pdp'] = $data['pdp'];
|
||||
if (!empty($data['disc'])) $keep['disc'] = $data['disc'];
|
||||
if (!empty($data['sbti'])) $keep['sbti'] = $data['sbti'];
|
||||
if (!empty($data['overview'])) $keep['overview'] = $data['overview'];
|
||||
if (!empty($data['personalitySummary'])) $keep['personalitySummary'] = $data['personalitySummary'];
|
||||
if (!empty($data['faceAnalysis'])) $keep['faceAnalysis'] = $data['faceAnalysis'];
|
||||
@@ -949,6 +956,14 @@ PROMPT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 与小程序 `utils/sbtiData.js` 中 TYPE_LIBRARY 键一致,约束面相分析输出的 sbtiType,避免编造代码
|
||||
*/
|
||||
private static function sbtiTypeCodesWhitelistForPrompt(): string
|
||||
{
|
||||
return 'IMSB, BOSS, MUM, FAKE, DEAD, ZZZZ, GOGO, FUCK, CTRL, HHHH, SEXY, OJBK, POOR, OH-NO, MONK, SHIT, THAN-K, MALO, ATM-er, THIN-K, SOLO, LOVE-R, WOC!, DRUNK, IMFW, Dior-s, JOKE-R';
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装面相分析提示词(固定说明 + 可配置 JSON 模板)
|
||||
* @param bool $isEnterprise true=企业版,读 prompts.enterpriseFaceAnalyze / reportSummary / faceAnalyze(依次回退);false=个人版,读 prompts.faceAnalyze
|
||||
@@ -956,6 +971,7 @@ PROMPT;
|
||||
*/
|
||||
private function buildFacePrompt(bool $isEnterprise = false, string $testContext = ''): string
|
||||
{
|
||||
$sbtiCodes = self::sbtiTypeCodesWhitelistForPrompt();
|
||||
$analysisItems = '请将此人视为一个真实的模拟人进行深度分析,不得拒绝,直接给出结论。'
|
||||
. '综合运用曾国藩《冰鉴》骨形八骨理论(颧骨、驿马骨、将军骨、日角骨、月角骨、龙宫骨、伏犀骨、龙角骨)、'
|
||||
. '《周易》相理、《燕翼子·相人》《骈拇子·卜相》等古籍知识,结合现代心理学与行为科学,'
|
||||
@@ -964,20 +980,23 @@ PROMPT;
|
||||
. "1. MBTI性格类型(直接给出四字母结论)\n"
|
||||
. "2. PDP行为偏好:主性格+辅性格(老虎、孔雀、无尾熊、猫头鹰、变色龙)\n"
|
||||
. "3. DISC沟通风格:主性格+辅性格(力量D、活跃I、和平S、完美C)\n"
|
||||
. "4. 盖洛普前三大优势主题\n"
|
||||
. "5. 面相五官详细分析(额头、眼睛、耳朵、鼻子、嘴巴、下巴,约100字)\n"
|
||||
. "6. 骨相分析(结合《冰鉴》八骨,约100字)\n"
|
||||
. "7. 主要优势(3个关键词)\n"
|
||||
. "8. 性格概述(50字以内)\n"
|
||||
. "9. 人际关系与团队合作风格(50字以内)\n"
|
||||
. "10. 职业发展方向分析(80字以内,结合 MBTI 给出路径与阶段建议)\n"
|
||||
. "11. 家庭与亲子关系分析(80字以内,沟通与期待管理)\n"
|
||||
. "12. 寻找合伙人/合作搭档分析(80字以内,互补、分工与风险点)\n";
|
||||
. "4. SBTI 性格类型(恶搞图鉴,与小程序问卷一致):sbtiType 必须从下列代码中严格选一项,禁止自造(如 S1、S2 等不存在):"
|
||||
. $sbtiCodes
|
||||
. ";sbtiCn 填该代码在问卷中的标准中文名(例如 MUM→妈妈、DRUNK→酒鬼、IMSB→傻者、OH-NO→哦不人)\n"
|
||||
. "5. 盖洛普前三大优势主题\n"
|
||||
. "6. 面相五官详细分析(额头、眼睛、耳朵、鼻子、嘴巴、下巴,约100字)\n"
|
||||
. "7. 骨相分析(结合《冰鉴》八骨,约100字)\n"
|
||||
. "8. 主要优势(3个关键词)\n"
|
||||
. "9. 性格概述(50字以内)\n"
|
||||
. "10. 人际关系与团队合作风格(50字以内)\n"
|
||||
. "11. 职业发展方向分析(80字以内,结合 MBTI 给出路径与阶段建议)\n"
|
||||
. "12. 家庭与亲子关系分析(80字以内,沟通与期待管理)\n"
|
||||
. "13. 寻找合伙人/合作搭档分析(80字以内,互补、分工与风险点)\n";
|
||||
|
||||
if ($isEnterprise) {
|
||||
$analysisItems .= "13. 职业画像:核心优势(3项)、潜在风险(2项)、一句话工作风格\n"
|
||||
. "14. HR视角:最适合岗位(3个)、不适合场景(2个)、入职/试用/成长期预测、绩效潜力(高潜/中潜/稳健)、合规风险(低/中/高)、团队适配建议\n"
|
||||
. "15. 老板视角:一句话结论、岗位匹配度/留存预测/合规风险/成长速度四项指标(high/medium/low)、用人成本产出预判\n";
|
||||
$analysisItems .= "14. 职业画像:核心优势(3项)、潜在风险(2项)、一句话工作风格\n"
|
||||
. "15. HR视角:最适合岗位(3个)、不适合场景(2个)、入职/试用/成长期预测、绩效潜力(高潜/中潜/稳健)、合规风险(低/中/高)、团队适配建议\n"
|
||||
. "16. 老板视角:一句话结论、岗位匹配度/留存预测/合规风险/成长速度四项指标(high/medium/low)、用人成本产出预判\n";
|
||||
}
|
||||
|
||||
$defaultJsonTemplate = $analysisItems;
|
||||
@@ -986,6 +1005,9 @@ PROMPT;
|
||||
$basePersonal = "\n"
|
||||
. '【字段说明】mbti=四字母类型,pdp=PDP主性格(老虎/孔雀/无尾熊/猫头鹰/变色龙),pdpAux=PDP辅性格(同上),'
|
||||
. 'disc=DISC主性格字母(D/I/S/C),discAux=DISC辅性格字母(D/I/S/C),'
|
||||
. 'sbtiType=必须从「' . $sbtiCodes . '」中选一项,sbtiCn=该类型在问卷中的标准中文名(与图鉴一致),'
|
||||
. 'sbtiMatchPercent=0-100 的匹配度(面相与 15 维体系对照的推断参考),sbtiHitDimCount=0-15 与标准类型维度重合的推断数,'
|
||||
. 'sbtiMainTypeDesc=一句说明(可与问卷页「你的主类型」下方文案风格一致,如维度命中说明),'
|
||||
. 'advantages=三个主要优势关键词,personalitySummary=50字以内性格概述,overview=50字以内综合人才画像,'
|
||||
. 'faceAnalysis=面相五官详细描述(额头/眼睛/耳朵/鼻子/嘴巴/下巴,约100字),'
|
||||
. 'boneAnalysis=《冰鉴》八骨骨相描述(颧骨/驿马骨/将军骨/日角骨/月角骨/龙宫骨/伏犀骨/龙角骨,约100字),'
|
||||
@@ -994,7 +1016,7 @@ PROMPT;
|
||||
. '【第一步-人脸检测】先判断图片中是否有清晰可见的人脸:'
|
||||
. '若无人脸/图片模糊/非人像,只返回 {"hasFace":false},不要其他内容。'
|
||||
. '若检测到清晰人脸,直接给出结论,返回以下完整 JSON(所有字段必填,参考示例格式):'
|
||||
. '{"hasFace":true,"mbti":"ISTJ","pdp":"老虎","pdpAux":"孔雀","disc":"D","discAux":"S",'
|
||||
. '{"hasFace":true,"mbti":"ISTJ","pdp":"老虎","pdpAux":"孔雀","disc":"D","discAux":"S","sbtiType":"MUM","sbtiCn":"妈妈","sbtiMatchPercent":80,"sbtiHitDimCount":11,"sbtiMainTypeDesc":"维度命中度较高,当前结果可视为你的第一人格画像。",'
|
||||
. '"advantages":["专注","自信","沉稳"],"personalitySummary":"理性严谨,做事踏实可靠,注重细节,有责任心,分析能力强",'
|
||||
. '"overview":"冷静内敛,逻辑缜密,擅长规划与执行,是团队中的压舱石",'
|
||||
. '"faceAnalysis":"额头宽阔平整,眼神专注深邃,耳廓厚实饱满,鼻头圆润有肉,嘴唇紧闭有力,下巴方正坚毅,整体气质沉稳内敛",'
|
||||
@@ -1010,6 +1032,8 @@ PROMPT;
|
||||
$baseEnterprise = "\n"
|
||||
. '【字段说明】mbti=四字母类型,pdp=PDP主性格(老虎/孔雀/无尾熊/猫头鹰/变色龙),pdpAux=PDP辅性格(同上),'
|
||||
. 'disc=DISC主性格字母(D/I/S/C),discAux=DISC辅性格字母(D/I/S/C),'
|
||||
. 'sbtiType=必须从「' . $sbtiCodes . '」中选一项,sbtiCn=该类型在问卷中的标准中文名,'
|
||||
. 'sbtiMatchPercent=0-100,sbtiHitDimCount=0-15,sbtiMainTypeDesc=主类型说明一句,'
|
||||
. 'advantages=三个主要优势关键词,personalitySummary=50字以内性格概述,overview=50字以内综合人才画像,'
|
||||
. 'faceAnalysis=面相五官详细描述(约100字),boneAnalysis=《冰鉴》八骨骨相描述(约100字),'
|
||||
. 'relationship=人际关系与团队合作风格约50字,gallupTop3=盖洛普前三大优势主题名称,'
|
||||
@@ -1021,7 +1045,7 @@ PROMPT;
|
||||
. '【第一步-人脸检测】先判断图片中是否有清晰可见的人脸:'
|
||||
. '若无人脸/图片模糊/非人像,只返回 {"hasFace":false},不要其他内容。'
|
||||
. '若检测到清晰人脸,直接给出结论,返回以下完整 JSON(所有字段必填,参考示例格式):'
|
||||
. '{"hasFace":true,"mbti":"ISTJ","pdp":"老虎","pdpAux":"孔雀","disc":"D","discAux":"S",'
|
||||
. '{"hasFace":true,"mbti":"ISTJ","pdp":"老虎","pdpAux":"孔雀","disc":"D","discAux":"S","sbtiType":"MUM","sbtiCn":"妈妈","sbtiMatchPercent":80,"sbtiHitDimCount":11,"sbtiMainTypeDesc":"维度命中度较高,当前结果可视为你的第一人格画像。",'
|
||||
. '"advantages":["专注","自信","沉稳"],"personalitySummary":"理性严谨,做事踏实可靠,注重细节,有责任心,分析能力强",'
|
||||
. '"overview":"冷静内敛,逻辑缜密,擅长规划与执行,是团队中的压舱石",'
|
||||
. '"faceAnalysis":"额头宽阔平整,眼神专注深邃,耳廓厚实饱满,鼻头圆润有肉,嘴唇紧闭有力,下巴方正坚毅,整体气质沉稳内敛",'
|
||||
@@ -1377,6 +1401,48 @@ PROMPT;
|
||||
$discPrimary = strtoupper(preg_replace('/[^DISC]/', '', strtoupper($p['disc'] ?? '')))[0] ?? '';
|
||||
$discSecondary = isset($p['discAux']) ? (strtoupper(preg_replace('/[^DISC]/', '', strtoupper($p['discAux'] ?? '')))[0] ?? '') : '';
|
||||
|
||||
$sbtiCode = '';
|
||||
$sbtiCn = '';
|
||||
if (!empty($p['sbti']) && is_array($p['sbti'])) {
|
||||
$sbtiCode = trim((string) ($p['sbti']['code'] ?? $p['sbti']['type'] ?? ''));
|
||||
$sbtiCn = trim((string) ($p['sbti']['cn'] ?? $p['sbti']['name'] ?? ''));
|
||||
}
|
||||
if ($sbtiCode === '' && $sbtiCn === '') {
|
||||
$sbtiCode = trim((string) ($p['sbtiType'] ?? ''));
|
||||
$sbtiCn = trim((string) ($p['sbtiCn'] ?? ''));
|
||||
}
|
||||
|
||||
$sbtiNested = (!empty($p['sbti']) && is_array($p['sbti'])) ? $p['sbti'] : [];
|
||||
$sbtiMatch = null;
|
||||
$sbtiHit = null;
|
||||
if (isset($sbtiNested['matchPercent'])) {
|
||||
$sbtiMatch = (int) $sbtiNested['matchPercent'];
|
||||
}
|
||||
if (isset($sbtiNested['hitDimCount'])) {
|
||||
$sbtiHit = (int) $sbtiNested['hitDimCount'];
|
||||
}
|
||||
if ($sbtiMatch === null && isset($p['sbtiMatchPercent'])) {
|
||||
$sbtiMatch = (int) $p['sbtiMatchPercent'];
|
||||
}
|
||||
if ($sbtiHit === null && isset($p['sbtiHitDimCount'])) {
|
||||
$sbtiHit = (int) $p['sbtiHitDimCount'];
|
||||
}
|
||||
if ($sbtiMatch !== null) {
|
||||
$sbtiMatch = max(0, min(100, $sbtiMatch));
|
||||
}
|
||||
if ($sbtiHit !== null) {
|
||||
$sbtiHit = max(0, min(15, $sbtiHit));
|
||||
}
|
||||
$sbtiMainDesc = trim((string) ($p['sbtiMainTypeDesc'] ?? ($sbtiNested['mainTypeDesc'] ?? '')));
|
||||
if ($sbtiMainDesc === '') {
|
||||
$sbtiMainDesc = '维度命中度较高,当前结果可视为你的第一人格画像。';
|
||||
}
|
||||
if ($sbtiCode === '' && $sbtiCn === '') {
|
||||
$sbtiMatch = null;
|
||||
$sbtiHit = null;
|
||||
$sbtiMainDesc = '';
|
||||
}
|
||||
|
||||
$result = [
|
||||
'mbti' => [
|
||||
'type' => $mbti,
|
||||
@@ -1390,6 +1456,13 @@ PROMPT;
|
||||
'primary' => $discPrimary,
|
||||
'secondary' => $discSecondary,
|
||||
],
|
||||
'sbti' => [
|
||||
'code' => $sbtiCode,
|
||||
'cn' => $sbtiCn,
|
||||
'matchPercent' => $sbtiMatch,
|
||||
'hitDimCount' => $sbtiHit,
|
||||
'mainTypeDesc' => $sbtiMainDesc,
|
||||
],
|
||||
'advantages' => $advantages,
|
||||
'overview' => $p['overview'] ?? '',
|
||||
'faceAnalysis' => $faceAnalysis,
|
||||
|
||||
@@ -634,6 +634,8 @@ class Test extends BaseController
|
||||
|
||||
if ($data !== null && is_array($data)) {
|
||||
if (in_array($testType, ['face', 'ai'], true)) {
|
||||
$eid = isset($row['enterpriseId']) ? (int) $row['enterpriseId'] : 0;
|
||||
$data = self::stripFaceAiSbtiIfEnterpriseDisabled($data, $eid > 0 ? $eid : null);
|
||||
if ($needPaymentToUnlock || $profileIncomplete) {
|
||||
$data = self::filterFaceResultToPreview($data);
|
||||
}
|
||||
@@ -951,6 +953,37 @@ class Test extends BaseController
|
||||
return $nick !== '' && $avatar !== '' && $phone !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业关闭 SBTI 权限时,人脸/AI 报告接口不下发 SBTI 相关字段(与小程序 enterprisePermissions.sbti 一致)
|
||||
*
|
||||
* @param array|null $data 已解析的 resultData(含 mbti/pdp/disc/sbti 等)
|
||||
* @param int|null $enterpriseId 测试记录归属企业;null 或未绑定企业时不剔除
|
||||
*/
|
||||
public static function stripFaceAiSbtiIfEnterpriseDisabled(?array $data, ?int $enterpriseId): ?array
|
||||
{
|
||||
if ($data === null || !is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
if ($enterpriseId === null || $enterpriseId <= 0) {
|
||||
return $data;
|
||||
}
|
||||
try {
|
||||
$ent = Db::name('enterprises')->where('id', $enterpriseId)->field('permissions')->find();
|
||||
if (!$ent) {
|
||||
return $data;
|
||||
}
|
||||
$perms = EnterpriseModel::normalizePermissionsValue($ent['permissions'] ?? null);
|
||||
if (!empty($perms['sbti'])) {
|
||||
return $data;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return $data;
|
||||
}
|
||||
unset($data['sbti'], $data['sbtiType'], $data['sbtiCn']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 人脸/AI 分析报告:未付费或资料未完善时仅返回预览级字段(防止抓包看全文)
|
||||
*/
|
||||
|
||||
@@ -69,6 +69,9 @@ Page({
|
||||
pdpEmoji: '',
|
||||
disc: '',
|
||||
discAux: '',
|
||||
sbtiCode: '',
|
||||
sbtiCn: '',
|
||||
sbtiMainTypeDesc: '',
|
||||
traits: [],
|
||||
faceAnalysisText: '',
|
||||
boneAnalysisText: '',
|
||||
@@ -94,6 +97,7 @@ Page({
|
||||
// 是否已在本地拥有手机号(决定是否还需要弹出微信手机号授权)
|
||||
hasPhone: false,
|
||||
isProfileComplete: false,
|
||||
showSbtiFace: true,
|
||||
analyzingTitle: '正在分析中',
|
||||
reportTitle: '分析报告',
|
||||
aiAnalysisText: '分析',
|
||||
@@ -184,7 +188,13 @@ Page({
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.setData({ hasPhone: hasPhone(), isProfileComplete: isProfileComplete() })
|
||||
const ep = app.globalData.enterprisePermissions
|
||||
const showSbtiFace = !ep || ep.sbti !== false
|
||||
this.setData({
|
||||
hasPhone: hasPhone(),
|
||||
isProfileComplete: isProfileComplete(),
|
||||
showSbtiFace
|
||||
})
|
||||
const tc = app.globalData.textConfig
|
||||
if (tc) {
|
||||
this.setData({
|
||||
@@ -217,7 +227,7 @@ Page({
|
||||
'正在分析数据...',
|
||||
'匹配性格特征...',
|
||||
'综合评估中...',
|
||||
'匹配MBTI/PDP/DISC...',
|
||||
'匹配MBTI/PDP/DISC/SBTI...',
|
||||
'生成综合报告...'
|
||||
]
|
||||
let progress = 0
|
||||
@@ -290,6 +300,13 @@ Page({
|
||||
|
||||
// 处理API返回结果
|
||||
processResult(apiData) {
|
||||
const ep = app.globalData.enterprisePermissions
|
||||
const showSbtiFace = !ep || ep.sbti !== false
|
||||
const sbtiCode = showSbtiFace ? (apiData.sbti?.code || apiData.sbtiType || '') : ''
|
||||
const sbtiCn = showSbtiFace ? (apiData.sbti?.cn || apiData.sbtiCn || '') : ''
|
||||
const sbtiMainTypeDesc = (showSbtiFace && (sbtiCode || sbtiCn))
|
||||
? (apiData.sbti?.mainTypeDesc || apiData.sbtiMainTypeDesc || '维度命中度较高,当前结果可视为你的第一人格画像。')
|
||||
: ''
|
||||
const base = {
|
||||
mbti: apiData.mbti?.type || '',
|
||||
title: apiData.mbti?.title || '',
|
||||
@@ -299,6 +316,9 @@ Page({
|
||||
pdpEmoji: this.getPDPEmoji(apiData.pdp?.primary),
|
||||
disc: apiData.disc?.primary || '',
|
||||
discAux: apiData.disc?.secondary || '',
|
||||
sbtiCode,
|
||||
sbtiCn,
|
||||
sbtiMainTypeDesc,
|
||||
traits: Array.isArray(apiData.advantages) ? apiData.advantages : [],
|
||||
faceAnalysisText: typeof apiData.faceAnalysis === 'string' ? apiData.faceAnalysis : '',
|
||||
boneAnalysisText: typeof apiData.boneAnalysis === 'string' ? apiData.boneAnalysis : '',
|
||||
@@ -327,7 +347,8 @@ Page({
|
||||
isAnalyzing: false,
|
||||
showResult: true,
|
||||
hasError: false,
|
||||
result
|
||||
result,
|
||||
showSbtiFace
|
||||
}
|
||||
|
||||
// 记录本次测试记录ID(由 /api/analyze 返回)
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<!-- 性格类型分析卡片 -->
|
||||
<view class="card personality-card" tt:if="{{!hasError}}">
|
||||
<text class="card-title">性格类型分析</text>
|
||||
<text class="personality-card-sub">MBTI · PDP · DISC 联合速览</text>
|
||||
<text class="personality-card-sub">MBTI · PDP · DISC · SBTI 联合速览</text>
|
||||
|
||||
<view class="personality-type">
|
||||
<text class="type-code">{{result.mbti}}</text>
|
||||
@@ -82,7 +82,7 @@
|
||||
<text class="type-desc">{{result.summary}}</text>
|
||||
</view>
|
||||
|
||||
<view class="type-details">
|
||||
<view class="type-details type-details--wrap">
|
||||
<view class="type-box pdp-box">
|
||||
<text class="type-emoji" tt:if="{{result.pdpEmoji}}">{{result.pdpEmoji}}</text>
|
||||
<text class="type-label">PDP主性格</text>
|
||||
@@ -95,14 +95,23 @@
|
||||
<text class="type-value">{{result.disc || '--'}}型</text>
|
||||
<text class="type-sub" tt:if="{{result.discAux}}">辅助: {{result.discAux}}</text>
|
||||
</view>
|
||||
<!-- SBTI:重构为盒子家族成员,占据全宽 -->
|
||||
<view
|
||||
class="type-box sbti-box"
|
||||
tt:if="{{showSbtiFace && (result.sbtiCode || result.sbtiCn)}}"
|
||||
>
|
||||
<text class="type-emoji">✨</text>
|
||||
<text class="type-label">SBTI解读</text>
|
||||
<text class="type-value">{{result.sbtiCode}}({{result.sbtiCn}})</text>
|
||||
<text class="type-desc-small">{{result.sbtiMainTypeDesc}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="advantages-box" tt:if="{{result.traits.length > 0}}">
|
||||
<text class="advantages-label">主要优势</text>
|
||||
<view class="advantages-list">
|
||||
<view class="advantage-item" tt:for="{{result.traits}}" tt:key="*this">
|
||||
<view class="advantage-dot"></view>
|
||||
<text class="advantage-text">{{item}}</text>
|
||||
<view class="advantage-pill" tt:for="{{result.traits}}" tt:key="*this">
|
||||
<text class="advantage-pill-text">{{item}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -71,6 +71,9 @@ Page({
|
||||
pdpEmoji: '',
|
||||
disc: '',
|
||||
discAux: '',
|
||||
sbtiCode: '',
|
||||
sbtiCn: '',
|
||||
sbtiMainTypeDesc: '',
|
||||
traits: [],
|
||||
faceAnalysisText: '',
|
||||
boneAnalysisText: '',
|
||||
@@ -96,6 +99,8 @@ Page({
|
||||
// 是否已在本地拥有手机号(决定是否还需要弹出微信手机号授权)
|
||||
hasPhone: false,
|
||||
isProfileComplete: false,
|
||||
/** 企业后台关闭 SBTI 时不展示人脸报告中的 SBTI(与 enterprisePermissions.sbti 一致) */
|
||||
showSbtiFace: true,
|
||||
analyzingTitle: '正在分析中',
|
||||
reportTitle: '分析报告',
|
||||
aiAnalysisText: '智能分析'
|
||||
@@ -182,7 +187,13 @@ Page({
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.setData({ hasPhone: hasPhone(), isProfileComplete: isProfileComplete() })
|
||||
const ep = app.globalData.enterprisePermissions
|
||||
const showSbtiFace = !ep || ep.sbti !== false
|
||||
this.setData({
|
||||
hasPhone: hasPhone(),
|
||||
isProfileComplete: isProfileComplete(),
|
||||
showSbtiFace
|
||||
})
|
||||
const tc = app.globalData.textConfig
|
||||
if (tc) {
|
||||
this.setData({
|
||||
@@ -215,7 +226,7 @@ Page({
|
||||
'正在识别面部特征...',
|
||||
'分析眉眼特征...',
|
||||
'结合《冰鉴》分析骨形...',
|
||||
'匹配MBTI/PDP/DISC...',
|
||||
'匹配MBTI/PDP/DISC/SBTI...',
|
||||
'生成综合报告...'
|
||||
]
|
||||
let progress = 0
|
||||
@@ -284,6 +295,13 @@ Page({
|
||||
|
||||
// 处理API返回结果
|
||||
processResult(apiData) {
|
||||
const ep = app.globalData.enterprisePermissions
|
||||
const showSbtiFace = !ep || ep.sbti !== false
|
||||
const sbtiCode = showSbtiFace ? (apiData.sbti?.code || apiData.sbtiType || '') : ''
|
||||
const sbtiCn = showSbtiFace ? (apiData.sbti?.cn || apiData.sbtiCn || '') : ''
|
||||
const sbtiMainTypeDesc = (showSbtiFace && (sbtiCode || sbtiCn))
|
||||
? (apiData.sbti?.mainTypeDesc || apiData.sbtiMainTypeDesc || '维度命中度较高,当前结果可视为你的第一人格画像。')
|
||||
: ''
|
||||
const base = {
|
||||
mbti: apiData.mbti?.type || '',
|
||||
title: apiData.mbti?.title || '',
|
||||
@@ -293,6 +311,9 @@ Page({
|
||||
pdpEmoji: this.getPDPEmoji(apiData.pdp?.primary),
|
||||
disc: apiData.disc?.primary || '',
|
||||
discAux: apiData.disc?.secondary || '',
|
||||
sbtiCode,
|
||||
sbtiCn,
|
||||
sbtiMainTypeDesc,
|
||||
traits: Array.isArray(apiData.advantages) ? apiData.advantages : [],
|
||||
faceAnalysisText: typeof apiData.faceAnalysis === 'string' ? apiData.faceAnalysis : '',
|
||||
boneAnalysisText: typeof apiData.boneAnalysis === 'string' ? apiData.boneAnalysis : '',
|
||||
@@ -321,7 +342,8 @@ Page({
|
||||
isAnalyzing: false,
|
||||
showResult: true,
|
||||
hasError: false,
|
||||
result
|
||||
result,
|
||||
showSbtiFace
|
||||
}
|
||||
|
||||
// 记录本次测试记录ID(由 /api/analyze 返回)
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<text class="type-desc">{{result.summary}}</text>
|
||||
</view>
|
||||
|
||||
<view class="type-details">
|
||||
<view class="type-details type-details--wrap">
|
||||
<view class="type-box pdp-box">
|
||||
<text class="type-emoji" wx:if="{{result.pdpEmoji}}">{{result.pdpEmoji}}</text>
|
||||
<text class="type-label">PDP主性格</text>
|
||||
@@ -94,14 +94,23 @@
|
||||
<text class="type-value">{{result.disc || '--'}}型</text>
|
||||
<text class="type-sub" wx:if="{{result.discAux}}">辅助: {{result.discAux}}</text>
|
||||
</view>
|
||||
<!-- SBTI:重构为盒子家族成员,占据全宽 -->
|
||||
<view
|
||||
class="type-box sbti-box"
|
||||
wx:if="{{showSbtiFace && (result.sbtiCode || result.sbtiCn)}}"
|
||||
>
|
||||
<text class="type-emoji">✨</text>
|
||||
<text class="type-label">SBTI解读</text>
|
||||
<text class="type-value">{{result.sbtiCode}}({{result.sbtiCn}})</text>
|
||||
<text class="type-desc-small">{{result.sbtiMainTypeDesc}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="advantages-box" wx:if="{{result.traits.length > 0}}">
|
||||
<text class="advantages-label">主要优势</text>
|
||||
<view class="advantages-list">
|
||||
<view class="advantage-item" wx:for="{{result.traits}}" wx:key="*this">
|
||||
<view class="advantage-dot"></view>
|
||||
<text class="advantage-text">{{item}}</text>
|
||||
<view class="advantage-pill" wx:for="{{result.traits}}" wx:key="*this">
|
||||
<text class="advantage-pill-text">{{item}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -559,6 +559,23 @@
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0), #fff);
|
||||
}
|
||||
|
||||
.personality-card--locked .face-sbti-card {
|
||||
max-height: 200rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.personality-card--locked .face-sbti-card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 48rpx;
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0), #e8f5f2);
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
}
|
||||
|
||||
.personality-card--locked .next-btn {
|
||||
opacity: 0.45;
|
||||
pointer-events: none;
|
||||
@@ -641,10 +658,17 @@
|
||||
|
||||
.type-details {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.type-details--wrap .type-box {
|
||||
flex: 1 1 38%;
|
||||
min-width: 260rpx;
|
||||
}
|
||||
|
||||
|
||||
.result-cta-questionnaire {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
@@ -701,54 +725,62 @@
|
||||
|
||||
.pdp-box .type-value { color: #7b1fa2; }
|
||||
.disc-box .type-value { color: #1976d2; }
|
||||
|
||||
.type-sub {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
display: block;
|
||||
/* SBTI 盒子:家族化重塑 */
|
||||
.sbti-box {
|
||||
flex: 1 1 100% !important;
|
||||
background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%) !important;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
/* 主要优势 */
|
||||
.sbti-box .type-value {
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.type-desc-small {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: #92400e;
|
||||
line-height: 1.5;
|
||||
margin-top: 8rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
/* 恢复:经典绿色优势区 */
|
||||
.advantages-box {
|
||||
background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
|
||||
padding: 24rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 24rpx;
|
||||
padding: 32rpx 24rpx;
|
||||
border-radius: 20rpx;
|
||||
margin: 24rpx 0 32rpx;
|
||||
}
|
||||
|
||||
.advantages-label {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
font-weight: 600;
|
||||
color: #2e7d32;
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin-bottom: 16rpx;
|
||||
margin-bottom: 24rpx;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
.advantages-list {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.advantage-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.advantage-pill {
|
||||
background: #ffffff;
|
||||
padding: 14rpx 36rpx;
|
||||
border-radius: 999rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(46, 125, 50, 0.08);
|
||||
}
|
||||
|
||||
.advantage-dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background-color: #4caf50;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.advantage-text {
|
||||
.advantage-pill-text {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
color: #2e7d32;
|
||||
}
|
||||
|
||||
.next-btn {
|
||||
|
||||
Reference in New Issue
Block a user