用工小程序前端代码
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.

589 lines
17 KiB

11 months ago
8 months ago
11 months ago
8 months ago
11 months ago
8 months ago
9 months ago
11 months ago
9 months ago
8 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
1 month ago
11 months ago
9 months ago
11 months ago
9 months ago
9 months ago
9 months ago
11 months ago
8 months ago
1 month ago
11 months ago
1 month ago
11 months ago
9 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
8 months ago
11 months ago
8 months ago
11 months ago
8 months ago
9 months ago
11 months ago
8 months ago
11 months ago
9 months ago
11 months ago
9 months ago
1 month ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
8 months ago
8 months ago
8 months ago
11 months ago
9 months ago
1 month ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
9 months ago
8 months ago
9 months ago
9 months ago
9 months ago
1 month ago
1 month ago
9 months ago
1 month ago
9 months ago
8 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
11 months ago
9 months ago
1 month ago
11 months ago
9 months ago
1 month ago
11 months ago
  1. <template>
  2. <view>
  3. <u--form labelPosition="left" :model="form" :rules="rules" ref="uForm" labelWidth="80">
  4. <view class="se-p-20">
  5. <view class="se-px-20 se-bgc-white se-br-10 se-fs-20">
  6. <u-form-item labelWidth="0">
  7. <view class="se-flex se-flex-ai-c">
  8. <view class="line-orange"></view>
  9. <view class="se-ml-10 se-fs-32 se-c-black se-fw-6">
  10. 标题
  11. </view>
  12. </view>
  13. </u-form-item>
  14. <u-form-item labelWidth="0" prop="title">
  15. <u--input v-model="form.title" placeholder="请在此输入标题"></u--input>
  16. </u-form-item>
  17. <u-form-item label="工作地点" prop="area" @click="handleAreaChange()">
  18. <u--input readonly v-model="form.area" placeholder="请选择工作地点"
  19. border="none"></u--input>
  20. <u-icon slot="right" name="arrow-right"></u-icon>
  21. </u-form-item>
  22. <!-- <u-form-item label="请选择地址" class="se-b-b" prop="area" @click="handleAreaChange()">
  23. <u--input readonly v-model="form.area" placeholder="请选择地址" border="none"></u--input>
  24. <u-icon slot="right" name="arrow-right" ></u-icon>
  25. </u-form-item> -->
  26. <!-- <u-form-item label="详细地址" prop="address">
  27. <u--textarea v-model="form.address" count
  28. placeholder="请输入详细地址"></u--textarea>
  29. </u-form-item> -->
  30. <u-form-item label="所属行业" prop="industryId" @click="handleindustryChange">
  31. <u--input @click="handleindustryChange" readonly v-model="form.industryName" placeholder="请选择行业"
  32. border="none"></u--input>
  33. <u-icon @click="handleindustryChange" slot="right" name="arrow-right"></u-icon>
  34. </u-form-item>
  35. <u-form-item label="所属工种" prop="typeId" @click="handleTypeChange">
  36. <u--input @click="handleTypeChange" v-model="form.typeName" readonly placeholder="请选择工种"
  37. border="none"></u--input>
  38. <u-icon @click="handleTypeChange" slot="right" name="arrow-right"></u-icon>
  39. </u-form-item>
  40. <u-form-item label="期望月薪" prop="salary">
  41. <view class="se-flex se-flex-h-c">
  42. <u--input v-model="form.salaryMin" class="se-w-200" placeholder="最小值"></u--input>
  43. <text class="se-mx-10">~</text>
  44. <u--input v-model="form.salaryMax" class="se-w-200" placeholder="最大值"></u--input>
  45. </view>
  46. </u-form-item>
  47. <u-form-item label="试工日薪" prop="dayMoney">
  48. <u--input v-model="form.dayMoney" placeholder="试工日薪"></u--input>
  49. </u-form-item>
  50. <u-form-item label="结算方式" prop="settlement">
  51. <u-radio-group v-model="form.settlement" placement="row">
  52. <u-radio activeColor="#FF7A31" name="0" label="提前支付"></u-radio>
  53. <u-radio activeColor="#FF7A31" class="se-ml-20" name="1" label="试用以后支付"></u-radio>
  54. </u-radio-group>
  55. </u-form-item>
  56. <u-form-item label="开始时间" prop="dateMin" @click="showMinDate=true">
  57. <u--input v-model="form.dateMin" disabled placeholder="开始时间"></u--input>
  58. </u-form-item>
  59. <u-form-item label="结束时间" prop="dateMax" @click="showMaxDate=true">
  60. <u--input v-model="form.dateMax" disabled placeholder="结束时间"></u--input>
  61. </u-form-item>
  62. <u-form-item label="联系电话" prop="mobile">
  63. <u--input v-model="form.mobile" placeholder="请输入联系方式"></u--input>
  64. </u-form-item>
  65. <u-form-item label="工作内容" prop="introduce">
  66. <u--textarea v-model="form.introduce" count
  67. placeholder="请选择工作内容"></u--textarea>
  68. </u-form-item>
  69. </view>
  70. </view>
  71. <view class="se-p-20">
  72. <view class="se-px-20 se-pb-20 se-bgc-white se-br-10 se-fs-20">
  73. <u-form-item prop="fileList" labelWidth="2">
  74. <view class="se-flex se-flex-v-sa">
  75. <view class="se-py-20 se-w-p-100 se-flex">
  76. <view class="line-orange"></view>
  77. <view class="se-ml-10">
  78. 图片上传
  79. </view>
  80. </view>
  81. <view class="se-py-20 se-w-p-100">
  82. <u-upload :fileList="form.fileList" @afterRead="afterRead" @delete="deletePic" name="1"
  83. multiple :maxCount="10"></u-upload>
  84. </view>
  85. </view>
  86. </u-form-item>
  87. </view>
  88. </view>
  89. <view class="se-px-20 se-pt-20">
  90. <view class="se-px-20 se-pb-80 se-fs-20 se-flex">
  91. <view @click="submit"
  92. class="se-mx-10 se-flex-1 se-br-40 se-flex-h-c se-h-80 se-lh-80 se-ta-c se-fs-28 se-c-white se-bgc-orange">
  93. <text>{{ editId ? '更新招聘信息' : '发布订单' }}</text>
  94. </view>
  95. </view>
  96. </view>
  97. </u--form>
  98. <!-- 性别 -->
  99. <u-action-sheet :show="showIndustry" :actions="indList" title="请选择行业" @close="showIndustry = false" @select="industrySelect">
  100. </u-action-sheet>
  101. <!-- 种类 -->
  102. <u-action-sheet :show="showType" :actions="typeList" title="请选择种类" @close="showType = false"
  103. @select="typeSelect">
  104. </u-action-sheet>
  105. <!-- 地址 -->
  106. <citySelect v-model="showPicker" @city-change="handleCityChange"></citySelect>
  107. <!-- 时间 Min-->
  108. <u-datetime-picker
  109. :show="showMinDate"
  110. :value="form.dateMin"
  111. :minDate="todayTimestamp"
  112. mode="datetime"
  113. closeOnClickOverlay
  114. @confirm="dateMinConfirm"
  115. @cancel="dateMinClose"
  116. @close="dateMinClose"
  117. ></u-datetime-picker>
  118. <u-datetime-picker
  119. :show="showMaxDate"
  120. :value="form.dateMax"
  121. :minDate="todayTimestamp"
  122. mode="datetime"
  123. closeOnClickOverlay
  124. @confirm="dateMaxConfirm"
  125. @cancel="dateMaxClose"
  126. @close="dateMaxClose"
  127. ></u-datetime-picker>
  128. </view>
  129. </template>
  130. <script>
  131. import QQMapWX from "@/util/qqmap-wx-jssdk.min.js"
  132. import { addTask,industryList,industryById, updateJob, getTaskById } from "@/common/api.js"
  133. import citySelect from '@/components/cityselect/index.vue'
  134. export default {
  135. props: {
  136. editId: {
  137. type: String,
  138. default: null
  139. }
  140. },
  141. components:{
  142. citySelect
  143. },
  144. data() {
  145. return {
  146. showMinDate:false,
  147. showMaxDate:false,
  148. todayTimestamp: new Date().setHours(0, 0, 0, 0),
  149. showPicker: false,
  150. showIndustry: false,
  151. indList:[],
  152. industryList: [
  153. {
  154. name: '打铁',
  155. },
  156. {
  157. name: '打牌',
  158. }
  159. ],
  160. showType: false,
  161. typeList: [],
  162. form: {
  163. title:"",
  164. area:'',
  165. address:'',
  166. industryId:"",
  167. industryName:"",
  168. settlement:'',
  169. date:"",
  170. dateMin:"",
  171. dateMax:"",
  172. mobile: '',
  173. typeId: '',
  174. typeName:"",
  175. salary:'',
  176. dayMoney:"",
  177. salaryMin: '',
  178. salaryMax: '',
  179. introduce: '',
  180. fileList: [],
  181. latitude:'',
  182. longitude:""
  183. },
  184. rules: {
  185. title:[
  186. {
  187. type: 'string',
  188. required: true,
  189. message: '请在此输入标题',
  190. trigger: ['blur', 'change']
  191. }
  192. ],
  193. area:[
  194. {
  195. type: 'string',
  196. required: true,
  197. message: '请选择地址',
  198. trigger: ['blur', 'change']
  199. }
  200. ],
  201. address:[
  202. {
  203. type: 'string',
  204. required: true,
  205. message: '请填写详细地址',
  206. trigger: ['blur', 'change']
  207. }
  208. ],
  209. industryName:[
  210. {
  211. type: 'string',
  212. required: true,
  213. message: '请选择行业',
  214. trigger: ['blur', 'change']
  215. }
  216. ],
  217. typeId:[
  218. {
  219. type: 'string',
  220. required: true,
  221. message: '请选择工种',
  222. trigger: ['blur', 'change']
  223. }
  224. ],
  225. dayMoney:[
  226. {
  227. required: true,
  228. message: '请输入试工日薪',
  229. trigger: ['blur', 'change']
  230. }
  231. ],
  232. settlement:[
  233. {
  234. type: 'string',
  235. required: true,
  236. message: '请选择结算方式',
  237. trigger: ['blur', 'change']
  238. }
  239. ],
  240. mobile: [
  241. {
  242. required: true,
  243. message: '请输入手机号',
  244. trigger: ['change','blur'],
  245. },
  246. {
  247. validator: (rule, value, callback) => {
  248. return uni.$u.test.mobile(value);
  249. },
  250. message: '手机号码不正确',
  251. trigger: ['change','blur'],
  252. },
  253. ],
  254. date: [{
  255. type: 'string',
  256. max: 1,
  257. required: true,
  258. message: '请填写时间',
  259. trigger: ['blur', 'change']
  260. }],
  261. salary: [{
  262. type: 'string',
  263. required: true,
  264. message: '请输入试用日薪',
  265. trigger: ['blur', 'change']
  266. }],
  267. introduce: [{
  268. type: 'string',
  269. required: true,
  270. message: '请输入工作内容',
  271. trigger: ['blur', 'change']
  272. }],
  273. fileList:[
  274. {
  275. validator: (rule, value, callback) => {
  276. if (value === null || value === undefined || value === '' || (Array.isArray(value) && value.length === 0)) {
  277. callback(new Error('照片不能为空'));
  278. } else {
  279. callback();
  280. }
  281. },
  282. trigger: 'blur'
  283. }
  284. ],
  285. },
  286. }
  287. },
  288. watch: {
  289. 'form.salaryMin': {
  290. handler(newVal, oldVal) {
  291. if (!uni.$u.test.isEmpty(newVal) && !uni.$u.test.isEmpty(this.form.salaryMax)) {
  292. this.form.salary = '有'
  293. } else {
  294. this.form.salary = ''
  295. }
  296. },
  297. immediate: true
  298. },
  299. 'form.salaryMax': {
  300. handler(newVal, oldVal) {
  301. if (!uni.$u.test.isEmpty(newVal) && !uni.$u.test.isEmpty(this.form.salaryMin)) {
  302. this.form.salary = '有'
  303. } else {
  304. this.form.salary = ''
  305. }
  306. },
  307. immediate: true
  308. },
  309. 'form.dateMin': {
  310. handler(newVal, oldVal) {
  311. if (!uni.$u.test.isEmpty(newVal) && !uni.$u.test.isEmpty(this.form.dateMax)) {
  312. this.form.date = '有'
  313. } else {
  314. this.form.date = ''
  315. }
  316. },
  317. immediate: true
  318. },
  319. 'form.dateMax': {
  320. handler(newVal, oldVal) {
  321. if (!uni.$u.test.isEmpty(newVal) && !uni.$u.test.isEmpty(this.form.dateMin)) {
  322. this.form.date = '有'
  323. } else {
  324. this.form.date = ''
  325. }
  326. },
  327. immediate: true
  328. },
  329. },
  330. methods: {
  331. dateMinConfirm(event){
  332. console.info(event)
  333. this.showMinDate = false
  334. this.form.dateMin = uni.$u.timeFormat(event.value, 'yyyy-mm-dd hh:MM:ss')
  335. },
  336. dateMinClose(){
  337. this.showMinDate = false
  338. },
  339. dateMaxConfirm(event){
  340. this.showMaxDate = false
  341. this.form.dateMax = uni.$u.timeFormat(event.value, 'yyyy-mm-dd hh:MM:ss')
  342. },
  343. dateMaxClose(){
  344. this.showMaxDate = false
  345. },
  346. handleAreaChange(){
  347. const that = this;
  348. wx.chooseLocation({
  349. type: 'gcj02',
  350. // type: 'wgs84',
  351. success: function (res) {
  352. that.form.latitude = res.latitude
  353. that.form.longitude = res.longitude
  354. if (!res.address && res.name) { //用户直接选择城市的逻辑
  355. return that.form.area = res.name
  356. }
  357. if (res.address || res.name) {
  358. return that.form.area = res.address + res.name
  359. }
  360. that.form.area = '' //用户啥都没选就点击勾选
  361. // const qqmapsdk = new QQMapWX({
  362. // key: 'TT7BZ-Z3LW4-KOAUB-KWHOA-SBJJ6-Y5B6R' // 必填
  363. // });
  364. // uni.showLoading({
  365. // title:"获取中...."
  366. // })
  367. // qqmapsdk.reverseGeocoder({
  368. // location: {
  369. // latitude: res.latitude,
  370. // longitude: res.longitude
  371. // },
  372. // success: function(response) {
  373. // console.log('逆地理编码结果:', response);
  374. // uni.hideLoading()
  375. // that.form.longitude = response.result.location.lng
  376. // that.form.latitude = response.result.location.lat
  377. // that.form.area = response.result.address
  378. // },
  379. // fail: function(error) {
  380. // uni.hideLoading()
  381. // console.error('逆地理编码失败:', error);
  382. // }
  383. // });
  384. }
  385. })
  386. // this.showPicker = true
  387. },
  388. handleCityChange(e) {
  389. console.info(e)
  390. this.form.area = e.province.label + '-' + e.city.label + '-' + e.area.label;
  391. },
  392. handleindustryChange() {
  393. this.showIndustry = true
  394. },
  395. industrySelect(e) {
  396. this.form.industryId=e.id
  397. this.form.industryName = e.name
  398. this.$refs.uForm.validateField('industryName')
  399. this.onIndustryById()
  400. },
  401. onIndustryById(){
  402. let that = this
  403. industryById({pid:that.form.industryId}).then(response=>{
  404. console.info("response",response);
  405. that.typeList = response.result
  406. // 如果是编辑模式且已有工种ID,需要在工种列表加载后验证工种字段
  407. if (that.editId && that.form.typeId) {
  408. that.$nextTick(() => {
  409. if (that.$refs.uForm) {
  410. that.$refs.uForm.validateField('typeId')
  411. }
  412. })
  413. }
  414. }).catch(error=>{
  415. })
  416. },
  417. handleTypeChange() {
  418. if(!this.form.industryId){
  419. return uni.$u.toast('请选择行业')
  420. }
  421. this.showType = true
  422. },
  423. typeSelect(e) {
  424. this.form.typeId = e.id
  425. this.form.typeName = e.name
  426. this.$refs.uForm.validateField('typeId')
  427. },
  428. submit() {
  429. this.$refs.uForm.validate().then(res => {
  430. this.onaddTask()
  431. }).catch(errors => {
  432. })
  433. },
  434. onaddTask(){
  435. let that = this
  436. let params ={
  437. "phone": that.form.mobile,//招聘方联系方式
  438. "salaryDay": that.form.dayMoney,//期望日薪
  439. "endTime": that.form.dateMax,
  440. "categoryOne": that.form.industryId,
  441. "categoryTwo": that.form.typeId,
  442. "latitude": that.form.latitude,
  443. "longitude": that.form.longitude,
  444. "salaryMax": that.form.salaryMax,//期望薪资最大值
  445. "salaryMin": that.form.salaryMin,//期望薪资最小值
  446. "payType": that.form.settlement,//结算方式 0提前支付 1 试用后支付
  447. "startTime": that.form.dateMin,
  448. "title": that.form.title,//工作标题
  449. "address": that.form.area,//工作地址
  450. "details": that.form.introduce,
  451. "image": that.form.fileList.map(item => item.url).join(','),//照片
  452. }
  453. // 如果是编辑模式,添加ID参数
  454. if (this.editId) {
  455. params.id = this.editId
  456. }
  457. if(this.$dayjs(params.startTime).isAfter(this.$dayjs(params.endTime))){
  458. return uni.$u.toast('开始时间不能大于结束时间')
  459. } else if(this.$dayjs(params.endTime).isBefore(this.$dayjs())){
  460. return uni.$u.toast('结束时间不能小于当前时间')
  461. }else if(this.$dayjs(params.startTime).isBefore(this.$dayjs())){
  462. return uni.$u.toast('开始时间不能小于当前时间')
  463. }
  464. // 根据是否为编辑模式选择不同的API
  465. const apiMethod = this.editId ? updateJob : addTask
  466. const successMessage = this.editId ? '更新成功!' : '提交成功!'
  467. apiMethod(params).then(response=>{
  468. console.info("response",response)
  469. uni.$u.toast(successMessage)
  470. setTimeout(()=>{
  471. uni.navigateBack({
  472. delta:1
  473. })
  474. },1500)
  475. }).catch(error=>{
  476. })
  477. },
  478. deletePic(event) {
  479. this.form.fileList.splice(e.index, 1)
  480. },
  481. async afterRead(e) {
  482. let self = this
  483. e.file.forEach(file => {
  484. self.$Oss.ossUpload(file.url).then(url => {
  485. self.form.fileList.push({
  486. url
  487. })
  488. })
  489. })
  490. },
  491. onIndustryList(){
  492. industryList({}).then(response=>{
  493. console.info("industryList",response);
  494. this.indList = response.result
  495. }).catch(error=>{
  496. })
  497. },
  498. // 获取招聘详情数据用于编辑
  499. getJobDetail() {
  500. getTaskById({
  501. id: this.editId,
  502. edit : '1'
  503. }).then(response => {
  504. const data = response.result
  505. // 回填表单数据
  506. this.form.title = data.title || ''
  507. this.form.area = data.address || ''
  508. this.form.industryId = data.categoryOne || ''
  509. this.form.industryName = data.categoryOneName || ''
  510. this.form.typeId = data.categoryTwo || ''
  511. this.form.typeName = data.categoryTwoName || ''
  512. this.form.salaryMin = data.salaryMin || ''
  513. this.form.salaryMax = data.salaryMax || ''
  514. this.form.dayMoney = String(data.salaryDay || '')
  515. this.form.settlement = data.payType || ''
  516. this.form.dateMin = data.startTime || ''
  517. this.form.dateMax = data.endTime || ''
  518. this.form.mobile = data.phone || ''
  519. this.form.introduce = data.details || ''
  520. this.form.latitude = data.latitude || ''
  521. this.form.longitude = data.longitude || ''
  522. // 处理图片列表
  523. if (data.image) {
  524. const imageUrls = data.image.split(',')
  525. this.form.fileList = imageUrls.map(url => ({ url: url.trim() }))
  526. }
  527. // 如果有行业ID,获取对应的工种列表
  528. if (this.form.industryId) {
  529. this.onIndustryById()
  530. }
  531. // 数据回填后,清除表单验证错误状态
  532. this.$nextTick(() => {
  533. if (this.$refs.uForm) {
  534. // 清除所有字段的验证错误
  535. this.$refs.uForm.clearValidate()
  536. // 或者单独验证已填充的字段
  537. if (this.form.industryName) {
  538. this.$refs.uForm.validateField('industryName')
  539. }
  540. if (this.form.typeId) {
  541. this.$refs.uForm.validateField('typeId')
  542. }
  543. if (this.form.dayMoney) {
  544. this.$refs.uForm.validateField('dayMoney')
  545. }
  546. }
  547. })
  548. }).catch(error => {
  549. console.error('获取招聘详情失败:', error)
  550. uni.showToast({
  551. title: '获取数据失败',
  552. icon: 'none'
  553. })
  554. })
  555. },
  556. },
  557. onReady() {
  558. this.$refs.uForm.setRules(this.rules)
  559. this.onIndustryList()
  560. // 如果是编辑模式,获取招聘详情数据
  561. if (this.editId) {
  562. this.getJobDetail()
  563. }
  564. },
  565. }
  566. </script>
  567. <style>
  568. </style>