index.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  1. <template>
  2. <div class="index" style="padding-bottom: 40px;">
  3. <!-- 搜索 -->
  4. <el-affix @change="change" :offset="60" style="width: 100%;">
  5. <div :style="isTop==true?'background:#ffffff;box-shadow: 0 10px 8px rgba(153, 153, 153, 0.1);':''"
  6. class="search flex align-center justify-center">
  7. <div class="search-box flex align-center justify-between">
  8. <div class="search-box-l flex align-center" @click="openCityDialog">
  9. <el-image style="width: 16px; height: 18px;margin-right: 5px;"
  10. src="/images/index/addressIcon.png" fit="cover" />
  11. <el-text style="color: #00DD9A;font-size: 16px;margin-right: 10px;">{{city}}</el-text>
  12. [切换城市]
  13. </div>
  14. <div class="search-box-c flex align-center justify-between">
  15. <div class="search-box-c-l flex align-center justify-center">
  16. <el-popover :show-arrow="false" :visible="visible" placement="bottom" title="热门搜索"
  17. width="calc(55vw - 100px)">
  18. <template #reference>
  19. <el-input @focus="Myfocus" @blur="visible = false" @keyup.enter="goSearch()"
  20. v-model="keyWord" placeholder="搜索职位、公司" />
  21. </template>
  22. <div class="searchLabel flex algin-center flex-wrap">
  23. <div class="searchLabel-item" @click="selectLabel(item.keyWord)"
  24. v-for="(item,index) in searchList" :key="index">
  25. {{item.keyWord}}
  26. </div>
  27. </div>
  28. </el-popover>
  29. </div>
  30. <div @click="goSearch()" class="search-box-c-r flex align-center justify-center">
  31. <el-image style="width: 20px; height: 20px;margin-right: 8px;"
  32. src="/images/index/search.png" fit="cover" />
  33. 搜索
  34. </div>
  35. </div>
  36. <div class="search-box-r flex align-center justify-center">
  37. <el-image style="width: 20px; height: 30px;margin-right: 10px;" src="/images/index/phone.png"
  38. fit="cover" />
  39. <div class="search-box-r-c">
  40. <div class="search-box-r-c-t">
  41. 扫描二维码
  42. </div>
  43. <div class="search-box-r-c-b">
  44. 不错过每条消息
  45. </div>
  46. </div>
  47. <div class="search-box-r-rq">
  48. <div class="search-box-r-rq-img">
  49. <img :src="options" style="width: 160px;height: auto;" />
  50. </div>
  51. <div class="search-box-r-rq-txt">
  52. 微信扫描二维码
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </el-affix>
  59. <!-- 切换类型 -->
  60. <div class="tabs flex align-center justify-center">
  61. <div class="tabs-box">
  62. <div @click="selectTabs(index)" :class="tabsCurr == index?'tabs-box-item-active':''"
  63. class="tabs-box-item" v-for="(item,index) in tabs" :key="index">
  64. {{item.name}}
  65. </div>
  66. </div>
  67. </div>
  68. <!-- banner/类型 -->
  69. <div v-if="bannerType.length>0" class="typeBanner flex align-center justify-center">
  70. <div @mouseleave="mouseLeave" class="typeBanner-box flex align-center justify-center">
  71. <div class="typeBanner-box-l ">
  72. <div :class="shotypeCurr == index && isShoType ?'typeBanner-box-l-item-active':''"
  73. @mouseenter="mouseEnter(index)" class="typeBanner-box-l-item flex align-center justify-between"
  74. v-for="(item,index) in bannerType" :key="index">
  75. <div class="typeBanner-box-l-item-l flex align-center">
  76. {{item?.ruleClassifyName}}
  77. <div v-if="item.childrens.length>0" v-for="(ite,ind) in item.childrens" :key="ind">
  78. <div class="typeBanner-box-l-item-l-i" v-if="ind<3">
  79. <div>
  80. {{ite.title}}
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. <div class="typeBanner-box-l-item-r">
  86. <el-icon :size="15" color="#333333">
  87. <CaretRight />
  88. </el-icon>
  89. </div>
  90. </div>
  91. </div>
  92. <div class="typeBanner-box-r" v-if="isShoType == false">
  93. <el-carousel :interval="6000" trigger="click" style="height: 470px;" autoplay>
  94. <el-carousel-item v-for="item in bannerListuser" style="height: 470px;" :key="item">
  95. <el-image style="width: 100%; height: 470px;border-radius: 0 24px 24px 0;"
  96. :src="item.imageUrl" fit="fill" />
  97. </el-carousel-item>
  98. </el-carousel>
  99. </div>
  100. <div class="typeBanner-box-r typeBanner-box-c" v-else>
  101. <div class="typeBanner-box-c-title">
  102. {{bannerType[shotypeCurr]?.ruleClassifyName}}
  103. </div>
  104. <div class="typeBanner-box-c-item flex justify-between flex-wrap"
  105. v-for="(ite,ind) in bannerType[shotypeCurr].childrens" :key="ind">
  106. <div class="typeBanner-box-c-item-l">
  107. {{ite.title}}
  108. </div>
  109. <div v-if="ite.childrens.length>0" class="typeBanner-box-c-item-r flex align-center flex-wrap">
  110. <div @click="selectLabel(it?.ruleClassifyName)" class="typeBanner-box-c-item-r-i"
  111. v-for="(it,ins) in ite.childrens" :key="ins">
  112. {{it?.ruleClassifyName}}
  113. </div>
  114. </div>
  115. </div>
  116. </div>
  117. </div>
  118. </div>
  119. <!-- 推荐 -->
  120. <div class="tuijian flex align-center justify-center">
  121. <div class="tuijian-box flex align-center justify-between">
  122. <div>
  123. 为你推荐
  124. <div class="tuijian-box-line"></div>
  125. </div>
  126. <div v-if="jobTypeList.citys" class="tuijian-r flex align-center">
  127. <el-image style="width: 26px; height: 26px;border-radius: 50%;margin-right: 10px;" :src="avatar"
  128. fit="cover" />
  129. 根据求职期望匹配:{{jobTypeList.citys}}<el-divider
  130. direction="vertical" />{{jobTypeList?.ruleClassifyName}}<el-divider
  131. direction="vertical" />{{jobTypeList.salaryRange}}
  132. </div>
  133. </div>
  134. </div>
  135. <div class="list flex align-center justify-center">
  136. <div v-loading="loading" class="list-box flex justify-between flex-wrap">
  137. <div v-if="recommendList.length!=0" class="list-box-item" @click="goDetails(item)"
  138. v-for="(item,index) in recommendList" :key="index">
  139. <div class="list-box-item-title flex align-center justify-between">
  140. <div class="list-box-item-title-name">
  141. {{ item?.ruleClassifyName }}
  142. </div>
  143. <div class="list-box-item-title-price">
  144. {{ item.salaryRange }}
  145. </div>
  146. </div>
  147. <!-- 公司名称-公司人数 -->
  148. <div class="list-box-item-title flex align-center justify-between">
  149. <div style="margin: 10px 0;">
  150. <span class="company-name" style="margin-right: 8rpx;">{{ item.company?.companyName || item.company?.companyAllName }}</span>&nbsp;
  151. <span class="company-people" v-if="item.company">{{ item.company ?
  152. item.company.companyPeople : '0人' }}</span>
  153. </div>
  154. </div>
  155. <!-- 职位标签 -->
  156. <div class="gwList-box-item-box-label flex align-center flex-wrap">
  157. <span class="job-tag">{{ item.education }}</span>
  158. <span class="job-tag">{{ item.experience }}</span>
  159. <span class="job-tag" v-for="(ite, ind) in parseWelfareTag(item.welfareTag)" :key="ind">{{ ite
  160. }}</span>
  161. </div>
  162. <!-- 公司简介-位置 -->
  163. <div class="list-box-item-info flex align-center justify-between">
  164. <div class="gwList-box-item-box-info-l flex align-center">
  165. <img :src="item.hr && item.hr.hrImg ? item.hr.hrImg : '/default.jpg'"
  166. style="width: 40px;height: 40px;border-radius: 50%;" mode="">
  167. </img>
  168. <div class="company-info-text">
  169. {{ item.user && item.user.userName || '未知' }}·{{ item.hr &&
  170. item.hr.hrPosition || '未知' }}
  171. </div>
  172. <div v-if="item.respondTime" class="reply-time">{{ item.respondTime }}
  173. </div>
  174. </div>
  175. <div class="location-text">
  176. {{ formatDistance(item.distance) }} {{ item.county }}
  177. </div>
  178. </div>
  179. </div>
  180. <div class="list-box-item" style="height: 0;padding: 0;"></div>
  181. </div>
  182. </div>
  183. <el-empty v-if="recommendList.length==0" description="暂无推荐" />
  184. <!-- 查看更多 -->
  185. <div v-if="recommendList.length!=0" class="moreData flex align-center justify-center">
  186. <div @click="selectLabel('')" class="moreData-box flex align-center justify-center">
  187. 查看更多
  188. </div>
  189. </div>
  190. <!-- 最新招聘 -->
  191. <div class="tuijian flex align-center justify-center">
  192. <div class="tuijian-box flex align-center justify-between">
  193. <div>
  194. 最新招聘
  195. <div class="tuijian-box-line"></div>
  196. </div>
  197. </div>
  198. </div>
  199. <div class="list flex align-center justify-center">
  200. <div v-loading="loadings" class="list-box flex justify-between flex-wrap">
  201. <div v-if="recommendLists.length!=0" @click="goDetails(item)" class="list-box-item"
  202. v-for="(item,index) in recommendLists" :key="index">
  203. <div class="list-box-item-title flex align-center justify-between">
  204. <div class="list-box-item-title-name">
  205. {{ item?.ruleClassifyName }}
  206. </div>
  207. <div class="list-box-item-title-price">
  208. {{ item.salaryRange }}
  209. </div>
  210. </div>
  211. <!-- 公司名称-公司人数 -->
  212. <div class="list-box-item-title flex align-center justify-between">
  213. <div style="margin: 10px 0;">
  214. <span class="company-name" style="margin-right: 8rpx;">{{ item.company?.companyName || item.company?.companyAllName }}</span>&nbsp;
  215. <span class="company-people" v-if="item.company">{{ item.company ?
  216. item.company.companyPeople : '0人' }}</span>
  217. </div>
  218. </div>
  219. <!-- 职位标签 -->
  220. <div class="gwList-box-item-box-label flex align-center flex-wrap">
  221. <span class="job-tag">{{ item.education }}</span>
  222. <span class="job-tag">{{ item.experience }}</span>
  223. <span class="job-tag" v-for="(ite, ind) in parseWelfareTag(item.welfareTag)" :key="ind">{{ ite
  224. }}</span>
  225. </div>
  226. <!-- 公司简介-位置 -->
  227. <div class="list-box-item-info flex align-center justify-between">
  228. <div class="gwList-box-item-box-info-l flex align-center">
  229. <img :src="item.hr && item.hr.hrImg ? item.hr.hrImg : '/default.jpg'"
  230. style="width: 40px;height: 40px;border-radius: 50%;" mode="">
  231. </img>
  232. <div class="company-info-text">
  233. {{ item.user && item.user.userName || '未知' }}·{{ item.hr &&
  234. item.hr.hrPosition || '未知' }}
  235. </div>
  236. <div v-if="item.respondTime" class="reply-time">{{ item.respondTime }}
  237. </div>
  238. </div>
  239. <div class="location-text">
  240. {{ formatDistance(item.distance) }} {{ item.county }}
  241. </div>
  242. </div>
  243. </div>
  244. <div class="list-box-item" style="height: 0;padding: 0;"></div>
  245. </div>
  246. </div>
  247. <el-empty v-if="recommendLists.length==0" description="暂无推荐" />
  248. <!-- 查看更多 -->
  249. <div v-if="recommendLists.length>0" class="moreData flex align-center justify-center">
  250. <div @click="selectLabel('')" class="moreData-box flex align-center justify-center">
  251. 查看更多
  252. </div>
  253. </div>
  254. <!-- 暂无简历提示框 -->
  255. <resumeTipsComp v-if="shoModal" :show="shoModal" @close="shoModal = false" @addResume="addResume" />
  256. <!-- 切换城市 -->
  257. <el-dialog v-model="allCitys" :draggable="true" destroy-on-close align-center center>
  258. <template #header>
  259. <div class="my-header flex align-center">
  260. <div class="my-header-title" style="font-weight: bold">
  261. 城市选择
  262. </div>
  263. <div class="my-header-title flex" style="margin-left: 40px; width: 300px">
  264. <el-input v-model="search" prefix-icon="Search" size="default" placeholder="请输入城市名称"
  265. @keyup.enter="handleSearch()" class="inputClass">
  266. </el-input>
  267. <el-button @click="handleSearch" style="margin-left: 10px" type="primary">搜索</el-button>
  268. </div>
  269. </div>
  270. </template>
  271. <div class="city flex align-center justify-center">
  272. <div class="city-box">
  273. <div class="city-box-city">
  274. <div class="city-box-cityt flex align-center justify-between">
  275. 定位城市
  276. <div @click="getLocation()" class="city-box-cityt-r flex align-center">
  277. <el-icon :size="14" name="RefreshRight" />
  278. 重新定位
  279. </div>
  280. </div>
  281. <div @click="selectCity(citys)" class="city-box-citys">{{ citys }}</div>
  282. </div>
  283. <div class="city-box-list">
  284. <ul class="city-box-lists" style="overflow: auto">
  285. <li class="city-box-lists-title">热门城市</li>
  286. <li class="city-box-lists-title-cs flex align-center flex-wrap">
  287. <div @click="selectCity(item)" class="city-box-lists-title-css"
  288. v-for="(item, index) in rmCity" :key="index">
  289. {{ item }}
  290. </div>
  291. </li>
  292. <li v-for="(item, index) in cityGroupList" :key="index" class="city-box-lists-item">
  293. <div v-if="item.city.length > 0">
  294. <div class="city-box-lists-item-title">
  295. {{ item.letter }}
  296. </div>
  297. <div class="flex align-center flex-wrap">
  298. <div class="city-box-lists-item-titles flex align-center"
  299. v-for="(ite, ind) in item.city" :key="ind">
  300. <div @click="selectCity(ite)">
  301. {{ ite }}
  302. </div>
  303. </div>
  304. </div>
  305. </div>
  306. </li>
  307. <el-empty v-if="cityGroupList.length == 0" description="暂无城市" />
  308. </ul>
  309. </div>
  310. </div>
  311. </div>
  312. </el-dialog>
  313. </div>
  314. </template>
  315. <script>
  316. import cityJs from '../../publicJs/city.js'
  317. import citySelect from '../../publicJs/citySelect.js'
  318. import axios from 'axios';
  319. import jsonp from 'axios-jsonp'
  320. import VueQrcode from 'vue-qrcode'
  321. import resumeTipsComp from '../../components/resumeTipsComp/resumeTipsComp.vue'
  322. export default {
  323. components: {
  324. VueQrcode,
  325. resumeTipsComp
  326. },
  327. data() {
  328. return {
  329. visible: false, //是否显示热门搜索
  330. size: 160, //二维码大小
  331. qrColor: {
  332. 'background': '#ffffff'
  333. },
  334. options: '', //生成二维码的内容
  335. allCitys: false, //是否显示全部城市弹框
  336. keyWord: '', //搜索内容
  337. isTop: false,
  338. searchBg: 'background:#ffffff',
  339. tabsCurr: 0,
  340. tabs: [{ name: '全日制', id: 1 },{ name: '兼职', id: 0 },{ name: '校招', id: 2 }, { name: '社招', id: 3 }],
  341. bannerType: [], //岗位分类
  342. recommendList: [], //推荐岗位
  343. recommendLists: [], //最新岗位
  344. isShoType: false,
  345. shotypeCurr: 0,
  346. isResume: false, //是否有简历
  347. shoModal: false, //暂无简历提示弹窗
  348. city: '', //当前选择的城市
  349. citys: '', //定位的城市
  350. longitude: '',
  351. latitude: '',
  352. cityList: cityJs, //所有的城市
  353. //城市选择弹框相关
  354. search: '', //城市搜索关键字
  355. cityGroupList: [], //按字母分组的城市列表
  356. rmCity: [], //热门城市列表
  357. jobTypeList: {}, //求职意向第一个
  358. loading: false,
  359. loadings: false,
  360. bannerListuser: [], //用户端轮播图
  361. searchList: [], //热门搜索列表
  362. }
  363. },
  364. computed: {
  365. avatar() {
  366. return this.$store.state.avatar;
  367. },
  368. },
  369. mounted() {
  370. if (localStorage.getItem('city')) {
  371. this.city = localStorage.getItem('city')
  372. }
  373. let inviterCode = this.$route.query.inviterCode
  374. if (inviterCode) {
  375. localStorage.setItem('inviterCode', inviterCode)
  376. }
  377. //app下载地址
  378. this.getAppDown()
  379. //获取热门搜索
  380. this.getMyRecordList();
  381. //岗位分类
  382. this.getJobTypeList();
  383. //banner
  384. this.getBannerList();
  385. //所有城市的列表
  386. // this.getAllCityList();
  387. if (localStorage.getItem('token')) {
  388. //求职意向
  389. this.getJobYx();
  390. //简历详情
  391. this.getJlInfo();
  392. }
  393. },
  394. methods: {
  395. //获取app下载地址
  396. getAppDown() {
  397. this.$Request.get('/app/common/type/423').then(res => {
  398. if (res.code == 0) {
  399. this.options = res.data.value
  400. }
  401. })
  402. },
  403. //选择热门搜索并跳转
  404. selectLabel(item) {
  405. this.keyWord = item
  406. this.goSearch()
  407. },
  408. //显示热门搜索
  409. Myfocus() {
  410. if (this.searchList.length > 0) {
  411. //有热门搜索才显示
  412. this.visible = true
  413. } else {
  414. //没有热门搜索不显示
  415. this.visible = false
  416. }
  417. },
  418. //获取热门搜索
  419. getMyRecordList() {
  420. let data = {
  421. userId: localStorage.getItem('userId') ? localStorage.getItem('userId') : '1'
  422. }
  423. this.$Request.get('/app/record/getMyRecordList', {
  424. params: data
  425. }).then(res => {
  426. if (res.code == 0 && res.data) {
  427. this.searchList = res.data.records
  428. }
  429. })
  430. },
  431. //去搜索页面
  432. goSearch() {
  433. this.$router.push({
  434. name: 'search',
  435. query: {
  436. keyWord: this.keyWord
  437. }
  438. })
  439. },
  440. //获取banner
  441. getBannerList() {
  442. this.$Request.get('/app/banner/selectBannerList?classify=1').then(res => {
  443. if (res.code == 0) {
  444. this.bannerListuser = res.data
  445. } else {
  446. this.bannerListuser = [
  447. 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fphoto%2F2007-11-7%2F200711072147151187.jpg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1674883340&t=4b9cbb7796600699ac28f75cd138ba04'
  448. ]
  449. }
  450. })
  451. },
  452. //获取岗位分类
  453. getJobTypeList() {
  454. this.$Request.get('/app/rule/getClassifyList').then(res => {
  455. if (res.code == 0) {
  456. if (res.data) {
  457. this.bannerType = res.data
  458. }
  459. }
  460. })
  461. },
  462. //获取简历
  463. getJlInfo() {
  464. this.$Request.get("/app/userFirst/getUserResumes").then(res => {
  465. if (res.code == 0) {
  466. if (res.data) {
  467. this.isResume = true
  468. //缓存简历id
  469. localStorage.setItem('resumeId', res.data.resumeList.resumesId)
  470. } else {
  471. this.isResume = false
  472. }
  473. } else {
  474. this.isResume = false
  475. }
  476. })
  477. },
  478. //获取职位 type: 1、推荐 2、最新
  479. getRecommendJob(type) {
  480. let data = {}
  481. if (Number(type) === 1) {
  482. this.loading = true
  483. data = {
  484. page: 1,
  485. limit: 9,
  486. type: this.tabs[this.tabsCurr].id, //工作性质
  487. ruleClassifyName: this.jobTypeList?.ruleClassifyName, //岗位名称
  488. screen: 1, //1推荐 2最新
  489. city: this.city || '', //城市
  490. salaryRange: this.formatSalaryRange(this.jobTypeList.salaryRange), //薪资范围
  491. education: '', //学历
  492. experience: '', //经验
  493. industry:'', //行业
  494. preference: '',//this.jobTypeList.industry || '',//偏好
  495. companyPeople: '', //公司规模
  496. lng: this.longitude,
  497. lat: this.latitude,
  498. // userId: localStorage.getItem('userId') ? localStorage.getItem('userId') : ''
  499. }
  500. } else {
  501. this.loadings = true
  502. data = {
  503. page: 1,
  504. limit: 9,
  505. type: this.tabs[this.tabsCurr].id, //工作性质
  506. ruleClassifyName: '', //岗位名称
  507. screen: 2, //1推荐 2最新
  508. city: this.city || '', //城市
  509. salaryRange: '', //薪资范围
  510. education: '', //学历
  511. experience: '', //经验
  512. industry: '', //行业
  513. preference: '',//偏好
  514. companyPeople: '', //公司规模
  515. lng: this.longitude,
  516. lat: this.latitude,
  517. // userId: localStorage.getItem('userId') ? localStorage.getItem('userId') : ''
  518. }
  519. }
  520. this.$Request.get('/app/postPush/userGetPostPushList', {
  521. params: data
  522. }).then(res => {
  523. if (res.code == 0) {
  524. // recommendList
  525. res.data.records.map(item => {
  526. if (item.positionWelfare) {
  527. item.positionWelfare = item.positionWelfare.split(',')
  528. } else {
  529. item.positionWelfare = []
  530. }
  531. })
  532. if (Number(type) == 1) {
  533. this.recommendList = res.data.records
  534. this.loading = false
  535. } else {
  536. this.recommendLists = res.data.records
  537. this.loadings = false
  538. }
  539. }
  540. })
  541. },
  542. //获取求职意向
  543. getJobYx() {
  544. this.$Request.get('/app/intention/getIntentionList').then(res => {
  545. if (res.code == 0 && res.data.length > 0) {
  546. res.data.map(item => {
  547. if (item.isDefault == 1) { //拿出第一意向
  548. this.jobTypeList = item
  549. }
  550. })
  551. this.getLocation();
  552. }
  553. })
  554. },
  555. //选择城市
  556. selectCity(city) {
  557. this.city = city
  558. this.allCitys = false
  559. localStorage.setItem('city', this.city)
  560. //重新获取岗位
  561. this.getRecommendJob(1)
  562. this.getRecommendJob(2)
  563. },
  564. //打开城市选择弹框
  565. openCityDialog() {
  566. this.allCitys = true;
  567. },
  568. //打开城市选择弹框
  569. openCityDialog() {
  570. this.allCitys = true;
  571. this.search = '';
  572. //获取热门城市列表
  573. this.getRmCityList();
  574. //获取按字母分组的城市列表
  575. this.getCityGroupList();
  576. },
  577. //获取热门城市列表
  578. getRmCityList() {
  579. let data = {
  580. limitCount: 10
  581. };
  582. this.$Request
  583. .get('/app/postPush/getHotCity', { params: data })
  584. .then(res => {
  585. if (res.code == 0) {
  586. this.rmCity = res.data;
  587. }
  588. });
  589. },
  590. //获取按字母分组的城市列表
  591. getCityGroupList(keyword = '') {
  592. const grouped = {};
  593. // 过滤:如果有关键字,就按城市名模糊匹配
  594. const filtered = keyword
  595. ? cityJs.filter(item => item.label.includes(keyword))
  596. : cityJs;
  597. // 遍历城市数据
  598. filtered.forEach(item => {
  599. // 按字母分组
  600. const letterObj = citySelect.getFirstLetter(item.label);
  601. const letter = letterObj.firstletter.toUpperCase();
  602. if (!grouped[letter]) grouped[letter] = [];
  603. grouped[letter].push(item.label);
  604. });
  605. // 生成按字母分组的城市列表
  606. const sortedLetters = Object.keys(grouped).sort();
  607. this.cityGroupList = sortedLetters.map(letter => ({
  608. letter,
  609. city: grouped[letter]
  610. }));
  611. },
  612. //搜索城市
  613. handleSearch() {
  614. this.getCityGroupList(this.search.trim());
  615. },
  616. //使用jsonp请求从腾讯地图获取经纬度
  617. getLocation() {
  618. let data = {
  619. key: "ZBABZ-ZWECU-UQTVV-4LYDR-COK3F-5SF75", //申请的密钥
  620. output: "jsonp",
  621. };
  622. let url = "https://apis.map.qq.com/ws/location/v1/ip"
  623. axios.get(url, {
  624. params: data,
  625. adapter: jsonp
  626. }).then(res => {
  627. this.longitude = res.data.result.location.lng
  628. this.latitude = res.data.result.location.lat
  629. this.citys = res.data.result.ad_info.city
  630. if (!this.city) {
  631. this.city = this.citys
  632. }
  633. this.getRecommendJob(1)
  634. this.getRecommendJob(2)
  635. localStorage.setItem('city', this.city)
  636. }).catch(err => {
  637. console.log(err)
  638. })
  639. },
  640. //去添加简历
  641. addResume() {
  642. this.shoModal = false
  643. this.$router.push({
  644. name: 'addResume'
  645. })
  646. },
  647. /**
  648. * @param {Object} item 详情参数
  649. * 去详情
  650. */
  651. goDetails(item) {
  652. if (localStorage.getItem('token')) {
  653. if (this.isResume) { //有简历
  654. this.$router.push({
  655. name: 'postInfo',
  656. query: {
  657. postPushId: item.postPushId
  658. }
  659. })
  660. } else { //无简历
  661. this.shoModal = true
  662. }
  663. } else {
  664. this.$router.push({
  665. name: 'login'
  666. })
  667. }
  668. },
  669. //鼠标移入事件
  670. mouseEnter(index) {
  671. this.shotypeCurr = index;
  672. this.isShoType = true
  673. },
  674. //鼠标移出事件
  675. mouseLeave() {
  676. this.shotypeCurr = 0;
  677. this.isShoType = false
  678. },
  679. /**
  680. * @param {Number} index 选择的索引
  681. * 切换类型
  682. */
  683. selectTabs(index) {
  684. this.tabsCurr = index
  685. //重新获取岗位
  686. this.getRecommendJob(1)
  687. this.getRecommendJob(2)
  688. },
  689. /**
  690. * @param {Boolean} e
  691. * 是否触顶
  692. */
  693. change(e) {
  694. this.isTop = e
  695. },
  696. formatSalaryRange(range) {
  697. if (!range || !range.includes('-')) return range
  698. const [min, max] = range.split('-').map(v => parseInt(v.trim()))
  699. if (isNaN(min) || isNaN(max)) return range
  700. // 除以1000并去掉小数点后多余的0
  701. const formatNum = num => {
  702. const val = num / 1000
  703. return val % 1 === 0 ? val.toFixed(0) + 'k' : val.toFixed(1) + 'k'
  704. }
  705. return `${formatNum(min)}-${formatNum(max)}`
  706. },
  707. parseWelfareTag(tagStr) {
  708. return tagStr ? tagStr.split(';').filter(Boolean) : []
  709. },
  710. formatDistance(distance) {
  711. if (distance == null || distance === '') return ''
  712. const num = parseFloat(distance)
  713. if (isNaN(num)) return ''
  714. // 小于1000显示米,否则显示千米
  715. if (num < 1000) {
  716. return `${num}m`
  717. } else {
  718. const km = num / 1000
  719. // 去掉多余的小数(保留一位小数)
  720. const formatted = km % 1 === 0 ? km.toFixed(0) : km.toFixed(1)
  721. return `${formatted}km`
  722. }
  723. },
  724. },
  725. }
  726. </script>
  727. <style lang="scss" scoped>
  728. $marginTop-60: 120px;
  729. :deep(.el-affix--fixed){
  730. width: 100% !important;
  731. right: 0;
  732. left: 0;
  733. }
  734. .searchLabel {
  735. width: 100%;
  736. .searchLabel-item {
  737. cursor: pointer;
  738. margin-right: 10px;
  739. margin-top: 10px;
  740. }
  741. .searchLabel-item:hover {
  742. color: #00DD9A;
  743. }
  744. }
  745. :deep(.el-input__wrapper) {
  746. box-shadow: none;
  747. border: none;
  748. }
  749. .my-header {
  750. padding: 10px 10px 0 10px;
  751. }
  752. :deep(.el-dialog) {
  753. border-radius: 14px !important;
  754. padding: 0;
  755. }
  756. :deep(.el-dialog__body) {
  757. padding-top: 10px !important;
  758. }
  759. :deep(.el-dialog__header) {
  760. background: linear-gradient(45deg, #f2fffa, #FFFFFF);
  761. border-radius: 14px 14px 0 0;
  762. }
  763. .citys {
  764. width: calc(100% - 20px);
  765. height: 300px;
  766. overflow: hidden;
  767. overflow-y: scroll;
  768. padding: 0 10px 10px 10px;
  769. }
  770. .citys-item {
  771. display: flex;
  772. flex-wrap: wrap;
  773. .citys-item-citys {
  774. background-color: #F2F2F7;
  775. width: fit-content;
  776. padding: 4px 10px;
  777. cursor: pointer;
  778. border-radius: 4px;
  779. margin-top: 20px;
  780. margin-right: 20px;
  781. }
  782. .citys-item-citys:hover {
  783. background-color: #00DD9A;
  784. color: #FFFFFF;
  785. }
  786. }
  787. .citys-top {
  788. width: 100%;
  789. .citys-top-cityt {
  790. font-weight: bold;
  791. color: #333333;
  792. }
  793. .citys-top-cityt-r {
  794. font-weight: 500;
  795. color: #999999;
  796. font-size: 12px;
  797. cursor: pointer;
  798. }
  799. .citys-top-citys {
  800. background-color: #F2F2F7;
  801. width: fit-content;
  802. padding: 4px 10px;
  803. margin-top: 10px;
  804. cursor: pointer;
  805. border-radius: 4px;
  806. margin-right: 20px;
  807. margin-bottom: 20px;
  808. }
  809. .citys-top-citys:hover {
  810. background-color: #00DD9A;
  811. color: #FFFFFF;
  812. }
  813. }
  814. .search {
  815. width: 100%;
  816. height: 110px;
  817. background-color: #F5F5F5;
  818. .search-box {
  819. width: calc(1800px - $marginTop-60 * 2);
  820. height: 50px;
  821. .search-box-l {
  822. font-size: 16px;
  823. color: #333333;
  824. cursor: pointer;
  825. flex-shrink: 0;
  826. }
  827. .search-box-c {
  828. margin:0 30px;
  829. flex: 1;
  830. // width: 70vw;
  831. height: 100%;
  832. background-color: #00DD9A;
  833. border-radius: 12px;
  834. }
  835. .search-box-c-l {
  836. width: calc(100% - 100px);
  837. height: calc(100% - 2px);
  838. background-color: #ffffff;
  839. border-radius: 12px;
  840. border: 1px solid #00DD9A;
  841. }
  842. .search-box-c-r {
  843. width: 100px;
  844. height: 100%;
  845. color: #ffffff;
  846. font-size: 16px;
  847. cursor: pointer;
  848. }
  849. .search-box-r {
  850. width: 200px;
  851. height: 100%;
  852. background-color: #ffffff;
  853. border-radius: 12px;
  854. cursor: pointer;
  855. position: relative;
  856. }
  857. .search-box-r:hover {
  858. .search-box-r-rq {
  859. display: inline-block;
  860. }
  861. }
  862. .search-box-r-rq {
  863. display: none;
  864. position: absolute;
  865. width: 200px;
  866. // height: 280px;
  867. background-color: #ffffff;
  868. border-radius: 8px;
  869. border: 1px solid #F0F0F0;
  870. top: 55px;
  871. right: 0px;
  872. z-index: 999;
  873. align-content: center;
  874. padding: 20px 0;
  875. .search-box-r-rq-img {
  876. width: 160px;
  877. height: 160px;
  878. margin-left: 20px;
  879. }
  880. img {
  881. width: 100%;
  882. height: 100%;
  883. }
  884. .search-box-r-rq-txt {
  885. width: 100%;
  886. text-align: center;
  887. color: #00DD9A;
  888. font-size: 16px;
  889. margin-top: 20px;
  890. }
  891. }
  892. .search-box-r-c-t {
  893. color: #333333;
  894. font-size: 16px;
  895. font-weight: 400;
  896. }
  897. .search-box-r-c-b {
  898. color: #999999;
  899. font-size: 14px;
  900. font-weight: 400;
  901. }
  902. }
  903. }
  904. .tabs {
  905. width: 100%;
  906. height: 40px;
  907. .tabs-box {
  908. width: calc(100% - $marginTop-60 * 2);
  909. height: 100%;
  910. overflow-x: auto;
  911. white-space: nowrap;
  912. position: relative;
  913. }
  914. .tabs-box::-webkit-scrollbar {
  915. /* Chrome, Safari, Opera */
  916. height: 0px !important;
  917. }
  918. .tabs-box::-webkit-scrollbar-thumb {
  919. background-color: #cccccc;
  920. /* 滚动条颜色 */
  921. }
  922. .tabs-box::-webkit-scrollbar-track {
  923. background-color: #ffffff;
  924. /* 轨道颜色 */
  925. }
  926. .tabs-box-item {
  927. display: inline-block;
  928. min-width: 80px;
  929. padding: 0 5px;
  930. height: 100%;
  931. text-align: center;
  932. line-height: 40px;
  933. font-size: 16px;
  934. color: #333333;
  935. font-weight: 400;
  936. margin-right: 10px;
  937. border-radius: 6px;
  938. cursor: pointer;
  939. position: relative;
  940. z-index: 1;
  941. }
  942. .tabs-box-item:hover {
  943. color: #06E1AB;
  944. }
  945. .tabs-box-item-active {
  946. color: #FFFFFF !important;
  947. background-color: #06E1AB !important;
  948. transition: background-color color 0.5s; // 添加过渡效果
  949. }
  950. }
  951. .typeBanner {
  952. width: 100%;
  953. height: auto;
  954. margin-top: 50px;
  955. .typeBanner-box {
  956. width: calc(100% - $marginTop-60 * 2);
  957. height: 450px;
  958. background-color: #ffffff;
  959. border-radius: 24px;
  960. }
  961. .typeBanner-box-l {
  962. width: 550px;
  963. height: 100%;
  964. background-color: #ffffff;
  965. border-radius: 24px 0 0 24px;
  966. align-content: space-around;
  967. padding: 10px 0;
  968. overflow: hidden;
  969. overflow-y: scroll;
  970. }
  971. .typeBanner-box-r {
  972. width: calc(100% - 550px);
  973. height: calc(100% + 20px);
  974. background-color: #ffffff;
  975. border-radius: 0 24px 24px 0;
  976. }
  977. .typeBanner-box-c::-webkit-scrollbar {
  978. /* Chrome, Safari, Opera */
  979. width: 0px;
  980. }
  981. .typeBanner-box-c::-webkit-scrollbar-thumb {
  982. background-color: #cccccc;
  983. /* 滚动条颜色 */
  984. }
  985. .typeBanner-box-c::-webkit-scrollbar-track {
  986. background-color: #ffffff;
  987. /* 轨道颜色 */
  988. }
  989. .typeBanner-box-c {
  990. // padding: 20px;
  991. overflow: hidden;
  992. overflow-y: scroll;
  993. .typeBanner-box-c-title {
  994. font-size: 16px;
  995. padding: 20px;
  996. }
  997. .typeBanner-box-c-item {
  998. padding: 0 20px;
  999. margin-bottom: 10px;
  1000. }
  1001. .typeBanner-box-c-item-l {
  1002. font-size: 14px;
  1003. color: #666666;
  1004. }
  1005. .typeBanner-box-c-item-r {
  1006. width: 80%;
  1007. border-bottom: 1px solid #F5F5F5;
  1008. }
  1009. .typeBanner-box-c-item-r-i:hover {
  1010. color: #00DD9A;
  1011. cursor: pointer;
  1012. }
  1013. .typeBanner-box-c-item-r-i {
  1014. margin-right: 20px;
  1015. margin-bottom: 20px;
  1016. }
  1017. }
  1018. .typeBanner-box-l-item-active {
  1019. box-shadow: 0 0 10px 0 rgba(153, 153, 153, 0.3);
  1020. .typeBanner-box-l-item-r {
  1021. .el-icon {
  1022. color: #00DD9A;
  1023. }
  1024. }
  1025. }
  1026. .typeBanner-box-l-item-l-i:hover {
  1027. color: #00DD9A;
  1028. }
  1029. .typeBanner-box-l-item-l {
  1030. width: 100%;
  1031. padding-left: 20px;
  1032. font-size: 16px;
  1033. overflow: hidden;
  1034. white-space: nowrap;
  1035. text-overflow: ellipsis;
  1036. -o-text-overflow: ellipsis;
  1037. }
  1038. .typeBanner-box-l-item-l-i {
  1039. font-size: 14px;
  1040. margin-left: 20px;
  1041. color: #666666;
  1042. }
  1043. .typeBanner-box-l-item-r {
  1044. padding-right: 20px;
  1045. }
  1046. .typeBanner-box-l-item {
  1047. width: calc(100% - 10px);
  1048. height: calc(100% / 7);
  1049. border-radius: 14px;
  1050. cursor: pointer;
  1051. }
  1052. }
  1053. .tuijian {
  1054. width: 100%;
  1055. margin-top: 65px;
  1056. .tuijian-box {
  1057. width: calc(100% - $marginTop-60 * 2);
  1058. color: #333333;
  1059. font-size: 18px;
  1060. }
  1061. .tuijian-box-line {
  1062. width: 24px;
  1063. height: 2px;
  1064. background-color: #00DD9A;
  1065. margin-top: 4px;
  1066. position: relative;
  1067. top: 50%;
  1068. left: 50%;
  1069. transform: translate(-50%, -50%);
  1070. }
  1071. .tuijian-r {
  1072. font-size: 14px;
  1073. color: #666666;
  1074. }
  1075. }
  1076. .list {
  1077. width: 100%;
  1078. min-height: 100px;
  1079. margin-top: 20px;
  1080. .list-box {
  1081. width: calc(100% - $marginTop-60 * 2);
  1082. // height: 100%;
  1083. min-height: 100px;
  1084. border-radius: 10px;
  1085. }
  1086. .list-box-item:hover {
  1087. box-shadow: 0 10px 10px 0 rgba(153, 153, 153, 0.3);
  1088. .list-box-item-title-name {
  1089. color: #00DD9A;
  1090. }
  1091. }
  1092. .list-box-item {
  1093. width: calc((100% - 40px) / 3);
  1094. height: 100%;
  1095. background-color: #ffffff;
  1096. border-radius: 10px;
  1097. padding: 20px 0;
  1098. cursor: pointer;
  1099. margin-bottom: 20px;
  1100. }
  1101. .list-box-item-title {
  1102. font-size: 16px;
  1103. padding: 0 20px;
  1104. .list-box-item-title-name {
  1105. color: #333333;
  1106. }
  1107. .list-box-item-title-price {
  1108. font-size: 18px;
  1109. color: #FF0000;
  1110. }
  1111. }
  1112. .list-box-item-label {
  1113. width: calc(100% - 40px);
  1114. height: 40px;
  1115. padding: 0 20px;
  1116. overflow: hidden;
  1117. .list-box-item-label-item {
  1118. padding: 4px 10px;
  1119. border-radius: 5px;
  1120. background-color: #F5F5F5;
  1121. color: #666666;
  1122. font-size: 14px;
  1123. margin-right: 10px;
  1124. margin-top: 10px;
  1125. }
  1126. }
  1127. .list-box-item-info {
  1128. margin-top: 20px;
  1129. border-top: 1px solid #F5F5F5;
  1130. padding: 0 20px;
  1131. padding-top: 20px;
  1132. .list-box-item-info-name:hover {
  1133. color: #00DD9A;
  1134. }
  1135. .list-box-item-info-name {
  1136. font-size: 16px;
  1137. color: #333333;
  1138. }
  1139. .list-box-item-info-price {
  1140. font-size: 16px;
  1141. color: #999999;
  1142. }
  1143. }
  1144. }
  1145. .moreData {
  1146. width: 100%;
  1147. height: auto;
  1148. margin-top: 10px;
  1149. .moreData-box:hover {
  1150. background-color: #00DD9A;
  1151. color: #ffffff;
  1152. }
  1153. .moreData-box {
  1154. width: 180px;
  1155. height: 40px;
  1156. border-radius: 35px;
  1157. background-color: rgba(0, 221, 154, 0.1);
  1158. color: #00DD9A;
  1159. font-size: 14px;
  1160. cursor: pointer;
  1161. transition: background-color 0.5s;
  1162. }
  1163. }
  1164. .showModal-img {
  1165. width: 100%;
  1166. height: 300px;
  1167. img {
  1168. width: 400px;
  1169. height: 300px;
  1170. }
  1171. }
  1172. .city {
  1173. width: 100%;
  1174. height: 500px;
  1175. .city-box {
  1176. width: 100%;
  1177. padding: 0 20px;
  1178. height: 100%;
  1179. }
  1180. .city-box-city {
  1181. .city-box-cityt {
  1182. width: 100%;
  1183. font-weight: bold;
  1184. .city-box-cityt-r {
  1185. font-weight: 500;
  1186. color: #999999;
  1187. font-size: 12px;
  1188. cursor: pointer;
  1189. }
  1190. }
  1191. .city-box-citys {
  1192. background-color: #F2F2F7;
  1193. width: fit-content;
  1194. padding: 4px 10px;
  1195. margin-top: 10px;
  1196. cursor: pointer;
  1197. border-radius: 4px;
  1198. }
  1199. .city-box-citys:hover {
  1200. background-color: #00DD9A;
  1201. color: #FFFFFF;
  1202. }
  1203. }
  1204. .city-box-list {
  1205. width: 100%;
  1206. height: 420px;
  1207. margin-top: 20px;
  1208. overflow-y: scroll;
  1209. }
  1210. .city-box-lists {
  1211. width: 100%;
  1212. height: 100%;
  1213. list-style: none;
  1214. padding: 0;
  1215. margin: 0;
  1216. }
  1217. .city-box-lists-title {
  1218. font-weight: bold;
  1219. }
  1220. .city-box-lists-title-css {
  1221. background-color: #F2F2F7;
  1222. width: fit-content;
  1223. padding: 4px 10px;
  1224. margin-top: 10px;
  1225. cursor: pointer;
  1226. border-radius: 4px;
  1227. margin-right: 20px;
  1228. margin-bottom: 20px;
  1229. }
  1230. .city-box-lists-title-css:hover {
  1231. background-color: #00DD9A;
  1232. color: #FFFFFF;
  1233. }
  1234. .city-box-lists-item-title {
  1235. font-weight: bold;
  1236. }
  1237. .city-box-lists-item-titles {
  1238. background-color: #F2F2F7;
  1239. width: fit-content;
  1240. padding: 4px 10px;
  1241. margin-top: 10px;
  1242. cursor: pointer;
  1243. border-radius: 4px;
  1244. margin-right: 20px;
  1245. margin-bottom: 20px;
  1246. }
  1247. .city-box-lists-item-titles:hover {
  1248. background-color: #00DD9A;
  1249. color: #FFFFFF;
  1250. }
  1251. }
  1252. .company-name,.company-people{
  1253. font-size: 14px;
  1254. font-weight: 400;
  1255. color: rgba(156, 164, 171, 1);
  1256. }
  1257. .gwList-box-item-box-label{
  1258. padding: 0 20px;
  1259. gap: 12px;
  1260. .job-tag{
  1261. padding: 4px;
  1262. background: rgba(198, 198, 198, 0.1);
  1263. border-radius: 4px;
  1264. font-size: 12px;
  1265. font-weight: 400;
  1266. color: rgba(153, 153, 153, 1);
  1267. }
  1268. }
  1269. .gwList-box-item-box-info-l{
  1270. .company-info-text{
  1271. margin: 0 10px;
  1272. color: rgba(156, 164, 171, 1);
  1273. font-size: 12px;
  1274. font-weight: 400;
  1275. }
  1276. .reply-time{
  1277. border-radius: 4px;
  1278. background: rgba(236, 225, 253, 1);
  1279. padding: 4px;
  1280. color: rgba(106.94, 84.63, 214.02, 0.96);
  1281. font-size: 12px;
  1282. font-weight: 400;
  1283. }
  1284. }
  1285. .location-text{
  1286. color: rgba(156, 164, 171, 1);
  1287. font-size: 12px;
  1288. font-weight: 400;
  1289. }
  1290. </style>