424 lines
27 KiB
Vue
424 lines
27 KiB
Vue
<template>
|
||
<!-- 设置弹窗 — 通过 Teleport 挂载到 body,避免被父组件样式影响 -->
|
||
<Teleport to="body">
|
||
<!-- 遮罩层 — 点击关闭弹窗 -->
|
||
<div v-if="modelValue" class="settings-dialog-overlay" @click="$emit('update:modelValue', false)">
|
||
<!-- 弹窗主体 — 阻止点击冒泡到遮罩层 -->
|
||
<div class="settings-dialog" @click.stop>
|
||
<!-- 右上角关闭按钮 -->
|
||
<span class="settings-dialog__close" @click="$emit('update:modelValue', false)">✕</span>
|
||
|
||
<!-- 左侧导航栏 -->
|
||
<div class="settings-dialog__sidebar">
|
||
<!-- 主导航 Tab 列表 -->
|
||
<div class="settings-dialog__nav">
|
||
<div
|
||
v-for="tab in tabs"
|
||
:key="tab.key"
|
||
class="settings-dialog__nav-item"
|
||
:class="{ 'settings-dialog__nav-item--active': activeTab === tab.key }"
|
||
@click="activeTab = tab.key"
|
||
>
|
||
<span class="settings-dialog__nav-icon">{{ tab.icon }}</span>
|
||
<span>{{ tab.label }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 底部操作区 — 隐私协议 + 退出登录 -->
|
||
<div class="settings-dialog__bottom-actions">
|
||
<!-- 用户隐私协议按钮 — 点击切换到隐私协议 tab -->
|
||
<button
|
||
class="settings-dialog__bottom-btn"
|
||
:class="{ 'settings-dialog__bottom-btn--active': activeTab === 'privacy' }"
|
||
@click="activeTab = 'privacy'"
|
||
>
|
||
用户隐私协议
|
||
</button>
|
||
<!-- 退出登录按钮 — 点击弹出确认弹窗 -->
|
||
<button class="settings-dialog__bottom-btn settings-dialog__bottom-btn--danger" @click="showLogout = true">
|
||
退出登录
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧内容区 — 根据 activeTab 切换显示 -->
|
||
<div class="settings-dialog__content">
|
||
<!-- Tab: 账号与安全 — 显示手机号、注销账号 -->
|
||
<template v-if="activeTab === 'account'">
|
||
<h2 class="settings-dialog__content-title">账号与安全</h2>
|
||
<div class="settings-dialog__section">
|
||
<div class="settings-dialog__section-label">手机号</div>
|
||
<p class="settings-dialog__section-value">{{ userPhone }}</p>
|
||
</div>
|
||
<div class="settings-dialog__danger-section">
|
||
<div class="settings-dialog__danger-title">注销我的账号</div>
|
||
<div class="settings-dialog__danger-row">
|
||
<p class="settings-dialog__danger-desc">永久删除你的账号及所有相关数据</p>
|
||
<button class="settings-dialog__danger-btn" @click="handleDeleteAccount">注销账号</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- Tab: 会员 — 显示当前会员信息、订阅管理 -->
|
||
<template v-if="activeTab === 'member'">
|
||
<h2 class="settings-dialog__content-title">会员</h2>
|
||
<div class="settings-dialog__section-label" style="margin-bottom: 0.12rem;">当前会员</div>
|
||
<div class="settings-dialog__member-card">
|
||
<div class="settings-dialog__member-header">
|
||
<div class="settings-dialog__member-title-row">
|
||
<span class="settings-dialog__member-name">正式会员</span>
|
||
<span
|
||
class="settings-dialog__member-badge"
|
||
:class="{ 'settings-dialog__member-badge--inactive': !memberStatus.isMember }"
|
||
>
|
||
{{ memberStatus.isMember ? '已开通' : '未开通' }}
|
||
</span>
|
||
</div>
|
||
<span class="settings-dialog__member-terms" @click="handleMemberTerms">会员条款</span>
|
||
</div>
|
||
<div class="settings-dialog__member-info-row">
|
||
<!-- 已开通:显示到期时间和剩余天数 -->
|
||
<span v-if="memberStatus.isMember" class="settings-dialog__member-price">
|
||
<span class="settings-dialog__member-expire-line">到期时间:{{ memberExpireDateTime }}</span>
|
||
<span class="settings-dialog__member-remain-line">剩余 {{ memberRemainDays }} 天</span>
|
||
</span>
|
||
<!-- 未开通:显示价格 -->
|
||
<span v-else class="settings-dialog__member-price">
|
||
¥19.99/月
|
||
</span>
|
||
</div>
|
||
</div>
|
||
<div class="settings-dialog__member-issue">
|
||
<!-- <div class="settings-dialog__member-issue-title">订阅状态异常?</div>-->
|
||
<!-- <p class="settings-dialog__member-issue-desc">-->
|
||
<!-- 如果你已经和完成了付款或更改了订阅但是没有看到最新状态,你可以尝试更新状态或联系我们获取帮助。-->
|
||
<!-- </p>-->
|
||
<!-- <div class="settings-dialog__member-issue-actions">-->
|
||
<!-- <button class="settings-dialog__member-issue-btn" @click="handleRefreshStatus">更新状态</button>-->
|
||
<!-- <button class="settings-dialog__member-issue-btn" @click="handleContactUs">联系我们</button>-->
|
||
<!-- </div>-->
|
||
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<!-- Tab: 岗位更新提醒 — 目标岗位、即时提醒开关、提醒频率 -->
|
||
<template v-if="activeTab === 'reminder'">
|
||
<!-- <h2 class="settings-dialog__content-title">岗位更新提醒</h2>-->
|
||
<h2 class="settings-dialog__content-title">目标岗位设置</h2>
|
||
<div class="settings-dialog__reminder-block">
|
||
<div class="settings-dialog__reminder-block-title-row">
|
||
<span class="settings-dialog__reminder-block-title">目标岗位</span>
|
||
<button class="settings-dialog__reminder-edit-btn" @click="handleEditTarget">编辑</button>
|
||
</div>
|
||
<div class="settings-dialog__reminder-target">
|
||
<div class="settings-dialog__reminder-group" v-if="intentionCategoryNames.length">
|
||
<span class="settings-dialog__reminder-group-label">岗位</span>
|
||
<div class="settings-dialog__reminder-tags">
|
||
<span class="settings-dialog__reminder-tag" v-for="name in intentionCategoryNames" :key="name">{{ name }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="settings-dialog__reminder-group" v-if="intentionIndustryNames.length">
|
||
<span class="settings-dialog__reminder-group-label">行业</span>
|
||
<div class="settings-dialog__reminder-tags">
|
||
<span class="settings-dialog__reminder-tag" v-for="name in intentionIndustryNames" :key="name">{{ name }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="settings-dialog__reminder-group" v-if="intentionRegionNames.length">
|
||
<span class="settings-dialog__reminder-group-label">地区</span>
|
||
<div class="settings-dialog__reminder-tags">
|
||
<span class="settings-dialog__reminder-tag" v-for="name in intentionRegionNames" :key="name">{{ name }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="settings-dialog__reminder-group">
|
||
<span class="settings-dialog__reminder-group-label">类型</span>
|
||
<div class="settings-dialog__reminder-tags">
|
||
<span class="settings-dialog__reminder-tag">{{ intentionEmploymentLabel }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- <div class="settings-dialog__reminder-block">-->
|
||
<!-- <div class="settings-dialog__reminder-block-title">即时岗位提醒</div>-->
|
||
<!-- <div class="settings-dialog__reminder-row">-->
|
||
<!-- <div class="settings-dialog__reminder-info">-->
|
||
<!-- <div class="settings-dialog__reminder-label">开启即时岗位更新提醒</div>-->
|
||
<!-- <div class="settings-dialog__reminder-desc">-->
|
||
<!-- 抢先申请 —— 在岗位发布后一小时内,即可收到为你量身定制的最新职位提醒-->
|
||
<!-- </div>-->
|
||
<!-- </div>-->
|
||
<!-- <el-switch v-model="reminders.instant" active-color="#4FC2C9" />-->
|
||
<!-- </div>-->
|
||
<!-- </div>-->
|
||
<!-- <div class="settings-dialog__reminder-block">-->
|
||
<!-- <div class="settings-dialog__reminder-block-title">岗位更新提醒频率</div>-->
|
||
<!-- <div class="settings-dialog__reminder-row">-->
|
||
<!-- <div class="settings-dialog__reminder-info">-->
|
||
<!-- <div class="settings-dialog__reminder-desc">-->
|
||
<!-- 会员用户每天可接收无限次岗位更新提醒,免费用户每天最多接收 1 次。-->
|
||
<!-- </div>-->
|
||
<!-- </div>-->
|
||
<!-- <el-select v-model="reminders.frequency" style="width: 1.2rem;">-->
|
||
<!-- <el-option label="1次/天" value="1" />-->
|
||
<!-- <el-option label="2次/天" value="2" />-->
|
||
<!-- <el-option label="5次/天" value="5" />-->
|
||
<!-- <el-option label="无限次" value="unlimited" />-->
|
||
<!-- </el-select>-->
|
||
<!-- </div>-->
|
||
<!-- </div>-->
|
||
</template>
|
||
<!-- Tab: 用户隐私协议 — 长文本,可滚动查看 -->
|
||
<template v-if="activeTab === 'privacy'">
|
||
<h2 class="settings-dialog__content-title">用户隐私协议</h2>
|
||
<div class="settings-dialog__privacy-content">
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>一、引言</h4>
|
||
<p>欢迎使用 Offer派(以下简称"本平台"或"我们")。我们深知个人信息对您的重要性,并会尽全力保护您的个人信息安全。我们致力于维持您对我们的信任,恪守以下原则保护您的个人信息:权责一致原则、目的明确原则、选择同意原则、最少够用原则、确保安全原则、主体参与原则、公开透明原则等。同时,我们承诺将按照业界成熟的安全标准,采取相应的安全保护措施来保护您的个人信息。请您在使用本平台服务前,仔细阅读并了解本隐私政策。</p>
|
||
</div>
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>二、我们如何收集和使用您的个人信息</h4>
|
||
<p>个人信息是指以电子或者其他方式记录的能够单独或者与其他信息结合识别特定自然人身份或者反映特定自然人活动情况的各种信息。我们仅会出于本政策所述的以下目的,收集和使用您的个人信息:</p>
|
||
<p>1. 注册与登录:当您注册本平台账号时,我们会收集您的手机号码用于创建账号和身份验证。您也可以选择填写昵称、头像等个人资料来完善您的账户信息。手机号码属于敏感信息,收集此类信息是为了满足相关法律法规的网络实名制要求,如果您不提供手机号码,将无法使用本平台的服务。</p>
|
||
<p>2. 简历管理:当您使用简历管理功能时,我们会收集您主动填写的简历信息,包括但不限于:姓名、性别、出生日期、教育经历、工作经历、项目经验、技能特长、求职意向、期望薪资、期望工作地点等。这些信息将用于为您提供精准的岗位推荐服务。您可以随时在个人中心修改或删除这些信息。</p>
|
||
<p>3. 岗位推荐与搜索:当您使用岗位搜索和推荐功能时,我们会收集您的搜索关键词、浏览记录、收藏记录、投递记录等行为数据,以便为您提供更加精准和个性化的岗位推荐。我们也会根据您的求职意向和简历信息,通过算法模型为您匹配合适的职位。</p>
|
||
<p>4. AI 助手服务:当您使用 AI 助手功能时,我们会收集您与 AI 的对话内容,用于提供智能问答、简历优化建议、面试辅导等服务。对话内容将被加密存储,并仅用于改善服务质量。我们不会将您的对话内容用于其他商业目的。</p>
|
||
<p>5. 消息通知:为了及时向您推送岗位更新、申请状态变更等重要信息,我们可能会收集您的设备标识符、推送令牌等信息,用于实现消息推送功能。您可以在设置中随时关闭消息推送。</p>
|
||
</div>
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>三、我们如何共享、转让、公开披露您的个人信息</h4>
|
||
<p>1. 共享:我们不会与任何公司、组织和个人共享您的个人信息,但以下情况除外:(1)在获取明确同意的情况下共享:获得您的明确同意后,我们会与其他方共享您的个人信息。(2)我们可能会根据法律法规规定,或按政府主管部门的强制性要求,对外共享您的个人信息。(3)与授权合作伙伴共享:仅为实现本隐私政策中声明的目的,我们的某些服务将由授权合作伙伴提供。我们可能会与合作伙伴共享您的某些个人信息,以提供更好的客户服务和用户体验。我们仅会出于合法、正当、必要、特定、明确的目的共享您的个人信息,并且只会共享提供服务所必要的个人信息。</p>
|
||
<p>2. 转让:我们不会将您的个人信息转让给任何公司、组织和个人,但以下情况除外:(1)在获取明确同意的情况下转让:获得您的明确同意后,我们会向其他方转让您的个人信息。(2)在涉及合并、收购或破产清算时,如涉及到个人信息转让,我们会在要求新的持有您个人信息的公司、组织继续受此隐私政策的约束,否则我们将要求该公司、组织重新向您征求授权同意。</p>
|
||
<p>3. 公开披露:我们仅会在以下情况下,公开披露您的个人信息:(1)获得您明确同意后。(2)基于法律的披露:在法律、法律程序、诉讼或政府主管部门强制性要求的情况下,我们可能会公开披露您的个人信息。</p>
|
||
</div>
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>四、我们如何保护您的个人信息</h4>
|
||
<p>1. 我们已使用符合业界标准的安全防护措施保护您提供的个人信息,防止数据遭到未经授权的访问、公开披露、使用、修改、损坏或丢失。我们会采取一切合理可行的措施,保护您的个人信息。例如,在您的浏览器与服务之间交换数据时受 SSL 加密保护;我们同时对网站提供 HTTPS 安全浏览方式;我们会使用加密技术确保数据的保密性;我们会使用受信赖的保护机制防止数据遭到恶意攻击;我们会部署访问控制机制,确保只有授权人员才可访问个人信息;以及我们会举办安全和隐私保护培训课程,加强员工对于保护个人信息重要性的认识。</p>
|
||
<p>2. 我们会采取一切合理可行的措施,确保未收集无关的个人信息。我们只会在达成本政策所述目的所需的期限内保留您的个人信息,除非需要延长保留期或受到法律的允许。</p>
|
||
<p>3. 互联网并非绝对安全的环境,而且电子邮件、即时通讯、及与其他用户的交流方式并未加密,我们强烈建议您不要通过此类方式发送个人信息。请使用复杂密码,协助我们保证您的账号安全。</p>
|
||
<p>4. 互联网环境并非百分之百安全,我们将尽力确保或担保您发送给我们的任何信息的安全性。如果我们的物理、技术、或管理防护设施遭到破坏,导致信息被非授权访问、公开披露、篡改、或毁坏,导致您的合法权益受损,我们将承担相应的法律责任。</p>
|
||
<p>5. 在不幸发生个人信息安全事件后,我们将按照法律法规的要求,及时向您告知:安全事件的基本情况和可能的影响、我们已采取或将要采取的处置措施、您可自主防范和降低风险的建议、对您的补救措施等。我们将及时将事件相关情况以邮件、信函、电话、推送通知等方式告知您,难以逐一告知个人信息主体时,我们会采取合理、有效的方式发布公告。</p>
|
||
</div>
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>五、您的权利</h4>
|
||
<p>按照中国相关的法律、法规、标准,以及其他国家、地区的通行做法,我们保障您对自己的个人信息行使以下权利:</p>
|
||
<p>1. 访问您的个人信息:您有权访问您的个人信息,法律法规规定的例外情况除外。如果您想行使数据访问权,可以通过以下方式自行访问:登录本平台,进入"个人资料"或"简历管理"页面,即可查看您的个人信息。</p>
|
||
<p>2. 更正您的个人信息:当您发现我们处理的关于您的个人信息有错误时,您有权要求我们做出更正。您可以通过上述访问方式提出更正申请。</p>
|
||
<p>3. 删除您的个人信息:在以下情形中,您可以向我们提出删除个人信息的请求:(1)如果我们处理个人信息的行为违反法律法规。(2)如果我们收集、使用您的个人信息,却未征得您的同意。(3)如果我们处理个人信息的行为违反了与您的约定。(4)如果您不再使用我们的产品或服务,或您注销了账号。(5)如果我们不再为您提供产品或服务。</p>
|
||
<p>4. 注销账户:您随时可注销此前注册的账户,您可以通过"设置 - 账号与安全 - 注销账号"进行操作。在注销账户之后,我们将停止为您提供产品或服务,并依据您的要求,删除您的个人信息,法律法规另有规定的除外。</p>
|
||
<p>5. 改变您授权同意的范围:每个业务功能需要一些基本的个人信息才能得以完成。对于额外收集的个人信息的收集和使用,您可以随时给予或收回您的授权同意。您可以通过关闭相应功能的方式来撤回授权。当您收回同意后,我们将不再处理相应的个人信息。但您收回同意的决定,不会影响此前基于您的授权而开展的个人信息处理。</p>
|
||
</div>
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>六、我们如何处理未成年人的个人信息</h4>
|
||
<p>我们的产品和服务主要面向成年人。如果没有父母或监护人的同意,未成年人不应创建自己的用户账户。如果我们发现在未事先获得可证实的父母或法定监护人同意的情况下收集了未成年人的个人信息,则会设法尽快删除相关数据。对于经父母或法定监护人同意而收集未成年人个人信息的情况,我们只会在受到法律允许、父母或监护人明确同意或者保护未成年人所必要的情况下使用或公开披露此信息。</p>
|
||
</div>
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>七、本隐私政策如何更新</h4>
|
||
<p>我们可能适时会对本隐私政策进行调整或变更,本隐私政策的任何更新将以标注更新时间的方式公布在本平台上,除法律法规或监管规定另有强制性规定外,经调整或变更的内容一经通知或公布后的7日后生效。如您在隐私政策调整或变更后继续使用我们提供的任一服务或访问我们相关网站的,我们相信这代表您已充分阅读、理解并接受修改后的隐私政策并受其约束。</p>
|
||
</div>
|
||
<div class="settings-dialog__privacy-section">
|
||
<h4>八、如何联系我们</h4>
|
||
<p>如果您对本隐私政策有任何疑问、意见或建议,可以通过以下方式与我们联系:发送邮件至 privacy@offerpai.com,或通过本平台内的"反馈"功能联系我们。一般情况下,我们将在15个工作日内回复。如果您对我们的回复不满意,特别是我们的个人信息处理行为损害了您的合法权益,您还可以向网信部门、电信主管部门、公安部门等监管部门进行投诉或举报,或通过向被告住所地有管辖权的法院提起诉讼来寻求解决方案。</p>
|
||
<p>本隐私政策的最终解释权归本平台所有。</p>
|
||
<p style="margin-top: 0.16rem; color: #999;">最后更新日期:2026年3月1日</p>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 退出登录确认弹窗 — 放在 Teleport 内部,确保层级在 overlay 之上 -->
|
||
<el-dialog v-model="showLogout" title="退出登录" width="3.6rem" style="line-height: 0.2rem" :close-on-click-modal="true" :append-to-body="false" :z-index="2100">
|
||
<p style="font-size: 0.14rem; color: #555; text-align: center;">确定要退出当前账号吗?</p>
|
||
<template #footer>
|
||
<el-button @click="showLogout = false">取消</el-button>
|
||
<el-button type="danger" @click="handleLogout">确认退出</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 求职目标设置弹窗 -->
|
||
<JobGoalDialog v-model="showGoalDialog" />
|
||
|
||
<!-- 注销账号弹窗 -->
|
||
<SettingsDeleteAccountDialog v-model="showDeleteAccount" />
|
||
|
||
<!-- 邀请注册送会员弹窗 -->
|
||
<SettingsInviteDialog v-model="showInviteDialog" />
|
||
</Teleport>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive, watch, computed } from 'vue'
|
||
import { useRouter } from 'vue-router'
|
||
import { useStore } from 'vuex'
|
||
import { logout } from '@/api/auth'
|
||
import { fetchMemberStatus, type MemberStatus } from '@/api/member'
|
||
import { timestampToLocalDateTime, timestampDiffDays } from '@/utils/time'
|
||
import JobGoalDialog from './JobGoalDialog.vue'
|
||
import { resolveRegionName } from '@/utils/region'
|
||
import { resolveIndustryName } from '@/utils/industry'
|
||
import { resolveJobCategoryName } from '@/utils/jobCategory'
|
||
import SettingsDeleteAccountDialog from './SettingsDeleteAccountDialog.vue'
|
||
import SettingsInviteDialog from './SettingsInviteDialog.vue'
|
||
|
||
/** 组件 Props — 控制弹窗显示/隐藏,可指定初始 Tab */
|
||
const props = defineProps<{ modelValue: boolean; initialTab?: string }>()
|
||
|
||
/** 组件 Emits — 通知父组件更新 modelValue */
|
||
const emit = defineEmits<{ (e: 'update:modelValue', value: boolean): void }>()
|
||
|
||
/** 路由实例 — 退出登录后跳转首页 */
|
||
const router = useRouter()
|
||
const store = useStore()
|
||
|
||
/** 左侧导航 Tab 配置 */
|
||
const tabs = [
|
||
{ key: 'account', label: '账号与安全', icon: '👤' },
|
||
{ key: 'member', label: '会员', icon: '🏅' },
|
||
{ key: 'reminder', label: '目标岗位设置', icon: '🔔' },
|
||
]
|
||
|
||
/** 当前选中的 Tab */
|
||
const activeTab = ref('account')
|
||
|
||
/** 用户手机号 — 从全局 store 读取 */
|
||
const userPhone = computed(() => store.state.userInfo?.mobileNumber || '')
|
||
|
||
/** 退出登录确认弹窗的显示状态 */
|
||
const showLogout = ref(false)
|
||
|
||
/** 监听弹窗开关 — 打开时锁定背景页面滚动,关闭时恢复 */
|
||
watch(() => props.modelValue, (val) => {
|
||
document.body.style.overflow = val ? 'hidden' : ''
|
||
if (val && props.initialTab) {
|
||
activeTab.value = props.initialTab
|
||
}
|
||
})
|
||
|
||
/** 岗位更新提醒的配置项 */
|
||
const reminders = reactive({
|
||
instant: true, // 是否开启即时岗位提醒
|
||
frequency: 'unlimited', // 提醒频率:1/2/5/unlimited
|
||
})
|
||
|
||
/** 求职目标弹窗显示状态 */
|
||
const showGoalDialog = ref(false)
|
||
|
||
/** 注销账号弹窗显示状态 */
|
||
const showDeleteAccount = ref(false)
|
||
|
||
/** 邀请注册弹窗显示状态 */
|
||
const showInviteDialog = ref(false)
|
||
|
||
/** 会员状态数据 */
|
||
const memberStatus = reactive<MemberStatus>({
|
||
isMember: false,
|
||
expireTime: undefined,
|
||
createTime: undefined,
|
||
updateTime: undefined,
|
||
})
|
||
|
||
/** 会员到期时间(格式化显示) */
|
||
const memberExpireDateTime = computed(() => {
|
||
return timestampToLocalDateTime(memberStatus.expireTime, 'returnMinute')
|
||
})
|
||
|
||
/** 会员剩余天数 */
|
||
const memberRemainDays = computed(() => {
|
||
return timestampDiffDays(memberStatus.expireTime)
|
||
})
|
||
|
||
/** 查询会员状态 */
|
||
const loadMemberStatus = async () => {
|
||
try {
|
||
const res = await fetchMemberStatus()
|
||
if (res.data) {
|
||
memberStatus.isMember = res.data.isMember ?? false
|
||
memberStatus.expireTime = res.data.expireTime
|
||
memberStatus.createTime = res.data.createTime
|
||
memberStatus.updateTime = res.data.updateTime
|
||
}
|
||
} catch {
|
||
// 查询失败保持默认未开通状态
|
||
}
|
||
}
|
||
|
||
/** 岗位名称列表 */
|
||
const intentionCategoryNames = computed(() => {
|
||
const ids = store.state.jobIntention.categoryIds || []
|
||
return ids.map((id: number) => resolveJobCategoryName(id))
|
||
})
|
||
|
||
/** 行业名称列表 */
|
||
const intentionIndustryNames = computed(() => {
|
||
const ids = store.state.jobIntention.industryIds || []
|
||
return ids.map((id: number) => resolveIndustryName(id))
|
||
})
|
||
|
||
/** 地区名称列表 */
|
||
const intentionRegionNames = computed(() => {
|
||
const codes = store.state.jobIntention.regionCodes || []
|
||
return codes.map((code: string) => resolveRegionName(code))
|
||
})
|
||
|
||
/** 就业类型标签 */
|
||
const intentionEmploymentLabel = computed(() => {
|
||
return store.state.jobIntention.employmentType === 1 ? '实习' : '全职'
|
||
})
|
||
|
||
/** 编辑目标岗位 — 打开求职目标弹窗 */
|
||
const handleEditTarget = () => {
|
||
showGoalDialog.value = true
|
||
}
|
||
|
||
/** 弹窗打开时加载求职意向数据和会员状态 */
|
||
watch(() => props.modelValue, (val) => {
|
||
if (val && store.state.isAuthenticated) {
|
||
store.dispatch('loadCommonData')
|
||
store.dispatch('loadJobIntention')
|
||
loadMemberStatus()
|
||
}
|
||
})
|
||
|
||
/** 注销账号 — 打开注销账号弹窗 */
|
||
const handleDeleteAccount = () => {
|
||
showDeleteAccount.value = true
|
||
}
|
||
|
||
/** 管理订阅 */
|
||
const handleManageSubscription = () => {
|
||
ElMessage.info('管理订阅功能开发中')
|
||
}
|
||
|
||
/** 查看会员条款 */
|
||
const handleMemberTerms = () => {
|
||
ElMessage.info('会员条款页面开发中')
|
||
}
|
||
|
||
/** 刷新订阅状态 */
|
||
const handleRefreshStatus = () => {
|
||
ElMessage.success('状态已更新')
|
||
}
|
||
|
||
/** 联系客服 */
|
||
const handleContactUs = () => {
|
||
ElMessage.info('联系客服功能开发中')
|
||
}
|
||
|
||
/** 退出登录 — 调用接口,后端会清除 Cookie,关闭弹窗,跳转 jobs 页 */
|
||
const handleLogout = async () => {
|
||
try {
|
||
const res = await logout()
|
||
if (res.code === '0') {
|
||
ElMessage.success('已退出登录')
|
||
}
|
||
} catch {
|
||
// 即使接口失败也关闭弹窗
|
||
}
|
||
store.commit('SET_AUTHENTICATED', false)
|
||
showLogout.value = false
|
||
emit('update:modelValue', false)
|
||
router.push('/')
|
||
}
|
||
</script>
|