diff --git a/components.d.ts b/components.d.ts index 331186e..7ea8728 100644 --- a/components.d.ts +++ b/components.d.ts @@ -11,8 +11,15 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { + AgentChatJobList: typeof import('./src/components/AgentChatJobList.vue')['default'] + AgentMatchJobAdd: typeof import('./src/components/AgentMatchJobAdd.vue')['default'] + AgentSettingsPanel: typeof import('./src/components/AgentSettingsPanel.vue')['default'] + AgentSetupWizard: typeof import('./src/components/AgentSetupWizard.vue')['default'] AiChat: typeof import('./src/components/AiChat.vue')['default'] + AiThinkingIndicator: typeof import('./src/components/tools/AiThinkingIndicator.vue')['default'] ElButton: typeof import('element-plus/es')['ElButton'] + ElCarousel: typeof import('element-plus/es')['ElCarousel'] + ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem'] ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElDialog: typeof import('element-plus/es')['ElDialog'] @@ -20,6 +27,7 @@ declare module 'vue' { ElInput: typeof import('element-plus/es')['ElInput'] ElOption: typeof import('element-plus/es')['ElOption'] ElRadio: typeof import('element-plus/es')['ElRadio'] + ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElSelect: typeof import('element-plus/es')['ElSelect'] ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTooltip: typeof import('element-plus/es')['ElTooltip'] @@ -39,6 +47,7 @@ declare module 'vue' { ProfilePageContent: typeof import('./src/components/ProfilePageContent.vue')['default'] RegionSelector: typeof import('./src/components/tools/RegionSelector.vue')['default'] ResumeAnalysisReportDrawer: typeof import('./src/components/ResumeAnalysisReportDrawer.vue')['default'] + ResumeEditNameDialog: typeof import('./src/components/ResumeEditNameDialog.vue')['default'] ResumeIssueFixDrawer: typeof import('./src/components/ResumeIssueFixDrawer.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] diff --git a/src/api/agent.ts b/src/api/agent.ts new file mode 100644 index 0000000..a1e6140 --- /dev/null +++ b/src/api/agent.ts @@ -0,0 +1,280 @@ +import request from '@/utils/request' +import type { ApiResult } from '@/api/auth' + +// ==================== 求职助手配置相关 ==================== + +/** 语言能力项 */ +export interface LanguageAbility { + /** 语种,如英语、日语、法语等 */ + language?: string + /** 掌握程度,可选值:入门/日常会话/商务会话/无障碍沟通/母语 */ + proficiency?: string +} + +/** 求职助手配置数据(查询返回 + 保存请求共用) */ +export interface AgentConfig { + /** 工作类型 1=实习 2=全职 */ + jobType?: number + /** Agent模式 1=协作模式 2=托管模式 */ + agentMode?: number + /** 每周投递目标数量 1=少于20个 2=20到50个 3=多于50个 */ + weeklyTarget?: number + /** 投递时自动针对岗位优化简历 0=关闭 1=开启 */ + autoOptimizeResume?: number + /** 是否愿意接受部门调剂 */ + acceptDeptTransfer?: string + /** 是否接受地点调剂 */ + acceptLocationTransfer?: string + /** 可参加的面试方式 */ + interviewType?: string[] + /** 语言能力 */ + languages?: LanguageAbility[] + /** 预计到岗时间 */ + availableDate?: string + /** 每周可实习天数 */ + internDaysPerWeek?: string + /** 预计实习时长 */ + internDuration?: string + /** 状态 0=未启用 1=已启用(仅查询返回) */ + status?: number +} + +/** + * 查询求职助手配置 + * GET /job-agent/config + */ +export function fetchAgentConfig() { + return request.get>('/job-agent/config') +} + +/** + * 保存求职助手配置 + * POST /job-agent/config/save + */ +export function saveAgentConfig(data: AgentConfig) { + return request.post('/job-agent/config/save', data) +} + +// ==================== 求职助手岗位推荐 ==================== + +/** 匹配度详情 */ +export interface AgentJobMatchDetail { + /** 学历匹配分 */ + educationScore: number + /** 技能匹配分 */ + skillScore: number + /** 经验匹配分 */ + experienceScore: number +} + +/** 推荐岗位项 */ +export interface AgentRecommendJob { + /** 岗位 ID */ + id: number + /** 岗位名称 */ + title: string + /** 薪资描述 */ + salary: string + /** 公司名称 */ + companyName: string + /** 公司简称 */ + companyShortName: string + /** 公司类型 */ + companyType: string + /** 公司 Logo */ + companyLogoUrl: string + /** 地区名称 */ + regionName: string + /** 岗位类型名称 */ + categoryName: string + /** 岗位标签 */ + tags: string[] + /** 来源链接 */ + sourceUrl: string + /** 是否收藏 */ + isFavorite: boolean + /** 投递状态(null=未投递,-1=待投递,0=已投递 1=面试中 2=有Offer 3=未通过 4=已结束) */ + applicationStatus: number | null + /** 岗位状态(0=有效 1=已下架 2=已过期) */ + status: number + /** 匹配总分(0-90) */ + matchScore: number + /** 匹配度详情 */ + matchDetail: AgentJobMatchDetail +} + +/** 求职助手岗位推荐返回数据 */ +export interface AgentRecommendResult { + /** 推荐说明(20字以内) */ + summary: string + /** 推荐的岗位列表(8-10个) */ + list: AgentRecommendJob[] +} + +/** 求职助手岗位推荐请求参数 */ +export interface AgentRecommendParams { + /** 用户偏好描述 */ + preference?: string + /** 排除已推荐过的岗位 ID 列表(字符串避免大整数精度丢失) */ + excludeJobIds?: (number | string)[] +} + +/** + * 求职助手岗位推荐 + * POST /job/agent/recommend + */ +export function fetchAgentRecommend(params: AgentRecommendParams = {}) { + return request.post>('/job/agent/recommend', params) +} + +// ==================== 岗位投递状态变更 ==================== + +/** 岗位投递请求参数 */ +export interface JobApplyParams { + /** 岗位 ID */ + jobId: number + /** 投递状态:-1=待投递 0=已投递 1=面试中 2=有Offer 3=未通过 4=已结束,null=取消 */ + status: number | null +} + +/** + * 变更岗位投递状态(添加到待投递等) + * POST /job/apply + */ +export function applyJob(params: JobApplyParams) { + return request.post('/job/apply', params) +} + +/** + * 取消投递 / 从待投递移除 + * DELETE /job/apply?jobId=xxx + * @param jobId 岗位 ID + */ +export function cancelApplyJob(jobId: number) { + return request.delete('/job/apply', { + params: { jobId }, + }) +} + +// ==================== Agent 对话消息 ==================== + +/** 消息创建时间 */ +export interface InstantTime { + /** 距 1970-01-01T00:00:00Z 的秒数 */ + seconds: number + /** 纳秒偏移(0 ~ 999,999,999) */ + nanos: number +} + +/** Agent 对话消息项 */ +export interface AgentChatMessage { + /** 消息 ID */ + id: number + /** 消息类型:user / assistant / recommend / apply_progress */ + type: string + /** 文本内容 */ + content: string + /** 附加数据 JSON(如推荐岗位列表等) */ + extra: string + /** 创建时间 */ + createTime: InstantTime +} + +/** + * 查询当前 Agent 对话消息列表 + * GET /job-agent/chat/messages?limit=xxx + * @param limit 查询条数 + */ +export function fetchAgentChatMessages(limit: number = 50) { + return request.get>('/job-agent/chat/messages', { + params: { limit }, + }) +} + +/** 添加对话消息请求参数 */ +export interface AddChatMessageParams { + /** 消息类型:user / assistant / recommend / apply_progress */ + type: string + /** 文本内容 */ + content?: string + /** 附加数据 JSON */ + extra?: string +} + +/** + * 添加 Agent 对话消息 + * POST /job-agent/chat/message + */ +export function addAgentChatMessage(params: AddChatMessageParams) { + return request.post('/job-agent/chat/message', params) +} + +// ==================== 批量查询岗位投递记录 ==================== + +/** 岗位投递记录项 */ +export interface JobApplyRecord { + /** 岗位 ID */ + jobId: number + /** 投递状态:-1=待投递 0=已投递 1=面试中 2=有Offer 3=未通过 4=已结束 */ + status: number + /** 投递时间 */ + applyTime: InstantTime + /** 创建时间 */ + createTime: InstantTime +} + +/** + * 根据岗位 ID 批量查询投递记录 + * POST /job/apply/listByJobIds + * @param jobIds 岗位 ID 列表 + */ +export function fetchApplyByJobIds(jobIds: number[]) { + return request.post>('/job/apply/listByJobIds', jobIds) +} + +// ==================== Agent AI 对话(Python 后端) ==================== + +import aiService from '@/utils/aiRequest' +import type { AiResult } from '@/utils/aiRequest' + +/** AI 对话历史消息项 */ +export interface AgentChatHistoryItem { + /** 角色:user / assistant */ + role: string + /** 消息内容 */ + content: string +} + +/** Agent AI 对话请求参数 */ +export interface AgentChatParams { + /** 用户输入的消息 */ + message: string + /** 简历 ID(字符串,避免大整数精度丢失) */ + resumeId: string + /** 对话历史 */ + history?: AgentChatHistoryItem[] + /** 意向岗位类型名称 */ + jobCategories?: string[] + /** 意向城市名称 */ + regions?: string[] + /** 意向行业名称 */ + industries?: string[] +} + +/** Agent AI 对话返回数据 */ +export interface AgentChatResponse { + /** AI 回复的消息内容 */ + message: string + /** 工具调用名称(null=普通回复,recommend=推荐岗位) */ + tool: string | null + /** 工具调用参数 */ + toolParams: Record | null +} + +/** + * Agent AI 对话(Python 后端) + * POST /job-agent/chat + */ +export function sendAgentChat(params: AgentChatParams) { + return aiService.post }>('/job-agent/chat', params).then(res => res.data) +} diff --git a/src/api/jobs.ts b/src/api/jobs.ts index 66a0ff7..e696a01 100644 --- a/src/api/jobs.ts +++ b/src/api/jobs.ts @@ -488,9 +488,11 @@ export interface CustomizeResumeData { /** * 查询定制简历结果(AI 接口) * GET /job/customize-resume + * @param jobId 岗位ID(必需) */ -export function fetchCustomizeResume() { +export function fetchCustomizeResume(jobId: string) { return aiService.get }>('/job/customize-resume', { + params: { job_id: jobId }, transformResponse: [(data: string) => { try { const processed = data.replace(/:\s*(\d{16,})/g, ':"$1"') @@ -585,8 +587,9 @@ export function aiEditResume(params: AiEditResumeParams) { * 撤销AI对话编辑简历的修改(AI 接口) * POST /job/customize-resume/rollback */ -export function rollbackCustomizeResume() { +export function rollbackCustomizeResume(jobId: string) { return aiService.post }>('/job/customize-resume/rollback', null, { + params: { job_id: jobId }, transformResponse: [(data: string) => { try { const processed = data.replace(/:\s*(\d{16,})/g, ':"$1"') @@ -604,8 +607,9 @@ export function rollbackCustomizeResume() { * 输入框失焦或选择器选中后自动调用 * @param data 定制简历完整数据 */ -export function updateCustomizeResume(data: CustomizeResumeData) { +export function updateCustomizeResume(data: CustomizeResumeData,jobId: string) { return aiService.put }>('/job/customize-resume', data, { + params: { job_id: jobId }, transformResponse: [(raw: string) => { try { const processed = raw.replace(/:\s*(\d{16,})/g, ':"$1"') diff --git a/src/api/resume.ts b/src/api/resume.ts index 2d5d950..0a22f5c 100644 --- a/src/api/resume.ts +++ b/src/api/resume.ts @@ -23,10 +23,10 @@ export interface ResumeListItem { targetPosition?: string /** 是否默认简历 0=否 1=是 */ isDefault?: number - /** 简历修改时间 */ - updateTime?: InstantTime - /** 简历创建时间 */ - createTime?: InstantTime + /** 简历修改时间(毫秒时间戳) */ + updateTime?: number + /** 简历创建时间(毫秒时间戳) */ + createTime?: number } /** @@ -275,6 +275,8 @@ export function saveResumeMain(data: SaveResumeMainParams) { /** 保存简历教育经历参数(单条) */ export interface SaveResumeEducationItem { + /** 记录ID(编辑时必传) */ + id?: string | number /** 学校名称 */ school?: string /** 专业 */ @@ -292,15 +294,45 @@ export interface SaveResumeEducationItem { } /** - * 保存简历教育经历(全量覆盖) + * 保存简历教育经历(全量覆盖)— 旧接口,保留兼容 * POST /resume/education */ export function saveResumeEducation(resumeId: string, data: SaveResumeEducationItem[]) { return request.post('/resume/education', { resumeId, items: data }) } +/** + * 添加单条教育经历,返回新记录ID + * POST /resume/education/add + */ +export function addResumeEducation(resumeId: string, data: SaveResumeEducationItem) { + return request.post>('/resume/education/add', data, { + params: { resumeId }, + }) +} + +/** + * 根据ID编辑单条教育经历 + * POST /resume/education/update + */ +export function updateResumeEducation(data: SaveResumeEducationItem) { + return request.post('/resume/education/update', data) +} + +/** + * 根据ID删除单条教育经历 + * POST /resume/education/delete + */ +export function deleteResumeEducation(id: string) { + return request.post('/resume/education/delete', null, { + params: { id }, + }) +} + /** 保存简历工作经历参数(单条) */ export interface SaveResumeWorkItem { + /** 记录ID(编辑时必传) */ + id?: string | number /** 公司名称 */ companyName?: string /** 职位 */ @@ -314,7 +346,7 @@ export interface SaveResumeWorkItem { } /** - * 保存简历工作经历(全量覆盖) + * 保存简历工作经历(全量覆盖)— 旧接口,保留兼容 * POST /resume/work */ export function saveResumeWork(resumeId: string, data: SaveResumeWorkItem[]) { @@ -322,15 +354,73 @@ export function saveResumeWork(resumeId: string, data: SaveResumeWorkItem[]) { } /** - * 保存简历实习经历(全量覆盖) + * 添加单条工作经历,返回新记录ID + * POST /resume/work/add + */ +export function addResumeWork(resumeId: string, data: SaveResumeWorkItem) { + return request.post>('/resume/work/add', data, { + params: { resumeId }, + }) +} + +/** + * 根据ID编辑单条工作经历 + * POST /resume/work/update + */ +export function updateResumeWork(data: SaveResumeWorkItem) { + return request.post('/resume/work/update', data) +} + +/** + * 根据ID删除单条工作经历 + * POST /resume/work/delete + */ +export function deleteResumeWork(id: string) { + return request.post('/resume/work/delete', null, { + params: { id }, + }) +} + +/** + * 保存简历实习经历(全量覆盖)— 旧接口,保留兼容 * POST /resume/internship */ export function saveResumeInternship(resumeId: string, data: SaveResumeWorkItem[]) { return request.post('/resume/internship', { resumeId, items: data }) } +/** + * 添加单条实习经历,返回新记录ID + * POST /resume/internship/add + */ +export function addResumeInternship(resumeId: string, data: SaveResumeWorkItem) { + return request.post>('/resume/internship/add', data, { + params: { resumeId }, + }) +} + +/** + * 根据ID编辑单条实习经历 + * POST /resume/internship/update + */ +export function updateResumeInternship(data: SaveResumeWorkItem) { + return request.post('/resume/internship/update', data) +} + +/** + * 根据ID删除单条实习经历 + * POST /resume/internship/delete + */ +export function deleteResumeInternship(id: string) { + return request.post('/resume/internship/delete', null, { + params: { id }, + }) +} + /** 保存简历项目经历参数(单条) */ export interface SaveResumeProjectItem { + /** 记录ID(编辑时必传) */ + id?: string | number /** 项目名称 */ projectName?: string /** 所属公司 */ @@ -346,15 +436,45 @@ export interface SaveResumeProjectItem { } /** - * 保存简历项目经历(全量覆盖) + * 保存简历项目经历(全量覆盖)— 旧接口,保留兼容 * POST /resume/project */ export function saveResumeProject(resumeId: string, data: SaveResumeProjectItem[]) { return request.post('/resume/project', { resumeId, items: data }) } +/** + * 添加单条项目经历,返回新记录ID + * POST /resume/project/add + */ +export function addResumeProject(resumeId: string, data: SaveResumeProjectItem) { + return request.post>('/resume/project/add', data, { + params: { resumeId }, + }) +} + +/** + * 根据ID编辑单条项目经历 + * POST /resume/project/update + */ +export function updateResumeProject(data: SaveResumeProjectItem) { + return request.post('/resume/project/update', data) +} + +/** + * 根据ID删除单条项目经历 + * POST /resume/project/delete + */ +export function deleteResumeProject(id: string) { + return request.post('/resume/project/delete', null, { + params: { id }, + }) +} + /** 保存简历竞赛经历参数(单条) */ export interface SaveResumeCompetitionItem { + /** 记录ID(编辑时必传) */ + id?: string | number /** 竞赛名称 */ competitionName?: string /** 获奖情况 */ @@ -366,13 +486,41 @@ export interface SaveResumeCompetitionItem { } /** - * 保存简历竞赛经历(全量覆盖) + * 保存简历竞赛经历(全量覆盖)— 旧接口,保留兼容 * POST /resume/competition */ export function saveResumeCompetition(resumeId: string, data: SaveResumeCompetitionItem[]) { return request.post('/resume/competition', { resumeId, items: data }) } +/** + * 添加单条竞赛经历,返回新记录ID + * POST /resume/competition/add + */ +export function addResumeCompetition(resumeId: string, data: SaveResumeCompetitionItem) { + return request.post>('/resume/competition/add', data, { + params: { resumeId }, + }) +} + +/** + * 根据ID编辑单条竞赛经历 + * POST /resume/competition/update + */ +export function updateResumeCompetition(data: SaveResumeCompetitionItem) { + return request.post('/resume/competition/update', data) +} + +/** + * 根据ID删除单条竞赛经历 + * POST /resume/competition/delete + */ +export function deleteResumeCompetition(id: string) { + return request.post('/resume/competition/delete', null, { + params: { id }, + }) +} + /** * 删除简历 * POST /resume/delete diff --git a/src/assets/images/插件操作界面.png b/src/assets/images/插件操作界面.png new file mode 100644 index 0000000..7a69c33 Binary files /dev/null and b/src/assets/images/插件操作界面.png differ diff --git a/src/assets/images/编辑简历名称.png b/src/assets/images/编辑简历名称.png new file mode 100644 index 0000000..9a8ab13 Binary files /dev/null and b/src/assets/images/编辑简历名称.png differ diff --git a/src/assets/styles/components/agent-chat-job-list.scss b/src/assets/styles/components/agent-chat-job-list.scss new file mode 100644 index 0000000..9d3cf0e --- /dev/null +++ b/src/assets/styles/components/agent-chat-job-list.scss @@ -0,0 +1,160 @@ +@use '../variables' as *; + +// ==================== Agent会话岗位列表组件样式 ==================== +.agent-chat-job-list { + background: $bg-middle; + border-radius: 0.12rem; + padding: 0.2rem; + margin-top: 0.16rem; + + // 推荐说明文字 + &__summary { + font-size: 0.13rem; + color: $text-dark; + font-weight: 500; + margin-bottom: 0.14rem; + line-height: 1.6; + } + + // 单个岗位项 + &__item { + display: flex; + align-items: center; + justify-content: space-between; + background: $bg-white; + border-radius: 0.1rem; + padding: 0.14rem 0.16rem; + margin-bottom: 0.08rem; + + &:last-of-type { + margin-bottom: 0; + } + } + + // 左侧信息区域 + &__info { + display: flex; + align-items: center; + gap: 0.12rem; + flex: 1; + min-width: 0; + } + + // 公司 Logo + &__logo { + width: 0.36rem; + height: 0.36rem; + border-radius: 0.06rem; + background: $bg-main; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: $text-middle; + overflow: hidden; + + img { + width: 100%; + height: 100%; + object-fit: cover; + } + + svg { + width: 0.2rem; + height: 0.2rem; + } + } + + // 岗位详情 + &__detail { + min-width: 0; + } + + // 公司名称 + &__company { + font-size: 0.14rem; + font-weight: 600; + color: $text-dark; + line-height: 1.4; + } + + // 岗位名称 + &__title { + font-size: 0.12rem; + color: $text-middle; + line-height: 1.4; + margin-bottom: 0.04rem; + } + + // 标签行 + &__tags { + display: flex; + gap: 0.06rem; + flex-wrap: wrap; + } + + // 单个标签 + &__tag { + font-size: 0.11rem; + color: $text-middle; + background: $bg-main; + padding: 0.02rem 0.08rem; + border-radius: 0.03rem; + } + + // 匹配度环形容器 + &__score { + position: relative; + width: 0.44rem; + height: 0.44rem; + flex-shrink: 0; + margin-left: 0.12rem; + } + + // 环形 SVG + &__ring { + width: 100%; + height: 100%; + } + + // 匹配度数字 + &__score-text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 0.11rem; + font-weight: 600; + color: $text-dark; + } + + // 底部按钮区域 + &__footer { + display: flex; + justify-content: center; + margin-top: 0.14rem; + } + + // 查看全部岗位按钮 + &__view-all-btn { + height: 0.38rem; + padding: 0 0.32rem; + background: $btn-dark; + color: $bg-white; + border: none; + border-radius: 0.19rem; + font-size: 0.13rem; + font-weight: 500; + cursor: pointer; + transition: all 0.25s ease; + line-height: 0.38rem; + + &:hover { + background: $btn-dark-hover; + } + + &:active { + transform: scale(0.98); + } + } +} diff --git a/src/assets/styles/components/agent-match-job-add.scss b/src/assets/styles/components/agent-match-job-add.scss new file mode 100644 index 0000000..a1e29f5 --- /dev/null +++ b/src/assets/styles/components/agent-match-job-add.scss @@ -0,0 +1,269 @@ +@use '../variables' as *; + +// ==================== Agent匹配岗位添加组件样式 ==================== +.agent-match-job-add { + background: $bg-white; + border-radius: 0.12rem; + height: 100%; + display: flex; + flex-direction: column; + + // 顶部标题栏 + &__header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.18rem 0.2rem; + border-bottom: 1px solid $border-color; + flex-shrink: 0; + } + + // 标题文字 + &__title { + font-size: 0.16rem; + font-weight: 700; + color: $text-dark; + } + + // 右侧操作区 + &__actions { + display: flex; + align-items: center; + gap: 0.1rem; + } + + // 全部添加按钮 + &__add-all-btn { + height: 0.32rem; + padding: 0 0.16rem; + background: $bg-white; + color: $text-dark; + border: 1px solid $border-color; + border-radius: 0.16rem; + font-size: 0.12rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + line-height: 0.3rem; + + &:hover { + border-color: $text-dark; + } + } + + // 关闭按钮 + &__close-btn { + width: 0.28rem; + height: 0.28rem; + border: none; + background: transparent; + cursor: pointer; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + + svg { + width: 0.24rem; + height: 0.24rem; + } + } + + // 岗位列表容器(可滚动) + &__list { + flex: 1; + overflow-y: auto; + padding: 0.12rem 0.2rem; + + // 自定义滚动条 + &::-webkit-scrollbar { + width: 4px; + } + + &::-webkit-scrollbar-thumb { + background: $border-color; + border-radius: 2px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + } + + // 单个岗位项 + &__item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.14rem 0; + border-bottom: 1px solid $border-color; + + &:last-child { + border-bottom: none; + } + } + + // 左侧信息区域 + &__info { + display: flex; + align-items: center; + gap: 0.12rem; + flex: 1; + min-width: 0; + } + + // 公司 Logo + &__logo { + width: 0.36rem; + height: 0.36rem; + border-radius: 0.06rem; + background: $bg-main; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: $text-middle; + overflow: hidden; + + img { + width: 100%; + height: 100%; + object-fit: cover; + } + + svg { + width: 0.2rem; + height: 0.2rem; + } + } + + // 岗位详情 + &__detail { + min-width: 0; + } + + // 公司名称 + &__company { + font-size: 0.14rem; + font-weight: 600; + color: $text-dark; + line-height: 1.4; + } + + // 岗位名称 + &__position { + font-size: 0.12rem; + color: $text-middle; + line-height: 1.4; + margin-bottom: 0.04rem; + } + + // 标签行 + &__tags { + display: flex; + gap: 0.06rem; + flex-wrap: wrap; + } + + // 单个标签 + &__tag { + font-size: 0.11rem; + color: $text-middle; + background: $bg-main; + padding: 0.02rem 0.08rem; + border-radius: 0.03rem; + } + + // 右侧:匹配度 + 按钮 + &__right { + display: flex; + align-items: center; + gap: 0.12rem; + flex-shrink: 0; + } + + // 匹配度环形容器 + &__score { + position: relative; + width: 0.44rem; + height: 0.44rem; + flex-shrink: 0; + } + + // 环形 SVG + &__ring { + width: 100%; + height: 100%; + } + + // 匹配度数字 + &__score-text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 0.11rem; + font-weight: 600; + color: $text-dark; + } + + // 添加/移除按钮 + &__action-btn { + height: 0.32rem; + padding: 0 0.16rem; + border-radius: 0.16rem; + font-size: 0.12rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + line-height: 0.3rem; + white-space: nowrap; + border: 1px solid $text-dark; + background: $bg-white; + color: $text-dark; + + &:hover { + background: $text-dark; + color: $bg-white; + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } + + // 移除状态 — 深色背景 + &--remove { + background: $text-dark; + color: $bg-white; + border-color: $text-dark; + + &:hover { + opacity: 0.85; + } + } + } + + // 底部查看更多 + &__footer { + padding: 0.14rem 0.2rem; + border-top: 1px solid $border-color; + flex-shrink: 0; + text-align: center; + } + + // 查看更多按钮 + &__more-btn { + font-size: 0.12rem; + color: $text-middle; + background: transparent; + border: none; + cursor: pointer; + text-decoration: underline; + padding: 0; + + &:hover { + color: $text-dark; + } + } +} diff --git a/src/assets/styles/components/agent-settings-panel.scss b/src/assets/styles/components/agent-settings-panel.scss new file mode 100644 index 0000000..a5fb6a0 --- /dev/null +++ b/src/assets/styles/components/agent-settings-panel.scss @@ -0,0 +1,145 @@ +@use '../variables' as *; + +// ==================== Agent设置面板样式 ==================== +.agent-settings-panel { + // 表单分组 + &__group { + margin-bottom: 0.28rem; + + &:last-child { margin-bottom: 0; } + } + + // 分组标签 + &__label { + font-size: 0.14rem; + font-weight: 600; + color: $text-dark; + margin-bottom: 0.14rem; + } + + // 提示图标 + &__tip { + color: $text-light; + cursor: pointer; + margin-left: 0.04rem; + font-size: 0.12rem; + } + + // 选项按钮行 + &__options { + display: flex; + gap: 0.12rem; + } + + // 单个选项按钮 + &__option { + padding: 0.08rem 0.2rem; + border: 1px solid $border-color; + border-radius: 0.06rem; + background: $bg-white; + color: $text-dark; + font-size: 0.13rem; + cursor: pointer; + transition: all 0.2s ease; + line-height: 1.4; + + &:hover { + border-color: $accent; + } + + // 大号选项(Agent模式、投递目标) + &--lg { + flex: 1; + text-align: center; + padding: 0.14rem 0.16rem; + font-size: 0.14rem; + font-weight: 500; + border-radius: 0.08rem; + } + + // 选中态 + &--active { + background: $bg-main; + border-color: $text-dark; + font-weight: 600; + } + } + + // 子标签 + &__sub-label { + font-size: 0.13rem; + color: $text-middle; + margin-bottom: 0.1rem; + } + + // 简历选择行 + &__resume-select { + display: flex; + align-items: center; + gap: 0.08rem; + background: $bg-main; + border-radius: 0.08rem; + padding: 0.06rem 0.12rem; + margin-bottom: 0.16rem; + } + + // 简历图标 + &__resume-icon { + width: 0.18rem; + height: 0.18rem; + flex-shrink: 0; + color: $text-middle; + + svg { + width: 100%; + height: 100%; + } + } + + // 下拉选择器样式覆盖 + &__select { + flex: 1; + + :deep(.el-input__wrapper) { + box-shadow: none; + background: transparent; + border: none; + padding: 0; + + &:hover, + &.is-focus { + box-shadow: none; + } + } + + :deep(.el-input__inner) { + font-size: 0.13rem; + color: $text-dark; + } + + :deep(.el-input__suffix) { + color: $text-light; + } + } + + // 开关行 + &__switch-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.12rem; + } + + // 开关文字 + &__switch-text { + font-size: 0.13rem; + color: $text-dark; + line-height: 1.5; + } + + // 开关副文字 + &__switch-sub { + font-size: 0.12rem; + color: $text-light; + } +} diff --git a/src/assets/styles/components/ai-chat.scss b/src/assets/styles/components/ai-chat.scss index ee7a77b..643b9c1 100644 --- a/src/assets/styles/components/ai-chat.scss +++ b/src/assets/styles/components/ai-chat.scss @@ -102,7 +102,7 @@ } &__msg--user &__msg-bubble { - background: #f0f3f6; + background: #fff; color: #1a1a2e; } @@ -123,7 +123,7 @@ flex-direction: column; gap: 0.08rem; margin-top: 0.12rem; - padding-right: 0.5rem; + margin-bottom: 0.12rem; } &__quick-item { @@ -135,11 +135,24 @@ font-size: 0.12rem; cursor: pointer; transition: background 0.2s; + max-width: 80%; &:hover { background: #f9fafb; color: #374151; } + + /* AI 提问靠左 */ + &--ai { + align-self: flex-start; + } + + /* 用户提问靠右 */ + &--user { + align-self: flex-end; + background: #f0f3f6; + border-color: #e0e3e6; + } } &__input-area { diff --git a/src/assets/styles/components/ai-thinking-indicator.scss b/src/assets/styles/components/ai-thinking-indicator.scss new file mode 100644 index 0000000..9523ae2 --- /dev/null +++ b/src/assets/styles/components/ai-thinking-indicator.scss @@ -0,0 +1,25 @@ +@use '../variables' as *; + +.ai-thinking-indicator { + display: flex; + justify-content: flex-start; + margin-bottom: 0.12rem; + + &__bubble { + background: #fff; + border: 1px solid #e5e7eb; + border-radius: 0.1rem; + padding: 0.12rem 0.14rem; + font-size: 0.13rem; + color: $text-middle; + font-style: italic; + display: flex; + align-items: center; + gap: 0.06rem; + } + + &__icon { + color: $accent; + font-size: 0.16rem; + } +} diff --git a/src/assets/styles/components/job-resume-custom-dialog.scss b/src/assets/styles/components/job-resume-custom-dialog.scss index 14d6728..10ca4b1 100644 --- a/src/assets/styles/components/job-resume-custom-dialog.scss +++ b/src/assets/styles/components/job-resume-custom-dialog.scss @@ -690,7 +690,7 @@ &__drawer { position: relative; background: $bg-white; - width: 9.4rem; + width: 10.4rem; height: 100vh; box-sizing: border-box; display: flex; @@ -753,7 +753,6 @@ // ==================== 步骤四:预览布局 ==================== &__preview { display: flex; - gap: 0.2rem; height: 100%; min-height: 0; } @@ -763,8 +762,7 @@ flex: 1; overflow-y: auto; background: $bg-white; - border: 1px solid $border-color; - border-radius: 0.08rem; + border-bottom: 1px solid $border-color; min-width: 0; } @@ -814,6 +812,7 @@ flex-direction: column; min-height: 0; overflow: hidden; + border-bottom: 0.01rem solid $border-color; } // AI优化结果卡片 @@ -953,6 +952,15 @@ &__ai-msg-bubble--loading { color: $text-middle; font-style: italic; + display: flex; + align-items: center; + gap: 0.06rem; + } + + // AI思考中的转圈加载图标 + &__ai-loading-icon { + color: $accent; + font-size: 0.16rem; } // 消息包裹容器(含撤销气泡) diff --git a/src/assets/styles/components/job-resume-template.scss b/src/assets/styles/components/job-resume-template.scss index 74890ef..129b651 100644 --- a/src/assets/styles/components/job-resume-template.scss +++ b/src/assets/styles/components/job-resume-template.scss @@ -54,6 +54,8 @@ margin-top: 16px; margin-bottom: 2px; line-height: 1.3; + break-after: avoid; + page-break-after: avoid; } // 分割线 @@ -80,6 +82,8 @@ align-items: flex-start; justify-content: space-between; margin-bottom: 4px; + break-inside: avoid; + page-break-inside: avoid; } &__item-left { @@ -130,6 +134,8 @@ font-size: 12px; line-height: 1.7; color: $text-dark; + break-inside: avoid; + page-break-inside: avoid; } } diff --git a/src/assets/styles/components/resume-edit-name-dialog.scss b/src/assets/styles/components/resume-edit-name-dialog.scss new file mode 100644 index 0000000..aba0989 --- /dev/null +++ b/src/assets/styles/components/resume-edit-name-dialog.scss @@ -0,0 +1,99 @@ +@use '../variables' as *; + +/* 编辑简历名称弹窗样式 */ +.resume-edit-name-dialog { + .el-dialog__header { + padding: 0.2rem 0.2rem 0; + } + + .el-dialog__body { + padding: 0 0.3rem 0.3rem; + } + + &__body { + display: flex; + flex-wrap: wrap; + gap: 0.24rem; + } + + /* 表单字段 */ + &__field { + width: 100%; + } + + /* 标签 */ + &__label { + display: block; + font-size: 0.16rem; + font-weight: 600; + color: $text-dark; + margin-bottom: 0.12rem; + } + + /* 必填星号 */ + &__required { + color: $danger; + margin-right: 0.04rem; + } + + /* 输入框 */ + &__input { + .el-input__wrapper { + border-radius: 0.1rem; + padding: 0.04rem 0.14rem; + box-shadow: 0 0 0 1px $border-color; + } + + .el-input__inner { + font-size: 0.14rem; + color: $text-dark; + height: 0.36rem; + line-height: normal; + + &::placeholder { + color: $text-light; + } + } + } + + /* 底部按钮区域 */ + &__footer { + width: 100%; + display: flex; + gap: 0.16rem; + margin-top: 0.08rem; + } + + /* 按钮通用 */ + &__btn { + flex: 1; + height: 0.46rem; + border-radius: 0.23rem; + font-size: 0.15rem; + font-weight: 500; + cursor: pointer; + border: none; + transition: opacity 0.2s; + + &:active { + opacity: 0.8; + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } + + /* 取消按钮 */ + &--cancel { + background: $bg-main; + color: $text-dark; + } + + /* 保存按钮 */ + &--save { + background: $accent; + color: $bg-white; + } + } +} diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss index f8345c7..6f42834 100644 --- a/src/assets/styles/index.scss +++ b/src/assets/styles/index.scss @@ -27,6 +27,10 @@ @use './components/job-resume-custom-edit-panel.scss'; @use './components/resume-analysis-report-drawer.scss'; @use './components/resume-issue-fix-drawer.scss'; +@use './components/resume-edit-name-dialog.scss'; +@use './components/agent-chat-job-list.scss'; +@use './components/agent-match-job-add.scss'; +@use './components/ai-thinking-indicator.scss'; // 全局样式(优先级最高) @use './auto.scss'; diff --git a/src/assets/styles/pages/agent.scss b/src/assets/styles/pages/agent.scss index f866feb..ff5ef7c 100644 --- a/src/assets/styles/pages/agent.scss +++ b/src/assets/styles/pages/agent.scss @@ -1,10 +1,11 @@ +@use 'sass:color'; @use '../variables' as *; // ==================== 求职助手页面样式 ==================== .agent-page { min-height: 100vh; background: $bg-main; - + font-size: 0.14rem; // 主内容区域(左侧导航栏右边的部分) &__content { margin-left: 2rem; @@ -35,13 +36,13 @@ transition: all 0.25s ease; user-select: none; - // 激活态 — 深色背景白色文字 + // 激活态 — 品牌色背景白色文字 &--active { - background: $text-dark; + background: $btn-dark; .agent-page__step-number { background: $bg-white; - color: $text-dark; + color: $btn-dark; } .agent-page__step-label { @@ -117,14 +118,14 @@ &__intro-header { display: flex; align-items: flex-start; - gap: 0.12rem; + gap: 0.02rem; margin-bottom: 0.2rem; } // 用户图标 &__intro-icon { - width: 0.28rem; - height: 0.28rem; + width: 0.20rem; + height: 0.20rem; flex-shrink: 0; color: $text-dark; margin-top: 0.02rem; @@ -150,7 +151,6 @@ color: $text-light; line-height: 1.7; margin-bottom: 0.28rem; - padding-left: 0.4rem; } // 导入个人资料行 @@ -162,7 +162,6 @@ background: $bg-main; border-radius: 0.08rem; margin-bottom: 0.28rem; - margin-left: 0.4rem; } // 导入图标 @@ -190,8 +189,7 @@ display: block; width: 2rem; height: 0.42rem; - margin-left: 0.4rem; - background: $text-dark; + background: $btn-dark; color: $bg-white; border: none; border-radius: 0.21rem; @@ -245,4 +243,827 @@ padding-bottom: 0.12rem; border-bottom: 1px solid $border-color; } + + // ==================== 第2步:确认目标 ==================== + + // 第2步整体容器 + &__step2 { + width: 100%; + max-width: 7rem; + margin: 0 auto; + } + + // 对话区域 + &__chat { + display: flex; + flex-direction: column; + gap: 0.2rem; + } + + // 对话行:头像 + 文字 + &__chat-row { + display: flex; + align-items: flex-start; + gap: 0.04rem; + } + + // 对话头像 + &__chat-avatar { + width: 0.32rem; + height: 0.32rem; + border-radius: 50%; + background: $bg-main; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: $text-middle; + + svg { + width: 0.18rem; + height: 0.18rem; + } + } + + // 对话文字 + &__chat-text { + font-size: 0.15rem; + font-weight: 600; + color: $text-dark; + line-height: 0.32rem; + } + + // 正在输入指示器 + &__chat-typing { + display: flex; + align-items: center; + gap: 0.05rem; + background: $bg-main; + border-radius: 0.16rem; + padding: 0.1rem 0.06rem; + + span { + width: 0.06rem; + height: 0.06rem; + border-radius: 50%; + background: $text-light; + animation: typingDot 1.4s infinite; + + &:nth-child(2) { animation-delay: 0.2s; } + &:nth-child(3) { animation-delay: 0.4s; } + } + } + + @keyframes typingDot { + 0%, 60%, 100% { opacity: 0.3; transform: scale(1); } + 30% { opacity: 1; transform: scale(1.2); } + } + + // ==================== 求职偏好卡片 ==================== + &__pref-card { + background: $bg-main; + border-radius: 0.12rem; + padding: 0.24rem; + } + + &__pref-desc { + font-size: 0.13rem; + color: $text-middle; + margin-bottom: 0.16rem; + line-height: 1.5; + } + + &__pref-tags { + display: flex; + flex-wrap: wrap; + gap: 0.08rem; + margin-bottom: 0.24rem; + } + + &__pref-tag { + padding: 0.06rem 0.16rem; + background: $bg-white; + border-radius: 0.04rem; + font-size: 0.13rem; + color: $text-dark; + } + + &__pref-actions { + display: flex; + gap: 0.12rem; + } + + &__pref-btn { + flex: 1; + height: 0.42rem; + border-radius: 0.21rem; + font-size: 0.14rem; + font-weight: 500; + cursor: pointer; + transition: all 0.25s ease; + border: none; + line-height: 0.42rem; + text-align: center; + padding: 0; + + &--edit { + background: $border-color; + color: $text-dark; + + &:hover { background: color.adjust($border-color, $lightness: -5%); } + } + + &--confirm { + background: $btn-dark; + color: $bg-white; + + &:hover { background: $btn-dark-hover; } + } + } + + // ==================== 匹配岗位卡片 ==================== + &__match-card { + background: $bg-main; + border-radius: 0.12rem; + padding: 0.24rem; + + } + + &__match-desc { + font-size: 0.13rem; + color: $text-dark; + font-weight: 500; + margin-bottom: 0.16rem; + line-height: 1.6; + } + + // 单个岗位项 + &__match-item { + display: flex; + align-items: center; + background: $bg-white; + border-radius: 0.1rem; + padding: 0.16rem; + margin-bottom: 0.1rem; + + &:last-of-type { margin-bottom: 0; } + } + + &__match-info { + display: flex; + align-items: center; + gap: 0.12rem; + flex: 1; + min-width: 0; + } + + // 公司图标 + &__match-icon { + width: 0.36rem; + height: 0.36rem; + border-radius: 0.06rem; + background: $bg-main; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: $text-middle; + + svg { + width: 0.2rem; + height: 0.2rem; + } + } + + &__match-detail { + min-width: 0; + } + + &__match-company { + font-size: 0.14rem; + font-weight: 600; + color: $text-dark; + line-height: 1.4; + } + + &__match-position { + font-size: 0.12rem; + color: $text-middle; + line-height: 1.4; + margin-bottom: 0.06rem; + } + + &__match-tags { + display: flex; + gap: 0.06rem; + flex-wrap: wrap; + } + + &__match-tag { + font-size: 0.11rem; + color: $text-middle; + background: $bg-main; + padding: 0.02rem 0.08rem; + border-radius: 0.03rem; + } + + // 匹配度环形 + &__match-score { + position: relative; + width: 0.44rem; + height: 0.44rem; + flex-shrink: 0; + margin: 0 0.16rem; + } + + &__match-ring { + width: 100%; + height: 100%; + } + + &__match-score-text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 0.11rem; + font-weight: 600; + color: $text-dark; + } + + // 点赞/踩按钮 + &__match-feedback { + display: flex; + flex-direction: column; + gap: 0.06rem; + flex-shrink: 0; + } + + &__match-fb-btn { + width: 0.3rem; + height: 0.3rem; + border: none; + background: transparent; + border-radius: 0.06rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: $text-light; + transition: all 0.2s ease; + padding: 0; + + svg { + width: 0.18rem; + height: 0.18rem; + } + + &:hover { color: $text-middle; } + + &--active { + color: $text-dark; + } + } + + // 不满意反馈输入框 + &__dislike-input { + margin-top: 0.12rem; + + input { + width: 100%; + height: 0.4rem; + border: 1px solid $border-color; + border-radius: 0.08rem; + padding: 0 0.14rem; + font-size: 0.13rem; + color: $text-dark; + background: $bg-white; + outline: none; + box-sizing: border-box; + + &::placeholder { color: $text-light; } + &:focus { border-color: $text-middle; } + } + } + + // 底部优化按钮 + &__step2-footer { + display: flex; + justify-content: center; + margin-top: 0.08rem; + } + + &__optimize-btn { + height: 0.44rem; + padding: 0 0.4rem; + background: $btn-dark; + color: $bg-white; + border: none; + border-radius: 0.22rem; + font-size: 0.14rem; + font-weight: 500; + cursor: pointer; + transition: all 0.25s ease; + line-height: 0.44rem; + + &:hover { background: $btn-dark-hover; } + &:active { transform: scale(0.98); } + } + + // ==================== 第3步:网申常见问题 ==================== + + // 第3步整体容器 — 左右两栏布局 + &__step3 { + display: flex; + gap: 0.24rem; + align-items: flex-start; + width: 100%; + } + + // 右侧表单包裹 + &__form-wrapper { + background: $bg-white; + border-radius: 0.12rem; + padding: 0.28rem; + border: 1px solid $border-color; + } + + // 表单标题 + &__form-title { + font-size: 0.15rem; + font-weight: 700; + color: $text-dark; + margin-bottom: 0.24rem; + padding-bottom: 0.12rem; + border-bottom: 1px solid $border-color; + } + + // 表单分组 + &__form-group { + margin-bottom: 0.28rem; + + &:last-child { margin-bottom: 0; } + } + + // 表单标签 + &__form-label { + font-size: 0.14rem; + font-weight: 600; + color: $text-dark; + margin-bottom: 0.12rem; + text-align: center; + } + + // 选项按钮行 + &__form-options { + display: flex; + justify-content: center; + gap: 0.12rem; + } + + // 单个选项按钮 + &__form-option { + padding: 0.08rem 0.24rem; + border: 1px solid $border-color; + border-radius: 0.06rem; + background: $bg-white; + color: $text-dark; + font-size: 0.13rem; + cursor: pointer; + transition: all 0.2s ease; + line-height: 1.4; + + &:hover { + border-color: $text-middle; + } + + // 选中态 + &--active { + background: $btn-dark; + color: $bg-white; + border-color: $btn-dark; + } + } + + // 下拉选择器行 + &__form-selects { + display: flex; + justify-content: center; + gap: 0.12rem; + } + + // 统一下拉选择器样式覆盖 + &__form-select { + width: 1.4rem; + + // 覆盖 Element Plus 选择器样式以匹配页面风格 + :deep(.el-input__wrapper) { + border-radius: 0.2rem; + box-shadow: none; + border: 1px solid $border-color; + padding: 0.02rem 0.12rem; + background: $bg-white; + transition: border-color 0.2s ease; + + &:hover, + &.is-focus { + border-color: $accent; + box-shadow: none; + } + } + + :deep(.el-input__inner) { + font-size: 0.13rem; + color: $text-dark; + text-align: center; + + &::placeholder { + color: $text-light; + } + } + + :deep(.el-input__suffix) { + color: $text-light; + } + } + + // ==================== 第3步下半部分:插件安装 ==================== + + // 安装步骤说明文字 + &__install-steps { + font-size: 0.13rem; + color: $text-middle; + line-height: 1.8; + margin-bottom: 0.28rem; + + p { margin: 0; } + } + + // 插件区域 + &__plugin-section { + text-align: center; + padding: 0.2rem 0; + } + + // 插件标题 + &__plugin-title { + font-size: 0.18rem; + font-weight: 700; + color: $text-dark; + margin-bottom: 0.24rem; + } + + // 浏览器按钮行 + &__browser-btns { + display: flex; + justify-content: center; + gap: 0.1rem; + flex-wrap: wrap; + } + + // 单个浏览器按钮 + &__browser-btn { + padding: 0.08rem 0.2rem; + border: 1px solid $border-color; + border-radius: 0.06rem; + background: $bg-white; + color: $text-dark; + font-size: 0.13rem; + cursor: pointer; + transition: all 0.2s ease; + + &:hover { + border-color: $accent; + color: $accent; + } + } + + // 指引图片幻灯片 + &__guide-slide { + display: flex; + align-items: center; + justify-content: center; + height: 100%; + + img { + max-width: 100%; + max-height: 100%; + object-fit: contain; + border-radius: 0.08rem; + } + } + + // ==================== 设置完成页 ==================== + + // 完成页容器 — 居中布局 + &__complete { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 1rem 0; + } + + // 完成页占位图标 + &__complete-icon { + width: 1.2rem; + height: 1.2rem; + margin-bottom: 0.32rem; + + svg { + width: 100%; + height: 100%; + } + } + + // 完成页标题 + &__complete-title { + font-size: 0.2rem; + font-weight: 700; + color: $text-dark; + margin: 0 0 0.12rem; + } + + // 完成页描述 + &__complete-desc { + font-size: 0.14rem; + color: $text-middle; + margin-bottom: 0.4rem; + } + + // 启用按钮 + &__complete-btn { + padding: 0.12rem 0.36rem; + background: $btn-dark; + color: $bg-white; + border: none; + border-radius: 0.24rem; + font-size: 0.15rem; + font-weight: 500; + cursor: pointer; + transition: all 0.25s ease; + + &:hover { background: $btn-dark-hover; } + &:active { transform: scale(0.98); } + } +} + + +// ==================== 求职助手正式内容区域 ==================== +.agent-main { + height: 100%; + display: flex; + justify-content: center; + + // 有右侧面板时取消居中 + &--with-panel { + //justify-content: flex-start; + } + + // 左侧主区域 + &__left { + flex: 1; + height: calc(100vh - 0.6rem); + display: flex; + flex-direction: column; + max-width: 8rem; + } + + // 右侧匹配岗位面板 + &__right { + flex: 1; + height: calc(100vh - 0.6rem); + margin-left: 0.2rem; + max-width: 8rem; + } + + // ==================== 顶部固定设置栏 ==================== + &__top-bar { + display: flex; + align-items: center; + gap: 0.1rem; + padding: 0.12rem 0.16rem; + background: $bg-white; + border-radius: 0.1rem; + flex-shrink: 0; + margin-bottom: 0.16rem; + } + + // 用户头像 + &__avatar { + width: 0.3rem; + height: 0.3rem; + border-radius: 50%; + background: $bg-main; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + color: $text-middle; + + svg { + width: 0.18rem; + height: 0.18rem; + } + } + + // 状态标签 + &__status-tag { + font-size: 0.12rem; + color: $accent; + background: rgba(79, 194, 201, 0.1); + padding: 0.03rem 0.1rem; + border-radius: 0.04rem; + white-space: nowrap; + flex-shrink: 0; + } + + // 状态提示文字 + &__status-text { + font-size: 0.12rem; + color: $text-middle; + flex: 1; + min-width: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + // 开始按钮 + &__start-btn { + height: 0.3rem; + padding: 0 0.14rem; + background: $text-dark; + color: $bg-white; + border: none; + border-radius: 0.15rem; + font-size: 0.12rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + line-height: 0.3rem; + white-space: nowrap; + flex-shrink: 0; + + &:hover { + opacity: 0.85; + } + } + + // 右侧工具按钮区 + &__tools { + display: flex; + align-items: center; + gap: 0.06rem; + flex-shrink: 0; + } + + // 工具按钮 + &__tool-btn { + width: 0.28rem; + height: 0.28rem; + border: none; + background: transparent; + cursor: pointer; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + color: $text-middle; + border-radius: 0.06rem; + transition: all 0.2s ease; + + svg { + width: 0.18rem; + height: 0.18rem; + } + + &:hover { + background: $bg-main; + color: $text-dark; + } + } + + // ==================== 中间聊天记录区域 ==================== + &__chat-area { + flex: 1; + overflow-y: auto; + padding: 0.16rem 0.1rem; + margin-bottom: 0.1rem; + + // 自定义滚动条 + &::-webkit-scrollbar { + width: 4px; + } + + &::-webkit-scrollbar-thumb { + background: $border-color; + border-radius: 2px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + } + + // ==================== 对话消息样式 ==================== + + // 对话行 + &__chat-row { + margin-bottom: 0.14rem; + + // 用户消息 — 右对齐 + &--user { + display: flex; + justify-content: flex-end; + } + } + + // 对话气泡 + &__chat-bubble { + display: inline-block; + max-width: 85%; + font-size: 0.14rem; + color: $text-dark; + line-height: 1.7; + padding: 0.1rem 0.16rem; + border-radius: 0.1rem; + background: $bg-white; + word-break: break-word; + + // 用户消息气泡 — 深色背景 + &--user { + background: $bg-main; + border: 1px solid $border-color; + } + + // AI 思考中的加载气泡 + &--loading { + color: $text-middle; + font-style: italic; + display: flex; + align-items: center; + gap: 0.06rem; + } + } + + // AI 思考中的转圈加载图标 + &__loading-icon { + color: $accent; + font-size: 0.16rem; + vertical-align: middle; + } + + // ==================== 底部固定输入框 ==================== + &__input-bar { + display: flex; + align-items: center; + gap: 0.1rem; + padding: 0.12rem 0.16rem; + background: $bg-white; + border-radius: 0.1rem; + border: 1px solid $border-color; + flex-shrink: 0; + } + + // 输入框 + &__input { + flex: 1; + border: none; + outline: none; + font-size: 0.13rem; + color: $text-dark; + background: transparent; + line-height: 0.3rem; + + &::placeholder { + color: $text-light; + } + } + + // 发送按钮 + &__send-btn { + width: 0.32rem; + height: 0.32rem; + border: none; + background: transparent; + cursor: pointer; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + color: $text-dark; + flex-shrink: 0; + transition: all 0.2s ease; + + svg { + width: 0.2rem; + height: 0.2rem; + } + + &:hover { + color: $accent; + } + } } diff --git a/src/assets/styles/pages/resume-detail.scss b/src/assets/styles/pages/resume-detail.scss index 6c2158e..1472144 100644 --- a/src/assets/styles/pages/resume-detail.scss +++ b/src/assets/styles/pages/resume-detail.scss @@ -439,8 +439,9 @@ align-items: center; justify-content: flex-end; gap: 0.1rem; - margin-top: 0.18rem; - padding-top: 0.14rem; + margin-top: 0.10rem; + padding-bottom: 0.14rem; + } // 问题类型按钮组(三选一) diff --git a/src/assets/styles/pages/resume.scss b/src/assets/styles/pages/resume.scss index 2a2e0ec..c435a77 100644 --- a/src/assets/styles/pages/resume.scss +++ b/src/assets/styles/pages/resume.scss @@ -163,8 +163,8 @@ // 弹出菜单 &__popup { position: absolute; - right: 0.3rem; - top: 0.1rem; + right: 0.46rem; + top: 0.18rem; background: $bg-white; border: 1px solid $border-color; border-radius: 0.1rem; @@ -201,3 +201,58 @@ } } } + +// ==================== 导出简历弹窗样式修正 ==================== +.resume-export-dialog { + font-size: 0.14rem; + .el-dialog__title { + font-size: 16px; + font-weight: 600; + } + + .el-dialog__body { + padding: 0.2rem 0.3rem 0.1rem; + } + + /* 修正 radio 组件在 100px 基准下的尺寸 */ + &__radio-group { + display: flex; + gap: 0.16rem; + + .el-radio { + font-size: 14px; + height: auto; + line-height: normal; + + .el-radio__inner { + width: 14px; + height: 14px; + } + + .el-radio__label { + font-size: 14px; + padding-left: 8px; + } + } + } + + .el-dialog__footer { + padding: 0.12rem 0.3rem 0.24rem; + + .el-button { + font-size: 13px; + padding: 8px 20px; + border-radius: 6px; + } + + .el-button--primary { + background: $btn-dark; + border-color: $btn-dark; + + &:hover { + background: $btn-dark-hover; + border-color: $btn-dark-hover; + } + } + } +} diff --git a/src/assets/styles/variables.scss b/src/assets/styles/variables.scss index 5c36e4f..95a9207 100644 --- a/src/assets/styles/variables.scss +++ b/src/assets/styles/variables.scss @@ -11,6 +11,9 @@ $selected-color: #F6FCFC; // 页面主背景色 $bg-main: #F3F4F5; +// 页面中间色景色(用于页面主题色背景和白色背景分隔,用于某些模块组件的组件外层背景等) +$bg-middle: #E6E6E6; + // 白色背景(卡片、输入框等) $bg-white: #FFFFFF; diff --git a/src/components/AgentChatJobList.vue b/src/components/AgentChatJobList.vue new file mode 100644 index 0000000..92899f1 --- /dev/null +++ b/src/components/AgentChatJobList.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/components/AgentMatchJobAdd.vue b/src/components/AgentMatchJobAdd.vue new file mode 100644 index 0000000..b05a55b --- /dev/null +++ b/src/components/AgentMatchJobAdd.vue @@ -0,0 +1,134 @@ + + + + + diff --git a/src/components/AgentSettingsPanel.vue b/src/components/AgentSettingsPanel.vue new file mode 100644 index 0000000..b6ba9b0 --- /dev/null +++ b/src/components/AgentSettingsPanel.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/src/components/AgentSetupWizard.vue b/src/components/AgentSetupWizard.vue new file mode 100644 index 0000000..9a4cd6e --- /dev/null +++ b/src/components/AgentSetupWizard.vue @@ -0,0 +1,472 @@ + + + + + diff --git a/src/components/AiChat.vue b/src/components/AiChat.vue index 2baaff5..f02a90a 100644 --- a/src/components/AiChat.vue +++ b/src/components/AiChat.vue @@ -25,27 +25,30 @@ - -
-
{{ msg.content }}
-
- - -
+ +
{{ q }}
+ + +
+
+
+ + +
@@ -55,8 +58,9 @@ class="ai-chat__input" placeholder="搜索职位、公司或关键词..." @keyup.enter="sendMessage" + :disabled="aiLoading" /> - @@ -67,8 +71,26 @@ diff --git a/src/components/JobResumeCustomDialog.vue b/src/components/JobResumeCustomDialog.vue index 9c98fd1..e78e928 100644 --- a/src/components/JobResumeCustomDialog.vue +++ b/src/components/JobResumeCustomDialog.vue @@ -286,9 +286,7 @@ -
-
AI正在思考中...
-
+
@@ -307,7 +305,7 @@
- +
@@ -318,7 +316,7 @@ - - + @@ -299,6 +299,14 @@ const showFeedbackDialog = ref(false) /** 当前操作的职位 ID(用于提交问题反馈) */ const feedbackJobId = ref(null) +/** 当前问助手的岗位 ID(传给 AiChat 组件) */ +const currentAskJobId = ref('') + +/** 点击"问助手"按钮,传入岗位 ID 给 AiChat */ +function askAssistant(job: JobItem) { + currentAskJobId.value = job.id +} + // ==================== 收藏统计 ==================== /** 收藏总数(用于 Tab 标签显示) */ diff --git a/src/views/Resume.vue b/src/views/Resume.vue index a57a2e6..75452c0 100644 --- a/src/views/Resume.vue +++ b/src/views/Resume.vue @@ -73,15 +73,53 @@ + + + + + + + + PDF 简历 + Word 简历 + + + + + +
+ +