diff --git a/admin/src/components/UserDetailDialog.vue b/admin/src/components/UserDetailDialog.vue index 38ba4a6..cad83d1 100644 --- a/admin/src/components/UserDetailDialog.vue +++ b/admin/src/components/UserDetailDialog.vue @@ -221,6 +221,41 @@
暂无人脸分析照片
+ +
+ + + + + + + + + + + + + +
+
+ 暂无简历文件。用户在企业版小程序「我的简历」中上传后,将在此列出(OSS 直链,点击打开下载或预览)。 +
+
+
@@ -403,6 +438,17 @@ const matchingEnterprises = computed(() => { return Array.isArray(m) ? m : [] }) +const resumeUploadList = computed(() => { + const raw = props.user?.resumeUploads + return Array.isArray(raw) ? raw : [] +}) + +function openResumeUrl(url: string) { + const u = (url || '').trim() + if (!u) return + window.open(u, '_blank', 'noopener,noreferrer') +} + function shortOrDash(s: string | undefined, max = 6) { if (!s) return '—' return s.length > max ? s.slice(0, max) + '…' : s @@ -1223,6 +1269,17 @@ function openMail(email: string) { border-radius: 8px; } +.ud-resume-files { + padding: 4px 0; +} +.ud-resume-table { + width: 100%; +} +.ud-muted { + color: #9ca3af; + font-size: 13px; +} + .ud-journey { display: flex; flex-direction: column; diff --git a/api/app/common/service/ResumeUploadsAdminService.php b/api/app/common/service/ResumeUploadsAdminService.php new file mode 100644 index 0000000..0288d32 --- /dev/null +++ b/api/app/common/service/ResumeUploadsAdminService.php @@ -0,0 +1,105 @@ + + */ + public static function listForWechatUser(int $wechatUserId, ?int $scopeEnterpriseId): array + { + if ($wechatUserId <= 0) { + return []; + } + try { + if ($scopeEnterpriseId !== null && (int) $scopeEnterpriseId > 0) { + $eid = (int) $scopeEnterpriseId; + $byE = Db::name('enterprise_resume_uploads')->alias('r') + ->leftJoin('enterprises e', 'e.id = r.enterpriseId') + ->where('r.userId', $wechatUserId) + ->where('r.enterpriseId', $eid) + ->field('r.id,r.enterpriseId,r.fileUrl,r.fileName,r.is_default,r.createdAt,e.name as enterpriseName') + ->order('r.createdAt', 'desc') + ->select() + ->toArray(); + $byNull = []; + $boundE = (int) (Db::name('wechat_users')->where('id', $wechatUserId)->value('enterpriseId') ?? 0); + if ($boundE === $eid) { + $byNull = Db::name('enterprise_resume_uploads')->alias('r') + ->leftJoin('enterprises e', 'e.id = r.enterpriseId') + ->where('r.userId', $wechatUserId) + ->whereNull('r.enterpriseId') + ->field('r.id,r.enterpriseId,r.fileUrl,r.fileName,r.is_default,r.createdAt,e.name as enterpriseName') + ->order('r.createdAt', 'desc') + ->select() + ->toArray(); + } + $rows = self::mergeRowsById($byE, $byNull); + } else { + $rows = Db::name('enterprise_resume_uploads')->alias('r') + ->leftJoin('enterprises e', 'e.id = r.enterpriseId') + ->where('r.userId', $wechatUserId) + ->field('r.id,r.enterpriseId,r.fileUrl,r.fileName,r.is_default,r.createdAt,e.name as enterpriseName') + ->order('r.createdAt', 'desc') + ->select() + ->toArray(); + } + } catch (\Throwable $e) { + return []; + } + + return self::mapRows($rows); + } + + /** + * @param list $a + * @param list $b + * @return list + */ + private static function mergeRowsById(array $a, array $b): array + { + $byId = []; + foreach (array_merge($a, $b) as $row) { + $id = (int) ($row['id'] ?? 0); + if ($id > 0) { + $byId[$id] = $row; + } + } + $out = array_values($byId); + usort($out, static function ($x, $y) { + $ax = (int) ($x['createdAt'] ?? 0); + $ay = (int) ($y['createdAt'] ?? 0); + + return $ay <=> $ax; + }); + + return $out; + } + + private static function mapRows(array $rows): array + { + $out = []; + foreach ($rows as $row) { + $ts = (int) ($row['createdAt'] ?? 0); + $out[] = [ + 'id' => (int) ($row['id'] ?? 0), + 'enterpriseId' => isset($row['enterpriseId']) && $row['enterpriseId'] !== null && (int) $row['enterpriseId'] > 0 + ? (int) $row['enterpriseId'] : null, + 'enterpriseName' => (string) ($row['enterpriseName'] ?? ''), + 'fileName' => (string) ($row['fileName'] ?? ''), + 'url' => (string) ($row['fileUrl'] ?? ''), + 'isDefault' => (int) ($row['is_default'] ?? 0) === 1, + 'uploadedAt' => $ts > 1000000000 ? $ts : null, + ]; + } + + return $out; + } +} diff --git a/api/app/controller/admin/AppUser.php b/api/app/controller/admin/AppUser.php index 57cacd4..e6942d7 100644 --- a/api/app/controller/admin/AppUser.php +++ b/api/app/controller/admin/AppUser.php @@ -2,6 +2,7 @@ namespace app\controller\admin; use app\BaseController; +use app\common\service\ResumeUploadsAdminService; use app\controller\admin\concern\ExtractsTestResults; use think\facade\Db; use think\facade\Request; @@ -496,6 +497,10 @@ class AppUser extends BaseController } } + $data['resumeUploads'] = ($enterpriseId && (int) $enterpriseId > 0) + ? ResumeUploadsAdminService::listForWechatUser((int) $id, (int) $enterpriseId) + : []; + return success($data); } diff --git a/api/app/controller/superadmin/AppUser.php b/api/app/controller/superadmin/AppUser.php index 93f1960..7da3c4f 100644 --- a/api/app/controller/superadmin/AppUser.php +++ b/api/app/controller/superadmin/AppUser.php @@ -2,6 +2,7 @@ namespace app\controller\superadmin; use app\BaseController; +use app\common\service\ResumeUploadsAdminService; use app\controller\admin\concern\ExtractsTestResults; use think\facade\Db; use think\facade\Request; @@ -561,6 +562,8 @@ class AppUser extends BaseController (string) ($data['discType'] ?? '') ); + $data['resumeUploads'] = ResumeUploadsAdminService::listForWechatUser((int) $id, null); + return success($data); } 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/pages/profile/index.js b/miniprogram/pages/profile/index.js index 79db3aa..efc0719 100644 --- a/miniprogram/pages/profile/index.js +++ b/miniprogram/pages/profile/index.js @@ -44,6 +44,10 @@ Page({ mpAuditMode: false, /** 仅 miniprogramAuditMode:隐藏「了解自己」深度套餐入口(虚拟商品合规) */ showDeepPricingEntry: true, + /** 审核/提审(与神仙 AI Tab 同源):隐藏「匹配工作」入口 */ + showMatchJobEntry: true, + /** 快捷入口网格列类名 quick-grid--2~4,按可见按钮数均分平铺(每行最多 4 个) */ + quickGridClass: 'quick-grid--4', /** 最近记录的数据库 ID,用于跳转时传参 */ mbtiResultId: null, sbtiResultId: null, @@ -106,6 +110,14 @@ Page({ ) }, + /** 性格测试 + 我的订单 + 可选「了解自己」「匹配工作」,按可见数 2~4 列均分 */ + _computeQuickGridCols(d) { + let n = 2 + if (d.showDeepPricingEntry) n++ + if (d.showMatchJobEntry) n++ + return Math.min(Math.max(n, 1), 4) + }, + onLoad() { // 仅在 onLoad 执行一次,onShow 里的 runLoginThenLoad 会导致重复请求 this.runLoginThenLoad() @@ -121,11 +133,14 @@ Page({ permDisc: !p || p.disc !== false, permDistribution: !p || p.distribution !== false, showDeepPricingEntry: !gd.miniprogramAuditMode, + showMatchJobEntry: !isAuditHideAiMode(gd), ...overrides } const d = { ...this.data, ...next } + const qCols = this._computeQuickGridCols(d) this.setData({ ...next, + quickGridClass: `quick-grid--${qCols}`, showLatestTestRow: this._computeShowLatestTestRow(d), showEmptyPersonalityTags: this._computeShowEmptyPersonalityTags(d) }) @@ -717,6 +732,11 @@ Page({ }, /** 匹配工作:新入口,跳转匹配工作中间页 */ goToMatchJob() { + const gd = app.globalData || {} + if (isAuditHideAiMode(gd)) { + wx.showToast({ title: '功能升级中', icon: 'none' }) + return + } try { require('../../utils/analytics').track('tap_match_job', {}) } catch (e) {} wx.navigateTo({ url: '/pages/match-job/index' }) }, diff --git a/miniprogram/pages/profile/index.wxml b/miniprogram/pages/profile/index.wxml index b10f478..bcd1105 100644 --- a/miniprogram/pages/profile/index.wxml +++ b/miniprogram/pages/profile/index.wxml @@ -202,7 +202,7 @@ - + 🧠 性格测试 @@ -215,7 +215,7 @@ 💎 了解自己 - + 💼 匹配工作 diff --git a/miniprogram/pages/profile/index.wxss b/miniprogram/pages/profile/index.wxss index 1a47615..242acea 100644 --- a/miniprogram/pages/profile/index.wxss +++ b/miniprogram/pages/profile/index.wxss @@ -920,6 +920,8 @@ custom-tab-bar { box-shadow: 0 4rpx 20rpx rgba(15, 23, 42, 0.05); border: 1rpx solid #f1f5f9; } +.quick-grid--1 { grid-template-columns: repeat(1, 1fr); } +.quick-grid--2 { grid-template-columns: repeat(2, 1fr); } .quick-grid--3 { grid-template-columns: repeat(3, 1fr); } .quick-grid--4 { grid-template-columns: repeat(4, 1fr); } .quick-grid__item { diff --git a/miniprogram/pages/result/disc.wxml b/miniprogram/pages/result/disc.wxml index 29e5887..c6d2c08 100644 --- a/miniprogram/pages/result/disc.wxml +++ b/miniprogram/pages/result/disc.wxml @@ -227,7 +227,7 @@ 结合 DISC、MBTI、PDP 与面相打造综合报告;团队可做岗位适配、沟通与协作建议。邀请好友测评可参与推广分润。 深度解读方案 - 推广中心 + 推广中心 diff --git a/miniprogram/pages/result/mbti.wxml b/miniprogram/pages/result/mbti.wxml index 5b38605..f2eb23f 100644 --- a/miniprogram/pages/result/mbti.wxml +++ b/miniprogram/pages/result/mbti.wxml @@ -284,7 +284,7 @@ 结合面相、MBTI、PDP、DISC 的综合报告;或为团队做岗位适配与沟通建议。邀请好友测评可参与推广分润(以活动规则为准)。 深度解读方案 - 推广中心 + 推广中心 diff --git a/miniprogram/pages/result/pdp.wxml b/miniprogram/pages/result/pdp.wxml index 5a9e8b2..c723a1a 100644 --- a/miniprogram/pages/result/pdp.wxml +++ b/miniprogram/pages/result/pdp.wxml @@ -240,7 +240,7 @@ 结合 PDP、MBTI、DISC 与面相综合报告;团队可做岗位适配、沟通协作与领导力建议。邀请好友测评可参与推广分润。 深度解读方案 - 推广中心 + 推广中心 diff --git a/miniprogram/pages/result/sbti.wxml b/miniprogram/pages/result/sbti.wxml index 29df4c3..d3b4532 100644 --- a/miniprogram/pages/result/sbti.wxml +++ b/miniprogram/pages/result/sbti.wxml @@ -179,7 +179,7 @@ 结合 SBTI、MBTI、PDP、DISC 与面相综合分析;获得亲密关系与发展路径的个性化建议。邀请好友参与测评可参与推广分润。 深度解读方案 - 推广中心 + 推广中心