diff --git a/app/components/HjcUserBar.vue b/app/components/HjcUserBar.vue index b302800..8432f11 100644 --- a/app/components/HjcUserBar.vue +++ b/app/components/HjcUserBar.vue @@ -4,6 +4,7 @@ {{ displayName }} 我的订单 企业资质 + 修改密码 diff --git a/server/api/tender/password/apply.post.ts b/server/api/tender/password/apply.post.ts new file mode 100644 index 0000000..8137a4e --- /dev/null +++ b/server/api/tender/password/apply.post.ts @@ -0,0 +1,33 @@ +import { $fetch } from 'ofetch' +import { createError, defineEventHandler, readBody } from 'h3' +import { useRuntimeConfig } from '#imports' +import { getTenantFromContext } from '../../../utils/tenant' + +/** + * 密码找回-提交申请(**匿名**,企业未登录时提交) + * POST /api/tender/password/apply { enterpriseName, creditCode, newPassword, confirmPassword, handbookUrl } + * 代理到 mp-api /api/hjc/auth/password/apply。 + * + * 注意:该接口对「企业不存在 / 双要素不匹配 / 已有待审核申请」一律返回**同一句话且 data 为 null**, + * 以免暴露某个企业是否在本平台注册过。前端因此不能靠 message 区分结果,只提示「已提交」并引导去查进度。 + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig() + const ctx = getTenantFromContext(event, config) + const body = await readBody(event) + + try { + return await $fetch('/hjc/auth/password/apply', { + baseURL: config.public.modulesApiBase, + method: 'POST', + headers: { TenantId: ctx.tenantId }, + query: { TenantId: ctx.tenantId }, + body + }) + } catch (error: any) { + throw createError({ + statusCode: error?.statusCode || error?.response?.status || 502, + statusMessage: error?.data?.message || error?.statusMessage || '提交失败' + }) + } +}) diff --git a/server/api/tender/password/change.put.ts b/server/api/tender/password/change.put.ts new file mode 100644 index 0000000..08ef259 --- /dev/null +++ b/server/api/tender/password/change.put.ts @@ -0,0 +1,38 @@ +import { $fetch } from 'ofetch' +import { createError, defineEventHandler, readBody, getHeader, getCookie } from 'h3' +import { useRuntimeConfig } from '#imports' +import { getTenantFromContext } from '../../../utils/tenant' + +/** + * 修改密码(**需登录态**,双因子:旧密码 + 账号绑定手机号短信验证码) + * PUT /api/tender/password/change { oldPassword, smsCode, newPassword, confirmPassword } + * 代理到 mp-api /api/hjc/auth/password/change。 + * + * 原样透传 ApiResult:后端对「旧密码不正确 / 短信验证码不正确 / 密码强度不够」都有明确文案, + * 由前端直接展示。 + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig() + const ctx = getTenantFromContext(event, config) + const body = await readBody(event) + const cookieToken = getCookie(event, 'hjc_token') + const auth = getHeader(event, 'authorization') || (cookieToken ? `Bearer ${cookieToken}` : null) + + try { + return await $fetch('/hjc/auth/password/change', { + baseURL: config.public.modulesApiBase, + method: 'PUT', + headers: { + TenantId: ctx.tenantId, + ...(auth ? { Authorization: auth } : {}) + }, + query: { TenantId: ctx.tenantId }, + body + }) + } catch (error: any) { + throw createError({ + statusCode: error?.statusCode || error?.response?.status || 502, + statusMessage: error?.data?.message || error?.statusMessage || '修改密码失败' + }) + } +}) diff --git a/server/api/tender/password/sms.post.ts b/server/api/tender/password/sms.post.ts new file mode 100644 index 0000000..508c46c --- /dev/null +++ b/server/api/tender/password/sms.post.ts @@ -0,0 +1,36 @@ +import { $fetch } from 'ofetch' +import { createError, defineEventHandler, getHeader, getCookie } from 'h3' +import { useRuntimeConfig } from '#imports' +import { getTenantFromContext } from '../../../utils/tenant' + +/** + * 修改密码-发送短信验证码(**需登录态**) + * POST /api/tender/password/sms(无 body) + * 代理到 mp-api /api/hjc/auth/password/sms。 + * + * 收件号由后端从登录态里取核心实例上的手机号(账号绑定手机号),**前端不能指定号码**—— + * 否则任何人都能给任意手机号发短信。 + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig() + const ctx = getTenantFromContext(event, config) + const cookieToken = getCookie(event, 'hjc_token') + const auth = getHeader(event, 'authorization') || (cookieToken ? `Bearer ${cookieToken}` : null) + + try { + return await $fetch('/hjc/auth/password/sms', { + baseURL: config.public.modulesApiBase, + method: 'POST', + headers: { + TenantId: ctx.tenantId, + ...(auth ? { Authorization: auth } : {}) + }, + query: { TenantId: ctx.tenantId } + }) + } catch (error: any) { + throw createError({ + statusCode: error?.statusCode || error?.response?.status || 502, + statusMessage: error?.data?.message || error?.statusMessage || '验证码发送失败' + }) + } +}) diff --git a/server/api/tender/password/status.get.ts b/server/api/tender/password/status.get.ts new file mode 100644 index 0000000..479d1bb --- /dev/null +++ b/server/api/tender/password/status.get.ts @@ -0,0 +1,36 @@ +import { $fetch } from 'ofetch' +import { createError, defineEventHandler, getQuery } from 'h3' +import { useRuntimeConfig } from '#imports' +import { getTenantFromContext } from '../../../utils/tenant' + +/** + * 密码找回-查询进度(**匿名**) + * GET /api/tender/password/status?enterpriseName=&creditCode= + * 代理到 mp-api /api/hjc/auth/password/apply/status。 + * + * 返回的 data 为 null 表示「未查询到申请记录」(查不到企业与命中多条脏数据都归为这一种, + * 同样不区分企业是否存在);有记录时只含状态与时间,**不含材料与新密码**。 + */ +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig() + const ctx = getTenantFromContext(event, config) + const query = getQuery(event) + + try { + return await $fetch('/hjc/auth/password/apply/status', { + baseURL: config.public.modulesApiBase, + method: 'GET', + headers: { TenantId: ctx.tenantId }, + query: { + TenantId: ctx.tenantId, + enterpriseName: query.enterpriseName, + creditCode: query.creditCode + } + }) + } catch (error: any) { + throw createError({ + statusCode: error?.statusCode || error?.response?.status || 502, + statusMessage: error?.data?.message || error?.statusMessage || '查询失败' + }) + } +})