支持设置默认企业

This commit is contained in:
Ghost
2026-03-24 10:07:00 +08:00
parent 79512b2fc6
commit 41f016b1ab
22 changed files with 594 additions and 166 deletions

View File

@@ -202,10 +202,15 @@ class Analyze extends BaseController
'amountYuan' => $standardAmountFen > 0 ? round($standardAmountFen / 100, 2) : 0,
];
// 若该类型需付费才显示完整报告:返回给前端的也做脱敏,与详情/历史一致(只显示部分,付费后从详情接口拿完整)
if ($requiresPayment) {
$responsePayload['faceAnalysis'] = null;
$responsePayload['boneAnalysis'] = null;
// 未付费 / 资料未完善:与 /api/test/detail 一致做预览脱敏,防止直接抓包拿到完整报告
$gateResponse = false;
if ($requiresPayment > 0) {
$gateResponse = true;
} elseif ($earlyUserId > 0 && !TestController::isWechatProfileComplete($earlyUserId)) {
$gateResponse = true;
}
if (is_array($responsePayload) && $gateResponse) {
$responsePayload = TestController::filterFaceResultToPreview($responsePayload);
}
// 把本次测试记录ID一起返回便于解锁后通过 /api/test/detail 拉取完整数据

View File

@@ -50,6 +50,30 @@ class AppConfig extends BaseController
}
}
// 系统配置:审核模式、默认企业(无带参入口时小程序回落)
$maintenanceMode = false;
$defaultEnterpriseId = null;
$systemRow = Db::name('system_config')->where('key', 'system')->find();
if ($systemRow && !empty($systemRow['value'])) {
$sysValEarly = is_string($systemRow['value']) ? json_decode($systemRow['value'], true) : $systemRow['value'];
if (is_array($sysValEarly)) {
if (!empty($sysValEarly['maintenanceMode'])) {
$maintenanceMode = true;
}
if (!empty($sysValEarly['defaultEnterpriseId'])) {
$de = (int) $sysValEarly['defaultEnterpriseId'];
if ($de > 0) {
$defaultEnterpriseId = $de;
}
}
}
}
// scope=enterprise 且用户未绑定企业时,用超管默认企业拉企业定价与文案
if ($scope !== 'personal' && $enterpriseId === null && $defaultEnterpriseId !== null) {
$enterpriseId = $defaultEnterpriseId;
$pricingType = 'enterprise';
}
$config = PricingConfigModel::getByTypeAndEnterprise($pricingType, $enterpriseId);
if ($config && !empty($config->config)) {
// PricingConfig 模型已对 config 做 JSON 转换,这里直接当数组/对象用即可
@@ -103,16 +127,6 @@ class AppConfig extends BaseController
}
$siteTitle = $miniprogramName !== '' ? $miniprogramName : ($siteName !== '' ? $siteName : '神仙团队AI性格测试');
// 审核模式(原 maintenanceMode开启后首页展示「开始性格测试」并跳转 test-select
$maintenanceMode = false;
$systemRow = Db::name('system_config')->where('key', 'system')->find();
if ($systemRow && !empty($systemRow['value'])) {
$sysVal = is_string($systemRow['value']) ? json_decode($systemRow['value'], true) : $systemRow['value'];
if (is_array($sysVal) && !empty($sysVal['maintenanceMode'])) {
$maintenanceMode = true;
}
}
// 小程序文案配置(分析中提示、按钮、报告标题等)
$textConfig = [
'analyzingTitle' => '正在分析中',
@@ -155,6 +169,7 @@ class AppConfig extends BaseController
'siteTitle' => $siteTitle,
'textConfig' => $textConfig,
'maintenanceMode' => $maintenanceMode,
'defaultEnterpriseId' => $defaultEnterpriseId,
]);
}

View File

