feat: add member URL pool and login tracking

This commit is contained in:
richjohnrambo
2026-10-15 10:41:29 +08:00
parent ca0d115e36
commit f8b5e4270b
46 changed files with 3733 additions and 66 deletions
+18 -19
View File
@@ -22,13 +22,7 @@
:action-column="actionColumn"
:scroll-x="scrollX"
:resize-height-offset="-10000"
>
<template #tableTitle>
<n-button v-if="hasPermission(['/appMember/edit'])" type="primary" @click="openEdit()"
>新增会员</n-button
>
</template>
</BasicTable>
/>
<div
class="action-column-scrollbar"
aria-label="操作栏横向滚动条"
@@ -42,7 +36,7 @@
<n-modal
v-model:show="showEdit"
preset="card"
:title="editForm.id ? '编辑会员' : '新增会员'"
title="编辑会员"
class="edit-modal"
>
<n-spin :show="editLoading">
@@ -63,12 +57,10 @@
<n-form-item label="用户名称" path="username" required
><n-input v-model:value="editForm.username" placeholder="请输入用户名称"
/></n-form-item>
<n-form-item label="手机号码" path="mobile" :required="!editForm.id"
<n-form-item label="手机号码" path="mobile"
><n-input
v-model:value="editForm.mobile"
:placeholder="
editForm.id ? editForm.currentMobile || '留空不修改' : '请输入手机号码'
"
:placeholder="editForm.currentMobile || '留空不修改'"
/></n-form-item>
<n-form-item label="账户余额"
><n-input :value="money(editForm.availableAmount)" disabled
@@ -92,12 +84,12 @@
v-model:value="editForm.riskStatus"
:options="dict.getOptionUnRef('appMemberRiskStatus')"
/></n-form-item>
<n-form-item label="登录密码" path="password" :required="!editForm.id"
<n-form-item label="登录密码" path="password"
><n-input
v-model:value="editForm.password"
type="password"
show-password-on="click"
:placeholder="editForm.id ? '留空不修改' : '至少8位,含字母和数字'"
placeholder="留空不修改"
/></n-form-item>
<n-form-item label="交易密码" path="tradePassword"
><n-input
@@ -151,6 +143,9 @@
<n-descriptions-item label="收货地址">{{ detail.addressCount }} 个</n-descriptions-item>
<n-descriptions-item label="下级团队">{{ detail.teamCount }} 人</n-descriptions-item>
<n-descriptions-item label="注册时间">{{ detail.createdAt }}</n-descriptions-item>
<n-descriptions-item label="注册域名">{{ detail.registerDomain || '待绑定' }}</n-descriptions-item>
<n-descriptions-item label="域名状态">{{ dict.getLabel('appMemberDomainStatus', detail.domainStatus) }}</n-descriptions-item>
<n-descriptions-item label="绑定时间">{{ detail.domainBoundAt || '-' }}</n-descriptions-item>
</n-descriptions>
<n-divider />
<n-space>
@@ -469,14 +464,13 @@
{ min: 3, max: 64, message: '用户名长度为3到64个字符', trigger: ['input', 'blur'] },
],
mobile: {
validator: (_rule, value) =>
editForm.id || String(value || '').trim() ? true : new Error('请输入手机号码'),
validator: () => true,
trigger: ['input', 'blur'],
},
password: {
validator: (_rule, value) => {
const text = String(value || '');
if (editForm.id && !text) return true;
if (!text) return true;
if (text.length < 8 || !/[A-Za-z]/.test(text) || !/\d/.test(text))
return new Error('密码至少8位且必须同时包含字母和数字');
return true;
@@ -511,6 +505,12 @@
h(TableAction as any, {
style: 'button',
actions: [
{
label: '详情',
type: 'default',
onClick: () => openDetail(record.id),
auth: ['/appMember/view'],
},
{
label: '编辑',
type: 'primary',
@@ -602,7 +602,7 @@
actionScrollLeft = externalMax > 0 ? (el.scrollLeft * actionMax) / externalMax : 0;
syncActionViewports(actionScrollLeft);
}
async function openEdit(row?: MemberRecord) {
async function openEdit(row: MemberRecord) {
reset(editForm, {
id: row?.id || 0,
username: row?.username || '',
@@ -621,7 +621,6 @@
frozenAmount: row?.frozenAmount || 0,
});
showEdit.value = true;
if (!row?.id) return;
editLoading.value = true;
try {
const data: any = await View({ id: row.id });