communicationRecords.vue 29 KB

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