This commit is contained in:
2025-11-04 15:16:22 +08:00
parent 262f398772
commit 8f5d92c80d
36 changed files with 8846 additions and 167 deletions

View File

@@ -0,0 +1,58 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:56:51
*/
import request from '@/utilsRc/request'
// 查询援助需求列表
export function listAssistService(query) {
return request({
url: '/demand/personAssistDemandInfo/list',
method: 'get',
params: query
})
}
// 查询援助需求详细
export function getAssistService(ids) {
return request({
url: '/demand/personAssistDemandInfo/' + ids,
method: 'get'
})
}
// 新增援助需求
export function addAssistService(data) {
return request({
url: '/demand/personAssistDemandInfo',
method: 'post',
data: data
})
}
// 修改援助需求
export function updateAssistService(data) {
return request({
url: '/demand/personAssistDemandInfo',
method: 'put',
data: data
})
}
// 删除援助需求
export function delAssistService(ids) {
return request({
url: '/manage/personDemand/' + ids,
method: 'delete'
})
}
// 个人援助需求办结
export function finishAssistService(data) {
return request({
url: '/demand/personAssistDemandInfo/assistDone',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,58 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:56:35
*/
import request from '@/utilsRc/request'
// 查询创业需求列表
export function listEntrepreneurshipService(query) {
return request({
url: '/demand/personEntrepreneurshipDemandInfo/list',
method: 'get',
params: query
})
}
// 查询创业需求详细
export function getEntrepreneurshipService(ids) {
return request({
url: '/demand/personEntrepreneurshipDemandInfo/' + ids,
method: 'get'
})
}
// 新增创业需求
export function addEntrepreneurshipService(data) {
return request({
url: '/demand/personEntrepreneurshipDemandInfo',
method: 'post',
data: data
})
}
// 修改创业需求
export function updateEntrepreneurshipService(data) {
return request({
url: '/demand/personEntrepreneurshipDemandInfo',
method: 'put',
data: data
})
}
// 删除创业需求
export function delEntrepreneurshipService(ids) {
return request({
url: '/manage/personDemand/' + ids,
method: 'delete'
})
}
// 个人援助需求办结
export function finishEntrepreneurshipService(data) {
return request({
url: '/demand/personEntrepreneurshipDemandInfo/entrepreneurshipDone',
method: 'post',
data: data
})
}

57
apiRc/needs/jobService.js Normal file
View File

@@ -0,0 +1,57 @@
/*
* @Date: 2025-04-07 14:23:47
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:56:39
*/
import request from '@/utilsRc/request'
// 查询求职需求列表
export function listJobService(query) {
return request({
url: '/manage/personDemand/list',
method: 'get',
params: query
})
}
// 查询求职需求详细
export function getJobService(ids) {
return request({
url: '/manage/personDemand/' + ids,
method: 'get'
})
}
// 新增求职需求
export function addJobService(data) {
return request({
url: '/manage/personDemand',
method: 'post',
data: data
})
}
// 修改求职需求
export function updateJobService(data) {
return request({
url: '/manage/personDemand',
method: 'put',
data: data
})
}
// 删除求职需求
export function delJobService(ids) {
return request({
url: '/manage/personDemand/' + ids,
method: 'delete'
})
}
//查询服务次数
export function serviceTraceability(userId) {
return request({
url: '/timelime/timelime/getFwcs/' + userId,
method: 'get'
})
}

View File

@@ -0,0 +1,58 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:56:42
*/
import request from '@/utilsRc/request'
// 查询其他需求列表
export function listOtherService(query) {
return request({
url: '/demand/personOtherDemandInfo/list',
method: 'get',
params: query
})
}
// 查询其他需求详细
export function getOtherService(ids) {
return request({
url: '/demand/personOtherDemandInfo/' + ids,
method: 'get'
})
}
// 新增其他需求
export function addOtherService(data) {
return request({
url: '/demand/personOtherDemandInfo',
method: 'post',
data: data
})
}
// 修改其他需求
export function updateOtherService(data) {
return request({
url: '/demand/personOtherDemandInfo',
method: 'put',
data: data
})
}
// 删除其他需求
export function delOtherService(ids) {
return request({
url: '/manage/personDemand/' + ids,
method: 'delete'
})
}
// 个人援助需求办结
export function finishOtherService(data) {
return request({
url: '/demand/personOtherDemandInfo/otherDemandDone',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,49 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:56:47
*/
import request from '@/utilsRc/request'
// 查询培训需求列表
export function listTrainService(query) {
return request({
url: '/demand/personTrainDemandInfo/list',
method: 'get',
params: query
})
}
// 查询培训需求详细
export function getTrainService(ids) {
return request({
url: '/demand/personTrainDemandInfo/' + ids,
method: 'get'
})
}
// 新增培训需求
export function addTrainService(data) {
return request({
url: '/demand/personTrainDemandInfo',
method: 'post',
data: data
})
}
// 修改培训需求
export function updateTrainService(data) {
return request({
url: '/demand/personTrainDemandInfo',
method: 'put',
data: data
})
}
// 删除培训需求
export function delTrainService(ids) {
return request({
url: '/manage/personDemand/' + ids,
method: 'delete'
})
}

View File

@@ -0,0 +1,50 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:56:56
*/
import request from '@/utilsRc/request'
// 查询角色列表
export function listInvestigate(query) {
return request({
url: '/process/processInterview/list',
method: 'get',
params: query
})
}
// 查询角色详细
export function getInvestigate(ids) {
return request({
url: '/process/processInterview/' + ids,
method: 'get'
})
}
// 新增角色
export function addInvestigate(data) {
return request({
// url: '/process/processInterview',
url: '/timelime/timelime',
method: 'post',
data: data
})
}
// 修改角色
export function updateInvestigate(data) {
return request({
url: '/process/processInterview',
method: 'put',
data: data
})
}
// 删除角色
export function delInvestigate(ids) {
return request({
url: '/process/processInterview/' + ids,
method: 'delete'
})
}

View File

@@ -0,0 +1,86 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:56:59
*/
import request from '@/utilsRc/request'
// 查询角色列表
export function listJobRecommend(query) {
return request({
url: '/process/processJobRecommend/list',
method: 'get',
params: query
})
}
// 查询角色列表
export function getWorkListReq(query) {
return request({
// url: '/personnel/personBaseInfo/postRecommend',
url: '/company/unitPostInfo/postElectedList',
method: 'get',
params: query
})
}
// 查询角色详细
export function getJobRecommend(ids) {
return request({
url: '/process/processJobRecommend/' + ids,
method: 'get'
})
}
// 新增角色
export function addJobRecommend(data) {
return request({
url: '/process/processJobRecommend',
method: 'post',
data: data
})
}
//岗位推荐保存和办结
export function saveJobRecommend(data) {
return request({
url: '/process/processJobRecommend/create',
method: 'post',
data: data
})
}
// 修改角色
export function updateJobRecommend(data) {
return request({
url: '/process/processJobRecommend',
method: 'put',
data: data
})
}
// 删除角色
export function delJobRecommend(ids) {
return request({
url: '/process/processJobRecommend/' + ids,
method: 'delete'
})
}
// 获取绑定的职位
export function getAddedJobs(params) {
return request({
// url: '/company/postDeliverInfo/list',
url: '/company/unitPostInfo/no/permission/list',
method: 'get',
params,
})
}
// // 获取推荐岗位
// export function getAddedJobs(params) {
// return request({
// url: '/personnel/personBaseInfo/postRecommend',
// method: 'get',
// params,
// })
// }

49
apiRc/service/jobTrack.js Normal file
View File

@@ -0,0 +1,49 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:57:02
*/
import request from '@/utilsRc/request'
// 查询角色列表
export function listJobTrack(query) {
return request({
url: '/process/processEmploymentTracking/list',
method: 'get',
params: query
})
}
// 查询角色详细
export function getJobTrack(ids) {
return request({
url: '/process/processEmploymentTracking/' + ids,
method: 'get'
})
}
// 新增角色
export function addJobTrack(data) {
return request({
url: '/process/processEmploymentTracking',
method: 'post',
data: data
})
}
// 修改角色
export function updateJobTrack(data) {
return request({
url: '/process/processEmploymentTracking',
method: 'put',
data: data
})
}
// 删除角色
export function delJobTrack(ids) {
return request({
url: '/process/processEmploymentTracking/' + ids,
method: 'delete'
})
}

View File

@@ -0,0 +1,49 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:57:05
*/
import request from '@/utilsRc/request'
// 查询角色列表
export function listPolicyConsultation(query) {
return request({
url: '/process/processPolicyConsult/list',
method: 'get',
params: query
})
}
// 查询角色详细
export function getPolicyConsultation(ids) {
return request({
url: '/process/processPolicyConsult/' + ids,
method: 'get'
})
}
// 新增角色
export function addPolicyConsultation(data) {
return request({
url: '/process/processPolicyConsult',
method: 'post',
data: data
})
}
// 修改角色
export function updatePolicyConsultation(data) {
return request({
url: '/process/processPolicyConsult',
method: 'put',
data: data
})
}
// 删除角色
export function delPolicyConsultation(ids) {
return request({
url: '/process/processPolicyConsult/' + ids,
method: 'delete'
})
}

View File

@@ -0,0 +1,49 @@
/*
* @Date: 2024-09-25 11:14:29
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 08:57:09
*/
import request from '@/utilsRc/request'
// 查询角色列表
export function listSkillTrain(query) {
return request({
url: '/process/processSkillTraining/list',
method: 'get',
params: query
})
}
// 查询角色详细
export function getSkillTrain(ids) {
return request({
url: '/process/processSkillTraining/' + ids,
method: 'get'
})
}
// 新增角色
export function addSkillTrain(data) {
return request({
url: '/process/processSkillTraining',
method: 'post',
data: data
})
}
// 修改角色
export function updateSkillTrain(data) {
return request({
url: '/process/processSkillTraining',
method: 'put',
data: data
})
}
// 删除角色
export function delSkillTrain(ids) {
return request({
url: '/process/processSkillTraining/' + ids,
method: 'delete'
})
}

View File

@@ -1,7 +1,7 @@
/*
* @Date: 2025-11-03 10:52:09
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-03 17:26:29
* @LastEditTime: 2025-11-04 11:14:21
*/
import App from '@/App'
import * as Pinia from 'pinia'
@@ -24,6 +24,7 @@ import uniDataSelect from './uni_modules/uni-data-select/components/uni-data-sel
import uniSwipeAction from './uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue'
import uniSwipeActionItem from './uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue'
import storeRc from './utilsRc/store/index.js'
import {processFileUrl,} from '@/utilsRc/common.js'
// iconfont.css 已在 App.vue 中通过 @import 引入,无需在此处重复引入
// import Tabbar from '@/components/tabbar/midell-box.vue'
// 自动导入 directives 目录下所有指令
@@ -57,6 +58,7 @@ export function createApp() {
app.component('uni-swipe-action-item', uniSwipeActionItem)
app.config.globalProperties.$processFileUrl = processFileUrl;
app.config.globalProperties.$getDict = getDict;
app.config.globalProperties.$store = storeRc;
app.config.globalProperties.$getDictSelectOption = async (dictType, isDigital = false, forceRefresh = false) => {

View File

@@ -0,0 +1,159 @@
<template>
<view class="upload-container">
<input type="file" multiple="multiple" accept="image/*" @change="handleFileChange">
<!-- <uni-upload :disabled="disabled" :width="width" :height="height" :fileList="internalFileList" :name="name" :multiple="multiple"
:maxCount="maxCount" @afterRead="handleAfterRead" @delete="handleRemove">
</uni-upload> -->
</view>
</template>
<script>
// import {
// uploadImg
// } from '@/api/company'
import config from '@/config'
//import {
// getToken
//} from '@/utils/auth'
export default {
props: {
maxSize: {
type: Number,
default: 5, // 最大文件大小MB
},
allowedFormats: {
type: Array,
default: () => [], // 允许的文件格式
},
maxImageSize: {
type: Object,
default: () => ({
width: 2048,
height: 2048
}), // 图片最大宽度和高度
},
width: {
type: String,
default: '100rpx', // 默认宽度
},
height: {
type: String,
default: '100rpx', // 默认高度
},
name: {
type: String,
default: 'file', // 默认name字段
},
multiple: {
type: Boolean,
default: false, // 是否允许多选,默认不允许
},
maxCount: {
type: Number,
default: 1, // 默认最大上传数量为1
},
fileList: {
type: Array,
default: () => [], // 默认的文件列表为空
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
internalFileList: [...this.fileList], // 内部的文件列表,确保与父组件的同步
};
},
watch: {
// 监听 fileList 的变化,确保内外部数据同步
fileList(newVal) {
this.internalFileList = [...newVal];
},
},
methods: {
// 新增图片
async handleAfterRead(event) {
let lists = [].concat(event.file);
let fileListLen = this.internalFileList.length;
lists.map((item) => {
this.internalFileList.push({
...item,
status: "uploading",
message: "上传中",
});
});
for (let i = 0; i < lists.length; i++) {
if (this.allowedFormats.length > 0) {
let fileType = lists[i].name.split('.').pop().toLowerCase();
if (!this.allowedFormats.includes(fileType)) {
// this.$emit('error', '不支持的文件格式');
uni.showToast({
title: '不支持的文件格式',
icon: 'none',
});
this.internalFileList.splice(fileListLen, 1);
this.$emit('update', this.internalFileList); // 通知父组件文件列表更新
return;
}
}
const result = await this.uploadFilePromise(lists[i].url);
let item = this.internalFileList[fileListLen];
this.internalFileList.splice(
fileListLen,
1,
Object.assign(item, {
status: "success",
message: "",
data: result,
})
);
fileListLen++;
this.$emit('update', this.internalFileList); // 通知父组件文件列表更新
}
},
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: config.baseUrl + '/system/oss/upload',
filePath: url,
name: "file",
header: {
Authorization: "Bearer " + getToken(),
},
success: (uploadFileRes) => {
let res = JSON.parse(uploadFileRes.data);
resolve(res.data);
},
fail: (err) => {
console.log(err);
},
});
});
},
handleRemove({file, index}) {
this.internalFileList.splice(index, 1); // 从文件列表中移除指定文件
this.$emit('update', this.internalFileList); // 通知父组件文件列表更新
},
},
};
</script>
<style scoped>
.upload-container {
display: flex;
align-items: center;
justify-content: center;
}
.upload-slot {
display: flex;
align-items: center;
justify-content: center;
border: 1px dashed #ccc;
border-radius: 4px;
padding: 20px;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -432,7 +432,7 @@ import { getPersonInfo } from "../../api/company/index.js";
// import { listEntrepreneurshipService } from "@/api/needs/entrepreneurshipService";
// import { listTrainService, delTrainService } from "@/api/needs/trainService";
import { listJobType } from "../../api/jobType/index";
// import ImageUpload from "@/components/ImageUpload";
// import ImageUpload from "@/packageRc/components/ImageUpload";
export default {
name: "serviceDetails",
components: {
@@ -537,7 +537,7 @@ export default {
},
];
arr.forEach((ele, index) => {
this.getDicts(ele.key).then((res) => {
this.$getDict(ele.key).then((res) => {
this.dict[ele.prop] = res.data;
this.$forceUpdate();
});
@@ -636,19 +636,9 @@ export default {
});
}
},
goRecommend() {
this.$tab.navigateTo(
`/pages/services/serviceDetail?activeType=2&showTab=1&userId=${this.form.userId}&name=${this.form.name}`
);
},
goPush() {
this.$tab.navigateTo(
`/pages/services/serviceDetail?activeType=3&showTab=1&userId=${this.form.userId}&name=${this.form.name}`
);
},
goNeedsDetail(item, needsType) {
uni.navigateTo({
url: `/pages/needs/needDetail?id=${item.id}&type=${needsType}&showTab=1`,
url: `/packageRc/pages/needs/needDetail?id=${item.id}&type=${needsType}&showTab=1`,
});
},
calculateAge(data) {
@@ -690,21 +680,23 @@ export default {
title: "提示",
content: "你确定要删除吗",
success: (res) => {
delPersonDemand(data.id).then((res) => {
if (res.code == 200) {
uni.showToast({
title: "删除成功",
icon: "none",
});
//刷新列表
this.getListPersonDemand();
} else {
uni.showToast({
title: "删除失败",
icon: "none",
});
}
});
if(res.confirm){
delPersonDemand(data.id).then((res) => {
if (res.code == 200) {
uni.showToast({
title: "删除成功",
icon: "none",
});
//刷新列表
this.getListPersonDemand();
} else {
uni.showToast({
title: "删除失败",
icon: "none",
});
}
});
}
},
});
},
@@ -743,9 +735,9 @@ export default {
// 获取当前的需求类型字符串
const demandType = demandTypeMap[needsType] || "other";
// 使用映射后的字符串构建URL并导航
this.$tab.navigateTo(
`/pages/services/serviceTraceability?id=${item.id}&demandType=${demandType}`
);
uni.navigateTo({
url: `/pages/services/serviceTraceability?id=${item.id}&demandType=${demandType}`
});
},
// 办结按钮
async finishJobRecommend(needsType) {
@@ -787,11 +779,11 @@ export default {
requirementTraining(item, index) {
if (index == 1) {
uni.navigateTo({
url: `/packageRc/pages/services/serviceDetail?personName=${item.personName}&personId=${item.personId}&jobDemandInfoId=${item.id}&jobWorkType=${item.jobWorkType}&type=3&showTab=1`
url: `/packageRc/pages/service/serviceDetail?personName=${item.personName}&personId=${item.personId}&jobDemandInfoId=${item.id}&jobWorkType=${item.jobWorkType}&type=3&showTab=1`
});
} else {
uni.navigateTo({
url: `/packageRc/pages/services/serviceDetail?personName=${item.personName}&personId=${item.personId}&skillTrainingId=${item.id}&personStatus=${item.personStatus}&type=4&showTab=1`
url: `/packageRc/pages/service/serviceDetail?personName=${item.personName}&personId=${item.personId}&skillTrainingId=${item.id}&personStatus=${item.personStatus}&type=4&showTab=1`
});
}
},

View File

@@ -1,7 +1,7 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-03 16:11:03
* @LastEditTime: 2025-11-04 13:53:56
-->
<template>
<view class="container">
@@ -493,7 +493,7 @@
if (this.edit) {
if(type === 'workTypeTree') {
if (!this.workTypeTreeColumns[0] || !this.workTypeTreeColumns[0].length) {
this.$u.toast('工种数据未加载,请稍后重试');
uni.showToast({title: '工种数据未加载,请稍后重试'});
return;
}
// 弹窗打开时初始化临时columns和index

View File

@@ -0,0 +1,132 @@
<template>
<view>
<uni-popup ref="showPersonChooser" background-color="#fff" type="bottom">
<view style="padding: 32rpx 32rpx 0">
<input @change="searchChange" placeholder="搜索选择人员" v-model="searchPerson"></input>
<scroll-view style="height: 500rpx;" :scroll-y="true">
<view v-for="(item, index) in personList" :key="index" :label="item.name" :value="item.name"
@click="bindPerson(item)" class="person-list" :class="{active: activePerson.id == item.id}">
<view style="display: flex;justify-content: space-between;font-size: 32rpx;font-weight: bold;">
{{ item.name }}
<view style="color: #8492a6; font-size: 13px;width: 50%;text-align: right;">{{ item.phone }}
</view>
</view>
<view style="color: #8492a6;margin-top: 7rpx;">现居住地{{item.currentResidentialAddress}}</view>
</view>
</scroll-view>
<view class="button-area">
<view class="btn" @click="closeshowPersonChooser">取消</view>
<view class="btn reset" @click="resetData">重置</view>
<view class="btn save" @click="saveInfo">确定</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import {
getPersonList
} from '@/apiRc/needs/person'
export default {
data() {
return {
showPersonChooser: false,
activePerson: {},
searchPerson: '',
personList: [],
searcher: '',
}
},
mounted() {
this.doSearch()
},
methods: {
open() {
this.$refs.showPersonChooser.open();
this.activePerson = {}
},
saveInfo() {
this.$emit('confirm', this.activePerson)
this.$refs.showPersonChooser.close()
},
searchChange() {
if (this.searcher) {
clearTimeout(this.searcher)
this.doSearch()
} else {
this.doSearch()
}
},
doSearch() {
this.searcher = setTimeout(() => {
getPersonList({
name: this.searchPerson,
pageSize: 100,
pageNum: 1
}).then(res => {
this.personList = res.rows
clearTimeout(this.searcher)
})
}, 200)
},
resetData(){
this.searchPerson = '';
this.personList = [];
this.activePerson = {}
},
bindPerson(item) {
this.activePerson = item;
this.$forceUpdate();
},
}
}
</script>
<style lang="scss" scoped>
.person-list {
padding: 24rpx 32rpx;
border-radius: 8rpx;
box-sizing: border-box;
border: 1px solid #e4e4e4;
margin-top: 32rpx;
&.active {
border: 1px solid #1890ff;
}
}
.button-area {
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
padding: 24rpx 32rpx 68rpx;
width: calc(100% + 64rpx);
margin-left: -32rpx;
background: #fff;
display: flex;
box-sizing: border-box;
margin-top: 40rpx;
border-radius: 16px 16px 0px 0px;
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
</style>

View File

@@ -0,0 +1,431 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:29:24
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 200rpx)':'calc(100vh - 194rpx)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">创业需求信息
<view v-if="!edit&&formData.id&&formData.currentStatus!=3" class="btn"
style="font-weight: normal;display: flex;" @click="edit=true">编辑<u-icon name="edit-pen"
color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<uni-forms labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form"
labelWidth="100">
<uni-forms-item label="姓名" name="personName" required
v-if="$store.getters.roles.includes('shequn'|| $store.getters.roles.includes('gly'))"
>
<view style="width: 100%;" @click="openPersonChooser"
:class="{disabledLine: !edit||!canChoosePerson, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<!-- <u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon> -->
</uni-forms-item>
<!--
<uni-forms-item label="服务需求标题" name="serviceRequirementTitle" required>
<u--textarea :disabled="!edit" v-model="formData.serviceRequirementTitle"
placeholder="请输入"></u--textarea>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</uni-forms-item> -->
<uni-forms-item label="有无场地需求" name="ywcdxq" required>
<radio-group :disabled="!edit" :value="formData.ywcdxq" placement="row">
<radio :customStyle="{marginRight: '16px'}" label="是" value="是"></radio>
<radio :customStyle="{marginRight: '16px'}" label="否" value="否"></radio>
</radio-group>
</uni-forms-item>
<uni-forms-item label="场地面积" name="cdmj">
<input :disabled="!edit" v-model="formData.cdmj" border="none"
placeholder="请输入"/>
<!-- <u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon> -->
</uni-forms-item>
<uni-forms-item label="办公人数" name="bgrs">
<input :disabled="!edit" v-model="formData.bgrs" border="none"
placeholder="请输入"/>
<!-- <u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon> -->
</uni-forms-item>
<uni-forms-item label="办公位置" name="bgdd">
<input :disabled="!edit" v-model="formData.bgdd" border="none"
placeholder="请输入"/>
<!-- <u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon> -->
</uni-forms-item>
<uni-forms-item label="有无创业培训需求" name="ywcypxxq" required>
<radio-group :disabled="!edit" :value="formData.ywcypxxq"
placement="row">
<radio :customStyle="{marginRight: '16px'}" label="是" value="是"></radio>
<radio :customStyle="{marginRight: '16px'}" label="否" value="否"></radio>
</radio-group>
</uni-forms-item>
<!-- <uni-forms-item label="是否意向接受创业培训" name="isInterestedEntrepreneurshipGuidance" required>-->
<!-- <radio-group :disabled="!edit" v-model="formData.isInterestedEntrepreneurshipGuidance"-->
<!-- placement="row">-->
<!-- <radio :customStyle="{marginRight: '16px'}" label="是" name="是"></radio>-->
<!-- <radio :customStyle="{marginRight: '16px'}" label="否" name="否"></radio>-->
<!-- </radio-group>-->
<!-- </uni-forms-item>-->
<uni-forms-item label="有无资金需求" name="ywzjxq" required>
<radio-group :disabled="!edit" :value="formData.ywzjxq" placement="row">
<radio :customStyle="{marginRight: '16px'}" label="是" value="是">是</radio>
<radio :customStyle="{marginRight: '16px'}" label="否" value="否">否</radio>
</radio-group>
</uni-forms-item>
<uni-forms-item label="需求说明" name="jobDescription" required>
<textarea :disabled="!edit" v-model="formData.jobDescription" placeholder="请输入"></textarea>
</uni-forms-item>
<!-- <uni-forms-item label="希望解决日期" name="hopeSolveDate" required>
<view style="width: 100%;" @click="showPicker('hopeSolveDate')"
:class="{disabledLine: !edit, noValue: !formData.hopeSolveDate}">
{{ formData.hopeSolveDate||'请选择' }}
</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</uni-forms-item> -->
</uni-forms>
</view>
</view>
<!-- <view class="inner" style="margin-top: 32rpx;">-->
<!-- <view class="inner-part">-->
<!-- <u&#45;&#45;form labelPosition="left" class="self-form" labelWidth="110">-->
<!-- <uni-forms-item label="需求说明" name="qtxqsm">-->
<!-- <textarea :disabled="!edit" v-model="formData.qtxqsm" placeholder="请输入"></textarea>-->
<!-- </uni-forms-item>-->
<!-- </u&#45;&#45;form>-->
<!-- </view>-->
<!-- </view>-->
<!-- <view class="inner">
<view class="part-title" style="margin-top: 32rpx;">附件信息</view>
<view class="inner-part">
<uni-forms labelPosition="left" class="self-form" labelWidth="110">
<uni-forms-item label="附件" name="fileUrl">
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</uni-forms-item>
</uni-forms>
</view>
</view> -->
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
</scroll-view>
<u-datetime-picker :show="show.hopeSolveDate" v-model="dates.hopeSolveDate" mode="date"
@confirm="confirmDate('hopeSolveDate', $event)" @cancel="cancelPicker('hopeSolveDate')"></u-datetime-picker>
<choose-person ref="personChooser" @confirm="personNameConfirm" />
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<view class="btn reset" @click="getPersonInfo()">重置</view>
<view class="btn save" @click="saveInfo">保存</view>
</view>
</view>
</template>
<script>
import {
getPersonBase
} from "@/apiRc/person";
import {
addPersonDemand,
updatePersonDemand,
getPersonDemand
} from "@/apiRc/needs/personDemand";
import ImageUpload from '/packageRc/components/ImageUpload'
import ChoosePerson from '/packageRc/pages/needs/components/choosePerson';
import dayjs from "dayjs";
export default {
components: {
ChoosePerson,
ImageUpload
},
props: {
needId: {
type: String,
default: ''
},
name: {
type: String,
default: ''
}
},
data() {
return {
fileList: [],
edit: true,
personBase: {},
dates: {},
formData: {
jobDescription:"",
demandType:"2",
personName: '',
personId:"",
userId:"",
serviceRequirementTitle: '',
isAcceptAssistance: '',
isAcceptApprovalResult: '',
},
rules: {
ywcdxq: [{
required: true,
message: '请选择有无场地需求',
trigger: ['blur', 'change'],
}, ],
ywcypxxq: [{
required: true,
message: '请选择有无创业培训需求',
trigger: ['blur', 'change'],
}, ],
isInterestedEntrepreneurshipGuidance: [{
required: true,
message: '请选择是否意向接受创业培训',
trigger: ['blur', 'change'],
}, ],
ywzjxq: [{
required: true,
message: '请选择有无资金需求',
trigger: ['blur', 'change'],
}, ],
},
dict: {},
show: {},
currentCityArr: [],
originalDept: [],
currentCity: '请选择',
bysj: '',
loading: false,
jobTypeList: [],
route: {},
canChoosePerson: false,
}
},
onReady() {
this.$refs.uForm.setRules(this.rules);
},
async created() {
this.loading = true;
// await this.$delay(600)
// this.setDefaultValues()
// setTimeout(() => {
// this.setName()
// }, 0);
},
methods: {
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
// setName(){
// this.formData.personName = this.name
// this.formData.personId = this.needid
// this.formData.userId = this.needid
// this.$forceUpdate();
// },
openPersonChooser() {
if (this.edit && this.canChoosePerson) {
this.$refs.personChooser.open();
}
},
personNameConfirm(event) {
this.formData.personName = event.name
this.formData.personId = event.id
this.formData.userId = event.userId
this.formNameChange();
this.$forceUpdate();
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.setDefaultValues()
this.getPersonInfo()
if(this.name){
this.formData.personName = this.name
this.formData.userId = this.needid
}
this.edit = true
},
getDetail(id) {
getPersonDemand(id).then(res => {
this.formData = res.data;
this.edit = false
this.fileList = this.$processFileUrl(this.formData.fileUrl)
})
},
confirmDate(type, e) {
this.show[type] = false;
let date = new Date(e.value)
this.formData[type] =
`${date.getFullYear()}-${(date.getMonth()+1)>9?(date.getMonth()+1):('0'+(date.getMonth()+1))}-${date.getDate()>9?date.getDate():('0'+date.getDate())}`
this.$forceUpdate();
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
this.$forceUpdate();
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
this.$forceUpdate();
},
showPicker(type) {
if (this.edit) {
this.show[type] = true
this.$forceUpdate()
}
},
getPersonInfo() {
this.loading = true;
this.$store.dispatch("GetInfo").then((res) => {
if (res.data.roles.indexOf('qunzhong') == -1) {
this.canChoosePerson = true;
} else {
this.canChoosePerson = false;
getPersonBase(res.data.user.userId).then(resp => {
this.formData.personId = resp.data.id
this.formData.userId = resp.data.userId
this.formData.personName = resp.data.name
this.formNameChange();
this.$forceUpdate();
})
}
})
},
formNameChange() {
let date = new Date()
// let day =
// `${date.getFullYear()}-${(date.getMonth()+1) + 1 > 9 ? (date.getMonth()+1) + 1: '0'+((date.getMonth()+1) + 1)}-${date.getDate() > 9 ? date.getDate(): '0'+date.getDate()}`
const dayNew = dayjs(date).format("YYYY-MM-DD");
this.formData.serviceRequirementTitle = `${this.formData.personName}_于${dayNew}_提出创业需求`
},
async saveInfo() {
uni.showLoading()
try {
if (!this.formData.jobDescription || this.formData.jobDescription.trim() === '') {
uni.showToast({title: '请填写需求说明!', icon: 'none'});
return;
}
// 验证表单
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('请检查必填项填写');
}
// 显示全局加载
// 根据 formData 是否有 id 来决定是更新还是新增
let response;
this.formData.demandType = 2;
let successMessage;
if (this.formData.id) {
response = await updatePersonDemand(this.formData);
successMessage = '修改成功';
} else {
response = await addPersonDemand(this.formData);
successMessage = '保存成功';
}
// 检查响应码是否为200
if (response.code === 200) {
uni.showToast({title: successMessage, icon: 'none'});
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
await this.$delay(1000); // 延迟1秒后返回上一页
uni.navigateBack();
}
}
} catch (error) {
if(error.length){
uni.showToast({title: '请填写完整信息!', icon: 'none'});
}else{
uni.showToast({title: '系统错误,请联系管理员!', icon: 'none'});
}
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
},
// 设置默认选中
setDefaultValues(){
this.$set(this.formData, 'ywcdxq', '是')
this.$set(this.formData, 'ywcypxxq', '是')
this.$set(this.formData, 'isInterestedEntrepreneurshipGuidance', '是')
this.$set(this.formData, 'ywzjxq', '是')
}
// saveInfo() {
// this.$refs.uForm.validate().then(res => {
// if (this.formData.id) {
// updateEntrepreneurshipService(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '修改成功'
// })
// this.edit = false;
// }
// })
// } else {
// addEntrepreneurshipService(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '保存成功'
// })
// uni.navigateBack();
// }
// })
// }
// }).catch(() => {
// uni.showToast({
// title: '请检查必填项填写',
// icon: 'none'
// })
// })
// }
}
}
</script>
<style lang="scss">
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
</style>

View File

@@ -0,0 +1,724 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:00:51
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 200rpx)':'calc(100vh - 194rpx)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">求职需求信息
<view v-if="!edit&&formData.id&&formData.currentStatus!=3" class="btn"
style="font-weight: normal;display: flex;" @click="edit=true">编辑<u-icon name="edit-pen"
color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<uni-forms labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form" labelWidth="100">
<!-- v-if="$store.getters.roles.includes('shequn') || $store.getters.roles.includes('gly')" -->
<uni-forms-item label="姓名" name="personName" required
>
<view v-if="name" style="width: 100%;"
class="disabledLine">
{{ formData.personName || '请选择' }}
</view>
<view v-else style="width: 100%;" @click="openPersonChooser"
:class="{disabledLine: !edit||!canChoosePerson, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</uni-forms-item>
<uni-forms-item label="求职工种" name="jobWorkType">
<picker
mode="multiSelector"
:range="workTypeColumns"
range-key="workTypeName"
:value="workTypeIndexes"
@change="onWorkTypePickerChange"
@columnchange="onWorkTypeColumnChange"
v-if="workTypeColumns[0] && workTypeColumns[0].length"
>
<view class="picker-view">
<text>{{ formData.jobWorkTypeName || '请选择工种' }}</text>
<u-icon name="arrow-down" color="#999999"></u-icon>
</view>
</picker>
<view v-else class="picker-view">
<text>工种数据加载中...</text>
</view>
</uni-forms-item>
<uni-forms-item label="最低薪酬" name="minRecruitmentSalary" required>
<input :disabled="!edit" v-model="formData.minRecruitmentSalary" border="none"
placeholder="请输入"/>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</uni-forms-item>
<uni-forms-item label="最高薪酬" name="highRecruitmentSalary" required>
<input :disabled="!edit" v-model="formData.highRecruitmentSalary" border="none"
placeholder="请输入"/>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</uni-forms-item>
<uni-forms-item label="希望工作地点" name="addressDesc">
<view class="df_flex df_flex_1">
<input placeholder="请输入" border="none" v-model="formData.addressDesc"
class="ellipsis_1" @focus="$refs.placePicker.openDialog()"/>
</view>
</uni-forms-item>
<uni-forms labelPosition="left" class="self-form" labelWidth="110" >
<uni-forms-item label="求职说明" name="jobDescription" required >
<textarea :disabled="!edit" v-model="formData.jobDescription"
placeholder="请输入" ></textarea>
</uni-forms-item>
</uni-forms>
</uni-forms>
</view>
</view>
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
<!-- <view class="inner">
<view class="part-title" style="margin-top: 32rpx;">附件信息</view>
<view class="inner-part">
<u--form labelPosition="left" class="self-form" labelWidth="110">
<uni-forms-item label="附件" name="fileUrl">
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</uni-forms-item>
</u--form>
</view>
</view> -->
</scroll-view>
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<view class="btn reset" @click="getDetail(formData.id)">重置</view>
<view class="btn save" @click="saveInfo">保存</view>
</view>
<choose-person ref="personChooser" @confirm="personNameConfirm" />
<PlacePicker ref="placePicker" @selected="handleSelected" />
</view>
</template>
<script>
import {
getPersonBase
} from "@/apiRc/person";
import {
addPersonDemand,
updatePersonDemand,
getPersonDemand
} from "@/apiRc/needs/personDemand";
import {
listJobType
} from "@/apiRc/jobType/index";
import ImageUpload from '/packageRc/components/ImageUpload'
import ChoosePerson from '/packageRc/pages/needs/components/choosePerson';
import PlacePicker from "/packageRc/components/placePicker";
export default {
components: {
ChoosePerson,
ImageUpload,
PlacePicker,
},
props: {
needId: {
type: String,
default: ''
},
name: {
type: String,
default: ''
}
},
data() {
return {
edit: true,
personBase: {},
dates: {},
currentCommunityId: '',
showPickerPicker: false,
formData: {
demandType:"1",
personName: '',
personId:"",
userId:"",
jobWorkType: '',
jobWorkTypeName: '',
selectedWorkType: '',
selectedWorkTypeName: '',
highRecruitmentSalary: '',
minRecruitmentSalary: '',
employmentType: '',
currentCommunity: '',
addressDesc: '',
jobDescription: '',
// fileUrl: []
},
rules: {
personName: [{
required: true,
message: '请填写姓名',
trigger: ['blur', 'change'],
}],
jobWorkType: [{
required: true,
message: '请选择求职工种',
trigger: ['blur', 'change'],
validator: (rule, value) => {
return (Array.isArray(value) && value.length > 0) || (!!value);
}
}],
highRecruitmentSalary: [{
required: true,
message: '请选择最高薪酬',
trigger: ['blur', 'change'],
}, ],
minRecruitmentSalary: [{
required: true,
message: '请选择最低薪酬',
trigger: ['blur', 'change'],
}, ],
jobDescription: [{
required: true,
message: '请填写求职说明',
trigger: ['blur', 'change'],
}, ]
// employmentType: [{
// required: true,
// message: '请选择用工形式',
// trigger: ['blur', 'change'],
// }, ],
// addressDesc: [{
// required: true,
// message: '请选择希望工作地点',
// trigger: ['blur', 'change'],
// }, ],
},
dict: {
emplymentYear: [],
salaryType: [],
highRecruitmentSalary: [],
minRecruitmentSalary: [],
unitNature: [],
employmentWillingness: []
},
show: {
hopeSolveDate: false,
jobWorkType: false,
emplymentYear: false,
salaryType: false,
highRecruitmentSalary: false,
minRecruitmentSalary: false,
unitNature: false,
employmentType: false,
employmentWillingness: false
},
currentCity: '请选择',
bysj: '',
loading: false,
jobTypeList: [],
route: {},
canChoosePerson: false,
fileList: [],
workTypeList: [],
workTypeColumns: [[], [], []],
workTypeIndexes: [0, 0, 0],
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.loading = true;
let arr = [{
key: 'qcjy_gznx',
prop: 'emplymentYear'
},
{
key: 'qcjy_gzlx',
prop: 'salaryType'
},
{
key: 'qcjy_zgzpgz',
prop: 'highRecruitmentSalary'
},
{
key: 'qcjy_zgzpgz',
prop: 'minRecruitmentSalary'
},
{
key: 'qcjy_dwxz',
prop: 'unitNature'
},
// {
// key: 'qcjy_ygxs',
// prop: 'employmentType'
// },
{
key: 'qcjt_jyyy',
prop: 'employmentWillingness'
},
]
// 使用 Promise.all 确保所有字典数据加载完成
Promise.all(arr.map(ele => this.getDicts(ele.key)))
.then(responses => {
responses.forEach((res, index) => {
this.dict[arr[index].prop] = res.data || [];
});
this.loading = false;
})
.catch(error => {
console.error('加载字典数据失败:', error);
// 设置默认空数组
arr.forEach(ele => {
this.dict[ele.prop] = [];
});
this.loading = false;
});
this.workTypeRemoteMethod('');
},
methods: {
// 获取字典数据
getDicts(dictType) {
return new Promise((resolve, reject) => {
// 这里应该调用实际的API暂时返回空数组
// 如果需要真实的API调用请替换下面的代码
setTimeout(() => {
resolve({ data: [] });
}, 100);
});
},
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
openPersonChooser() {
if (this.edit && this.canChoosePerson) {
this.$refs.personChooser.open();
}
},
setName(){
this.formData.personName = this.name
this.formData.personId = this.needId
this.formData.userId = this.needId
},
personNameConfirm(event) {
this.formData.personName = event.name
this.formData.personId = event.id
this.formData.userId = event.userId
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.getPersonInfo()
if(this.name){
this.formData.personName = this.name
this.formData.userId = this.needId
}
this.edit = true
},
getDetail(id) {
getPersonDemand(id).then(res => {
this.formData = res.data;
// 设置工种索引(需要等工种数据加载完成后)
if (this.formData.jobWorkType && this.workTypeColumns[0].length) {
this.setWorkTypeIndexes(this.formData.jobWorkType);
}
this.currentCommunityId = +res.data.currentCommunity
this.formData.currentCommunity = res.data.currentCommunity
this.edit = false;
this.fileList = this.$processFileUrl(this.formData.fileUrl)
}).catch(error => {
console.error('Error fetching job detail:', error);
});
},
confirmDate(type, e) {
this.show[type] = false;
let date = new Date(e.value)
this.formData[type] =
`${date.getFullYear()}-${(date.getMonth()+1)>9?(date.getMonth()+1):('0'+(date.getMonth()+1))}-${date.getDate()>9?date.getDate():('0'+date.getDate())}`
},
workTypeRemoteMethod(key) {
listJobType({
workTypeName: key,
pageNum: 1,
pageSize: 50
}).then(
(res) => {
console.log('工种数据加载成功:', res.rows);
this.jobTypeList = res.rows;
// 处理树形数据为级联选择器格式
this.processWorkTypeTree(res.rows);
}
).catch(error => {
console.error('获取工种列表失败:', error);
this.workTypeList = [];
this.workTypeColumns = [[], [], []];
});
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
},
getCityOptions(data) {
if (data && data[0] && data[0].children) {
return [data].concat(this.getCityOptions(data[0].children))
} else {
return [data]
}
},
getDictLabel(value, list) {
if (list && Array.isArray(list)) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel || '请选择'
} else {
return '请选择'
}
}
return '请选择'
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
},
jobTypeConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].id
this.formData.jobWorkTypeName = event.value[0].workTypeName
},
showPicker(type) {
if (this.edit) {
if(type === 'workTypeTree') {
if (!this.workTypeTreeColumns[0] || !this.workTypeTreeColumns[0].length) {
uni.showToast({title: '工种数据未加载,请稍后重试'});
return;
}
// 弹窗打开时初始化临时columns和index
this.tempWorkTypeTreeColumns = JSON.parse(JSON.stringify(this.workTypeTreeColumns));
this.tempWorkTypeTreeIndex = [...this.workTypeTreeIndex];
}
this.show[type] = true;
}
},
getPersonInfo() {
this.loading = true;
this.$store.dispatch("GetInfo").then((res) => {
if (res.data.roles.indexOf('qunzhong') == -1) {
this.canChoosePerson = true;
} else {
this.canChoosePerson = false;
getPersonBase(res.data.user.userId).then(resp => {
this.formData.personId = resp.data.id
this.formData.userId = resp.data.userId
this.formData.personName = resp.data.name
})
}
})
},
async saveInfo() {
uni.showLoading();
try {
// 先检查求职说明是否为空,如果为空直接提示
if (!this.formData.jobDescription || this.formData.jobDescription.trim() === '') {
uni.showToast({title: '请填写求职说明!'});
return;
}
// 验证表单
console.log(this.formData)
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('表单验证失败');
}
// 显示全局加载
this.formData.demandType = 1;
// this.formData.userId = this.formData.personId
// 根据 formData 是否有 id 来决定是更新还是新增
let response;
let successMessage;
if (this.formData.id) {
response = await updatePersonDemand(this.formData);
successMessage = '修改成功';
} else {
response = await addPersonDemand(this.formData);
successMessage = '保存成功';
}
// 检查响应码是否为200
if (response.code === 200) {
uni.showToast({title: successMessage});
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
setTimeout(() => {
uni.navigateBack();
}, 2000);
}
}
} catch (error) {
if(error.length){
uni.showToast({title: '请填写完整信息!'});
}else{
uni.showToast({title: '系统错误,请联系管理员!'});
}
// uni.showToast({title: '请检查必填项填写'});
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
},
popupclosed() {
this.showPickerPicker = false
},
onChange(e) {
const arr = e.detail.value
this.formData.currentCity = arr[0].value || "";
this.formData.currentArea = arr[1].value || "";
this.formData.currentStreet = arr[2].value || "";
this.formData.currentCommunity = arr[3].value + '' || "";
this.$forceUpdate();
},
// 接收地图数据
handleSelected(marker) {
this.$set(this.formData, "addressDesc", marker.address);
this.$set(this.formData, "latitude", marker.location.lat);
this.$set(this.formData, "longitude", marker.location.lng);
},
// 处理树形数据为级联选择器格式
processWorkTypeTree(treeData) {
if (!treeData || !Array.isArray(treeData)) {
this.workTypeColumns = [[], [], []];
return;
}
// 第一级
const level1 = treeData.filter(item => item.level === "1");
// 第二级
const level2 = treeData.filter(item => item.level === "2");
// 第三级
const level3 = treeData.filter(item => item.level === "3");
// 构建级联数据
const columns = [];
columns[0] = level1;
// 根据第一级选择,过滤第二级
if (level1.length > 0) {
const firstLevelId = level1[0].id;
columns[1] = level2.filter(item => item.parentId === firstLevelId);
} else {
columns[1] = [];
}
// 根据第二级选择,过滤第三级
if (columns[1].length > 0) {
const secondLevelId = columns[1][0].id;
columns[2] = level3.filter(item => item.parentId === secondLevelId);
} else {
columns[2] = [];
}
this.workTypeColumns = columns;
console.log('级联数据构建完成:', this.workTypeColumns);
},
// 级联选择器列变化事件
onWorkTypeColumnChange(e) {
const { column, value } = e.detail;
const newIndexes = [...this.workTypeIndexes];
newIndexes[column] = value;
// 重置后续列的数据
if (column === 0) {
// 第一列变化,重置第二、三列
const selectedLevel1 = this.workTypeColumns[0][value];
if (selectedLevel1) {
const level2 = this.jobTypeList.filter(item =>
item.level === "2" && item.parentId === selectedLevel1.id
);
this.workTypeColumns[1] = level2;
this.workTypeColumns[2] = [];
newIndexes[1] = 0;
newIndexes[2] = 0;
}
} else if (column === 1) {
// 第二列变化,重置第三列
const selectedLevel2 = this.workTypeColumns[1][value];
if (selectedLevel2) {
const level3 = this.jobTypeList.filter(item =>
item.level === "3" && item.parentId === selectedLevel2.id
);
this.workTypeColumns[2] = level3;
newIndexes[2] = 0;
}
}
this.workTypeIndexes = newIndexes;
},
// 级联选择器确认事件
onWorkTypePickerChange(e) {
const indexes = e.detail.value;
const selectedLevel1 = this.workTypeColumns[0][indexes[0]];
const selectedLevel2 = this.workTypeColumns[1][indexes[1]];
const selectedLevel3 = this.workTypeColumns[2][indexes[2]];
if (selectedLevel3) {
// 选择第三级
this.formData.jobWorkType = selectedLevel3.id;
this.formData.jobWorkTypeName = `${selectedLevel1.workTypeName}/${selectedLevel2.workTypeName}/${selectedLevel3.workTypeName}`;
} else if (selectedLevel2) {
// 选择第二级
this.formData.jobWorkType = selectedLevel2.id;
this.formData.jobWorkTypeName = `${selectedLevel1.workTypeName}/${selectedLevel2.workTypeName}`;
} else if (selectedLevel1) {
// 选择第一级
this.formData.jobWorkType = selectedLevel1.id;
this.formData.jobWorkTypeName = selectedLevel1.workTypeName;
}
this.workTypeIndexes = indexes;
},
// 根据工种ID设置索引
setWorkTypeIndexes(workTypeId) {
// 在工种列表中查找对应的工种
const targetWorkType = this.jobTypeList.find(item => item.id == workTypeId);
if (!targetWorkType) return;
// 根据level确定是哪一级
if (targetWorkType.level === "1") {
const index = this.workTypeColumns[0].findIndex(item => item.id == workTypeId);
if (index !== -1) {
this.workTypeIndexes = [index, 0, 0];
}
} else if (targetWorkType.level === "2") {
// 需要先找到父级
const parent = this.jobTypeList.find(item => item.id == targetWorkType.parentId);
if (parent) {
const parentIndex = this.workTypeColumns[0].findIndex(item => item.id == parent.id);
const childIndex = this.workTypeColumns[1].findIndex(item => item.id == workTypeId);
if (parentIndex !== -1 && childIndex !== -1) {
this.workTypeIndexes = [parentIndex, childIndex, 0];
}
}
} else if (targetWorkType.level === "3") {
// 需要找到祖父级和父级
const parent = this.jobTypeList.find(item => item.id == targetWorkType.parentId);
const grandparent = this.jobTypeList.find(item => item.id == parent.parentId);
if (parent && grandparent) {
const grandparentIndex = this.workTypeColumns[0].findIndex(item => item.id == grandparent.id);
const parentIndex = this.workTypeColumns[1].findIndex(item => item.id == parent.id);
const childIndex = this.workTypeColumns[2].findIndex(item => item.id == workTypeId);
if (grandparentIndex !== -1 && parentIndex !== -1 && childIndex !== -1) {
this.workTypeIndexes = [grandparentIndex, parentIndex, childIndex];
}
}
}
}
}
}
</script>
<style lang="scss">
/* 为表单元素添加一些间距 */
.self-form {
width: 100%;
}
.noValue {
font-size: 28rpx;
color: #333;
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
.picker-view {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 28rpx 36rpx;
background: #ffffff;
border: 2rpx solid #e5e5e5;
border-radius: 12rpx;
min-height: 88rpx;
box-sizing: border-box;
transition: all 0.3s ease;
}
.picker-view:active {
background: #f8f9fa;
border-color: #007aff;
}
.picker-view text {
color: #333333;
font-size: 28rpx;
flex: 1;
}
.picker-view .u-icon {
margin-left: 16rpx;
color: #999999;
}
::v-deep .u-textarea{
background-color: red !important;
border-radius: 12rpx;
border: 2rpx solid red;
}
</style>

View File

@@ -0,0 +1,335 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:16:26
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 200rpx)':'calc(100vh - 194rpx)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">需求信息
<view v-if="!edit&&formData.id&&formData.currentStatus!=3" class="btn"
style="font-weight: normal;display: flex;" @click="edit=true">编辑<u-icon name="edit-pen"
color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<uni-forms labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form"
labelWidth="100">
<u-form-item label="姓名" prop="personName" required
v-if="$store.getters.roles.includes('shequn')|| $store.getters.roles.includes('gly')">
<view style="width: 100%;" @click="openPersonChooser"
:class="{disabledLine: !edit||!canChoosePerson, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="需求说明" prop="jobDescription" required>
<u-textarea :disabled="!edit" v-model="formData.jobDescription" placeholder="请输入"></u-textarea>
</u-form-item>
</uni-forms>
</view>
</view>
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
</scroll-view>
<u-datetime-picker :show="show.hopeSolveDate" v-model="dates.hopeSolveDate" mode="date"
@confirm="confirmDate('hopeSolveDate', $event)" @cancel="cancelPicker('hopeSolveDate')"></u-datetime-picker>
<choose-person ref="personChooser" @confirm="personNameConfirm" />
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<view class="btn reset" @click="getDetail(formData.id)">重置</view>
<view class="btn save" @click="saveInfo">保存</view>
</view>
</view>
</template>
<script>
import {
getPersonBase
} from "@/apiRc/person";
import {
addPersonDemand,
updatePersonDemand,
getPersonDemand
} from "@/apiRc/needs/personDemand";
import ImageUpload from '/packageRc/components/ImageUpload'
import ChoosePerson from '/packageRc/pages/needs/components/choosePerson';
import {
listJobType
} from "@/apiRc/jobType/index";
import dayjs from "dayjs";
export default {
components: {
ChoosePerson,
ImageUpload
},
props: {
needId: {
type: String,
default: ''
},
name: {
type: String,
default: ''
}
},
data() {
return {
fileList: [],
edit: true,
personBase: {},
dates: {},
formData: {
isAcceptAssistance: '',
isAcceptApprovalResult: '',
qtxqsm: ''
},
rules: {
personName: [{
required: true,
message: '请填写姓名',
trigger: ['blur', 'change'],
}, ],
qtxqsm: [{
required: true,
message: '请填写需求说明',
trigger: ['blur', 'change'],
}, ],
},
dict: {},
show: {},
currentCityArr: [],
originalDept: [],
currentCity: '请选择',
bysj: '',
loading: false,
jobTypeList: [],
route: {},
canChoosePerson: false,
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.loading = true;
},
methods: {
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
workTypeRemoteMethod(key) {
listJobType({
workTypeName: key,
pageNum: 1,
pageSize: 50
}).then(
(res) => {
this.jobTypeList = res.rows;
}
);
},
openPersonChooser() {
if (this.edit && this.canChoosePerson) {
this.$refs.personChooser.open();
}
},
personNameConfirm(event) {
this.formData.personName = event.name
this.formData.personId = event.id
this.formData.userId = event.userId
this.formNameChange();
this.$forceUpdate();
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.getPersonInfo()
if(this.name){
this.formData.personName = this.name
this.formData.userId = this.needid
}
this.edit = true
},
getDetail(id) {
getPersonDemand(id).then(res => {
this.formData = res.data;
this.edit = false
this.fileList = this.$processFileUrl(this.formData.fileUrl)
})
},
confirmDate(type, e) {
this.show[type] = false;
let date = new Date(e.value)
this.formData[type] =
`${date.getFullYear()}-${(date.getMonth()+1)>9?(date.getMonth()+1):('0'+(date.getMonth()+1))}-${date.getDate()>9?date.getDate():('0'+date.getDate())}`
this.$forceUpdate();
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
this.$forceUpdate();
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
this.$forceUpdate();
},
showPicker(type) {
if (this.edit) {
this.show[type] = true
this.$forceUpdate()
}
},
getPersonInfo() {
this.loading = true;
this.$store.dispatch("GetInfo").then((res) => {
if (res.data.roles.indexOf('qunzhong') == -1) {
this.canChoosePerson = true;
} else {
this.canChoosePerson = false;
getPersonBase(res.data.user.userId).then(resp => {
this.formData.personId = resp.data.id
this.formData.userId = resp.data.userId
this.formData.personName = resp.data.name
this.formNameChange();
this.$forceUpdate();
})
}
})
},
formNameChange() {
let date = new Date()
let day =
`${date.getFullYear()}-${(date.getMonth()+1) + 1 > 9 ? (date.getMonth()+1) + 1: '0'+((date.getMonth()+1) + 1)}-${date.getDate() > 9 ? date.getDate(): '0'+date.getDate()}`
const dayNew = dayjs(date).format("YYYY-MM-DD");
this.formData.demandTitle = `${this.formData.personName}_于${dayNew}_提出其他需求`
},
async saveInfo() {
uni.showLoading();
try {
// 验证表单
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('请检查必填项填写');
}
// 显示全局加载
// 根据 formData 是否有 id 来决定是更新还是新增
let response;
let successMessage;
this.formData.demandType = 9;
// this.formData.userId = this.formData.personId
if (this.formData.id) {
response = await updatePersonDemand(this.formData);
successMessage = '修改成功';
} else {
response = await addPersonDemand(this.formData);
successMessage = '保存成功';
}
// 检查响应码是否为200
if (response.code === 200) {
this.$u.toast(successMessage);
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
await this.$delay(1000); // 延迟1秒后返回上一页
uni.navigateBack();
}
} else {
throw new Error('服务器响应错误');
}
} catch (error) {
if(error.length){
this.$u.toast('请填写完整信息!');
}else{
this.$u.toast('系统错误,请联系管理员!');
}
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
}
// saveInfo() {
// this.$refs.uForm.validate().then(res => {
// if (this.formData.id) {
// updatePersonDemand(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '修改成功'
// })
// this.edit = false;
// }
// })
// } else {
// addPersonDemand(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '保存成功'
// })
// uni.navigateBack();
// }
// })
// }
// }).catch(() => {
// uni.showToast({
// title: '请检查必填项填写',
// icon: 'none'
// })
// })
// }
}
}
</script>
<style lang="scss">
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
</style>

View File

@@ -0,0 +1,590 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:29:43
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 200rpx)':'calc(100vh - 194rpx)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">培训需求信息
<view v-if="!edit&&formData.id&&formData.currentStatus!=3" class="btn"
style="font-weight: normal;display: flex;" @click="edit=true">编辑<u-icon name="edit-pen"
color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<uni-forms labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form"
labelWidth="120">
<uni-forms-item label="姓名" prop="personName" required
v-if="$store.getters.roles.includes('shequn'|| $store.getters.roles.includes('gly'))">
<view style="width: 100%;" @click="openPersonChooser"
:class="{disabledLine: !edit||!canChoosePerson, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</uni-forms-item>
<uni-forms-item label="培训意愿工种" prop="qwpxgz" required>
<picker
mode="multiSelector"
:range="workTypeColumns"
range-key="workTypeName"
:value="workTypeIndexes"
@change="onWorkTypePickerChange"
@columnchange="onWorkTypeColumnChange"
v-if="workTypeColumns[0] && workTypeColumns[0].length"
>
<view class="picker-view">
<text>{{ formData.qwpxgzName || '请选择工种' }}</text>
<u-icon name="arrow-down" color="#999999"></u-icon>
</view>
</picker>
<view v-else class="picker-view">
<text>工种数据加载中...</text>
</view>
</uni-forms-item>
<uni-forms-item label="期望培训时间" prop="qwpxsj" required>
<view class="bordered" style="width: 100%" @click="showTime = true"
:class="{ noValue: !formData.qwpxsj }">
{{ formData.qwpxsj || "请选择" }}</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</uni-forms-item>
</uni-forms>
<uni-forms labelPosition="left" class="self-form" labelWidth="110">
<uni-forms-item label="需求说明" prop="jobDescription">
<u-textarea :disabled="!edit" v-model="formData.jobDescription" placeholder="请输入"></u-textarea>
</uni-forms-item>
</uni-forms>
</view>
</view>
<!-- <view class="inner">
<view class="part-title" style="margin-top: 32rpx;">附件信息</view>
<view class="inner-part">
<uni-forms labelPosition="left" class="self-form" labelWidth="110">
<uni-forms-item label="附件" prop="fileUrl">
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</uni-forms-item>
</uni-forms>
</view>
</view> -->
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
</scroll-view>
<u-datetime-picker :show="show.qwpxsj" v-model="dates.qwpxsj" mode="date"
@confirm="confirmDate('qwpxsj', $event)" @cancel="cancelPicker('qwpxsj')"></u-datetime-picker>
<u-picker :show="show.qwpxgz" :columns="[jobTypeList]" keyName="workTypeName"
@confirm="jobTypeConfirm('qwpxgz', $event)" @cancel="cancelPicker('qwpxgz')"></u-picker>
<choose-person ref="personChooser" @confirm="personNameConfirm" />
<u-datetime-picker style="position: relative; z-index: 100" :show="showTime" v-model="hopeSolveDate"
mode="datetime" closeOnClickOverlay @confirm="confirmDate" @cancel="showTime = false"
@close="showTime = false"></u-datetime-picker>
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<view class="btn reset" @click="getDetail(formData.id)">重置</view>
<view class="btn save" @click="saveInfo">保存</view>
</view>
</view>
</template>
<script>
import {
getPersonBase
} from "@/apiRc/person";
import {
addPersonDemand,
updatePersonDemand,
getPersonDemand
} from "@/apiRc/needs/personDemand";
import {
listJobType
} from "@/apiRc/jobType/index";
import ImageUpload from '/packageRc/components/ImageUpload'
import ChoosePerson from '/packageRc/pages/needs/components/choosePerson';
import dayjs from "dayjs";
export default {
components: {
ChoosePerson,
ImageUpload
},
props: {
needId: {
type: String,
default: ''
},
name: {
type: String,
default: ''
}
},
data() {
return {
fileList: [],
edit: true,
showTime: false,
personBase: {},
hopeSolveDate: Number(new Date()),
dates: {},
formData: {
demandType: "3",
personName: '',
personId: "",
userId: "",
demandTitle: '',
isAcceptAssistance: '',
isAcceptApprovalResult: '',
personName: '',
qwpxsj: '',
qwpxgz: '',
qwpxgzName: ''
},
rules: {
personName: [{
required: true,
message: '请填写姓名',
trigger: ['blur', 'change'],
}, ],
qwpxgz: [{
required: true,
message: '请选择培训意愿工种',
trigger: ['blur', 'change'],
validator: (rule, value) => {
// 允许数组且有值,或字符串有值
return (Array.isArray(value) && value.length > 0) || (!!value);
}
}, ],
qwpxsj: [{
required: true,
message: '请选择期望培训时间',
trigger: ['blur', 'change'],
}, ],
},
dict: {},
show: {},
currentCityArr: [],
originalDept: [],
currentCity: '请选择',
bysj: '',
loading: false,
jobTypeList: [],
route: {},
canChoosePerson: false,
workTypeTreeList: [],
searchKeyword: '',
workTypeList: [],
workTypeColumns: [[], [], []],
workTypeIndexes: [0, 0, 0],
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.loading = true;
this.workTypeRemoteMethod('');
},
methods: {
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
openPersonChooser() {
if (this.edit && this.canChoosePerson) {
this.$refs.personChooser.open();
}
},
personNameConfirm(event) {
this.formData.personName = event.name
this.formData.personId = event.id
this.formData.userId = event.userId
this.formNameChange();
this.$forceUpdate();
},
confirmDate(e) {
this.showTime = false;
// 获取选中的日期
const date = e.value;
// 使用 uView 的 uTime 方法格式化日期,包含时分秒
const formattedDateTime = uni.$u.timeFormat(date, "yyyy-mm-dd");
// 设置表单数据
this.formData.qwpxsj = formattedDateTime;
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.getPersonInfo()
if(this.name){
this.formData.personName = this.name
this.formData.userId = this.needid
}
this.edit = true
},
workTypeRemoteMethod(key) {
listJobType({
workTypeName: key,
pageNum: 1,
pageSize: 50
}).then(
(res) => {
console.log('工种数据加载成功:', res.rows);
this.jobTypeList = res.rows;
// 处理树形数据为级联选择器格式
this.processWorkTypeTree(res.rows);
}
).catch(error => {
console.error('获取工种列表失败:', error);
this.workTypeList = [];
this.workTypeColumns = [[], [], []];
});
},
jobTypeConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].id
this.formData.qwpxgzName = event.value[0].workTypeName
this.$forceUpdate();
},
getDetail(id) {
getPersonDemand(id).then(res => {
this.formData = res.data;
// 设置工种索引(需要等工种数据加载完成后)
if (this.formData.qwpxgz && this.workTypeColumns[0].length) {
this.setWorkTypeIndexes(this.formData.qwpxgz);
}
this.edit = false;
this.fileList = this.$processFileUrl(this.formData.fileUrl)
}).catch(error => {
console.error('Error fetching training detail:', error);
});
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.$set(this.show, type, false)
this.$forceUpdate()
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
this.$forceUpdate();
},
showPicker(type) {
if (this.edit) {
this.show[type] = true
this.$forceUpdate()
}
},
getPersonInfo() {
this.loading = true;
this.$store.dispatch("GetInfo").then((res) => {
if (res.data.roles.indexOf('qunzhong') == -1) {
this.canChoosePerson = true;
} else {
this.canChoosePerson = false;
getPersonBase(res.data.user.userId).then(resp => {
this.formData.personId = resp.data.id
this.formData.userId = resp.data.userId
this.formData.personName = resp.data.name
this.formNameChange();
this.$forceUpdate();
})
}
})
},
formNameChange() {
let date = new Date()
const dayNew = dayjs(date).format("YYYY-MM-DD");
this.formData.demandTitle = `${this.formData.personName}_于${dayNew}_提出培训需求`
},
async saveInfo() {
uni.showLoading();
try {
// 手动检查培训意愿工种是否已选择
if (!this.formData.qwpxgz || this.formData.qwpxgz.trim() === '') {
this.$u.toast('请选择培训意愿工种!');
return;
}
// 手动检查期望培训时间是否已选择
if (!this.formData.qwpxsj || this.formData.qwpxsj.trim() === '') {
this.$u.toast('请选择期望培训时间!');
return;
}
// 验证表单
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('请检查必填项填写');
return
}
let response;
let successMessage;
this.formData.demandType = 3;
if (this.formData.id) {
response = await updatePersonDemand(this.formData);
successMessage = '修改成功';
} else {
response = await addPersonDemand(this.formData);
successMessage = '保存成功';
}
// 检查响应码是否为200
if (response.code === 200) {
this.$u.toast(successMessage);
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
await this.$delay(1000); // 延迟1秒后返回上一页
uni.navigateBack();
}
}
} catch (error) {
if(error.length){
this.$u.toast('请填写完整信息!');
}else{
this.$u.toast('系统错误,请联系管理员!');
}
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
},
// getWorkTypeTree() {
// listJobType({
// workTypeName: '',
// pageNum: 1,
// pageSize: 9999
// }).then(res => {
// console.log("11111",this.workTypeTreeList)
// this.workTypeTreeList = Array.isArray(res.rows) ? res.rows : [];
// });
// },
// 处理树形数据为级联选择器格式
processWorkTypeTree(treeData) {
if (!treeData || !Array.isArray(treeData)) {
this.workTypeColumns = [[], [], []];
return;
}
// 第一级
const level1 = treeData.filter(item => item.level === "1");
// 第二级
const level2 = treeData.filter(item => item.level === "2");
// 第三级
const level3 = treeData.filter(item => item.level === "3");
// 构建级联数据
const columns = [];
columns[0] = level1;
// 根据第一级选择,过滤第二级
if (level1.length > 0) {
const firstLevelId = level1[0].id;
columns[1] = level2.filter(item => item.parentId === firstLevelId);
} else {
columns[1] = [];
}
// 根据第二级选择,过滤第三级
if (columns[1].length > 0) {
const secondLevelId = columns[1][0].id;
columns[2] = level3.filter(item => item.parentId === secondLevelId);
} else {
columns[2] = [];
}
this.workTypeColumns = columns;
console.log('级联数据构建完成:', this.workTypeColumns);
},
// 级联选择器列变化事件
onWorkTypeColumnChange(e) {
const { column, value } = e.detail;
const newIndexes = [...this.workTypeIndexes];
newIndexes[column] = value;
// 重置后续列的数据
if (column === 0) {
// 第一列变化,重置第二、三列
const selectedLevel1 = this.workTypeColumns[0][value];
if (selectedLevel1) {
const level2 = this.jobTypeList.filter(item =>
item.level === "2" && item.parentId === selectedLevel1.id
);
this.workTypeColumns[1] = level2;
this.workTypeColumns[2] = [];
newIndexes[1] = 0;
newIndexes[2] = 0;
}
} else if (column === 1) {
// 第二列变化,重置第三列
const selectedLevel2 = this.workTypeColumns[1][value];
if (selectedLevel2) {
const level3 = this.jobTypeList.filter(item =>
item.level === "3" && item.parentId === selectedLevel2.id
);
this.workTypeColumns[2] = level3;
newIndexes[2] = 0;
}
}
this.workTypeIndexes = newIndexes;
},
// 级联选择器确认事件
onWorkTypePickerChange(e) {
const indexes = e.detail.value;
const selectedLevel1 = this.workTypeColumns[0][indexes[0]];
const selectedLevel2 = this.workTypeColumns[1][indexes[1]];
const selectedLevel3 = this.workTypeColumns[2][indexes[2]];
// 使用$set确保响应式更新
if (selectedLevel3) {
// 选择第三级
this.$set(this.formData, 'qwpxgz', selectedLevel3.id);
this.$set(this.formData, 'qwpxgzName', `${selectedLevel1.workTypeName}/${selectedLevel2.workTypeName}/${selectedLevel3.workTypeName}`);
} else if (selectedLevel2) {
// 选择第二级
this.$set(this.formData, 'qwpxgz', selectedLevel2.id);
this.$set(this.formData, 'qwpxgzName', `${selectedLevel1.workTypeName}/${selectedLevel2.workTypeName}`);
} else if (selectedLevel1) {
// 选择第一级
this.$set(this.formData, 'qwpxgz', selectedLevel1.id);
this.$set(this.formData, 'qwpxgzName', selectedLevel1.workTypeName);
}
this.workTypeIndexes = indexes;
// 强制重新渲染组件
this.$forceUpdate();
},
// 根据工种ID设置索引
setWorkTypeIndexes(workTypeId) {
// 在工种列表中查找对应的工种
const targetWorkType = this.jobTypeList.find(item => item.id == workTypeId);
if (!targetWorkType) return;
// 根据level确定是哪一级
if (targetWorkType.level === "1") {
const index = this.workTypeColumns[0].findIndex(item => item.id == workTypeId);
if (index !== -1) {
this.workTypeIndexes = [index, 0, 0];
}
} else if (targetWorkType.level === "2") {
// 需要先找到父级
const parent = this.jobTypeList.find(item => item.id == targetWorkType.parentId);
if (parent) {
const parentIndex = this.workTypeColumns[0].findIndex(item => item.id == parent.id);
const childIndex = this.workTypeColumns[1].findIndex(item => item.id == workTypeId);
if (parentIndex !== -1 && childIndex !== -1) {
this.workTypeIndexes = [parentIndex, childIndex, 0];
}
}
} else if (targetWorkType.level === "3") {
// 需要找到祖父级和父级
const parent = this.jobTypeList.find(item => item.id == targetWorkType.parentId);
const grandparent = this.jobTypeList.find(item => item.id == parent.parentId);
if (parent && grandparent) {
const grandparentIndex = this.workTypeColumns[0].findIndex(item => item.id == grandparent.id);
const parentIndex = this.workTypeColumns[1].findIndex(item => item.id == parent.id);
const childIndex = this.workTypeColumns[2].findIndex(item => item.id == workTypeId);
if (grandparentIndex !== -1 && parentIndex !== -1 && childIndex !== -1) {
this.workTypeIndexes = [grandparentIndex, parentIndex, childIndex];
}
}
}
},
}
}
</script>
<style lang="scss">
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
.bordered {
border: 1rpx solid #dadbde;
padding: 9px;
border-radius: 4px;
}
.picker-view {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 28rpx 36rpx;
background: #ffffff;
border: 2rpx solid #e5e5e5;
border-radius: 12rpx;
min-height: 88rpx;
box-sizing: border-box;
transition: all 0.3s ease;
}
.picker-view:active {
background: #f8f9fa;
border-color: #007aff;
}
.picker-view text {
color: #333333;
font-size: 28rpx;
flex: 1;
}
.picker-view .u-icon {
margin-left: 16rpx;
color: #999999;
}
</style>

