diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/.npmrc b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/.npmrc new file mode 100644 index 0000000..fdb6938 --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/.npmrc @@ -0,0 +1,4 @@ +# pnpm 配置 +shamefully-hoist=true +strict-peer-dependencies=false +auto-install-peers=true diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/index.html b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/index.html new file mode 100644 index 0000000..dfe92ff --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/index.html @@ -0,0 +1,13 @@ + + + + + + 简历智能体 - HR管理系统 + + + +
+ + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/package.json b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/package.json new file mode 100644 index 0000000..8b1d171 --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/package.json @@ -0,0 +1,26 @@ +{ + "name": "ylhp-hr-frontend", + "version": "0.1.0", + "private": true, + "type": "module", + "packageManager": "pnpm@9.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.4.0", + "vue-router": "^4.2.0", + "pinia": "^2.1.0", + "axios": "^1.6.0", + "element-plus": "^2.5.0", + "@element-plus/icons-vue": "^2.3.0", + "dayjs": "^1.11.0" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.0", + "vite": "^5.0.0", + "sass": "^1.70.0" + } +} diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/App.vue b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/App.vue new file mode 100644 index 0000000..02e6d3e --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/App.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/api/api.js b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/api/api.js new file mode 100644 index 0000000..1eae067 --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/api/api.js @@ -0,0 +1,154 @@ +import axios from 'axios' + +const api = axios.create({ + baseURL: '', + timeout: 30000, + headers: { + 'Content-Type': 'application/json' + } +}) + +// 响应拦截器 - 统一处理 +api.interceptors.response.use( + (response) => { + const data = response.data + if (data.code !== 200) { + return Promise.reject(new Error(data.msg || '请求失败')) + } + return data + }, + (error) => { + return Promise.reject(error) + } +) + +// 招聘者管理 API +export const recruiterApi = { + // 获取平台来源列表 + getSources: () => api.get('/api/recruiters/sources'), + + // 获取招聘者列表 + getList: (params = {}) => api.get('/api/recruiters', { params }), + + // 获取招聘者详情 + getDetail: (id) => api.get(`/api/recruiters/${id}`), + + // 创建招聘者 + create: (data) => api.post('/api/recruiters', data), + + // 自动注册 + register: (data) => api.post('/api/recruiters/register', data), + + // 更新招聘者 + update: (id, data) => api.put(`/api/recruiters/${id}`, data), + + // 删除招聘者 + delete: (id) => api.delete(`/api/recruiters/${id}`), + + // 启用招聘者 + activate: (id) => api.post(`/api/recruiters/${id}/activate`), + + // 停用招聘者 + deactivate: (id) => api.post(`/api/recruiters/${id}/deactivate`), + + // 同步招聘者 + sync: (id) => api.post(`/api/recruiters/${id}/sync`) +} + +// 职位管理 API +export const jobApi = { + // 获取职位列表 + getList: (params = {}) => api.get('/api/jobs', { params }), + + // 筛选职位 + filter: (data) => api.post('/api/jobs/filter', data), + + // 获取职位详情 + getDetail: (id) => api.get(`/api/jobs/${id}`), + + // 创建职位 + create: (data) => api.post('/api/jobs', data), + + // 更新职位 + update: (id, data) => api.put(`/api/jobs/${id}`, data), + + // 删除职位 + delete: (id) => api.delete(`/api/jobs/${id}`), + + // 关联评价方案 + bindSchema: (id, schemaId) => api.post(`/api/jobs/${id}/bind-schema`, { evaluation_schema_id: schemaId }), + + // 获取职位关联的评价方案 + getSchema: (id) => api.get(`/api/jobs/${id}/schema`), + + // 获取评价方案列表 + getSchemaList: (params = {}) => api.get('/api/jobs/schemas/list', { params }) +} + +// 候选人管理 API +export const candidateApi = { + // 获取筛选通过的候选人 + getFiltered: (params = {}) => api.get('/candidates/filtered', { params }), + + // 筛选候选人 + filter: (data) => api.post('/candidates/filter', data), + + // 获取候选人详情 + getDetail: (id) => api.get(`/candidates/${id}`), + + // 标记候选人筛选状态 + markFiltered: (data) => api.post('/candidates/mark-filtered', data), + + // 更新候选人评分 + updateScore: (data) => api.post('/candidates/update-score', data), + + // 根据评分范围查询 + getByScoreRange: (params) => api.get('/candidates/by-score-range', { params }) +} + +// 定时任务管理 API +export const schedulerApi = { + // 获取任务列表 + getJobs: () => api.get('/api/scheduler/jobs'), + + // 获取任务状态列表 + getJobsStatus: () => api.get('/api/scheduler/jobs/status'), + + // 获取单个任务状态 + getJobStatus: (id) => api.get(`/api/scheduler/jobs/${id}/status`), + + // 立即执行任务 + runJob: (id) => api.post(`/api/scheduler/jobs/${id}/run`), + + // 暂停任务 + pauseJob: (id) => api.post(`/api/scheduler/jobs/${id}/pause`), + + // 恢复任务 + resumeJob: (id) => api.post(`/api/scheduler/jobs/${id}/resume`), + + // 更新任务配置 + updateConfig: (id, data) => api.put(`/api/scheduler/jobs/${id}/config`, data), + + // 获取调度器状态 + getStatus: () => api.get('/api/scheduler/status'), + + // 启动调度器 + start: () => api.post('/api/scheduler/start'), + + // 停止调度器 + stop: () => api.post('/api/scheduler/stop') +} + +// 系统 API +export const systemApi = { + // 获取首页信息 + getHome: () => api.get('/'), + + // 健康检查 + health: () => api.get('/health'), + + // 获取API状态 + getStatus: () => api.get('/api/status') +} + +export default api diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/components/Layout.vue b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/components/Layout.vue new file mode 100644 index 0000000..2f8cff7 --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/components/Layout.vue @@ -0,0 +1,160 @@ + + + + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/main.js b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/main.js new file mode 100644 index 0000000..9e3a977 --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/main.js @@ -0,0 +1,22 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import ElementPlus from 'element-plus' +import * as ElementPlusIconsVue from '@element-plus/icons-vue' +import 'element-plus/dist/index.css' +import zhCn from 'element-plus/dist/locale/zh-cn.mjs' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +// 注册所有图标 +for (const [key, component] of Object.entries(ElementPlusIconsVue)) { + app.component(key, component) +} + +app.use(createPinia()) +app.use(router) +app.use(ElementPlus, { locale: zhCn }) + +app.mount('#app') diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/router/index.js b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/router/index.js new file mode 100644 index 0000000..6323a7f --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/router/index.js @@ -0,0 +1,49 @@ +import { createRouter, createWebHistory } from 'vue-router' +import Layout from '@/components/Layout.vue' + +const routes = [ + { + path: '/', + component: Layout, + redirect: '/dashboard', + children: [ + { + path: 'dashboard', + name: 'Dashboard', + component: () => import('@/views/Dashboard.vue'), + meta: { title: '首页', icon: 'HomeFilled' } + }, + { + path: 'recruiters', + name: 'Recruiters', + component: () => import('@/views/Recruiters.vue'), + meta: { title: '招聘者管理', icon: 'UserFilled' } + }, + { + path: 'jobs', + name: 'Jobs', + component: () => import('@/views/Jobs.vue'), + meta: { title: '职位管理', icon: 'Briefcase' } + }, + { + path: 'candidates', + name: 'Candidates', + component: () => import('@/views/Candidates.vue'), + meta: { title: '候选人管理', icon: 'Avatar' } + }, + { + path: 'scheduler', + name: 'Scheduler', + component: () => import('@/views/Scheduler.vue'), + meta: { title: '定时任务', icon: 'Clock' } + } + ] + } +] + +const router = createRouter({ + history: createWebHistory(), + routes +}) + +export default router diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Candidates.vue b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Candidates.vue new file mode 100644 index 0000000..b817bfb --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Candidates.vue @@ -0,0 +1,364 @@ + + + + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Dashboard.vue b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Dashboard.vue new file mode 100644 index 0000000..3b500be --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Dashboard.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Jobs.vue b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Jobs.vue new file mode 100644 index 0000000..23cbfff --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Jobs.vue @@ -0,0 +1,478 @@ + + + + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Recruiters.vue b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Recruiters.vue new file mode 100644 index 0000000..0bb225e --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Recruiters.vue @@ -0,0 +1,415 @@ + + + + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Scheduler.vue b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Scheduler.vue new file mode 100644 index 0000000..a88d5a5 --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/src/views/Scheduler.vue @@ -0,0 +1,357 @@ + + + + + diff --git a/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/vite.config.js b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/vite.config.js new file mode 100644 index 0000000..165f3f3 --- /dev/null +++ b/src/main/web/cn.yinlihupo/ylhp_hr_2_0_fronted/vite.config.js @@ -0,0 +1,25 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import { resolve } from 'path' + +export default defineConfig({ + plugins: [vue()], + resolve: { + alias: { + '@': resolve(__dirname, 'src') + } + }, + server: { + port: 3000, + proxy: { + '/api': { + target: 'http://localhost:8000', + changeOrigin: true + }, + '/candidates': { + target: 'http://localhost:8000', + changeOrigin: true + } + } + } +})