refactor(admin-web): 简化授权管理页面,独立共管钱包功能
将授权管理页面的共管钱包功能独立成单独页面,并简化授权管理页面: 授权管理页面简化: - 移除共管钱包部分(已独立) - 移除后端不支持的复杂配置表单(考核规则、阶梯目标等) - 保留核心功能:授权列表、筛选、创建授权、撤销授权 - 添加创建授权对话框(用户+类型+地区+跳过考核期) - 添加撤销授权对话框(带原因输入) - 支持5种授权类型:社区、省团队、正式省公司、市团队、正式市公司 共管钱包独立页面: - 新建 /co-managed-wallet 页面 - 复用现有 CoManagedWalletSection 组件 - 侧边栏添加"共管钱包"菜单项 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
dcd6f2ce18
commit
d81e230639
|
|
@ -671,3 +671,273 @@
|
|||
min-width: 108px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 卡片头部 */
|
||||
.authorization__cardHeader {
|
||||
align-self: stretch;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* 创建按钮 */
|
||||
.authorization__createBtn {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background-color: #005a9c;
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
font-family: inherit;
|
||||
@include transition-fast;
|
||||
|
||||
&:hover {
|
||||
background-color: darken(#005a9c, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
/* 类型徽章 */
|
||||
.authorization__typeBadge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
background-color: #e0e7ff;
|
||||
color: #3730a3;
|
||||
}
|
||||
|
||||
/* 类型和地区列 */
|
||||
.authorization__tableCell--type {
|
||||
width: 100px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.authorization__tableCell--region {
|
||||
width: 140px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 空数据行 */
|
||||
.authorization__emptyRow {
|
||||
align-self: stretch;
|
||||
padding: 40px 24px;
|
||||
text-align: center;
|
||||
color: #6b7280;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 已撤销状态 */
|
||||
.authorization__badge--revoked {
|
||||
background-color: #fef2f2;
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
/* 模态框样式 */
|
||||
.modal__overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal__content {
|
||||
background-color: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.modal__title {
|
||||
margin: 0 0 20px 0;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.modal__form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.modal__formGroup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.modal__label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.modal__input {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border-radius: 6px;
|
||||
background-color: #f3f4f6;
|
||||
border: 1px solid #e5e7eb;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::placeholder {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: #005a9c;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.modal__select {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border-radius: 6px;
|
||||
background-color: #f3f4f6;
|
||||
border: 1px solid #e5e7eb;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
appearance: none;
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
|
||||
background-position: right 8px center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px;
|
||||
}
|
||||
|
||||
.modal__textarea {
|
||||
width: 100%;
|
||||
border-radius: 6px;
|
||||
background-color: #f3f4f6;
|
||||
border: 1px solid #e5e7eb;
|
||||
padding: 10px 12px;
|
||||
font-size: 14px;
|
||||
color: #1e293b;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
resize: vertical;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::placeholder {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: #005a9c;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.modal__toggleRow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.modal__toggleLabel {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #1e293b;
|
||||
}
|
||||
|
||||
.modal__hint {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.modal__warning {
|
||||
margin: 0;
|
||||
padding: 12px;
|
||||
background-color: #fef2f2;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
color: #991b1b;
|
||||
line-height: 1.5;
|
||||
|
||||
strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.modal__footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.modal__cancelBtn {
|
||||
cursor: pointer;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 6px;
|
||||
background-color: #fff;
|
||||
padding: 8px 16px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #6b7280;
|
||||
font-family: inherit;
|
||||
@include transition-fast;
|
||||
|
||||
&:hover {
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
}
|
||||
|
||||
.modal__confirmBtn {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background-color: #005a9c;
|
||||
padding: 8px 20px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
font-family: inherit;
|
||||
@include transition-fast;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background-color: darken(#005a9c, 5%);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&--danger {
|
||||
background-color: #dc2626;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background-color: darken(#dc2626, 5%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,449 +3,526 @@
|
|||
import { useState } from 'react';
|
||||
import { PageContainer } from '@/components/layout';
|
||||
import { cn } from '@/utils/helpers';
|
||||
import { CoManagedWalletSection } from '@/components/features/co-managed-wallet';
|
||||
import styles from './authorization.module.scss';
|
||||
|
||||
/**
|
||||
* 省/市公司数据接口
|
||||
* 授权角色类型
|
||||
*/
|
||||
interface CompanyItem {
|
||||
type AuthorizationType =
|
||||
| 'COMMUNITY'
|
||||
| 'AUTH_PROVINCE_COMPANY'
|
||||
| 'PROVINCE_COMPANY'
|
||||
| 'AUTH_CITY_COMPANY'
|
||||
| 'CITY_COMPANY';
|
||||
|
||||
/**
|
||||
* 授权角色名称映射
|
||||
*/
|
||||
const authorizationTypeLabels: Record<AuthorizationType, string> = {
|
||||
COMMUNITY: '社区',
|
||||
AUTH_PROVINCE_COMPANY: '省团队',
|
||||
PROVINCE_COMPANY: '正式省公司',
|
||||
AUTH_CITY_COMPANY: '市团队',
|
||||
CITY_COMPANY: '正式市公司',
|
||||
};
|
||||
|
||||
/**
|
||||
* 授权记录接口
|
||||
*/
|
||||
interface AuthorizationItem {
|
||||
id: string;
|
||||
avatar: string;
|
||||
userId: string;
|
||||
accountSequence: string;
|
||||
nickname: string;
|
||||
accountId: string;
|
||||
province: string;
|
||||
city?: string;
|
||||
teamAdoptions: number;
|
||||
authStatus: 'authorized' | 'pending';
|
||||
avatar?: string;
|
||||
type: AuthorizationType;
|
||||
region?: string; // 如: "广东省" 或 "广东省深圳市"
|
||||
skipAssessment: boolean;
|
||||
createdAt: string;
|
||||
status: 'active' | 'revoked';
|
||||
}
|
||||
|
||||
/**
|
||||
* 阶梯性考核目标数据接口
|
||||
*/
|
||||
interface TargetItem {
|
||||
month: string;
|
||||
provinceMonthly: number;
|
||||
provinceTotal: number;
|
||||
cityMonthly: number;
|
||||
cityTotal: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 特殊城市规则接口
|
||||
*/
|
||||
interface SpecialCityRule {
|
||||
city: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
// 模拟省公司数据
|
||||
const mockProvinceCompanies: CompanyItem[] = [
|
||||
{ id: '1', avatar: '', nickname: '用户昵称一', accountId: '123456789', province: '广东省', teamAdoptions: 1234, authStatus: 'authorized' },
|
||||
];
|
||||
|
||||
// 模拟市公司数据
|
||||
const mockCityCompanies: CompanyItem[] = [
|
||||
{ id: '1', avatar: '', nickname: '用户昵称二', accountId: '987654321', province: '广东省', city: '深圳市', teamAdoptions: 567, authStatus: 'pending' },
|
||||
];
|
||||
|
||||
// 阶梯性考核目标数据
|
||||
const targetData: TargetItem[] = [
|
||||
{ month: '第 1 个月', provinceMonthly: 500, provinceTotal: 500, cityMonthly: 100, cityTotal: 100 },
|
||||
{ month: '第 2 个月', provinceMonthly: 500, provinceTotal: 1000, cityMonthly: 100, cityTotal: 200 },
|
||||
{ month: '...', provinceMonthly: 0, provinceTotal: 0, cityMonthly: 0, cityTotal: 0 },
|
||||
{ month: '第 9 个月', provinceMonthly: 1000, provinceTotal: 6000, cityMonthly: 200, cityTotal: 1200 },
|
||||
];
|
||||
|
||||
// 特殊城市规则
|
||||
const specialCities: SpecialCityRule[] = [
|
||||
{ city: '北京市', enabled: false },
|
||||
{ city: '上海市', enabled: true },
|
||||
// 模拟授权数据
|
||||
const mockAuthorizations: AuthorizationItem[] = [
|
||||
{
|
||||
id: '1',
|
||||
userId: '12345',
|
||||
accountSequence: 'D25122700001',
|
||||
nickname: '张三',
|
||||
type: 'PROVINCE_COMPANY',
|
||||
region: '广东省',
|
||||
skipAssessment: false,
|
||||
createdAt: '2025-01-01',
|
||||
status: 'active',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
userId: '12346',
|
||||
accountSequence: 'D25122700002',
|
||||
nickname: '李四',
|
||||
type: 'AUTH_CITY_COMPANY',
|
||||
region: '广东省深圳市',
|
||||
skipAssessment: true,
|
||||
createdAt: '2025-01-02',
|
||||
status: 'active',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
userId: '12347',
|
||||
accountSequence: 'D25122700003',
|
||||
nickname: '王五',
|
||||
type: 'COMMUNITY',
|
||||
region: '榴莲社区A',
|
||||
skipAssessment: false,
|
||||
createdAt: '2025-01-03',
|
||||
status: 'active',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 授权管理页面
|
||||
* 基于 UIPro Figma 设计实现
|
||||
* 简化版 - 保留核心授权功能
|
||||
*/
|
||||
export default function AuthorizationPage() {
|
||||
// 省公司规则状态
|
||||
const [provinceThreshold, setProvinceThreshold] = useState('500');
|
||||
const [provinceBenefit, setProvinceBenefit] = useState('20');
|
||||
const [provinceAfterBenefit, setProvinceAfterBenefit] = useState('20');
|
||||
const [provinceResetEnabled, setProvinceResetEnabled] = useState(true);
|
||||
// 筛选状态
|
||||
const [filterType, setFilterType] = useState<AuthorizationType | ''>('');
|
||||
const [filterStatus, setFilterStatus] = useState<'active' | 'revoked' | ''>('');
|
||||
const [searchKeyword, setSearchKeyword] = useState('');
|
||||
|
||||
// 市公司规则状态
|
||||
const [cityThreshold, setCityThreshold] = useState('100');
|
||||
const [cityBenefit, setCityBenefit] = useState('40');
|
||||
const [cityAfterBenefit, setCityAfterBenefit] = useState('40');
|
||||
const [cityResetEnabled, setCityResetEnabled] = useState(true);
|
||||
// 创建授权对话框状态
|
||||
const [showCreateModal, setShowCreateModal] = useState(false);
|
||||
const [createForm, setCreateForm] = useState({
|
||||
accountSequence: '',
|
||||
type: 'COMMUNITY' as AuthorizationType,
|
||||
region: '',
|
||||
skipAssessment: false,
|
||||
});
|
||||
|
||||
// 授权限制规则
|
||||
const [topRankLimit, setTopRankLimit] = useState('10');
|
||||
const [specialRules, setSpecialRules] = useState(specialCities);
|
||||
// 取消授权对话框状态
|
||||
const [showRevokeModal, setShowRevokeModal] = useState(false);
|
||||
const [revokeTarget, setRevokeTarget] = useState<AuthorizationItem | null>(null);
|
||||
const [revokeReason, setRevokeReason] = useState('');
|
||||
|
||||
// 筛选后的数据
|
||||
const filteredData = mockAuthorizations.filter((item) => {
|
||||
if (filterType && item.type !== filterType) return false;
|
||||
if (filterStatus && item.status !== filterStatus) return false;
|
||||
if (searchKeyword) {
|
||||
const keyword = searchKeyword.toLowerCase();
|
||||
return (
|
||||
item.nickname.toLowerCase().includes(keyword) ||
|
||||
item.accountSequence.toLowerCase().includes(keyword) ||
|
||||
(item.region && item.region.toLowerCase().includes(keyword))
|
||||
);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// 处理创建授权
|
||||
const handleCreate = () => {
|
||||
// TODO: 调用API创建授权
|
||||
console.log('创建授权:', createForm);
|
||||
setShowCreateModal(false);
|
||||
setCreateForm({
|
||||
accountSequence: '',
|
||||
type: 'COMMUNITY',
|
||||
region: '',
|
||||
skipAssessment: false,
|
||||
});
|
||||
};
|
||||
|
||||
// 处理取消授权
|
||||
const handleRevoke = () => {
|
||||
// TODO: 调用API取消授权
|
||||
console.log('取消授权:', revokeTarget, '原因:', revokeReason);
|
||||
setShowRevokeModal(false);
|
||||
setRevokeTarget(null);
|
||||
setRevokeReason('');
|
||||
};
|
||||
|
||||
// 打开取消授权对话框
|
||||
const openRevokeModal = (item: AuthorizationItem) => {
|
||||
setRevokeTarget(item);
|
||||
setShowRevokeModal(true);
|
||||
};
|
||||
|
||||
// 判断是否需要地区选择
|
||||
const needsRegion = (type: AuthorizationType) => {
|
||||
return type !== 'COMMUNITY' || type === 'COMMUNITY';
|
||||
};
|
||||
|
||||
// 获取地区输入提示
|
||||
const getRegionPlaceholder = (type: AuthorizationType) => {
|
||||
switch (type) {
|
||||
case 'COMMUNITY':
|
||||
return '输入社区名称';
|
||||
case 'AUTH_PROVINCE_COMPANY':
|
||||
case 'PROVINCE_COMPANY':
|
||||
return '选择省份 (如: 广东省)';
|
||||
case 'AUTH_CITY_COMPANY':
|
||||
case 'CITY_COMPANY':
|
||||
return '选择城市 (如: 广东省深圳市)';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
// 渲染开关组件
|
||||
const renderToggle = (checked: boolean, onChange: (checked: boolean) => void) => (
|
||||
<div
|
||||
className={cn(styles.authorization__toggle, checked ? styles['authorization__toggle--on'] : styles['authorization__toggle--off'])}
|
||||
className={cn(
|
||||
styles.authorization__toggle,
|
||||
checked ? styles['authorization__toggle--on'] : styles['authorization__toggle--off']
|
||||
)}
|
||||
onClick={() => onChange(!checked)}
|
||||
role="switch"
|
||||
aria-checked={checked}
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) => e.key === 'Enter' && onChange(!checked)}
|
||||
>
|
||||
<div className={cn(styles.authorization__toggleHandle, checked ? styles['authorization__toggleHandle--on'] : styles['authorization__toggleHandle--off'])} />
|
||||
</div>
|
||||
);
|
||||
|
||||
// 渲染省公司表格
|
||||
const renderProvinceTable = () => (
|
||||
<div className={styles.authorization__table}>
|
||||
<div className={styles.authorization__tableHeader}>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--avatar'])}>头像</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--nickname'])}>昵称</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--accountId'])}>账户序列号</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--province'])}>所属省份</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--teamAdoptions'])}>伞下团队认种总量(棵)</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--status'])}>授权状态</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--actions'])}>操作</div>
|
||||
</div>
|
||||
{mockProvinceCompanies.map((item) => (
|
||||
<div key={item.id} className={styles.authorization__tableRow}>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--avatar'])}>
|
||||
<div
|
||||
className={styles.authorization__avatar}
|
||||
style={item.avatar ? { backgroundImage: `url(${item.avatar})` } : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--nickname'])}>{item.nickname}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--accountId'])}>{item.accountId}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--province'])}>{item.province}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--teamAdoptions'])}>{item.teamAdoptions.toLocaleString()}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--status'])}>
|
||||
<span className={cn(styles.authorization__badge, item.authStatus === 'authorized' ? styles['authorization__badge--authorized'] : styles['authorization__badge--pending'])}>
|
||||
{item.authStatus === 'authorized' ? '已授权' : '待授权'}
|
||||
</span>
|
||||
</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--actions'])}>
|
||||
<button className={cn(styles.authorization__actionBtn, styles['authorization__actionBtn--authorize'])}>授权为省公司</button>
|
||||
<button className={cn(styles.authorization__actionBtn, styles['authorization__actionBtn--revoke'])}>取消省公司授权</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
// 渲染市公司表格
|
||||
const renderCityTable = () => (
|
||||
<div className={styles.authorization__table}>
|
||||
<div className={styles.authorization__tableHeader}>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--avatar'])}>头像</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--nickname'])}>昵称</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--accountId'])}>账户序列号</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--city'])}>所属省/市</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--teamAdoptions'])}>伞下团队认种总量(棵)</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--status'])}>授权状态</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--header'], styles['authorization__tableCell--actions'])}>操作</div>
|
||||
</div>
|
||||
{mockCityCompanies.map((item) => (
|
||||
<div key={item.id} className={styles.authorization__tableRow}>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--avatar'])}>
|
||||
<div
|
||||
className={styles.authorization__avatar}
|
||||
style={item.avatar ? { backgroundImage: `url(${item.avatar})` } : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--nickname'])}>{item.nickname}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--accountId'])}>{item.accountId}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--city'])}>{item.province} / {item.city}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--teamAdoptions'])}>{item.teamAdoptions}</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--status'])}>
|
||||
<span className={cn(styles.authorization__badge, item.authStatus === 'authorized' ? styles['authorization__badge--authorized'] : styles['authorization__badge--pending'])}>
|
||||
{item.authStatus === 'authorized' ? '已授权' : '待授权'}
|
||||
</span>
|
||||
</div>
|
||||
<div className={cn(styles.authorization__tableCell, styles['authorization__tableCell--actions'])}>
|
||||
<button className={cn(styles.authorization__actionBtn, styles['authorization__actionBtn--authorize'])}>授权为市公司</button>
|
||||
<button className={cn(styles.authorization__actionBtn, styles['authorization__actionBtn--revoke'])}>取消市公司授权</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__toggleHandle,
|
||||
checked
|
||||
? styles['authorization__toggleHandle--on']
|
||||
: styles['authorization__toggleHandle--off']
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<PageContainer title="授权管理">
|
||||
<div className={styles.authorization}>
|
||||
{/* 共管钱包管理 */}
|
||||
<CoManagedWalletSection />
|
||||
|
||||
{/* 授权省公司管理 */}
|
||||
{/* 授权列表 */}
|
||||
<section className={styles.authorization__card}>
|
||||
<h3 className={styles.authorization__cardTitle}>授权省公司管理</h3>
|
||||
<div className={styles.authorization__filters}>
|
||||
<select className={styles.authorization__select} aria-label="选择省份">
|
||||
<option value="">选择省份</option>
|
||||
<option value="guangdong">广东省</option>
|
||||
<option value="zhejiang">浙江省</option>
|
||||
<option value="jiangsu">江苏省</option>
|
||||
</select>
|
||||
<select className={styles.authorization__select} aria-label="授权状态">
|
||||
<option value="">授权状态</option>
|
||||
<option value="authorized">已授权</option>
|
||||
<option value="pending">待授权</option>
|
||||
</select>
|
||||
<input className={styles.authorization__input} placeholder="关键词搜索" type="text" aria-label="关键词搜索" />
|
||||
<button className={styles.authorization__searchBtn}>查询</button>
|
||||
</div>
|
||||
{renderProvinceTable()}
|
||||
<p className={styles.authorization__help}>帮助:在此管理和筛选具备省公司资格的账号,并发起授权操作。</p>
|
||||
</section>
|
||||
<div className={styles.authorization__cardHeader}>
|
||||
<h3 className={styles.authorization__cardTitle}>授权列表</h3>
|
||||
<button
|
||||
className={styles.authorization__createBtn}
|
||||
onClick={() => setShowCreateModal(true)}
|
||||
>
|
||||
+ 创建授权
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 授权省公司团队权益考核规则 */}
|
||||
<section className={styles.authorization__card}>
|
||||
<h3 className={styles.authorization__cardTitle}>授权省公司团队权益考核规则</h3>
|
||||
<div className={styles.authorization__form}>
|
||||
<div className={styles.authorization__formRow}>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>首次考核触发门槛(棵)</label>
|
||||
<input
|
||||
className={styles.authorization__formInput}
|
||||
type="text"
|
||||
value={provinceThreshold}
|
||||
onChange={(e) => setProvinceThreshold(e.target.value)}
|
||||
placeholder="500"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>考核阶段单棵权益(积分)</label>
|
||||
<input
|
||||
className={styles.authorization__formInput}
|
||||
type="text"
|
||||
value={provinceBenefit}
|
||||
onChange={(e) => setProvinceBenefit(e.target.value)}
|
||||
placeholder="20"
|
||||
/>
|
||||
<span className={styles.authorization__formHint}>即,累计完成 {provinceThreshold} 棵目标前,每新增 1 棵获得的权益</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.authorization__formRow}>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>考核达标后每新增 1 棵省公司获得(积分)</label>
|
||||
<input
|
||||
className={styles.authorization__formInput}
|
||||
type="text"
|
||||
value={provinceAfterBenefit}
|
||||
onChange={(e) => setProvinceAfterBenefit(e.target.value)}
|
||||
placeholder="20"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>考核周期</label>
|
||||
<select className={styles.authorization__select} style={{ width: '100%' }} aria-label="考核周期">
|
||||
<option value="monthly">按月考核</option>
|
||||
<option value="quarterly">按季度考核</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.authorization__toggleRow}>
|
||||
<span className={styles.authorization__toggleLabel}>未达成本月考核目标时,权益失效并从 0 重新累计 {provinceThreshold} 棵</span>
|
||||
{renderToggle(provinceResetEnabled, setProvinceResetEnabled)}
|
||||
</div>
|
||||
<div className={styles.authorization__saveWrapper}>
|
||||
<button className={styles.authorization__saveBtn}>保存设置</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 授权市公司管理 */}
|
||||
<section className={styles.authorization__card}>
|
||||
<h3 className={styles.authorization__cardTitle}>授权市公司管理</h3>
|
||||
<div className={styles.authorization__filters}>
|
||||
<select className={styles.authorization__select} aria-label="选择省份">
|
||||
<option value="">选择省份</option>
|
||||
<option value="guangdong">广东省</option>
|
||||
<option value="zhejiang">浙江省</option>
|
||||
</select>
|
||||
<select className={styles.authorization__select} aria-label="选择城市">
|
||||
<option value="">选择城市</option>
|
||||
<option value="shenzhen">深圳市</option>
|
||||
<option value="guangzhou">广州市</option>
|
||||
</select>
|
||||
<select className={styles.authorization__select} aria-label="授权状态">
|
||||
<option value="">授权状态</option>
|
||||
<option value="authorized">已授权</option>
|
||||
<option value="pending">待授权</option>
|
||||
</select>
|
||||
<input className={styles.authorization__input} placeholder="关键词搜索" type="text" aria-label="关键词搜索" />
|
||||
<button className={styles.authorization__searchBtn}>查询</button>
|
||||
</div>
|
||||
{renderCityTable()}
|
||||
<p className={styles.authorization__help}>帮助:在此管理和筛选具备市公司资格的账号,并发起授权操作。</p>
|
||||
</section>
|
||||
|
||||
{/* 授权市公司团队权益考核规则 */}
|
||||
<section className={styles.authorization__card}>
|
||||
<h3 className={styles.authorization__cardTitle}>授权市公司团队权益考核规则</h3>
|
||||
<div className={styles.authorization__form}>
|
||||
<div className={styles.authorization__formRow}>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>首次考核触发门槛(棵)</label>
|
||||
<input
|
||||
className={styles.authorization__formInput}
|
||||
type="text"
|
||||
value={cityThreshold}
|
||||
onChange={(e) => setCityThreshold(e.target.value)}
|
||||
placeholder="100"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>考核阶段单棵权益(积分)</label>
|
||||
<input
|
||||
className={styles.authorization__formInput}
|
||||
type="text"
|
||||
value={cityBenefit}
|
||||
onChange={(e) => setCityBenefit(e.target.value)}
|
||||
placeholder="40"
|
||||
/>
|
||||
<span className={styles.authorization__formHint}>即,累计完成 {cityThreshold} 棵目标前,每新增 1 棵获得的权益</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.authorization__formRow}>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>考核达标后每新增 1 棵市公司获得(积分)</label>
|
||||
<input
|
||||
className={styles.authorization__formInput}
|
||||
type="text"
|
||||
value={cityAfterBenefit}
|
||||
onChange={(e) => setCityAfterBenefit(e.target.value)}
|
||||
placeholder="40"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.authorization__formGroup}>
|
||||
<label className={styles.authorization__formLabel}>考核周期</label>
|
||||
<select className={styles.authorization__select} style={{ width: '100%' }} aria-label="考核周期">
|
||||
<option value="monthly">按月考核</option>
|
||||
<option value="quarterly">按季度考核</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.authorization__toggleRow}>
|
||||
<span className={styles.authorization__toggleLabel}>未达成本月考核目标时,权益失效并从 0 重新累计 {cityThreshold} 棵</span>
|
||||
{renderToggle(cityResetEnabled, setCityResetEnabled)}
|
||||
</div>
|
||||
<div className={styles.authorization__saveWrapper}>
|
||||
<button className={styles.authorization__saveBtn}>保存设置</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 正式省公司/市公司授权管理 */}
|
||||
<div className={styles.authorization__officialSection}>
|
||||
<section className={styles.authorization__officialCard}>
|
||||
<h3 className={styles.authorization__officialTitle}>正式省公司授权管理</h3>
|
||||
<p className={styles.authorization__officialDesc}>当省公司完成全部阶梯性考核后,可在此授权为正式省公司。</p>
|
||||
<div className={styles.authorization__officialTable}>
|
||||
<div className={styles.authorization__officialRow}>
|
||||
<div className={styles.authorization__officialCell}>头像</div>
|
||||
<div className={styles.authorization__officialCell}>昵称</div>
|
||||
<div className={styles.authorization__officialCell}>序列号</div>
|
||||
<div className={styles.authorization__officialCell}>省份</div>
|
||||
<div className={styles.authorization__officialCell}>状态</div>
|
||||
<div className={styles.authorization__officialCell}>操作</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className={styles.authorization__officialCard}>
|
||||
<h3 className={styles.authorization__officialTitle}>正式市公司授权管理</h3>
|
||||
<p className={styles.authorization__officialDesc}>当市公司完成全部阶梯性考核后,可在此授权为正式市公司。</p>
|
||||
<div className={styles.authorization__officialTable}>
|
||||
<div className={styles.authorization__officialRow}>
|
||||
<div className={styles.authorization__officialCell}>头像</div>
|
||||
<div className={styles.authorization__officialCell}>昵称</div>
|
||||
<div className={styles.authorization__officialCell}>序列号</div>
|
||||
<div className={styles.authorization__officialCell}>省/市</div>
|
||||
<div className={styles.authorization__officialCell}>状态</div>
|
||||
<div className={styles.authorization__officialCell}>操作</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* 省公司 / 市公司 授权限制规则 */}
|
||||
<section className={styles.authorization__card}>
|
||||
<h3 className={styles.authorization__cardTitle}>省公司 / 市公司 授权限制规则</h3>
|
||||
<div className={styles.authorization__rules}>
|
||||
<div className={styles.authorization__ruleItem}>每个省份仅可授权 1 个省公司账号</div>
|
||||
<div className={styles.authorization__ruleItem}>
|
||||
<div className={styles.authorization__ruleInline}>
|
||||
<span>每个城市仅可授权 1 个市公司账号</span>
|
||||
<span className={styles.authorization__ruleNote}>(例如:广东省深圳市)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.authorization__ruleItem}>
|
||||
<div className={styles.authorization__ruleInline}>
|
||||
<span>伞下团队认种总量排名前</span>
|
||||
<input
|
||||
className={styles.authorization__ruleInput}
|
||||
type="text"
|
||||
value={topRankLimit}
|
||||
onChange={(e) => setTopRankLimit(e.target.value)}
|
||||
aria-label="排名限制"
|
||||
/>
|
||||
<span>的账号具备授权资格</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.authorization__specialRules}>
|
||||
<div className={styles.authorization__specialTitle}>特殊城市授权规则 (如直辖市、特别行政区)</div>
|
||||
<div className={styles.authorization__specialTable}>
|
||||
{specialRules.map((rule, index) => (
|
||||
<div key={rule.city} className={styles.authorization__specialRow}>
|
||||
<div className={styles.authorization__specialCity}>{rule.city}</div>
|
||||
<div className={styles.authorization__specialToggle}>
|
||||
{renderToggle(rule.enabled, (enabled) => {
|
||||
const newRules = [...specialRules];
|
||||
newRules[index] = { ...rule, enabled };
|
||||
setSpecialRules(newRules);
|
||||
})}
|
||||
<span className={styles.authorization__specialLabel}>启用特例</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* 筛选区域 */}
|
||||
<div className={styles.authorization__filters}>
|
||||
<select
|
||||
className={styles.authorization__select}
|
||||
value={filterType}
|
||||
onChange={(e) => setFilterType(e.target.value as AuthorizationType | '')}
|
||||
aria-label="授权类型"
|
||||
>
|
||||
<option value="">全部类型</option>
|
||||
{Object.entries(authorizationTypeLabels).map(([value, label]) => (
|
||||
<option key={value} value={value}>
|
||||
{label}
|
||||
</option>
|
||||
))}
|
||||
</div>
|
||||
</select>
|
||||
<select
|
||||
className={styles.authorization__select}
|
||||
value={filterStatus}
|
||||
onChange={(e) => setFilterStatus(e.target.value as 'active' | 'revoked' | '')}
|
||||
aria-label="授权状态"
|
||||
>
|
||||
<option value="">全部状态</option>
|
||||
<option value="active">有效</option>
|
||||
<option value="revoked">已撤销</option>
|
||||
</select>
|
||||
<input
|
||||
className={styles.authorization__input}
|
||||
placeholder="搜索昵称、账户序列号、地区..."
|
||||
type="text"
|
||||
value={searchKeyword}
|
||||
onChange={(e) => setSearchKeyword(e.target.value)}
|
||||
aria-label="关键词搜索"
|
||||
/>
|
||||
<button className={styles.authorization__searchBtn}>查询</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 省公司 / 市公司 阶梯性考核目标 */}
|
||||
<section className={styles.authorization__card}>
|
||||
<div className={styles.authorization__targetHeader}>
|
||||
<h3 className={styles.authorization__targetTitle}>省公司 / 市公司 阶梯性考核目标</h3>
|
||||
<button className={styles.authorization__editBtn}>编辑</button>
|
||||
</div>
|
||||
<div className={styles.authorization__targetTable}>
|
||||
<div className={styles.authorization__targetHeader2}>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--header'], styles['authorization__targetCell--month'])}>考核月</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--header'], styles['authorization__targetCell--provinceMonthly'])}>省代当月目标(棵)</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--header'], styles['authorization__targetCell--provinceTotal'])}>省代累计目标(棵)</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--header'], styles['authorization__targetCell--cityMonthly'])}>市代当月目标(棵)</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--header'], styles['authorization__targetCell--cityTotal'])}>市代累计目标(棵)</div>
|
||||
</div>
|
||||
<div className={styles.authorization__targetBody}>
|
||||
{targetData.map((row, index) => (
|
||||
<div key={row.month} className={cn(styles.authorization__targetRow, index < targetData.length - 1 && styles['authorization__targetRow--bordered'])}>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--month'])}>{row.month}</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--provinceMonthly'])}>{row.month === '...' ? '...' : row.provinceMonthly}</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--provinceTotal'])}>{row.month === '...' ? '...' : row.provinceTotal}</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--cityMonthly'])}>{row.month === '...' ? '...' : row.cityMonthly}</div>
|
||||
<div className={cn(styles.authorization__targetCell, styles['authorization__targetCell--cityTotal'])}>{row.month === '...' ? '...' : row.cityTotal}</div>
|
||||
{/* 授权表格 */}
|
||||
<div className={styles.authorization__table}>
|
||||
<div className={styles.authorization__tableHeader}>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--header'],
|
||||
styles['authorization__tableCell--avatar']
|
||||
)}
|
||||
>
|
||||
头像
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--header'],
|
||||
styles['authorization__tableCell--nickname']
|
||||
)}
|
||||
>
|
||||
昵称
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--header'],
|
||||
styles['authorization__tableCell--accountId']
|
||||
)}
|
||||
>
|
||||
账户序列号
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--header'],
|
||||
styles['authorization__tableCell--type']
|
||||
)}
|
||||
>
|
||||
授权类型
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--header'],
|
||||
styles['authorization__tableCell--region']
|
||||
)}
|
||||
>
|
||||
地区/名称
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--header'],
|
||||
styles['authorization__tableCell--status']
|
||||
)}
|
||||
>
|
||||
状态
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--header'],
|
||||
styles['authorization__tableCell--actions']
|
||||
)}
|
||||
>
|
||||
操作
|
||||
</div>
|
||||
</div>
|
||||
{filteredData.map((item) => (
|
||||
<div key={item.id} className={styles.authorization__tableRow}>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--avatar']
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={styles.authorization__avatar}
|
||||
style={item.avatar ? { backgroundImage: `url(${item.avatar})` } : undefined}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--nickname']
|
||||
)}
|
||||
>
|
||||
{item.nickname}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--accountId']
|
||||
)}
|
||||
>
|
||||
{item.accountSequence}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--type']
|
||||
)}
|
||||
>
|
||||
<span className={styles.authorization__typeBadge}>
|
||||
{authorizationTypeLabels[item.type]}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--region']
|
||||
)}
|
||||
>
|
||||
{item.region || '-'}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--status']
|
||||
)}
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
styles.authorization__badge,
|
||||
item.status === 'active'
|
||||
? styles['authorization__badge--authorized']
|
||||
: styles['authorization__badge--revoked']
|
||||
)}
|
||||
>
|
||||
{item.status === 'active' ? '有效' : '已撤销'}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
styles.authorization__tableCell,
|
||||
styles['authorization__tableCell--actions']
|
||||
)}
|
||||
>
|
||||
{item.status === 'active' && (
|
||||
<button
|
||||
className={cn(
|
||||
styles.authorization__actionBtn,
|
||||
styles['authorization__actionBtn--revoke']
|
||||
)}
|
||||
onClick={() => openRevokeModal(item)}
|
||||
>
|
||||
撤销授权
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{filteredData.length === 0 && (
|
||||
<div className={styles.authorization__emptyRow}>暂无授权记录</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<p className={styles.authorization__help}>帮助:完成全部 9 个月阶梯考核后,可升级为正式省/市公司。</p>
|
||||
|
||||
<p className={styles.authorization__help}>
|
||||
帮助:在此管理所有授权用户,包括社区、省团队、市团队、正式省公司和正式市公司。
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{/* 创建授权对话框 */}
|
||||
{showCreateModal && (
|
||||
<div className={styles.modal__overlay} onClick={() => setShowCreateModal(false)}>
|
||||
<div className={styles.modal__content} onClick={(e) => e.stopPropagation()}>
|
||||
<h3 className={styles.modal__title}>创建授权</h3>
|
||||
<div className={styles.modal__form}>
|
||||
<div className={styles.modal__formGroup}>
|
||||
<label className={styles.modal__label}>账户序列号</label>
|
||||
<input
|
||||
className={styles.modal__input}
|
||||
type="text"
|
||||
placeholder="输入用户账户序列号 (如: D25122700001)"
|
||||
value={createForm.accountSequence}
|
||||
onChange={(e) =>
|
||||
setCreateForm({ ...createForm, accountSequence: e.target.value })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.modal__formGroup}>
|
||||
<label className={styles.modal__label}>授权类型</label>
|
||||
<select
|
||||
className={styles.modal__select}
|
||||
value={createForm.type}
|
||||
onChange={(e) =>
|
||||
setCreateForm({ ...createForm, type: e.target.value as AuthorizationType })
|
||||
}
|
||||
>
|
||||
{Object.entries(authorizationTypeLabels).map(([value, label]) => (
|
||||
<option key={value} value={value}>
|
||||
{label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
{needsRegion(createForm.type) && (
|
||||
<div className={styles.modal__formGroup}>
|
||||
<label className={styles.modal__label}>
|
||||
{createForm.type === 'COMMUNITY' ? '社区名称' : '地区'}
|
||||
</label>
|
||||
<input
|
||||
className={styles.modal__input}
|
||||
type="text"
|
||||
placeholder={getRegionPlaceholder(createForm.type)}
|
||||
value={createForm.region}
|
||||
onChange={(e) => setCreateForm({ ...createForm, region: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.modal__formGroup}>
|
||||
<div className={styles.modal__toggleRow}>
|
||||
<span className={styles.modal__toggleLabel}>跳过考核期</span>
|
||||
{renderToggle(createForm.skipAssessment, (checked) =>
|
||||
setCreateForm({ ...createForm, skipAssessment: checked })
|
||||
)}
|
||||
</div>
|
||||
<p className={styles.modal__hint}>
|
||||
开启后,用户将直接获得完整权益,无需经过考核期
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.modal__footer}>
|
||||
<button
|
||||
className={styles.modal__cancelBtn}
|
||||
onClick={() => setShowCreateModal(false)}
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
className={styles.modal__confirmBtn}
|
||||
onClick={handleCreate}
|
||||
disabled={!createForm.accountSequence || !createForm.region}
|
||||
>
|
||||
确认创建
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 撤销授权对话框 */}
|
||||
{showRevokeModal && revokeTarget && (
|
||||
<div className={styles.modal__overlay} onClick={() => setShowRevokeModal(false)}>
|
||||
<div className={styles.modal__content} onClick={(e) => e.stopPropagation()}>
|
||||
<h3 className={styles.modal__title}>撤销授权</h3>
|
||||
<div className={styles.modal__form}>
|
||||
<p className={styles.modal__warning}>
|
||||
确定要撤销用户 <strong>{revokeTarget.nickname}</strong> (
|
||||
{revokeTarget.accountSequence}) 的{' '}
|
||||
<strong>{authorizationTypeLabels[revokeTarget.type]}</strong> 授权吗?
|
||||
</p>
|
||||
<div className={styles.modal__formGroup}>
|
||||
<label className={styles.modal__label}>撤销原因</label>
|
||||
<textarea
|
||||
className={styles.modal__textarea}
|
||||
placeholder="请输入撤销原因..."
|
||||
value={revokeReason}
|
||||
onChange={(e) => setRevokeReason(e.target.value)}
|
||||
rows={3}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.modal__footer}>
|
||||
<button
|
||||
className={styles.modal__cancelBtn}
|
||||
onClick={() => setShowRevokeModal(false)}
|
||||
>
|
||||
取消
|
||||
</button>
|
||||
<button
|
||||
className={cn(styles.modal__confirmBtn, styles['modal__confirmBtn--danger'])}
|
||||
onClick={handleRevoke}
|
||||
disabled={!revokeReason}
|
||||
>
|
||||
确认撤销
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
'use client';
|
||||
|
||||
import { PageContainer } from '@/components/layout';
|
||||
import { CoManagedWalletSection } from '@/components/features/co-managed-wallet';
|
||||
|
||||
/**
|
||||
* 共管钱包管理页面
|
||||
* 独立管理分布式多方共管钱包
|
||||
*/
|
||||
export default function CoManagedWalletPage() {
|
||||
return (
|
||||
<PageContainer title="共管钱包管理">
|
||||
<CoManagedWalletSection />
|
||||
</PageContainer>
|
||||
);
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ const topMenuItems: MenuItem[] = [
|
|||
{ key: 'users', icon: '/images/Container2.svg', label: '用户管理', path: '/users' },
|
||||
{ key: 'leaderboard', icon: '/images/Container3.svg', label: '龙虎榜', path: '/leaderboard' },
|
||||
{ key: 'authorization', icon: '/images/Container4.svg', label: '授权管理', path: '/authorization' },
|
||||
{ key: 'co-managed-wallet', icon: '/images/Container4.svg', label: '共管钱包', path: '/co-managed-wallet' },
|
||||
{ key: 'notifications', icon: '/images/Container3.svg', label: '通知管理', path: '/notifications' },
|
||||
{ key: 'pending-actions', icon: '/images/Container3.svg', label: '待办操作', path: '/pending-actions' },
|
||||
{ key: 'withdrawals', icon: '/images/Container5.svg', label: '提现审核', path: '/withdrawals' },
|
||||
|
|
|
|||
Loading…
Reference in New Issue