View File

@@ -0,0 +1,59 @@
export default {
props: {
// 内置图标名称,或图片路径,建议绝对路径
icon: {
type: String,
default: uni.$u.props.empty.icon
},
// 提示文字
text: {
type: String,
default: uni.$u.props.empty.text
},
// 文字颜色
textColor: {
type: String,
default: uni.$u.props.empty.textColor
},
// 文字大小
textSize: {
type: [String, Number],
default: uni.$u.props.empty.textSize
},
// 图标的颜色
iconColor: {
type: String,
default: uni.$u.props.empty.iconColor
},
// 图标的大小
iconSize: {
type: [String, Number],
default: uni.$u.props.empty.iconSize
},
// 选择预置的图标类型
mode: {
type: String,
default: uni.$u.props.empty.mode
},
// 图标宽度单位px
width: {
type: [String, Number],
default: uni.$u.props.empty.width
},
// 图标高度单位px
height: {
type: [String, Number],
default: uni.$u.props.empty.height
},
// 是否显示组件
show: {
type: Boolean,
default: uni.$u.props.empty.show
},
// 组件距离上一个元素之间的距离默认px单位
marginTop: {
type: [String, Number],
default: uni.$u.props.empty.marginTop
}
}
}

View File

@@ -0,0 +1,128 @@
<template>
<view
class="u-empty"
:style="[emptyStyle]"
v-if="show"
>
<u-icon
v-if="!isSrc"
:name="mode === 'message' ? 'chat' : `empty-${mode}`"
:size="iconSize"
:color="iconColor"
margin-top="14"
></u-icon>
<image
v-else
:style="{
width: $u.addUnit(width),
height: $u.addUnit(height),
}"
:src="icon"
mode="widthFix"
></image>
<text
class="u-empty__text"
:style="[textStyle]"
>{{text ? text : icons[mode]}}</text>
<view class="u-empty__wrap" v-if="$slots.default || $slots.$default">
<slot />
</view>
</view>
</template>
<script>
import props from './props.js';
/**
* empty 内容为空
* @description 该组件用于需要加载内容,但是加载的第一页数据就为空,提示一个"没有内容"的场景, 我们精心挑选了十几个场景的图标,方便您使用。
* @tutorial https://www.uviewui.com/components/empty.html
* @property {String} icon 内置图标名称,或图片路径,建议绝对路径
* @property {String} text 提示文字
* @property {String} textColor 文字颜色 (默认 '#c0c4cc' )
* @property {String | Number} textSize 文字大小 (默认 14
* @property {String} iconColor 图标的颜色 (默认 '#c0c4cc'
* @property {String | Number} iconSize 图标的大小 (默认 90
* @property {String} mode 选择预置的图标类型 (默认 'data'
* @property {String | Number} width 图标宽度单位px (默认 160
* @property {String | Number} height 图标高度单位px (默认 160
* @property {Boolean} show 是否显示组件 (默认 true
* @property {String | Number} marginTop 组件距离上一个元素之间的距离默认px单位 (默认 0
* @property {Object} customStyle 定义需要用到的外部样式
*
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
* @example <u-empty text="所谓伊人,在水一方" mode="list"></u-empty>
*/
export default {
name: "u-empty",
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
icons: {
car: '购物车为空',
page: '页面不存在',
search: '没有搜索结果',
address: '没有收货地址',
wifi: '没有WiFi',
order: '订单为空',
coupon: '没有优惠券',
favor: '暂无收藏',
permission: '无权限',
history: '无历史记录',
news: '无新闻列表',
message: '消息列表为空',
list: '列表为空',
data: '数据为空',
comment: '暂无评论',
}
}
},
computed: {
// 组件样式
emptyStyle() {
const style = {}
style.marginTop = uni.$u.addUnit(this.marginTop)
// 合并customStyle样式此参数通过mixin中的props传递
return uni.$u.deepMerge(uni.$u.addStyle(this.customStyle), style)
},
// 文本样式
textStyle() {
const style = {}
style.color = this.textColor
style.fontSize = uni.$u.addUnit(this.textSize)
return style
},
// 判断icon是否图片路径
isSrc() {
return this.icon.indexOf('/') >= 0
}
}
}
</script>
<style lang="scss" scoped>
@import '@/uni_modules/uview-ui/libs/css/components.scss';
$u-empty-text-margin-top:20rpx !default;
$u-empty-slot-margin-top:20rpx !default;
.u-empty {
@include flex;
flex-direction: column;
justify-content: center;
align-items: center;
&__text {
@include flex;
justify-content: center;
align-items: center;
margin-top: $u-empty-text-margin-top;
}
}
.u-slot-wrap {
@include flex;
justify-content: center;
align-items: center;
margin-top:$u-empty-slot-margin-top;
}
</style>

