特易招,招聘小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

522 lines
12 KiB

10 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
8 months ago
10 months ago
2 months ago
2 months ago
10 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
2 months ago
10 months ago
8 months ago
2 months ago
10 months ago
2 months ago
2 months ago
10 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
8 months ago
10 months ago
8 months ago
2 months ago
10 months ago
8 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
10 months ago
8 months ago
10 months ago
8 months ago
8 months ago
2 months ago
10 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
10 months ago
8 months ago
8 months ago
2 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
2 months ago
8 months ago
8 months ago
8 months ago
2 months ago
2 months ago
2 months ago
2 months ago
8 months ago
10 months ago
2 months ago
10 months ago
2 months ago
2 months ago
10 months ago
8 months ago
8 months ago
8 months ago
10 months ago
  1. <template>
  2. <view class="page">
  3. <navbar title="在线简历"
  4. leftClick
  5. @leftClick="$utils.navigateBack"/>
  6. <view class="box">
  7. <view class="list">
  8. <view class="item"
  9. v-for="(item, index) in list"
  10. :key="index">
  11. <view class="title">
  12. {{ item.title }}
  13. </view>
  14. <!-- 工种选择器模式 -->
  15. <view class="job-type-selector" v-if="item.useJobTypePicker" @click="openJobTypePicker">
  16. <view class="selected-job-type">
  17. {{ selectedJobType || form.typeId_dictText || '请选择工种' }}
  18. </view>
  19. <uv-icon name="arrow-right" size="30rpx"></uv-icon>
  20. </view>
  21. <view class="tagList" v-else-if="!item.useAddressPicker">
  22. <view :class="{act : i == item.index}"
  23. @click="clickTag(item, i)" v-for="(t, i) in item.tag"
  24. :key="t.id">
  25. {{ t.name || t.adress }}
  26. </view>
  27. </view>
  28. <!-- 地址选择器模式 -->
  29. <view class="address-selector" v-else @click="openAddressPicker">
  30. <view class="selected-address">
  31. {{ selectedAddress || form.expectAddress_dictText || '请选择工作地区' }}
  32. </view>
  33. <uv-icon name="arrow-right" size="30rpx"></uv-icon>
  34. </view>
  35. </view>
  36. </view>
  37. <view class="form-sheet-cell">
  38. <view class="label">
  39. 求职岗位
  40. </view>
  41. <input placeholder="请输入求职岗位"
  42. v-model="form.title" />
  43. </view>
  44. <view class="form-sheet-cell">
  45. <view class="label">
  46. 您的年龄
  47. </view>
  48. <input placeholder="请输入年龄"
  49. type="number"
  50. v-model="form.age" />
  51. </view>
  52. <view class="form-sheet-cell">
  53. <view class="label">
  54. 您的性别
  55. </view>
  56. <uv-radio-group v-model="form.sex">
  57. <view style="display: flex;justify-content: center;">
  58. <uv-radio
  59. :customStyle="{margin: '8px'}"
  60. v-for="(item, index) in sexList"
  61. :key="index"
  62. iconSize="30rpx"
  63. size="40rpx"
  64. labelSize="26rpx"
  65. :label="item.name"
  66. :name="item.name">
  67. </uv-radio>
  68. </view>
  69. </uv-radio-group>
  70. </view>
  71. <view class="form-sheet-cell">
  72. <view class="label">
  73. 您的民族
  74. </view>
  75. <input placeholder="请输入民族"
  76. v-model="form.nation" />
  77. </view>
  78. <view class="form-sheet-cell">
  79. <view class="label">
  80. 期望薪资
  81. </view>
  82. <view class="price">
  83. <input placeholder="下限" v-model="form.salaryLow" />
  84. ~
  85. <input placeholder="上限" v-model="form.salaryUp" />
  86. </view>
  87. </view>
  88. <view class="form-sheet-cell"
  89. @click="openPicker('qualification')">
  90. <view class="label">
  91. 您的学历
  92. </view>
  93. <input placeholder="请选择学历"
  94. disabled
  95. v-model="form.qualification" />
  96. </view>
  97. <!-- <view class="form-sheet-cell">
  98. <view class="label">
  99. 您的学历
  100. </view>
  101. <input placeholder="请输入您的学历"
  102. v-model="form.qualification" />
  103. </view> -->
  104. <uv-textarea
  105. v-model="form.brief"
  106. count
  107. :maxlength="300"
  108. autoHeight
  109. placeholder="请输入个人介绍"></uv-textarea>
  110. <view class="uni-color-btn"
  111. @click="submit">
  112. 发布
  113. </view>
  114. </view>
  115. <uv-picker ref="picker"
  116. :columns="columns"
  117. @confirm="pickerConfirm"></uv-picker>
  118. <!-- 地址选择组件 -->
  119. <AddressPicker ref="addressPicker" :multiple="true" :showSelectWholeCity="true" :onlyCity="false" @confirm="onAddressConfirm" />
  120. <!-- 工种选择组件 -->
  121. <JobTypePicker ref="jobTypePicker" @confirm="onJobTypeConfirm" />
  122. </view>
  123. </template>
  124. <script>
  125. import { mapState } from 'vuex'
  126. import AddressPicker from '@/components/AddressPicker.vue'
  127. import JobTypePicker from '@/components/JobTypePicker.vue'
  128. export default {
  129. components: {
  130. AddressPicker,
  131. JobTypePicker
  132. },
  133. data() {
  134. return {
  135. list: [
  136. {
  137. title: '您希望从事的工种',
  138. tag: [],
  139. index: 0,
  140. type : 'typeId',
  141. useJobTypePicker: true, // 标记使用工种选择器
  142. },
  143. {
  144. title: '您希望从事工作的地区',
  145. tag: [],
  146. index: 0,
  147. type : 'expectAddress',
  148. useAddressPicker: true, // 标记使用地址选择器
  149. },
  150. {
  151. title: '您希望从事工作的性质',
  152. tag: [],
  153. index: 0,
  154. type : 'natureId',
  155. },
  156. ],
  157. form : {
  158. sex : '男',
  159. qulification : '',
  160. title: '',
  161. typeId : '',
  162. expectAddress : '',
  163. natureId : '',
  164. age : '',
  165. nation : '',
  166. salaryLow : '',
  167. salaryUp : '',
  168. qualification : '',
  169. brief: '',
  170. },
  171. sexList : [
  172. {
  173. name : '男',
  174. },
  175. {
  176. name : '女',
  177. },
  178. ],
  179. picker : {
  180. qualification : [
  181. '初中',
  182. '高中',
  183. '专科',
  184. '本科',
  185. '研究生',
  186. '博士',
  187. ],
  188. },
  189. pickerKey : 'workAge',
  190. selectedAddress: '', // 选中的地址文本
  191. selectedJobType: '', // 选中的工种文本
  192. }
  193. },
  194. computed : {
  195. ...mapState(['natureList', 'jobTypeList', 'addressList']),
  196. columns(){
  197. return [this.picker[this.pickerKey]]
  198. },
  199. },
  200. onLoad() {
  201. this.list[0].tag = this.jobTypeList
  202. this.list[1].tag = this.addressList
  203. this.list[2].tag = this.natureList
  204. this.queryResumeByUserId()
  205. },
  206. methods: {
  207. clickTag(item, index){
  208. item.index = index
  209. },
  210. openPicker(key, picker){
  211. this.pickerKey = key
  212. if(picker){
  213. picker.open()
  214. }else{
  215. this.$refs.picker.open()
  216. }
  217. },
  218. pickerConfirm(e){
  219. console.log(e);
  220. let data = e.value[0]
  221. if(data && data.id){
  222. this.form[this.pickerKey] = data.id
  223. this.form[this.pickerKey + '_dictText'] = data.name || data.adress
  224. }else{
  225. this.form[this.pickerKey] = data
  226. }
  227. },
  228. // 提交
  229. submit(){
  230. // if(this.fileList.length == 0){
  231. // return uni.showToast({
  232. // title: '请上传图片',
  233. // icon : 'none'
  234. // })
  235. // }
  236. this.list.forEach(n => {
  237. // 如果使用地址选择器或工种选择器,跳过从tag获取值
  238. if(!n.useAddressPicker && !n.useJobTypePicker) {
  239. this.form[n.type] = n.tag[n.index].id
  240. }
  241. })
  242. if (this.$utils.verificationAll(this.form, {
  243. title: '请输入求职岗位',
  244. typeId : '请选择工种',
  245. expectAddress : '请选择工作的地区',
  246. natureId : '请选择工作的性质',
  247. age : '请输入您的年龄',
  248. sex : '请选择性别',
  249. nation : '请输入您的民族',
  250. salaryLow : '请输入期望薪资下限',
  251. salaryUp : '请输入期望薪资上限',
  252. qualification : '请选择您的学历',
  253. brief: '请输入个人介绍',
  254. })) {
  255. return
  256. }
  257. let data = {
  258. title: this.form.title,
  259. typeId : this.form.typeId,
  260. expectAddress : this.form.expectAddress,
  261. natureId : this.form.natureId,
  262. age : this.form.age,
  263. nation : this.form.nation,
  264. salaryLow : this.form.salaryLow,
  265. salaryUp : this.form.salaryUp,
  266. qualification : this.form.qualification,
  267. brief: this.form.brief,
  268. sex: this.form.sex,
  269. }
  270. if(this.form.id){
  271. data.id = this.form.id
  272. }
  273. this.$api('addResume', data, res => {
  274. if(res.code == 200){
  275. uni.showToast({
  276. title: '保存成功!',
  277. icon: 'none'
  278. })
  279. setTimeout(uni.navigateBack, 1000, -1)
  280. }
  281. })
  282. },
  283. queryResumeByUserId(){
  284. this.$api('queryResumeByUserId', res => {
  285. if(res.code == 200 && res.result && res.result.records[0]){
  286. this.form = res.result.records[0]
  287. this.list.forEach((n, i) => {
  288. // 如果是地址选择器,需要根据ID找到对应的地址文本
  289. if(n.useAddressPicker && this.form[n.type]) {
  290. // 回显地址:根据存储的ID找到对应的地址文本
  291. this.selectedAddress = this.getAddressTextById(this.form[n.type])
  292. } else if(n.useJobTypePicker && this.form[n.type]) {
  293. // 回显工种:根据存储的ID找到对应的工种文本
  294. this.selectedJobType = this.getJobTypeTextById(this.form[n.type])
  295. } else {
  296. n.tag.forEach((e, index) => {
  297. if(this.form[n.type] == e.id){
  298. n.index = index
  299. }
  300. })
  301. }
  302. })
  303. }
  304. })
  305. },
  306. // 打开地址选择器
  307. openAddressPicker() {
  308. this.$refs.addressPicker.open()
  309. },
  310. // 根据ID获取地址文本(用于回显)
  311. getAddressTextById(idOrIds) {
  312. if (!idOrIds) return ''
  313. // 如果是多个ID(逗号分隔)
  314. if (typeof idOrIds === 'string' && idOrIds.includes(',')) {
  315. const ids = idOrIds.split(',')
  316. const addressTexts = []
  317. ids.forEach(id => {
  318. const address = this.findAddressById(id.trim())
  319. if (address) {
  320. addressTexts.push(address.adress)
  321. }
  322. })
  323. return addressTexts.join(',')
  324. } else {
  325. // 单个ID
  326. const address = this.findAddressById(idOrIds)
  327. return address ? address.adress : ''
  328. }
  329. },
  330. // 递归查找地址
  331. findAddressById(id) {
  332. // 在省级地址中查找
  333. for (let province of this.addressList) {
  334. if (province.id == id) {
  335. return province
  336. }
  337. }
  338. // 如果没找到,需要异步获取下级地址进行查找
  339. // 这里简化处理,实际项目中可能需要更复杂的缓存机制
  340. return null
  341. },
  342. // 地址选择确认回调
  343. onAddressConfirm(addressResult) {
  344. // 显示地址文本给用户看
  345. this.selectedAddress = addressResult.fullAddress
  346. // 传给后端的是ID或ID数组
  347. if (addressResult.selectedIds && addressResult.selectedIds.length > 0) {
  348. // 多选模式,传ID数组的字符串形式
  349. this.form.expectAddress = addressResult.selectedIds.join(',')
  350. } else {
  351. // 单选模式,传单个ID
  352. this.form.expectAddress = addressResult.selectedId
  353. }
  354. },
  355. // 打开工种选择器
  356. openJobTypePicker() {
  357. this.$refs.jobTypePicker.open()
  358. },
  359. // 工种选择确认回调
  360. onJobTypeConfirm(jobTypeResult) {
  361. // 显示工种文本给用户看
  362. this.selectedJobType = jobTypeResult.selectedJobType.name
  363. // 传给后端的是ID
  364. this.form.typeId = jobTypeResult.selectedId
  365. this.form.typeId_dictText = jobTypeResult.selectedJobType.name
  366. },
  367. // 根据ID获取工种文本(用于回显)
  368. getJobTypeTextById(id) {
  369. if (!id) return ''
  370. // 在一级工种中查找
  371. for (let jobType of this.jobTypeList) {
  372. if (jobType.id == id) {
  373. return jobType.name
  374. }
  375. }
  376. // 如果没找到,返回空字符串
  377. // 实际项目中可能需要异步获取下级工种进行查找
  378. return ''
  379. },
  380. },
  381. }
  382. </script>
  383. <style scoped lang="scss">
  384. .page{
  385. background-color: #fff;
  386. min-height: 100vh;
  387. .box{
  388. padding: 30rpx;
  389. .list {
  390. .item {
  391. margin-top: 20rpx;
  392. .title {
  393. font-weight: 900;
  394. font-size: 30rpx;
  395. }
  396. .tagList {
  397. display: flex;
  398. flex-wrap: wrap;
  399. padding: 10rpx 0;
  400. view {
  401. background: rgba($uni-color, 0.1);
  402. padding: 10rpx 20rpx;
  403. margin: 10rpx;
  404. border-radius: 10rpx;
  405. font-size: 26rpx;
  406. }
  407. .act {
  408. color: #fff;
  409. background: $uni-color;
  410. }
  411. }
  412. .address-selector {
  413. display: flex;
  414. justify-content: space-between;
  415. align-items: center;
  416. background: rgba($uni-color, 0.1);
  417. padding: 20rpx;
  418. margin: 10rpx;
  419. border-radius: 10rpx;
  420. font-size: 26rpx;
  421. .selected-address {
  422. flex: 1;
  423. color: #333;
  424. }
  425. }
  426. .job-type-selector {
  427. display: flex;
  428. justify-content: space-between;
  429. align-items: center;
  430. background: rgba($uni-color, 0.1);
  431. padding: 20rpx;
  432. margin: 10rpx;
  433. border-radius: 10rpx;
  434. font-size: 26rpx;
  435. .selected-job-type {
  436. flex: 1;
  437. color: #333;
  438. }
  439. }
  440. }
  441. }
  442. .form-sheet-cell{
  443. display: flex;
  444. background-color: #fff;
  445. padding: 20rpx;
  446. align-items: center;
  447. .label{
  448. width: 160rpx;
  449. font-weight: 900;
  450. }
  451. .price{
  452. display: flex;
  453. text-align: center;
  454. input{
  455. width: 150rpx;
  456. border: 1px solid $uni-color;
  457. margin: 0 10rpx;
  458. }
  459. }
  460. input{
  461. flex: 1;
  462. background-color: rgba($uni-color, 0.1);
  463. padding: 10rpx 20rpx;
  464. border-radius: 10rpx;
  465. }
  466. .right-icon{
  467. margin-left: auto;
  468. }
  469. }
  470. /deep/ .uv-textarea{
  471. background-color: rgba($uni-color, 0.1) !important;
  472. min-height: 400rpx;
  473. }
  474. }
  475. }
  476. </style>