communicationRecords.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. <template>
  2. <view class="page">
  3. <!-- Custom Navbar -->
  4. <view class="custom-navbar">
  5. <view class="navbar-content">
  6. <view class="navbar-left" @click="goBack">
  7. <u-icon name="arrow-leftward" color="color: rgba(51, 51, 51, 1);" size="36"></u-icon>
  8. </view>
  9. <view class="navbar-title">沟通记录</view>
  10. <view class="navbar-right"></view>
  11. </view>
  12. </view>
  13. <view class="tab-section-bg">
  14. <text class="title-text">沟通记录</text>
  15. <text class="interview-manage" @click="goToInterviewManage">面试管理</text>
  16. </view>
  17. <!-- Tab Navigation -->
  18. <view class="tab-section">
  19. <u-tabs :list="tabs" :current="activeTab" @change="switchTab" :is-scroll="false" :height="88"
  20. :font-size="24" active-color="rgba(1, 107, 246, 1)" inactive-color="rgba(102, 102, 102, 1)"
  21. :bar-width="80" :bar-height="4" :gutter="40" bg-color="#ffffff" :bar-style="{
  22. borderRadius: '2rpx'
  23. }"></u-tabs>
  24. </view>
  25. <!-- Content Section -->
  26. <view class="content-section">
  27. <!-- Communication Records List -->
  28. <view class="communication-list" v-if="activeTab === 0">
  29. <!-- 有数据时显示列表 -->
  30. <view v-if="communicationRecords.length > 0">
  31. <!-- Date Group -->
  32. <view class="date-group" v-for="(group, groupIndex) in groupedRecords" :key="groupIndex">
  33. <view class="date-header">
  34. <text class="date-text">{{ group.date }}</text>
  35. </view>
  36. <!-- Records for this date -->
  37. <view class="talent-card" v-for="(record, recordIndex) in group.records" :key="recordIndex"
  38. @click="goToResumeDetail(record)">
  39. <view class="talent-content">
  40. <!-- 头像和基本信息 -->
  41. <view class="talent-header">
  42. <image :src="record.userAvatar" class="talent-avatar" mode="aspectFill"></image>
  43. <view class="talent-info">
  44. <view class="talent-name-section">
  45. <view class="talent-name">{{ record.userName }}</view>
  46. <view class="talent-tags">
  47. <view class="status-tag online" v-if="record.isOnline">在线</view>
  48. <view class="status-tag hot" v-if="record.isHot">热门搜索</view>
  49. <view class="status-tag active" v-if="record.lastActive">
  50. {{ record.lastActive }}</view>
  51. </view>
  52. </view>
  53. <!-- 经验和薪资 -->
  54. <view class="talent-experience">
  55. <text class="experience-text">{{ record.resumesWorkExperience }}年</text>
  56. <text class="education-salary">{{ record.degree }}
  57. {{ record.minSalary }}-{{record.maxSalary}}</text>
  58. <text
  59. class="status-text">{{ record.resumesStatus==1?'在职&考虑机会':"离职" }}</text>
  60. </view>
  61. </view>
  62. </view>
  63. <!-- 当前职位 -->
  64. <view class="current-job" v-if="record.companyName">
  65. <image src="../../static/images/aixin.svg" class="job-icon" mode="aspectFit">
  66. </image>
  67. <text class="job-text">{{ record.companyName }}</text>
  68. </view>
  69. <!-- 求职期望 -->
  70. <view class="job-expectation">
  71. <image src="../../static/images/xiangzi.svg" class="job-icon" mode="aspectFit">
  72. </image>
  73. <text class="expectation-text">求职期望: {{ record.expectedPosition }}</text>
  74. </view>
  75. <!-- 技能标签 -->
  76. <view class="skill-tags">
  77. <view class="skill-tag" v-for="(skill, skillIndex) in record.skillName.split(',')"
  78. :key="skillIndex">
  79. {{ skill }}
  80. </view>
  81. </view>
  82. <!-- 工作描述 -->
  83. <view class="job-description">
  84. <text class="description-text">{{ record.workContent }}</text>
  85. </view>
  86. </view>
  87. </view>
  88. </view>
  89. </view>
  90. <!-- 空状态显示 -->
  91. <view class="empty-state" v-else>
  92. <view class="empty-illustration">
  93. <image src="../../static/images/index/Hrempty.svg" class="empty-image" mode="aspectFit" />
  94. </view>
  95. </view>
  96. </view>
  97. <!-- Interview Records List -->
  98. <view class="interview-list" v-if="activeTab === 1">
  99. <!-- Date Selector -->
  100. <view class="date-selector">
  101. <!-- Month Switcher -->
  102. <view class="month-switcher">
  103. <u-icon name="arrow-left" color="#666" size="28" @click="changeMonth(-1)"></u-icon>
  104. <text class="current-month">{{ currentYear }}年{{ currentMonth }}月</text>
  105. <u-icon name="arrow-right" color="#666" size="28" @click="changeMonth(1)"></u-icon>
  106. </view>
  107. <!-- Week Days -->
  108. <view class="week-days">
  109. <text class="day-name" v-for="day in currentMonthDays" :key="day.name">{{ day.name }}</text>
  110. </view>
  111. <!-- Month Dates -->
  112. <view class="month-dates">
  113. <view class="date-item"
  114. :class="{
  115. active: date.isSelected,
  116. 'other-month': date.isOtherMonth
  117. }"
  118. v-for="(date,index) in currentMonthDates"
  119. :key="index"
  120. @click="selectDate(date)">
  121. <text class="date-value">{{ date.value }}</text>
  122. </view>
  123. </view>
  124. </view>
  125. <!-- Interview Records -->
  126. <view class="interview-records">
  127. <!-- 有数据时显示列表 -->
  128. <view v-if="interviewRecords.length > 0">
  129. <view class="interview-record"
  130. :class="{ 'today': formatDate(record.interviewDateTime,'YYYY-MM-DD') === formatDate(selectDate,'YYYY-MM-DD') }"
  131. v-for="(record, index) in interviewRecords" :key="index"
  132. @click="goToInterviewDetail(record)">
  133. <view class="record-content">
  134. <view class="record-left">
  135. <text
  136. class="date-label">{{ checkDate(record.interviewDateTime) === 1 ? '今天' : checkDate(record.interviewDateTime) === 2 ? '明天' : record.interviewDateTime.substring(5, 10) }}</text>
  137. <text
  138. class="time-label">{{ record.detailTime? record.detailTime : record.interviewDateTime.substring(11, 16) }}</text>
  139. </view>
  140. <view class="record-divider"></view>
  141. <view class="record-right">
  142. <text class="candidate-name">{{ record.userEntity.userName }}</text>
  143. <block v-if="record.resumesListDto.length > 0">
  144. <text
  145. class="candidate-details">{{ record.resumesListDto[0].resumesWorkExperience? record.resumesListDto[0].resumesWorkExperience + '年' :'无经验'}}
  146. {{ record.resumesListDto[0].degree }}
  147. {{ record.resumesListDto[0].minSalary }}-{{ record.resumesListDto[0].maxSalary }}</text>
  148. </block>
  149. </view>
  150. </view>
  151. </view>
  152. </view>
  153. <!-- 空状态显示 -->
  154. <view class="empty-state" v-else>
  155. <view class="empty-illustration">
  156. <image style="height: 300px;" src="../../static/images/index/Hrempty.svg" class="empty-image" mode="aspectFit" />
  157. </view>
  158. </view>
  159. </view>
  160. </view>
  161. <!-- 收藏标签页 -->
  162. <view class="favorite-list" v-if="activeTab === 2">
  163. <!-- 有数据时显示列表 -->
  164. <view v-if="favoriteRecords.length > 0">
  165. <!-- 收藏记录列表内容 -->
  166. <view class="qyList flex justify-center">
  167. <view class="qyList-box">
  168. <view class="qyList-box-item flex justify-center" v-for="(item, index) in favoriteRecords"
  169. :key="index"
  170. @click="goNav(`/pages/talentSearch/resumeDetail?resumesId=${item.resumesId}&postPushId=${item.postPushId}`)">
  171. <view class="qyList-box-item-box">
  172. <view class="qyList-box-item-info flex justify-between align-center" v-if="item.resumesListDto[0]">
  173. <view class="qyList-box-item-info-l">
  174. <view style="color: #212121; font-size: 38rpx; font-weight: 800">
  175. {{ item.resumesListDto[0].userName }}
  176. </view>
  177. <view class="flex align-center flex-wrap"
  178. style="color: #999999; font-size: 26rpx; margin-top: 10rpx">
  179. <text>{{ item.resumesListDto[0].userAge }}岁</text>
  180. <text style="margin-left: 20rpx; margin-right: 20rpx">|</text>
  181. <text>{{ item.resumesListDto[0].resumesWorkExperience }}年</text>
  182. <text style="margin-left: 20rpx; margin-right: 20rpx">|</text>
  183. <text>{{ item.resumesListDto[0].degree }}</text>
  184. <text style="margin-left: 20rpx; margin-right: 20rpx">|</text>
  185. <text>期望{{item.resumesListDto[0].minSalary}} - {{item.resumesListDto[0].maxSalary}}</text>
  186. </view>
  187. </view>
  188. <view class="qyList-box-item-info-r">
  189. <image
  190. :src="item.resumesListDto[0].userAvatar ? item.resumesListDto[0].userAvatar : '../../static/logo.png'"
  191. style="width: 95rpx; height: 95rpx; border-radius: 50%" mode=""></image>
  192. </view>
  193. </view>
  194. <view class="qyList-box-item-job flex align-center" v-if="item.resumesListDto[0]">
  195. <image src="../../static/images/qi.png"
  196. style="width: 30rpx; height: 32rpx; margin-right: 16rpx" mode=""></image>
  197. <view class="txt-desc flex align-center justify-between">
  198. <view>
  199. <view>{{ item.resumesListDto[0].companyName }}</view>
  200. <view v-if="item.resumesListDto[0]">
  201. {{ item.resumesListDto[0].lastWorkStartTime ? item.resumesListDto[0].lastWorkStartTime.slice(0, 10)
  202. : ''
  203. }}--{{
  204. item.resumesListDto[0].lastWorkEndTime ? item.resumesListDto[0].lastWorkEndTime.slice(0, 10) : '' }}
  205. </view>
  206. </view>
  207. <view>
  208. <view>
  209. {{ item.resumesListDto[0].school ? item.resumesListDto[0].school : '' }}
  210. </view>
  211. <view>
  212. {{ item.resumesListDto[0].degree }}
  213. </view>
  214. </view>
  215. </view>
  216. </view>
  217. <view class="qyList-box-item-job flex align-center" v-if="item.resumesListDto[0]">
  218. <u-icon name="heart-fill" color="#016BF6" size="30" style="margin-right: 16rpx">
  219. </u-icon>
  220. 期望岗位:{{ item.resumesListDto[0].expectedPosition }}
  221. </view>
  222. <!-- <view class="qyList-box-item-rem" v-if="item.resumesDetails">
  223. 优势:{{ item.resumes.workContent }}
  224. </view> -->
  225. </view>
  226. </view>
  227. </view>
  228. </view>
  229. </view>
  230. <!-- 空状态显示 -->
  231. <view class="empty-state" v-else>
  232. <view class="empty-illustration">
  233. <image src="../../static/images/index/Hrempty.svg" class="empty-image" mode="aspectFit" />
  234. </view>
  235. </view>
  236. </view>
  237. <!-- 收藏职位标签页 -->
  238. <view class="favorite-jobs-list" v-if="activeTab === 3">
  239. <!-- 有数据时显示列表 -->
  240. <view v-if="favoriteJobs.length > 0">
  241. <!-- 收藏职位列表内容 -->
  242. </view>
  243. <!-- 空状态显示 -->
  244. <view class="empty-state" v-else>
  245. <view class="empty-illustration">
  246. <image src="../../static/images/index/Hrempty.svg" class="empty-image" mode="aspectFit" />
  247. </view>
  248. </view>
  249. </view>
  250. </view>
  251. </view>
  252. </template>
  253. <script>
  254. export default {
  255. data() {
  256. return {
  257. statusBarHeight: 0,
  258. activeTab: 0,
  259. tabs: [{
  260. name: '沟通过'
  261. },
  262. {
  263. name: '面试'
  264. },
  265. {
  266. name: '收藏简历'
  267. },
  268. // { name: '收藏职位' }
  269. ],
  270. communicationRecords: [],
  271. // 面试相关数据
  272. selectedDate: null, // 当前选中的日期
  273. // 收藏相关数据
  274. favoriteRecords: [], // 收藏记录(空数组,显示空状态)
  275. favoriteJobs: [], // 收藏职位(空数组,显示空状态)
  276. interviewRecords: [],
  277. // 当前显示的年月
  278. currentYear: new Date().getFullYear(),
  279. currentMonth: new Date().getMonth() + 1 // 1-12
  280. }
  281. },
  282. computed: {
  283. groupedRecords() {
  284. const records = Array.isArray(this.communicationRecords) ?
  285. this.communicationRecords :
  286. []
  287. const groups = {}
  288. records
  289. .filter(r => r && r.lastTime) // 过滤掉 null 或没有 lastTime 的数据
  290. .forEach(record => {
  291. const date = record.lastTime.substring(0, 10)
  292. if (!groups[date]) {
  293. groups[date] = {
  294. date,
  295. records: []
  296. }
  297. }
  298. groups[date].records.push(record)
  299. })
  300. return Object.values(groups)
  301. },
  302. // 星期名称
  303. currentMonthDays() {
  304. const weekDays = ['日', '一', '二', '三', '四', '五', '六']
  305. return weekDays.map(name => ({
  306. name
  307. }))
  308. },
  309. // 当前月的日期
  310. currentMonthDates() {
  311. const today = new Date()
  312. // 计算当前月份的第一天
  313. const firstDay = new Date(this.currentYear, this.currentMonth - 1, 1)
  314. // 计算当前月份的天数
  315. const daysInMonth = new Date(this.currentYear, this.currentMonth, 0).getDate()
  316. // 计算第一天是星期几(0-6,0是周日)
  317. const firstDayOfWeek = firstDay.getDay()
  318. // 生成当前月份的日期数组
  319. const monthDates = []
  320. // 添加上月的日期(填充第一行)
  321. if (firstDayOfWeek > 0) {
  322. const prevMonthLastDay = new Date(this.currentYear, this.currentMonth - 1, 0).getDate()
  323. for (let i = firstDayOfWeek - 1; i >= 0; i--) {
  324. const date = new Date(this.currentYear, this.currentMonth - 1, prevMonthLastDay - i)
  325. monthDates.push({
  326. value: date.getDate().toString(),
  327. date: date,
  328. isSelected: false,
  329. isOtherMonth: true
  330. })
  331. }
  332. }
  333. // 添加当月的日期
  334. for (let i = 1; i <= daysInMonth; i++) {
  335. const date = new Date(this.currentYear, this.currentMonth - 1, i)
  336. const isToday = date.toDateString() === today.toDateString()
  337. const isSelected = this.selectedDate ?
  338. date.toDateString() === this.selectedDate.toDateString() : isToday
  339. monthDates.push({
  340. value: i.toString(),
  341. date: date,
  342. isSelected: isSelected,
  343. isOtherMonth: false
  344. })
  345. }
  346. // 添加下月的日期(填充最后一行)
  347. const totalCells = Math.ceil(monthDates.length / 7) * 7
  348. if (monthDates.length < totalCells) {
  349. const remainingCells = totalCells - monthDates.length
  350. for (let i = 1; i <= remainingCells; i++) {
  351. const date = new Date(this.currentYear, this.currentMonth, i)
  352. monthDates.push({
  353. value: i.toString(),
  354. date: date,
  355. isSelected: false,
  356. isOtherMonth: true
  357. })
  358. }
  359. }
  360. return monthDates
  361. },
  362. },
  363. onLoad(options) {
  364. console.log(options);
  365. this.activeTab = options.tab ? parseInt(options.tab) : 0
  366. const systemInfo = uni.getSystemInfoSync()
  367. this.statusBarHeight = systemInfo.statusBarHeight || 0
  368. this.getData()
  369. this.getInterviewRecords()
  370. this.getFavoriteRecords()
  371. },
  372. methods: {
  373. getFavoriteRecords() {
  374. this.$Request.getT("/app/myCollection/getCompanyCollectionList").then(res => {
  375. console.log(res);
  376. this.favoriteRecords = res.data.records //收藏记录
  377. })
  378. },
  379. checkDate(targetDate) {
  380. const today = new Date();
  381. const tomorrow = new Date();
  382. tomorrow.setDate(today.getDate() + 1);
  383. const inputDate = new Date(targetDate);
  384. // 重置时间为 00:00:00 进行比较
  385. today.setHours(0, 0, 0, 0);
  386. tomorrow.setHours(0, 0, 0, 0);
  387. inputDate.setHours(0, 0, 0, 0);
  388. if (inputDate.getTime() === today.getTime()) {
  389. return 1; // 今天
  390. } else if (inputDate.getTime() === tomorrow.getTime()) {
  391. return 2; // 明天
  392. } else {
  393. return 0; // 其他日期
  394. }
  395. },
  396. formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
  397. const d = new Date(date);
  398. const padZero = (num) => String(num).padStart(2, '0');
  399. const replacements = {
  400. 'YYYY': d.getFullYear(),
  401. 'MM': padZero(d.getMonth() + 1),
  402. 'DD': padZero(d.getDate()),
  403. 'HH': padZero(d.getHours()),
  404. 'mm': padZero(d.getMinutes()),
  405. 'ss': padZero(d.getSeconds()),
  406. 'SSS': padZero(d.getMilliseconds()).padStart(3, '0'),
  407. 'M': d.getMonth() + 1,
  408. 'D': d.getDate(),
  409. 'H': d.getHours(),
  410. 'm': d.getMinutes(),
  411. 's': d.getSeconds()
  412. };
  413. return format.replace(/YYYY|MM|DD|HH|mm|ss|SSS|M|D|H|m|s/g, match => replacements[match]);
  414. },
  415. getInterviewRecords() {
  416. this.$Request.getT("/app/interviewRecord/getHrInterviewList").then(res => {
  417. console.log(res);
  418. this.interviewRecords = res.data.records //沟通记录
  419. })
  420. },
  421. getYearMonthInterval(startDate, endDate) {
  422. // 确保传入的是 Date 对象
  423. const start = new Date(startDate);
  424. const end = new Date(endDate);
  425. console.log(start, end, '为啥')
  426. return;
  427. // 确保结束日期在开始日期之后
  428. if (end < start) {
  429. throw new Error('结束日期必须在开始日期之后');
  430. }
  431. // 计算年份差异
  432. let yearDiff = end.getFullYear() - start.getFullYear();
  433. // 计算月份差异
  434. let monthDiff = end.getMonth() - start.getMonth();
  435. // 如果结束日期的月份小于开始日期的月份,需要借年
  436. if (monthDiff < 0) {
  437. yearDiff--;
  438. monthDiff += 12;
  439. }
  440. // 如果月份相同,但结束日期的日期小于开始日期的日期,也需要借月
  441. if (monthDiff === 0 && end.getDate() < start.getDate()) {
  442. yearDiff--;
  443. monthDiff = 11;
  444. } else if (end.getDate() < start.getDate()) {
  445. monthDiff--;
  446. }
  447. return [yearDiff, monthDiff];
  448. },
  449. goBack() {
  450. uni.navigateBack()
  451. },
  452. switchTab(index) {
  453. this.activeTab = index
  454. },
  455. goToResumeDetail(record) {
  456. console.log('查看简历详情:', record)
  457. uni.navigateTo({
  458. url: `/pages/talentSearch/resumeDetail?resumeId=${record.id}`
  459. })
  460. },
  461. selectDate(date) {
  462. // 选中当前点击的日期
  463. this.selectedDate = date.date
  464. console.log('选中日期:', date.date)
  465. },
  466. // 切换月份
  467. changeMonth(direction) {
  468. let newMonth = this.currentMonth + direction
  469. let newYear = this.currentYear
  470. if (newMonth < 1) {
  471. newMonth = 12
  472. newYear--
  473. } else if (newMonth > 12) {
  474. newMonth = 1
  475. newYear++
  476. }
  477. this.currentYear = newYear
  478. this.currentMonth = newMonth
  479. },
  480. goToInterviewDetail(record) {
  481. console.log('查看面试详情:', record)
  482. uni.navigateTo({
  483. url: `/my/jilu/bossMianshiDetail?recordId=${record.recordId}`
  484. })
  485. },
  486. goToInterviewManage() {
  487. console.log('跳转到面试管理')
  488. uni.navigateTo({
  489. url: '/pages/recruitmentData/interviewManage'
  490. })
  491. },
  492. getData() {
  493. this.$Request.getT("/app/chat/chatUser").then(res => {
  494. console.log(res);
  495. this.communicationRecords = res.data.records //沟通记录
  496. })
  497. },
  498. goNav(url) {
  499. uni.navigateTo({
  500. url: url
  501. })
  502. }
  503. }
  504. }
  505. </script>
  506. <style lang="scss" scoped>
  507. .page {
  508. height: 100vh;
  509. overflow: hidden;
  510. }
  511. .tab-section-bg {
  512. position: fixed;
  513. top: 150rpx;
  514. left: 0;
  515. right: 0;
  516. z-index: 1000;
  517. background-color: #ffffff;
  518. padding: 32rpx;
  519. display: flex;
  520. justify-content: space-between;
  521. align-items: center;
  522. .title-text {
  523. color: rgba(51, 51, 51, 1);
  524. font-family: DM Sans;
  525. font-size: 48rpx;
  526. font-weight: 700;
  527. line-height: 60rpx;
  528. letter-spacing: 0px;
  529. }
  530. .interview-manage {
  531. color: rgba(1, 107, 246, 1);
  532. font-family: DM Sans;
  533. font-size: 28rpx;
  534. font-weight: 400;
  535. line-height: 60rpx;
  536. letter-spacing: 0px;
  537. text-align: left;
  538. }
  539. }
  540. /* Custom Navbar */
  541. .custom-navbar {
  542. position: fixed;
  543. top: 0;
  544. left: 0;
  545. right: 0;
  546. z-index: 1000;
  547. background-color: #ffffff;
  548. padding-top: 80rpx;
  549. }
  550. .navbar-content {
  551. display: flex;
  552. align-items: center;
  553. justify-content: space-between;
  554. height: 44px;
  555. padding: 20rpx;
  556. }
  557. .navbar-left {
  558. width: 44px;
  559. height: 44px;
  560. display: flex;
  561. align-items: center;
  562. justify-content: center;
  563. }
  564. .navbar-title {
  565. color: rgba(51, 51, 51, 1);
  566. font-family: DM Sans;
  567. font-size: 30rpx;
  568. font-weight: 700;
  569. line-height: 52rpx;
  570. letter-spacing: 0.5%;
  571. text-align: center;
  572. }
  573. .navbar-right {
  574. width: 44px;
  575. }
  576. /* Tab Section */
  577. .tab-section {
  578. position: fixed;
  579. top: 250rpx;
  580. left: 0;
  581. right: 0;
  582. background: white;
  583. z-index: 99;
  584. }
  585. /* Content Section */
  586. .content-section {
  587. margin-top: 330rpx;
  588. padding: 20rpx;
  589. height: calc(100vh - 330rpx) !important;
  590. overflow-y: auto;
  591. }
  592. /* Date Group */
  593. .date-group {
  594. margin-bottom: 20rpx;
  595. }
  596. .date-header {
  597. margin-bottom: 16rpx;
  598. }
  599. .date-text {
  600. color: rgba(153, 153, 153, 1);
  601. font-family: DM Sans;
  602. font-size: 24rpx;
  603. font-weight: 400;
  604. line-height: 32rpx;
  605. margin-left: 32rpx;
  606. }
  607. /* Talent Card */
  608. .talent-card {
  609. background-color: #ffffff;
  610. border-radius: 16rpx;
  611. margin-bottom: 20rpx;
  612. padding: 30rpx;
  613. // box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  614. }
  615. .talent-content {
  616. .talent-header {
  617. display: flex;
  618. align-items: flex-start;
  619. .talent-avatar {
  620. width: 80rpx;
  621. height: 80rpx;
  622. border-radius: 50%;
  623. margin-right: 20rpx;
  624. }
  625. .talent-info {
  626. flex: 1;
  627. .talent-name-section {
  628. display: flex;
  629. align-items: center;
  630. justify-content: flex-start;
  631. width: 100%;
  632. margin-bottom: 6rpx;
  633. }
  634. .talent-name {
  635. color: rgba(51, 51, 51, 1);
  636. font-family: DM Sans;
  637. font-size: 28rpx;
  638. font-weight: 500;
  639. line-height: 36rpx;
  640. letter-spacing: 0.5%;
  641. text-align: left;
  642. margin-right: 16rpx;
  643. }
  644. .talent-tags {
  645. display: flex;
  646. flex-wrap: wrap;
  647. gap: 10rpx;
  648. .status-tag {
  649. padding: 8rpx;
  650. border-radius: 12rpx;
  651. font-size: 18rpx;
  652. font-family: DM Sans;
  653. font-weight: 400;
  654. line-height: 20rpx;
  655. letter-spacing: -0.5px;
  656. text-align: left;
  657. &.online {
  658. background: rgba(213, 255, 231, 1);
  659. color: rgba(29, 209, 104, 1);
  660. }
  661. &.hot {
  662. background: rgba(252, 233, 220, 1);
  663. color: rgba(1, 107, 246, 1);
  664. }
  665. &.active {
  666. color: rgba(153, 153, 153, 1);
  667. }
  668. }
  669. }
  670. }
  671. }
  672. .talent-experience {
  673. display: flex;
  674. align-items: center;
  675. margin-bottom: 12rpx;
  676. gap: 16rpx;
  677. color: rgba(156, 164, 171, 1);
  678. font-family: DM Sans;
  679. font-size: 24rpx;
  680. font-weight: 400;
  681. line-height: 32rpx;
  682. letter-spacing: 0.5%;
  683. text-align: left;
  684. }
  685. .current-job {
  686. display: flex;
  687. align-items: center;
  688. margin-bottom: 12rpx;
  689. .job-icon {
  690. width: 40rpx;
  691. height: 40rpx;
  692. margin-right: 8rpx;
  693. }
  694. .job-text {
  695. color: rgba(156, 164, 171, 1);
  696. font-family: DM Sans;
  697. font-size: 24rpx;
  698. font-weight: 400;
  699. line-height: 40rpx;
  700. letter-spacing: 0.5%;
  701. text-align: left;
  702. flex: 1;
  703. }
  704. .work-period {
  705. color: rgba(153, 153, 153, 1);
  706. font-family: DM Sans;
  707. font-size: 22rpx;
  708. font-weight: 400;
  709. line-height: 28rpx;
  710. }
  711. }
  712. .job-expectation {
  713. display: flex;
  714. align-items: center;
  715. margin-bottom: 16rpx;
  716. .job-icon {
  717. width: 40rpx;
  718. height: 40rpx;
  719. margin-right: 8rpx;
  720. }
  721. .expectation-text {
  722. color: rgba(156, 164, 171, 1);
  723. font-family: DM Sans;
  724. font-size: 24rpx;
  725. font-weight: 400;
  726. line-height: 40rpx;
  727. letter-spacing: 0.5%;
  728. text-align: left;
  729. }
  730. }
  731. .skill-tags {
  732. display: flex;
  733. flex-wrap: wrap;
  734. gap: 10rpx;
  735. margin-bottom: 16rpx;
  736. .skill-tag {
  737. padding: 8rpx;
  738. background: rgba(198, 198, 198, 0.1);
  739. border-radius: 12rpx;
  740. color: rgba(153, 153, 153, 1);
  741. font-family: DM Sans;
  742. font-size: 20rpx;
  743. font-weight: 400;
  744. line-height: 20rpx;
  745. letter-spacing: -0.5px;
  746. text-align: left;
  747. }
  748. }
  749. .job-description {
  750. margin-bottom: 12rpx;
  751. .description-text {
  752. color: rgba(97, 110, 124, 1);
  753. font-family: DM Sans;
  754. font-size: 24rpx;
  755. font-weight: 400;
  756. line-height: 32rpx;
  757. letter-spacing: 0px;
  758. text-align: left;
  759. }
  760. }
  761. }
  762. /* Interview List Styles */
  763. .interview-list {
  764. padding: 0 20rpx;
  765. }
  766. /* Date Selector */
  767. .date-selector {
  768. background: #ffffff;
  769. border-radius: 12rpx;
  770. padding: 24rpx;
  771. margin-bottom: 20rpx;
  772. }
  773. /* Month Switcher */
  774. .month-switcher {
  775. display: flex;
  776. align-items: center;
  777. justify-content: space-between;
  778. margin-bottom: 24rpx;
  779. }
  780. .current-month {
  781. color: rgba(51, 51, 51, 1);
  782. font-family: DM Sans;
  783. font-size: 28rpx;
  784. font-weight: 700;
  785. line-height: 36rpx;
  786. }
  787. /* Week Days */
  788. .week-days {
  789. display: flex;
  790. justify-content: space-between;
  791. margin-bottom: 16rpx;
  792. padding: 0 10rpx;
  793. }
  794. .day-name {
  795. color: rgba(153, 153, 153, 1);
  796. font-family: DM Sans;
  797. font-size: 24rpx;
  798. font-weight: 400;
  799. line-height: 32rpx;
  800. text-align: center;
  801. flex: 1;
  802. }
  803. /* Month Dates */
  804. .month-dates {
  805. display: flex;
  806. flex-wrap: wrap;
  807. padding: 0 10rpx;
  808. }
  809. .date-item {
  810. width: 14.28%;
  811. display: flex;
  812. justify-content: center;
  813. align-items: center;
  814. height: 72rpx;
  815. // border-radius: 50%;
  816. cursor: pointer;
  817. box-sizing: border-box;
  818. }
  819. .date-item.active {
  820. background: rgba(1, 107, 246, 1);
  821. }
  822. .date-item.other-month {
  823. opacity: 0.5;
  824. }
  825. .date-value {
  826. color: rgba(51, 51, 51, 1);
  827. font-family: DM Sans;
  828. font-size: 28rpx;
  829. font-weight: 400;
  830. line-height: 36rpx;
  831. text-align: center;
  832. }
  833. .date-item.active .date-value {
  834. color: #ffffff;
  835. }
  836. .date-item.other-month .date-value {
  837. color: rgba(153, 153, 153, 1);
  838. }
  839. /* Interview Records */
  840. .interview-records {
  841. background: #ffffff;
  842. border-radius: 12rpx;
  843. padding: 24rpx 0;
  844. // border: 0.5px solid rgba(227, 231, 236, 1);
  845. }
  846. .interview-record {
  847. display: flex;
  848. position: relative;
  849. border-radius: 8rpx;
  850. margin-bottom: 16rpx;
  851. }
  852. .interview-record.today {
  853. background: rgba(250, 187, 143, 1);
  854. }
  855. .interview-record:not(.today) {
  856. background: rgba(221, 221, 221, 1);
  857. }
  858. .interview-record:last-child {
  859. margin-bottom: 0;
  860. }
  861. /* Record Content */
  862. .record-content {
  863. flex: 1;
  864. display: flex;
  865. align-items: center;
  866. gap: 24rpx;
  867. }
  868. .record-left {
  869. width: 25%;
  870. display: flex;
  871. flex-direction: column;
  872. min-width: 80rpx;
  873. padding: 32rpx;
  874. }
  875. .record-divider {
  876. width: 10rpx;
  877. height: 100%;
  878. background: rgba(1, 107, 246, 1);
  879. }
  880. .record-right {
  881. flex: 1;
  882. display: flex;
  883. flex-direction: column;
  884. gap: 8rpx;
  885. }
  886. .date-label {
  887. color: rgba(106, 106, 106, 1);
  888. font-family: DM Sans;
  889. font-size: 16rpx;
  890. font-weight: 400;
  891. line-height: 40rpx;
  892. letter-spacing: 0.5%;
  893. text-align: right;
  894. }
  895. .time-label {
  896. color: rgba(106, 106, 106, 1);
  897. font-family: DM Sans;
  898. font-size: 24rpx;
  899. font-weight: 400;
  900. line-height: 32rpx;
  901. letter-spacing: 0.5%;
  902. text-align: left;
  903. }
  904. .candidate-name {
  905. color: rgba(51, 51, 51, 1);
  906. font-family: DM Sans;
  907. font-size: 32rpx;
  908. font-weight: 600;
  909. line-height: 40rpx;
  910. }
  911. .candidate-details {
  912. color: rgba(102, 102, 102, 1);
  913. font-family: DM Sans;
  914. font-size: 24rpx;
  915. font-weight: 400;
  916. line-height: 32rpx;
  917. }
  918. /* Empty State - 与jobManagement页面保持一致 */
  919. .empty-state {
  920. display: flex;
  921. align-items: center;
  922. justify-content: center;
  923. padding: 40rpx;
  924. .empty-illustration {
  925. margin-bottom: 40rpx;
  926. .empty-image {
  927. width: 700rpx;
  928. height: 800rpx;
  929. }
  930. }
  931. .empty-text {
  932. color: rgba(120, 130, 138, 1);
  933. font-family: DM Sans;
  934. font-size: 28rpx;
  935. font-weight: 400;
  936. line-height: 36rpx;
  937. letter-spacing: 0.5%;
  938. text-align: center;
  939. }
  940. }
  941. .qyList {
  942. width: 100%;
  943. height: auto;
  944. margin-top: 20rpx;
  945. .qyList-box {
  946. width: 686rpx;
  947. height: 100%;
  948. .qyList-box-item {
  949. width: 100%;
  950. // height: 400rpx;
  951. padding-bottom: 40rpx;
  952. background-color: #ffffff;
  953. border-radius: 24rpx;
  954. margin-bottom: 20rpx;
  955. .qyList-box-item-box {
  956. width: 626rpx;
  957. height: 100%;
  958. }
  959. .qyList-box-item-info {
  960. margin-top: 40rpx;
  961. }
  962. .qyList-box-item-job {
  963. color: #121212;
  964. font-size: 28rpx;
  965. font-weight: 500;
  966. margin-top: 20rpx;
  967. }
  968. .qyList-box-item-rem {
  969. color: #999999;
  970. font-size: 26rpx;
  971. margin-top: 20rpx;
  972. }
  973. }
  974. }
  975. }
  976. .txt-desc{
  977. color: rgba(153, 153, 153, 1);
  978. font-family: DM Sans;
  979. font-size: 20rpx;
  980. font-weight: 400;
  981. line-height: 34rpx;
  982. letter-spacing: 0%;
  983. flex: 1;
  984. }
  985. </style>