index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. <template>
  2. <view class="detail-container">
  3. <scroll-view scroll-y class="scroll-wrapper">
  4. <!-- 顶部基础信息 -->
  5. <view class="section header-section">
  6. <view class="title-line">
  7. <view class="left-box">
  8. <text class="job-name">{{ jobInfo.postName || '' }}</text>
  9. <text class="urgent-tag" v-if="jobInfo.isUrgent === 1">急招</text>
  10. </view>
  11. <text class="salary">{{ jobInfo.salaryRange || '面议' }}</text>
  12. </view>
  13. <view class="meta-list">
  14. <view class="meta-item">
  15. <image src="/static/icons/location.svg" class="icon" mode="aspectFit"></image>
  16. <text>{{ jobInfo.workProvince || '' }}{{ jobInfo.workCity ? '·' + jobInfo.workCity : '' }}{{ jobInfo.workDistrict ? '·' + jobInfo.workDistrict : '' }}</text>
  17. </view>
  18. <view class="meta-item">
  19. <image src="/static/icons/user.svg" class="icon" mode="aspectFit"></image>
  20. <text>招录 {{ jobInfo.recruitNum || 1 }} 人</text>
  21. </view>
  22. <view class="meta-item">
  23. <image src="/static/icons/time.svg" class="icon" mode="aspectFit"></image>
  24. <text>截止时间:{{ jobInfo.registrationEndDate ? jobInfo.registrationEndDate.split(' ')[0] : '长期有效' }}</text>
  25. </view>
  26. </view>
  27. </view>
  28. <!-- HR 信息 -->
  29. <view class="section hr-section">
  30. <image :src="jobInfo.companyAvatar || '/static/images/hr_avatar.svg'" class="hr-avatar" mode="aspectFill"></image>
  31. <view class="hr-content">
  32. <text class="hr-name">{{ jobInfo.companyName || '平台推荐' }}</text>
  33. <text class="hr-desc">人事负责人</text>
  34. </view>
  35. </view>
  36. <!-- 岗位详情内容 -->
  37. <view class="section detail-content">
  38. <view class="section-title">岗位详情</view>
  39. <!-- 标签云 -->
  40. <view class="tag-cloud">
  41. <text class="tag-label" v-for="tag in tags" :key="tag">{{ tag }}</text>
  42. </view>
  43. <!-- 岗位描述(富文本,来自数据库 post_description) -->
  44. <view class="rich-text-wrapper" v-if="jobInfo.postDescription">
  45. <rich-text :nodes="jobInfo.postDescription"></rich-text>
  46. </view>
  47. <view class="info-block" v-else>
  48. <text class="block-text">暂无岗位详情</text>
  49. </view>
  50. </view>
  51. <!-- 办公地址 - 接入动态地图并使用气泡显示地址 -->
  52. <view class="section address-section">
  53. <view class="section-title">办公地址</view>
  54. <view class="map-wrapper">
  55. <map
  56. class="map-view"
  57. :latitude="latitude"
  58. :longitude="longitude"
  59. :markers="markers"
  60. :scale="16"
  61. show-location
  62. ></map>
  63. </view>
  64. </view>
  65. <!-- 公司概况 -->
  66. <view class="section company-section">
  67. <view class="company-header">
  68. <image :src="jobInfo.companyAvatar || '/static/images/logo1.png'" class="company-logo" mode="aspectFit"></image>
  69. <text class="company-name">{{ jobInfo.companyName || '未知企业' }}</text>
  70. </view>
  71. <text class="company-desc">
  72. 这是一段公司的概览信息,暂无详细内容。
  73. </text>
  74. </view>
  75. <!-- 到底提示 -->
  76. <view class="end-tip">
  77. <text>— 已到底啦~ —</text>
  78. </view>
  79. <view class="safe-bottom-holder"></view>
  80. </scroll-view>
  81. <!-- 底部操作栏 -->
  82. <view class="bottom-action-bar">
  83. <view class="collect-box" @click="toggleCollect">
  84. <image :src="isCollected ? '/static/icons/star_filled.svg' : '/static/icons/star_hollow.svg'"
  85. class="star-icon"
  86. mode="aspectFit"></image>
  87. <view class="collect-text">{{ isCollected ? '已收藏' : '收藏' }}</view>
  88. </view>
  89. <view
  90. class="consult-btn"
  91. :class="[jobState]"
  92. @click="handleMainAction"
  93. >
  94. <text>{{ btnText }}</text>
  95. </view>
  96. </view>
  97. </view>
  98. </template>
  99. <script setup lang="js">
  100. import { ref, computed, onUnmounted } from 'vue';
  101. import { onShow, onLoad } from '@dcloudio/uni-app';
  102. import { getPositionDetail } from '../../api/position.js';
  103. import { createOrGetSession } from '../../api/message.js';
  104. import { addCollection, delCollection, checkCollection } from '../../api/collection.js';
  105. import { getAssessmentRecordList, getAssessmentList } from '../../api/assessment.js';
  106. const isCollected = ref(false);
  107. const collectionId = ref(null);
  108. const jobInfo = ref({});
  109. const tags = ref([]);
  110. // 岗位状态: 'initial', 'paid', 'assessed', 'added'
  111. const jobState = ref('initial');
  112. const btnText = computed(() => {
  113. switch (jobState.value) {
  114. case 'initial': return '咨询';
  115. case 'paid': return '开始测评';
  116. case 'assessed': return '投递简历';
  117. case 'added': return '已投递';
  118. default: return '咨询';
  119. }
  120. });
  121. const positionId = ref(null);
  122. const checkState = async () => {
  123. console.log('Checking job state for position:', positionId.value);
  124. const userInfo = uni.getStorageSync('userInfo');
  125. if (!userInfo || !userInfo.studentId || !positionId.value) {
  126. jobState.value = 'initial';
  127. return;
  128. }
  129. // ① 已投递过 → 直接显示已投递
  130. const appliedKey = `candidate_applied_${positionId.value}`;
  131. if (uni.getStorageSync(appliedKey)) {
  132. jobState.value = 'added';
  133. return;
  134. }
  135. try {
  136. // ② 查询该岗位关联的测评列表
  137. const evalRes = await getAssessmentList({ positionId: positionId.value, pageNum: 1, pageSize: 100 });
  138. // 检查该岗位下是否有测评已支付(按evaluationId区分)
  139. const isAnyEvalPaid = evalRes.code === 200 && evalRes.rows
  140. ? evalRes.rows.some(e => uni.getStorageSync(`audit_paid_${e.id}`))
  141. : uni.getStorageSync(`audit_paid_${positionId.value}`);
  142. if (evalRes.code !== 200 || !evalRes.rows || evalRes.rows.length === 0) {
  143. // 无关联测评,检查是否已支付
  144. jobState.value = isAnyEvalPaid ? 'paid' : 'initial';
  145. return;
  146. }
  147. // ③ 获取用户的测评记录
  148. const recordRes = await getAssessmentRecordList(userInfo.studentId);
  149. if (recordRes.code !== 200 || !recordRes.data) {
  150. jobState.value = isAnyEvalPaid ? 'paid' : 'initial';
  151. return;
  152. }
  153. // ④ 检查用户是否通过了该岗位关联的任一测评
  154. const evaluationIds = evalRes.rows.map(e => e.id);
  155. const passedRecord = recordRes.data.find(r =>
  156. r.finalResult === '1' && evaluationIds.includes(r.evaluationId)
  157. );
  158. if (passedRecord) {
  159. // 测评通过 → 显示"投递简历"
  160. jobState.value = 'assessed';
  161. } else if (isAnyEvalPaid) {
  162. // 已付款但未通过测评 → 显示"开始测评"
  163. jobState.value = 'paid';
  164. } else {
  165. // 未支付测评费用,只显示咨询按钮
  166. jobState.value = 'initial';
  167. }
  168. } catch (err) {
  169. console.error('检查状态失败:', err);
  170. jobState.value = 'initial';
  171. }
  172. };
  173. const latitude = ref(31.22863);
  174. const longitude = ref(121.45039);
  175. const markers = ref([]);
  176. const fetchDetail = async (id) => {
  177. console.log('fetchDetail called with id:', id); // 调试日志
  178. uni.showLoading({ title: '加载中...' });
  179. try {
  180. const res = await getPositionDetail(id);
  181. console.log('getPositionDetail响应:', res); // 调试日志
  182. if (res.code === 200 && res.data) {
  183. jobInfo.value = res.data;
  184. positionId.value = res.data.id;
  185. const data = res.data;
  186. // 地图坐标赋值
  187. if (data.latitude && data.longitude) {
  188. latitude.value = parseFloat(data.latitude);
  189. longitude.value = parseFloat(data.longitude);
  190. markers.value = [{
  191. id: 1,
  192. latitude: latitude.value,
  193. longitude: longitude.value,
  194. title: data.postName || '办公地点',
  195. iconPath: '/static/icons/location.svg',
  196. width: 32,
  197. height: 32,
  198. callout: {
  199. content: data.workAddress || (data.workProvince + data.workCity + data.workDistrict),
  200. color: '#333333',
  201. fontSize: 12,
  202. borderRadius: 8,
  203. padding: 8,
  204. bgColor: '#ffffff',
  205. display: 'ALWAYS',
  206. boxShadow: '0 4rpx 12rpx rgba(0,0,0,0.1)'
  207. }
  208. }];
  209. } else {
  210. // 如果没有经纬度,显示一个默认位置或清空标记
  211. markers.value = [];
  212. }
  213. let t = [];
  214. if(data.postTypeLabel) t.push(data.postTypeLabel);
  215. if(data.schoolRequirementLabel) t.push(data.schoolRequirementLabel);
  216. if(data.gradeRequirementLabel) t.push(data.gradeRequirementLabel);
  217. if(data.welfareTags) {
  218. t.push(...data.welfareTags.split(',').filter(Boolean));
  219. }
  220. tags.value = t;
  221. // 检查是否已收藏
  222. console.log('准备检查收藏状态, id:', id);
  223. checkCollectionStatus(id);
  224. }
  225. } catch(err) {
  226. console.error('获取岗位详情失败:', err);
  227. } finally {
  228. uni.hideLoading();
  229. }
  230. };
  231. // 检查收藏状态
  232. const checkCollectionStatus = async (id) => {
  233. console.log('checkCollectionStatus called with id:', id); // 调试日志
  234. const userInfo = uni.getStorageSync('userInfo');
  235. console.log('checkCollectionStatus userInfo:', userInfo); // 调试日志
  236. if (!userInfo || !userInfo.studentId) {
  237. console.log('checkCollectionStatus: 用户未登录');
  238. return;
  239. }
  240. try {
  241. console.log('调用checkCollection API, studentId:', userInfo.studentId, 'targetId:', id, 'type: job'); // 调试日志
  242. const res = await checkCollection(userInfo.studentId, id, 'job');
  243. console.log('checkCollection API响应:', res); // 调试日志
  244. if (res.code === 200 && res.data) {
  245. isCollected.value = true;
  246. collectionId.value = res.data.id; // 保存收藏记录ID
  247. console.log('设置为已收藏, collectionId:', res.data.id);
  248. } else {
  249. isCollected.value = false;
  250. collectionId.value = null;
  251. console.log('设置为未收藏');
  252. }
  253. } catch (err) {
  254. console.error('检查收藏状态失败', err);
  255. }
  256. };
  257. // 切换收藏状态
  258. const toggleCollect = async () => {
  259. console.log('toggleCollect clicked'); // 调试日志
  260. const userInfo = uni.getStorageSync('userInfo');
  261. console.log('userInfo:', userInfo); // 调试日志
  262. if (!userInfo || !userInfo.studentId) {
  263. console.log('用户未登录'); // 调试日志
  264. uni.showToast({ title: '请先登录', icon: 'none' });
  265. setTimeout(() => {
  266. uni.navigateTo({ url: '/pages/login/login' });
  267. }, 1000);
  268. return;
  269. }
  270. if (!jobInfo.value.id) {
  271. console.log('jobInfo.value.id 为空:', jobInfo.value); // 调试日志
  272. return;
  273. }
  274. console.log('准备发送收藏请求, jobInfo.value.id:', jobInfo.value.id); // 调试日志
  275. uni.showLoading({ title: isCollected.value ? '取消收藏中...' : '收藏中...' });
  276. try {
  277. if (isCollected.value) {
  278. // 取消收藏
  279. console.log('取消收藏, collectionId:', collectionId.value); // 调试日志
  280. if (collectionId.value) {
  281. const res = await delCollection(collectionId.value);
  282. console.log('取消收藏响应:', res); // 调试日志
  283. if (res.code === 200) {
  284. isCollected.value = false;
  285. collectionId.value = null;
  286. uni.showToast({ title: '已取消收藏', icon: 'none' });
  287. }
  288. }
  289. } else {
  290. // 添加收藏
  291. const requestData = {
  292. studentId: userInfo.studentId,
  293. targetId: jobInfo.value.id,
  294. type: 'job'
  295. };
  296. console.log('添加收藏请求数据:', requestData); // 调试日志
  297. const res = await addCollection(requestData);
  298. console.log('添加收藏响应:', res); // 调试日志
  299. if (res.code === 200) {
  300. isCollected.value = true;
  301. // 添加成功后重新检查获取完整的收藏记录ID
  302. checkCollectionStatus(jobInfo.value.id);
  303. uni.showToast({ title: '收藏成功', icon: 'success' });
  304. } else {
  305. uni.showToast({ title: res.msg || '收藏失败', icon: 'none' });
  306. }
  307. }
  308. } catch (err) {
  309. console.error('操作收藏失败', err);
  310. uni.showToast({ title: '操作失败', icon: 'none' });
  311. } finally {
  312. uni.hideLoading();
  313. }
  314. };
  315. onLoad((options) => {
  316. if (options.id) {
  317. positionId.value = options.id;
  318. fetchDetail(options.id);
  319. }
  320. // 监听支付完成事件(chat.vue 支付成功后会 emit)
  321. uni.$on('payment_done', (data) => {
  322. console.log('收到 payment_done 事件:', data);
  323. checkState();
  324. });
  325. // 监听简历投递完成事件(select-resume.vue 投递成功后会 emit)
  326. uni.$on('resume_delivered', (data) => {
  327. console.log('收到 resume_delivered 事件:', data);
  328. if (data && data.postId == positionId.value) {
  329. jobState.value = 'added';
  330. }
  331. });
  332. });
  333. onShow(() => {
  334. if (positionId.value) {
  335. checkState();
  336. }
  337. });
  338. onUnmounted(() => {
  339. uni.$off('payment_done');
  340. uni.$off('resume_delivered');
  341. });
  342. const handleMainAction = async () => {
  343. if (jobState.value === 'initial') {
  344. try {
  345. uni.showLoading({ title: '正在连接客服...' });
  346. const userInfo = uni.getStorageSync('userInfo') || {};
  347. const userId = userInfo.studentId || null;
  348. const userName = userInfo.name || '用户';
  349. const userAvatar = userInfo.avatarUrl || '/static/images/user_avatar.svg';
  350. const res = await createOrGetSession({
  351. sessionType: 1,
  352. fromUserId: userId,
  353. fromUserName: userName,
  354. fromUserAvatar: userAvatar,
  355. sourceId: 'job_' + positionId.value
  356. });
  357. uni.hideLoading();
  358. if (res.data) {
  359. const session = res.data;
  360. uni.navigateTo({
  361. url: `/pages/chat/chat?sessionId=${session.sessionId}&sessionNo=${session.sessionNo || ''}&fromUserId=${userId}&userName=${encodeURIComponent(userName)}&jobName=${encodeURIComponent(jobInfo.value.postName || '')}&type=job&positionId=${positionId.value}&salaryRange=${encodeURIComponent(jobInfo.value.salaryRange || '')}&companyName=${encodeURIComponent(jobInfo.value.companyName || '')}&workCity=${encodeURIComponent(jobInfo.value.workCity || '')}`
  362. });
  363. } else {
  364. uni.showToast({ title: '创建会话失败', icon: 'none' });
  365. }
  366. } catch (err) {
  367. uni.hideLoading();
  368. console.error('创建会话失败:', err);
  369. uni.showToast({ title: '连接失败,请重试', icon: 'none' });
  370. }
  371. } else if (jobState.value === 'paid') {
  372. uni.navigateTo({
  373. url: '/pages/assessment/remind?family=audit'
  374. });
  375. } else if (jobState.value === 'assessed') {
  376. // 投递简历:跳转到选择简历页面
  377. const userInfo = uni.getStorageSync('userInfo') || {};
  378. if (!userInfo.studentId) {
  379. uni.showToast({ title: '请先登录', icon: 'none' });
  380. setTimeout(() => {
  381. uni.navigateTo({ url: '/pages/login/login' });
  382. }, 1000);
  383. return;
  384. }
  385. uni.navigateTo({
  386. url: `/pages/my/select-resume?postId=${positionId.value}`
  387. });
  388. }
  389. };
  390. const updateState = (state) => {
  391. jobState.value = state;
  392. };
  393. // 状态逻辑已移至 checkState 内部
  394. </script>
  395. <style lang="scss" scoped>
  396. .detail-container {
  397. width: 100%;
  398. height: 100vh;
  399. background-color: #FFFFFF;
  400. display: flex;
  401. flex-direction: column;
  402. }
  403. .scroll-wrapper {
  404. flex: 1;
  405. }
  406. .section {
  407. padding: 30rpx 40rpx;
  408. background-color: #FFFFFF;
  409. }
  410. .section-title {
  411. font-size: 34rpx;
  412. font-weight: bold;
  413. color: #1A1A1A;
  414. margin-bottom: 30rpx;
  415. }
  416. /* 头部样式 */
  417. .header-section {
  418. padding-top: 20rpx;
  419. .title-line {
  420. display: flex;
  421. justify-content: space-between;
  422. align-items: center;
  423. margin-bottom: 24rpx;
  424. .left-box {
  425. display: flex;
  426. align-items: center;
  427. .job-name {
  428. font-size: 44rpx;
  429. font-weight: bold;
  430. color: #1A1A1A;
  431. margin-right: 16rpx;
  432. }
  433. .urgent-tag {
  434. font-size: 20rpx;
  435. color: #FF4D4F;
  436. border: 1rpx solid #FF4D4F;
  437. padding: 2rpx 10rpx;
  438. border-radius: 6rpx;
  439. }
  440. }
  441. .salary {
  442. font-size: 38rpx;
  443. font-weight: bold;
  444. color: #1F6CFF;
  445. }
  446. }
  447. .meta-list {
  448. .meta-item {
  449. display: flex;
  450. align-items: center;
  451. margin-bottom: 12rpx;
  452. font-size: 26rpx;
  453. color: #777777;
  454. .icon {
  455. width: 30rpx;
  456. height: 30rpx;
  457. margin-right: 12rpx;
  458. opacity: 0.7;
  459. }
  460. .warning-text {
  461. color: #FF4D4F;
  462. margin-left: 16rpx;
  463. }
  464. }
  465. }
  466. }
  467. /* HR 区域 */
  468. .hr-section {
  469. border-top: 1rpx solid #F8F9FB;
  470. display: flex;
  471. align-items: center;
  472. padding: 30rpx 40rpx;
  473. .hr-avatar {
  474. width: 100rpx;
  475. height: 100rpx;
  476. border-radius: 50%;
  477. margin-right: 24rpx;
  478. background-color: #F0F0F0;
  479. }
  480. .hr-content {
  481. .hr-name {
  482. display: block;
  483. font-size: 30rpx;
  484. font-weight: bold;
  485. color: #1A1A1A;
  486. margin-bottom: 4rpx;
  487. }
  488. .hr-desc {
  489. font-size: 24rpx;
  490. color: #888888;
  491. }
  492. }
  493. }
  494. /* 岗位详情描述 */
  495. .detail-content {
  496. border-top: 10rpx solid #F8F9FB;
  497. .tag-cloud {
  498. display: flex;
  499. flex-wrap: wrap;
  500. gap: 16rpx;
  501. margin-bottom: 40rpx;
  502. .tag-label {
  503. background-color: #F5F7FA;
  504. color: #888888;
  505. font-size: 24rpx;
  506. padding: 10rpx 24rpx;
  507. border-radius: 6rpx;
  508. }
  509. }
  510. .rich-text-wrapper {
  511. font-size: 28rpx;
  512. color: #555555;
  513. line-height: 1.8;
  514. }
  515. .info-block {
  516. margin-bottom: 24rpx;
  517. .block-label {
  518. display: block;
  519. font-size: 28rpx;
  520. font-weight: bold;
  521. color: #1A1A1A;
  522. margin-bottom: 8rpx;
  523. }
  524. .block-text {
  525. font-size: 28rpx;
  526. color: #555555;
  527. line-height: 1.6;
  528. }
  529. .list-item {
  530. display: flex;
  531. margin-bottom: 8rpx;
  532. .dot {
  533. font-weight: bold;
  534. margin-right: 12rpx;
  535. color: #1A1A1A;
  536. }
  537. .list-text {
  538. font-size: 28rpx;
  539. color: #555555;
  540. line-height: 1.6;
  541. }
  542. }
  543. }
  544. }
  545. /* 办公地址区 - 动态地图 */
  546. .address-section {
  547. border-top: 10rpx solid #F8F9FB;
  548. .map-wrapper {
  549. position: relative;
  550. width: 100%;
  551. height: 360rpx;
  552. border-radius: 12rpx;
  553. overflow: hidden;
  554. box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.06);
  555. .map-view {
  556. width: 100%;
  557. height: 100%;
  558. }
  559. }
  560. }
  561. /* 公司概况区 */
  562. .company-section {
  563. border-top: 10rpx solid #F8F9FB;
  564. .company-header {
  565. display: flex;
  566. align-items: center;
  567. margin-bottom: 24rpx;
  568. .company-logo {
  569. width: 80rpx;
  570. height: 80rpx;
  571. border-radius: 12rpx;
  572. background: #f0f0f0;
  573. margin-right: 20rpx;
  574. }
  575. .company-name {
  576. font-size: 32rpx;
  577. font-weight: bold;
  578. color: #1A1A1A;
  579. }
  580. }
  581. .company-desc {
  582. font-size: 28rpx;
  583. color: #666666;
  584. line-height: 1.6;
  585. }
  586. }
  587. .end-tip {
  588. padding: 60rpx 0;
  589. text-align: center;
  590. text {
  591. font-size: 24rpx;
  592. color: #CCCCCC;
  593. }
  594. }
  595. .safe-bottom-holder {
  596. height: 140rpx;
  597. }
  598. /* 底部栏 */
  599. .bottom-action-bar {
  600. position: fixed;
  601. bottom: 0;
  602. left: 0;
  603. right: 0;
  604. height: 120rpx;
  605. background-color: #FFFFFF;
  606. display: flex;
  607. align-items: center;
  608. padding: 0 40rpx;
  609. padding-bottom: env(safe-area-inset-bottom);
  610. box-shadow: 0 -4rpx 20rpx rgba(0,0,0,0.08);
  611. z-index: 999;
  612. .collect-box {
  613. display: flex;
  614. flex-direction: column;
  615. align-items: center;
  616. width: 80rpx;
  617. margin-right: 40rpx;
  618. background: transparent; /* 强制背景透明 */
  619. .star-icon {
  620. width: 44rpx;
  621. height: 44rpx;
  622. margin-bottom: 4rpx;
  623. background: transparent;
  624. display: block;
  625. }
  626. .collect-text {
  627. font-size: 20rpx;
  628. color: #999999;
  629. }
  630. }
  631. .consult-btn {
  632. flex: 1;
  633. background-color: #FFB700;
  634. height: 88rpx;
  635. border-radius: 44rpx;
  636. display: flex;
  637. align-items: center;
  638. justify-content: center;
  639. transition: all 0.3s;
  640. text {
  641. color: #FFFFFF;
  642. font-size: 32rpx;
  643. font-weight: bold;
  644. }
  645. &.initial, &.paid {
  646. background-color: #FFB700;
  647. box-shadow: 0 8rpx 16rpx rgba(255, 183, 0, 0.2);
  648. }
  649. &.assessed {
  650. background-color: #1F6CFF; // 测评通过后变为蓝色,投递简历
  651. box-shadow: 0 8rpx 16rpx rgba(31, 108, 255, 0.2);
  652. }
  653. &.added {
  654. background-color: #E0E0E0 !important; // 已投递后禁用灰色
  655. box-shadow: none !important;
  656. pointer-events: none;
  657. text {
  658. color: #999 !important;
  659. }
  660. }
  661. &:active {
  662. opacity: 0.9;
  663. }
  664. }
  665. }
  666. </style>