删除禁用账户功能及相关代码
- 删除个人资料标签页中的禁用/启用账户列表项 - 删除禁用账户对话框和启用账户对话框 - 删除反馈对话框(禁用账户后显示) - 删除账户状态相关的状态变量和计算属性 - 删除 handleAccountStatus、handleDisableAccountConfirm、handleEnableAccountConfirm 等处理函数 - 删除反馈相关的状态变量和处理函数(feedbackRating、feedbackReason、feedbackNote 等) - 从 API 模块中删除 disableAccount、enableAccount、submitFeedback 函数 - 删除账户状态对话框和星级评分的 CSS 样式
This commit is contained in:
parent
423e28c09c
commit
dfad1a1d80
@ -286,47 +286,6 @@ export const becomeDeveloper = async (teamName: string): Promise<{ success: bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 禁用账户
|
|
||||||
export const disableAccount = async (totpCode?: string): Promise<{ success: boolean; message?: string }> => {
|
|
||||||
try {
|
|
||||||
const response = await axios.post(
|
|
||||||
`/api/action/jcloud.api.account.disable_account`,
|
|
||||||
{ totp_code: totpCode || null },
|
|
||||||
{
|
|
||||||
headers: get_session_api_headers(),
|
|
||||||
withCredentials: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return { success: true, message: response.data?.message || '账户已禁用' }
|
|
||||||
} catch (error: any) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: error.response?.data?.detail || error.response?.data?.message || error.message || '禁用账户失败'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启用账户
|
|
||||||
export const enableAccount = async (): Promise<{ success: boolean; message?: string }> => {
|
|
||||||
try {
|
|
||||||
const response = await axios.post(
|
|
||||||
`/api/action/jcloud.api.account.enable_account`,
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
headers: get_session_api_headers(),
|
|
||||||
withCredentials: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return { success: true, message: response.data?.message || '账户已启用' }
|
|
||||||
} catch (error: any) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: error.response?.data?.detail || error.response?.data?.message || error.message || '启用账户失败'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新密码
|
// 更新密码
|
||||||
export const updatePassword = async (params: {
|
export const updatePassword = async (params: {
|
||||||
@ -553,29 +512,3 @@ export const disable2FA = async (totpCode: string): Promise<{ success: boolean;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交反馈
|
|
||||||
export const submitFeedback = async (team: string, message: string, note: string, rating: number, route?: string): Promise<{ success: boolean; message?: string }> => {
|
|
||||||
try {
|
|
||||||
const response = await axios.post(
|
|
||||||
`/api/action/jcloud.api.account.feedback`,
|
|
||||||
{
|
|
||||||
team,
|
|
||||||
message,
|
|
||||||
note,
|
|
||||||
rating,
|
|
||||||
route: route || null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headers: get_session_api_headers(),
|
|
||||||
withCredentials: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return { success: true, message: response.data?.message || '反馈已提交' }
|
|
||||||
} catch (error: any) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
message: error.response?.data?.detail || error.response?.data?.message || error.message || '提交反馈失败'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -107,25 +107,6 @@
|
|||||||
</n-thing>
|
</n-thing>
|
||||||
</n-list-item>
|
</n-list-item>
|
||||||
|
|
||||||
<!-- 禁用/启用账户 -->
|
|
||||||
<n-list-item>
|
|
||||||
<n-thing>
|
|
||||||
<template #header>
|
|
||||||
<span class="text-base font-medium">{{ accountStatusTitle }}</span>
|
|
||||||
</template>
|
|
||||||
<template #description>
|
|
||||||
<span class="text-sm text-gray-600">{{ accountStatusSubtitle }}</span>
|
|
||||||
</template>
|
|
||||||
<template #action>
|
|
||||||
<n-button
|
|
||||||
:type="teamEnabled ? 'error' : 'primary'"
|
|
||||||
@click="handleAccountStatus"
|
|
||||||
>
|
|
||||||
{{ accountStatusButtonLabel }}
|
|
||||||
</n-button>
|
|
||||||
</template>
|
|
||||||
</n-thing>
|
|
||||||
</n-list-item>
|
|
||||||
</n-list>
|
</n-list>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
|
||||||
@ -775,130 +756,6 @@
|
|||||||
</p>
|
</p>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
|
|
||||||
<!-- 禁用账户对话框 -->
|
|
||||||
<n-modal
|
|
||||||
v-model:show="showDisableAccountDialog"
|
|
||||||
preset="dialog"
|
|
||||||
type="warning"
|
|
||||||
:title="t('Disable Account')"
|
|
||||||
:positive-text="t('Disable Account')"
|
|
||||||
:positive-button-props="{ type: 'error' }"
|
|
||||||
:loading="disableAccountLoading"
|
|
||||||
:mask-closable="true"
|
|
||||||
:close-on-esc="true"
|
|
||||||
@positive-click="handleDisableAccountConfirm"
|
|
||||||
>
|
|
||||||
<div class="account-status-dialog-content">
|
|
||||||
<p class="account-status-dialog-title">{{ t('After confirming this action:') }}</p>
|
|
||||||
<ul class="account-status-dialog-list">
|
|
||||||
<li>{{ t('Your account will be disabled') }}</li>
|
|
||||||
<li>{{ t('Your activated sites will be suspended immediately and deleted after one week.') }}</li>
|
|
||||||
<li>{{ t('Your account billing will stop') }}</li>
|
|
||||||
</ul>
|
|
||||||
<p class="account-status-dialog-text">{{ t('You can log in later to re-enable your account. Do you want to continue?') }}</p>
|
|
||||||
</div>
|
|
||||||
</n-modal>
|
|
||||||
|
|
||||||
<!-- 启用账户对话框 -->
|
|
||||||
<n-modal
|
|
||||||
v-model:show="showEnableAccountDialog"
|
|
||||||
preset="dialog"
|
|
||||||
:title="t('Enable Account')"
|
|
||||||
:positive-text="t('Enable Account')"
|
|
||||||
:loading="enableAccountLoading"
|
|
||||||
:mask-closable="true"
|
|
||||||
:close-on-esc="true"
|
|
||||||
@positive-click="handleEnableAccountConfirm"
|
|
||||||
>
|
|
||||||
<div class="account-status-dialog-content">
|
|
||||||
<p class="account-status-dialog-title">{{ t('After confirming this action:') }}</p>
|
|
||||||
<ul class="account-status-dialog-list">
|
|
||||||
<li>{{ t('Your account will be enabled') }}</li>
|
|
||||||
<li>{{ t('Your suspended sites will be reactivated') }}</li>
|
|
||||||
<li>{{ t('Your account billing will resume') }}</li>
|
|
||||||
</ul>
|
|
||||||
<p class="account-status-dialog-text">{{ t('Do you want to continue?') }}</p>
|
|
||||||
</div>
|
|
||||||
</n-modal>
|
|
||||||
|
|
||||||
<!-- 反馈对话框 -->
|
|
||||||
<n-modal
|
|
||||||
v-model:show="showFeedbackDialog"
|
|
||||||
preset="card"
|
|
||||||
:title="t('Tell us why you are leaving')"
|
|
||||||
:style="{ width: '600px' }"
|
|
||||||
:mask-closable="false"
|
|
||||||
:close-on-esc="false"
|
|
||||||
>
|
|
||||||
<n-space vertical :size="20">
|
|
||||||
<p class="text-sm text-gray-800">
|
|
||||||
{{ t('By sharing your thoughts, help us improve your experience.') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- 星级评分 -->
|
|
||||||
<div>
|
|
||||||
<span class="block text-sm leading-4 text-gray-600 mb-2">
|
|
||||||
{{ t('Please rate your experience') }}
|
|
||||||
</span>
|
|
||||||
<div class="star-rating">
|
|
||||||
<span
|
|
||||||
v-for="rating in [1, 2, 3, 4, 5]"
|
|
||||||
:key="rating"
|
|
||||||
class="star-rating-star"
|
|
||||||
@click="feedbackRating = rating"
|
|
||||||
@mouseenter="hoveredRating = rating"
|
|
||||||
@mouseleave="hoveredRating = 0"
|
|
||||||
>
|
|
||||||
<n-icon :size="20">
|
|
||||||
<Icon
|
|
||||||
:icon="(hoveredRating || feedbackRating) >= rating ? 'tabler:star-filled' : 'tabler:star'"
|
|
||||||
:style="{ color: (hoveredRating || feedbackRating) >= rating ? '#ECAC4B' : '#C0C6CC' }"
|
|
||||||
/>
|
|
||||||
</n-icon>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 原因选择 -->
|
|
||||||
<n-form-item :label="t('Select a reason')" required>
|
|
||||||
<n-select
|
|
||||||
v-model:value="feedbackReason"
|
|
||||||
:options="feedbackReasons.map(r => ({ label: r, value: r }))"
|
|
||||||
:placeholder="t('Select a reason')"
|
|
||||||
/>
|
|
||||||
</n-form-item>
|
|
||||||
|
|
||||||
<!-- 详细说明 -->
|
|
||||||
<n-form-item :label="t('The reason I am leaving Jingrow is...')">
|
|
||||||
<n-input
|
|
||||||
v-model:value="feedbackNote"
|
|
||||||
type="textarea"
|
|
||||||
:rows="4"
|
|
||||||
:placeholder="t('The reason I am leaving Jingrow is...')"
|
|
||||||
/>
|
|
||||||
</n-form-item>
|
|
||||||
|
|
||||||
<!-- 错误提示 -->
|
|
||||||
<n-alert
|
|
||||||
v-if="feedbackError"
|
|
||||||
type="error"
|
|
||||||
:title="feedbackError"
|
|
||||||
/>
|
|
||||||
</n-space>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<n-space justify="end">
|
|
||||||
<n-button @click="closeFeedbackDialog">{{ t('Cancel') }}</n-button>
|
|
||||||
<n-button
|
|
||||||
type="primary"
|
|
||||||
:loading="feedbackLoading"
|
|
||||||
@click="handleSubmitFeedback"
|
|
||||||
>
|
|
||||||
{{ t('Submit') }}
|
|
||||||
</n-button>
|
|
||||||
</n-space>
|
|
||||||
</template>
|
|
||||||
</n-modal>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -949,8 +806,6 @@ import {
|
|||||||
updateFeatureFlags,
|
updateFeatureFlags,
|
||||||
getUserAccountInfo,
|
getUserAccountInfo,
|
||||||
becomeDeveloper,
|
becomeDeveloper,
|
||||||
disableAccount,
|
|
||||||
enableAccount,
|
|
||||||
updatePassword,
|
updatePassword,
|
||||||
testPasswordStrength,
|
testPasswordStrength,
|
||||||
validatePartnerCode,
|
validatePartnerCode,
|
||||||
@ -959,8 +814,7 @@ import {
|
|||||||
getPartnerName,
|
getPartnerName,
|
||||||
get2FAQRCodeUrl,
|
get2FAQRCodeUrl,
|
||||||
enable2FA,
|
enable2FA,
|
||||||
disable2FA,
|
disable2FA
|
||||||
submitFeedback
|
|
||||||
} from '../../shared/api/account'
|
} from '../../shared/api/account'
|
||||||
import ClickToCopyField from '../../shared/components/ClickToCopyField.vue'
|
import ClickToCopyField from '../../shared/components/ClickToCopyField.vue'
|
||||||
|
|
||||||
@ -1060,35 +914,6 @@ const twoFAError = ref('')
|
|||||||
// 重置密码
|
// 重置密码
|
||||||
const showResetPasswordDialog = ref(false)
|
const showResetPasswordDialog = ref(false)
|
||||||
|
|
||||||
// 账户状态
|
|
||||||
const teamEnabled = computed(() => teamInfo.value?.enabled || false)
|
|
||||||
const accountStatusTitle = computed(() => {
|
|
||||||
return teamEnabled.value ? t('Disable Account') : t('Enable Account')
|
|
||||||
})
|
|
||||||
const accountStatusSubtitle = computed(() => {
|
|
||||||
return teamEnabled.value
|
|
||||||
? t('Disable your account and stop billing')
|
|
||||||
: t('Enable your account and resume billing')
|
|
||||||
})
|
|
||||||
const accountStatusButtonLabel = computed(() => {
|
|
||||||
return teamEnabled.value ? t('Disable') : t('Enable')
|
|
||||||
})
|
|
||||||
|
|
||||||
// 账户状态对话框
|
|
||||||
const showDisableAccountDialog = ref(false)
|
|
||||||
const showEnableAccountDialog = ref(false)
|
|
||||||
const disableAccountLoading = ref(false)
|
|
||||||
const enableAccountLoading = ref(false)
|
|
||||||
|
|
||||||
// 反馈对话框
|
|
||||||
const showFeedbackDialog = ref(false)
|
|
||||||
const feedbackRating = ref(0)
|
|
||||||
const feedbackReason = ref('')
|
|
||||||
const feedbackNote = ref('')
|
|
||||||
const feedbackLoading = ref(false)
|
|
||||||
const feedbackError = ref('')
|
|
||||||
const hoveredRating = ref(0)
|
|
||||||
|
|
||||||
// API Secret 相关
|
// API Secret 相关
|
||||||
const showCreateSecretDialog = ref(false)
|
const showCreateSecretDialog = ref(false)
|
||||||
const createSecretData = ref<{ api_key: string; api_secret: string } | null>(null)
|
const createSecretData = ref<{ api_key: string; api_secret: string } | null>(null)
|
||||||
@ -1749,128 +1574,6 @@ watch(show2FADialog, (newVal) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 处理账户状态(禁用/启用)
|
|
||||||
const handleAccountStatus = () => {
|
|
||||||
if (teamEnabled.value) {
|
|
||||||
showDisableAccountDialog.value = true
|
|
||||||
} else {
|
|
||||||
showEnableAccountDialog.value = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确认禁用账户
|
|
||||||
const handleDisableAccountConfirm = async () => {
|
|
||||||
disableAccountLoading.value = true
|
|
||||||
try {
|
|
||||||
const result = await disableAccount()
|
|
||||||
if (result.success) {
|
|
||||||
message.success(t('Your account has been disabled successfully'))
|
|
||||||
showDisableAccountDialog.value = false
|
|
||||||
await loadUserAccountInfo()
|
|
||||||
// 显示反馈对话框
|
|
||||||
showFeedbackDialog.value = true
|
|
||||||
} else {
|
|
||||||
message.error(result.message || t('Failed to disable account'))
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
disableAccountLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 反馈原因选项
|
|
||||||
const feedbackReasons = [
|
|
||||||
t('我要迁移到其他产品'),
|
|
||||||
t('我只是在探索这个产品'),
|
|
||||||
t('我更喜欢自己托管实例'),
|
|
||||||
t('已将站点迁移到另一个Jingrow账户'),
|
|
||||||
t('我不喜欢Jingrow的体验'),
|
|
||||||
t('Jingrow对我来说太贵了'),
|
|
||||||
t('支付问题'),
|
|
||||||
t('缺少功能'),
|
|
||||||
t('我的原因不在此列表中')
|
|
||||||
]
|
|
||||||
|
|
||||||
// 提交反馈
|
|
||||||
const handleSubmitFeedback = async () => {
|
|
||||||
// 验证
|
|
||||||
if (!feedbackReason.value) {
|
|
||||||
feedbackError.value = t('请选择一个原因')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (feedbackRating.value === 0) {
|
|
||||||
feedbackError.value = t('请评价您的体验')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const requiresNote = [
|
|
||||||
t('支付问题'),
|
|
||||||
t('缺少功能'),
|
|
||||||
t('我的原因不在此列表中')
|
|
||||||
].includes(feedbackReason.value)
|
|
||||||
|
|
||||||
if (requiresNote && !feedbackNote.value) {
|
|
||||||
feedbackError.value = t('请简要说明原因')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
feedbackLoading.value = true
|
|
||||||
feedbackError.value = ''
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await submitFeedback(
|
|
||||||
teamInfo.value?.name || '',
|
|
||||||
feedbackReason.value,
|
|
||||||
feedbackNote.value,
|
|
||||||
feedbackRating.value
|
|
||||||
)
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
message.success(t('Your feedback has been submitted successfully'))
|
|
||||||
showFeedbackDialog.value = false
|
|
||||||
// 重置表单
|
|
||||||
feedbackRating.value = 0
|
|
||||||
feedbackReason.value = ''
|
|
||||||
feedbackNote.value = ''
|
|
||||||
// 延迟跳转
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.href = '/'
|
|
||||||
}, 1000)
|
|
||||||
} else {
|
|
||||||
feedbackError.value = result.message || t('提交反馈失败')
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
feedbackError.value = error.message || t('提交反馈失败')
|
|
||||||
} finally {
|
|
||||||
feedbackLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭反馈对话框
|
|
||||||
const closeFeedbackDialog = () => {
|
|
||||||
showFeedbackDialog.value = false
|
|
||||||
feedbackRating.value = 0
|
|
||||||
feedbackReason.value = ''
|
|
||||||
feedbackNote.value = ''
|
|
||||||
feedbackError.value = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确认启用账户
|
|
||||||
const handleEnableAccountConfirm = async () => {
|
|
||||||
enableAccountLoading.value = true
|
|
||||||
try {
|
|
||||||
const result = await enableAccount()
|
|
||||||
if (result.success) {
|
|
||||||
message.success(t('Your account has been enabled successfully'))
|
|
||||||
showEnableAccountDialog.value = false
|
|
||||||
await loadUserAccountInfo()
|
|
||||||
} else {
|
|
||||||
message.error(result.message || t('Failed to enable account'))
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
enableAccountLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建 API Secret
|
// 创建 API Secret
|
||||||
const handleCreateSecret = async () => {
|
const handleCreateSecret = async () => {
|
||||||
@ -2302,58 +2005,6 @@ onMounted(async () => {
|
|||||||
border-color: transparent !important;
|
border-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 账户状态对话框样式 */
|
|
||||||
.account-status-dialog-content {
|
|
||||||
padding: 16px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-status-dialog-title {
|
|
||||||
font-size: 16px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-status-dialog-list {
|
|
||||||
list-style-type: disc;
|
|
||||||
list-style-position: inside;
|
|
||||||
margin: 0 0 16px 0;
|
|
||||||
padding-left: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #4b5563;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-status-dialog-list li {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-status-dialog-list li:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account-status-dialog-text {
|
|
||||||
font-size: 16px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 星级评分样式 */
|
|
||||||
.star-rating {
|
|
||||||
display: flex;
|
|
||||||
gap: 4px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.star-rating-star {
|
|
||||||
display: inline-block;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: transform 0.1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.star-rating-star:hover {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 响应式设计 */
|
/* 响应式设计 */
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
.settings-page :deep(.n-grid) {
|
.settings-page :deep(.n-grid) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user