@@ -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 与面相综合分析;获得亲密关系与发展路径的个性化建议。邀请好友参与测评可参与推广分润。
深度解读方案
- 推广中心
+ 推广中心