| @@ -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, | |||
| } | |||
| } | |||