@@ -98,6 +98,11 @@ class Payment extends BaseController
}
}
// 测试结果未带 enterpriseId 时使用小程序请求中的企业上下文scene/绑定/超管默认企业)
if (empty($enterpriseId) && $enterpriseIdParam > 0) {
$enterpriseId = $enterpriseIdParam;
}
// 充值场景优先使用显式传入的企业ID否则回退到当前用户已绑定企业
if ($productType === 'recharge') {
if ($enterpriseIdParam > 0) {

View File

@@ -80,6 +80,9 @@ class Test extends BaseController
$requiresPayment = (int) ($row['requiresPayment'] ?? 0);
$isPaid = (int) ($row['isPaid'] ?? 0);
$orderId = isset($row['orderId']) ? (int) $row['orderId'] : null;
$paidAmountRow = isset($row['paidAmount']) ? (int) $row['paidAmount'] : 0;
$needPayUnlock = $requiresPayment && !$isPaid && $paidAmountRow > 0;
$profileIncomplete = !self::isWechatProfileComplete($userId);
$raw = $row['resultData'] ?? ($row['result'] ?? null);
$data = null;
@@ -87,8 +90,14 @@ class Test extends BaseController
$decoded = json_decode($raw, true);
$data = is_array($decoded) ? $decoded : $raw;
}
if ($requiresPayment && !$isPaid && $data !== null) {
$data = $this->filterResultToPartial($testType, $data);
if ($data !== null && is_array($data)) {
if (in_array($testType, ['face', 'ai'], true)) {
if ($needPayUnlock || $profileIncomplete) {
$data = self::filterFaceResultToPreview($data);
}
} elseif ($requiresPayment && !$isPaid) {
$data = $this->filterResultToPartial($testType, $data);
}
}
$paymentFields = [
@@ -358,8 +367,15 @@ class Test extends BaseController
$testType = $row['testType'] ?? '';
// 仅当需要付款且未付款且金额>0 时才脱敏系统设置需付款但金额为0 则直接可查看
$needPaymentToUnlock = $requiresPayment && !$isPaid && $paidAmount > 0;
if ($needPaymentToUnlock && $data !== null) {
$data = $this->filterResultToPartial($testType, $data);
$profileIncomplete = !self::isWechatProfileComplete($userId);
if ($data !== null && is_array($data)) {
if (in_array($testType, ['face', 'ai'], true)) {
if ($needPaymentToUnlock || $profileIncomplete) {
$data = self::filterFaceResultToPreview($data);
}
} elseif ($needPaymentToUnlock) {
$data = $this->filterResultToPartial($testType, $data);
}
}
return success([
@@ -550,12 +566,6 @@ class Test extends BaseController
if (!is_array($data)) {
return $data;
}
if ($testType === 'face' || $testType === 'ai') {
$out = $data;
$out['faceAnalysis'] = null;
$out['boneAnalysis'] = null;
return $out;
}
if ($testType === 'mbti') {
return [
'mbtiType' => $data['mbtiType'] ?? $data['mbti'] ?? '',
@@ -577,6 +587,82 @@ class Test extends BaseController
return $data;
}
/**
* 微信用户资料是否与小程序 isProfileComplete 一致:头像、昵称、手机号必填
*/
public static function isWechatProfileComplete(int $userId): bool
{
if ($userId <= 0) {
return false;
}
$row = Db::name('wechat_users')->where('id', $userId)->field('nickname,avatar,phone')->find();
if (!$row) {
return false;
}
$nick = trim((string) ($row['nickname'] ?? ''));
$avatar = trim((string) ($row['avatar'] ?? ''));
$phone = trim((string) ($row['phone'] ?? ''));
return $nick !== '' && $avatar !== '' && $phone !== '';
}
/**
* 人脸/AI 分析报告:未付费或资料未完善时仅返回预览级字段(防止抓包看全文)
*/
public static function filterFaceResultToPreview(array $data): array
{
$out = $data;
$out['faceAnalysis'] = null;
$out['boneAnalysis'] = null;
unset($out['faceAnalysisText'], $out['boneAnalysisText']);
$out['relationship'] = '';
$out['portrait'] = null;
$out['hrView'] = null;
$out['bossView'] = null;
$out['resumeHighlights'] = '';
if (isset($out['careers'])) {
$out['careers'] = [];
}
$sum = (string) ($out['personalitySummary'] ?? '');
$ov = (string) ($out['overview'] ?? '');
$out['personalitySummary'] = self::truncatePreviewText($sum, 72);
$out['overview'] = self::truncatePreviewText($ov, 72);
$out['gallupTop3'] = [];
$adv = $out['advantages'] ?? [];
if (is_array($adv) && $adv !== []) {
$slice = array_slice($adv, 0, 2);
$out['advantages'] = array_map(function ($x) {
return self::truncatePreviewText((string) $x, 28);
}, $slice);
} else {
$out['advantages'] = [];
}
return $out;
}
private static function truncatePreviewText(string $s, int $maxChars): string
{
$s = trim($s);
if ($s === '') {
return '';
}
if (function_exists('mb_strlen') && function_exists('mb_substr')) {
if (mb_strlen($s, 'UTF-8') > $maxChars) {
return mb_substr($s, 0, $maxChars, 'UTF-8') . '…';
}
return $s;
}
if (strlen($s) > $maxChars) {
return substr($s, 0, $maxChars) . '…';
}
return $s;
}
/**
* 获取当前用户最近的 MBTI / DISC / PDP 测试记录(暂不使用人脸/AI 结果),供简历综合分析使用
* @param int $userId 微信用户 ID

View File

@@ -4,6 +4,7 @@ namespace app\controller\superadmin;
use app\BaseController;
use app\model\SystemConfig as SystemConfigModel;
use app\model\User as UserModel;
use app\model\Enterprise as EnterpriseModel;
use think\facade\Request;
use think\facade\Db;
@@ -55,7 +56,8 @@ class Settings extends BaseController
'miniprogramName' => '神仙团队AI性格测试',
'maintenanceMode' => false,
'maxTestsPerDay' => 100,
'trialTestCount' => 10
'trialTestCount' => 10,
'defaultEnterpriseId' => null,
],
'notification' => $notificationConfig ? $notificationConfig->value : [
'emailNotification' => true,
@@ -100,12 +102,30 @@ class Settings extends BaseController
$input = [];
}
$allowedKeys = ['siteName', 'siteDescription', 'miniprogramName', 'maintenanceMode', 'maxTestsPerDay', 'trialTestCount'];
$allowedKeys = ['siteName', 'siteDescription', 'miniprogramName', 'maintenanceMode', 'maxTestsPerDay', 'trialTestCount', 'defaultEnterpriseId'];
$data = array_intersect_key($input, array_flip($allowedKeys));
// 兼容 fallbackJSON 解析失败时尝试 Request::only
if (empty($data)) {
$data = Request::only($allowedKeys);
}
// 默认企业0 或空视为不启用
if (array_key_exists('defaultEnterpriseId', $data)) {
$de = $data['defaultEnterpriseId'];
if ($de === '' || $de === null) {
$data['defaultEnterpriseId'] = null;
} else {
$deInt = (int) $de;
if ($deInt <= 0) {
$data['defaultEnterpriseId'] = null;
} else {
$exists = EnterpriseModel::where('id', $deInt)->find();
if (!$exists) {
return error('所选默认企业不存在', 400);
}
$data['defaultEnterpriseId'] = $deInt;
}
}
}
$textConfig = $input['textConfig'] ?? (Request::param('textConfig') ?: []);
try {
@@ -117,7 +137,13 @@ class Settings extends BaseController
$config->enterprise_id = 0;
$config->description = '系统基础配置';
}
$config->value = $data;
// 合并保存,避免仅提交部分字段时丢失其它键(如 defaultEnterpriseId
$oldVal = $config->value;
$oldArr = is_array($oldVal) ? $oldVal : (is_string($oldVal) ? (json_decode($oldVal, true) ?: []) : []);
if (!is_array($oldArr)) {
$oldArr = [];
}
$config->value = array_merge($oldArr, $data);
$config->save();
// 更新站点信息