@@ -0,0 +1,3 @@ | |||
node_modules | |||
dist | |||
dist-ssr |
@@ -0,0 +1,3 @@ | |||
{ | |||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] | |||
} |
@@ -0,0 +1,18 @@ | |||
# Vue 3 + TypeScript + Vite | |||
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more. | |||
## Recommended IDE Setup | |||
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). | |||
## Type Support For `.vue` Imports in TS | |||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. | |||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: | |||
1. Disable the built-in TypeScript Extension | |||
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette | |||
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` | |||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. |
@@ -5,7 +5,7 @@ | |||
<link rel="icon" type="image/svg+xml" href="/logo_1.jpg" /> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
<title>后台管理系统</title> | |||
<script type="module" crossorigin src="/assets/index-gVPLuavq.js"></script> | |||
<script type="module" crossorigin src="/assets/index-uU_dXTTD.js"></script> | |||
<link rel="stylesheet" crossorigin href="/assets/index-ioYE9aJh.css"> | |||
</head> | |||
<body> |
@@ -0,0 +1,13 @@ | |||
<!doctype html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="UTF-8" /> | |||
<link rel="icon" type="image/svg+xml" href="/logo_1.jpg" /> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
<title>后台管理系统</title> | |||
</head> | |||
<body> | |||
<div id="app"></div> | |||
<script type="module" src="/src/main.ts"></script> | |||
</body> | |||
</html> |
@@ -0,0 +1,38 @@ | |||
{ | |||
"name": "job-master", | |||
"private": true, | |||
"version": "0.0.0", | |||
"type": "module", | |||
"scripts": { | |||
"dev": "vite", | |||
"build": "vue-tsc && vite build", | |||
"preview": "vite preview" | |||
}, | |||
"dependencies": { | |||
"@vueup/vue-quill": "^1.2.0", | |||
"ant-design-vue": "^4.0.7", | |||
"axios": "^1.6.2", | |||
"dayjs": "^1.11.10", | |||
"echarts": "^5.4.3", | |||
"moment": "^2.30.1", | |||
"vue": "^3.2.36", | |||
"vue-router": "^4.2.5", | |||
"vuex": "^4.1.0" | |||
}, | |||
"devDependencies": { | |||
"@vitejs/plugin-vue": "^4.5.0", | |||
"less": "^4.2.0", | |||
"less-loader": "^11.1.3", | |||
"typescript": "^5.2.2", | |||
"vite": "^5.0.0", | |||
"vue-tsc": "^1.8.22" | |||
}, | |||
"description": "This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.", | |||
"main": "index.js", | |||
"repository": { | |||
"type": "git", | |||
"url": "https://gitee.com/soleilw/job-master.git" | |||
}, | |||
"author": "", | |||
"license": "ISC" | |||
} |
@@ -0,0 +1,13 @@ | |||
<script setup lang="ts"> | |||
import zhCN from 'ant-design-vue/es/locale/zh_CN'; | |||
</script> | |||
<template> | |||
<a-config-provider :locale="zhCN"> | |||
<router-view></router-view> | |||
</a-config-provider> | |||
</template> | |||
<style scoped> | |||
</style> |
@@ -0,0 +1,88 @@ | |||
import axios from 'axios'; | |||
import * as typeHelper from '@/utils/typeHelper'; | |||
import { message } from 'ant-design-vue'; | |||
import { router } from '@/router'; | |||
const instance = axios.create({ | |||
// baseURL: 'http://114.132.85.7:8889', | |||
baseURL: 'https://rcsc-test.jcjob.cn/api', | |||
timeout: 30000, | |||
headers: { | |||
'Content-Type': 'application/json' | |||
}, | |||
withCredentials: false, | |||
}) | |||
// 请求拦截 | |||
// 添加请求拦截器 | |||
instance.interceptors.request.use(function (config) { | |||
sessionStorage.getItem('token') ? config.headers.Authorization = sessionStorage.getItem('token') : ''; | |||
// 在发送请求之前做些什么 | |||
return config; | |||
}, function (error) { | |||
// 对请求错误做些什么 | |||
return Promise.reject(error); | |||
}); | |||
// 添加响应拦截器 | |||
instance.interceptors.response.use(function (response) { | |||
switch (response.data.code) { | |||
case -1: | |||
message.warning(response.data.msg); | |||
break; | |||
case 0: | |||
break; | |||
case 1: | |||
return response; | |||
break; | |||
case 401: | |||
message.warning(response.data.msg); | |||
sessionStorage.clear(); | |||
window.location.reload(); | |||
router.replace('/login'); | |||
case 403: | |||
message.warning(response.data.msg); | |||
break; | |||
case 600: | |||
if(response.data.errors) { | |||
response.data.errors.forEach((item:String) => { | |||
message.warning(item); | |||
}) | |||
} else { | |||
message.warning(response.data.msg); | |||
} | |||
break; | |||
default: | |||
console.log(response) | |||
} | |||
// 2xx 范围内的状态码都会触发该函数。 | |||
// 对响应数据做点什么 | |||
return response; | |||
}, function (error) { | |||
// 超出 2xx 范围的状态码都会触发该函数。 | |||
// 对响应错误做点什么 | |||
console.log(error) | |||
return Promise.reject(error); | |||
}); | |||
export const httpGet : Function = (url : string, data : object, cb : Function) => { | |||
instance.get(url, { | |||
params: data | |||
}).then(res => { | |||
const resData = res; | |||
typeHelper.isFunction(cb) && cb(resData); | |||
}).catch(err => { | |||
cb(err.response) | |||
}) | |||
} | |||
export const httpPost : Function = (url : string, data : object, cb : Function) => { | |||
instance.post(url, data).then(res => { | |||
const resData = res; | |||
typeHelper.isFunction(cb) && cb(resData); | |||
}).catch(err => { | |||
console.log(err) | |||
// cb(err.response) | |||
}) | |||
} |
@@ -0,0 +1,203 @@ | |||
import { postModel, getModel } from '@/utils/reqHelper' | |||
import { url } from '../url' | |||
export const Login = postModel(url.userLogin); | |||
export const GetUserMenulist = getModel(url.UserMenulist); | |||
// 角色 | |||
export const PostRoleAdd = postModel(url.RoleAdd); | |||
export const PostRoleDel = postModel(url.RoleDel); | |||
export const PostRoleEdit = postModel(url.RoleEdit); | |||
export const GetRoleList = getModel(url.RoleList); | |||
export const PostRoleAddpermission = postModel(url.RoleAddpermission); | |||
export const getRoleGetpermissions = getModel(url.RoleGetpermissions); | |||
export const PostRoleDelpermission = postModel(url.RoleDelpermission); | |||
// 权限 | |||
export const addPermission = postModel(url.permissionAdd); | |||
export const getPermission = getModel(url.permissionList); | |||
export const updatePermission = postModel(url.permissionUpdate); | |||
export const getPermissionListWithchilds = getModel(url.permissionListWithchilds); | |||
// 账号 | |||
export const addAccount = postModel(url.accountAdd); | |||
export const getAccount = getModel(url.accountList); | |||
export const updateAccount = postModel(url.accountUpdate); | |||
// 企业 | |||
export const addCompany = postModel(url.companyAdd); | |||
export const getCompanyList = getModel(url.companyList); | |||
export const updateCompany = postModel(url.companyEdit); | |||
// VIP | |||
export const PostCompanyVipmanage = postModel(url.companyVipmanage); | |||
export const GetCompanyInfo = getModel(url.companyInfo); | |||
export const GetCompanyVipInfo = getModel(url.companyVipInfo); | |||
export const PostCompanyMultiClose = postModel(url.companyMultiClose); | |||
export const PostCompanyMultiOpen = postModel(url.companyMultiOpen); | |||
export const PostCompanyEdit = postModel(url.companyEdit); | |||
export const PostCompanyViplist = getModel(url.companyViplist); | |||
export const PostCompanyJobAdd = postModel(url.companyJobAdd); | |||
export const PostCompanyJobEdit = postModel(url.companyJobEdit); | |||
export const GetCompanyJobList = getModel(url.companyJobList); | |||
export const PostCompanyJobInfo = getModel(url.companyJobInfo); | |||
export const PostCompanyDepartmentAdd = postModel(url.companyDepartmentAdd); | |||
export const PostCompanyDepartmentEdit = postModel(url.companyDepartmentEdit); | |||
export const GetCompanyDepartmentList = getModel(url.CompanyDepartmentList); | |||
export const GetCompanyDepartmentInfo = getModel(url.companyDepartmentInfo); | |||
// 类型 | |||
export const PostHousekeepingtypeAdd = postModel(url.HousekeepingtypeAdd); | |||
export const PostHousekeepingtypeDel = postModel(url.HousekeepingtypeDel); | |||
export const PostHousekeepingtypeUpdate = postModel(url.HousekeepingtypeUpdate); | |||
export const GetHousekeepingtypeList = getModel(url.HousekeepingtypeList); | |||
export const GetHousekeepingtypeDetail = getModel(url.HousekeepingtypeDetail); | |||
// 职位 | |||
export const PostHousekeepingapplyAdd = postModel(url.HousekeepingapplyAdd); | |||
export const PostHousekeepingapplyDel = postModel(url.HousekeepingapplyDel); | |||
export const PostHousekeepingapplyUpdate = postModel(url.HousekeepingapplyUpdate); | |||
export const GetHousekeepingapplyList = getModel(url.HousekeepingapplyList); | |||
export const GetHousekeepingapplyDetail = getModel(url.HousekeepingapplyDetail); | |||
// 需求 | |||
export const PostHousekeepingAdd = postModel(url.HousekeepingAdd); | |||
export const PostHousekeepingDel = postModel(url.HousekeepingDel); | |||
export const PostHousekeepingUpdate = postModel(url.HousekeepingUpdate); | |||
export const GetHousekeepingList = getModel(url.HousekeepingList); | |||
export const GetHousekeepingDetail = getModel(url.HousekeepingDetail); | |||
// 预定 | |||
export const PostHousekeepingappointmentAdd = postModel(url.HousekeepingappointmentAdd); | |||
export const PostHousekeepingappointmentDel = postModel(url.HousekeepingappointmentDel); | |||
export const PostHousekeepingappointmentUpdate = postModel(url.HousekeepingappointmentUpdate); | |||
export const GetHousekeepingappointmentList = getModel(url.HousekeepingappointmentList); | |||
export const GetHousekeepingappointmentDetail = getModel(url.HousekeepingappointmentDetail); | |||
// 招聘会 | |||
export const PostRecruitmentAdd = postModel(url.RecruitmentAdd); | |||
export const PostRecruitmentDel = postModel(url.RecruitmentDel); | |||
export const PostRecruitmentUpdate = postModel(url.RecruitmentUpdate); | |||
export const listRecruitment = getModel(url.recruitmentList); | |||
export const GetRecruitmentDetail = getModel(url.RecruitmentDetail); | |||
// 招聘会企业 | |||
export const PostRecruitmentBookAdd = postModel(url.RecruitmentBookAdd); | |||
export const PostRecruitmentBookDel = postModel(url.RecruitmentBookDel); | |||
export const PostRecruitmentBookUpdate = postModel(url.RecruitmentBookUpdate); | |||
export const GetRecruitmentBookList = getModel(url.RecruitmentBookList); | |||
// 文章栏目 | |||
export const addSection = postModel(url.sectionAdd); | |||
export const delSection = postModel(url.sectionDel); | |||
export const updateSection = postModel(url.sectionUpdate); | |||
export const listSection = getModel(url.sectionList); | |||
// 文章 | |||
export const addArticle = postModel(url.articleAdd); | |||
export const delArticle = postModel(url.articleDel); | |||
export const updateArticle = postModel(url.articleUpdate); | |||
export const listArticle = getModel(url.articleList); | |||
// 广告 | |||
export const PostAdvertareaAdd = postModel(url.advertareaAdd); | |||
export const PostAdvertareaDel = postModel(url.advertareaDel); | |||
export const PostAdvertareaUpdate = postModel(url.advertareaUpdate); | |||
export const GetAdvertareaList = getModel(url.advertareaList); | |||
export const GetAdvertareaDetail = getModel(url.advertareaDetail); | |||
// 投放 | |||
export const PostAdvertscheduleAdd = postModel(url.advertscheduleAdd); | |||
export const PostAdvertscheduleDel = postModel(url.advertscheduleDel); | |||
export const PostAdvertscheduleUpdate = postModel(url.advertscheduleUpdate); | |||
export const GetAdvertscheduleList = getModel(url.advertscheduleList); | |||
export const GetAdvertscheduleDetail = getModel(url.advertscheduleDetail); | |||
// 活动 | |||
export const PostActivityExportUsers = postModel(url.activityExportUsers); | |||
export const PostActivityaddressAdd = postModel(url.activityaddressAdd); | |||
export const PostActivityaddressDel = postModel(url.activityaddressDel); | |||
export const PostActivityaddressUpdate = postModel(url.activityaddressUpdate); | |||
export const GetActivityaddressList = getModel(url.activityaddressList); | |||
export const GetActivityaddressDetail = getModel(url.activityaddressDetail); | |||
export const GetActivityaddressCate = getModel(url.activityaddressCate); | |||
// 字典数据 | |||
export const GetDictTree = getModel(url.dictTree); | |||
export const PostImageUpload = postModel(url.ImageUpload); | |||
// 简历 | |||
// 列表 | |||
export const PostJobseekerList = postModel(url.JobseekerList); | |||
export const GetJobseekerDetail = getModel(url.JobseekerDetail); | |||
// 基本资料 | |||
export const PostJobapplicantAdd = postModel(url.JobapplicantAdd); | |||
export const PostJobapplicantDel = postModel(url.JobapplicantDel); | |||
export const PostJobapplicantUpdate = postModel(url.JobapplicantUpdate); | |||
export const GetJobapplicantList = getModel(url.JobapplicantList); | |||
export const GetJobapplicantDetail = getModel(url.JobapplicantDetail); | |||
// 联系方式 | |||
export const PostJobapplicantAddcontact = postModel(url.JobapplicantAddcontact); | |||
export const PostJobapplicantDelcontact = postModel(url.JobapplicantDelcontact); | |||
export const PostJobapplicantUpdatecontact = postModel(url.JobapplicantUpdatecontact); | |||
export const PostJobapplicantListcontact = getModel(url.JobapplicantListcontact); | |||
export const PostJobapplicantContactdetail = getModel(url.JobapplicantContactdetail); | |||
// 证书技能 | |||
export const PostJobapplicantAddskill = postModel(url.JobapplicantAddskill); | |||
export const PostJobapplicantDelskill = postModel(url.JobapplicantDelskill); | |||
export const PostJobapplicantUpdateskill = postModel(url.JobapplicantUpdateskill); | |||
export const PostJobapplicantListskill = getModel(url.JobapplicantListskill); | |||
export const PostJobapplicantSkilldetail = getModel(url.JobapplicantSkilldetail); | |||
// 培训经历 | |||
export const PostJobapplicantAddtraining = postModel(url.JobapplicantAddtraining); | |||
export const PostJobapplicantDeltraining = postModel(url.JobapplicantDeltraining); | |||
export const PostJobapplicantUpdatetraining = postModel(url.JobapplicantUpdatetraining); | |||
export const PostJobapplicantListtraining = getModel(url.JobapplicantListtraining); | |||
export const PostJobapplicantTrainingdetail = getModel(url.JobapplicantTrainingdetail); | |||
// 求职意向-基本 | |||
export const PostJobapplicantAdddesirebase = postModel(url.JobapplicantAdddesirebase); | |||
export const PostJobapplicantDeldesirebase = postModel(url.JobapplicantDeldesirebase); | |||
export const PostJobapplicantUpdatedesirebase = postModel(url.JobapplicantUpdatedesirebase); | |||
export const PostJobapplicantListdesirebase = getModel(url.JobapplicantListdesirebase); | |||
export const PostJobapplicantDesirebasedetail = getModel(url.JobapplicantDesirebasedetail); | |||
// 求职意向-地区 | |||
export const PostJobapplicantAdddesirearea = postModel(url.JobapplicantAdddesirearea); | |||
export const PostJobapplicantDeldesirearea = postModel(url.JobapplicantDeldesirearea); | |||
export const PostJobapplicantUpdatedesirearea = postModel(url.JobapplicantUpdatedesirearea); | |||
export const PostJobapplicantListdesirearea = getModel(url.JobapplicantListdesirearea); | |||
export const PostJobapplicantDesireareadetail = getModel(url.JobapplicantDesireareadetail); | |||
// 求职意向-职位 | |||
export const PostJobapplicantAdddesireindustry = postModel(url.JobapplicantAdddesireindustry); | |||
export const PostJobapplicantDeldesireindustry = postModel(url.JobapplicantDeldesireindustry); | |||
export const PostJobapplicantUpdatedesireindustry = postModel(url.JobapplicantUpdatedesireindustry); | |||
export const PostJobapplicantListdesireindustry = getModel(url.JobapplicantListdesireindustry); | |||
export const PostJobapplicantDesireindustrydetail = getModel(url.JobapplicantDesireindustrydetail); | |||
// 工作经历 | |||
export const PostJobapplicantAddexperience = postModel(url.JobapplicantAddexperience); | |||
export const PostJobapplicantDelexperience = postModel(url.JobapplicantDelexperience); | |||
export const PostJobapplicantUpdateexperience = postModel(url.JobapplicantUpdateexperience); | |||
export const PostJobapplicantListexperience = getModel(url.JobapplicantListexperience); | |||
export const PostJobapplicantExperiencedetail = getModel(url.JobapplicantExperiencedetail); | |||
// 证书 | |||
export const PostJobapplicantAddcertificate = postModel(url.JobapplicantAddcertificate); | |||
export const PostJobapplicantUpdatecertificate = postModel(url.JobapplicantUpdatecertificate); | |||
export const PostJobapplicantListcertificate = getModel(url.JobapplicantListcertificate); | |||
export const PostJobapplicantCertificatedetail = getModel(url.JobapplicantCertificatedetail); | |||
export const PostJobapplicantAddintroduction = postModel(url.JobapplicantAddintroduction); // 个人介绍 | |||
export const PostJobapplicantDelintroduction = postModel(url.JobapplicantDelintroduction); // 个人介绍 | |||
export const PostJobapplicantUpdateintroduction = postModel(url.JobapplicantUpdateintroduction); // 个人介绍 | |||
export const GetJobapplicantListintroduction = getModel(url.JobapplicantListintroduction); // 个人介绍 | |||
export const GetJobapplicantIntroductiondetail = getModel(url.JobapplicantIntroductiondetail); // 个人详情 | |||
// 统计 | |||
export const GetStatsMajor= getModel(url.StatsMajor); | |||
export const GetStatsCertificate= getModel(url.StatsCertificate); | |||
export const GetStatsWorkExperience= getModel(url.StatsWorkExperience); | |||
export const GetStatsHa= getModel(url.StatsHa); | |||
export const GetStatsAgeandgender= getModel(url.StatsAgeandgender); | |||
export const GetStatsEducation= getModel(url.StatsEducation); | |||
export const GetStatsPosition= getModel(url.StatsPosition); |
@@ -0,0 +1,9 @@ | |||
declare namespace roleType { | |||
type addRoleType = { | |||
id ?: string, | |||
name: string, | |||
code: string, | |||
description: string | |||
} | |||
} |
@@ -0,0 +1,9 @@ | |||
declare namespace searchType { | |||
type searchParams = { | |||
page : string, | |||
pagesize : string, | |||
sort : string, | |||
sortby : string, | |||
keyword ?: string | |||
} | |||
} |
@@ -0,0 +1,188 @@ | |||
declare namespace urlType { | |||
type url = { | |||
userLogin : String, | |||
UserMenulist : String, | |||
RoleAdd : String, | |||
RoleList : String, | |||
RoleDel : String, | |||
RoleEdit : String, | |||
RoleAddpermission : String, | |||
RoleGetpermissions : String, | |||
RoleDelpermission : String, | |||
permissionAdd : String, | |||
permissionList : String, | |||
permissionUpdate : String, | |||
permissionListWithchilds : String, | |||
accountAdd : String, | |||
accountList : String, | |||
accountUpdate : String, | |||
companyAdd : String, | |||
companyList : String, | |||
companyEdit : String, | |||
companyInfo : String, | |||
companyVipInfo : String, | |||
companyMultiClose : String, | |||
companyMultiOpen : String, | |||
companyEdit : String, | |||
companyVipmanage : String, | |||
companyViplist : String, | |||
companyJobAdd : String, | |||
companyJobEdit : String, | |||
companyJobList : String, | |||
companyJobInfo : String, | |||
companyDepartmentAdd : String, | |||
companyDepartmentEdit : String, | |||
CompanyDepartmentList : String, | |||
companyDepartmentInfo : String, | |||
// 类型 | |||
HousekeepingtypeAdd : String, | |||
HousekeepingtypeDel : String, | |||
HousekeepingtypeUpdate : String, | |||
HousekeepingtypeList : String, | |||
HousekeepingtypeDetail : String, | |||
// 职位 | |||
HousekeepingapplyAdd : String, | |||
HousekeepingapplyDel : String, | |||
HousekeepingapplyUpdate : String, | |||
HousekeepingapplyList : String, | |||
HousekeepingapplyDetail : String, | |||
// 需求 | |||
HousekeepingAdd : String, | |||
HousekeepingDel : String, | |||
HousekeepingUpdate : String, | |||
HousekeepingList : String, | |||
HousekeepingDetail : String, | |||
// 预定 | |||
HousekeepingappointmentAdd : String, | |||
HousekeepingappointmentDel : String, | |||
HousekeepingappointmentUpdate : String, | |||
HousekeepingappointmentList : String, | |||
HousekeepingappointmentDetail : String, | |||
RecruitmentAdd : String, | |||
RecruitmentDel : String, | |||
RecruitmentUpdate : String, | |||
recruitmentList : String, | |||
RecruitmentDetail : String, | |||
RecruitmentBookAdd : String, | |||
RecruitmentBookDel : String, | |||
RecruitmentBookUpdate : String, | |||
RecruitmentBookList : String, | |||
sectionAdd : String, | |||
sectionDel : String, | |||
sectionUpdate : String, | |||
sectionList : String, | |||
// 文章 | |||
articleAdd : String, | |||
articleDel : String, | |||
articleUpdate : String, | |||
articleList : String, | |||
dictTree : String, | |||
ImageUpload : String, | |||
advertareaAdd : String, | |||
advertareaDel : String, | |||
advertareaUpdate : String, | |||
advertareaList : String, | |||
advertareaDetail : String, | |||
advertscheduleAdd : String, | |||
advertscheduleDel : String, | |||
advertscheduleUpdate : String, | |||
advertscheduleList : String, | |||
advertscheduleDetail : String, | |||
// 活动 | |||
activityExportUsers: String, | |||
activityaddressAdd: String, | |||
activityaddressDel: String, | |||
activityaddressUpdate: String, | |||
activityaddressList: String, | |||
activityaddressDetail: String, | |||
activityaddressCate: String, | |||
// 简历 | |||
// 列表 | |||
'JobseekerList' : String, // 查看 | |||
'JobseekerDetail' : String, // 详情 | |||
// 基本资料 | |||
'JobapplicantAdd' : String, // 添加 | |||
'JobapplicantDel' : String, // 删除 | |||
'JobapplicantUpdate' : String, // 修改 | |||
'JobapplicantList' : String, // 查看 | |||
'JobapplicantDetail' : String, // 详情 | |||
// 个人介绍 | |||
'JobapplicantAddintroduction' : String, | |||
'JobapplicantDelintroduction' : String, | |||
'JobapplicantUpdateintroduction' : String, | |||
'JobapplicantListintroduction' : String, | |||
'JobapplicantIntroductiondetail' : String, | |||
// 联系信息 | |||
'JobapplicantAddcontact' : String, | |||
'JobapplicantDelcontact' : String, | |||
'JobapplicantUpdatecontact' : String, | |||
'JobapplicantListcontact' : String, | |||
'JobapplicantContactdetail' : String, | |||
// 专业技能 | |||
'JobapplicantAddskill' : String, | |||
'JobapplicantDelskill' : String, | |||
'JobapplicantUpdateskill' : String, | |||
'JobapplicantListskill' : String, | |||
'JobapplicantSkilldetail' : String, | |||
// 培训经历 | |||
'JobapplicantAddtraining' : String, | |||
'JobapplicantDeltraining' : String, | |||
'JobapplicantUpdatetraining' : String, | |||
'JobapplicantListtraining' : String, | |||
'JobapplicantTrainingdetail' : String, | |||
// 求职意向-基本 | |||
'JobapplicantAdddesirebase' : String, | |||
'JobapplicantDeldesirebase' : String, | |||
'JobapplicantUpdatedesirebase' : String, | |||
'JobapplicantDesirebasedetail' : String, | |||
// 求职意向-地区 | |||
'JobapplicantAdddesirearea' : String, | |||
'JobapplicantDeldesirearea' : String, | |||
'JobapplicantUpdatedesirearea' : String, | |||
'JobapplicantListdesirearea' : String, | |||
'JobapplicantDesireareadetail' : String, | |||
// 求职意向-职位 | |||
'JobapplicantAdddesireindustry' : String, | |||
'JobapplicantDeldesireindustry' : String, | |||
'JobapplicantUpdatedesireindustry' : String, | |||
'JobapplicantListdesireindustry' : String, | |||
'JobapplicantDesireindustrydetail' : String, | |||
// 证书 | |||
'JobapplicantAddcertificate' : String, | |||
'JobapplicantDelcertificate' : String, | |||
'JobapplicantUpdatecertificate' : String, | |||
'JobapplicantListcertificate' : String, | |||
'JobapplicantCertificatedetail' : String, | |||
// 工作经历 | |||
'JobapplicantAddexperience' : String, | |||
'JobapplicantDelexperience' : String, | |||
'JobapplicantUpdateexperience' : String, | |||
'JobapplicantListexperience' : String, | |||
'JobapplicantExperiencedetail' : String, | |||
// 统计 | |||
StatsMajor: String, | |||
StatsCertificate: String, | |||
StatsWorkExperience: String, | |||
StatsHa: String, | |||
StatsAgeandgender: String, | |||
StatsEducation: String, | |||
StatsPosition: String, | |||
} | |||
} |
@@ -0,0 +1,193 @@ | |||
let admin : string = '/admin'; | |||
let common : string = '/common'; | |||
// 角色 | |||
export const url : urlType.url = { | |||
userLogin: admin + '/user/login', | |||
UserMenulist: admin + '/user/menulist', | |||
// 角色 | |||
RoleAdd: admin + '/role/add', | |||
RoleList: admin + '/role/list', | |||
RoleDel: admin + '/role/del', | |||
RoleEdit: admin + '/role/update', | |||
RoleAddpermission: admin + '/role/addpermission', | |||
RoleGetpermissions: admin + '/role/getpermissions', | |||
RoleDelpermission: admin + '/role/delpermission', | |||
permissionAdd: admin + '/permission/add', | |||
permissionList: admin + '/permission/list', | |||
permissionUpdate: admin + '/permission/update', | |||
permissionListWithchilds: admin + '/permission/listwithchilds', | |||
accountAdd: admin + '/user/add', | |||
accountList: admin + '/user/list', | |||
accountUpdate: admin + '/user/update', | |||
companyAdd: admin + '/company/add', | |||
companyList: admin + '/company/list', | |||
companyInfo: admin + '/company/info', | |||
companyVipInfo: admin + '/company/vipinfo', | |||
companyMultiClose: admin + '/company/multiclose', | |||
companyMultiOpen: admin + '/company/multiopen', | |||
companyEdit: admin + '/company/edit', | |||
companyVipmanage: admin + '/company/vipmanage', | |||
companyViplist: admin + '/company/viplist', | |||
companyJobAdd: admin + '/company/job_add', | |||
companyJobEdit: admin + '/company/job_edit', | |||
companyJobList: admin + '/company/job_list', | |||
companyJobInfo: admin + '/company/job_info', | |||
companyDepartmentAdd: admin + '/company/department_add', | |||
companyDepartmentEdit: admin + '/company/department_edit', | |||
CompanyDepartmentList: admin + '/company/department_list', | |||
companyDepartmentInfo: admin + '/company/department_info', | |||
// 家政 | |||
// 类型 | |||
HousekeepingtypeAdd: admin + '/housekeepingtype/add', | |||
HousekeepingtypeDel: admin + '/housekeepingtype/del', | |||
HousekeepingtypeUpdate: admin + '/housekeepingtype/update', | |||
HousekeepingtypeList: admin + '/housekeepingtype/list', | |||
HousekeepingtypeDetail: admin + '/housekeepingtype/detail', | |||
// 职位 | |||
HousekeepingapplyAdd: admin + '/housekeepingapply/add', | |||
HousekeepingapplyDel: admin + '/housekeepingapply/del', | |||
HousekeepingapplyUpdate: admin + '/housekeepingapply/update', | |||
HousekeepingapplyList: admin + '/housekeepingapply/list', | |||
HousekeepingapplyDetail: admin + '/housekeepingapply/detail', | |||
// 需求 | |||
HousekeepingAdd: admin + '/housekeeping/add', | |||
HousekeepingDel: admin + '/housekeeping/del', | |||
HousekeepingUpdate: admin + '/housekeeping/update', | |||
HousekeepingList: admin + '/housekeeping/list', | |||
HousekeepingDetail: admin + '/housekeeping/detail', | |||
// 预定 | |||
HousekeepingappointmentAdd: admin + '/housekeepingappointment/add', | |||
HousekeepingappointmentDel: admin + '/housekeepingappointment/del', | |||
HousekeepingappointmentUpdate: admin + '/housekeepingappointment/update', | |||
HousekeepingappointmentList: admin + '/housekeepingappointment/list', | |||
HousekeepingappointmentDetail: admin + '/housekeepingappointment/detail', | |||
// 招聘会 | |||
RecruitmentAdd: admin + '/recruitment/add', | |||
RecruitmentDel: admin + '/recruitment/del', | |||
RecruitmentUpdate: admin + '/recruitment/update', | |||
recruitmentList: admin + '/recruitment/list', | |||
RecruitmentDetail: admin + '/recruitment/detail', | |||
// 招聘参与企业 | |||
RecruitmentBookAdd: admin + '/recruitmentbook/add', | |||
RecruitmentBookDel: admin + '/recruitmentbook/del', | |||
RecruitmentBookUpdate: admin + '/recruitmentbook/update', | |||
RecruitmentBookList: admin + '/recruitmentbook/list', | |||
// 文章栏目 | |||
sectionAdd: admin + '/section/add', | |||
sectionDel: admin + '/section/del', | |||
sectionUpdate: admin + '/section/update', | |||
sectionList: admin + '/section/list', | |||
// 文章 | |||
articleAdd: admin + '/article/add', | |||
articleDel: admin + '/article/del', | |||
articleUpdate: admin + '/article/update', | |||
articleList: admin + '/article/list', | |||
// 字典 | |||
dictTree: common + '/dict/tree', | |||
ImageUpload: common + '/image/upload?imgtype=1', | |||
// 广告 | |||
// 广告列表 | |||
advertareaAdd: admin + '/advertarea/add', | |||
advertareaDel: admin + '/advertarea/del', | |||
advertareaUpdate: admin + '/advertarea/update', | |||
advertareaList: admin + '/advertarea/list', | |||
advertareaDetail: admin + '/advertarea/detail', | |||
// 投放 | |||
advertscheduleAdd: admin + '/advertschedule/add', | |||
advertscheduleDel: admin + '/advertschedule/del', | |||
advertscheduleUpdate: admin + '/advertschedule/update', | |||
advertscheduleList: admin + '/advertschedule/list', | |||
advertscheduleDetail: admin + '/advertarea/detail', | |||
// 活动管理 | |||
activityExportUsers: admin + '/activity/export_users', // 导出参加活动用户 | |||
// 活动地址 | |||
activityaddressAdd: admin + '/activityaddress/add', | |||
activityaddressDel: admin + '/activityaddress/del', | |||
activityaddressUpdate: admin + '/activityaddress/update', | |||
activityaddressList: admin + '/activityaddress/list', | |||
activityaddressDetail: admin + '/activityaddress/detail', | |||
activityaddressCate: admin + '/activityaddress/cate', // 地址分类 | |||
// 简历 | |||
// 列表 | |||
'JobseekerList': admin + '/jobseeker/list', // 查看 | |||
'JobseekerDetail': admin + '/jobseeker/detail', // 详情 | |||
// 基本资料 | |||
'JobapplicantAdd': admin + '/jobapplicant/add', // 添加 | |||
'JobapplicantDel': admin + '/jobapplicant/del', // 删除 | |||
'JobapplicantUpdate': admin + '/jobapplicant/update', // 修改 | |||
'JobapplicantList': admin + '/jobapplicant/list', // 查看 | |||
'JobapplicantDetail': admin + '/jobapplicant/detail', // 详情 | |||
// 个人介绍 | |||
'JobapplicantAddintroduction': '/admin/jobapplicant/addintroduction', | |||
'JobapplicantDelintroduction': admin + '/jobapplicant/delintroduction', // 删除 | |||
'JobapplicantUpdateintroduction': admin + '/jobapplicant/updateintroduction', // 修改 | |||
'JobapplicantListintroduction': '/admin/jobapplicant/listintroduction', | |||
'JobapplicantIntroductiondetail': '/admin/jobapplicant/introductiondetail', | |||
// 联系信息 | |||
'JobapplicantAddcontact': admin + '/jobapplicant/addcontact', // 添加 | |||
'JobapplicantDelcontact': admin + '/jobapplicant/delcontact', // 删除 | |||
'JobapplicantUpdatecontact': admin + '/jobapplicant/updatecontact', // 修改 | |||
'JobapplicantListcontact': admin + '/jobapplicant/listcontact', // 查看 | |||
'JobapplicantContactdetail': admin + '/jobapplicant/contactdetail', // 详情 | |||
// 专业技能 | |||
'JobapplicantAddskill': admin + '/jobapplicant/addskill', // 添加 | |||
'JobapplicantDelskill': admin + '/jobapplicant/delskill', // 删除 | |||
'JobapplicantUpdateskill': admin + '/jobapplicant/updateskill', // 修改 | |||
'JobapplicantListskill': admin + '/jobapplicant/listskill', // 查看 | |||
'JobapplicantSkilldetail': admin + '/jobapplicant/skilldetail', // 详情 | |||
// 培训经历 | |||
'JobapplicantAddtraining': admin + '/jobapplicant/addtraining', // 添加 | |||
'JobapplicantDeltraining': admin + '/jobapplicant/deltraining', // 删除 | |||
'JobapplicantUpdatetraining': admin + '/jobapplicant/updatetraining', // 修改 | |||
'JobapplicantListtraining': admin + '/jobapplicant/listtraining', // 查看 | |||
'JobapplicantTrainingdetail': admin + '/jobapplicant/trainingdetail', // 详情 | |||
// 求职意向-基本 | |||
'JobapplicantAdddesirebase': '/admin/jobapplicant/adddesirebase', // 添加 | |||
'JobapplicantDeldesirebase': '/admin/jobapplicant/deldesirebase', // 删除 | |||
'JobapplicantUpdatedesirebase': '/admin/jobapplicant/updatedesirebase', // 修改 | |||
'JobapplicantDesirebasedetail': '/admin/jobapplicant/desirebasedetail', // 详情 | |||
// 求职意向-地区 | |||
'JobapplicantAdddesirearea': admin + '/jobapplicant/adddesirearea', // 添加 | |||
'JobapplicantDeldesirearea': admin + '/jobapplicant/deldesirearea', // 删除 | |||
'JobapplicantUpdatedesirearea': admin + '/jobapplicant/updatedesirearea', // 修改 | |||
'JobapplicantListdesirearea': admin + '/jobapplicant/listdesirearea', // 查看 | |||
'JobapplicantDesireareadetail': admin + '/jobapplicant/desireareadetail', // 详情 | |||
// 求职意向-职位 | |||
'JobapplicantAdddesireindustry': admin + '/jobapplicant/adddesireindustry', // 添加 | |||
'JobapplicantDeldesireindustry': admin + '/jobapplicant/deldesireindustry', // 删除 | |||
'JobapplicantUpdatedesireindustry': admin + '/jobapplicant/updatedesireindustry', // 修改 | |||
'JobapplicantListdesireindustry': admin + '/jobapplicant/listdesireindustry', // 查看 | |||
'JobapplicantDesireindustrydetail': admin + '/jobapplicant/desireindustrydetail', // 详情 | |||
// 证书 | |||
'JobapplicantAddcertificate': admin + '/jobapplicant/addcertificate', // 添加 | |||
'JobapplicantDelcertificate': admin + '/jobapplicant/delcertificate', // 删除 | |||
'JobapplicantUpdatecertificate': admin + '/jobapplicant/updatecertificate', // 修改 | |||
'JobapplicantListcertificate': admin + '/jobapplicant/listcertificate', // 查看 | |||
'JobapplicantCertificatedetail': admin + '/jobapplicant/certificatedetail', // 详情 | |||
// 工作经历 | |||
'JobapplicantAddexperience': admin + '/jobapplicant/addexperience', // 添加 | |||
'JobapplicantDelexperience': admin + '/jobapplicant/delexperience', // 删除 | |||
'JobapplicantUpdateexperience': admin + '/jobapplicant/updateexperience', // 修改 | |||
'JobapplicantListexperience': admin + '/jobapplicant/listexperience', // 查看 | |||
'JobapplicantExperiencedetail': admin + '/jobapplicant/experiencedetail', // 详情 | |||
// 统计 | |||
StatsMajor: admin + '/stats/major', // 求职者专业统计 | |||
StatsCertificate: admin + '/stats/certificate', // 求职者技能证书统计 | |||
StatsWorkExperience: admin + '/stats/work_experience', // 求职者工作经验统计 | |||
StatsHa: admin + '/stats/ha', // 求职者节假日与食宿统计 | |||
StatsAgeandgender: admin + '/stats/ageandgender', // 求职者年龄与性别统计 | |||
StatsEducation: admin + '/stats/education', // 求职者学历统计 | |||
StatsPosition: admin + '/stats/position', // 求职者求职意向统计 | |||
} |
@@ -0,0 +1 @@ | |||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg> |
@@ -0,0 +1,39 @@ | |||
<template> | |||
<a-cascader v-model:value="cascaderParentId" @change="parentChange" :options="listOptions" | |||
:fieldNames="listFieldNames" :changeOnSelect="true" :placeholder="placeholder" style="width: 100%" change-on-select/> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, defineProps, watch, defineEmits } from 'vue'; | |||
import { GetDictTree } from '@/apis/models'; | |||
const props = defineProps(['dict', 'placeholder', 'cascader_content']); | |||
let listOptions = ref([]); | |||
let cascaderParentId = ref<String>([]); | |||
const listFieldNames = ref({ label: 'name', value: 'id', children: 'children' }); | |||
let placeholder = ref('请选择'); | |||
placeholder.value = props.placeholder | |||
watch(() => [props.dict, props.cascader_content], | |||
(newVal, oldVal) => { | |||
GetDictTree({ | |||
code: newVal[0] | |||
}).then(res => { | |||
listOptions.value = res.data.dicts | |||
}) | |||
cascaderParentId.value = newVal[1] | |||
}) | |||
onMounted(() => { | |||
GetDictTree({ | |||
code: props.dict | |||
}).then(res => { | |||
listOptions.value = res.data.dicts | |||
}) | |||
}) | |||
const emit = defineEmits(); | |||
const parentChange = (val, selectedOptions) => { | |||
emit('saveCascader', {arr1: val, arr2: selectedOptions}); | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,52 @@ | |||
<template> | |||
<div ref="pie" style="width: 100%; height: 240px;"></div> | |||
</template> | |||
<script setup lang="ts"> | |||
import { ref, onMounted, computed } from 'vue'; | |||
import { init } from 'echarts'; | |||
const pie = ref(null); | |||
// 设置环形图的数据 | |||
const ageData = [ | |||
{ name: '0-18岁', value: 20 }, | |||
{ name: '19-30岁', value: 30 }, | |||
{ name: '31-45岁', value: 40 }, | |||
{ name: '46岁以上', value: 10 }, | |||
]; | |||
// 使用setup函数创建环形图 | |||
onMounted(() => { | |||
console.log(pie) | |||
const aa = init(pie.value) | |||
const option = { | |||
legend: { | |||
orient: 'vertical', | |||
top: '10%', | |||
left: 'left' | |||
}, | |||
tooltip: { | |||
trigger: 'item', | |||
formatter: '{a} <br/>{b} : {c} ({d}%)', | |||
}, | |||
series: [ | |||
{ | |||
name: '年龄分布', | |||
type: 'pie', | |||
radius: ['40%', '70%'], | |||
center: ['50%', '50%'], | |||
data: ageData, | |||
emphasis: { | |||
itemStyle: { | |||
shadowBlur: 10, | |||
shadowOffsetX: 0, | |||
shadowColor: 'rgba(0, 0, 0, 0.5)', | |||
}, | |||
}, | |||
}, | |||
], | |||
}; | |||
aa.setOption(option) | |||
}); | |||
</script> |
@@ -0,0 +1,50 @@ | |||
<template> | |||
<a-row :gutter="16" style="margin-bottom: 16px;"> | |||
<a-col v-if="needAdd"> | |||
<a-button type="primary" @click="showModal"> | |||
<template #icon> | |||
<PlusOutlined /> | |||
</template> | |||
新建 | |||
</a-button> | |||
</a-col> | |||
<a-col> | |||
<a-button type="primary" @click="refreshTable"> | |||
<template #icon> | |||
<SyncOutlined /> | |||
</template> | |||
刷新 | |||
</a-button> | |||
</a-col> | |||
<a-col> | |||
<a-button type="primary" @click="showSearch"> | |||
<template #icon> | |||
<SearchOutlined /> | |||
</template> | |||
搜索 | |||
</a-button> | |||
</a-col> | |||
<slot></slot> | |||
</a-row> | |||
</template> | |||
<script setup lang="ts"> | |||
import { ref, defineProps, computed, watch, defineEmits } from 'vue'; | |||
import { SyncOutlined, PlusOutlined, SearchOutlined } from '@ant-design/icons-vue'; | |||
import { useCommon } from '@/hooks/useCommon'; | |||
let { showModal, showSearch } = useCommon(); | |||
let props = defineProps({ | |||
need_add: { | |||
type: Boolean, | |||
default: true | |||
} | |||
}); | |||
let needAdd = ref<Boolean>(props.need_add) | |||
const emit = defineEmits(); | |||
const refreshTable = () => { | |||
emit('refresh'); | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,103 @@ | |||
<template> | |||
<div> | |||
<template v-for="(item, index) in permissionList"> | |||
<a-row class="a-row" align="middle"> | |||
<a-col span="6" class="a-col"> | |||
<a-checkbox v-model:checked="item.checked" @change="one($event, index, item)" | |||
:label="item.name">{{item.name}}</a-checkbox> | |||
</a-col> | |||
<a-col span="18" class="a-col"> | |||
<template v-if="item.childs"> | |||
<a-row align="middle"> | |||
<template v-for="(childItem, childIndex) in item.childs"> | |||
<a-col span="6" class="a-col"><a-checkbox v-model:checked="childItem.checked" | |||
@change="one($event, index, childItem)" | |||
:label="childItem.name">{{childItem.name}}</a-checkbox></a-col> | |||
<a-col span="18" class="a-col"> | |||
<template v-if="childItem.childs"> | |||
<a-row align="middle"> | |||
<template v-for="(thirdItem, thirdIndex) in childItem.childs"> | |||
<a-col span="6"><a-checkbox v-model:checked="thirdItem.checked" | |||
@change="one($event, index, thirdItem)" | |||
:label="thirdItem.name">{{thirdItem.name}}</a-checkbox></a-col> | |||
</template> | |||
</a-row> | |||
</template> | |||
</a-col> | |||
</template> | |||
</a-row> | |||
</template> | |||
</a-col> | |||
</a-row> | |||
</template> | |||
</div> | |||
</template> | |||
<script setup lang="ts"> | |||
import { ref, onMounted, defineProps, watch } from 'vue'; | |||
import { getPermissionListWithchilds, getRoleGetpermissions, PostRoleAddpermission } from '@/apis/models'; | |||
import { message } from 'ant-design-vue'; | |||
const emit = defineEmits(); | |||
let permissionList = ref<object[]>([]) | |||
let props = defineProps(['roleId', 'roleName']); | |||
onMounted(async () => { | |||
let res = await getPermissionListWithchilds({ page: 1, pagesize: 10, sort: 'id', sortby: "asc", keyword: "" }); | |||
permissionList.value = res.data.permissions; | |||
let res1 = await getRoleGetpermissions({ ids: props.roleId.toString() }); | |||
emit('detailTitle', { title: props.roleName, length: res1.data.permissions.length }); | |||
permissionList.value = markChecked(permissionList.value, res1.data.permissions); | |||
}) | |||
const one = (e, index, item) => { | |||
PostRoleAddpermission({ role_id: props.roleId, permission_id: item.id }).then(res => { | |||
message.success('为角色新增菜单/权限成功'); | |||
getOneRole(); | |||
}) | |||
} | |||
// 获取角色的权限 | |||
const getOneRole = () => { | |||
getRoleGetpermissions({ ids: props.roleId.toString() }).then(res => { | |||
permissionList.value = markChecked(permissionList.value, res.data.permissions); | |||
}); | |||
} | |||
const markChecked = (arr1, arr2) => { | |||
arr1.forEach((itemA : Object) => { | |||
const matchingItem = arr2.find(itemB => itemB.id === itemA.id); | |||
if (matchingItem) { | |||
itemA.checked = true; | |||
} | |||
if (itemA.childs && itemA.childs.length) { | |||
debugger | |||
markChecked(itemA.childs, arr2); | |||
} | |||
}); | |||
return arr1; | |||
} | |||
</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> |
@@ -0,0 +1,200 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item required label="简历是否可见" name="简历是否可见"> | |||
<a-radio-group v-model:value="createForm.hide_resume" button-style="solid"> | |||
<a-radio-button value="1">是</a-radio-button> | |||
<a-radio-button value="2">否</a-radio-button> | |||
</a-radio-group> | |||
</a-form-item> | |||
<a-form-item required label="家政版块是否可见" name="createForm.house_keeping_status"> | |||
<a-radio-group v-model:value="createForm.house_keeping_status" button-style="solid"> | |||
<a-radio-button value="1">是</a-radio-button> | |||
<a-radio-button value="2">否</a-radio-button> | |||
</a-radio-group> | |||
</a-form-item> | |||
<a-form-item required label="姓名" name="name"> | |||
<a-input v-model:value="createForm.name" placeholder="请输入姓名" /> | |||
</a-form-item> | |||
<a-form-item required label="身份证" name="id_number"> | |||
<a-input v-model:value="createForm.id_number" placeholder="请输入身份证" /> | |||
</a-form-item> | |||
<a-form-item required label="性别" name="createForm.gender"> | |||
<a-radio-group v-model:value="createForm.gender" button-style="solid"> | |||
<a-radio-button value="男">男</a-radio-button> | |||
<a-radio-button value="女">女</a-radio-button> | |||
</a-radio-group> | |||
</a-form-item> | |||
<a-form-item required label="出生日期" name="dob"> | |||
<a-date-picker v-model:value="createForm.dob" :locale="locale" :format="dateFormat" @panelChange="dobChange"/> | |||
</a-form-item> | |||
<a-form-item required label="工作经验(年)" name="work_experience"> | |||
<a-input v-model:value="createForm.work_experience" placeholder="请输入工作经验" /> | |||
</a-form-item> | |||
<a-form-item label="学历" name="education"> | |||
<a-c-select :dict="2006" :placeholder="educationPlaceholder" @saveSelect="saveEducation"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="户口所在地"> | |||
<a-c-cascader :dict="2009" @saveCascader="regLevelSave" placeholder="请选择户口所在地" ></a-c-cascader> | |||
</a-form-item> | |||
<a-form-item label="现居地"> | |||
<a-c-cascader :dict="2009" @saveCascader="nowLevelSave" placeholder="请选择现居地" ></a-c-cascader> | |||
</a-form-item> | |||
<a-form-item label="职称"> | |||
<a-c-select :dict="2014" :placeholder="titlePlaceholder" @saveSelect="saveTitle"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="婚姻状况"> | |||
<a-c-select :dict="2011" :placeholder="maritalStatusPlaceholder" | |||
@saveSelect="saveMaritalStatus"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="民族"> | |||
<a-c-select :dict="2012" :placeholder="ethnicityPlaceholder" @saveSelect="saveEthnicity"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="身高(厘米cm)"> | |||
<a-input-number :min="0" type="number" v-model:value="createForm.height" placeholder="请输入身高" /> | |||
</a-form-item> | |||
<a-form-item label="体重(千克kg)"> | |||
<a-input-number :min="0" type="number" v-model:value="createForm.weight" placeholder="请输入体重" /> | |||
</a-form-item> | |||
<a-form-item label="政治面貌"> | |||
<a-c-select :dict="2010" :placeholder="politicalStatusPlaceholder" | |||
@saveSelect="savePoliticalStatus"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="籍贯"> | |||
<a-c-cascader :dict="2009" @saveCascader="nativePlaceSave" placeholder="请选择籍贯"></a-c-cascader> | |||
</a-form-item> | |||
<a-form-item :wrapper-col="{ span: 14, offset: 4 }"> | |||
<a-button type="primary" @click="onSubmit">保存</a-button> | |||
<a-button style="margin-left: 10px">重置</a-button> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
import moment, { Moment } from 'moment'; | |||
import 'moment/dist/locale/zh-cn'; | |||
import locale from "ant-design-vue/es/date-picker/locale/zh_CN"; | |||
let createForm = ref({ | |||
hide_resume: 0, | |||
house_keeping_status: 0, | |||
photo: 'aaa.jpg', | |||
name: '', | |||
id_number: '', | |||
gender: "女", | |||
dob: ref<Moment>(), | |||
work_experience: '', | |||
education: 0, | |||
reg_level1: 0, | |||
reg_level2: 0, | |||
reg_level3: 0, | |||
reg_level4: 0, | |||
now_level1: 0, | |||
now_level2: 0, | |||
now_level3: 0, | |||
now_level4: 0, | |||
title: 0, | |||
marital_status: 0, | |||
ethnicity: 0, | |||
height: '', | |||
weight: '', | |||
political_status: 0, | |||
native_place: 0 | |||
}) | |||
const onSubmit = () => { | |||
console.log(createForm.value) | |||
} | |||
const resetForm = () => { | |||
createForm.value = { | |||
hide_resume: 0, | |||
house_keeping_status: 0, | |||
photo: 'aaa.jpg', | |||
name: '', | |||
id_number: '', | |||
gender: "女", | |||
dob: ref<Moment>(), | |||
work_experience: '', | |||
education: 0, | |||
reg_level1: 0, | |||
reg_level2: 0, | |||
reg_level3: 0, | |||
reg_level4: 0, | |||
now_level1: 0, | |||
now_level2: 0, | |||
now_level3: 0, | |||
now_level4: 0, | |||
title: 0, | |||
marital_status: 0, | |||
ethnicity: 0, | |||
height: '', | |||
weight: '', | |||
political_status: 0, | |||
native_place: 0 | |||
} | |||
} | |||
// 出生日期 | |||
const dateFormat = ref('YYYY-MM-DD'); | |||
const dobChange = (val) => { | |||
moment(val, 'YYYY-MM-DD'); | |||
console.log(val) | |||
} | |||
// 学历 | |||
const educationPlaceholder = ref('请选择学历'); | |||
const saveEducation = (data) => { | |||
createForm.value.education = data.val; | |||
} | |||
// 职称 | |||
const titlePlaceholder = ref('请选择职称') | |||
const saveTitle = (data) => { | |||
createForm.value.title = data.val; | |||
} | |||
// 婚姻状态 | |||
const maritalStatusPlaceholder = ref('请选择婚姻状态') | |||
const saveMaritalStatus = (data) => { | |||
createForm.value.marital_status = data.val; | |||
} | |||
// 民族 | |||
const ethnicityPlaceholder = ref('请选择民族') | |||
const saveEthnicity = (data) => { | |||
createForm.value.ethnicity = data.val; | |||
} | |||
// 政治面貌 | |||
const politicalStatusPlaceholder = ref('请选择政治面貌') | |||
const savePoliticalStatus = (data) => { | |||
createForm.value.political_status = data.val; | |||
} | |||
// 户口所在地 | |||
const regLevelSave = (data) => { | |||
for (let i = 0; i < 4; i++) { | |||
createForm.value[`reg_level${i + 1}`] = data.arr1[i] || 0; | |||
} | |||
} | |||
// 户口所在地 | |||
const nowLevelSave = (data) => { | |||
for (let i = 0; i < 4; i++) { | |||
createForm.value[`now_level${i + 1}`] = data.arr1[i] || 0; | |||
} | |||
} | |||
// 户口所在地 | |||
const nativePlaceSave = (data) => { | |||
if (data.arr1.length == 1) { | |||
return false; | |||
} else { | |||
createForm.value.native_place = data.arr1[1]; | |||
} | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,52 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item label="固话" name="landline"> | |||
<a-input v-model:value="createForm.landline" placeholder="请输入固话" /> | |||
</a-form-item> | |||
<a-form-item required label="移动电话" name="mobile"> | |||
<a-input v-model:value="createForm.mobile" placeholder="请输入移动电话" /> | |||
</a-form-item> | |||
<a-form-item label="QQ" name="qq"> | |||
<a-input v-model:value="createForm.qq" placeholder="请输入QQ" /> | |||
</a-form-item> | |||
<a-form-item label="个人网站" name="personal_website"> | |||
<a-input v-model:value="createForm.personal_website" placeholder="请输入个人网站" /> | |||
</a-form-item> | |||
<a-form-item label="通信地址" name="mailing_address"> | |||
<a-input v-model:value="createForm.mailing_address" placeholder="请输入通信地址" /> | |||
</a-form-item> | |||
<a-form-item label="邮编" name="postal_code"> | |||
<a-input v-model:value="createForm.postal_code" placeholder="请输入邮编" /> | |||
</a-form-item> | |||
<a-form-item :wrapper-col="{ span: 14, offset: 4 }"> | |||
<a-button type="primary" @click="onSubmit">保存</a-button> | |||
<a-button style="margin-left: 10px">重置</a-button> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
let createForm = ref({ | |||
landline: '', | |||
mobile: '', | |||
qq: '', | |||
personal_website: '', | |||
mailing_address: '', | |||
postal_code: '', | |||
}) | |||
const resetForm = () => { | |||
createForm.value = { | |||
landline: '', | |||
mobile: '', | |||
qq: '', | |||
personal_website: '', | |||
mailing_address: '', | |||
postal_code: '', | |||
} | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,32 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item label="证书名称" name="name"> | |||
<a-input v-model:value="createForm.name" placeholder="请输入证书名称" /> | |||
</a-form-item> | |||
<a-form-item required label="证书描述" name="description"> | |||
<a-input v-model:value="createForm.description" placeholder="请输入证书描述" /> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
let createForm = ref({ | |||
name: '', | |||
description: '', | |||
certificate_photo: '', | |||
}) | |||
const resetForm = () => { | |||
createForm.value = { | |||
name: '', | |||
description: '', | |||
certificate_photo: '', | |||
} | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,54 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item required label="是否至今" name="是否至今"> | |||
<a-radio-group v-model:value="createForm.end_today" button-style="solid"> | |||
<a-radio-button value="1">非至今</a-radio-button> | |||
<a-radio-button value="2">至今</a-radio-button> | |||
</a-radio-group> | |||
</a-form-item> | |||
<a-form-item label="公司名称" name="company_name"> | |||
<a-input v-model:value="createForm.company_name" placeholder="请输入公司名称" /> | |||
</a-form-item> | |||
<a-form-item required label="职位" name="position"> | |||
<a-input v-model:value="createForm.position" placeholder="请输入职位" /> | |||
</a-form-item> | |||
<a-form-item label="离职原因" name="reason_for_leaving"> | |||
<a-input v-model:value="createForm.reason_for_leaving" placeholder="请输入离职原因" /> | |||
</a-form-item> | |||
<a-form-item :wrapper-col="{ span: 14, offset: 4 }"> | |||
<a-button type="primary" @click="onSubmit">保存</a-button> | |||
<a-button style="margin-left: 10px">重置</a-button> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
let createForm = ref({ | |||
start_year: 0, | |||
start_month: 0, | |||
end_year: 0, | |||
end_month: 0, | |||
end_today: 0, | |||
company_name: '', | |||
position: '', | |||
reason_for_leaving: '' | |||
}) | |||
const resetForm = () => { | |||
createForm.value = { | |||
start_year: 0, | |||
start_month: 0, | |||
end_year: 0, | |||
end_month: 0, | |||
end_today: 0, | |||
company_name: '', | |||
position: '', | |||
reason_for_leaving: '' | |||
} | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,145 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item label="意向地区"> | |||
<a-c-cascader :dict="2009" @saveCascader="areaSave"></a-c-cascader> | |||
</a-form-item> | |||
<a-form-item label="意向职位"> | |||
<a-c-cascader :dict="2004" @saveCascader="positionSave"></a-c-cascader> | |||
</a-form-item> | |||
<a-form-item label="求职类型"> | |||
<a-c-select :dict="2019" placeholder="请选择求职类型" @saveSelect="saveJobType"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="人才类型"> | |||
<a-c-select :dict="2020" placeholder="请选择求职类型" @saveSelect="saveTalentType"></a-c-select> | |||
</a-form-item> | |||
<a-form-item required label="工作经验(年)" name="work_experience"> | |||
<a-input v-model:value="createForm.base.work_experience" placeholder="请输入工作经验" /> | |||
</a-form-item> | |||
<a-form-item required label="其他职位" name="other_positions"> | |||
<a-input v-model:value="createForm.base.other_positions" placeholder="请输入其他职位" /> | |||
</a-form-item> | |||
<a-form-item label="月薪要求范围"> | |||
<a-c-select :dict="2005" placeholder="请选择月薪要求范围" @saveSelect="saveSalaryRange"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="可到职日期"> | |||
<a-c-select :dict="2013" placeholder="请选择可到职日期" @saveSelect="saveAvailableDate"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="职称要求"> | |||
<a-c-select :dict="2014" placeholder="请选择职称要求" @saveSelect="saveTitleRequirement"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="技能认证"> | |||
<a-c-select :dict="2015" placeholder="请选择技能认证" @saveSelect="saveSkillCertification"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="食宿要求"> | |||
<a-c-select :dict="2016" placeholder="请选择食宿要求" @saveSelect="saveAccommodationRequirement"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="节假日休息情况"> | |||
<a-c-select :dict="2017" placeholder="请选择节假日休息情况" @saveSelect="saveHolidayRest"></a-c-select> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
let createForm = ref({ | |||
area: { | |||
level1: 0, | |||
level2: 0, | |||
level3: 0, | |||
level4: 0, | |||
}, | |||
position: { | |||
industry: 0, | |||
}, | |||
base: { | |||
job_type: 0, | |||
talent_type: 0, | |||
work_experience: 0, | |||
other_positions: '', | |||
salary_range: 0, | |||
available_date: 0, | |||
title_requirement: 0, | |||
skill_certification: 0, | |||
accommodation_requirement: 0, | |||
holiday_rest: 0, | |||
} | |||
}) | |||
const resetForm = () => { | |||
createForm.value = { | |||
area: { | |||
level1: 0, | |||
level2: 0, | |||
level3: 0, | |||
level4: 0, | |||
}, | |||
position: { | |||
industry: 0, | |||
}, | |||
base: { | |||
job_type: 0, | |||
talent_type: 0, | |||
work_experience: 0, | |||
other_positions: '', | |||
salary_range: 0, | |||
available_date: 0, | |||
title_requirement: 0, | |||
skill_certification: 0, | |||
accommodation_requirement: 0, | |||
holiday_rest: 0, | |||
} | |||
} | |||
} | |||
// 意向地区 | |||
const areaSave = (data) => { | |||
for (let i = 0; i < 4; i++) { | |||
createForm.value[`now_level${i + 1}`] = data.arr1[i] || 0; | |||
} | |||
} | |||
// 意向求职 | |||
const positionSave = (data) => { | |||
for (let i = 0; i < 4; i++) { | |||
createForm.value[`now_level${i + 1}`] = data.arr1[i] || 0; | |||
} | |||
} | |||
// 求职类型 | |||
const saveJobType = (data) => { | |||
createForm.value.job_type = data.val; | |||
} | |||
// 人才类型 | |||
const saveTalentType = (data) => { | |||
createForm.value.base.talent_type = data.val; | |||
} | |||
// 月薪要求范围 | |||
const saveSalaryRange = (data) => { | |||
createForm.value.base.salary_range = data.val; | |||
} | |||
// 可到职日期 | |||
const saveAvailableDate = (data) => { | |||
createForm.value.base.available_date = data.val; | |||
} | |||
// 职称要求 | |||
const saveTitleRequirement = (data) => { | |||
createForm.value.base.title_requirement = data.val; | |||
} | |||
// 技能认证 | |||
const saveSkillCertification = (data) => { | |||
createForm.value.base.skill_certification = data.val; | |||
} | |||
// 食宿要求 | |||
const saveAccommodationRequirement = (data) => { | |||
createForm.value.base.accommodation_requirement = data.val; | |||
} | |||
// 节假日休息情况 | |||
const saveHolidayRest = (data) => { | |||
createForm.value.base.holiday_rest = data.val; | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,34 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item label="个人简介" name="description"> | |||
<QuillEditor theme="snow" :options="options" toolbar="full"/> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
import { QuillEditor } from '@vueup/vue-quill' | |||
import '@vueup/vue-quill/dist/vue-quill.snow.css'; | |||
const options = ref({ | |||
debug: 'info', | |||
modules: { | |||
}, | |||
placeholder: '请输入个人简介', | |||
theme: 'snow' | |||
}) | |||
let createForm = ref({ | |||
description: '', | |||
}) | |||
const resetForm = () => { | |||
createForm.value = { | |||
description: '', | |||
} | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,68 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item label="英语" name="english"> | |||
<a-c-select :dict="2008" placeholder="请选择掌握程度" @saveSelect="saveEnglish"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="国语" name="mandarin"> | |||
<a-c-select :dict="2008" placeholder="请选择掌握程度" @saveSelect="saveMandarin"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="粤语" name="cantonese"> | |||
<a-c-select :dict="2008" placeholder="请选择掌握程度" @saveSelect="saveCantonese"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="第二外语" name="other_language"> | |||
<a-c-select :dict="2007" placeholder="请选择掌握程度" @saveSelect="saveOtherLanguage"></a-c-select> | |||
</a-form-item> | |||
<a-form-item label="计算机能力" name="computer_skills"> | |||
<a-input v-model:value="createForm.computer_skills" placeholder="请输入计算机能力" /> | |||
</a-form-item> | |||
<a-form-item :wrapper-col="{ span: 14, offset: 4 }"> | |||
<a-button type="primary" @click="onSubmit">保存</a-button> | |||
<a-button style="margin-left: 10px">重置</a-button> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
let createForm = ref({ | |||
english: 0, | |||
mandarin: 0, | |||
cantonese: 0, | |||
other_language: 0, | |||
computer_skills: "" | |||
}) | |||
const resetForm = () => { | |||
createForm.value = { | |||
english: 0, | |||
mandarin: 0, | |||
cantonese: 0, | |||
other_language: 0, | |||
computer_skills: "" | |||
} | |||
} | |||
// 英语 | |||
const saveEnglish = (data) => { | |||
createForm.value.english = data.val; | |||
} | |||
// 国语 | |||
const saveMandarin = (data) => { | |||
createForm.value.mandarin = data.val; | |||
} | |||
// 粤语 | |||
const saveCantonese = (data) => { | |||
createForm.value.cantonese = data.val; | |||
} | |||
// 第二外语 | |||
const saveOtherLanguage = (data) => { | |||
createForm.value.english = data.val; | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,64 @@ | |||
<template> | |||
<a-c-form :createForm="createForm"> | |||
<a-form-item required label="是否至今" name="是否至今"> | |||
<a-radio-group v-model:value="createForm.end_today" button-style="solid"> | |||
<a-radio-button value="1">非至今</a-radio-button> | |||
<a-radio-button value="2">至今</a-radio-button> | |||
</a-radio-group> | |||
</a-form-item> | |||
<a-form-item label="学校/培训机构" name="school_or_institution"> | |||
<a-input v-model:value="createForm.school_or_institution" placeholder="请输入学校/培训机构" /> | |||
</a-form-item> | |||
<a-form-item required label="专业" name="major"> | |||
<a-input v-model:value="createForm.major" placeholder="请输入专业" /> | |||
</a-form-item> | |||
<a-form-item label="获得证书" name="certificate"> | |||
<a-input v-model:value="createForm.certificate" placeholder="请输入获得证书" /> | |||
</a-form-item> | |||
<a-form-item label="曾获学校奖项或技能比赛奖项" name="certificate"> | |||
<a-input v-model:value="createForm.awards" placeholder="请输入曾获学校奖项或技能比赛奖项" /> | |||
</a-form-item> | |||
<a-form-item label="曾任职务" name="awards"> | |||
<a-input v-model:value="createForm.awards" placeholder="请输入曾任职务" /> | |||
</a-form-item> | |||
<a-form-item :wrapper-col="{ span: 14, offset: 4 }"> | |||
<a-button type="primary" @click="onSubmit">保存</a-button> | |||
<a-button style="margin-left: 10px">重置</a-button> | |||
</a-form-item> | |||
</a-c-form> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
let createForm = ref({ | |||
start_year: 0, | |||
start_month: 0, | |||
end_year: 0, | |||
end_month: 0, | |||
end_today: 0, | |||
school_or_institution: '', | |||
major: '', | |||
certificate: '', | |||
awards: '', | |||
positions_held: '', | |||
}) | |||
const resetForm = () => { | |||
createForm.value = { | |||
start_year: 0, | |||
start_month: 0, | |||
end_year: 0, | |||
end_month: 0, | |||
end_today: 0, | |||
school_or_institution: '', | |||
major: '', | |||
certificate: '', | |||
awards: '', | |||
positions_held: '', | |||
} | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,17 @@ | |||
<template> | |||
<a-row :gutter="[16,16]"> | |||
<slot></slot> | |||
<a-col> | |||
<a-button size="mini">搜索</a-button> | |||
</a-col> | |||
<a-col><a-button size="mini">重置</a-button></a-col> | |||
</a-row> | |||
</template> | |||
<script setup lang="ts"> | |||
import { useSearch } from '@/hooks/useSearch'; | |||
</script> | |||
<style lang="less" scoped> | |||
</style> |
@@ -0,0 +1,37 @@ | |||
<template> | |||
<a-select v-model:value="value" @change="handleChange" :placeholder="placeholder" show-search :filter-option="false" | |||
label-in-value @search="handleSearch" :options="listOptions"> | |||
<a-select-option v-for="item in listOptions" :key="item.id" :value="item.id" :label="item.full_name" label-in-value>{{item.full_name}}</a-select-option> | |||
</a-select> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, defineProps, watch, defineEmits, computed } from 'vue'; | |||
const props = defineProps(['list', 'placeholder']); | |||
let placeholder = ref<String>(props.placeholder); | |||
let listOptions = ref<Object[]>(props.list) | |||
watch(() => props.list, (newVal:string, oldVal:string) => { | |||
newVal.map(item => { | |||
listOptions.push({id: item}) | |||
}) | |||
listOptions.value = newVal; | |||
}) | |||
// 搜索 | |||
let lastKeyWord = ref<String>(''); | |||
const emit = defineEmits(); | |||
const handleSearch = (val : string) => { | |||
lastKeyWord.value = val; | |||
emit('searchKey', { keyword: val}); | |||
} | |||
const handleChange = (val : string) => { | |||
console.log(val) | |||
emit('saveSearch', { val: val }); | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,40 @@ | |||
<template> | |||
<a-select v-model:value="selectValue" @change="handleChange" :placeholder="placeholder"> | |||
<a-select-option v-for="item in listOptions" :key="item.id" :value="item.id">{{item.name}}</a-select-option> | |||
</a-select> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, defineProps, watch, defineEmits } from 'vue'; | |||
import { GetDictTree } from '@/apis/models'; | |||
let listOptions = ref([]); | |||
let selectValue = ref(''); | |||
let placeholder = ref('请选择'); | |||
const props = defineProps(['dict', 'placeholder', 'select_content']); | |||
placeholder.value = props.placeholder | |||
watch(() => [props.dict, props.select_content], | |||
(newVal:string, oldVal:string) => { | |||
GetDictTree({ | |||
code: newVal[0] | |||
}).then((res:object) => { | |||
listOptions.value = res.data.dicts | |||
}) | |||
selectValue.value = newVal[1] | |||
}) | |||
onMounted(() => { | |||
GetDictTree({ | |||
code: props.dict | |||
}).then((res:object) => { | |||
listOptions.value = res.data.dicts | |||
}) | |||
}) | |||
const emit = defineEmits(); | |||
const handleChange = (val) => { | |||
emit('saveSelect', { val: val }); | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,38 @@ | |||
<template> | |||
<a-select v-model:value="selectValue" @change="handleChange" :placeholder="placeholder" label-in-value> | |||
<a-select-option v-for="item in listOptions" :key="item.id" :value="item.id" :label="item.name">{{item.name}}</a-select-option> | |||
</a-select> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, defineProps, watch, defineEmits } from 'vue'; | |||
import { GetDictTree } from '@/apis/models'; | |||
const props = defineProps(['dict', 'placeholder', 'select_content']); | |||
let listOptions = ref([]); | |||
let selectValue = ref<Number>(0); | |||
let placeholder = ref<String>(props.placeholder); | |||
watch(() => [props.dict, props.select_content], | |||
(newVal) => { | |||
GetDictTree({ | |||
code: newVal[0] | |||
}).then((res:object) => { | |||
listOptions.value = res.data.dicts | |||
}) | |||
selectValue.value = newVal[1] == 0 ? props.placeholder : newVal[1]; | |||
}, { immediate: true }) | |||
onMounted(() => { | |||
GetDictTree({ | |||
code: props.dict | |||
}).then((res:object) => { | |||
listOptions.value = res.data.dicts | |||
}) | |||
}) | |||
const emit = defineEmits(); | |||
const handleChange = (val) => { | |||
emit('saveSelect', { val: val }); | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,90 @@ | |||
<template> | |||
<a-table :data-source="data" :columns="columns" scrollToFirstRowOnChange :pagination="pagination" | |||
@change="pageChange" bordered class="ant-table-striped" childrenColumnName="childs" rowKey="id" :indentSize="30" | |||
:expanded-row-keys="state.expandRowKeys" | |||
:rowClassName="(record, index) => (index % 2 === 1 ? 'table-striped' : null)" :loading="loading" | |||
:scroll="{ y: 600 }"> | |||
<template #photo_image="{ record }"> | |||
<slot name="photo_image" :record='record'></slot> | |||
</template> | |||
<template #license_image="{ record }"> | |||
<slot name="license_image" :record='record'></slot> | |||
</template> | |||
<template #operation="{ record }"> | |||
<slot :record='record'></slot> | |||
</template> | |||
<template #p_type="{ record }"> | |||
<slot name="p_type" :record='record'></slot> | |||
</template> | |||
<template #parent_id="{ record }"> | |||
<slot name="parent_id" :record='record'></slot> | |||
</template> | |||
<template #permission_name="{ record }"> | |||
<slot name="permission_name" :record='record'></slot> | |||
</template> | |||
<template #expandIcon="{ record }"> | |||
<template v-if="record.childs && record.childs.length === 0"><span | |||
style="margin-right: 24px"></span></template> | |||
<template v-else> | |||
<button :class="[ | |||
'ant-table-row-expand-icon', | |||
!state.isExpand[record.id] | |||
? 'ant-table-row-expand-icon-collapsed' //使用组件库原展开按钮的样式 | |||
: 'ant-table-row-expand-icon-expanded' | |||
]" @click="expandRow(record.id)"> | |||
</button> | |||
</template> | |||
</template> | |||
</a-table> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, defineEmits, defineProps, watch } from 'vue'; | |||
let props = defineProps(['data', 'columns', 'pagination', 'loading']); | |||
const emit = defineEmits(); | |||
let data = ref<Object[]>([]) | |||
let columns = ref<Object[]>([]) | |||
let loading = ref<Boolean>(props.loading); | |||
let pagination = ref<CommonType.PageType>({ | |||
current: 1, | |||
pageSize: 10, | |||
total: 10, | |||
pageSizeOptions: ['10', '20', '30', '40'], | |||
hideOnSinglePage: false, | |||
showSizeChanger: true | |||
}) | |||
watch(() => [props.data, props.columns, props.pagination, props.loading], | |||
(newVal, oldVal) => { | |||
data.value = newVal[0]; | |||
columns.value = newVal[1]; | |||
pagination.value = newVal[2]; | |||
loading.value = newVal[3] | |||
}) | |||
const pageChange = (val) => { | |||
emit("page", val) | |||
} | |||
const state = ref({ | |||
expandRowKeys: [], | |||
isExpand: {} | |||
}) | |||
const expandRow = (id) => { | |||
state.value.isExpand[id] = !state.value.isExpand[id]; | |||
if (!state.value.expandRowKeys.includes(id)) { | |||
state.value.expandRowKeys.push(id); | |||
} else { | |||
const closedIndex = state.value.expandRowKeys.indexOf(id); | |||
state.value.expandRowKeys.splice(closedIndex, 1); | |||
} | |||
}; | |||
</script> | |||
<style scoped> | |||
.ant-table-striped :deep(.table-striped) td { | |||
background-color: #fafafa; | |||
} | |||
</style> |
@@ -0,0 +1,61 @@ | |||
<template> | |||
<a-select v-model:value="selectValue" show-search label-in-value :placeholder="placeholder" style="width: 100%" | |||
:filter-option="false" :not-found-content="fetching ? undefined : null" :options="listOptions" | |||
@search="searchList" @change="searchChange" :disabled="selectDisabled" :mode="mode"> | |||
<template v-if="fetching" #notFoundContent> | |||
<a-spin size="small" /> | |||
</template> | |||
</a-select> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, defineProps, watch, defineEmits } from 'vue'; | |||
import { getCompanyList } from '@/apis/models'; | |||
import { debounce } from 'lodash-es'; | |||
const emit = defineEmits(); | |||
const props = defineProps( | |||
{ | |||
list: Array, | |||
placeholder: String, | |||
select_value: Number, | |||
select_disabled: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
mode: { | |||
type: String, | |||
default: '' | |||
} | |||
}); | |||
let listOptions = ref([]); | |||
let fetching = ref(false); | |||
let placeholder = ref<String>(props.placeholder); | |||
let selectValue = ref<String>(''); | |||
let lastFetchId = 0; | |||
let selectDisabled = ref<Boolean>(false) | |||
let mode = ref<String>(props.mode) | |||
watch(() => [props.list, props.select_value, props.select_disabled], | |||
(newVal, oldVal) => { | |||
listOptions.value = newVal[0] | |||
selectValue.value = newVal[1] == '' ? placeholder.value : newVal[1]; | |||
selectDisabled.value = newVal[2]; | |||
mode.value = newVal[3] | |||
debugger | |||
}, { immediate: true }) | |||
const searchList = debounce(value => { | |||
lastFetchId += 1; | |||
const fetchId = lastFetchId; | |||
listOptions.value = []; | |||
fetching.value = true; | |||
emit('searchData', {keyword: value}); | |||
if (fetchId !== lastFetchId) { | |||
return; | |||
} | |||
fetching.value = false; | |||
}, 300); | |||
const searchChange = (data) => { | |||
emit('getSelectValue', data); | |||
} | |||
</script> |
@@ -0,0 +1,43 @@ | |||
<template> | |||
<a-tree-select v-model:value="treecCascaderParentId" style="width: 100%" | |||
:tree-data="treeData" tree-checkable allow-clear :show-checked-strategy="SHOW_PARENT" | |||
:placeholder="placeholder" tree-node-filter-prop="label" | |||
:fieldNames="listFieldNames" :maxTagCount="3" @change="parentChange" /> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, defineProps, watch, defineEmits } from 'vue'; | |||
import { GetDictTree } from '@/apis/models'; | |||
import { TreeSelect } from 'ant-design-vue'; | |||
const props = defineProps(['dict', 'placeholder', 'tree_content']); | |||
let treeData = ref([]); | |||
let treecCascaderParentId = ref<number[]>([]); | |||
const listFieldNames = ref({ label: 'name', value: 'id', children: 'children' }); | |||
let placeholder = ref('请选择'); | |||
placeholder.value = props.placeholder | |||
const SHOW_PARENT = TreeSelect.SHOW_ALL; | |||
watch(() => [props.dict, props.tree_content], | |||
(newVal, oldVal) => { | |||
GetDictTree({ | |||
code: newVal[0] | |||
}).then(res => { | |||
treeData.value = res.data.dicts | |||
}) | |||
treecCascaderParentId.value = newVal[1] | |||
}, {immediate: true}) | |||
// onMounted(() => { | |||
// GetDictTree({ | |||
// code: props.dict | |||
// }).then(res => { | |||
// treeData.value = res.data.dicts | |||
// }) | |||
// }) | |||
const emit = defineEmits(); | |||
const parentChange = (val) => { | |||
emit('saveTreeNode', {arr1: val}); | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,103 @@ | |||
<template> | |||
<a-row> | |||
<a-col :span="4" style="display: flex;align-items: center;"> | |||
<menu-unfold-outlined v-if="collapsed" class="trigger" @click="onCollapsed" /> | |||
<menu-fold-outlined v-else class="trigger" @click="onCollapsed" /> | |||
<a-input-search v-model:value="routerValue" placeholder="请输入想进入的管理页面" @keyup.enter="onSearch" | |||
@search="onSearch" style="margin-left: 10px;" /> | |||
</a-col> | |||
<a-col :span="20"> | |||
<a-row type="flex" justify="end" :gutter="20"> | |||
<a-col flex="200px"> | |||
<div>{{time}}</div> | |||
</a-col> | |||
<a-col flex="50px"> | |||
<a-avatar src="@/static/images/logo_1.jpg"></a-avatar> | |||
</a-col> | |||
<a-col flex="50px"> | |||
<div>admin</div> | |||
</a-col> | |||
<a-col flex="16px"> | |||
<LogoutOutlined @click="loginOut" /> | |||
</a-col> | |||
</a-row> | |||
</a-col> | |||
</a-row> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, computed } from 'vue'; | |||
import { store } from '@/store'; | |||
import { router } from '@/router'; | |||
import { MenuUnfoldOutlined, MenuFoldOutlined, LogoutOutlined } from '@ant-design/icons-vue'; | |||
import { getTime } from '@/utils/timeHelper'; | |||
import { useComputed } from '@/hooks/useComputed'; | |||
import { useMenu } from '@/hooks/useMenu'; | |||
let { menuList, onMenu, message } = useMenu(); | |||
let routerValue : string = ref(''); | |||
const time : string = ref(''); | |||
const currentTime = () => { | |||
setInterval(() => { | |||
time.value = getTime().nowTime + " " + getTime().nowDate + " " + getTime().nowWeek; | |||
}, 500); | |||
}; | |||
const collapsed = computed(() => { | |||
return store.state.collapsed | |||
}) | |||
const onCollapsed = () => { | |||
store.commit('getCollapsed'); | |||
} | |||
onMounted(() => { | |||
currentTime(); | |||
}); | |||
const loginOut = () => { | |||
sessionStorage.clear(); | |||
window.location.reload(); | |||
router.replace('/login'); | |||
} | |||
const onSearch = (val) => { | |||
const result = menuList.value.some(item => deepCompareAndMarkChecked(item, val)); | |||
if(result.result == 1) { | |||
onMenu(result.path) | |||
} else { | |||
message.warning('无此页面') | |||
} | |||
} | |||
const deepCompareAndMarkChecked = (item : Object, str : String) => { | |||
let data = { | |||
result: 0, | |||
path: '' | |||
}; | |||
if (item.meta.title === str) { | |||
return data = { | |||
result: 1, | |||
path: item.path | |||
}; | |||
} | |||
if (item.children && Array.isArray(item.children)) { | |||
for (const child of item.children) { | |||
const result = deepCompareAndMarkChecked(child, str); | |||
if (result === 1) { | |||
return data = { | |||
result: 1, | |||
path: obj.path | |||
}; | |||
} | |||
} | |||
} | |||
return data = { | |||
result: 0, | |||
path: '' | |||
}; | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,60 @@ | |||
<template> | |||
<a-layout class="layout-box" style="background: #fff; height: 100%;"> | |||
<a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible | |||
style="background: #19be6b; overflow-y: auto;, height: '100vh', left: 0"> | |||
<div class="logo" v-if="collapsed"> | |||
<img src="@/static/images/logo_1.jpg" alt="" style="width: 100%;height: 100%;"> | |||
</div> | |||
<div class="logo" v-else> | |||
<img src="@/static/images/logo.png" alt="" style="width: 100%;height: 100%;" > | |||
</div> | |||
<a-sider></a-sider> | |||
</a-layout-sider> | |||
<a-layout> | |||
<a-layout-header style="background: #fff; padding: 0 16px"> | |||
<a-header></a-header> | |||
</a-layout-header> | |||
<a-layout-content :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }"> | |||
<router-view></router-view> | |||
</a-layout-content> | |||
<a-layout-footer style="text-align: center;padding: 0 0 8px 0;"> | |||
技术支持:中山安域 | |||
</a-layout-footer> | |||
</a-layout> | |||
</a-layout> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, computed } from 'vue'; | |||
import { store } from '@/store'; | |||
import ASider from './sider/aSider.vue'; | |||
import AHeader from './header/aHeader.vue'; | |||
import { MenuUnfoldOutlined, MenuFoldOutlined, } from '@ant-design/icons-vue'; | |||
const collapsed = computed(() => { | |||
return store.state.collapsed | |||
}) | |||
</script> | |||
<style lang="less"> | |||
#components-layout-demo-custom-trigger .trigger { | |||
font-size: 18px; | |||
line-height: 64px; | |||
padding: 0 24px; | |||
cursor: pointer; | |||
transition: color 0.3s; | |||
} | |||
#components-layout-demo-custom-trigger .trigger:hover { | |||
color: #1890ff; | |||
} | |||
.logo { | |||
height: 32px; | |||
margin: 16px; | |||
} | |||
.site-layout .site-layout-background { | |||
background: #fff; | |||
} | |||
</style> |
@@ -0,0 +1,74 @@ | |||
<template> | |||
<a-menu mode="inline" v-model:openKeys="openSubMenu" @openChange="onOpenChange" inlineCollapsed | |||
v-model:selectedKeys="selectedMenu" style="background: #19be6b; height: '90vh';color: #fff;"> | |||
<template v-for="(item,index) in menuList"> | |||
<template v-if="!item.children"> | |||
<a-menu-item :key="item.path" @click="onMenu(item.path)"> | |||
<template #icon> | |||
<component :is="item.meta.icon"></component> | |||
</template> | |||
<span>{{item.meta.title}}</span> | |||
</a-menu-item> | |||
</template> | |||
<template v-else> | |||
<a-sub-menu :key="item.path"> | |||
<template #icon> | |||
<component :is="item.meta.icon"></component> | |||
</template> | |||
<template #title>{{item.meta.title}}</template> | |||
<template v-for="(twoItem, twoIndex) in item.children"> | |||
<a-sub-menu v-if="twoItem.children" :key="twoItem.path"> | |||
<template #title> | |||
{{twoItem.meta.title}} | |||
</template> | |||
<a-menu-item v-for="(threeItem, threeIndex) in twoItem.children" :key="threeItem.path" | |||
@click="onMenu(threeItem.path)">{{ threeItem.meta.title }}</a-menu-item> | |||
</a-sub-menu> | |||
<a-menu-item v-else @click="onMenu(twoItem.path)" :key="twoItem.path"> | |||
{{ twoItem.meta.title }} | |||
</a-menu-item> | |||
</template> | |||
</a-sub-menu> | |||
</template> | |||
</template> | |||
</a-menu> | |||
</template> | |||
<script setup lang="ts"> | |||
import { ref, onMounted, computed } from 'vue'; | |||
import { useMenu } from '@/hooks/useMenu'; | |||
let { menuList, onMenu, routerCur, routerArrayCur } = useMenu(); | |||
const selectedMenu = computed(() => { | |||
let newSelectedMenu = [routerCur()]; | |||
return newSelectedMenu; | |||
}) | |||
const openSubMenu = computed(() => { | |||
let newOpenSubMenu = [routerArrayCur()]; | |||
return newOpenSubMenu; | |||
}) | |||
const onOpenChange = (openKeys) => { | |||
const latestOpenKey : string = openKeys.length > 0 ? openKeys[openKeys.length - 1] : undefined; | |||
if (latestOpenKey) { | |||
openSubMenu.value = latestOpenKey ? [latestOpenKey] : []; | |||
} else { | |||
openSubMenu.value = []; | |||
} | |||
} | |||
</script> | |||
<style lang="less" scoped> | |||
::-webkit-scrollbar { | |||
/* 设置滚动条宽度 */ | |||
width: 0px; | |||
} | |||
.ant-menu { | |||
background-color: #f0f2f5; | |||
/* 修改菜单的背景颜色 */ | |||
} | |||
.ant-menu .ant-sub-menu { | |||
color: #000000; | |||
} | |||
</style> |
@@ -0,0 +1,58 @@ | |||
<template> | |||
<div class="map"> | |||
<iframe id="mapPage" width="100%" height="800" frameborder=0 :src="getSrc"> | |||
</iframe> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
data() { | |||
return {} | |||
}, | |||
computed: { | |||
getSrc() { | |||
var baseUrl = 'https://apis.map.qq.com/tools/locpicker?search=1&type=1&key=' + 'MPBBZ-HUICZ-EGRXB-7AHZI-R4GQZ-QWBSO' + '&referer=' + 'myapp' | |||
if (this.lat && this.lng) { | |||
baseUrl += `&coord=${this.lat},${this.lng}` | |||
} | |||
return baseUrl | |||
} | |||
}, | |||
props: { | |||
mapKey: { | |||
type: String, | |||
default: '' | |||
}, | |||
keyName: { | |||
type: String, | |||
default: '' | |||
}, | |||
lat: { | |||
type: [String, Number] | |||
}, | |||
lng: { | |||
type: [String, Number] | |||
} | |||
}, | |||
mounted() { | |||
var self = this; | |||
window.addEventListener('message', function(event) { | |||
// 对于无法识别的地址,直接返回无法选择 | |||
var loc = event.data; | |||
if (loc && loc.module === 'locationPicker') { // 防止其他应用也会向该页面post信息,需判断module是否为'locationPicker' | |||
self.$emit('getLoc', loc) | |||
} | |||
}, false) | |||
} | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.map { | |||
width: 100%; | |||
height: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,72 @@ | |||
<template> | |||
<a-card title="求职者专业统计"> | |||
<major-search @searchData="searchData" @clearData="clearData" :search_params="commomParams.search"></major-search> | |||
<a-c-table :data="commomParams.table.data" :columns="commomParams.table.columns" :pagination="commomParams.page" | |||
@page="getPage" :loading="loading"> | |||
</a-c-table> | |||
</a-card> | |||
</template> | |||
<script setup lang="ts"> | |||
import { ref, onMounted } from 'vue'; | |||
import MajorSearch from '@/components/statistics/resume/major/search/index.vue'; | |||
import { GetStatsMajor } from '@/apis/models'; | |||
import { useCommon } from '@/hooks/useCommon'; | |||
let { commomParams } = useCommon(); | |||
let loading = ref<Boolean>(true); | |||
onMounted(() => { | |||
getData(commomParams.value.search); | |||
}) | |||
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: 'major', | |||
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 GetStatsMajor(commomParams.value.search); | |||
loading.value = false; | |||
commomParams.value.table.data = res.data.list; | |||
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; | |||
} | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,57 @@ | |||
<template> | |||
<a-range-picker @Change="getRange" /> | |||
</template> | |||
<script lang="ts" setup> | |||
import { ref, onMounted, watch, computed } from 'vue'; | |||
import { useCommon } from '@/hooks/useCommon'; | |||
let { commomParams, dayjs } = useCommon(); | |||
const dayjsRef = ref(dayjs); | |||
let props = defineProps(['search_params']); | |||
const emit = defineEmits(); | |||
interface listType { | |||
start_date: String, | |||
end_date: String | |||
} | |||
commomParams.value.search = commomParams.value.search as listType; | |||
commomParams.value.search.start_date = '2020-01-01'; | |||
commomParams.value.search.end_date = dayjs().format('YYYY-MM-DD'); | |||
commomParams.value.search.sort = 'major'; | |||
watch(() => props.search_params, (newVal) => { | |||
emit('searchData', commomParams.value.search) | |||
}, { | |||
immediate: true | |||
}) | |||
const getRange = (val) => { | |||
commomParams.value.search.start_date = dayjsRef.value(val[0]).format('YYYY-MM-DD'); | |||
commomParams.value.search.end_date = dayjsRef.value(val[1]).format('YYYY-MM-DD'); | |||
emit('searchData', commomParams.value.search); | |||
} | |||
const getData = () => { | |||
emit('searchData', commomParams.value.search); | |||
} | |||
// 清空搜索 | |||
const clearSearch = () => { | |||
commomParams.value.search = { | |||
page: 1, | |||
pagesize: 10, | |||
sort: 'major', | |||
sortby: 'asc', | |||
keyword: '' | |||
} | |||
emit('clearData', commomParams.value.search); | |||
} | |||
const onClose = () => { | |||
clearSearch() | |||
} | |||
</script> | |||
<style> | |||
</style> |
@@ -0,0 +1,157 @@ | |||
<template> | |||
<div style="display: flex;"> | |||
<img v-if="imagesLength == 1 && imageUrl" :src="imageUrl" alt="avatar" width="100px" height="100px" | |||
style="margin-right: 10px;" /> | |||
<template v-else> | |||
<template v-for="(item, index) in imagesList" v-key="index"> | |||
<div style="margin-right: 10px;"> | |||
<a-space direction="vertical"> | |||
<a-image :src="item.url" :width="100" :height="100" /> | |||
<a-button block danger size="small" @click="delImage(index)">删除此张</a-button> | |||
</a-space> | |||
</div> | |||
</template> | |||
</template> | |||
<template v-if="imagesList.length < imagesLength || imagesList.length == 1"> | |||
<a-upload a-upload v-model:file-list="fileList" list-type="picture-card" class="avatar-uploader" | |||
:show-upload-list="false" :before-upload="beforeUpload" :data="uploadData" | |||
:customRequest="uploadCustom"> | |||
<plus-outlined /> | |||
<div class="ant-upload-text">{{uploadTxt}}</div> | |||
</a-upload> | |||
</template> | |||
</div> | |||
</template> | |||
<script setup lang="ts"> | |||
import { ref, onMounted, computed, defineProps, watch, defineEmits } from 'vue'; | |||
import axios from 'axios'; | |||
import { useCommon } from '@/hooks/useCommon'; | |||
let { message, imageprefix } = useCommon(); | |||
const props = defineProps({ | |||
upload_txt: String, | |||
success_image: String, | |||
images_length: Number, | |||
images_list: { | |||
type: Array, | |||
default: [] | |||
}, | |||
image_type: { | |||
type: Number, | |||
default: 1 | |||
} | |||
}); | |||
const emit = defineEmits(); | |||
const headers = ref<Object>({ | |||
Authorization: sessionStorage.getItem('token'), | |||
'X-Requested-With': null | |||
}) | |||
const uploadData = ref<Object>({ | |||
image: '' | |||
}) | |||
const imageType = ref<Number>(props.image_type) | |||
let imagesList = ref<Object[]>([]) | |||
let odImagesList = ref<Object[]>([]) // 暂存 | |||
let fileList = ref<Object[]>([]) | |||
let imageUrl = ref<String>(props.success_image) // 图片路径 | |||
let uploadTxt = ref<String>(props.upload_txt) | |||
let imagesLength = ref<Number>(props.images_length) | |||
watch(() => [props.success_image, props.image_type, props.images_list], (newVal, oldVal) => { | |||
imageUrl.value = newVal[0]; | |||
imageType.value = newVal[1]; | |||
odImagesList.value = [] | |||
imagesList.value = [] | |||
if (newVal[2]) { | |||
newVal[2].map(item => { | |||
odImagesList.value.push({ photo: item }) | |||
}) | |||
} | |||
if (newVal[2]) { | |||
newVal[2].map(item => { | |||
imagesList.value.push({ url: imageprefix + item }) | |||
}) | |||
} | |||
}, { | |||
immediate: true | |||
}) | |||
const beforeUpload = (file) => { | |||
uploadData.value.image = file | |||
} | |||
const uploadCustom = (e) => { | |||
let formdata = new FormData() | |||
formdata.append('image', e.file) | |||
axios({ | |||
url: 'https://rcsc-test.jcjob.cn/api/common/image/upload?imgtype=' + imageType.value, | |||
method: 'post', | |||
data: formdata, | |||
headers: headers.value | |||
}).then((res) => { | |||
if (imagesLength.value === 1) { | |||
imagesList.value = [{ | |||
uid: '-1', // 文件唯一标识,建议设置为负数,防止和内部产生的 id 冲突 | |||
name: e.file.name, // 文件名 | |||
status: 'done', // 状态有:uploading done error removed | |||
url: "https://rcsc-test.jcjob.cn/img" + res.data.data.filename | |||
}] | |||
} else { | |||
if (imagesList.value.length < imagesLength.value) { | |||
console.log(imagesList.value) | |||
imagesList.value.push({ | |||
uid: '-' + (imagesList.value.length + 1), // 文件唯一标识,建议设置为负数,防止和内部产生的 id 冲突 | |||
name: e.file.name, // 文件名 | |||
status: 'done', // 状态有:uploading done error removed | |||
url: "https://rcsc-test.jcjob.cn/img" + res.data.data.filename | |||
}) | |||
} else { | |||
message.danger('最多上传5张'); | |||
} | |||
} | |||
console.log(res.data.data.filename) | |||
message.success(`${props.upload_txt}成功`); | |||
emit('uploadSuccess', res.data.data.filename) | |||
}) | |||
} | |||
// 删除照片 | |||
const delImage = (index) => { | |||
imagesList.value.splice(index, 1) | |||
odImagesList.value.splice(index, 1) | |||
console.log(odImagesList.value) | |||
emit('delImageAfter', odImagesList.value) | |||
} | |||
// const uploadChange = ({ file, fileList }) => { | |||
// console.log(fileList) | |||
// if (file.file.response) { | |||
// message.success(`${props.upload_txt}成功`); | |||
// emit('uploadSuccess', file.file.response) | |||
// } | |||
// } | |||
</script> | |||
<style scoped lang="less"> | |||
.avatar-uploader>.ant-upload { | |||
width: 128px; | |||
height: 128px; | |||
} | |||
.ant-upload-select-picture-card i { | |||
font-size: 32px; | |||
color: #999; | |||
} | |||
.ant-upload-select-picture-card .ant-upload-text { | |||
margin-top: 8px; | |||
color: #666; | |||
} | |||
.ant-upload-select-picture-card .ant-upload-list-item { | |||
width: 128px; | |||
height: 128px; | |||
margin-right: 8px; | |||
} | |||
</style> |
@@ -0,0 +1,35 @@ | |||
declare namespace CommonType { | |||
type PageType = { | |||
current ?: Number; | |||
pageSize ?: Number; | |||
total ?: Number; | |||
pageSizeOptions ?: String[]; | |||
hideOnSinglePage ?: Boolean; | |||
showSizeChanger ?: Boolean; | |||
} | |||
type ModelType = { | |||
title ?: String; | |||
okText : String | '提交'; | |||
resetText : String | '重置'; | |||
cancelText : String | '取消'; | |||
} | |||
type SearchType = { | |||
page ?: Number, | |||
pagesize ?: Number, | |||
sort ?: String, | |||
sortby ?: String, | |||
keyword ?: String | |||
} | |||
type TableType = { | |||
data : Object[], | |||
columns : Object[], | |||
} | |||
type DeleteType = { | |||
id ?: Number | |||
} | |||
} | |||
@@ -0,0 +1,44 @@ | |||
import { ref } from 'vue'; | |||
import { router } from '@/router'; | |||
export const useAsRouter = () => { | |||
// 获取当前路由 | |||
function routerCur() { | |||
return router.currentRoute.value.path | |||
} | |||
// 获取当前路由父路由 | |||
function routerArrayCur() { | |||
return router.currentRoute.value.matched[1].path; | |||
} | |||
// 跳转路由 | |||
function routerTo(url : string) { | |||
router.push(url) | |||
} | |||
// 匹配路由页面 | |||
function routerDynamic(userRouter : string[], originRouter : Object[]) { | |||
const finalRouter = originRouter.filter(item => userRouter.includes(item.name)).map(item => ({ ...item, children: item.children ? routerDynamic(userRouter, item.children) : null })); | |||
return finalRouter; | |||
} | |||
// 添加路由 | |||
function routerAdd(route) { | |||
router.addRoute('', route); | |||
} | |||
// 初始化路由 | |||
function routerInit() { | |||
return router.options.routes + router.options.routes.LayoutRoute; | |||
} | |||
return { | |||
routerCur, | |||
routerArrayCur, | |||
routerTo, | |||
routerDynamic, | |||
routerAdd, | |||
routerInit | |||
} | |||
} |
@@ -0,0 +1,149 @@ | |||
import { ref } from 'vue'; | |||
import { store } from '@/store'; | |||
import { useAsRouter } from './useAsRouter' | |||
import dayjs, { Dayjs } from 'dayjs'; | |||
import 'dayjs/locale/zh-cn'; | |||
dayjs.locale('zh-cn'); | |||
import { message } from 'ant-design-vue'; | |||
interface CommonInterface { | |||
model ?: CommonType.ModelType, | |||
page ?: CommonType.PageType | |||
search ?: CommonType.SearchType | |||
table ?: CommonType.TableType | |||
delParam ?: CommonType.DeleteType, | |||
} | |||
export const useCommon = () => { | |||
const { routerTo, routerCur, routerArrayCur } = useAsRouter(); | |||
let commomParams = ref<CommonInterface>({ | |||
model: { | |||
title: '', | |||
okText: '提交', | |||
resetText: '重置', | |||
cancelText: '取消', | |||
}, | |||
page: { | |||
current: 1, | |||
pageSize: 1, | |||
total: 10, | |||
pageSizeOptions: ['10', '20', '30', '40'], | |||
hideOnSinglePage: false, | |||
showSizeChanger: true | |||
}, | |||
search: { | |||
page: 1, | |||
pagesize: 10, | |||
sort: 'id', | |||
sortby: 'desc', | |||
keyword: '' | |||
}, | |||
table: { | |||
data: [], | |||
columns: [], | |||
}, | |||
delParam: { | |||
id: 0 | |||
}, | |||
// // MENU | |||
// openSubMenu: [], | |||
// menuList: [], | |||
}) | |||
let openAddModel = ref<Boolean>(store.state.openAddModel); | |||
let openOtherModel_1 = ref<Boolean>(store.state.openOtherModel_1); | |||
let openSearchModel = ref<Boolean>(store.state.openSearchModel); // 搜索 | |||
// 点击菜单获取路由 | |||
const onMenu = (path) => { | |||
routerTo(path); | |||
}; | |||
// Modal | |||
const hideModal = () => { | |||
store.commit('getOpenModel', { | |||
openAddModel: false | |||
}) | |||
} | |||
// 打开添加/编辑对话框 | |||
const showModal = () => { | |||
store.commit('getOpenModel', { | |||
openAddModel: true | |||
}) | |||
}; | |||
const showOtherModal1 = () => { | |||
store.commit('getOpenMoreModel', { | |||
openOtherModel_1: true | |||
}) | |||
}; | |||
const hideOtherModal1 = () => { | |||
store.commit('getOpenMoreModel', { | |||
openOtherModel_1: false | |||
}) | |||
} | |||
// 打开搜索 | |||
const showSearch = () => { | |||
store.commit('getSearchModel', { | |||
openSearchModel: true | |||
}) | |||
}; | |||
const hideSearch = () => { | |||
store.commit('getSearchModel', { | |||
openSearchModel: false | |||
}) | |||
} | |||
// 富文本全局 | |||
let richOption = ref<Object>({ | |||
debug: 'info', | |||
modules: { | |||
}, | |||
placeholder: '请输入文字' | |||
}); | |||
// 禁止使用日期 | |||
const disabledDate = (val: Dayjs) => { | |||
return val && val > dayjs().endOf('day'); | |||
}; | |||
// 照片前缀 | |||
const imageprefix : string = 'https://rcsc-test.jcjob.cn/img/' | |||
return { | |||
store, | |||
commomParams, | |||
openAddModel, | |||
onMenu, | |||
hideModal, | |||
showModal, | |||
openOtherModel_1, | |||
showOtherModal1, | |||
hideOtherModal1, | |||
dayjs, | |||
richOption, | |||
message, | |||
disabledDate, | |||
imageprefix, | |||
openSearchModel, | |||
showSearch, | |||
hideSearch | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
import { ref } from 'vue'; | |||
import { useAsRouter } from './useAsRouter' | |||
import { store } from '@/store' | |||
import { message } from 'ant-design-vue'; | |||
export const useMenu = () => { | |||
const { routerTo, routerCur, routerArrayCur } = useAsRouter(); | |||
const openSubMenu = ref<string[]>([]); | |||
const menuList = ref<object[]>(store.state.permissions.menuList); | |||
// 点击菜单获取路由 | |||
const onMenu = (path) => { | |||
routerTo(path); | |||
}; | |||
return { | |||
routerCur, | |||
routerArrayCur, | |||
openSubMenu, | |||
menuList, | |||
onMenu, | |||
message | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
import { createApp } from 'vue'; | |||
import './style.css'; | |||
import App from './App.vue'; | |||
import { router } from './router' | |||
import { store } from './store'; | |||
import Antd from 'ant-design-vue'; | |||
import 'ant-design-vue/dist/reset.css'; | |||
import { QuillEditor } from '@vueup/vue-quill' | |||
import '@vueup/vue-quill/dist/vue-quill.snow.css'; | |||
import ACOperation from '@/components/cOperation/cOperation.vue'; | |||
import ACTable from '@/components/cTable/cTable.vue'; | |||
import ACCascader from '@/components/cCascader/cascader.vue'; | |||
import AShujilian from '@/components/form/shujilian.vue'; | |||
import SearchSelect from '@/components/form/search-select.vue'; | |||
import AXuanze from '@/components/cSelect/xuanze.vue'; | |||
import ACSelect from '@/components/cSelect/select.vue'; | |||
import ACSelectCommon from '@/components/cSelect/common.vue'; | |||
import UploadOne from '@/components/upload/one.vue'; | |||
import { Model } from 'node_modules/echarts/index'; | |||
router.beforeEach((to, from, next) => { | |||
document.title = `${to.meta.title} - 菊城人才市场后台管理`; | |||
if (!sessionStorage.getItem('token')) { | |||
if (to.matched.length > 0 && !to.matched.some(record => record.meta.requiresAuth)) { | |||
next() | |||
} else { | |||
next({ | |||
path: '/login' | |||
}) | |||
} | |||
} else { | |||
if (store.state.permissions.permissionList == null) { | |||
store.dispatch('permissions/FETCH_PERMISSION').then(() => { | |||
next({ | |||
path: to.path | |||
}) | |||
}) | |||
} else { | |||
if (to.path !== '/login') { | |||
next() | |||
} else { | |||
next(from.fullPath) | |||
} | |||
} | |||
} | |||
}) | |||
const app = createApp(App); | |||
app.component('a-c-operation', ACOperation); | |||
app.component('a-c-table', ACTable); | |||
app.component('a-c-cascader', ACCascader); | |||
app.component('a-c-select', ACSelect); | |||
app.component('a-xuanze', AXuanze); | |||
app.component('a-shujilian', AShujilian); | |||
app.component('search-select', SearchSelect); | |||
app.component('a-c-select-common', ACSelectCommon); | |||
app.component('QuillEditor', QuillEditor) | |||
app.component('upload-one', UploadOne) | |||
app.use(router); | |||
app.use(store); | |||
app.use(Antd); | |||
app.mount('#app'); |
@@ -0,0 +1,326 @@ | |||
import type { AppRouteRecordRaw, AppRouteModule } from '@/router/types'; | |||
import { HomeOutlined } from '@ant-design/icons-vue'; | |||
import { routerList } from './routerList'; | |||
// 权限管理 | |||
const PermissionRoute : AppRouteRecordRaw = { | |||
path: '/permission', | |||
name: 'permission', | |||
component: routerList.Permission, | |||
meta: { | |||
title: '权限管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
{ | |||
path: '/role', | |||
name: 'role', | |||
component: routerList.ROLE, | |||
meta: { | |||
title: '角色管理', | |||
icon: HomeOutlined | |||
} | |||
}, | |||
{ | |||
path: '/account', | |||
name: 'account', | |||
component: routerList.Account, | |||
meta: { | |||
title: '账号管理', | |||
icon: HomeOutlined | |||
} | |||
}, | |||
{ | |||
path: '/permission/list', | |||
name: 'list', | |||
component: routerList.List, | |||
meta: { | |||
title: '权限管理', | |||
icon: HomeOutlined | |||
} | |||
} | |||
] | |||
}; | |||
// 企业相关 | |||
const CompanyRoute : AppRouteRecordRaw = { | |||
path: '/company', | |||
name: 'company', | |||
component: routerList.Company, | |||
meta: { | |||
title: '企业管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [{ | |||
path: '/member', | |||
name: 'member', | |||
component: routerList.Member, | |||
meta: { | |||
title: '企业列表', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/vip', | |||
name: 'vip', | |||
component: routerList.Vip, | |||
meta: { | |||
title: 'VIP管理', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/department', | |||
name: 'department', | |||
component: routerList.Department, | |||
meta: { | |||
title: '部门管理', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/job', | |||
name: 'job', | |||
component: routerList.Job, | |||
meta: { | |||
title: '职位管理', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
] | |||
}; | |||
// 家政 | |||
const HomemakeRoute : AppRouteRecordRaw = { | |||
path: '/homemake', | |||
name: 'homemake', | |||
component: routerList.Homemake, | |||
meta: { | |||
title: '家政管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [{ | |||
path: '/homemake/type', | |||
name: 'homemakeType', | |||
component: routerList.HomemakeType, | |||
meta: { | |||
title: '家政类型', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/homemake/position', | |||
name: 'homemakePosition', | |||
component: routerList.HomemakePosition, | |||
meta: { | |||
title: '职位申请', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/homemake/demand', | |||
name: 'homemakeDemand', | |||
component: routerList.HomemakeDemand, | |||
meta: { | |||
title: '家政需求', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/homemake/appointment', | |||
name: 'homemakeAppointment', | |||
component: routerList.HomemakeAppointment, | |||
meta: { | |||
title: '家政预定', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
] | |||
}; | |||
// 求职者管理 | |||
const JokSeekerRoute : AppRouteRecordRaw = { | |||
path: '/job-seeker', | |||
name: 'jobSeeker', | |||
component: routerList.JobSeeker, | |||
meta: { | |||
title: '求职者管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
{ | |||
path: '/resume', | |||
name: 'jobResume', | |||
component: routerList.JobResume, | |||
meta: { | |||
title: '简历列表', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
] | |||
}; | |||
// 招聘会管理 | |||
const JokFairRoute : AppRouteRecordRaw = { | |||
path: '/job-fair', | |||
name: 'jobFair', | |||
component: routerList.JokFair, | |||
meta: { | |||
title: '招聘会管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
{ | |||
path: '/job/fair/list', | |||
name: 'jobFairList', | |||
component: routerList.JobFairList, | |||
meta: { | |||
title: '招聘会列表', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
// { | |||
// path: '/job/fair/company', | |||
// name: 'jobFairCompany', | |||
// component: routerList.JobFairCompany, | |||
// meta: { | |||
// title: '参与企业', | |||
// icon: HomeOutlined | |||
// }, | |||
// }, | |||
] | |||
}; | |||
// 资讯管理 | |||
const InformationRoute : AppRouteRecordRaw = { | |||
path: '/information', | |||
name: 'information', | |||
component: routerList.Information, | |||
meta: { | |||
title: '资讯管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
{ | |||
path: '/section', | |||
name: 'section', | |||
component: routerList.InformationSection, | |||
meta: { | |||
title: '栏目/频道', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/article', | |||
name: 'article', | |||
component: routerList.InformationArticle, | |||
meta: { | |||
title: '文章列表', | |||
icon: HomeOutlined | |||
}, | |||
} | |||
], | |||
}; | |||
// 广告管理 | |||
const AdvertisementRoute : AppRouteRecordRaw = { | |||
path: '/advertisement', | |||
name: 'advertisement', | |||
component: routerList.Advertisement, | |||
meta: { | |||
title: '广告/活动管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
{ | |||
path: '/advertisement/list', | |||
name: 'advertisementList', | |||
component: routerList.AdvertisementList, | |||
meta: { | |||
title: '广告/活动列表', | |||
icon: HomeOutlined | |||
}, | |||
}, | |||
{ | |||
path: '/put/in', | |||
name: 'putIn', | |||
component: routerList.AdvertisementPutin, | |||
meta: { | |||
title: '广告/活动投放', | |||
icon: HomeOutlined | |||
}, | |||
} | |||
], | |||
}; | |||
// 活动管理 | |||
const ActivityRoute : AppRouteRecordRaw = { | |||
path: '/activity', | |||
name: 'activity', | |||
component: routerList.Activity, | |||
meta: { | |||
title: '活动管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
// { | |||
// path: '/activity/list', | |||
// name: 'activityList', | |||
// component: routerList.ActivityList, | |||
// meta: { | |||
// title: '活动列表', | |||
// icon: HomeOutlined | |||
// }, | |||
// }, | |||
{ | |||
path: '/activity/address', | |||
name: 'activityAddress', | |||
component: routerList.ActivityAddress, | |||
meta: { | |||
title: '活动地址', | |||
icon: HomeOutlined | |||
}, | |||
} | |||
], | |||
}; | |||
// 统计 | |||
const StatisticsRoute : AppRouteRecordRaw = { | |||
path: '/statistics', | |||
name: 'statistics', | |||
component: routerList.Statistics, | |||
meta: { | |||
title: '统计管理', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
{ | |||
path: '/statistics/resume', | |||
name: 'statisticsResume', | |||
component: routerList.StatisticsResume, | |||
meta: { | |||
title: '简历统计', | |||
icon: HomeOutlined | |||
}, | |||
children: [ | |||
{ | |||
path: '/statistics/resume/major', | |||
name: 'statisticsResumeMajor', | |||
component: routerList.StatisticsResumeMajor, | |||
meta: { | |||
title: '职称与技能', | |||
icon: HomeOutlined | |||
}, | |||
} | |||
], | |||
} | |||
], | |||
}; | |||
export const routesModuleList : AppRouteModule[] = [CompanyRoute,HomemakeRoute, JokSeekerRoute, JokFairRoute, InformationRoute, AdvertisementRoute, ActivityRoute, StatisticsRoute,PermissionRoute]; |
@@ -0,0 +1,8 @@ | |||
import { createRouter, createWebHistory } from 'vue-router'; | |||
import { basicRoutes } from './routes'; | |||
export const router = createRouter({ | |||
history: createWebHistory(), | |||
routes: basicRoutes | |||
}) |
@@ -0,0 +1,80 @@ | |||
import Permission from '@/views/permission/index.vue'; | |||
import ROLE from '@/views/permission/role/index.vue'; | |||
import Account from '@/views/permission/account/index.vue'; | |||
import List from '@/views/permission/list/index.vue'; | |||
// 企业管理 | |||
import Company from '@/views/company/index.vue'; | |||
import Department from '@/views/company/department/index.vue'; | |||
import Job from '@/views/company/position/index.vue'; | |||
import Member from '@/views/company/list/index.vue'; | |||
import Vip from '@/views/company/vip/index.vue'; | |||
// 家政 | |||
import Homemake from '@/views/homemake/index.vue'; | |||
import HomemakeType from '@/views/homemake/type/index.vue'; | |||
import HomemakePosition from '@/views/homemake/position/index.vue'; | |||
import HomemakeDemand from '@/views/homemake/demand/index.vue'; | |||
import HomemakeAppointment from '@/views/homemake/appointment/index.vue'; | |||
// 求职者管理 | |||
import JobSeeker from '@/views/jobSeeker/index.vue'; | |||
import JobResume from '@/views/jobSeeker/resume/index.vue'; | |||
// 招聘会管理 | |||
import JobFair from '@/views/jobFair/index.vue'; | |||
import JobFairList from '@/views/jobFair/list/index.vue'; | |||
import JobFairCompany from '@/views/jobFair/company/index.vue'; | |||
// 资讯管理 | |||
import Information from '@/views/information/index.vue'; | |||
import InformationSection from '@/views/information/section/index.vue'; | |||
import InformationArticle from '@/views/information/article/index.vue'; | |||
// 广告管理 | |||
import Advertisement from '@/views/advertisement/index.vue'; | |||
import AdvertisementList from '@/views/advertisement/list/index.vue'; | |||
import AdvertisementPutin from '@/views/advertisement/putin/index.vue'; | |||
// 活动管理 | |||
import Activity from '@/views/activity/index.vue'; | |||
import ActivityList from '@/views/activity/list/index.vue'; | |||
import ActivityAddress from '@/views/activity/address/index.vue'; | |||
// 统计 | |||
import Statistics from '@/views/statistics/index.vue'; | |||
import StatisticsResume from '@/views/statistics/resume/index.vue'; | |||
import StatisticsResumeMajor from '@/views/statistics/resume/major/index.vue'; | |||
export const routerList = { | |||
Permission, | |||
ROLE, | |||
Account, | |||
List, | |||
Company, | |||
Department, | |||
Job, | |||
Member, | |||
Vip, | |||
Homemake, | |||
HomemakeType, | |||
HomemakePosition, | |||
HomemakeDemand, | |||
HomemakeAppointment, | |||
JobSeeker, | |||
JobResume, | |||
JobFair, | |||
JobFairList, | |||
JobFairCompany, | |||
Information, | |||
InformationSection, | |||
InformationArticle, | |||
Advertisement, | |||
AdvertisementList, | |||
AdvertisementPutin, | |||
Activity, | |||
ActivityList, | |||
ActivityAddress, | |||
Statistics, | |||
StatisticsResume, | |||
StatisticsResumeMajor | |||
} |
@@ -0,0 +1,37 @@ | |||
import type { AppRouteRecordRaw } from '@/router/types'; | |||
import { HomeOutlined } from '@ant-design/icons-vue'; | |||
import LOGIN from '@/views/login/login.vue'; | |||
import HOME from '@/views/home/home.vue'; | |||
import Layout from '@/components/layout/index.vue'; | |||
// 登录路由 | |||
export const LoginRoute: AppRouteRecordRaw = { | |||
path: '/login', | |||
name: 'login', | |||
component: LOGIN, | |||
meta: { | |||
title: '登录' | |||
} | |||
} | |||
// layout路由 | |||
export const LayoutRoute: AppRouteRecordRaw = { | |||
path: '', | |||
name: 'layout', | |||
component: Layout, | |||
redirect: '/home', | |||
children: [{ | |||
path: '/home', | |||
name: 'home', | |||
component: HOME, | |||
meta: { | |||
title: '首页', | |||
icon: HomeOutlined | |||
} | |||
}] | |||
} | |||
export const basicRoutes = [ | |||
LoginRoute | |||
] |
@@ -0,0 +1,12 @@ | |||
import type { RouteRecordRaw, RouteMeta } from 'vue-router'; | |||
// @ts-ignore | |||
export interface UseRouteRecordRaw extends omit<RouteRecordRaw, 'meta'> { | |||
path ?: string, | |||
name ?: string, | |||
component ?: string, | |||
meta: RouteMeta, | |||
children ?: UseRouteRecordRaw[] | |||
} | |||
export type UseRouteModule = UseRouteRecordRaw; |
@@ -0,0 +1,13 @@ | |||
import { createStore } from 'vuex'; | |||
import { state } from './state'; | |||
import { mutations } from './mutations'; | |||
import { permissionsModule } from './usePermissionStore'; | |||
export const store = createStore({ | |||
state, | |||
mutations, | |||
modules: { | |||
permissions: permissionsModule, | |||
} | |||
}) | |||
@@ -0,0 +1,49 @@ | |||
const getCollapsed = (state : object) => { | |||
state.collapsed = !state.collapsed; | |||
} | |||
const getOpenModel = (state : object, payload : object) => { | |||
state.openAddModel = payload.openAddModel; | |||
} | |||
const getOpenMoreModel = (state : object, payload : object) => { | |||
state.openOtherModel_1 = payload.openOtherModel_1; | |||
} | |||
// 搜索 | |||
const getSearchModel = (state : object, payload : object) => { | |||
state.openSearchModel = payload.openSearchModel; | |||
} | |||
// 查看部门 | |||
const getShowDepartmentModel = (state : object, payload : object) => { | |||
state.showDepartmentModel = payload.showDepartmentModel; | |||
} | |||
// 查看职位 | |||
const getShowPositionModel = (state : object, payload : object) => { | |||
state.showPositionModel = payload.showPositionModel; | |||
} | |||
// 查看公司 | |||
const getShowCompanyModel = (state : object, payload : object) => { | |||
state.showCompanyModel = payload.showCompanyModel; | |||
} | |||
// 加入 | |||
const getShowAddCompanyModel = (state : object, payload : object) => { | |||
state.showAddCompanyModel = payload.showAddCompanyModel; | |||
} | |||
export const mutations = { | |||
getCollapsed, | |||
getOpenModel, | |||
getOpenMoreModel, | |||
getSearchModel, | |||
getShowDepartmentModel, | |||
getShowPositionModel, | |||
getShowCompanyModel, | |||
getShowAddCompanyModel, | |||
} |
@@ -0,0 +1,12 @@ | |||
import { StateType } from './types' | |||
export const state = <StateType>{ | |||
collapsed: false, | |||
openAddModel: false, | |||
openOtherModel_1: false, | |||
showDepartmentModel: false, | |||
showPositionModel: false, | |||
showCompanyModel: false, | |||
showAddCompanyModel: false, | |||
openSearchModel: false // 搜索 | |||
} |
@@ -0,0 +1,10 @@ | |||
export interface StateType { | |||
collapsed: boolean, | |||
openAddModel: boolean, | |||
openOtherModel_1: boolean, | |||
showDepartmentModel: boolean, | |||
showPositionModel: boolean, | |||
showCompanyModel: boolean, | |||
showAddCompanyModel: boolean, | |||
openSearchModel: boolean | |||
} |
@@ -0,0 +1,78 @@ | |||
import { Module } from 'vuex'; | |||
import { useAsRouter } from '@/hooks/useAsRouter'; | |||
import { routesModuleList } from '@/router/dynamic'; | |||
import { LayoutRoute } from '@/router/routes'; | |||
import { GetUserMenulist } from '@/apis/models'; | |||
const { routerDynamic, routerAdd, routerInit } = useAsRouter(); | |||
export interface PermissionState { | |||
arrresult : string[]; | |||
menuList : string[]; | |||
permissionList : string[] | null; | |||
breadcrumbList : string[]; | |||
} | |||
const state : PermissionState = { | |||
arrresult: [], | |||
menuList: [], | |||
permissionList: null, | |||
breadcrumbList: [] | |||
}; | |||
const mutations = { | |||
SET_PERMISSION(state, routes) { | |||
state.permissionList = routes | |||
}, | |||
SET_MENU(state, menu) { | |||
state.menuList = menu | |||
} | |||
}; | |||
const actions = { | |||
async FETCH_PERMISSION({ | |||
state, | |||
commit | |||
}) { | |||
try { | |||
// state.arrresult = []; | |||
// let res = await GetUserMenulist(); | |||
// res.data.menulist.map(item => { | |||
// pushItem(item) | |||
// }) | |||
// let arr = state.arrresult; | |||
// let arr = getArr | |||
let arr = ['permission', 'role', 'account', 'company', 'vip', 'member', 'homemake', 'homemakeType', 'homemakePosition', 'homemakeDemand', 'homemakeAppointment', 'job', 'department', 'jobSeeker', 'jobResume', 'jobFair', 'jobFairList', 'jobFairCompany', 'information', 'section', 'article', 'list', 'putIn', 'advertisementList', 'advertisement', 'activity', 'activityList', 'activityAddress', 'statistics', 'statisticsResume', 'statisticsResumeMajor']; | |||
let routes = routerDynamic(arr, routesModuleList); | |||
LayoutRoute.children.push(...routes); | |||
commit('SET_MENU', LayoutRoute.children); | |||
routerAdd(LayoutRoute); | |||
let initialRoutes = routerInit(); | |||
commit('SET_PERMISSION', [...initialRoutes]); | |||
} catch { | |||
} | |||
} | |||
}; | |||
const pushItem = (item : Object) => { | |||
state.arrresult.push(item.action) | |||
if (item.childs) { | |||
for (const child of item.childs) { | |||
pushItem(child) | |||
} | |||
} | |||
return state.arrresult; | |||
} | |||
export const permissionsModule : Module<PermissionState> = { | |||
namespaced: true, | |||
state, | |||
mutations, | |||
actions | |||
}; |
@@ -0,0 +1,79 @@ | |||
:root { | |||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; | |||
line-height: 1.5; | |||
font-weight: 400; | |||
color-scheme: light dark; | |||
color: rgba(255, 255, 255, 0.87); | |||
background-color: #242424; | |||
font-synthesis: none; | |||
text-rendering: optimizeLegibility; | |||
-webkit-font-smoothing: antialiased; | |||
-moz-osx-font-smoothing: grayscale; | |||
} | |||
a { | |||
font-weight: 500; | |||
color: #646cff; | |||
text-decoration: inherit; | |||
} | |||
a:hover { | |||
color: #535bf2; | |||
} | |||
body { | |||
margin: 0; | |||
display: flex; | |||
place-items: center; | |||
min-width: 320px; | |||
min-height: 100vh; | |||
} | |||
h1 { | |||
font-size: 3.2em; | |||
line-height: 1.1; | |||
} | |||
button { | |||
border-radius: 8px; | |||
border: 1px solid transparent; | |||
padding: 0.6em 1.2em; | |||
font-size: 1em; | |||
font-weight: 500; | |||
font-family: inherit; | |||
background-color: #1a1a1a; | |||
cursor: pointer; | |||
transition: border-color 0.25s; | |||
} | |||
button:hover { | |||
border-color: #646cff; | |||
} | |||
button:focus, | |||
button:focus-visible { | |||
outline: 4px auto -webkit-focus-ring-color; | |||
} | |||
.card { | |||
padding: 2em; | |||
} | |||
#app { | |||
width: 100%; | |||
height: 100%; | |||
overflow: hidden; | |||
overflow: auto; | |||
} | |||
@media (prefers-color-scheme: light) { | |||
:root { | |||
color: #213547; | |||
background-color: #ffffff; | |||
} | |||
a:hover { | |||
color: #747bff; | |||
} | |||
button { | |||
background-color: #f9f9f9; | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
declare namespace ColType { | |||
type type = { | |||
title: String, | |||
dataIndex: String, | |||
slots: Object | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
export const findidx : Function = (arr: any, val: any) => { | |||
return arr.findIndex(item => { | |||
return item.id === val | |||
}) | |||
} | |||
export const intersectionAlike : Function = (objA: any, objB: any) => { | |||
const result = {}; | |||
for (const keyA in objA) { | |||
if (objB.hasOwnProperty(keyA)) { | |||
result[keyA] = objB[keyA]; | |||
} | |||
} | |||
return result; | |||
} | |||
export const hasValue : Function = (obj: any) => { | |||
let result = ''; | |||
result = Object.keys(obj).filter(key => obj[key] !== 0).map(key => `${obj[key]}`).join('') | |||
return result; | |||
} | |||
export const divObj : Function = (obj: any) => { | |||
const result = [] | |||
obj.reduce((acc, curr, index) => { | |||
curr.idx = index; | |||
result.push(curr) | |||
// const key = `node${index}Info`; | |||
// acc[key] = curr; | |||
// return acc; | |||
}, {}); | |||
return result; | |||
} | |||
export const alreadyValue: Function = (obj: any) => { | |||
const result = [] | |||
obj.reduce((acc, curr, index) => { | |||
curr.idx = index; | |||
result.push(curr) | |||
// const key = `node${index}Info`; | |||
// acc[key] = curr; | |||
// return acc; | |||
}, {}); | |||
return result; | |||
} |
@@ -0,0 +1,6 @@ | |||
const ImagePath = '~/static/images/'; | |||
export const ImageUrl: object = { | |||
// 未登录头像 | |||
logo: ImagePath + 'logo.jpg', | |||
} |
@@ -0,0 +1,30 @@ | |||
import { httpGet, httpPost } from '@/apis' | |||
export const getModel : Function = (url : string) => { | |||
return function (params : object) { | |||
return new Promise((resolve, reject) => { | |||
httpGet(url, params, function (response) { | |||
if (response.data.code == 0) { | |||
resolve(response.data) | |||
} else { | |||
reject(response) | |||
} | |||
}) | |||
}) | |||
} | |||
} | |||
export const postModel : Function = (url : string) => { | |||
return function (params : object) { | |||
return new Promise((resolve, reject) => { | |||
httpPost(url, params, function (response) { | |||
if (response.data.code == 0) { | |||
resolve(response.data) | |||
} else { | |||
reject(response) | |||
} | |||
}) | |||
}) | |||
} | |||
} | |||
@@ -0,0 +1,51 @@ | |||
interface TimeType { | |||
nowTime ?: string; | |||
nowDate ?: string; | |||
nowWeek ?: string; | |||
} | |||
const timeParams : TimeType = { | |||
nowTime: '', | |||
nowDate: '', | |||
nowWeek: '' | |||
} | |||
export const getTime = () => { | |||
const yy = new Date().getFullYear(); | |||
const mm = new Date().getMonth() + 1; | |||
const dd = new Date().getDate(); | |||
const week = new Date().getDay(); | |||
const hh = new Date().getHours(); | |||
const mf = | |||
new Date().getMinutes() < 10 ? | |||
"0" + new Date().getMinutes() : | |||
new Date().getMinutes(); | |||
let ss = new Date().getSeconds().toString(); | |||
ss = ss.length < 2 ? ('0' + ss) : ss; | |||
switch (week) { | |||
case 1: | |||
timeParams.nowWeek = "星期一"; | |||
break; | |||
case 2: | |||
timeParams.nowWeek = "星期二"; | |||
break; | |||
case 3: | |||
timeParams.nowWeek = "星期三"; | |||
break; | |||
case 4: | |||
timeParams.nowWeek = "星期四"; | |||
break; | |||
case 5: | |||
timeParams.nowWeek = "星期五"; | |||
break; | |||
case 6: | |||
timeParams.nowWeek = "星期六"; | |||
break; | |||
case 7: | |||
timeParams.nowWeek = "星期日"; | |||
} | |||
timeParams.nowTime = hh + ":" + mf + ":" + ss; | |||
timeParams.nowDate = yy + "/" + mm + "/" + dd; | |||
return timeParams; | |||
} |
@@ -0,0 +1,15 @@ | |||
import { httpGet, httpPost } from '@/apis' | |||
import { message } from 'ant-design-vue'; | |||
export const warnToast : Function = (msg : string) => { | |||
message.warning(msg); | |||
} | |||
export const errorToast : Function = (msg : string) => { | |||
message.error(msg); | |||
} | |||
export const successToast : Function = (msg : string) => { | |||
message.success(msg); | |||
} | |||
@@ -0,0 +1,9 @@ | |||
function isType<T>(type:T) { | |||
return function(obj) { | |||
return Object.prototype.toString.call(obj) === "[object " + type + "]"; | |||
} | |||
} | |||
export let isFunction = (obj) => { | |||
return isType("Function")(obj); | |||
} |
@@ -0,0 +1,43 @@ | |||
declare namespace companyListType { | |||
type addrFormType = { | |||
full_name ?: String, | |||
registration_number ?: String, | |||
establishment_date ?: String, | |||
contact ?: String, | |||
phone ?: String, | |||
mobile ?: String, | |||
email ?: String, | |||
fax ?: String, | |||
website ?: String, | |||
province ?: Number, | |||
city ?: Number, | |||
district ?: Number, | |||
street ?: Number, | |||
address ?: String, | |||
industry ?: Number, | |||
nature ?: Number, | |||
scale ?: Number, | |||
introduction ?: String, | |||
photo ?: String, | |||
photo_status ?: Number, | |||
license_path ?: String, | |||
license_status : '', | |||
login_name ?: String, | |||
login_pwd ?: String, | |||
company_photos ?: Object[] | |||
} | |||
type addOtherFormType = { | |||
chengli_date?: String, | |||
content?: String, | |||
photo_img?: String, | |||
license_img?: String, | |||
company_photo_img?: String, | |||
company_photos ?: String[], | |||
company_address_cascader?: String, | |||
company_industry_cascader?: String, | |||
company_nature_cascader?: String, | |||
company_scale_cascader?: String, | |||
} | |||
} | |||