| @@ -5,8 +5,8 @@ | |||
| <link rel="icon" type="image/svg+xml" href="/vite.svg" /> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
| <title>Vite + Vue + TS</title> | |||
| <script type="module" crossorigin src="/assets/index-JJeaanAG.js"></script> | |||
| <link rel="stylesheet" crossorigin href="/assets/index-0kds0h5a.css"> | |||
| <script type="module" crossorigin src="/assets/index-M75Plfpg.js"></script> | |||
| <link rel="stylesheet" crossorigin href="/assets/index-9Ic14vNC.css"> | |||
| </head> | |||
| <body> | |||
| <div id="app"></div> | |||
| @@ -59,7 +59,7 @@ instance.interceptors.response.use(function (response) { | |||
| msgModel(response.data.msg) | |||
| break; | |||
| case 600: | |||
| if (response.data.errors) { | |||
| if (response.data.errors && Object.keys(response.data.errors).length > 0 ) { | |||
| msgModel(response.data.errors) | |||
| } else { | |||
| msgModel(response.data.msg) | |||
| @@ -7,11 +7,14 @@ export const PostImageUpload = postModel(url.ImageUpload); | |||
| export const PostJobseekerRegister = postModel(url.JobseekerRegister); | |||
| export const PostCompanyRegister = postModel(url.CompanyRegister); | |||
| export const PostJobseekerlogin = postModel(url.Jobseekerlogin); | |||
| export const GetCaptcha = getModel(url.Captcha); | |||
| export const PostSmsSend = postModel(url.SmsSend); | |||
| export const PostJobseekerSmsLogin = postModel(url.JobseekerSmsLogin); | |||
| export const PostCustomerVerify = postModel(url.CustomerVerify); | |||
| export const PostJobseekerEditPwd = postModel(url.JobseekerEditPwd); | |||
| export const PostCompanyLoginByMobile = postModel(url.CompanyLoginByMobile); | |||
| // 招聘会 | |||
| export const PostRecruitmentBookcompany = getModel(url.RecruitmentBookcompany);// 获取招聘会参与的企业 | |||
| @@ -85,11 +88,11 @@ export const PostCompanyTalentPoolDel = postModel(url.CompanyTalentPoolDel); // | |||
| export const GetCompanyTalentPoolList = getModel(url.CompanyTalentPoolList); // 人才库列表 | |||
| // 企业开通微信小程序账号公司权限 | |||
| export const PostCompanycustomercodeAdd = getModel(url.CompanycustomercodeAdd); // 添加 | |||
| export const PostCompanycustomercodeAdd = postModel(url.CompanycustomercodeAdd); // 添加 | |||
| export const PostCompanycustomercodeDel = postModel(url.CompanycustomercodeDel); // 删除 | |||
| export const PostCompanycustomercodeUpdate = postModel(url.CompanycustomercodeUpdate); // 编辑 | |||
| export const PostCompanycustomercodeList = getModel(url.CompanycustomercodeList); // 列表 | |||
| export const PostCompanycustomercodeDetail = getModel(url.CompanycustomercodeDetail); // 添加 | |||
| export const GetCompanycustomercodeList = getModel(url.CompanycustomercodeList); // 列表 | |||
| export const GetCompanycustomercodeDetail = getModel(url.CompanycustomercodeDetail); // 添加 | |||
| // 展示广告位 | |||
| export const GetAdvertscheduleList = getModel(url.AdvertscheduleList); // 添加 | |||
| @@ -121,6 +124,19 @@ export const PostRecruitmentbookUpdate = postModel(url.RecruitmentbookUpdate); / | |||
| export const GetRecruitmentbookList = getModel(url.RecruitmentbookList); // 列表 | |||
| export const GetRecruitmentbookDetail = getModel(url.RecruitmentbookDetail); // 详情 | |||
| // 收藏 | |||
| export const PostJobseekAddfavorite = postModel(url.JobseekAddfavorite); | |||
| export const PostJobseekDelfavorite = postModel(url.JobseekDelfavorite); | |||
| export const PostJobseekUpdatefavorite = postModel(url.JobseekUpdatefavorite); | |||
| export const GetJobseekListfavorite = getModel(url.JobseekListfavorite); | |||
| export const GetJobseekFavoritedetail = getModel(url.JobseekFavoritedetail); | |||
| // 投递 | |||
| export const PostJobseekAddapplication = postModel(url.JobseekAddapplication); | |||
| export const PostJobseekDelapplication = postModel(url.JobseekDelapplication); | |||
| export const PostJobseekUpdateapplication = postModel(url.JobseekUpdateapplication); | |||
| export const GetJobseekListapplication = getModel(url.JobseekListapplication); | |||
| export const GetJobseekApplicationdetail = getModel(url.JobseekApplicationdetail); | |||
| // 简历 | |||
| // 列表 | |||
| export const PostJobseekerList = postModel(url.JobseekerList); | |||
| @@ -10,6 +10,8 @@ declare namespace urlType { | |||
| JobseekerSmsLogin : String, | |||
| CustomerVerify : String, | |||
| JobseekerEditPwd : String, | |||
| CompanyLoginByMobile: String, | |||
| Jobseekerlogin: String, | |||
| // 招聘会 | |||
| RecruitmentBookcompany : String, | |||
| @@ -104,6 +106,18 @@ declare namespace urlType { | |||
| RecruitmentbookList : String, | |||
| RecruitmentbookDetail : String, | |||
| // 收藏 | |||
| 'JobseekAddfavorite':String, | |||
| 'JobseekDelfavorite': String, | |||
| 'JobseekUpdatefavorite': String, | |||
| 'JobseekListfavorite': String, | |||
| 'JobseekFavoritedetail': String, | |||
| // 投递 | |||
| 'JobseekAddapplication': String, | |||
| 'JobseekDelapplication':String, | |||
| 'JobseekUpdateapplication': String, | |||
| 'JobseekListapplication': String, | |||
| 'JobseekApplicationdetail':String, | |||
| // 简历 | |||
| @@ -1,29 +1,34 @@ | |||
| let web: string = '/web'; | |||
| let common: string = '/common'; | |||
| let web : string = '/web'; | |||
| let common : string = '/common'; | |||
| // 角色 | |||
| export const url : urlType.url = { | |||
| // 字典 | |||
| dictTree: common + '/dict/tree', | |||
| ImageUpload: common + '/image/upload?imgtype=1', | |||
| JobseekerRegister: web + '/jobseeker/register', // 个人注册 | |||
| CompanyRegister: web + '/company/register', // 企业注册 | |||
| Captcha: common + '/captcha', // 获取验证码 | |||
| SmsSend: common + '/sms/send', // 短信验证码 | |||
| JobseekerSmsLogin: web + '/jobseeker/smslogin', // 个人登录 | |||
| Jobseekerlogin: web + '/jobseeker/login', // 个人登录 | |||
| CustomerVerify: web + '/customer/verify', // 转换为HR | |||
| JobseekerEditPwd: web + '/jobseek/edit_pwd', // 修改密码 | |||
| CompanyLoginByMobile: web + '/company/login_by_mobile', // 企业登录 | |||
| // 招聘会 | |||
| RecruitmentBookcompany: web + '/recruitment/bookcompany', // 获取招聘会参与的企业 | |||
| RecruitmentList: web + '/recruitment/list', // 招聘会列表 | |||
| // 求职者管理中心 | |||
| ViewhistoryList: web + '/viewhistory/list', // 获取简历被查看记录 | |||
| InterviewList: web + '/interview/list', // 获取应聘记录列表 | |||
| // 企业管理中心 | |||
| CompanyRecommentResume: web + '/company/recomment_resume', // 推荐简历 | |||
| CompanyProfile: web + '/company/profile', // 企业基本资料 | |||
| @@ -49,14 +54,14 @@ export const url : urlType.url = { | |||
| CompanyJobRecycleList: web + '/company/job_recycle_list', // 回收站列表 | |||
| CompanyJobRecoverRecycle: web + '/company/job_recover_recycle', // 回收站列表 | |||
| CompanyJobStatusChange: web + '/company/job_status_change', // 回收站列表 | |||
| // 部门管理 | |||
| CompanyDepartmentAdd: web + '/company/department_add', // 新增部门 | |||
| CompanyDepartmentEdit: web + '/company/department_edit', // 编辑部门 | |||
| CompanyDepartmentList: web + '/company/department_list', // 部门列表 | |||
| CompanyDepartmentDel: web + '/company/department_del', // 部门删除 | |||
| CompanyRecrBookList: web + '/company/recr_book_list', // 已预定招聘会列表 | |||
| // 简历管理 | |||
| CompanyResumeList: web + '/company/resume_list', // 收到的简历列表 | |||
| CompanyResumeRecycle: web + '/company/resume_recycle', // 简历放进回收站 | |||
| @@ -68,29 +73,29 @@ export const url : urlType.url = { | |||
| CompanyResumeInterviewAdmission: web + '/company/interview_admission', // 是否录取 | |||
| CompanyResumeInterviewViewStatus: web + '/company/interview_view_status', // 是否参加面试 | |||
| CompanyResumeViewedContactList: web + '/company/viewed_contact_list', // 已查看联系方式 | |||
| // 人才库 | |||
| CompanyTalentPoolAdd: web + '/company/talent_pool_add', // 添加人才库 | |||
| CompanyTalentPoolDel: web + '/company/talent_pool_del', // 删除人才库记录 | |||
| CompanyTalentPoolList: web + '/company/talent_pool_list', // 人才库列表 | |||
| // 企业开通微信小程序账号公司权限 | |||
| CompanycustomercodeAdd: web + '/companycustomercode/add', // 添加 | |||
| CompanycustomercodeDel: web + '/companycustomercode/del', // 删除 | |||
| CompanycustomercodeUpdate: web + '/companycustomercode/update', // 编辑 | |||
| CompanycustomercodeList: web + '/companycustomercode/list', // 列表 | |||
| CompanycustomercodeDetail: web + '/companycustomercode/detail', // 详情 | |||
| // 展示广告位 | |||
| AdvertscheduleList: web + '/advertschedule/list', // 详情 | |||
| // 资讯 | |||
| SectionList: web + '/section/list', // 列表 | |||
| SectionDetail: web + '/section/detail', // 详情 | |||
| ArticleList: web + '/article/list', | |||
| ArticlenDetail: web + '/article/detail', | |||
| ArticleList: web + '/article/list', | |||
| ArticlenDetail: web + '/article/detail', | |||
| // 职位 | |||
| JobDetail: web + '/job/detail', // 获取职位详情 | |||
| JobSearch: web + '/job/search', // 职位搜索 | |||
| @@ -99,23 +104,23 @@ export const url : urlType.url = { | |||
| JobUrgentjobs: web + '/job/urgentjobs', // 急招职位 | |||
| JobHighpayjobs: web + '/job/highpayjobs', // 高薪职位 | |||
| JobCampusjobs: web + '/job/campusjobs', // 校园招聘 | |||
| // 招聘会企业预定 | |||
| RecruitmentbookAdd: web + '/recruitmentbook/add', // 添加 | |||
| RecruitmentbookDel: web + '/recruitmentbook/del', // 删除 | |||
| RecruitmentbookUpdate: web + '/recruitmentbook/update', // 编辑 | |||
| RecruitmentbookList: web + '/recruitmentbook/list', // 列表 | |||
| RecruitmentbookDetail: web + '/recruitmentbook/detail', // 详情 | |||
| // 反馈 | |||
| FeedbackAdd: common + '/feedback/add', // 添加 | |||
| FeedbackDel: common + '/feedback/del', // 删除 | |||
| FeedbackUpdate: common + '/feedback/update', // 编辑 | |||
| FeedbackList: common + '/feedback/list', // 列表 | |||
| FeedbackDetail: common + '/feedback/detail', // 详情 | |||
| // 简历 | |||
| JobseekerList: web + '/jobseeker/list', // 获取简历完整资料列表 | |||
| JobseekerDetail: web + '/jobseeker/detail', // 获取简历完整资料 | |||
| @@ -123,8 +128,21 @@ export const url : urlType.url = { | |||
| PersonInterviewList: web + '/person/interview_list', // 面试邀请记录 | |||
| PersonInterviewViewStatus: web + '/person/interview_view_status', // 是否参加面试 | |||
| PersonInterviewDel: web + '/person/interview_del', // 删除面试邀请 | |||
| // 收藏 | |||
| 'JobseekAddfavorite': web + '/jobseek/addfavorite', // 添加 | |||
| 'JobseekDelfavorite': web + '/jobseek/delfavorite', // 删除 | |||
| 'JobseekUpdatefavorite': web + '/jobseek/updatefavorite', // 修改 | |||
| 'JobseekListfavorite': web + '/jobseek/listfavorite', // 查看 | |||
| 'JobseekFavoritedetail': web + '/jobseek/favoritedetail', // 详情 | |||
| // 投递 | |||
| 'JobseekAddapplication': web + '/jobseek/addapplication', // 添加 | |||
| 'JobseekDelapplication': web + '/jobseek/delapplication', // 删除 | |||
| 'JobseekUpdateapplication': web + '/jobseek/updateapplication', // 修改 | |||
| 'JobseekListapplication': web + '/jobseek/listapplication', // 查看 | |||
| 'JobseekApplicationdetail': web + '/jobseek/applicationdetail', // 详情 | |||
| // 基本资料 | |||
| 'JobapplicantAdd': web + '/jobapplicant/add', // 添加 | |||
| 'JobapplicantDel': web + '/jobapplicant/del', // 删除 | |||
| @@ -184,5 +202,5 @@ export const url : urlType.url = { | |||
| 'JobapplicantUpdateexperience': web + '/jobapplicant/updateexperience', // 修改 | |||
| 'JobapplicantListexperience': web + '/jobapplicant/listexperience', // 查看 | |||
| 'JobapplicantExperiencedetail': web + '/jobapplicant/experiencedetail', // 详情 | |||
| } | |||
| @@ -0,0 +1,134 @@ | |||
| <template> | |||
| <template v-if="!seekerList || seekerList.length == 0"> | |||
| <a-empty style="height: 100vh;"> | |||
| <template #description> | |||
| 无求职者信息 | |||
| </template> | |||
| </a-empty> | |||
| </template> | |||
| <template v-else> | |||
| <a-row :gutter="[20,20]"> | |||
| <a-col span="24" v-for="(item, index) in seekerList"> | |||
| <a-card> | |||
| <div class="talent-box"> | |||
| <a-list> | |||
| <a-list-item> | |||
| <template #actions> | |||
| <a-button @click="detail(item)"> | |||
| <StarOutlined /> | |||
| 预览 | |||
| </a-button> | |||
| <a-button> | |||
| <StarOutlined /> | |||
| 收藏 | |||
| </a-button> | |||
| <a-button> | |||
| 邀请面试 | |||
| </a-button> | |||
| </template> | |||
| <a-list-item-meta> | |||
| <template #title> | |||
| {{item.seekername}} | |||
| </template> | |||
| <template #description> | |||
| <div> | |||
| {{item.gender}} | |||
| <a-divider type="vertical" /> | |||
| {{item.education_text}} | |||
| <a-divider type="vertical" /> | |||
| {{item.now_level1_text}}{{item.now_level2_text}} | |||
| </div> | |||
| <div style="margin-top: 10px; overflow: hidden; | |||
| display: -webkit-box; | |||
| -webkit-line-clamp: 1; | |||
| -webkit-box-orient: vertical; | |||
| text-overflow: ellipsis;"> | |||
| <div v-html="item.introduction"></div> | |||
| </div> | |||
| </template> | |||
| <template #avatar> | |||
| <image-container | |||
| :imgObj="{src: '/images/onlylogo.jpg',width: '48px',height:'48px'}"></image-container> | |||
| </template> | |||
| </a-list-item-meta> | |||
| </a-list-item> | |||
| </a-list> | |||
| </div> | |||
| </a-card> | |||
| </a-col> | |||
| <a-col span="24"> | |||
| <a-flex justify="center"> | |||
| <a-space> | |||
| <a-pagination hideOnSinglePage :total="commomParams.page.total" @change="getPage" /> | |||
| </a-space> | |||
| </a-flex> | |||
| </a-col> | |||
| </a-row> | |||
| <resume-detail v-if="detail_record" :detail_record="detail_record"></resume-detail> | |||
| </template> | |||
| </template> | |||
| <script setup lang="ts"> | |||
| import { ref, computed, onMounted, defineProps, watch } from 'vue'; | |||
| import ResumeDetail from '@/components/jobseeker/resume/detail/index.vue' | |||
| import { PostJobseekerList } from '@/apis/models'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { store, commomParams, dayjs, richOption, ExclamationCircleOutlined, Modal, showOtherModal1 } = useCommon(); | |||
| let props = defineProps(['search']); | |||
| let seekerList = ref<object[]>([]) | |||
| let loading = ref<Boolean>(true); | |||
| const getPage = (data : object) => { | |||
| commomParams.value.search.page = data.current; | |||
| commomParams.value.search.pagesize = data.pageSize; | |||
| getData(); | |||
| } | |||
| const getData = async () => { | |||
| try { | |||
| loading.value = true; | |||
| let res = await PostJobseekerList(commomParams.value.search); | |||
| loading.value = false; | |||
| seekerList.value = res.data.seekers; | |||
| commomParams.value.page = { | |||
| current: commomParams.value.search.page, | |||
| pageSize: commomParams.value.search.pagesize, | |||
| total: res.data.total, | |||
| pageSizeOptions: ['10', '20', '30', '40'], | |||
| hideOnSinglePage: false, | |||
| showSizeChanger: true | |||
| }; | |||
| } catch { | |||
| loading.value = false; | |||
| } | |||
| } | |||
| const onLoadMore = () => { | |||
| commomParams.value.search.page = commomParams.value.search.page + 1; | |||
| getData(); | |||
| } | |||
| let detail_record = ref<Object>(null) | |||
| const detail = (record) => { | |||
| detail_record.value = record; | |||
| showOtherModal1() | |||
| } | |||
| // onMounted(() => { | |||
| // getData(); | |||
| // }) | |||
| watch(() => [props.search], (newVal) => { | |||
| if (newVal[0] ) { | |||
| commomParams.value.search = newVal[0]; | |||
| getData(); | |||
| } | |||
| }, { immediate: true }) | |||
| </script> | |||
| <style scoped lang="less"> | |||
| </style> | |||
| @@ -77,45 +77,42 @@ | |||
| <a-input v-model:value="value" placeholder="请输入计算机能力" size="large" /> | |||
| </a-form-item> | |||
| </a-col> | |||
| <!-- | |||
| <a-col span="12"> | |||
| <a-form-item label="工作经验"> | |||
| <a-xuanze :dict="2021" placeholder="请选择工作经验" @saveSelect="saveEthnicity" | |||
| :select_content="commomParams.search.ethnicity"></a-xuanze> | |||
| </a-form-item> | |||
| </a-col> | |||
| <a-col span="12"> | |||
| <a-form-item label="最小年龄" name="age_min"> | |||
| <a-xuanze :dict="2012" placeholder="请选择民族" @saveSelect="saveEthnicity" | |||
| :select_content="commomParams.search.ethnicity"></a-xuanze> | |||
| </a-col> --> | |||
| <!-- <a-col span="6"> | |||
| <a-form-item label="最大年龄"> | |||
| <a-input-number :min="0" v-model:value="commomParams.search.keyword" placeholder="请输入最小年龄" | |||
| size="large" style="width: 100%;"/> | |||
| </a-form-item> | |||
| </a-col> | |||
| <a-col span="12"> | |||
| <a-form-item label="最大年龄" name="age_max"> | |||
| <a-xuanze :dict="2012" placeholder="请选择民族" @saveSelect="saveEthnicity" | |||
| :select_content="commomParams.search.ethnicity"></a-xuanze> | |||
| <a-col span="6"> | |||
| <a-form-item label="最大年龄"> | |||
| <a-input-number :max="99" v-model:value="commomParams.search.keyword" placeholder="请输入最大年龄" | |||
| size="large" style="width: 100%;"/> | |||
| </a-form-item> | |||
| </a-col> | |||
| <a-col span="12"> | |||
| <a-form-item label="最小年龄" name="age_min"> | |||
| <a-xuanze :dict="2012" placeholder="请选择民族" @saveSelect="saveEthnicity" | |||
| :select_content="commomParams.search.ethnicity"></a-xuanze> | |||
| </a-col> --> | |||
| <a-col span="6"> | |||
| <a-form-item label="最小工作经验(年)"> | |||
| <a-input-number :min="0" v-model:value="commomParams.search.min_work_experience" placeholder="请输入最小工作经验" | |||
| size="large" style="width: 100%;"/> | |||
| </a-form-item> | |||
| </a-col> | |||
| <a-col span="12"> | |||
| <a-form-item label="最大年龄" name="age_max"> | |||
| <a-xuanze :dict="2012" placeholder="请选择民族" @saveSelect="saveEthnicity" | |||
| :select_content="commomParams.search.ethnicity"></a-xuanze> | |||
| <a-col span="6"> | |||
| <a-form-item label="最大工作经验(年)"> | |||
| <a-input-number :max="99" v-model:value="commomParams.search.max_work_experience" placeholder="请输入最大工作经验" | |||
| size="large" style="width: 100%;"/> | |||
| </a-form-item> | |||
| </a-col> | |||
| <a-col span="24"> | |||
| <a-flex justify="flex-end"> | |||
| <a-space> | |||
| <a-button type="primary" @click="saveForm" size="large">开始搜索</a-button> | |||
| <a-button type="primary" @click="getData" size="large">开始搜索</a-button> | |||
| </a-space> | |||
| </a-flex> | |||
| </a-col> | |||
| @@ -163,20 +160,20 @@ | |||
| commomParams.value.search.english = 0; | |||
| commomParams.value.search.mandarin = 0; | |||
| commomParams.value.search.cantonese = 0; | |||
| commomParams.value.search.other_language = ''; | |||
| commomParams.value.search.other_language = 0; | |||
| commomParams.value.search.max_work_experience = 0; | |||
| commomParams.value.search.min_work_experience = 0; | |||
| commomParams.value.search.gender = '不限'; | |||
| commomParams.value.search.gender = ''; | |||
| commomParams.value.search.maxheight = 0; | |||
| commomParams.value.search.minheight = 0; | |||
| commomParams.value.search.maxweight = 0; | |||
| commomParams.value.search.minweight = 0; | |||
| watch(() => props.search_params, (newVal) => { | |||
| emit('searchData', commomParams.value.search) | |||
| }, { | |||
| immediate: true | |||
| }) | |||
| // watch(() => props.search_params, (newVal) => { | |||
| // emit('searchData', commomParams.value.search) | |||
| // }, { | |||
| // immediate: true | |||
| // }) | |||
| const getData = () => { | |||
| emit('searchData', commomParams.value.search) | |||
| @@ -194,6 +191,44 @@ | |||
| emit('clearData', commomParams.value.search) | |||
| } | |||
| const saveTitle = (data) => { | |||
| commomParams.value.search.title = data.val ? data.val : 0; | |||
| } | |||
| const saveEducation = (data) => { | |||
| commomParams.value.search.education = data.val ? data.val : 0; | |||
| } | |||
| const saveMaritalStatus = (data) => { | |||
| commomParams.value.search.marital_status = data.val ? data.val : 0; | |||
| } | |||
| const savePoliticalStatus = (data) => { | |||
| commomParams.value.search.title = data.val ? data.val : 0; | |||
| } | |||
| const saveAvailableDateDesire = (data) => { | |||
| commomParams.value.search.available_date_desire = data.val ? data.val : 0; | |||
| } | |||
| const saveEnglish = (data) => { | |||
| commomParams.value.search.english = data.val ? data.val : 0; | |||
| } | |||
| const saveMandarin = (data) => { | |||
| commomParams.value.search.mandarin = data.val ? data.val : 0; | |||
| } | |||
| const saveCantonese = (data) => { | |||
| commomParams.value.search.cantonese = data.val ? data.val : 0; | |||
| } | |||
| const saveOtherLanguage = (data) => { | |||
| commomParams.value.search.other_language = data.val ? data.val : 0; | |||
| } | |||
| </script> | |||
| <style> | |||
| @@ -13,14 +13,10 @@ | |||
| <a-flex vertical style="width: 100%;background-color: #fff;border-radius: 10px;padding: 20px;"> | |||
| <a-card :title="item.job_name"> | |||
| <template #extra> | |||
| <a-space> | |||
| <a-button @click="rejectInterview(item.id)">拒绝面试</a-button> | |||
| <a-button @click="receiveInterview(item.id)" class="main-color">接受面试</a-button> | |||
| </a-space> | |||
| <div>企业查看状态:{{item.status_text}}</div> | |||
| </template> | |||
| <div>面试时间:{{item.invite_date}}</div> | |||
| <div>面试结果:{{item.employ_status_txt}}</div> | |||
| <div>面试企业:{{item.company_name}}</div> | |||
| <div>投递时间:{{item.created_at}}</div> | |||
| <div>企业名称:{{item.company_name}}</div> | |||
| </a-card> | |||
| </a-flex> | |||
| </a-col> | |||
| @@ -37,7 +33,7 @@ | |||
| <script setup lang="ts"> | |||
| import { ref, computed, onMounted, defineEmits, createVNode } from 'vue'; | |||
| import { GetInterviewList } from '@/apis/models'; | |||
| import { GetJobseekListapplication } from '@/apis/models'; | |||
| import { warnToast, successToast } from '@/utils/toastHelper'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { store, commomParams, dayjs, richOption, ExclamationCircleOutlined, Modal } = useCommon(); | |||
| @@ -76,9 +72,9 @@ | |||
| const getData = async () => { | |||
| try { | |||
| loading.value = true; | |||
| let res = await GetInterviewList(commomParams.value.search); | |||
| let res = await GetJobseekListapplication(commomParams.value.search); | |||
| loading.value = false; | |||
| jobList.value = res.data.interviews; | |||
| jobList.value = res.data.jobapplicationrecords; | |||
| commomParams.value.page = { | |||
| current: commomParams.value.search.page, | |||
| pageSize: commomParams.value.search.pagesize, | |||
| @@ -1,8 +1,149 @@ | |||
| <template> | |||
| <template v-if="!jobList || jobList.length == 0"> | |||
| <a-empty style="height: 100vh;"> | |||
| <template #description> | |||
| 无职位信息 | |||
| </template> | |||
| </a-empty> | |||
| </template> | |||
| <template v-else> | |||
| <a-row :gutter="[10,20]"> | |||
| <a-col span="8" v-for="(item, index) in jobList"> | |||
| <a-card :title="item.job_name"> | |||
| <template #extra> | |||
| <a-button @click="cancelCollect(item.id,item.job_id)">取消收藏</a-button> | |||
| </template> | |||
| <div>企业名称:{{item.company_name}}</div> | |||
| <div>收藏时间:{{item.created_at}}</div> | |||
| <a-popover trigger="click" placement="rightTop"> | |||
| <template #content> | |||
| <job-detail v-if="detail_record" :detail_record="detail_record"></job-detail> | |||
| </template> | |||
| <a-button @click="detail(item.job_id)">详情</a-button> | |||
| </a-popover> | |||
| </a-card> | |||
| </a-col> | |||
| </a-row> | |||
| </template> | |||
| </template> | |||
| <script> | |||
| <script setup lang="ts"> | |||
| import { ref, computed, onMounted, defineEmits, createVNode } from 'vue'; | |||
| import { GetJobseekListfavorite, PostJobseekUpdatefavorite } from '@/apis/models'; | |||
| import JobDetail from '@/components/jobseeker/invite/detail/index.vue' | |||
| import { warnToast, successToast } from '@/utils/toastHelper'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { store, commomParams, dayjs, richOption, ExclamationCircleOutlined, Modal, showOtherModal1 } = useCommon(); | |||
| let loading = ref<Boolean>(true); | |||
| let jobList = ref([]); | |||
| let total = ref<Number>(0) | |||
| const searchData = (data : object) => { | |||
| commomParams.value.search = data | |||
| getData(); | |||
| } | |||
| const clearData = (data : object) => { | |||
| if (data) { | |||
| commomParams.value.search = data | |||
| } else { | |||
| commomParams.value.search = { | |||
| page: 1, | |||
| pagesize: 12, | |||
| sort: 'id', | |||
| sortby: 'asc', | |||
| keyword: '' | |||
| } | |||
| } | |||
| getData(); | |||
| } | |||
| const getPage = (page, pageSize) => { | |||
| commomParams.value.search.page = page; | |||
| commomParams.value.search.pagesize = pageSize; | |||
| getData(); | |||
| } | |||
| const getData = async () => { | |||
| try { | |||
| loading.value = true; | |||
| let res = await GetJobseekListfavorite(commomParams.value.search); | |||
| loading.value = false; | |||
| jobList.value = res.data.jobapplicantfavorites; | |||
| commomParams.value.page = { | |||
| current: commomParams.value.search.page, | |||
| pageSize: commomParams.value.search.pagesize, | |||
| total: res.data.total, | |||
| pageSizeOptions: ['10', '20', '30', '40'], | |||
| hideOnSinglePage: false, | |||
| showSizeChanger: true | |||
| }; | |||
| } catch { | |||
| loading.value = false; | |||
| } | |||
| } | |||
| const cancelCollect = (id : Number, job_id : Number) => { | |||
| Modal.confirm({ | |||
| title: `是否要取消收藏该职位`, | |||
| centered: true, | |||
| icon: createVNode(ExclamationCircleOutlined), | |||
| onOk() { | |||
| PostJobseekUpdatefavorite({ id: id, job_id: job_id }).then(res => { | |||
| successToast('已取消收藏') | |||
| getData(); | |||
| }) | |||
| }, | |||
| onCancel() { | |||
| }, | |||
| }); | |||
| } | |||
| let detail_record = ref<Object>(null) | |||
| const detail = (record) => { | |||
| detail_record.value = record; | |||
| showOtherModal1() | |||
| } | |||
| onMounted(() => { | |||
| getData(); | |||
| }) | |||
| </script> | |||
| <style> | |||
| <style lang="less" scoped> | |||
| .job-box { | |||
| display: flex; | |||
| flex-direction: column; | |||
| justify-content: space-around; | |||
| // align-items: center; | |||
| width: 100%; | |||
| .job-title { | |||
| padding: 20px; | |||
| background-color: #ffffff; | |||
| .aaaa { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| } | |||
| } | |||
| .job-company { | |||
| padding: 20px; | |||
| background-color: #cccccc; | |||
| .aaaa { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| } | |||
| } | |||
| } | |||
| .mt10 { | |||
| margin-bottom: 10px; | |||
| } | |||
| </style> | |||
| @@ -0,0 +1,86 @@ | |||
| <template> | |||
| <a-spin :spinning="spinning"> | |||
| <template v-if="detail"> | |||
| <a-card :title="detail.base.name" style="width: 500px;" :bordered="false"> | |||
| <template #extra>{{detail.base.pay_range_text}}</template> | |||
| <a-flex style="width: 100%;"> | |||
| <a-descriptions :column="1" title="职位描述"> | |||
| <a-descriptions-item label="职位性质">{{detail.company.nature_text}}</a-descriptions-item> | |||
| <a-descriptions-item label="招聘人数">{{detail.base.invite_count}}人</a-descriptions-item> | |||
| <a-descriptions-item | |||
| label="工作地区">{{detail.locations ? detail.locations[0].name : '未知地址'}}</a-descriptions-item> | |||
| <a-descriptions-item label="月新范围">{{detail.base.pay_range_text}}</a-descriptions-item> | |||
| <a-descriptions-item label="食宿条件">{{detail.base.shisu_text}}</a-descriptions-item> | |||
| <a-descriptions-item label="节假日">{{detail.base.holidays_text}}</a-descriptions-item> | |||
| <a-descriptions-item label="有效期">{{detail.base.disabled_date}}</a-descriptions-item> | |||
| <a-descriptions-item label="有效期至">{{detail.base.name}}</a-descriptions-item> | |||
| <a-descriptions-item label="联系人">{{detail.contact.contact}}</a-descriptions-item> | |||
| <a-descriptions-item | |||
| label="职业类别">{{detail.base.types ? detail.base.types[0].name : '未知'}}</a-descriptions-item> | |||
| <a-descriptions-item label="联系电话">{{detail.contact.mobile}} <a-button size="small"> | |||
| 查看 | |||
| </a-button></a-descriptions-item> | |||
| <a-descriptions-item></a-descriptions-item> | |||
| <a-descriptions-item label="职业描述"> | |||
| <div v-html="detail.base.describe_text"></div></a-descriptions-item> | |||
| </a-descriptions> | |||
| </a-flex> | |||
| </a-card> | |||
| </template> | |||
| </a-spin> | |||
| </template> | |||
| <script setup lang="ts"> | |||
| import { ref, onMounted, defineProps, computed, watch, defineEmits } from 'vue'; | |||
| import { GetJobDetail } from '@/apis/models'; | |||
| import { message } from 'ant-design-vue'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { store, commomParams, hideOtherModal1, openOtherModel_1 } = useCommon(); | |||
| const emit = defineEmits(); | |||
| let props = defineProps(['detail_record']); | |||
| let detail = ref<Object>(null) | |||
| let spinning = ref<Boolean>(false); // 加载中 | |||
| openOtherModel_1 = computed(() => { | |||
| return store.state.openOtherModel_1; | |||
| }) | |||
| watch(() => [props.detail_record], (newVal) => { | |||
| if (newVal[0]) { | |||
| spinning.value = false | |||
| GetJobDetail({ id: props.detail_record }).then(res => { | |||
| detail.value = res.data | |||
| console.log(detail.value) | |||
| }) | |||
| } | |||
| }, { immediate: true }) | |||
| const cancelModal = () => { | |||
| hideOtherModal1() | |||
| } | |||
| </script> | |||
| <style lang="less" scoped> | |||
| .a-row:first-child { | |||
| border-bottom: none; | |||
| border-radius: 10px 10px 0 0; | |||
| } | |||
| .a-row:last-child { | |||
| border-radius: 0 0 10px 10px; | |||
| } | |||
| .a-row { | |||
| padding: 6px; | |||
| border: 1px #f0f0f0 solid; | |||
| .a-col:first-child {} | |||
| } | |||
| .a-col { | |||
| padding: 6px; | |||
| // padding-top: 6px; | |||
| } | |||
| </style> | |||
| @@ -11,7 +11,7 @@ | |||
| <a-row :gutter="[10,20]"> | |||
| <a-col span="12" v-for="(item, index) in jobList"> | |||
| <a-flex vertical style="width: 100%;background-color: #fff;border-radius: 10px;padding: 20px;"> | |||
| <a-card :title="item.job_name"> | |||
| <a-card :title="item.job_name" @click="detail(item.job_id)"> | |||
| <template #extra> | |||
| <a-space> | |||
| <a-button @click="rejectInterview(item.id)">拒绝面试</a-button> | |||
| @@ -21,6 +21,12 @@ | |||
| <div>面试时间:{{item.invite_date}}</div> | |||
| <div>面试结果:{{item.employ_status_txt}}</div> | |||
| <div>面试企业:{{item.company_name}}</div> | |||
| <a-popover trigger="click" placement="rightTop"> | |||
| <template #content> | |||
| <job-detail v-if="detail_record" :detail_record="detail_record"></job-detail> | |||
| </template> | |||
| <a-button @click="detail(item.job_id)">详情</a-button> | |||
| </a-popover> | |||
| </a-card> | |||
| </a-flex> | |||
| </a-col> | |||
| @@ -38,9 +44,10 @@ | |||
| <script setup lang="ts"> | |||
| import { ref, computed, onMounted, defineEmits, createVNode } from 'vue'; | |||
| import { GetPersonInterviewList, PostPersonInterviewViewStatus } from '@/apis/models'; | |||
| import JobDetail from '@/components/jobseeker/invite/detail/index.vue' | |||
| import { warnToast, successToast } from '@/utils/toastHelper'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { store, commomParams, dayjs, richOption, ExclamationCircleOutlined, Modal } = useCommon(); | |||
| let { store, commomParams, dayjs, richOption, ExclamationCircleOutlined, Modal, showOtherModal1 } = useCommon(); | |||
| const emit = defineEmits(); | |||
| let loading = ref<Boolean>(true); | |||
| let jobList = ref([]); | |||
| @@ -123,7 +130,7 @@ | |||
| Modal.confirm({ | |||
| title: `是否要拒绝面试`, | |||
| centered: true, | |||
| icon: PostPersonInterviewViewStatus(ExclamationCircleOutlined), | |||
| icon: createVNode(ExclamationCircleOutlined), | |||
| onOk() { | |||
| PostPersonInterviewViewStatus({ id: id, view_status: 3 }).then(res => { | |||
| successToast('已拒绝') | |||
| @@ -136,6 +143,12 @@ | |||
| }); | |||
| } | |||
| let detail_record = ref<Object>(null) | |||
| const detail = (record) => { | |||
| detail_record.value = record; | |||
| showOtherModal1() | |||
| } | |||
| onMounted(() => { | |||
| getData(); | |||
| }) | |||
| @@ -0,0 +1,215 @@ | |||
| <template> | |||
| <a-modal v-model:visible="openOtherModel_1" title="预览简历" ok-text="提交" cancel-text="取消" @ok="sumbitForm" | |||
| @cancel="cancelModal" width="60%"> | |||
| <a-spin :spinning="spinning"> | |||
| <a-typography> | |||
| <a-typography-title :level="4">基本资料</a-typography-title> | |||
| <a-typography-paragraph> | |||
| <a-row :gutter="[20,20]"> | |||
| <a-col span="24"> | |||
| <a-row :gutter="[20,20]"> | |||
| <a-col span="10"> | |||
| <a-row> | |||
| <a-col span="24"> | |||
| 姓 名:{{detail.seekername}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 性 别:{{detail.gender}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 身份证号:{{detail.id_number}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 民 族:{{detail.ethnicity_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 身 高:{{detail.height}}cm | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 政治面貌:{{detail.political_status_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 联系方式:{{detail.mobile}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 邮 箱:{{detail.email}} | |||
| </a-col> | |||
| </a-row> | |||
| </a-col> | |||
| <a-col span="8"> | |||
| <a-row> | |||
| <a-col span="24"> | |||
| 出生日期:{{detail.dob}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 婚姻状况:{{detail.marital_status_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 学 历:{{detail.education_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 体 重:{{detail.weight}}kg | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 现居地址:{{detail.now_level1_txt ? detail.now_level1_txt : ''}}{{detail.now_level2_txt ? detail.now_level2_txt : ''}}{{detail.now_level3_txt ? detail.now_level3_txt : ''}}{{detail.now_level4_txt ? detail.now_level4_txt : ''}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 籍 贯:{{detail.native_place_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 户口地址:{{detail.now_level1_txt ? detail.now_level1_txt : ''}}{{detail.now_level2_txt ? detail.now_level2_txt : ''}}{{detail.now_level3_txt ? detail.now_level3_txt : ''}}{{detail.now_level4_txt ? detail.now_level4_txt : ''}} | |||
| </a-col> | |||
| </a-row> | |||
| </a-col> | |||
| <a-col span="6"> | |||
| <image-container | |||
| :imgObj="{src: detail.photo? 'https://admin1.jcjob.cn/img/' + detail.photo : '', width: '200px',height: '280px',mode: 'fill'}"></image-container> | |||
| </a-col> | |||
| </a-row> | |||
| </a-col> | |||
| </a-row> | |||
| </a-typography-paragraph> | |||
| <a-typography-title :level="4">个人简介</a-typography-title> | |||
| <a-typography-paragraph> | |||
| <div v-html="detail.description"></div> | |||
| </a-typography-paragraph> | |||
| <a-typography-title :level="4">求职期望</a-typography-title> | |||
| <a-typography-paragraph> | |||
| <a-row> | |||
| <a-col span="24"> | |||
| 工作经验:{{detail.work_experience}}年 | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 期望薪资:{{detail.salary_range_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| <a-row> | |||
| <a-col span="8" v-if="detail.desire_areas"> | |||
| <a-row> | |||
| <a-col span="24" v-for="(item,index) in detail.desire_areas"> | |||
| 期望地址{{index + 1}}:{{item.level1_txt ? item.level1_txt : ''}}{{item.level2_txt ? item.level2_txt : ''}}{{item.level3_txt ? item.level3_txt : ''}}{{item.level4_txt ? item.level4_txt : ''}} | |||
| </a-col> | |||
| </a-row> | |||
| </a-col> | |||
| <a-col span="8" v-if="detail.desire_positions"> | |||
| <a-row> | |||
| <a-col span="24" v-for="(item,index) in detail.desire_positions"> | |||
| 期望职位{{index + 1}}:{{item.level1_txt ? item.level1_txt : ''}}{{item.level2_txt ? item.level2_txt : ''}} | |||
| </a-col> | |||
| </a-row> | |||
| </a-col> | |||
| <a-col span="8" v-if="detail.desire_industrys"> | |||
| <a-row> | |||
| <a-col span="24" v-for="(item,index) in detail.desire_industrys"> | |||
| 期望行业{{index + 1}}:{{item.industry_txt}} | |||
| </a-col> | |||
| </a-row> | |||
| </a-col> | |||
| </a-row> | |||
| </a-col> | |||
| </a-row> | |||
| </a-typography-paragraph> | |||
| </a-typography> | |||
| <a-typography-title :level="4">专业技能掌握能力</a-typography-title> | |||
| <a-typography-paragraph> | |||
| <a-row> | |||
| <a-col span="24"> | |||
| 英 语:{{detail.english_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 国 语:{{detail.mandarin_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 粤 语:{{detail.cantonese_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 第二外语:{{detail.salary_range_txt}} | |||
| </a-col> | |||
| <a-col span="24"> | |||
| 计算机能力:{{detail.computer_skills}} | |||
| </a-col> | |||
| </a-row> | |||
| </a-typography-paragraph> | |||
| <a-typography-title :level="4">工作经历</a-typography-title> | |||
| <a-typography-paragraph> | |||
| <template v-for="(item,index) in detail.experiences"> | |||
| <a-card :title="item.company_name" style="margin-bottom: 10px;"> | |||
| <template #extra>{{item.position}}</template> | |||
| <p>工作时间:{{item.start_year}}.{{item.start_month}}至{{item.end_year}}.{{item.end_month}}</p> | |||
| <p>离职原因:{{item.reason_for_leaving}}</p> | |||
| </a-card> | |||
| </template> | |||
| </a-typography-paragraph> | |||
| <a-typography-title :level="4">教育/培训经历</a-typography-title> | |||
| <a-typography-paragraph> | |||
| <template v-for="(item,index) in detail.trainings"> | |||
| <a-card :title="item.school_or_institution" style="margin-bottom: 10px;"> | |||
| <template #extra>{{item.major}}</template> | |||
| <p>教育/培训时间:{{item.start_year}}.{{item.start_month}}至{{item.end_year}}.{{item.end_month}}</p> | |||
| <p>曾担任的职务:{{item.positions_held}}</p> | |||
| <p>获得的证书:{{item.certificate}}</p> | |||
| <p>获得的奖项:{{item.awards}}</p> | |||
| </a-card> | |||
| </template> | |||
| </a-typography-paragraph> | |||
| </a-spin> | |||
| </a-modal> | |||
| </template> | |||
| <script setup lang="ts"> | |||
| import { ref, onMounted, defineProps, computed, watch, defineEmits } from 'vue'; | |||
| import { GetJobseekerDetail, GetJobapplicantIntroductiondetail, PostJobapplicantTrainingdetail, PostJobapplicantDesireindustrydetail, PostJobapplicantExperiencedetail } from '@/apis/models'; | |||
| import { message } from 'ant-design-vue'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { store, commomParams, hideOtherModal1, openOtherModel_1 } = useCommon(); | |||
| const emit = defineEmits(); | |||
| let props = defineProps(['detail_record']); | |||
| let detailTitle = ref<String>('') | |||
| let detail = ref<Object>({}) | |||
| let trainList = ref<Object[]>([]) | |||
| let experienceList = ref<Object[]>([]) | |||
| let introduction = ref<Object>({}) | |||
| let spinning = ref<Boolean>(false); // 加载中 | |||
| openOtherModel_1 = computed(() => { | |||
| return store.state.openOtherModel_1; | |||
| }) | |||
| watch(() => [props.detail_record], (newVal) => { | |||
| if (newVal[0]) { | |||
| spinning.value = false | |||
| GetJobseekerDetail({ customer_id: props.detail_record.customer_id }).then(res => { | |||
| detail.value = res.data | |||
| console.log(detail.value) | |||
| }) | |||
| } | |||
| }, { immediate: true }) | |||
| const cancelModal = () => { | |||
| hideOtherModal1() | |||
| } | |||
| </script> | |||
| <style lang="less" scoped> | |||
| .a-row:first-child { | |||
| border-bottom: none; | |||
| border-radius: 10px 10px 0 0; | |||
| } | |||
| .a-row:last-child { | |||
| border-radius: 0 0 10px 10px; | |||
| } | |||
| .a-row { | |||
| padding: 6px; | |||
| border: 1px #f0f0f0 solid; | |||
| .a-col:first-child {} | |||
| } | |||
| .a-col { | |||
| padding: 6px; | |||
| // padding-top: 6px; | |||
| } | |||
| </style> | |||
| @@ -264,10 +264,11 @@ | |||
| let interviewListLength = ref<Number>(0) | |||
| onMounted(() => { | |||
| GetPersonInterviewList({ status: 0 }).then(res => { | |||
| interviewListLength.value = res.data.list.length | |||
| }) | |||
| if(sessionStorage.getItem('pageType') == 'personal' && sessionStorage.getItem('role') == 'personal') { | |||
| GetPersonInterviewList({ status: 0 }).then(res => { | |||
| interviewListLength.value = res.data.list.length | |||
| }) | |||
| } | |||
| }) | |||
| </script> | |||
| @@ -0,0 +1,21 @@ | |||
| export const cols = <ColType.type[]>[ | |||
| { | |||
| title: '验证码', | |||
| dataIndex: 'code' | |||
| }, { | |||
| title: '绑定的账号', | |||
| dataIndex: 'customer.username' | |||
| }, { | |||
| title: '使用状态', | |||
| dataIndex: 'customer_id' | |||
| }, { | |||
| title: '生成时间', | |||
| dataIndex: 'created_at', | |||
| }, | |||
| { | |||
| title: '操作', | |||
| dataIndex: 'operation', | |||
| slots: { customRender: 'operation' }, | |||
| }, | |||
| ] | |||
| @@ -0,0 +1,141 @@ | |||
| <template> | |||
| <a-search @searchData="searchData" @clearData="clearData" :search_params="commomParams.search"></a-search> | |||
| <a-card title="转换验证码"> | |||
| <template #extra> | |||
| <a-button @click="getCode">生成验证码</a-button> | |||
| </template> | |||
| <a-biaoge :data="commomParams.table.data" :columns="commomParams.table.columns" :pagination="commomParams.page" | |||
| @page="getPage" :loading="loading"> | |||
| <template #default="{ record }"> | |||
| <a-row :gutter="20"> | |||
| <a-col> | |||
| <a-dropdown placement="bottomRight"> | |||
| <template #overlay> | |||
| <a-menu> | |||
| <a-menu-item key="1"> | |||
| <a-button @click="copyCode(record.code)" block>复制</a-button> | |||
| </a-menu-item> | |||
| <a-menu-item key="2"> | |||
| <a-button @click="del(record.id)" block>删除</a-button> | |||
| </a-menu-item> | |||
| </a-menu> | |||
| </template> | |||
| <a-button> | |||
| 操作 | |||
| <DownOutlined /> | |||
| </a-button> | |||
| </a-dropdown> | |||
| </a-col> | |||
| </a-row> | |||
| </template> | |||
| </a-biaoge> | |||
| </a-card> | |||
| </template> | |||
| <script setup lang="ts"> | |||
| import { ref, onMounted, computed, defineEmits, createVNode } from 'vue'; | |||
| import { PostCompanycustomercodeAdd, PostCompanycustomercodeDel, PostCompanycustomercodeUpdate, GetCompanycustomercodeList } from '@/apis/models'; | |||
| import ASearch from '@/components/user/conver/search.vue'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| import { cols } from '@/components/user/conver/columns'; | |||
| import { warnToast, successToast } from '@/utils/toastHelper'; | |||
| const emit = defineEmits(); | |||
| let { commomParams, ExclamationCircleOutlined, Modal } = useCommon(); | |||
| let loading = ref<Boolean>(true); | |||
| onMounted(() => { | |||
| getData(); | |||
| }) | |||
| const searchData = (data : object) => { | |||
| commomParams.value.search = data | |||
| getData(); | |||
| } | |||
| const clearData = (data : object) => { | |||
| if (data) { | |||
| commomParams.value.search = data | |||
| } else { | |||
| commomParams.value.search = { | |||
| page: 1, | |||
| pagesize: 10, | |||
| sort: 'id', | |||
| sortby: 'asc', | |||
| keyword: '' | |||
| } | |||
| } | |||
| getData(); | |||
| } | |||
| const getPage = (data : object) => { | |||
| commomParams.value.search.page = data.current; | |||
| commomParams.value.search.pagesize = data.pageSize; | |||
| getData(); | |||
| } | |||
| const getData = async () => { | |||
| try { | |||
| loading.value = true; | |||
| let res = await GetCompanycustomercodeList(commomParams.value.search); | |||
| loading.value = false; | |||
| commomParams.value.table.data = res.data.companycustomercodes; | |||
| commomParams.value.table.columns = cols; | |||
| commomParams.value.page = { | |||
| current: commomParams.value.search.page, | |||
| pageSize: commomParams.value.search.pagesize, | |||
| total: res.data.total, | |||
| pageSizeOptions: ['10', '20', '30', '40'], | |||
| hideOnSinglePage: false, | |||
| showSizeChanger: true | |||
| }; | |||
| } catch { | |||
| loading.value = false; | |||
| } | |||
| } | |||
| // 修改 | |||
| const edit = (record : Object) => { | |||
| emit('toEdit', { record: record }) | |||
| } | |||
| const getCode = (id) => { | |||
| Modal.confirm({ | |||
| title: '是否要生成验证码', | |||
| icon: createVNode(ExclamationCircleOutlined), | |||
| centered: true, | |||
| onOk() { | |||
| PostCompanycustomercodeAdd().then(res => { | |||
| successToast('已生成验证码') | |||
| getData() | |||
| }) | |||
| }, | |||
| onCancel() { | |||
| }, | |||
| }); | |||
| } | |||
| const copyCode = async (code) => { | |||
| try { | |||
| await navigator.clipboard.writeText(code); | |||
| successToast('复制成功'); | |||
| } catch (err) { | |||
| warnToast('复制到剪贴板失败,请手动复制'); | |||
| } | |||
| } | |||
| const del = (id : number) => { | |||
| commomParams.value.delParam = { id: id }; | |||
| PostCompanycustomercodeDel(commomParams.value.delParam).then(res => { | |||
| successToast('删除成功'); | |||
| getData(); | |||
| }) | |||
| } | |||
| </script> | |||
| <style scoped lang="less"> | |||
| </style> | |||
| @@ -0,0 +1,54 @@ | |||
| <template> | |||
| <a-form :model="commomParams.search"> | |||
| <a-row :gutter="20"> | |||
| <a-col span="6"> | |||
| <a-form-item> | |||
| <a-input-search v-model:value="commomParams.search.keyword" placeholder="请输入账号名" enter-button="搜索" | |||
| @search="getData" /> | |||
| </a-form-item> | |||
| </a-col> | |||
| <a-col span="6"> | |||
| <a-button type="primary" @click="clearSearch">重置</a-button> | |||
| </a-col> | |||
| </a-row> | |||
| </a-form> | |||
| </template> | |||
| <script lang="ts" setup> | |||
| import { ref, onMounted, watch, computed } from 'vue'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { commomParams } = useCommon(); | |||
| let props = defineProps(['search_params']); | |||
| const emit = defineEmits(); | |||
| watch(() => props.search_params, (newVal) => { | |||
| emit('searchData', commomParams.value.search) | |||
| },{ | |||
| immediate: true | |||
| }) | |||
| const getData = () => { | |||
| emit('searchData', commomParams.value.search) | |||
| } | |||
| // 清空搜索 | |||
| const clearSearch = () => { | |||
| commomParams.value.search = { | |||
| page: 1, | |||
| pagesize: 10, | |||
| sort: 'id', | |||
| sortby: 'asc', | |||
| keyword: '' | |||
| } | |||
| emit('clearData', commomParams.value.search) | |||
| } | |||
| </script> | |||
| <style> | |||
| </style> | |||
| @@ -5,8 +5,8 @@ | |||
| <a-col span="12"> | |||
| <a-row> | |||
| <a-col span="24"> | |||
| <a-form-item required label="邮箱" name="email"> | |||
| <a-input v-model:value="createForm.email" placeholder="请输入邮箱" /> | |||
| <a-form-item label="邮箱" name="email"> | |||
| <a-input v-model:value="createForm.email" placeholder="请输入邮箱" size="large"/> | |||
| </a-form-item> | |||
| </a-col> | |||
| <a-col span="24"> | |||
| @@ -27,6 +27,10 @@ const getShowEdit = (state, payload) => { | |||
| state.show_edit = payload.show_edit; | |||
| } | |||
| const getOpenMoreModel = (state : object, payload : object) => { | |||
| state.openOtherModel_1 = payload.openOtherModel_1; | |||
| } | |||
| export const mutations = { | |||
| getRouteName, | |||
| setShowLoginBox, | |||
| @@ -34,5 +38,6 @@ export const mutations = { | |||
| getToken, | |||
| getRole, | |||
| getPageType, | |||
| getShowEdit | |||
| getShowEdit, | |||
| getOpenMoreModel | |||
| } | |||
| @@ -7,5 +7,6 @@ export const state = <StateType>{ | |||
| token: '', | |||
| role: '', | |||
| pageType: '', | |||
| show_edit: false | |||
| show_edit: false, | |||
| openOtherModel_1: false, | |||
| } | |||
| @@ -5,5 +5,6 @@ export interface StateType { | |||
| token ?: String, | |||
| role ?: String, | |||
| pageType ?: String, | |||
| show_edit ?: Boolean | |||
| show_edit ?: Boolean, | |||
| openOtherModel_1 : Boolean, | |||
| } | |||
| @@ -4,13 +4,24 @@ | |||
| <a-col span="18"> | |||
| <a-row> | |||
| <a-col span="4"> | |||
| <common-left-sider :menu_list="menu_list" :selected_key="[1]" | |||
| <common-left-sider :menu_list="menu_list" :selected_key="[2]" | |||
| @changeKey="changeKey"></common-left-sider> | |||
| </a-col> | |||
| <a-col span="20"> | |||
| <div style="width: 100%;background-color: #fff;padding: 20px;border-radius: 10px;"> | |||
| <resume-search v-if="curKey == 1"></resume-search> | |||
| <resume-result v-if="curKey == 2"></resume-result> | |||
| <resume-search v-if="curKey == 1" @searchData="searchData"></resume-search> | |||
| <a-tabs v-model:activeKey="activeKey" @change="activeKeyChange" v-if="curKey == 2" | |||
| type="card"> | |||
| <a-tab-pane :key="1" tab="推荐人才"> | |||
| <resume-result v-if="activeKey == 1" :search="searchParams"></resume-result> | |||
| </a-tab-pane> | |||
| <a-tab-pane :key="2" tab="最新简历" force-render> | |||
| <resume-result :search="searchParams"></resume-result> | |||
| </a-tab-pane> | |||
| <a-tab-pane :key="3" tab="应届毕业生"> | |||
| <resume-result v-if="activeKey == 3" :search="searchParams"></resume-result> | |||
| </a-tab-pane> | |||
| </a-tabs> | |||
| </div> | |||
| </a-col> | |||
| </a-row> | |||
| @@ -22,13 +33,27 @@ | |||
| <script setup lang="ts"> | |||
| import { ref, computed, onMounted } from 'vue'; | |||
| import ResumeSearch from '@/components/company/search/index.vue' | |||
| import ResumeResult from '@/components/resume/result/index.vue' | |||
| let menu_list = ref([{ title: '简历搜索', key: 1 },{ title: '搜索结果', key: 2 }]) | |||
| let curKey = ref<Number>(1) | |||
| import ResumeResult from '@/components/company/result/index.vue' | |||
| let menu_list = ref([{ title: '简历搜索', key: 1 }, { title: '简历列表', key: 2 }]) | |||
| let curKey = ref<Number>(2) | |||
| let activeKey = ref<Number>(1); | |||
| let searchParams = ref<any>(null) | |||
| const changeKey = (data) => { | |||
| curKey.value = data.key; | |||
| } | |||
| const searchData = (data) => { | |||
| searchParams.value = data; | |||
| if(activeKey.value == 2) { | |||
| searchParams.value.sortby = 'desc' | |||
| } | |||
| curKey.value = 2 | |||
| } | |||
| </script> | |||
| <style> | |||
| <style scoped> | |||
| :deep(.ant-tabs-tab-btn) { | |||
| color: #4FBE70 !important; | |||
| } | |||
| </style> | |||
| @@ -33,8 +33,8 @@ | |||
| {{basic.qq ? basic.qq : '未填写'}} | |||
| </a-descriptions-item> | |||
| <a-descriptions-item> | |||
| <a-button type="link" class="main-color"> | |||
| <RedoOutlined style="color: #4FBE70" />刷新简历 | |||
| <a-button type="link" class="main-color" @click="refreshResume"> | |||
| <RedoOutlined style="color: #4FBE70" :spin="refreshing" rotate="90"/>刷新简历 | |||
| </a-button> | |||
| </a-descriptions-item> | |||
| <a-descriptions-item label="简历是否在家政可见"> | |||
| @@ -58,16 +58,16 @@ | |||
| <a-col span="18"> | |||
| <a-tabs v-model:activeKey="activeKey" @change="activeKeyChange"> | |||
| <a-tab-pane :key="1" tab="面试记录"> | |||
| <invite-interview></invite-interview> | |||
| <invite-interview v-if="activeKey == 1"></invite-interview> | |||
| </a-tab-pane> | |||
| <a-tab-pane :key="2" tab="投递记录" force-render> | |||
| <invite-apply></invite-apply> | |||
| <invite-apply v-if="activeKey == 2"></invite-apply> | |||
| </a-tab-pane> | |||
| <a-tab-pane :key="3" tab="谁看过我"> | |||
| <invite-seeme></invite-seeme> | |||
| <invite-seeme v-if="activeKey == 3"></invite-seeme> | |||
| </a-tab-pane> | |||
| <a-tab-pane :key="4" tab="收藏的职位"> | |||
| <invite-collect></invite-collect> | |||
| <invite-collect v-if="activeKey == 4"></invite-collect> | |||
| </a-tab-pane> | |||
| </a-tabs> | |||
| </a-col> | |||
| @@ -82,18 +82,34 @@ | |||
| import InviteApply from '@/components/jobseeker/invite/apply/index.vue' | |||
| import InviteSeeme from '@/components/jobseeker/invite/seeme/index.vue' | |||
| import InviteCollect from '@/components/jobseeker/invite/collect/index.vue' | |||
| import { GetJobseekerDetail, GetCompanyRecommentResume, GetViewHistoryList, GetPersonInterviewList } from '@/apis/models'; | |||
| import { GetJobseekerDetail, GetCompanyRecommentResume, GetViewHistoryList, GetPersonInterviewList, PostJobapplicantUpdate } from '@/apis/models'; | |||
| import { warnToast, successToast } from '@/utils/toastHelper'; | |||
| import { EditOutlined, FileSearchOutlined, RedoOutlined } from '@ant-design/icons-vue'; | |||
| import { useCommon } from '@/hooks/useCommon'; | |||
| let { commomParams, ExclamationCircleOutlined, Modal, onMenu } = useCommon(); | |||
| let jobList = ref<object[]>([]) | |||
| let jobList = ref<Object[]>([]) | |||
| let basic = ref<Object>({}) | |||
| let seeLength = ref<Number>(0) | |||
| let activeKey = ref<Number>(1) | |||
| let refreshing = ref<Boolean>(false) | |||
| let createForm = ref<Object>({ | |||
| hide_resume: 0, | |||
| house_keeping_status: 0, | |||
| remind_interview: 2 | |||
| }) | |||
| const toResume = () => { | |||
| debugger | |||
| onMenu('/jobseeker/resume') | |||
| } | |||
| const refreshResume = () => { | |||
| refreshing.value = true; | |||
| successToast('简历已刷新') | |||
| refreshing.value = false | |||
| } | |||
| onMounted(() => { | |||
| GetJobseekerDetail({ customer_id: sessionStorage.getItem('id') }).then(res => { | |||
| basic.value = res.data | |||
| @@ -1,6 +1,6 @@ | |||
| export let dataForm = { | |||
| username: "18022147412", | |||
| password: "123456", | |||
| username: "", | |||
| password: "", | |||
| capt_id: "", | |||
| captcha: "" | |||
| } | |||
| @@ -72,6 +72,17 @@ export const reset = () => { | |||
| capt_id: "", | |||
| captcha: "" | |||
| } | |||
| smsDataForm = { | |||
| mobile: "", | |||
| captcha: "", | |||
| capt_id: "" | |||
| }; | |||
| smsLoginDataForm = { | |||
| mobile: "", | |||
| sms_code: "", | |||
| } | |||
| return { dataForm, otherDataForm, personalDataForm, companyDataForm } | |||
| return { dataForm, otherDataForm, personalDataForm, companyDataForm, smsDataForm, smsLoginDataForm} | |||
| } | |||
| @@ -141,7 +141,7 @@ | |||
| <script lang="ts" setup> | |||
| import { ref, onMounted, computed, onBeforeUnmount } from 'vue'; | |||
| import { GetCaptcha, PostCompanyLogin, PostSmsSend, PostJobseekerSmsLogin } from '@/apis/models'; | |||
| import { GetCaptcha, PostJobseekerlogin,PostCompanyLogin, PostSmsSend, PostJobseekerSmsLogin, PostCompanyLoginByMobile} from '@/apis/models'; | |||
| import { store } from '@/store/index'; | |||
| import { router } from '@/router/index'; | |||
| import { dataForm, otherDataForm, personalDataForm, companyDataForm, smsDataForm, smsLoginDataForm, reset } from '@/views/login/data.ts'; | |||
| @@ -206,39 +206,36 @@ | |||
| const loginTypeChange = () => { | |||
| getCaptcha() | |||
| resetForm() | |||
| } | |||
| const changeLoginMethod = (val : string) => { | |||
| loginMethod.value = val; | |||
| createForm.value = reset().dataForm as LoginType.LoginFormType; | |||
| getCaptcha() | |||
| resetForm() | |||
| } | |||
| const toModule = (val : string) => { | |||
| currentModule.value = val; | |||
| createForm.value = reset().dataForm as LoginType.LoginFormType; | |||
| personalForm.value = reset().dataForm as RegisterType.RegisterPersonalFormType; | |||
| companyForm.value = reset().dataForm as RegisterType.RegisterCompanyFormType; | |||
| smsForm.value = reset().dataForm as LoginType.SmsFormType; | |||
| smsLoginForm.value = reset().dataForm as LoginType.SmsLoginFormType; | |||
| personalForm.value = reset().personalDataForm as RegisterType.RegisterPersonalFormType; | |||
| companyForm.value = reset().companyDataForm as RegisterType.RegisterCompanyFormType; | |||
| smsForm.value = reset().smsDataForm as LoginType.SmsFormType; | |||
| smsLoginForm.value = reset().smsLoginDataForm as LoginType.SmsLoginFormType; | |||
| getCaptcha() | |||
| } | |||
| const resetForm = () => { | |||
| createForm.value = reset().dataForm as LoginType.LoginFormType; | |||
| personalForm.value = reset().dataForm as RegisterType.RegisterPersonalFormType; | |||
| companyForm.value = reset().dataForm as RegisterType.RegisterCompanyFormType; | |||
| smsForm.value = reset().dataForm as LoginType.SmsFormType; | |||
| smsLoginForm.value = reset().dataForm as LoginType.SmsLoginFormType; | |||
| personalForm.value = reset().personalDataForm as RegisterType.RegisterPersonalFormType; | |||
| companyForm.value = reset().companyDataForm as RegisterType.RegisterCompanyFormType; | |||
| smsForm.value = reset().smsDataForm as LoginType.SmsFormType; | |||
| smsLoginForm.value = reset().smsLoginDataForm as LoginType.SmsLoginFormType; | |||
| getCaptcha() | |||
| } | |||
| const getCaptcha = () => { | |||
| capt_id.value = '' | |||
| createForm.value.captcha = ''; | |||
| GetCaptcha().then(res => { | |||
| capt_id.value = res.data.capt_id; | |||
| codeImage.value = res.data.img; | |||
| @@ -247,9 +244,9 @@ | |||
| const login = () => { | |||
| if (loginSegmentedValue.value == '我要求职') { | |||
| if (loginMethod == 'password') { | |||
| if (loginMethod.value == 'password') { | |||
| createForm.value.capt_id = capt_id.value; | |||
| PostCompanyLogin(createForm.value).then(res => { | |||
| PostJobseekerlogin(createForm.value).then(res => { | |||
| successToast('登录成功'); | |||
| store.commit('setShowLoginBox', { | |||
| showLoginBox: false | |||
| @@ -258,19 +255,19 @@ | |||
| token: res.data.jwttoken.accesstoken | |||
| }) | |||
| store.commit('getRole', { | |||
| role: 'company' | |||
| role: 'personal' | |||
| }) | |||
| store.commit('getPageType', { | |||
| pageType: 'company' | |||
| pageType: 'personal' | |||
| }) | |||
| sessionStorage.setItem('token', res.data.jwttoken.accesstoken) | |||
| sessionStorage.setItem('role', 'company') | |||
| sessionStorage.setItem('pageType', 'company') | |||
| sessionStorage.setItem('id', res.data.company_id) | |||
| sessionStorage.setItem('role', 'personal') | |||
| sessionStorage.setItem('pageType', 'personal') | |||
| sessionStorage.setItem('id', res.data.customerid) | |||
| store.commit('permissions/SET_PERMISSION', null) | |||
| store.commit('permissions/SET_MENU', []) | |||
| resetForm() | |||
| router.push('/manage/home') | |||
| router.push('/jobseeker/home') | |||
| }).catch(err => { | |||
| getCaptcha() | |||
| }) | |||
| @@ -304,32 +301,63 @@ | |||
| }) | |||
| } | |||
| } else { | |||
| createForm.value.capt_id = capt_id.value; | |||
| PostCompanyLogin(createForm.value).then(res => { | |||
| successToast('登录成功'); | |||
| store.commit('setShowLoginBox', { | |||
| showLoginBox: false | |||
| }) | |||
| store.commit('getToken', { | |||
| token: res.data.jwttoken.accesstoken | |||
| }) | |||
| store.commit('getRole', { | |||
| role: 'company' | |||
| if (loginMethod.value == 'password') { | |||
| createForm.value.capt_id = capt_id.value; | |||
| PostCompanyLogin(createForm.value).then(res => { | |||
| successToast('登录成功'); | |||
| store.commit('setShowLoginBox', { | |||
| showLoginBox: false | |||
| }) | |||
| store.commit('getToken', { | |||
| token: res.data.jwttoken.accesstoken | |||
| }) | |||
| store.commit('getRole', { | |||
| role: 'company' | |||
| }) | |||
| store.commit('getPageType', { | |||
| pageType: 'company' | |||
| }) | |||
| sessionStorage.setItem('token', res.data.jwttoken.accesstoken) | |||
| sessionStorage.setItem('role', 'company') | |||
| sessionStorage.setItem('pageType', 'company') | |||
| sessionStorage.setItem('id', res.data.company_id) | |||
| store.commit('permissions/SET_PERMISSION', null) | |||
| store.commit('permissions/SET_MENU', []) | |||
| resetForm() | |||
| router.push('/manage/home') | |||
| }).catch(err => { | |||
| getCaptcha() | |||
| }) | |||
| store.commit('getPageType', { | |||
| pageType: 'company' | |||
| } else { | |||
| smsLoginForm.value.mobile = createForm.value.username ? createForm.value.username : ''; | |||
| smsLoginForm.value.sms_code = Number(smsLoginForm.value.sms_code) | |||
| PostCompanyLoginByMobile(smsLoginForm.value).then(res => { | |||
| successToast('登录成功'); | |||
| store.commit('setShowLoginBox', { | |||
| showLoginBox: false | |||
| }) | |||
| store.commit('getToken', { | |||
| token: res.data.jwttoken.accesstoken | |||
| }) | |||
| store.commit('getRole', { | |||
| role: 'company' | |||
| }) | |||
| store.commit('getPageType', { | |||
| pageType: 'company' | |||
| }) | |||
| sessionStorage.setItem('token', res.data.jwttoken.accesstoken) | |||
| sessionStorage.setItem('role', 'company') | |||
| sessionStorage.setItem('pageType', 'company') | |||
| sessionStorage.setItem('id', res.data.company_id) | |||
| store.commit('permissions/SET_PERMISSION', null) | |||
| store.commit('permissions/SET_MENU', []) | |||
| resetForm() | |||
| router.push('/manage/home') | |||
| }).catch(err => { | |||
| getCaptcha() | |||
| }) | |||
| sessionStorage.setItem('token', res.data.jwttoken.accesstoken) | |||
| sessionStorage.setItem('role', 'company') | |||
| sessionStorage.setItem('pageType', 'company') | |||
| sessionStorage.setItem('id', res.data.company_id) | |||
| store.commit('permissions/SET_PERMISSION', null) | |||
| store.commit('permissions/SET_MENU', []) | |||
| resetForm() | |||
| router.push('/manage/home') | |||
| }).catch(err => { | |||
| getCaptcha() | |||
| }) | |||
| } | |||
| } | |||
| } | |||
| @@ -12,6 +12,7 @@ | |||
| <user-expense v-if="curKey == 1"></user-expense> | |||
| <user-password v-if="curKey == 2"></user-password> | |||
| <user-email v-if="curKey == 3"></user-email> | |||
| <user-conver v-if="curKey == 4"></user-conver> | |||
| </div> | |||
| </a-col> | |||
| </a-row> | |||
| @@ -25,8 +26,9 @@ | |||
| import UserExpense from '@/components/user/expense/index.vue' | |||
| import UserPassword from '@/components/user/password/index.vue' | |||
| import UserEmail from '@/components/user/email/index.vue' | |||
| import UserConver from '@/components/user/conver/index.vue' | |||
| let companyList = ref<object[]>([{}, {}, {}, {}, {}, {}]) | |||
| let menu_list = ref([{ title: '费用管理', key: 1 },{ title: '修改登录密码', key: 2},{ title: '修改邮箱', key: 3}]) | |||
| let menu_list = ref([{ title: '费用管理', key: 1 },{ title: '修改登录密码', key: 2},{ title: '修改邮箱', key: 3},{ title: '生成招聘者代码', key: 4}]) | |||
| let curKey = ref<Number>(1) | |||
| const changeKey = (data) => { | |||
| curKey.value = data.key; | |||