chore: establish V1.1 recovery baseline
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* DangerActionDialog 危险动作确认弹窗(规范 §107 DANGER_ACTION)
|
||||
*
|
||||
* 用于:拉黑 / 解除匹配 / 暂停寻找 / 退出服务 / 关闭账号
|
||||
* 不变量(AGENTS.md):
|
||||
* - 第 4 条:Block 前必须二次确认,本弹窗为唯一确认入口;
|
||||
* - 第 6 条:解除匹配/退出服务这类不可逆动作同样需要确认。
|
||||
*
|
||||
* 用法:
|
||||
* <ui-danger-action-dialog
|
||||
* visible="{{showBlockDialog}}"
|
||||
* action="block"
|
||||
* target-name="王女士"
|
||||
* bind:confirm="onConfirmBlock"
|
||||
* bind:cancel="onCancelBlock" />
|
||||
*/
|
||||
const { DANGER_ACTION } = require('../../constants');
|
||||
|
||||
const ACTION_CONFIG = {
|
||||
[DANGER_ACTION.BLOCK]: {
|
||||
title: '拉黑该用户',
|
||||
confirmText: '确认拉黑',
|
||||
danger: true,
|
||||
buildContent: (name) => `拉黑后 ${name || '该用户'} 将无法与你互动,你也不会再收到对方的推荐与消息。此操作可由你随时解除。`,
|
||||
},
|
||||
[DANGER_ACTION.UNBLOCK]: {
|
||||
title: '解除拉黑',
|
||||
confirmText: '确认解除',
|
||||
danger: false,
|
||||
buildContent: (name) => `解除拉黑后,${name || '对方'} 将可以重新看到你并向你发起互动。请确认你已准备好重新与对方接触。`,
|
||||
},
|
||||
[DANGER_ACTION.UNMATCH]: {
|
||||
title: '解除匹配',
|
||||
confirmText: '确认解除',
|
||||
danger: true,
|
||||
buildContent: (name) => `解除与 ${name || '对方'} 的匹配后,你们的会话将立即停用,历史记录保留但不可继续发送消息。此操作不可撤销。`,
|
||||
},
|
||||
[DANGER_ACTION.PAUSE]: {
|
||||
title: '暂停寻找',
|
||||
confirmText: '暂停寻找',
|
||||
danger: false,
|
||||
buildContent: () => '暂停后你将不再被推荐给他人,也无法收到新的喜欢提示。可随时恢复。',
|
||||
},
|
||||
[DANGER_ACTION.SUCCESS_MATCH]: {
|
||||
title: '成功牵手',
|
||||
confirmText: '发起牵手请求',
|
||||
danger: false,
|
||||
buildContent: (name) => `发起牵手请求后,${name || '对方'} 需在 7 天内确认。双方均确认后关系将置为"成功牵手",平台将不再为你推荐其他人。`,
|
||||
},
|
||||
[DANGER_ACTION.LOGOUT]: {
|
||||
title: '退出登录',
|
||||
confirmText: '确认退出',
|
||||
danger: false,
|
||||
buildContent: () => '退出后需重新通过微信登录。本地未同步的草稿可能丢失。',
|
||||
},
|
||||
[DANGER_ACTION.CLOSE_ACCOUNT]: {
|
||||
title: '关闭账号',
|
||||
confirmText: '申请关闭',
|
||||
danger: true,
|
||||
buildContent: () => '关闭账号后你的资料将进入 30 天冷静期,期间可联系客服恢复;超过冷静期将永久删除并不可恢复。',
|
||||
},
|
||||
};
|
||||
|
||||
Component({
|
||||
options: { addGlobalClass: true },
|
||||
properties: {
|
||||
visible: { type: Boolean, value: false },
|
||||
action: { type: String, value: 'block' },
|
||||
targetName: { type: String, value: '' },
|
||||
},
|
||||
data: {
|
||||
config: null,
|
||||
},
|
||||
observers: {
|
||||
action(action) {
|
||||
this.setData({ config: ACTION_CONFIG[action] || ACTION_CONFIG[DANGER_ACTION.BLOCK] });
|
||||
},
|
||||
'targetName'(name) {
|
||||
// 重新计算 content
|
||||
const cfg = this.data.config;
|
||||
if (cfg && cfg.buildContent) {
|
||||
this.setData({
|
||||
config: { ...cfg, content: cfg.buildContent(name) },
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
const action = this.data.action;
|
||||
const cfg = ACTION_CONFIG[action] || ACTION_CONFIG[DANGER_ACTION.BLOCK];
|
||||
this.setData({
|
||||
config: { ...cfg, content: cfg.buildContent(this.data.targetName) },
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onConfirm() {
|
||||
this.triggerEvent('confirm', { action: this.data.action });
|
||||
},
|
||||
onCancel() {
|
||||
this.triggerEvent('cancel', { action: this.data.action });
|
||||
},
|
||||
onStop() {
|
||||
// 阻止冒泡到 mask
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"ui-button": "../button/index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<view wx:if="{{visible}}" class="ui-dialog-mask" catchtap="onCancel">
|
||||
<view class="ui-dialog" catchtap="onStop">
|
||||
<view class="ui-dialog__title">{{config.title}}</view>
|
||||
<view class="ui-dialog__content">{{config.content}}</view>
|
||||
<view class="ui-dialog__actions">
|
||||
<ui-button
|
||||
variant="ghost"
|
||||
size="md"
|
||||
class="ui-dialog__btn"
|
||||
bindtap="onCancel"
|
||||
>取消</ui-button>
|
||||
<ui-button
|
||||
variant="{{config.danger ? 'danger' : 'primary'}}"
|
||||
size="md"
|
||||
class="ui-dialog__btn"
|
||||
bindtap="onConfirm"
|
||||
>{{config.confirmText}}</ui-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,47 @@
|
||||
.ui-dialog-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: var(--color-bg-overlay);
|
||||
z-index: var(--z-modal);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 var(--spacing-6);
|
||||
}
|
||||
.ui-dialog {
|
||||
width: 100%;
|
||||
max-width: 600rpx;
|
||||
background: var(--color-bg-card);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--spacing-5) var(--spacing-4) var(--spacing-4);
|
||||
box-shadow: var(--shadow-popup);
|
||||
animation: ui-dialog-in var(--motion-normal) var(--ease-standard);
|
||||
}
|
||||
@keyframes ui-dialog-in {
|
||||
from { transform: scale(0.92); opacity: 0; }
|
||||
to { transform: scale(1); opacity: 1; }
|
||||
}
|
||||
.ui-dialog__title {
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-text-primary);
|
||||
text-align: center;
|
||||
margin-bottom: var(--spacing-3);
|
||||
}
|
||||
.ui-dialog__content {
|
||||
font-size: var(--font-size-md);
|
||||
color: var(--color-text-secondary);
|
||||
line-height: var(--line-height-relaxed);
|
||||
text-align: center;
|
||||
margin-bottom: var(--spacing-5);
|
||||
}
|
||||
.ui-dialog__actions {
|
||||
display: flex;
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
.ui-dialog__btn {
|
||||
flex: 1;
|
||||
}
|
||||
Reference in New Issue
Block a user