View File

@@ -0,0 +1,182 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:04:39
-->
<template>
<view class="page" style="background-image: url('../../../packageRc/static/pageBg.png');">
<!-- 需求新增 -->
<view class="tab-list" v-if="showTab != 1">
<view class="tab" :class="{active: activeType == 1}" @click="canChangeType ? changeType(1) : ''">求职<br>需求
</view>
<view class="tab" :class="{active: activeType == 3}" @click="canChangeType ? changeType(3) : ''">创业<br>需求
</view>
<view class="tab" :class="{active: activeType == 4}" @click="canChangeType ? changeType(4) : ''">培训<br>需求
</view>
<view class="tab" :class="{active: activeType == 5}" @click="canChangeType ? changeType(5) : ''">其他<br>需求
</view>
</view>
<jobService v-if="activeType == 1" :needId="id" :name="name" ref="type1" />
<entrepreneurshipService :needId="id" :name="name" v-if="activeType == 3" ref="type3" />
<trainService v-if="activeType == 4" :needId="id" :name="name" ref="type4" />
<otherService v-if="activeType == 5" :needId="id" :name="name" ref="type5" />
<!-- 社区端 - 显示隐藏退出组件 -->
<exitPopup />
</view>
</template>
<script>
import jobService from './components/jobService.vue';
import entrepreneurshipService from './components/entrepreneurshipService.vue';
import trainService from './components/trainService.vue';
import otherService from './components/otherService.vue';
export default {
components: {
jobService,
entrepreneurshipService,
trainService,
otherService,
},
data() {
return {
isAdd: true,
activeType: 1,
canChangeType: true,
id: '',
name:"",
}
},
onLoad(options) {
this.showTab = options.showTab
this.id = options.id
this.name = options.name
if (options.id && options.type) {
this.isAdd = false
this.activeType = options.type
this.canChangeType = false;
this.$nextTick(() => {
this.$refs['type' + options.type].getDetail(options.id)
})
} else {
// 添加需求的时候根据传入的类型 判断对应的表单
this.changeType(options.activeType || 1)
}
},
methods: {
changeType(type) {
this.activeType = type
this.$nextTick(() => {
this.$refs['type' + type].addOne()
})
},
goBack() {
uni.navigateBack();
},
}
}
</script>
<style lang="scss">
@import "/packageRc/static/scss/index.scss";
.page {
background-color: #f4f4f4 !important;
height: 100vh;
background-repeat: no-repeat;
padding-top: 32rpx;
background-size: 100% auto;
}
.button-area {
padding: 24rpx 32rpx 68rpx;
background: #fff;
display: flex;
box-sizing: border-box;
margin-top: 40rpx;
border-radius: 16px 16px 0px 0px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
.tab-list {
display: flex;
width: calc(100% - 64rpx);
margin: 16rpx auto 30rpx;
text-align: center;
border-radius: 16rpx;
background: #fff;
;
.tab {
width: 25%;
display: flex;
align-items: center;
justify-content: center;
border: 4rpx solid #FFFFFF;
background: #fff;
border-radius: 16rpx;
font-size: 28rpx;
color: #878787;
height: 106rpx;
&.active {
background: #1A62CE;
color: #fff;
position: relative;
font-weight: bold;
&::before {
content: '';
position: absolute;
bottom: -13rpx;
border-top: 14rpx solid #1A62CE;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
left: calc(50% - 7rpx);
z-index: 2;
}
&::after {
content: '';
position: absolute;
z-index: 1;
bottom: -18rpx;
border-top: 14rpx solid #fff;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
left: calc(50% - 7rpx);
}
}
}
}
</style>

View File

@@ -0,0 +1,781 @@
<template>
<view class="page">
<view class="page-header">
<view class="title df_flex" style="text-align: left;padding:50rpx 32rpx;">
<u-icon name="arrow-left" color="#fff" size="38rpx" @tap="$tab.navigateBack()"></u-icon>
<text style="margin-left: 30rpx;" class="df_flex_1">需求列表</text>
<u-icon v-show="$store.getters.roles.includes('shequn')" @tap="$store.commit('SET_SHOWEXITPOPUP', true)" name="list" size="44rpx" color="#fff"></u-icon>
</view>
</view>
<view class="input-outer-part"
style="padding-top: 12rpx;margin-top: 16rpx;padding-bottom: 0;max-height: unset;">
<view class="search-line">
<u-input placeholder="请输入群众姓名进行搜索" v-model="queryParams.searchValue" border="none" />
<img src="https://rc.jinan.gov.cn/qcwjyH5/static/images/person/search.png" class="search-icon" @click="search()" />
</view>
<view class="inner"
style="width: calc(100% + 64rpx);margin-left: -32rpx;height: 122rpx;position: relative;z-index: 2;">
<PopupList :checkData="checkData" @searchCheck="search" ref="PopupList" @popupSearch="popupSearch" />
</view>
<view v-if="total" style="position: relative;padding-bottom: 16px;color: #000;">
<text> {{ total }} </text>
</view>
<scroll-view :scroll-y="true" style="height: calc(100vh - 422rpx);position: relative;z-index: 1;"
@scrolltolower="getBottomList">
<u-swipe-action>
<u-swipe-action-item @click="clickDelete(item)" v-for="(item, index) in tableData" :key="index"
style="margin-bottom: 24rpx;border-radius: 16rpx;" :options="options1">
<view class="job-item">
<view class="top-container" @click="goNeedsDetail(item)">
<view class="title-line">
<view class="title">{{ item.personName }}</view>
</view>
<!-- <view class="status-card" v-if="item.currentStatus == 3">已完成服务</view>
<view class="status-card in" v-else-if="item.untreatedCount <= 7">7天以内</view>
<view class="status-card out"
v-else-if="item.untreatedCount > 7&&item.untreatedCount <= 14">大于7天</view>
<view class="status-card far" v-else>已超期</view> -->
<view class="info"><text>状态</text><text
:class="item.currentStatus == 1 ? 'not' : item.currentStatus == 2 ? 'ing' : item.currentStatus == 3 ? 'finish' : '' ">
{{ getDictLabel(item.currentStatus, currentStatusList) }}
</text></view>
<view class="info" v-if="queryParams.needsType == 1">
<text>需求工种</text>{{ item.jobWorkTypeName }}
</view>
<view class="info" v-if="queryParams.needsType == 3">
<text>需求名称</text>{{ item.serviceRequirementTitle }}
</view>
<view class="info"
v-if="queryParams.needsType == 2||queryParams.needsType == 4||queryParams.needsType == 5">
<text>需求名称</text>{{ item.demandTitle }}
</view>
</view>
<!--
item.currentStatus = 1 待处理2 处理中 3 已完成
queryParams.needsType 1 求职需求 2 援助需求 3 创业需求 4 培训需求 5其他需求 展示办结按钮
item.currentStatus = 1待处理 item.currentStatus = 2 处理中
求职需求列表(queryParams.needsType = 1) 展示 推荐办理
培训需求列表(queryParams.needsType = 4) 展示 培训办理
援助创业其他列表 展示办理
item.currentStatus = 3 已完成
统一展示 服务追溯
-->
<view class="item_btn df_flex df_align_center df_justify_center">
<!-- 需求已处理完成的 展示服务追溯 -->
<view v-if="item.currentStatus == 3" class="df_flex_1">
<u-button type="primary" :plain="true" color="#BF5818" text="服务追溯"
@click="serviceTraceButton(item)" :customStyle="{border: 'none'}"></u-button>
</view>
<!-- 需求处于待处理处理中 -->
<view v-else class="df_flex_1">
<!-- 求职需求 -->
<view v-if="queryParams.needsType == 1" class="df_flex">
<u-button type="primary" :plain="true" color="#BF5818" text="推荐"
:customStyle="{border: 'none'}"
@click="requirementTraining(item, 1)"></u-button>
<view class="line"></view>
<u-button type="primary" :plain="true" color="#BF5818" text="办理"
:customStyle="{border: 'none'}" @click="requirementHandling(item)"></u-button>
</view>
<!-- 培训需求 -->
<view v-else-if="queryParams.needsType == 4" class="df_flex">
<u-button type="primary" :plain="true" color="#BF5818" text="培训"
:customStyle="{border: 'none'}"
@click="requirementTraining(item, 4)"></u-button>
<view class="line"></view>
<u-button type="primary" :plain="true" color="#BF5818" text="办理"
:customStyle="{border: 'none'}" @click="requirementHandling(item)"></u-button>
</view>
<!-- 其他需求 -->
<view v-else>
<u-button type="primary" :plain="true" color="#BF5818" text="办理"
:customStyle="{border: 'none'}" @click="requirementHandling(item)"></u-button>
</view>
</view>
</view>
</view>
</u-swipe-action-item>
</u-swipe-action>
<view style="padding-bottom: 24rpx;">
<img v-if="!total&&!loading" src="https://rc.jinan.gov.cn/qcwjyH5/static/images/person/empty.png"
style="width: 100%;display: block;margin: 0 auto;" />
<view v-if="loading"><u-loading-icon></u-loading-icon>
<view style="text-align: center;color: #8E8E8E;font-size: 24rpx;">加载中~</view>
</view>
<view v-else-if="showMorePage" style="text-align: center;color: #1A62CE;font-size: 24rpx;">加载更多
</view>
<view style="text-align: center;color: #8E8E8E;font-size: 24rpx;" v-else>没有更多数据了~</view>
</view>  
</scroll-view>
</view>
<u-popup :show="openDeal" style="position: relative;z-index: 100;" closeOnClickOverlay @close="openDeal=false">
<u--form class="self-form" labelPosition="top" :model="formData" :rules="rules" ref="uForm"
labelWidth="300">
<u-form-item label="实际解决时间" prop="actualSolveDate" required>
<view class="bordered" style="width: 100%;" @click="showTime=true"
:class="{noValue: !formData.actualSolveDate}">{{ formData.actualSolveDate||'请选择' }}</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="附件" prop="fileUrl" >
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</u-form-item>
<u-form-item label="解决说明" prop="solveDesc" required>
<u-textarea v-model="formData.solveDesc" placeholder="请输入"></u-textarea>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
</u--form>
<view class="button-area">
<view class="btn" @click="openDeal = false">取消</view>
<view class="btn reset" @click="formData.actualSolveDate = '';formData.solveDesc = ''">重置</view>
<view class="btn save" @click="finishJobRecommend">办结</view>
</view>
</u-popup>
<view class="addNeeds" @click="goAddNeeds()">
<img src="https://rc.jinan.gov.cn/qcwjyH5/static/images/person/addNeeds.png" />
</view>
<!-- <u-datetime-picker style="position: relative;z-index: 100;" :show="showTime" v-model="hopeSolveDate"
mode="datetime" @confirm="confirmDate" closeOnClickOverlay @close="showTime=false"
@cancel="showTime=false"></u-datetime-picker> -->
<u-datetime-picker
style="position: relative;z-index: 100;"
:show="showTime"
v-model="hopeSolveDate"
mode="datetime"
closeOnClickOverlay
@confirm="confirmDate"
@cancel="showTime=false"
@close="showTime=false"
></u-datetime-picker>
<!-- 社区端 - 显示隐藏退出组件 -->
<exitPopup />
</view>
</template>
<script>
import PopupList from "packageRc/components/PopupLists.vue";
import ImageUpload from '/packageRc/components/ImageUpload'
import {
requirementCompletion
} from '@/apiRc/company'
import {
listJobService,
delJobService
} from '@/apiRc/needs/jobService'
import {
listAssistService,
delAssistService,
finishAssistService
} from '@/apiRc/needs/assistService'
import {
listEntrepreneurshipService,
delEntrepreneurshipService,
finishEntrepreneurshipService
} from '@/apiRc/needs/entrepreneurshipService'
import {
listTrainService,
delTrainService
} from '@/apiRc/needs/trainService'
import {
listOtherService,
delOtherService,
finishOtherService
} from '@/apiRc/needs/otherService'
export default {
components: {
PopupList,
ImageUpload
},
data() {
return {
checkData: [],
options1: [{
text: '删除'
}],
queryParams: {
pageNum: 1,
pageSize: 10,
needsType: 1
},
total: 0,
showMorePage: true,
tableData: [],
person: {},
loading: false,
openDeal: false,
showTime: false,
formData: {
actualSolveDate: '',
solveDesc: ''
},
rules: {
actualSolveDate: [{
required: true,
message: '请选择实际解决时间',
trigger: ['blur', 'change'],
}, ],
solveDesc: [{
required: true,
message: '请填写解决说明',
trigger: ['blur', 'change'],
}, ],
},
hopeSolveDate: Number(new Date()),
currentStatusList: [],
fileList: [],
}
},
onLoad({
dictValue
}) {
this.queryParams.needsType = dictValue
this.getCheckData()
},
onShow() {
this.search();
},
methods: {
// 新增需求
goAddNeeds() {
this.$tab.navigateTo(`/pages/needs/needDetail?activeType=${this.queryParams.needsType}&showTab=1`)
},
confirmDate(e) {
this.showTime = false;
// 获取选中的日期
const date = e.value;
// 使用 uView 的 uTime 方法格式化日期,包含时分秒
const formattedDateTime = uni.$u.timeFormat(date, 'yyyy-mm-dd hh:MM:ss');
// 设置表单数据
this.formData.actualSolveDate = formattedDateTime;
},
// 需求推荐/培训
requirementTraining(item, index) {
if (index == 1) {
this.$tab.navigateTo(
`/pages/services/serviceDetail?personName=${item.personName}&personId=${item.personId}&jobDemandInfoId=${item.id}&jobWorkType=${item.jobWorkType}&type=3&showTab=1`
)
} else {
this.$tab.navigateTo(
`/pages/services/serviceDetail?personName=${item.personName}&personId=${item.personId}&skillTrainingId=${item.id}&personStatus=${item.personStatus}&type=4&showTab=1`
)
}
},
clickDelete(item) {
this.loading = true;
if (this.queryParams.needsType == 1) {
delJobService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 2) {
delAssistService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 3) {
delEntrepreneurshipService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 4) {
delTrainService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 5) {
delOtherService(item.id).then((res) => {
this.deleteFinish(res)
});
}
},
deleteFinish() {
uni.showToast({
title: '删除成功'
})
this.search()
},
goNeedsDetail(item) {
uni.navigateTo({
url: `/pages/needs/needDetail?id=${item.id}&type=${this.queryParams.needsType}&showTab=1`
})
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '--'
}
}
},
async getCheckData() {
let workExperienceYears
await this.getDicts('qcjy_gznx').then(res => {
workExperienceYears = res.data
})
await this.getDicts('qcjy_xqlc').then(res => {
this.currentStatusList = res.data;
console.log(res.data)
})
this.checkData = [
// {
// name: "需求类型",
// type: "needsType",
// data: [{dictLabel: '求职需求', dictValue: '1'},{dictLabel: '援助需求', dictValue: '2'},{dictLabel: '创业需求', dictValue: '3'},{dictLabel: '培训需求', dictValue: '4'},{dictLabel: '其他需求', dictValue: '5'}],
// activeIndex: 0,
// },
{
name: "需求状态",
type: "currentStatus",
data: [{
dictLabel: '全部',
dictValue: ''
}].concat(this.currentStatusList),
activeIndex: 0,
},
// {
// name: "工作经验",
// type: "workExperienceYears",
// data: [{dictLabel: '全部', dictValue: ''}].concat(workExperienceYears),
// activeIndex: 0,
// },
];
},
popupSearch(queryParams) {
queryParams.forEach((item, index) => {
if (item.data[item.activeIndex].dictLabel == "全部") {
this.queryParams[item.type] = "";
} else {
this.queryParams[item.type] = item.data[item.activeIndex].dictValue;
}
});
this.search()
},
search() {
this.showMorePage = true;
this.queryParams.pageNum = 1;
this.queryParams.pageSize = 10;
this.tableData = [];
this.total = 0;
this.getList();
},
// 服务追溯
serviceTraceButton(item) {
// 定义需求类型与对应的字符串映射
const demandTypeMap = {
1: 'job', // 求职需求
2: 'assist', // 援助需求
3: 'entrepreneurship', // 创业需求
4: 'train', // 培训需求
5: 'other' // 其他需求
};
// 获取当前的需求类型字符串
const demandType = demandTypeMap[this.queryParams.needsType] || 'other';
// 使用映射后的字符串构建URL并导航
this.$tab.navigateTo(`/pages/services/serviceTraceability?id=${item.id}&demandType=${demandType}`);
},
// 触底加载
getBottomList() {
if (
this.queryParams.pageNum * this.queryParams.pageSize >=
this.total
) {
this.showMorePage = false;
} else if (
this.queryParams.pageNum * this.queryParams.pageSize <
this.total
) {
this.queryParams.pageNum++;
this.getList();
if (
this.queryParams.pageNum * this.queryParams.pageSize >=
this.total
) {
this.showMorePage = false;
}
}
},
// 获取列表
async getList() {
this.loading = true;
if (this.queryParams.needsType == 1) {
listJobService(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 2) {
listAssistService(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 3) {
listEntrepreneurshipService(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 4) {
listTrainService(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 5) {
listOtherService(this.queryParams).then((res) => {
this.gettedData(res)
});
}
},
gettedData(res) {
if (res.code == 200) {
if (res.rows.length < 10) {
this.showMorePage = false;
}
this.loading = false;
this.tableData = this.tableData.concat(res.rows);
this.total = res.total;
} else {
this.loading = false;
uni.showToast({
title: res.msg,
icon: "none",
});
}
},
// 需求办结
requirementHandling(item) {
this.openDeal = true;
this.formData = {
id: item.id,
currentStatus: '3'
}
},
// 需求推荐
requirementRecommendation(item) {
this.$tab.navigateTo(
`/pages/services/serviceDetail?personName=${item.personName}&personId=${item.personId}&jobDemandInfoId=${item.id}&jobWorkType=${item.jobWorkType}&type=3&showTab=1`
)
},
// 办结按钮
async finishJobRecommend() {
try {
// 检查必填项
if (!this.formData.actualSolveDate) {
throw new Error('解决时间不能为空');
}
if (!this.formData.solveDesc) {
throw new Error('解决说明不能为空');
}
// 显示全局加载
this.$showLoading();
// 根据 queryParams.needsType 获取对应的 URL
const obj = {
1: '/demand/personJobDemandInfo/JdJobDemandDone',
2: '/demand/personAssistDemandInfo/assistDone',
3: '/demand/personEntrepreneurshipDemandInfo/entrepreneurshipDone',
4: '/demand/personTrainDemandInfo/JdTrainDemandDone',
5: '/demand/personOtherDemandInfo/otherDemandDone',
};
const url = obj[this.queryParams.needsType];
if (!url) {
throw new Error('无效的需求类型');
}
const {
code,
msg
} = await requirementCompletion(url, this.formData);
// 检查响应码是否为200
if (code === 200) {
// 显示成功的提示信息
this.$u.toast(msg);
this.openDeal = false;
this.search();
}
} catch (error) {
// 处理错误并显示提示信息
this.$u.toast('请检查必填项填写');
console.error('完成需求时发生错误:', error);
} finally {
// 确保加载页总是会被隐藏
this.$hideLoading();
}
},
// async finishJobRecommend() {
// this.openDeal = true;
// const obj = {
// 1: '/demand/personJobDemandInfo/JdJobDemandDone',
// 2: '/demand/personAssistDemandInfo/assistDone',
// 3: '/demand/personEntrepreneurshipDemandInfo/entrepreneurshipDone',
// 4: '/demand/personTrainDemandInfo/JdTrainDemandDone',
// 5: '/demand/personOtherDemandInfo/otherDemandDone',
// }
// if (!this.formData.actualSolveDate) return this.$u.toast('解决时间不能为空');
// if (!this.formData.solveDesc) return this.$u.toast('解决说明不能为空');
// const {
// code,
// data,
// msg
// } = await requirementCompletion(obj[this.queryParams.needsType], this.formData)
// if (code == 200) {
// this.$u.toast(msg)
// this.openDeal = false
// this.search()
// }
// },
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
}
}
</script>
<style lang="scss" scoped>
.page {
background-color: #EEF1F5 !important;
height: 100vh;
background-image: url('https://rc.jinan.gov.cn/qcwjyH5/static/images/top.png');
background-repeat: no-repeat;
background-size: 100% auto;
}
.search-line {
border-radius: 32px;
background: #FFFFFF;
box-sizing: border-box;
border: 1px solid #107AFD;
height: 64rpx;
border-radius: 32rpx;
padding: 0 32rpx;
display: flex;
align-items: center;
position: relative;
z-index: 1;
margin-top: 24rpx;
.search-icon {
width: 40rpx;
}
}
.job-item {
position: relative;
.item_btn{
height: 100rpx;
border-top: 1px solid #e3e8ee;
}
.line{
position: absolute;
right: 50%;
bottom: 20rpx;
width: 1px;
height: 60rpx;
background-color: #e3e8ee;
}
.status-card {
position: absolute;
right: 0;
top: 0;
border-radius: 0 16rpx 0 16rpx;
width: 160rpx;
line-height: 40rpx;
text-align: center;
color: #fff;
background: #B2C0D1;
border: 1px solid #9BA9B9;
font-size: 24rpx;
&.in {
background: #29D297;
border: 1px solid #1BBA83;
}
&.out {
background: #ECB83D;
border: 1px solid #D7892B;
}
&.far {
background: #EC7737;
border: 1px solid #C24F1A;
}
}
.top-container {
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
// margin-bottom: 24rpx;
.title-line {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 32rpx;
font-weight: bold;
margin-bottom: 16rpx;
.type-tag {
line-height: 40rpx;
width: 128rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
&.qz {
background: #28CB5E;
}
&.yz {
background: #DD6728;
}
&.cy {
background: #23B5C5;
}
&.px {
background: #DDA728;
}
&.qt {
background: #2870DD;
}
}
.title {
color: #3D3D3D;
width: calc(100% - 137rpx);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 40rpx;
}
.salary {
width: 33%;
color: #FA6553;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: right
}
}
.info {
color: #3D3D3D;
margin-bottom: 7rpx;
font-size: 28rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text {
color: #8E8E8E;
}
.not {
color: #EC7737;
font-weight: bold;
}
.ing {
color: #ECB83D;
font-weight: bold;
}
.finish {
color: #21C88D;
font-weight: bold;
}
}
}
.function-btn {
color: #BF5818;
border-top: 1px solid #E2E8EF;
padding-bottom: 6rpx;
line-height: 90rpx;
text-align: center;
}
}
.self-form {
padding: 32rpx;
.bordered {
border: 1rpx solid #dadbde;
padding: 9px;
border-radius: 4px;
}
}
.button-area {
padding: 24rpx 32rpx 68rpx;
background: #fff;
display: flex;
box-sizing: border-box;
border-radius: 16px 16px 0px 0px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
.noValue {
color: rgb(192, 196, 204);
}
.addNeeds {
position: fixed;
right: 0;
bottom: 150rpx;
width: 150rpx;
overflow: hidden;
z-index: 10;
border-radius: 44rpx;
border-radius: 75rpx;
img {
display: block;
width: 100%;
}
}
</style>

View File

@@ -0,0 +1,517 @@
<template>
<view>
<view class="page">
<view class="page-header">
<u-icon class="back-icon" name="arrow-left" color="#fff" size="16" @click="goBack()"></u-icon>
<view class="title">需求列表</view>
<view style="width: 16rpx;"></view> <!-- 占位保证左右对称 -->
</view>
<view class="input-outer-part"
style="padding-top: 12rpx;margin-top: 16rpx;padding-bottom: 0;max-height: unset;">
<!-- <view class="inner"
style="width: calc(100% + 64rpx);margin-left: -32rpx;height: 122rpx;position: relative;z-index: 2;">
<PopupList :checkData="checkData" @searchCheck="search" ref="PopupList"
@popupSearch="popupSearch" />
</view> -->
<scroll-view :scroll-y="true" style="height: calc(100vh - 242rpx);position: relative;z-index: 1;"
@scrolltolower="getBottomList">
<u-swipe-action>
<u-swipe-action-item @click="clickDelete(item)" v-for="(item, index) in tableData" :key="index"
style="margin-bottom: 24rpx;border-radius: 16rpx;" :options="options1">
<view @click="goNeedsDetail(item)" class="job-item">
<view class="title-line" v-if="queryParams.needsType==1">
<view class="type-tag qz">求职需求</view>
<view class="title">{{getJobWorkTypeName(item.jobWorkType)}}</view>
</view>
<view class="title-line" v-if="queryParams.needsType==2">
<view class="type-tag yz">援助需求</view>
<view class="title">{{ item.demandTitle }}</view>
</view>
<view class="title-line" v-if="queryParams.needsType==3">
<view class="type-tag cy">创业需求</view>
<view class="title">{{ item.personName }}的创业需求</view>
</view>
<view class="title-line" v-if="queryParams.needsType==4">
<view class="type-tag px">培训需求</view>
<view class="title">{{ item.personName }}的培训需求</view>
</view>
<view class="title-line" v-if="queryParams.needsType==5">
<view class="type-tag qt">其他需求</view>
<view class="title">{{ item.personName }}的其他需求</view>
</view>
<view class="info"><text>需求状态</text><text
:class="item.currentStatus == 1 ? 'not' : item.currentStatus == 2 ? 'ing' : item.currentStatus == 3 ? 'finish' : '' ">
{{ getDictLabel(item.currentStatus, currentStatusList) }}
</text></view>
<view class="bottom-line">
<view class="info"><text>提交时间</text>{{ item.createTime }}</view>
<view style="font-size:12px;">左划删除需求</view>
</view>
</view>
</u-swipe-action-item>
</u-swipe-action>
<img v-if="!total&&!loading" src="https://rc.jinan.gov.cn/qcwjyH5/static/images/person/empty.png"
style="width: 100%;display: block;margin: 0 auto;" />
<view v-if="loading"><u-loading-icon></u-loading-icon>
<view style="text-align: center;color: #8E8E8E;font-size: 24rpx;">加载中~</view>
</view>
<view v-else-if="showMorePage" style="text-align: center;color: #1A62CE;font-size: 24rpx;">加载更多
</view>
<view class="addNeeds" @click="goAddNeeds()">
<img src="https://rc.jinan.gov.cn/qcwjyH5/static/images/person/addNeeds.png" />
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
import {
getPersonBase
} from "@/apiRc/person";
import PopupList from "../../components/PopupLists.vue";
import {
listJobService,
delJobService
} from '@/apiRc/needs/jobService'
import { listPersonDemand, delPersonDemand } from "@/apiRc/needs/personDemand";
import {
listAssistService,
delAssistService
} from '@/api/apiRc/assistService'
import {
listEntrepreneurshipService,
delEntrepreneurshipService
} from '@/api/apiRc/entrepreneurshipService'
import {
listTrainService,
delTrainService
} from '@/api/apiRc/trainService'
import { listJobType } from "@/apiRc/jobType/index";
import {
listOtherService,
delOtherService
} from '@/apiRc/needs/otherService'
export default {
components: {
PopupList,
},
onShow() {
this.search();
},
data() {
return {
checkData: [],
options1: [{
text: '删除'
}],
queryParams: {
pageNum: 1,
pageSize: 10,
needsType: 1,
userId: '',
},
jobTypeList:[],
total: 0,
showMorePage: true,
tableData: [],
person: {},
loading: false,
currentStatusList: [],
}
},
mounted() {
},
onLoad({
dictValue,userId
}) {
this.queryParams.needsType = dictValue
this.queryParams.userId = userId
this.getCheckData()
this.getDicts('qcjy_xqlc').then(res => {
this.currentStatusList = res.data;
})
this.workTypeRemoteMethod()
this.getDicts('qcjy_zgzpgz').then(res => {
this.salaryList = res.data;
})
getPersonBase(this.$store.state.user.userId).then(resp => {
this.person = resp.data
this.queryParams.personId = resp.data.id
})
},
methods: {
getJobWorkTypeName(data){
if (data) {
let arr = this.jobTypeList.filter((ele) => ele.id == data);
return arr[0].workTypeName;
}
},
workTypeRemoteMethod(key) {
listJobType({
workTypeName: key,
pageNum: 1,
pageSize: 50,
}).then((res) => {
this.jobTypeList = res.rows;
});
},
goAddNeeds() {
this.$tab.navigateTo(`/pages/needs/needDetail?activeType=${this.queryParams.needsType}&showTab=1`)
},
goBack() {
uni.navigateBack()
},
clickDelete(item) {
this.loading = true;
if (this.queryParams.needsType == 1) {
delJobService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 2) {
delAssistService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 3) {
delEntrepreneurshipService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 4) {
delTrainService(item.id).then((res) => {
this.deleteFinish(res)
});
} else if (this.queryParams.needsType == 5) {
delOtherService(item.id).then((res) => {
this.deleteFinish(res)
});
}
},
deleteFinish() {
uni.showToast({
title: '删除成功'
})
this.search()
},
goNeedsDetail(item) {
uni.navigateTo({
url: `/pages/needs/needDetail?id=${item.id}&type=${this.queryParams.needsType}&showTab=1`
})
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
async getCheckData() {
let workExperienceYears
await this.getDicts('qcjy_gznx').then(res => {
workExperienceYears = res.data
})
this.checkData = [
// {
// name: "需求类型",
// type: "needsType",
// data: [{dictLabel: '求职需求', dictValue: '1'},{dictLabel: '援助需求', dictValue: '2'},{dictLabel: '创业需求', dictValue: '3'},{dictLabel: '培训需求', dictValue: '4'},{dictLabel: '其他需求', dictValue: '5'}],
// activeIndex: 0,
// },
// {
// name: "工作经验",
// type: "workExperienceYears",
// data: [{
// dictLabel: '全部',
// dictValue: ''
// }].concat(workExperienceYears),
// activeIndex: 0,
// },
];
},
popupSearch(queryParams) {
queryParams.forEach((item, index) => {
if (item.data[item.activeIndex].dictLabel == "全部") {
this.queryParams[item.type] = "";
} else {
this.queryParams[item.type] = item.data[item.activeIndex].dictValue;
}
});
this.search()
},
search() {
this.showMorePage = true;
this.queryParams.pageNum = 1;
this.queryParams.pageSize = 10;
this.tableData = [];
this.total = 0;
this.getList();
},
// 触底加载
getBottomList() {
if (
this.queryParams.pageNum * this.queryParams.pageSize >=
this.total
) {
this.showMorePage = false;
} else if (
this.queryParams.pageNum * this.queryParams.pageSize <
this.total
) {
this.queryParams.pageNum++;
this.getList();
if (
this.queryParams.pageNum * this.queryParams.pageSize >=
this.total
) {
this.showMorePage = false;
}
}
},
// 获取列表
async getList() {
this.loading = true;
if (this.queryParams.needsType == 1) {
this.queryParams.demandType = 1
listPersonDemand(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 2) {
listAssistService(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 3) {
this.queryParams.demandType = 2
listPersonDemand(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 4) {
this.queryParams.demandType = 3
listPersonDemand(this.queryParams).then((res) => {
this.gettedData(res)
});
} else if (this.queryParams.needsType == 5) {
this.queryParams.demandType = 9
listPersonDemand(this.queryParams).then((res) => {
this.gettedData(res)
});
}
},
gettedData(res) {
if (res.code == 200) {
if (res.rows.length < 10) {
this.showMorePage = false;
}
this.loading = false;
this.tableData = this.tableData.concat(res.rows);
this.total = res.total;
} else {
this.loading = false;
uni.showToast({
title: res.msg,
icon: "none",
});
}
}
}
}
</script>
<style lang="scss" scoped>
.page {
background-color: #eef1f5 !important;
height: 100vh;
background-image: url('https://rc.jinan.gov.cn/qcwjyH5/static/images/top.png');
background-repeat: no-repeat;
background-size: 100% auto;
}
.search-line {
border-radius: 32px;
background: #FFFFFF;
box-sizing: border-box;
border: 1px solid #107AFD;
height: 64rpx;
border-radius: 32rpx;
padding: 0 32rpx;
display: flex;
align-items: center;
position: relative;
z-index: 1;
margin-top: 24rpx;
.search-icon {
width: 40rpx;
}
}
.job-item {
border-radius: 24rpx; /* 增大圆角,使界面更圆润 */
padding: 32rpx;
margin: 30rpx 30rpx 24rpx 30rpx; /* 添加左右30rpx边距 */
background-color: #FFFFFF; /* 设置白色背景,避免与底层背景重合 */
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); /* 添加轻微阴影增强层次感 */
.title-line {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 32rpx;
font-weight: bold;
margin-bottom: 16rpx;
.type-tag {
line-height: 40rpx;
width: 128rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
&.qz {
background: #28CB5E;
}
&.yz {
background: #DD6728;
}
&.cy {
background: #23B5C5;
}
&.px {
background: #DDA728;
}
&.qt {
background: #2870DD;
}
}
.title {
color: #3D3D3D;
width: calc(100% - 137rpx);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 40rpx;
}
.salary {
width: 33%;
color: #FA6553;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: right
}
}
.info {
color: #3D3D3D;
margin-bottom: 7rpx;
font-size: 28rpx;
text {
color: #8E8E8E;
}
.not {
color: #EC7737;
font-weight: bold;
}
.ing {
color: #ECB83D;
font-weight: bold;
}
.finish {
color: #21C88D;
font-weight: bold;
}
}
.bottom-line {
display: flex;
justify-content: space-between;
margin-top: 21rpx;
.info {
margin-bottom: 0;
}
.toudi-btn {
background: linear-gradient(90deg, #1A62CE 0%, #1D8ACE 100%);
color: #fff;
width: 140rpx;
line-height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
border-radius: 20rpx;
img {
width: 22rpx;
margin-right: 10rpx;
}
}
}
}
.addNeeds {
position: fixed;
right: 10px;
bottom: 150rpx;
width: 150rpx; /* 改小一点,比如 100rpx */
height: 10vh; /* 新增高度 */
overflow: hidden;
z-index: 10;
border-radius: 50rpx; /* 圆角要和宽高一半一致,才能正圆 */
img {
display: block;
width: 100%;
height: 100%; /* 让图片填满容器 */
object-fit: cover; /* 保证图片不变形,裁剪多余部分 */
}
}
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
height: 80rpx; // 可根据实际调整
}
.back-icon {
flex-shrink: 0;
margin-left: 20rpx;
}
.title {
flex: 1;
text-align: center;
font-size: 32rpx;
color: #fff;
font-weight: bold;
}
</style>

View File

@@ -0,0 +1,134 @@
<template>
<uni-popup ref="showPersonChooser" type="bottom" round background-color="#fff">
<view style="width: 100%;position: relative;z-index: 100;box-sizing: border-box;background: #fff;padding-top: 10px;">
<input class="search" @change="searchChange" placeholder="搜索选择人员" v-model="searchPerson"/>
<scroll-view style="height: 500rpx;padding: 0 32rpx;box-sizing: border-box;" :scroll-y="true">
<view v-for="(item, index) in personList" :key="index" @click="bindPerson(item)"
class="person-list" :class="{active: activePerson.id == item.id}">
<template v-if="choiceType==3">
<view>{{ item.personName }}</view>
<view style="color: #8492a6;margin-top: 7rpx;">期望工种{{item.jobWorkTypeName}}</view>
</template>
<template v-else-if="choiceType==4">
<view>{{ item.personName }}</view>
<view style="color: #8492a6;margin-top: 7rpx;">意愿培训工种{{item.trainingIntentionWorkTypeName}}</view>
</template>
<template v-else>
<view style="display: flex;justify-content: space-between;font-size: 32rpx;font-weight: bold;">{{ item.name }}
<view style="color: #8492a6; font-size: 13px;width: 50%;text-align: right;">{{ item.phone }}</view>
</view>
<view style="color: #8492a6;margin-top: 7rpx;">现居住地{{item.currentResidentialAddress}}</view>
</template>
</view>
</scroll-view>
<view class="button-area" style="position: relative;">
<view class="btn" @click="closeshowPersonChooser">取消</view>
<view class="btn reset" @click="resetData">重置</view>
<view class="btn save" @click="saveInfo">确定</view>
</view>
</view>
</uni-popup>
</template>
<script>
import {getPersonList} from '@/apiRc/needs/person'
import { listJobService } from "@/apiRc/needs/jobService";
import { listTrainService } from "@/apiRc/needs/trainService";
export default {
props: {
choiceType: {
default: 1
}
},
mounted() {
this.doSearch()
},
data() {
return {
showPersonChooser: false,
activePerson: {},
searchPerson: '',
personList: [],
searcher: '',
}
},
methods: {
open() {
this.$refs.showPersonChooser.open();
this.activePerson = {}
},
closeshowPersonChooser() {
this.$refs.showPersonChooser.close()
},
saveInfo() {
this.$emit('confirm', this.activePerson)
this.$refs.showPersonChooser.close()
},
searchChange(){
console.log('搜索内容:' + this.searchPerson);
if(this.searcher){
clearTimeout(this.searcher)
this.doSearch()
}else{
this.doSearch()
}
},
doSearch() {
this.searcher = setTimeout(() => {
uni.showLoading('加载中...');
// alert("选择的choiceType" + this.choiceType );
if(this.choiceType == 3) {
listJobService({personName: this.searchPerson, pageSize: 100, pageNum: 1}).then(res => {
uni.hideLoading();
this.personList = res.rows
clearTimeout(this.searcher)
})
}else if(this.choiceType == 4) {
listTrainService({personName: this.searchPerson, pageSize: 100, pageNum: 1}).then(res => {
uni.hideLoading();
this.personList = res.rows
clearTimeout(this.searcher)
})
}else{
getPersonList({name: this.searchPerson, pageSize: 100, pageNum: 1}).then(res => {
uni.hideLoading();
this.personList = res.rows
clearTimeout(this.searcher)
})
}
}, 200)
},
resetData(){
this.searchPerson = '';
this.personList = [];
this.activePerson = {}
},
bindPerson(item) {
this.activePerson = item;
this.$forceUpdate();
},
}
}
</script>
<style lang="scss" scoped>
.person-list{
padding: 24rpx 32rpx;
border-radius: 8rpx;
box-sizing: border-box;
border: 1px solid #e4e4e4;
margin-top: 32rpx;
&.active{
border: 1px solid #1890ff;
}
}
.search{
margin: 0 32rpx;
border: 1px solid #e4e4e4;
border-radius: 50rpx;
height: 64rpx;
padding: 0 20rpx;
}
</style>

View File

@@ -0,0 +1,752 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 09:06:28
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 150px)':'calc(100vh - 144px)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-blqksm: space-between;">服务信息
<view v-if="!edit&&formData.id" class="btn" style="font-weight: normal;display: flex;"
@click="edit=true">编辑<u-icon name="edit-pen" color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<u--form labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form"
labelWidth="110">
<u-form-item label="类型" v-if="!userId" required>
<view class="status_radio df_flex df_flex_1">
<u-radio-group v-model="formData.type" placement="column">
<u-radio v-for="(item, index) in validType" :key="index" :label="item.label"
:name="item.value">
</u-radio>
</u-radio-group>
</view>
</u-form-item>
<u-form-item label="被服务对象" prop="serviceObjectName" required v-if="formData.type == 0">
<view class="picker-view" :class="{selected: formData.serviceObjectName}" @click="openPersonChooser">
<text :class="formData.serviceObjectName ? 'picker-text' : 'picker-placeholder'">
{{ formData.serviceObjectName || '请选择被服务对象' }}
</text>
</view>
</u-form-item>
<u-form-item label="被服务对象" prop="serviceObjectName" required v-else>
<view class="picker-view" :class="{selected: formData.serviceObjectName}" @click="$refs.enterpriseChooser.open()">
<text :class="formData.serviceObjectName ? 'picker-text' : 'picker-placeholder'">
{{ formData.serviceObjectName || '请选择被服务对象' }}
</text>
</view>
</u-form-item>
<u-form-item label="服务时间" prop="practicalSolutionTime" required>
<view class="picker-view" :class="{selected: formData.practicalSolutionTime}" @click="showPicker('practicalSolutionTime')">
<text :class="formData.practicalSolutionTime ? 'picker-text' : 'picker-placeholder'">
{{ formData.practicalSolutionTime || '请选择服务时间' }}
</text>
</view>
</u-form-item>
<u-form-item label="经办人" prop="agentUserName" required>
<u--input :disabled="!edit" v-model="formData.agentUserName" border="none"
placeholder="请输入"></u--input>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="服务类型" prop="demandType" required>
<view class="picker-view" :class="{selected: formData.demandType}" @click="showPicker('demandType')">
<text :class="formData.demandType ? 'picker-text' : 'picker-placeholder'">
{{ getDictLabel(formData.demandType, dict.demandType) || '请选择服务类型' }}
</text>
</view>
</u-form-item>
<u-form-item label="服务内容" prop="serviceContent" required>
<view class="picker-view" :class="{selected: formData.serviceContent}" @tap="showServiceContentSelect">
<text :class="formData.serviceContent ? 'picker-text' : 'picker-placeholder'">
{{ getMultiDictLabel(formData.serviceContent, dict.serviceContent) || '请选择服务内容' }}
</text>
</view>
</u-form-item>
<u-form-item label="电话沟通结果" prop="dhgtjg" v-if="formData.demandType == '5'" required>
<view class="picker-view" :class="{selected: formData.dhgtjg}" @click="showPicker('dhgtjg')">
<text :class="formData.dhgtjg ? 'picker-text' : 'picker-placeholder'">
{{ getDictLabel(formData.dhgtjg, dict.dhgtjg) || '请选择电话沟通结果' }}
</text>
</view>
</u-form-item>
<!-- 新增人员状态展示方式与服务类型一致 -->
<u-form-item label="人员状态" prop="personStatus" required >
<view class="picker-view" :class="{selected: formData.personStatus}" @click="showPicker('personStatus')">
<text :class="formData.personStatus ? 'picker-text' : 'picker-placeholder'">
{{ getDictLabel(formData.personStatus, dict.personStatus) || '请选择人员状态' }}
</text>
</view>
</u-form-item>
<u-form-item label="服务情况说明" prop="blqksm" required>
<u-textarea :disabled="!edit" v-model="formData.blqksm" placeholder="请输入"></u-textarea>
</u-form-item>
</u--form>
</view>
</view>
<view class="inner">
<view class="part-title" style="margin-top: 32rpx;">附件信息</view>
<view class="inner-part">
<u--form labelPosition="left" class="self-form" labelWidth="110">
<u-form-item label="附件" prop="fileUrl">
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</u-form-item>
</u--form>
</view>
</view>
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
</scroll-view>
<u-datetime-picker :show="show.practicalSolutionTime" v-model="hopeSolveDate" mode="date" @confirm="confirmDate('practicalSolutionTime', $event)"
@cancel="cancelPicker('practicalSolutionTime')" @close="cancelPicker('practicalSolutionTime')" closeOnClickOverlay></u-datetime-picker>
<choose-person ref="personChooser" @confirm="personNameConfirm" />
<enterprise-list-pop ref="enterpriseChooser" @confirm="enterpriseConfirm" />
<u-picker :show="show.dhgtjg" :columns="[dict.dhgtjg]" keyName="dictLabel"
@confirm="pickerConfirm('dhgtjg', $event)" @cancel="cancelPicker('dhgtjg')"></u-picker>
<u-picker :show="show.demandType" :columns="[dict.demandType]" keyName="dictLabel"
@confirm="pickerConfirm('demandType', $event)" @cancel="cancelPicker('demandType')"></u-picker>
<u-picker :show="show.personStatus" :columns="[dict.personStatus]" keyName="dictLabel"
@confirm="pickerConfirm('personStatus', $event)" @cancel="cancelPicker('personStatus')"></u-picker>
<u-popup :show="show.serviceContent" mode="bottom" @close="cancelSelect">
<view class="select-content">
<view class="select-header">
<text @tap="cancelSelect">取消</text>
<text class="title">服务内容</text>
<text @tap="confirmSelect">确定</text>
</view>
<scroll-view scroll-y class="checkbox-scroll">
<view class="checkbox-group">
<u-checkbox-group v-model="tempServiceContent" placement="column">
<view
v-for="(item, index) in dict.serviceContent"
:key="index"
class="checkbox-item"
>
<u-checkbox
:name="item.dictValue"
:label="item.dictLabel"
></u-checkbox>
</view>
</u-checkbox-group>
</view>
</scroll-view>
</view>
</u-popup>
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<view class="btn reset" @click="formData = {}" v-if="!formData.id">重置</view>
<view class="btn save" @click="saveInfo">保存</view>
</view>
</view>
</template>
<script>
import {
addInvestigate,
updateInvestigate,
getInvestigate
} from "@/apiRc/service/investigate";
import ImageUpload from '@/packageRc/components/ImageUpload'
import ChoosePerson from './choosePerson.vue';
export default {
components: {
ChoosePerson,
ImageUpload,
},
props: {
userId: {
type: String,
default: ''
},
name:{
type: String,
default: ''
}
},
data() {
return {
edit: true,
personBase: {},
dates: {},
hopeSolveDate: Number(new Date()),
formData: {
type: 0,
serviceContent: [],
personStatus: '' // 新增字段
},
rules: {
serviceObjectName: [{
required: true,
message: '请选择被服务人员',
trigger: ['blur', 'change'],
}, ],
unitName: [{
required: true,
message: '请选择被服务对象',
trigger: ['blur', 'change'],
}],
practicalSolutionTime: [{
required: true,
message: '请选择服务时间',
trigger: ['blur', 'change'],
}, ],
agentUserName: [{
required: true,
message: '请填写服务人员',
trigger: ['blur', 'change'],
}, ],
demandType: [{
required: true,
message: '请填写服务类型',
trigger: ['blur', 'change'],
}, ],
blqksm:[{
required: true,
message: '请填写服务情况说明',
trigger: ['blur', 'change'],
}],
dhgtjg: [
{
required: false,
validator: (rule, value, callback) => {
if (this.formData.demandType === '5' && (!value || value === '')) {
callback(new Error('请输入电话沟通结果'));
} else {
callback();
}
},
trigger: ['blur', 'change'],
}
],
personStatus: [{
required: true,
message: '请选择人员状态',
trigger: ['blur', 'change'],
}]
},
dict: {
serviceContent: [],
personStatus: [] // 新增
},
show: {
serviceContent: false,
personStatus: false // 新增
},
loading: false,
fileList: [],
validType: [{
label: "个人",
value: "0",
},
{
label: "企业",
value: "1",
},
],
serviceContentList: [],
tempServiceContent: [],
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.serviceontent();
this.loading = true;
let arr = [{
key: 'qyjy_dhgtjg',
prop: 'dhgtjg'
},
{
key: 'qyjy_zdfwlx',
prop: 'demandType'
},
// 新增人员状态字典
{
key: 'qcjy_ryzt', // 如有实际key请替换
prop: 'personStatus'
},
]
arr.forEach(ele => {
this.$getDict(ele.key).then(res => {
this.dict[ele.prop] = res.data
this.$forceUpdate();
})
})
this.$getDict("qcjy_fwnr").then(res => {
console.log("获取到的服务内容数据:", res.data);
this.dict.serviceContent = res.data;
this.$forceUpdate();
});
},
mounted() {
setTimeout(() => {
this.setName()
}, 0)
},
methods: {
serviceontent(){
this.$getDict("qcjy_fwnr").then(res=>{
console.log("服务内容列表",res.data)
})
},
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
setName(){
this.formData.serviceObjectName = this.name
this.formData.serviceObjectId = this.userId
this.formData.userId = this.userId
this.$forceUpdate();
},
openPersonChooser() {
if (this.edit) {
this.$refs.personChooser.open();
}
},
personNameConfirm(event) {
this.formData.serviceObjectName = event.name
this.formData.serviceObjectId = event.id
this.$forceUpdate();
},
// 选择企业
enterpriseConfirm({
unitName,
id
}) {
this.$set(this.formData, 'serviceObjectName', unitName)
this.$set(this.formData, 'serviceObjectId', id)
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {
type: "0"
}
this.edit = true
},
getDetail(id) {
getInvestigate(id).then(res => {
const data = res.data;
// 处理服务内容为数组
if (data.serviceContent) {
data.serviceContent = typeof data.serviceContent === 'string'
? data.serviceContent.split(',').filter(Boolean)
: data.serviceContent;
} else {
data.serviceContent = [];
}
this.formData = data;
this.edit = false;
this.fileList = this.$processFileUrl(this.formData.fileUrl);
})
},
confirmDate(type, e) {
this.show[type] = false;
// 获取选中的日期
const date = e.value;
// 使用 uView 的 uTime 方法格式化日期,包含时分秒
const formattedDateTime = uni.$u.timeFormat(date, "yyyy-mm-dd hh:MM:ss");
this.formData[type] = formattedDateTime
this.$forceUpdate();
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
this.$forceUpdate();
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false;
if (type === 'serviceContent') {
// 多选处理
this.formData[type] = event.value.map(item => item.dictValue);
} else {
// 其他字段保持原样
this.formData[type] = event.value[0].dictValue;
}
this.$forceUpdate();
},
showPicker(type) {
if (this.edit) {
this.show[type] = true
this.$forceUpdate()
}
},
async saveInfo() {
try {
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('请检查必填项填写');
}
let demandType = this.formData.demandType;
// 确保 serviceContent 是数组并且有值
if (!Array.isArray(this.formData.serviceContent) || this.formData.serviceContent.length === 0) {
this.$u.toast("请选择服务内容!");
return;
}
// 处理服务内容数组
this.formData.fwnr = this.formData.serviceContent.join(',');
// 显示全局加载
this.$showLoading();
// 根据 formData 是否有 id 来决定是更新还是新增
let response;
let successMessage;
if (this.formData.id) {
response = await updateInvestigate(this.formData);
successMessage = '修改成功';
} else {
console.log("h5表单",this.formData)
delete this.formData.type
response = await addInvestigate(this.formData);
successMessage = '保存成功';
}
// 检查响应码是否为200
if (response.code === 200) {
this.$u.toast(successMessage);
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
await this.$delay(1000); // 延迟1秒后返回上一页
uni.navigateBack();
}
}
} catch (error) {
this.$u.toast("请填写完整内容");
} finally {
// 确保加载页总是会被隐藏
this.$hideLoading();
}
},
getMultiDictLabel(values, list) {
if (!values || !list) return '';
const valueArray = typeof values === 'string' ? values.split(',') : values;
if (!Array.isArray(valueArray)) return '';
return valueArray.map(value => {
const item = list.find(ele => ele.dictValue == value);
return item ? item.dictLabel : '';
}).filter(Boolean).join('、');
},
checkboxGroupChange(values) {
this.formData.serviceContent = values;
this.$forceUpdate();
},
processServiceContentList() {
this.serviceContentList = this.dict.serviceContent.map(item => ({
label: item.dictLabel,
value: item.dictValue
}));
},
showServiceContentSelect() {
console.log("点击了服务内容");
if (this.edit) {
this.tempServiceContent = Array.isArray(this.formData.serviceContent)
? [...this.formData.serviceContent]
: [];
this.show.serviceContent = true;
this.$forceUpdate();
}
},
cancelSelect() {
console.log("取消选择");
this.show.serviceContent = false;
this.$forceUpdate();
},
confirmSelect() {
console.log("确认选择", this.tempServiceContent);
this.formData.serviceContent = [...this.tempServiceContent];
this.show.serviceContent = false;
this.$forceUpdate();
},
}
}
</script>
<style lang="scss">
.page ::v-deep .u-navbar__content {
background-color: transparent !important;
}
.input-outer-part {
.status_radio {
.u-radio-group {
display: flex;
flex-direction: row;
}
.u-radio {
margin-right: 50rpx;
}
}
}
.page {
background-color: #EEF1F5 !important;
height: 100vh;
background-image: url('https://rc.jinan.gov.cn/qcwjyH5/static/images/top.png');
background-repeat: no-repeat;
background-size: 100% auto;
}
.button-area {
padding: 24rpx 32rpx 68rpx;
width: calc(100% + 64rpx);
margin-left: -32rpx;
background: #fff;
display: flex;
box-sizing: border-box;
margin-top: 40rpx;
border-radius: 16px 16px 0px 0px;
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
// 改进选择器样式
.picker-view {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 28rpx 36rpx;
background: #ffffff;
border: 2rpx solid #e5e5e5;
border-radius: 12rpx;
min-height: 88rpx;
box-sizing: border-box;
transition: all 0.3s ease;
position: relative;
&:active {
background: #f8f9fa;
border-color: #007aff;
transform: scale(0.98);
}
&::after {
content: '';
position: absolute;
right: 36rpx;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
border-top: 12rpx solid #999999;
}
.picker-text {
color: #333333;
font-size: 28rpx;
flex: 1;
}
.picker-placeholder {
color: #999999;
font-size: 28rpx;
}
}
// 选中状态的样式
.picker-view.selected {
border-color: #1D64CF;
background: #f0f8ff;
&::after {
border-top-color: #1D64CF;
}
}
.checkbox-container {
padding: 10rpx 0;
.u-checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.u-checkbox {
margin-right: 30rpx;
margin-bottom: 20rpx;
}
}
.select-content {
background-color: #fff;
border-radius: 24rpx 24rpx 0 0;
.select-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #EBEEF5;
text {
font-size: 28rpx;
&:first-child {
color: #909399;
padding: 10rpx 20rpx;
}
&:last-child {
color: #1D64CF;
font-weight: 500;
padding: 10rpx 20rpx;
}
&.title {
font-size: 32rpx;
color: #303133;
font-weight: 500;
}
}
}
.checkbox-scroll {
max-height: 700rpx;
padding: 20rpx 0;
}
.checkbox-group {
padding: 0 30rpx;
}
.checkbox-item {
padding: 24rpx 0;
border-bottom: 1px solid #F2F6FC;
display: flex;
align-items: center;
&:last-child {
border-bottom: none;
}
// 修改 checkbox 样式
::v-deep .u-checkbox {
width: 100%;
margin: 0;
display: flex;
align-items: center;
&__label {
font-size: 28rpx;
color: #303133;
margin-left: 16rpx;
}
&__icon-wrap {
width: 36rpx;
height: 36rpx;
border-radius: 6rpx;
border: 2rpx solid #DCDFE6;
display: flex;
align-items: center;
justify-content: center;
&--checked {
background-color: #1D64CF;
border-color: #1D64CF;
}
}
}
}
}
// 增加选中态的样式
::v-deep .u-checkbox__icon-wrap--checked {
.u-checkbox__icon {
color: #fff;
transform: scale(0.8);
}
}
</style>

View File

@@ -0,0 +1,629 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 13:56:42
-->
<template>
<view>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 200rpx)':'calc(100vh - 194rpx)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">服务信息
<view v-if="!edit&&formData.id" class="btn" style="font-weight: normal;display: flex;"
@click="edit=true">编辑<u-icon name="edit-pen" color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<view class="self-form">
<view class="form-item">
<view class="form-label ">人员姓名<text class="required">*</text></view>
<view style="width: calc(100% - 120rpx);word-break: break-all;" @click="openPersonChooser"
:class="{disabledLine: !edit, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<view class="icon-right" style="width: 40rpx; height: 40rpx;"></view>
</view>
<view class="form-item">
<view class="form-label ">标题<text class="required">*</text></view>
<textarea :disabled="!edit" v-model="formData.recommendTopic"
:class="['form-textarea', { 'form-textarea-disabled': !edit }]"
placeholder="请输入"></textarea>
<view class="icon-right" style="width: 40rpx; height: 40rpx;"></view>
</view>
<view class="form-item">
<view class="form-label ">备注</view>
<textarea :disabled="!edit" v-model="formData.remark"
:class="['form-textarea', { 'form-textarea-disabled': !edit }]"
placeholder="请输入"></textarea>
<view class="icon-right" style="width: 40rpx; height: 40rpx;"></view>
</view>
<view class="form-item">
<view class="form-label ">附件</view>
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</view>
</view>
</view>
</view>
<view class="inner" v-if="showInfo != '1'">
<view class="part-title" style="margin-top: 32rpx;">求职需求信息</view>
<view class="inner-part">
<view class="self-form">
<view class="form-item">
<view class="form-label ">求职工种</view>
<view style="width: calc(100% - 120rpx);word-break: break-all;"
class="disabledLine">
{{ getJobWorkTypeName(activePersonInfo.jobWorkType) }}
</view>
</view>
<view class="form-item">
<view class="form-label ">最低薪酬</view>
<view style="width: calc(100% - 120rpx);word-break: break-all;"
class="disabledLine">
{{ activePersonInfo.minRecruitmentSalary || '--' }}
</view>
</view>
<view class="form-item">
<view class="form-label ">最高薪酬</view>
<view style="width: calc(100% - 120rpx);word-break: break-all;"
class="disabledLine">
{{ activePersonInfo.highRecruitmentSalary || '--' }}
</view>
</view>
</view>
<view class="tuijian-btn" v-if="edit" @click="showPositionChooser">推荐岗位</view>
</view>
</view>
<view class="inner">
<view class="part-title" style="margin-top: 32rpx;">人员推荐记录</view>
<view class="inner-part">
<view v-for="(item, index) in tuijianList" :key="index" class="job-list">
<view>{{ item.postName }}</view>
<view style="color: #8492a6;margin-top: 7rpx;">工种{{item.recruitWorkTypeName}}</view>
<view style="color: #8492a6;margin-top: 7rpx;">单位名称{{item.unitName}}</view>
<view class="del-btn" @click="removeTuijian(item)">删除</view>
</view>
<img v-if="!tuijianList.length" src="https://rc.jinan.gov.cn/qcwjyH5/static/images/person/empty.png"
style="width: 100%;display: block;margin: 0 auto;" />
<view v-if="!tuijianList.length" style="text-align: center;color: #8E8E8E;font-size: 24rpx;">暂无数据~
</view>
</view>
</view>
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
</scroll-view>
<choose-person style="width: 100%;position: relative;z-index: 2;" :choiceType="3" ref="personChooser" @confirm="personNameConfirm" />
<positionChooser ref="positionChooser" @confirm="jobListConfirm" />
<!-- <u-datetime-picker :show="show.actualSolveDate" v-model="dates.actualSolveDate" mode="date"
@confirm="confirmDate('actualSolveDate', $event)"
@cancel="cancelPicker('hopeSolveDate')"></u-datetime-picker> -->
<!-- <uni-popup ref="openDeal" style="position: relative;z-index: 2;">
<u--form class="self-form popup" labelPosition="top" :model="formData" :rules="rules" ref="uForm"
labelWidth="300" style="width: calc(100% - 64rpx);margin: 0 auto;">
<u-form-item label="实际办理时间" prop="actualSolveDate" required>
<view class="bordered" style="width: 100%;" @click="showPicker('actualSolveDate')"
:class="{noValue: !formData.actualSolveDate}">{{ formData.actualSolveDate||'请选择' }}</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="办理说明" prop="solveDesc" required>
<u-textarea v-model="formData.solveDesc" placeholder="请输入"></u-textarea>
</u-form-item>
</u--form>
<view class="button-area" style="width: 100%;margin-left: 0;box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);">
<view class="btn" @click="closeDeal">取消</view>
<view class="btn reset" @click="form.actualSolveDate = '';formData.solveDesc = ''">重置</view>
</view>
</uni-popup> -->
</view>
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<!-- <view class="btn save" @click="finishJobRecommend">办结</view> -->
<view class="btn save" @click="formData.currentStatus='2';saveInfo()">保存</view>
</view>
</view>
</template>
<script>
import {
deptTreeSelect
} from "@/apiRc/person";
import {
addJobRecommend,
updateJobRecommend,
getJobRecommend,
getAddedJobs,
saveJobRecommend
} from "@/apiRc/service/jobRecommend";
import {
getPersonDemand
} from "@/apiRc/needs/personDemand";
import { listJobType } from "@/apiRc/jobType/index";
import ImageUpload from '@/packageRc/components/ImageUpload'
import ChoosePerson from './choosePerson.vue';
import positionChooser from './positionChooser.vue';
import dayjs from "dayjs";
export default {
components: {
ChoosePerson,
positionChooser,
ImageUpload
},
props: {
showInfo: {
type: String,
default: '0'
}
},
data() {
return {
fileList: [],
jobTypeList:[],
edit: true,
originalDept: [],
personBase: {},
dates: {},
formData: {
recommendTopic: '',
personName: '',
},
rules: {
personName: [{
required: true,
message: '请填写姓名',
trigger: ['blur', 'change'],
}, ],
recommendTopic: [{
required: true,
message: '请填写服务需求标题',
trigger: ['blur', 'change'],
}, ],
},
dict: {},
show: {},
loading: false,
workParams: {},
activePersonInfo: {},
tuijianList: [],
openDeal: false,
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.loading = true;
this.$getDict('qcjy_zgzpgz').then(res => {
this.dict.salary = res.data
})
this.workTypeRemoteMethod()
},
methods: {
closeDeal() {
this.$refs.openDeal.close()
},
// saveDeal() {
// if (!this.formData.actualSolveDate) {
// uni.showToast({
// title: '请填写实际解决时间!',
// icon: 'none'
// })
// return;
// }
// if (!this.formData.solveDesc) {
// uni.showToast({
// title: '请填写办理说明!',
// icon: 'none'
// })
// return;
// }
// this.formData.currentStatus = '3'
// this.$refs.openDeal.close();
// this.saveInfo()
// },
// finishJobRecommend() {
// this.$refs.uForm.validate().then(res => {
// this.$refs.openDeal.open()
// }).catch(() => {
// uni.showToast({
// title: '请检查必填项填写',
// icon: 'none'
// })
// })
// },
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
removeTuijian({
id
}) {
if (!this.edit) return
this.tuijianList = this.tuijianList.filter(t => t.id !== id);
},
openPersonChooser() {
if (this.edit) {
console.log("this",this.activePersonInfo)
this.$refs.personChooser.open();
}
},
showPositionChooser() {
if (this.edit) {
console.log("this.params",this.workParams)
this.workParams.latitude=this.activePersonInfo.latitude
this.workParams.longitude=this.activePersonInfo.longitude
this.$refs.positionChooser.open(this.workParams);
}
},
personNameConfirm(event) {
this.formData.personName = event.personName
this.formData.personId = event.personId
this.formData.jobDemandInfoId = event.id
// this.form.personStatus = event.currentStatus;
this.activePersonInfo = event;
console.log("event",event)
this.formNameChange(event);
this.$forceUpdate();
},
jobListConfirm(event) {
this.tuijianList = event;
},
// changeFile(e) {
// if (e.length) {
// let data = e[0];
// this.formData.fileUrl = data.data ? data.data.url : data.url
// } else {
// this.formData.fileUrl = ''
// }
// },
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.edit = true
},
addForPerson({
jobDemandInfoId
}) {
if (!jobDemandInfoId) return
getPersonDemand(jobDemandInfoId).then(res => {
this.activePersonInfo = res.data
this.formNameChange(this.activePersonInfo)
})
},
// 单独设置 人员姓名 和 id
setPersonName(data){
this.formData.personName = data.personName
this.formData.personId = data.personId
this.formData.jobDemandInfoId = data.jobDemandInfoId
this.addForPerson(data)
},
getDetail(id) {
// 查询角色详情
getJobRecommend(id).then(res => {
this.formData = res.data;
this.fileList = this.$processFileUrl(this.formData.fileUrl)
// 获取详情的时候 调用方法 拿到求职需求详情
this.addForPerson(res.data)
this.edit = false
this.getAddedJobsList(res.data)
})
},
// 获取推荐人员列表
getAddedJobsList({
postIdList
}) {
getAddedJobs({
postIdList,
pageNum: 1,
pageSize: 10000
}).then((res) => {
this.tuijianList = res.rows;
});
},
confirmDate(type, e) {
this.show[type] = false;
let date = new Date(e.value)
this.formData[type] =
`${date.getFullYear()}-${(date.getMonth()+1)>9?(date.getMonth()+1):('0'+(date.getMonth()+1))}-${date.getDate()>9?date.getDate():('0'+date.getDate())}`
this.$forceUpdate();
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
this.$forceUpdate();
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
workTypeRemoteMethod(key) {
listJobType({
workTypeName: key,
pageNum: 1,
pageSize: 50,
}).then((res) => {
this.jobTypeList = res.rows;
});
},
getJobWorkTypeName(data){
if (data) {
let arr = this.jobTypeList.filter((ele) => ele.id == data);
if(arr.length){
return arr[0].workTypeName;
}else{
return '--'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
this.$forceUpdate();
},
// showPicker(type) {
// if (this.edit) {
// this.show[type] = true
// this.$forceUpdate()
// }
// },
formNameChange(e) {
let date = new Date()
// let day =
// `${date.getFullYear()}-${(date.getMonth()+1) + 1 > 9 ? (date.getMonth()+1) + 1: '0'+((date.getMonth()+1) + 1)}-${date.getDate() > 9 ? date.getDate(): '0'+date.getDate()}`
const dayNew = dayjs(date).format("YYYY-MM-DD");
this.formData.recommendTopic =
`${this.$store.state.user.nick}_于${dayNew}对人员_${this.formData.personName}_进行_${this.getJobWorkTypeName(e.jobWorkType)}岗位推荐`;
this.$set(this.workParams, "recruitWorkType", e.jobWorkType);
this.$set(this.workParams, "workLocation", e.hopeWorkLocation);
this.$set(this.workParams, "minRecruitmentSalary", e.minRecruitmentSalary);
this.$set(this.workParams, "highRecruitmentSalary", e.highRecruitmentSalary);
this.$set(this.workParams, "longitude", e.longitude);
this.$set(this.workParams, "latitude", e.latitude);
// this.$set(this.workParams, "userId", e.userId);
},
async saveInfo() {
uni.showLoading();
try {
// 验证表单
let isValid = true
// = await this.$refs.uForm.validate();
for(let prop in this.rules){
this.rules[prop].forEach(ele => {
if(ele.required = false && !this.formData[prop]){
isValid = false
}
})
}
if (!isValid) {
uni.showToast({
title: '请检查必填项填写',
icon: 'none'
})
// throw new Error('请检查必填项填写');
}
// 显示全局加载
// 更新 formData 中的 postIdList
this.formData.postIdList = this.tuijianList.map((ele) => ele.id);
this.formData.id = this.formData.jobDemandInfoId;
// 保存职位推荐
const response = await saveJobRecommend(this.formData);
// 检查响应码是否为200
if (response.code === 200) {
uni.showToast({title: '提交成功', icon: 'none'});
}
// 延迟1秒后返回上一页
setTimeout(() => {
uni.navigateBack();
}, 1000);
} catch (error) {
uni.showToast({title: '错误详情:' + error, icon: 'none'});
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
},
// saveInfo() {
// this.$refs.uForm.validate().then(res => {
// this.formData.postIdList = this.tuijianList.map((ele) => ele.id)
// saveJobRecommend(this.formData).then(response => {
// if (response.code == 200) {
// uni.showToast({
// title: '提交成功'
// })
// }
// uni.navigateBack();
// });
// if(this.formData.id){
// updateJobRecommend(this.formData).then(res => {
// if(res.code == 200) {
// uni.showToast({
// title: '修改成功'
// })
// this.edit = false;
// }
// })
// }else{
// addJobRecommend(this.formData).then(res => {
// if(res.code == 200) {
// uni.showToast({
// title: '保存成功'
// })
// uni.navigateBack();
// }
// })
// }
// }).catch((e) => {
// uni.showToast({
// title: '请检查必填项填写',
// icon: 'none'
// })
// })
// }
}
}
</script>
<style lang="scss">
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
width: 100%;
}
// 改进选择器样式
.picker-view {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 28rpx 36rpx;
background: #ffffff;
border: 2rpx solid #e5e5e5;
border-radius: 12rpx;
min-height: 88rpx;
box-sizing: border-box;
transition: all 0.3s ease;
position: relative;
&:active {
background: #f8f9fa;
border-color: #007aff;
transform: scale(0.98);
}
&::after {
content: '';
position: absolute;
right: 36rpx;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
border-top: 12rpx solid #999999;
}
.picker-text {
color: #333333;
font-size: 28rpx;
flex: 1;
}
.picker-placeholder {
color: #999999;
font-size: 28rpx;
}
}
// 选中状态的样式
.picker-view.selected {
border-color: #1D64CF;
background: #f0f8ff;
&::after {
border-top-color: #1D64CF;
}
}
.tuijian-btn {
background: #197cd2;
line-height: 60rpx;
width: 176rpx;
margin-right: 16rpx;
margin-top: 24rpx;
font-size: 28rpx;
color: #fff;
text-align: center;
border-radius: 8rpx;
margin: 0 auto;
}
.job-list {
padding: 24rpx 32rpx;
border-radius: 8rpx;
box-sizing: border-box;
border: 1px solid #e4e4e4;
margin-bottom: 24rpx;
position: relative;
&.active {
border: 1px solid #1890ff;
}
.del-btn {
background: #E95A49;
line-height: 48rpx;
width: 120rpx;
margin-right: 0;
margin-top: 0rpx;
margin-left: auto;
font-size: 24rpx;
color: #fff;
text-align: center;
border-radius: 8rpx;
}
}
.self-form.popup {
padding-top: 32rpx;
.bordered {
border: 1rpx solid #dadbde;
padding: 9px;
border-radius: 4px;
}
}
.form-label{
width: 120rpx;
}
</style>

View File

@@ -0,0 +1,399 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:16:13
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 150px)':'calc(100vh - 144px)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">服务信息
<view v-if="!edit&&formData.id" class="btn" style="font-weight: normal;display: flex;"
@click="edit=true">编辑<u-icon name="edit-pen" color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<u--form labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form"
labelWidth="110">
<u-form-item label="姓名" prop="personName" required>
<view style="width: 100%;" @click="openPersonChooser"
:class="{disabledLine: !edit, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="人员状态" prop="personStatus">
<view style="width: 100%;" @click="showPicker('personStatus')"
:class="{disabledLine: !edit, noValue: !formData.personStatus}">
{{ getDictLabel(formData.personStatus, dict.personStatus)||'请选择' }}
</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="就业类别" prop="employmentType" required>
<view style="width: 100%;" @click="showPicker('employmentType')"
:class="{disabledLine: !edit, noValue: !formData.employmentType}">
{{ getDictLabel(formData.employmentType, dict.employmentType)||'请选择' }}
</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="就业单位" prop="employmentUnit" required>
<u--input :disabled="!edit" v-model="formData.employmentUnit" border="none"
placeholder="请输入"></u--input>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="就业状态" prop="employmentStatus" required>
<view style="width: 100%;" @click="showPicker('employmentStatus')"
:class="{disabledLine: !edit, noValue: !formData.employmentStatus}">
{{ getDictLabel(formData.employmentStatus, dict.employmentStatus)||'请选择' }}
</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="就业岗位" prop="employmentPosition">
<u--input :disabled="!edit" v-model="formData.employmentPosition" border="none"
placeholder="请输入"></u--input>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="岗位工资" prop="money">
<u--input :disabled="!edit" v-model="formData.money" border="none"
placeholder="请输入"></u--input>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="就业时间" prop="time">
<view style="width: 100%;" @click="showPicker('time')"
:class="{disabledLine: !edit, noValue: !formData.time}">{{ formData.time||'请选择' }}
</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
</u--form>
</view>
</view>
<view class="inner" style="margin-top: 32rpx;">
<view class="inner-part">
<u--form labelPosition="left" class="self-form" labelWidth="110">
<u-form-item label="备注" prop="remark">
<u-textarea :disabled="!edit" v-model="formData.remark" placeholder="请输入"></u-textarea>
</u-form-item>
</u--form>
</view>
</view>
<view class="inner">
<view class="part-title" style="margin-top: 32rpx;">附件信息</view>
<view class="inner-part">
<u--form labelPosition="left" class="self-form" labelWidth="110">
<u-form-item label="附件" prop="fileUrl">
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</u-form-item>
</u--form>
</view>
</view>
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
</scroll-view>
<u-datetime-picker :show="show.time" v-model="dates.time" mode="date" @confirm="confirmDate('time', $event)"
@cancel="cancelPicker('time')"></u-datetime-picker>
<u-picker :show="show.personStatus" :columns="[dict.personStatus]" keyName="dictLabel"
@confirm="pickerConfirm('personStatus', $event)" @cancel="cancelPicker('personStatus')"></u-picker>
<u-picker :show="show.employmentType" :columns="[dict.employmentType]" keyName="dictLabel"
@confirm="pickerConfirm('employmentType', $event)" @cancel="cancelPicker('employmentType')"></u-picker>
<u-picker :show="show.employmentStatus" :columns="[dict.employmentStatus]" keyName="dictLabel"
@confirm="pickerConfirm('employmentStatus', $event)" @cancel="cancelPicker('employmentStatus')"></u-picker>
<choose-person ref="personChooser" @confirm="personNameConfirm" />
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<view class="btn reset" @click="formData = {}" v-if="!formData.id">重置</view>
<view class="btn save" @click="saveInfo">保存</view>
</view>
</view>
</template>
<script>
import {
addJobTrack,
updateJobTrack,
getJobTrack
} from "@/apiRc/service/jobTrack";
import ImageUpload from '@/packageRc/components/ImageUpload'
import ChoosePerson from './choosePerson.vue';
export default {
components: {
ChoosePerson,
ImageUpload
},
data() {
return {
edit: true,
personBase: {},
dates: {},
formData: {
personName: '',
time: '',
visitor: '',
},
rules: {
personName: [{
required: true,
message: '请填写姓名',
trigger: ['blur', 'change'],
}, ],
employmentType: [{
required: true,
message: '请选择就业类别',
trigger: ['blur', 'change'],
}, ],
employmentUnit: [{
required: true,
message: '请填写就业单位',
trigger: ['blur', 'change'],
}, ],
employmentStatus: [{
required: true,
message: '请选择就业状态',
trigger: ['blur', 'change'],
}, ],
},
dict: {},
show: {},
loading: false,
fileList: [],
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.loading = true;
let arr = [{
key: 'qcjy_ryzt',
prop: 'personStatus'
},
{
key: 'qcjy_jylb',
prop: 'employmentType'
},
{
key: 'qcjy_jyzt',
prop: 'employmentStatus'
},
]
arr.forEach(ele => {
this.$getDict(ele.key).then(res => {
this.dict[ele.prop] = res.data
this.$forceUpdate();
})
})
},
methods: {
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
openPersonChooser() {
if (this.edit) {
this.$refs.personChooser.open();
}
},
personNameConfirm(event) {
this.formData.personName = event.name
this.formData.personId = event.id
this.$forceUpdate();
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.edit = true
},
getDetail(id) {
getJobTrack(id).then(res => {
this.formData = res.data;
this.edit = false
this.fileList = this.$processFileUrl(this.formData.fileUrl)
})
},
confirmDate(type, e) {
this.show[type] = false;
let date = new Date(e.value)
this.formData[type] =
`${date.getFullYear()}-${(date.getMonth()+1)>9?(date.getMonth()+1):('0'+(date.getMonth()+1))}-${date.getDate()>9?date.getDate():('0'+date.getDate())}`
this.$forceUpdate();
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
this.$forceUpdate();
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
this.$forceUpdate();
},
showPicker(type) {
if (this.edit) {
this.show[type] = true
this.$forceUpdate()
}
},
async saveInfo() {
try {
// 验证表单
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('请检查必填项填写');
}
// 显示全局加载
this.$showLoading();
// 根据 formData 是否有 id 来决定是更新还是新增
let successMessage;
let response;
if (this.formData.id) {
response = await updateJobTrack(this.formData);
successMessage = '修改成功';
} else {
response = await addJobTrack(this.formData);
successMessage = '保存成功';
}
// 检查响应码是否为200
if (response.code === 200) {
this.$u.toast(successMessage);
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
await this.$delay(1000); // 延迟1秒后返回上一页
uni.navigateBack();
}
}
} catch (error) {
this.$u.toast('错误详情:' + error);
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
},
// saveInfo() {
// this.$refs.uForm.validate().then(res => {
// if (this.formData.id) {
// updateJobTrack(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '修改成功'
// })
// this.edit = false;
// }
// })
// } else {
// addJobTrack(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '保存成功'
// })
// uni.navigateBack();
// }
// })
// }
// }).catch(() => {
// uni.showToast({
// title: '请检查必填项填写',
// icon: 'none'
// })
// })
// }
}
}
</script>
<style lang="scss">
.page ::v-deep .u-navbar__content {
background-color: transparent !important;
}
.page {
background-color: #EEF1F5 !important;
height: 100vh;
background-image: url('https://rc.jinan.gov.cn/qcwjyH5/static/images/top.png');
background-repeat: no-repeat;
background-size: 100% auto;
}
.button-area {
padding: 24rpx 32rpx 68rpx;
width: calc(100% + 64rpx);
margin-left: -32rpx;
background: #fff;
display: flex;
box-sizing: border-box;
margin-top: 40rpx;
border-radius: 16px 16px 0px 0px;
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
</style>

View File

@@ -0,0 +1,331 @@
<!--
* @Date: 2024-10-09 17:07:39
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:16:17
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 150px)':'calc(100vh - 144px)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">服务信息
<view v-if="!edit&&formData.id" class="btn" style="font-weight: normal;display: flex;"
@click="edit=true">编辑<u-icon name="edit-pen" color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<u--form labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form"
labelWidth="110">
<u-form-item label="姓名" prop="personName" required>
<view style="width: 100%;" @click="openPersonChooser"
:class="{disabledLine: !edit, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<!-- <u--input disabled v-model="formData.personName" border="none" placeholder="请输入" ></u--input> -->
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="咨询时间" prop="time" required>
<view style="width: 100%;" @click="showPicker('time')"
:class="{disabledLine: !edit, noValue: !formData.time}">{{ formData.time||'请选择' }}
</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="咨询讲解人员" prop="expositor" required>
<u--input :disabled="!edit" v-model="formData.expositor" border="none"
placeholder="请输入"></u--input>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
</u--form>
</view>
</view>
<view class="inner" style="margin-top: 32rpx;">
<view class="inner-part">
<u--form labelPosition="left" class="self-form" labelWidth="110">
<u-form-item label="情况说明" prop="content">
<u-textarea :disabled="!edit" v-model="formData.content" placeholder="请输入"></u-textarea>
</u-form-item>
</u--form>
</view>
</view>
<view class="inner">
<view class="part-title" style="margin-top: 32rpx;">附件信息</view>
<view class="inner-part">
<u--form labelPosition="left" class="self-form" labelWidth="110">
<u-form-item label="附件" prop="fileUrl">
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</u-form-item>
</u--form>
</view>
</view>
<handler-data style="margin-top: 30rpx;" v-if="false"/>
</scroll-view>
<u-datetime-picker :show="show.time" v-model="dates.time" mode="date" @confirm="confirmDate('time', $event)"
@cancel="cancelPicker('time')"></u-datetime-picker>
<choose-person ref="personChooser" @confirm="personNameConfirm" />
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<view class="btn reset" @click="formData = {}" v-if="!formData.id">重置</view>
<view class="btn save" @click="saveInfo">保存</view>
</view>
</view>
</template>
<script>
import {
addPolicyConsultation,
updatePolicyConsultation,
getPolicyConsultation
} from "@/apiRc/service/policyConsultation";
import ImageUpload from '@/packageRc/components/ImageUpload'
import ChoosePerson from './choosePerson.vue';
export default {
components: {
ChoosePerson,
ImageUpload,
},
data() {
return {
fileList: [],
edit: true,
personBase: {},
dates: {},
formData: {
demandTitle: '',
isAcceptAssistance: '',
isAcceptApprovalResult: '',
personName: '',
},
rules: {
time: [{
required: true,
message: '请填写咨询讲解人员',
trigger: ['blur', 'change'],
}, ],
expositor: [{
required: true,
message: '请选择咨询时间',
trigger: ['blur', 'change'],
}, ],
personName: [{
required: true,
message: '请填写姓名',
trigger: ['blur', 'change'],
}, ],
},
show: {},
loading: false,
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.loading = true;
},
methods: {
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
openPersonChooser() {
if (this.edit) {
this.$refs.personChooser.open();
}
},
personNameConfirm(event) {
this.formData.personName = event.name
this.formData.personId = event.id
this.$forceUpdate();
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.edit = true
},
getDetail(id) {
getPolicyConsultation(id).then(res => {
this.formData = res.data;
this.edit = false
this.fileList = this.$processFileUrl(this.formData.fileUrl)
})
},
confirmDate(type, e) {
this.show[type] = false;
let date = new Date(e.value)
this.formData[type] =
`${date.getFullYear()}-${(date.getMonth()+1)>9?(date.getMonth()+1):('0'+(date.getMonth()+1))}-${date.getDate()>9?date.getDate():('0'+date.getDate())}`
console.log(this.show[type], type)
this.$forceUpdate();
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
this.$forceUpdate();
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
this.$forceUpdate();
},
showPicker(type) {
if (this.edit) {
this.show[type] = true
this.$forceUpdate()
}
},
async saveInfo() {
try {
// 验证表单
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('请检查必填项填写');
}
// 显示全局加载
this.$showLoading();
// 根据 formData 是否有 id 来决定是更新还是新增
let response;
let successMessage;
if (this.formData.id) {
response = await updatePolicyConsultation(this.formData);
successMessage = '修改成功';
} else {
response = await addPolicyConsultation(this.formData);
successMessage = '保存成功';
}
// 检查响应码是否为200
if (response.code === 200) {
this.$u.toast(successMessage);
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
await this.$delay(1000); // 延迟1秒后返回上一页
uni.navigateBack();
}
}
} catch (error) {
this.$u.toast('错误详情:' + error);
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
},
// saveInfo() {
// this.$refs.uForm.validate().then(res => {
// if (this.formData.id) {
// updatePolicyConsultation(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '修改成功'
// })
// this.edit = false;
// }
// })
// } else {
// addPolicyConsultation(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '保存成功'
// })
// uni.navigateBack();
// }
// })
// }
// }).catch(() => {
// uni.showToast({
// title: '请检查必填项填写',
// icon: 'none'
// })
// })
// }
}
}
</script>
<style lang="scss">
.page ::v-deep .u-navbar__content {
background-color: transparent !important;
}
.page {
background-color: #EEF1F5 !important;
height: 100vh;
background-image: url('https://rc.jinan.gov.cn/qcwjyH5/static/images/top.png');
background-repeat: no-repeat;
background-size: 100% auto;
}
.button-area {
padding: 24rpx 32rpx 68rpx;
width: calc(100% + 64rpx);
margin-left: -32rpx;
background: #fff;
display: flex;
box-sizing: border-box;
margin-top: 40rpx;
border-radius: 16px 16px 0px 0px;
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
</style>

View File

@@ -0,0 +1,388 @@
<template>
<uni-popup ref="showPersonChooser" type="bottom" round background-color="#fff">
<view style="padding: 32rpx 0">
<!-- <u--input @change="searchChange" placeholder="搜索选择岗位" v-model="searchPerson"></u--input> -->
<scroll-view style="height: 900rpx;" :scroll-y="true" @scrolltolower="getBottomList">
<!-- 搜索区域 -->
<view class="search-area">
<view class="search-inputs">
<input
v-model="searchValue"
placeholder="请输入公司/岗位名称"
border="surround"
clearable
class="search-input"
/>
</view>
<button type="primary" @click="onSearch" class="search-btn">搜索</button>
</view>
<!-- 岗位列表 -->
<view v-for="(item, index) in jobList"
:key="index"
@click="chooseJob(item)"
class="job-card"
:class="{active: activeJobList.indexOf(item.id)!=-1}">
<!-- 岗位名称和薪资 -->
<view class="job-header">
<text class="job-title">{{item.postName}}</text>
<text class="job-salary">{{formatSalary(item.minRecruitmentSalary, item.highRecruitmentSalary)}}</text>
</view>
<!-- 标签区域 -->
<view class="tag-area">
<text class="tag">{{getDictLabel(item.minEducation, xue_li) || '学历不限'}}</text>
<text class="tag">{{item.profession || '专业不限'}}</text>
<text class="tag">全职</text>
</view>
<!-- 公司信息 -->
<view class="company-info">
<view class="company-detail">
<text class="company-name">{{item.unitName}}</text>
<view class="location-line">
<text class="location">
<text class="location-icon">📍</text>
{{item.workLocation || '暂无地址'}}
</text>
</view>
</view>
</view>
<!-- 推荐标记 -->
<view class="recommend-tag" v-if="choosedIdList.indexOf(item.id) != -1">推荐</view>
</view>
<view v-if="loadingJob">加载中...</view>
<div v-if="jobList.length == 0&&!loadingJob" :text="'暂无数据'"></div>
</scroll-view>
<view class="button-area">
<view class="btn" @click="closeshowPersonChooser">取消</view>
<view class="btn save" @click="saveInfo">确定</view>
</view>
<!-- <view style="color: #8492a6;margin-top: 7rpx;">距离
<text style="color: #fa6553;">{{item.distance || '--'}} km</text>
</view> -->
</view>
</uni-popup>
</template>
<script>
import { getWorkListReq } from '@/apiRc/service/jobRecommend'
export default {
data() {
return {
showPersonChooser: false,
activeJobList: [],
searchPerson: '',
searcher: '',
workParams: {},
jobList: [],
jobTotal: 0,
showMorePage: true,
choosedIdList: [],
loadingJob: false,
xue_li:[],
searchValue: '',
searchJob: '',
}
},
methods: {
onSearch() {
// 重置页码和列表
this.workParams.pageNum = 1;
this.jobList = [];
// 添加搜索条件
this.workParams.searchValue = this.searchValue;
this.doSearch();
},
formatSalary(min, max) {
if (!min && !max) return '薪资面议';
if (!min) return `${max}元/月`;
if (!max) return `${min}元/月`;
return `${min}-${max}元/月`;
},
closeshowPersonChooser() {
this.$refs.showPersonChooser.close()
},
open(workParams) {
console.log("workparams",workParams)
this.$refs.showPersonChooser.open()
this.activeJobList = []
// this.workParams = workParams
this.workParams = {
// ...workParams,
recruitWorkType: workParams.recruitWorkType,
// longitude: workParams.longitude,
// latitude: workParams.latitude,
pageNum: 1,
pageSize: 10,
latitude:workParams.latitude,
longitude:workParams.longitude
}
this.jobTotal = 0;
this.jobList = [];
this.doSearch()
},
saveInfo() {
this.$emit('confirm', this.activeJobList)
this.$refs.showPersonChooser.close()
},
searchChange(){
if(this.searcher){
clearTimeout(this.searcher)
this.doSearch()
}else{
this.doSearch()
}
}, // 触底加载
getBottomList() {
if (this.workParams.pageNum * this.workParams.pageSize >= this.jobTotal) {
this.showMorePage = false;
} else if (this.workParams.pageNum * this.workParams.pageSize < this.jobTotal) {
this.workParams.pageNum++;
this.doSearch();
if (this.workParams.pageNum * this.workParams.pageSize >= this.jobTotal) {
this.showMorePage = false;
}
}
},
getDictLabel(value, list) {
if (list && value) {
const found = list.find(ele => ele.dictValue === value);
return found ? found.dictLabel : '学历不限';
}
return '学历不限';
},
doSearch() {
this.loadingJob = true;
// 先获取学历字典
this.$getDict('qcjy_jycd').then(res => {
this.xue_li = res.data;
// 再获取岗位列表
getWorkListReq(this.workParams).then((res) => {
this.loadingJob = false;
if (res.code == 200) {
if (res.rows.length < 10) {
this.showMorePage = false;
}
this.loading = false;
this.jobList = this.jobList.concat(res.rows);
this.jobTotal = res.total;
} else {
this.loading = false;
uni.showToast({
title: res.msg,
icon: "none",
});
}
});
});
},
chooseJob(item) {
let index = this.choosedIdList.indexOf(item.id);
if(index == -1){
this.activeJobList.push(item);
this.choosedIdList.push(item.id);
}else{
this.activeJobList.splice(index, 1);
this.choosedIdList.splice(index, 1);
}
this.$forceUpdate();
},
}
}
</script>
<style lang="scss" scoped>
.person-list{
padding: 24rpx 32rpx;
border-radius: 8rpx;
box-sizing: border-box;
border: 1px solid #e4e4e4;
margin-top: 32rpx;
position: relative;
&.active{
border: 1px solid #1890ff;
}
.tjBtn{
position: absolute;
right: -16rpx;
top: 0;
line-height: 48rpx;
width: 120rpx;
margin-right: 16rpx;
font-size: 24rpx;
color: #fff;
text-align: center;
border-radius: 0 8rpx 0 8rpx;
background: #1D64CF;
}
}
// .button-area{
// box-shadow: 0 0 10rpx rgba(0,0,0,0.1);
// padding: 24rpx 32rpx 68rpx;
// width: calc(100% + 64rpx);
// margin-left: -32rpx;
// background: #fff;
// display: flex;
// box-sizing: border-box;
// margin-top: 40rpx;
// border-radius: 16px 16px 0px 0px;
// .btn{
// line-height: 72rpx;
// width: 176rpx;
// margin-right: 16rpx;
// font-size: 28rpx;
// border: 1px solid #B8C5D4;
// color: #282828;
// text-align: center;
// border-radius: 8rpx;
// }
// .reset{
// background: #DCE2E9;
// }
// .save{
// background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
// color: #fff;
// border: 0;
// flex-grow: 1;
// }
// }
.part-title{
margin-bottom: 10rpx;
font-size: 28rpx;
font-weight: bold;
}
.search-area {
padding: 20rpx 32rpx;
display: flex;
align-items: center;
gap: 16rpx;
.search-inputs {
flex: 1;
display: flex;
gap: 16rpx;
.search-input {
flex: 1;
border: 1px solid #e4e4e4;
border-radius: 40rpx;
height: 60rpx;
padding: 0 16rpx;
}
}
.search-btn {
width: 140rpx;
height: 60rpx;
line-height: 60rpx;
margin: 0;
background: #1890ff;
color: #fff;
font-size: 24rpx;
}
}
.job-card {
background: #FFFFFF;
border-radius: 12rpx;
padding: 24rpx;
margin: 0 32rpx 20rpx;
position: relative;
border: 1px solid #EBEEF5;
&.active {
border: 1px solid #1890ff;
}
}
.job-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
}
.job-title {
font-size: 32rpx;
font-weight: 500;
color: #333333;
}
.job-salary {
font-size: 28rpx;
color: #FA6553;
font-weight: 500;
}
.tag-area {
display: flex;
gap: 12rpx;
margin-bottom: 16rpx;
flex-wrap: wrap;
}
.tag {
font-size: 24rpx;
color: #666666;
background: #F5F7FA;
padding: 4rpx 12rpx;
border-radius: 4rpx;
}
.company-info {
display: flex;
align-items: center;
}
.company-detail {
flex: 1;
}
.company-name {
font-size: 26rpx;
color: #666666;
display: block;
}
.location-line {
display: flex;
align-items: center;
gap: 16rpx;
margin-top: 4rpx;
}
.location {
font-size: 24rpx;
color: #666666;
display: flex;
align-items: center;
.location-icon {
font-size: 24rpx;
margin-right: 4rpx;
}
}
.post-date {
font-size: 24rpx;
color: #999999;
}
.recommend-tag {
position: absolute;
right: -2rpx;
top: 0;
background: #1D64CF;
color: #FFFFFF;
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 0 12rpx 0 12rpx;
}
</style>

View File

@@ -0,0 +1,445 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 14:16:11
-->
<template>
<view class="input-outer-part">
<scroll-view scroll-y="true" :style="{height: edit?'calc(100vh - 150px)':'calc(100vh - 144px)'}">
<view class="inner">
<view class="part-title" style="display: flex;justify-content: space-between;">服务信息
<view v-if="!edit&&formData.id" class="btn" style="font-weight: normal;display: flex;"
@click="edit=true">编辑<u-icon name="edit-pen" color="#A6A6A6"></u-icon></view>
</view>
<view class="inner-part">
<u--form labelPosition="left" :model="formData" :rules="rules" ref="uForm" class="self-form"
labelWidth="110">
<u-form-item label="姓名" prop="personName" required>
<view style="width: 100%;" @click="openPersonChooser"
:class="{disabledLine: !edit, noValue: !formData.personName}">
{{ formData.personName || '请选择' }}
</view>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<!-- <u-form-item label="人员状态" prop="personStatus">
<view style="width: 100%;" @click="showPicker('personStatus')" :class="{disabledLine: !edit, noValue: !formData.personStatus}">{{ getDictLabel(formData.personStatus, dict.personStatus)||'请选择' }}</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6" ></u-icon>
</u-form-item> -->
<u-form-item label="培训人员" prop="trainingStaff" required>
<u--input :disabled="!edit" v-model="formData.trainingStaff" border="none"
placeholder="请输入"></u--input>
<u-icon slot="right" name="edit-pen" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="培训时间" prop="time" required>
<view style="width: 100%;" @click="showPicker('time')"
:class="{disabledLine: !edit, noValue: !formData.time}">{{ formData.time||'请选择' }}
</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="培训题目" prop="trainingTopic" required>
<u-textarea :disabled="!edit" v-model="formData.trainingTopic"
placeholder="请输入"></u-textarea>
</u-form-item>
<u-form-item label="培训内容" prop="trainingContent" required>
<u-textarea :disabled="!edit" v-model="formData.trainingContent"
placeholder="请输入"></u-textarea>
</u-form-item>
</u--form>
</view>
</view>
<view class="inner">
<view class="part-title" style="margin-top: 32rpx;">附件信息</view>
<view class="inner-part">
<u--form labelPosition="left" class="self-form" labelWidth="110">
<u-form-item label="附件" prop="fileUrl">
<ImageUpload :fileList="fileList" @update="changeFile" :maxCount="6" />
</u-form-item>
</u--form>
</view>
</view>
<!-- 办理完成后 需求说明 -->
<req-comp :form="{
actualSolveDate: formData.actualSolveDate,
actualSolvePeople: formData.actualSolvePeople,
solveDesc: formData.solveDesc,
fileUrl: formData.fileUrl
}" />
</scroll-view>
<u-datetime-picker :show="show.time" v-model="dates.time" mode="date" @confirm="confirmDate('time', $event)"
@cancel="cancelPicker('time')"></u-datetime-picker>
<u-datetime-picker :show="show.actualSolveDate" v-model="dates.actualSolveDate" mode="date"
@confirm="confirmDate('actualSolveDate', $event)"
@cancel="cancelPicker('actualSolveDate')"></u-datetime-picker>
<!-- <u-picker :show="show.personStatus" :columns="[dict.personStatus]" keyName="dictLabel" @confirm="pickerConfirm('personStatus', $event)" @cancel="cancelPicker('personStatus')"></u-picker> -->
<choose-person :choiceType="4" ref="personChooser" @confirm="personNameConfirm" />
<u-popup :show="openDeal" style="position: relative;z-index: 2;">
<u--form class="self-form popup" labelPosition="top" :model="formData" :rules="rules" ref="uForm"
labelWidth="300" style="width: calc(100% - 64rpx);margin: 0 auto;">
<u-form-item label="实际办理时间" prop="actualSolveDate" required>
<view class="bordered" style="width: 100%;" @click="showPicker('actualSolveDate')"
:class="{noValue: !formData.actualSolveDate}">{{ formData.actualSolveDate||'请选择' }}</view>
<u-icon slot="right" name="arrow-down" color="#A6A6A6"></u-icon>
</u-form-item>
<u-form-item label="办理说明" prop="solveDesc" required>
<u-textarea v-model="formData.solveDesc" placeholder="请输入"></u-textarea>
</u-form-item>
</u--form>
<view class="button-area" style="width: 100%;margin-left: 0;box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);">
<view class="btn" @click="openDeal = false">取消</view>
<view class="btn reset" @click="form.actualSolveDate = '';formData.solveDesc = ''">重置</view>
<!-- <view class="btn save" @click="saveDeal">办结</view> -->
</view>
</u-popup>
<view class="button-area" v-if="edit">
<view class="btn" @click="cancelPage">取消</view>
<!-- <view class="btn save" @click="finishSkillTrain">办结</view> -->
<view class="btn save" @click="formData.skillTrainingStatus='2';saveInfo()">保存</view>
</view>
</view>
</template>
<script>
import {
addSkillTrain,
updateSkillTrain,
getSkillTrain
} from "@/apiRc/service/skillTrain";
import ImageUpload from '@/packageRc/components/ImageUpload'
import ChoosePerson from './choosePerson.vue';
export default {
components: {
ChoosePerson,
ImageUpload
},
data() {
return {
fileList: [],
edit: true,
personBase: {},
dates: {},
formData: {
personName: '',
trainingStaff: '',
time: '',
trainingTopic: '',
trainingContent: '',
},
rules: {
personName: [{
required: true,
message: '请填写姓名',
trigger: ['blur', 'change'],
}, ],
trainingStaff: [{
required: true,
message: '请填写培训人员',
trigger: ['blur', 'change'],
}, ],
time: [{
required: true,
message: '请选择培训时间',
trigger: ['blur', 'change'],
}, ],
trainingTopic: [{
required: true,
message: '请填写培训题目',
trigger: ['blur', 'change'],
}, ],
trainingContent: [{
required: true,
message: '请填写培训内容',
trigger: ['blur', 'change'],
}, ],
},
dict: {},
show: {},
loading: false,
openDeal: false,
form: {},
}
},
onReady() {
this.$refs.uForm.setRules(this.rules)
},
created() {
this.$getDict('qcjy_ryzt').then(res => {
this.dict.personStatus = res.data
})
this.loading = true;
},
methods: {
cancelPage() {
if (this.formData.id) {
this.edit = false;
this.getDetail(this.formData.id)
} else {
uni.navigateBack()
}
},
saveDeal() {
if (!this.formData.actualSolveDate) {
uni.showToast({
title: '请填写实际解决时间!',
icon: 'none'
})
return;
}
if (!this.formData.solveDesc) {
uni.showToast({
title: '请填写办理说明!',
icon: 'none'
})
return;
}
this.formData.skillTrainingStatus = '3'
this.openDeal = false;
this.saveInfo()
},
finishSkillTrain() {
this.$refs.uForm.validate().then(res => {
this.openDeal = true;
}).catch(() => {
uni.showToast({
title: '请检查必填项填写',
icon: 'none'
})
})
},
openPersonChooser() {
if (this.edit) {
this.$refs.personChooser.open();
}
},
personNameConfirm(event) {
this.formData.personName = event.personName
this.formData.personId = event.personId
this.formData.skillTrainingId = event.id
this.formNameChange();
this.$forceUpdate();
},
changeFile(e) {
// 清空当前的 fileUrl 数组
this.formData.fileUrl = [];
// 如果 e 有长度(即用户选择了文件)
if (e.length) {
// 遍历每个文件对象并获取其 url
for (let data of e) {
const url = data.data ? data.data.url : data.url;
this.formData.fileUrl.push(url);
}
}
this.formData.fileUrl = this.$arrayToString(this.formData.fileUrl)
},
addOne() {
this.formData = {}
this.edit = true
},
// addForPerson(options) {
// this.formData = {
// personName: options.personName,
// personId: options.personId,
// skillTrainingId: options.skillTrainingId
// }
// this.edit = true
// },
getDetail(id) {
getSkillTrain(id).then(res => {
this.formData = res.data || {};
this.edit = false
if(this.formData.fileUrl) {
this.fileList = this.$processFileUrl(this.formData.fileUrl)
}
})
},
confirmDate(type, e) {
this.show[type] = false;
let date = new Date(e.value)
this.formData[type] =
`${date.getFullYear()}-${(date.getMonth()+1)>9?(date.getMonth()+1):('0'+(date.getMonth()+1))}-${date.getDate()>9?date.getDate():('0'+date.getDate())}`
this.$forceUpdate();
},
goBack() {
uni.navigateBack();
},
cancelPicker(type) {
this.show[type] = false
this.$forceUpdate();
},
// 单独设置 人员姓名 和 id
setPersonName(data){
this.formData.personName = data.personName
this.formData.personId = data.personId
this.formData.skillTrainingId = data.skillTrainingId
// this.addForPerson(data)
},
getDictLabel(value, list) {
if (list) {
let arr = list.filter(ele => ele.dictValue == value)
if (arr.length) {
return arr[0].dictLabel
} else {
return '请选择'
}
}
},
pickerConfirm(type, event) {
this.show[type] = false
this.formData[type] = event.value[0].dictValue
this.$forceUpdate();
},
showPicker(type) {
if (this.edit) {
this.show[type] = true
this.$forceUpdate()
}
},
formNameChange() {
let date = new Date()
let day =
`${date.getFullYear()}-${(date.getMonth()+1) + 1 > 9 ? (date.getMonth()+1) + 1: '0'+((date.getMonth()+1) + 1)}-${date.getDate() > 9 ? date.getDate(): '0'+date.getDate()}`
this.formData.trainingTopic =
`${this.$store.state.user.nick}_于${day}对人员_${this.formData.personName}_进行XXXX培训`;
},
async saveInfo() {
try {
// 验证表单
const isValid = await this.$refs.uForm.validate();
if (!isValid) {
throw new Error('请检查必填项填写');
}
// 显示全局加载
this.$showLoading();
// 根据 formData 是否有 id 来决定是更新还是新增
let response;
let successMessage;
if (this.formData.id) {
response = await updateSkillTrain(this.formData);
successMessage = '修改成功';
} else {
response = await addSkillTrain(this.formData);
successMessage = '保存成功';
}
if (response.code === 200) {
this.$u.toast(successMessage);
// 如果是编辑模式,关闭编辑状态;否则返回上一页
if (this.formData.id) {
this.edit = false;
} else {
await this.$delay(1000); // 延迟1秒后返回上一页
uni.navigateBack();
}
}
} catch (error) {
// 处理错误并显示提示信息
this.$u.toast('错误详情:' + error);;
} finally {
// 确保加载页总是会被隐藏
uni.hideLoading();
}
},
// saveInfo() {
// this.$refs.uForm.validate().then(res => {
// if (this.formData.id) {
// updateSkillTrain(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '修改成功'
// })
// this.edit = false;
// }
// })
// } else {
// addSkillTrain(this.formData).then(res => {
// if (res.code == 200) {
// uni.showToast({
// title: '保存成功'
// })
// uni.navigateBack();
// }
// })
// }
// }).catch(() => {
// uni.showToast({
// title: '请检查必填项填写',
// icon: 'none'
// })
// })
// }
}
}
</script>
<style lang="scss">
.page ::v-deep .u-navbar__content {
background-color: transparent !important;
}
.page {
background-color: #EEF1F5 !important;
height: 100vh;
background-image: url('https://rc.jinan.gov.cn/qcwjyH5/static/images/top.png');
background-repeat: no-repeat;
background-size: 100% auto;
}
.button-area {
padding: 24rpx 32rpx 68rpx;
width: calc(100% + 64rpx);
margin-left: -32rpx;
background: #fff;
display: flex;
box-sizing: border-box;
margin-top: 40rpx;
border-radius: 16px 16px 0px 0px;
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
.noValue {
color: rgb(192, 196, 204);
}
.self-form.popup {
padding-top: 32rpx;
.bordered {
border: 1rpx solid #dadbde;
padding: 9px;
border-radius: 4px;
}
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
</style>

View File

@@ -0,0 +1,224 @@
<!--
* @Date: 2024-10-08 14:29:36
* @LastEditors: shirlwang
* @LastEditTime: 2025-11-04 13:56:02
-->
<template>
<view class="page" style="background-image: url('../../../packageRc/static/pageBg.png');position:relative;">
<view class="tab-list" v-if="showTab != 1">
<view class="tab" :class="{active: activeType == 1}" @click="canChangeType ? changeType(1) : ''">走访<br>调查
</view>
<view class="tab" :class="{active: activeType == 2}" @click="canChangeType ? changeType(2) : ''">政策法规<br>咨询
</view>
<view class="tab" :class="{active: activeType == 3}" @click="canChangeType ? changeType(3) : ''">岗位<br>推荐
</view>
<view class="tab" :class="{active: activeType == 4}" @click="canChangeType ? changeType(4) : ''">技术培训<br>操作
</view>
<view class="tab" :class="{active: activeType == 5}" @click="canChangeType ? changeType(5) : ''">就业<br>跟踪
</view>
</view>
<investigate :userId="userId" :name="name" v-if="activeType == 1" ref="type1" />
<policyConsultation v-if="activeType == 2" ref="type2" />
<jobRecommend v-if="activeType == 3" ref="type3" :showInfo="showInfo"/>
<skillTrain v-if="activeType == 4" ref="type4" />
<jobTrack v-if="activeType == 5" ref="type5" />
</view>
</template>
<script>
import investigate from './components/investigate.vue';
import policyConsultation from './components/policyConsultation.vue';
import jobRecommend from './components/jobRecommend.vue';
import skillTrain from './components/skillTrain.vue';
import jobTrack from './components/jobTrack.vue';
export default {
components: {
investigate,
policyConsultation,
jobRecommend,
skillTrain,
jobTrack,
},
data() {
return {
isAdd: true,
activeType: 1,
showTab: undefined,
canChangeType: true,
userId: '',
name:"",
showInfo: '0'
}
},
onLoad(options) {
this.userId = options.userId
this.name = options.name
this.showTab = options.showTab
this.showInfo = options.showInfo || '0'
if (options.id && options.type) {
this.activeType = options.type
this.canChangeType = false;
this.isAdd = false
// 获取服务详情
this.$nextTick(() => {
this.$refs['type' + options.type].getDetail(options.id)
})
} else if (options.personName && options.personId) {
this.canChangeType = false;
this.activeType = options.type
this.$nextTick(() => {
this.$refs['type' + options.type].setPersonName(options)
})
}
// else if (options.personName && options.personId) {
// this.canChangeType = false;
// this.activeType = options.type
// this.$nextTick(() => {
// // 获取求职需求详情
// this.$refs['type' + options.type].addForPerson(options)
// })
// }
else {
this.changeType(options.activeType || 1)
}
},
onReady() {},
created() {},
methods: {
changeType(type) {
this.activeType = type
this.$nextTick(() => {
this.$refs['type' + type].addOne()
})
},
goBack() {
uni.navigateBack();
},
}
}
</script>
<style lang="scss">
@import "/packageRc/static/scss/index.scss";
.page {
background-color: #F4F4F4 !important;
height: 100vh;
background-repeat: no-repeat;
background-size: 100% auto;
position: relative;
}
.button-area {
padding: 24rpx 32rpx 68rpx;
background: #fff;
display: flex;
width: 100%;
box-sizing: border-box;
margin-top: 40rpx;
border-radius: 16px 16px 0px 0px;
position: absolute;
bottom: 0;
left: 0;
box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
.btn {
line-height: 72rpx;
width: 176rpx;
margin-right: 16rpx;
font-size: 28rpx;
border: 1px solid #B8C5D4;
color: #282828;
text-align: center;
border-radius: 8rpx;
}
.reset {
background: #DCE2E9;
}
.save {
background: linear-gradient(103deg, #1D64CF 0%, #1590D4 99%);
color: #fff;
border: 0;
flex-grow: 1;
}
}
.noValue {
color: rgb(192, 196, 204);
}
.disabledLine {
background: rgb(245, 247, 250);
cursor: not-allowed;
}
.inner {
background: #fff;
border-radius: 16rpx;
padding: 32rpx;
margin-bottom: 24rpx;
}
.input-outer-part{
// width: calc(100% - 64rpx);
padding-top: 32rpx;
// margin: 0 auto;;
}
.inner-part {
width: 100%;
}
.tab-list {
display: flex;
width: calc(100% - 64rpx);
margin: 16rpx auto 30rpx;
text-align: center;
border-radius: 16rpx;
background: #fff;
;
.tab {
width: 25%;
display: flex;
align-items: center;
justify-content: center;
border: 4rpx solid #FFFFFF;
background: #fff;
border-radius: 16rpx;
font-size: 28rpx;
color: #878787;
height: 106rpx;
&.active {
background: #1A62CE;
color: #fff;
position: relative;
font-weight: bold;
&::before {
content: '';
position: absolute;
bottom: -13rpx;
border-top: 14rpx solid #1A62CE;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
left: calc(50% - 7rpx);
z-index: 2;
}
&::after {
content: '';
position: absolute;
z-index: 1;
bottom: -18rpx;
border-top: 14rpx solid #fff;
border-left: 12rpx solid transparent;
border-right: 12rpx solid transparent;
left: calc(50% - 7rpx);
}
}
}
}
</style>

View File

@@ -0,0 +1,92 @@
.inner-part {
width: 100%;
}
.self-form {
width: 100%;
}
.form-item {
display: flex;
align-items: flex-start;
// margin-bottom: 24rpx;
background-color: #fff;
border-radius: 8rpx;
padding: 24rpx 0;
}
.form-label {
width: 200rpx;
font-size: 28rpx;
color: #333;
flex-shrink: 0;
line-height: 48rpx;
}
.required {
color: #f56c6c;
margin-left: 4rpx;
}
.form-textarea {
flex: 1;
border: none;
outline: none;
font-size: 28rpx;
color: #333;
background: none;
min-height: 120rpx;
line-height: 40rpx;
}
.form-textarea-disabled {
color: #909399;
background-color: #f5f7fa;
}
.icon-right {
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
color: #A6A6A6;
margin-left: 16rpx;
}
.input-outer-part{
position: relative;
box-sizing: border-box;
.inner{
z-index: 1;
position: relative;
background: #fff;
width: calc(100% - 64rpx);
margin: 0 auto;
box-sizing: border-box;
border-radius: 16rpx;
padding: 32rpx;
margin-bottom: 24rpx;
.part-title{
color: #3D3D3D;
font-weight: bold;
line-height: 28rpx;
margin-top: 9rpx;
padding-left: 12rpx;
border-left: 6rpx solid #1A62CE;
font-size: 32rpx;
margin-bottom: 24rpx;
}
.inner-part{
background: #fff;
border-radius: 16rpx;
.self-form{
.u-form-item__body{
padding: 14px 0;
}
}
}
}
}

View File

@@ -451,6 +451,16 @@
"style": {
"navigationBarTitleText": "添加帮扶"
}
} , {
"path": "pages/service/serviceDetail",
"style": {
"navigationBarTitleText": "服务"
}
} , {
"path": "pages/needs/needDetail",
"style": {
"navigationBarTitleText": "需求"
}
}
]
}],

View File

@@ -20,7 +20,7 @@ const request = config => {
if (getToken() && !isToken) {
config.header['Authorization'] = 'Bearer ' + getToken()
}
config.header['Authorization'] = 'Bearer ' + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJVMDRocERSZjdZMXJUbUxXb05uOUpzYUdDZzBNazJJQSIsInVzZXJJZCI6MX0.LZ29vvA4tK3b9Hki4nU9Jb1himXZM2AEOue3CMRY95w'
config.header['Authorization'] = 'Bearer ' + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiI5aW9ycXdMYVp5aXFienBJOXdvVGlYc3R3V0xydkFqWSIsInVzZXJJZCI6MX0.lfsx6tcpSUYYenWmz8T7gsgc8_t1sFNif_e2nOBRRL4'
// get请求映射params参数
if (config.params) {
let url = config.url + '?' + tansParams(config.params)