Merge remote-tracking branch 'origin/main' into feature/0905_登录注册流程重构
# Conflicts: # src/App.vue # src/views/components/login/index.vue # src/views/components/management/person/index.vue # src/views/login/style.scss
This commit is contained in:
@ -2,40 +2,44 @@
|
||||
<div class="bg-#fff rounded-8px w-100% py-0 px-20px pb-24px">
|
||||
<div class="title-row">
|
||||
<span class="title">账号管理</span>
|
||||
<a-button type="outline" class="add-account-button" @click="handleAddAccount">添加子账号</a-button>
|
||||
<Button type="primary" ghost class="add-account-button" @click="handleAddAccount">添加子账号</Button>
|
||||
</div>
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data="dataSource"
|
||||
<Table
|
||||
:dataSource="dataSource"
|
||||
:pagination="pagination"
|
||||
:showSorterTooltip="false"
|
||||
class="mt-8px"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<template #empty>
|
||||
<Table.Column title="手机号" dataIndex="mobile">
|
||||
<template #customRender="{ record }">
|
||||
<div class="flex item-center pt-13px pb-13px">
|
||||
<span class="mr-4px">{{ record.mobile }}</span>
|
||||
<Tag v-if="record.type === 0" class="primary-account">主账号</Tag>
|
||||
<Tag v-else class="sub-account">子账号</Tag>
|
||||
</div>
|
||||
</template>
|
||||
</Table.Column>
|
||||
<Table.Column title="操作" dataIndex="action" width="120">
|
||||
<template #customRender="{ record }">
|
||||
<Button
|
||||
v-if="record.type !== 0"
|
||||
class="delete-button"
|
||||
size="small"
|
||||
type="primary"
|
||||
ghost
|
||||
danger
|
||||
@click="openDeleteModal(record)"
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</template>
|
||||
</Table.Column>
|
||||
<template #emptyText>
|
||||
<NoData />
|
||||
</template>
|
||||
<template #mobile="{ record }">
|
||||
<div class="flex item-center pt-13px pb-13px">
|
||||
<span class="mr-4px">{{ record.mobile }}</span>
|
||||
<a-tag v-if="record.type === 0" class="primary-account">主账号</a-tag>
|
||||
<a-tag v-else class="sub-account">子账号</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<a-button
|
||||
v-if="record.type !== 0"
|
||||
class="delete-button"
|
||||
size="mini"
|
||||
type="outline"
|
||||
status="danger"
|
||||
@click="openDeleteModal(record)"
|
||||
>
|
||||
删除
|
||||
</a-button>
|
||||
</template>
|
||||
</a-table>
|
||||
<Modal v-model:visible="addAccountVisible" width="480px" title="添加子账号" :okText="okText" @ok="handleOk">
|
||||
</Table>
|
||||
<Modal v-model:open="addAccountVisible" centered width="480px" title="添加子账号" :okText="okText" @ok="handleOk" >
|
||||
<div v-if="canAddAccount" class="add-account-container">
|
||||
<h2 class="add-account-title">生成企业专属链接,成员通过访问即可注册并加入企业账号。</h2>
|
||||
<p class="add-account-subtitle">子账号可独立登录,权限继承主账号配置。</p>
|
||||
@ -52,15 +56,15 @@
|
||||
<p class="cannot-add-account-subtitle">如需添加更多子账号,您可联系销售人员进行购买和权限扩展。</p>
|
||||
</div>
|
||||
</Modal>
|
||||
<CustomerServiceModal v-model:visible="customerServiceVisible" />
|
||||
<DeleteModal v-model:visible="deleteVisible" :title="deleteTitle" @ok="handleDelete">
|
||||
<p class="delete-modal-content">删除后,该账号将无法登录您的企业。</p>
|
||||
<CustomerServiceModal v-model:open="customerServiceVisible" centered/>
|
||||
<DeleteModal v-model:open="deleteVisible" centered :content="deleteTitle" @ok="handleDelete" @cancel="deleteVisible = false">
|
||||
</DeleteModal>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import Container from '@/components/container.vue';
|
||||
import { ref, onMounted, reactive, computed } from 'vue';
|
||||
import { Button, Table, message, Tag } from 'ant-design-vue';
|
||||
|
||||
import { fetchSubAccountPage, removeEnterpriseAccount, getEnterpriseInviteCode } from '@/api/all';
|
||||
import Modal from '@/components/modal.vue';
|
||||
import DeleteModal from '@/components/delete-modal.vue';
|
||||
@ -82,10 +86,10 @@ const columns = [
|
||||
const dataSource = ref([]);
|
||||
const pagination = reactive({
|
||||
total: 0,
|
||||
showPageSize: true,
|
||||
showTotal: true,
|
||||
defaultCurrent: 1,
|
||||
defaultPageSize: 10,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total: number, range: [number, number]) => `共 ${total} 条记录`,
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
});
|
||||
|
||||
const params = reactive({
|
||||
@ -120,13 +124,12 @@ const currentSelectAccount = ref();
|
||||
|
||||
const { copy, copied, isSupported } = useClipboard({ source: inviteUrl });
|
||||
|
||||
function handlePageChange(current: number) {
|
||||
params.page = current;
|
||||
getSubAccount();
|
||||
}
|
||||
|
||||
function handlePageSizeChange(pageSize: number) {
|
||||
params.page_size = pageSize;
|
||||
function handleTableChange(paginationInfo: any, filters: any, sorter: any) {
|
||||
params.page = paginationInfo.current;
|
||||
params.page_size = paginationInfo.pageSize;
|
||||
// 更新分页状态
|
||||
pagination.current = paginationInfo.current;
|
||||
pagination.pageSize = paginationInfo.pageSize;
|
||||
getSubAccount();
|
||||
}
|
||||
|
||||
@ -155,13 +158,13 @@ function handleOk() {
|
||||
return;
|
||||
}
|
||||
if (!isSupported) {
|
||||
AMessage.error('您的浏览器不支持复制,请手动复制!');
|
||||
message.error('您的浏览器不支持复制,请手动复制!');
|
||||
}
|
||||
copy(inviteUrl.value);
|
||||
if (!copied) {
|
||||
AMessage.error('复制失败,请手动复制!');
|
||||
message.error('复制失败,请手动复制!');
|
||||
}
|
||||
AMessage.success('复制成功!');
|
||||
message.success('复制成功!');
|
||||
}
|
||||
|
||||
function openDeleteModal(record: { id: number; mobile: string }) {
|
||||
@ -172,7 +175,7 @@ function openDeleteModal(record: { id: number; mobile: string }) {
|
||||
|
||||
async function handleDelete() {
|
||||
await removeEnterpriseAccount(currentSelectAccount.value.id);
|
||||
AMessage.success('移除成功!');
|
||||
message.success('移除成功!');
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@ -275,14 +278,7 @@ onMounted(() => {
|
||||
color: var(--Text-2, rgba(60, 64, 67, 1));
|
||||
}
|
||||
}
|
||||
.delete-modal-content {
|
||||
margin-left: 34px;
|
||||
margin-top: 16px;
|
||||
font-family: $font-family-medium;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: var(--Text-2, rgba(60, 64, 67, 1));
|
||||
}
|
||||
|
||||
.title-row {
|
||||
display: flex;
|
||||
height: 64px;
|
||||
|
||||
@ -3,39 +3,53 @@
|
||||
<div class="title-row">
|
||||
<span class="title">企业信息</span>
|
||||
</div>
|
||||
<a-table :columns="columns" :data="dataSource" :pagination="false" class="mt-8px">
|
||||
<template #empty>
|
||||
<Table :dataSource="dataSource" :pagination="false" :showSorterTooltip="false" class="mt-8px">
|
||||
<Table.Column title="企业信息" dataIndex="info">
|
||||
<template #customRender="{ record }">
|
||||
{{ record.name }}
|
||||
</template>
|
||||
</Table.Column>
|
||||
<Table.Column title="操作" dataIndex="action" width="120">
|
||||
<template #customRender>
|
||||
<Button class="edit-button" size="small" type="primary" ghost @click="handleUpdate">修改</Button>
|
||||
</template>
|
||||
</Table.Column>
|
||||
<template #emptyText>
|
||||
<NoData />
|
||||
</template>
|
||||
<template #info="{ record }">
|
||||
{{ record.name }}
|
||||
</template>
|
||||
<template #action>
|
||||
<a-button class="edit-button" size="mini" type="outline" @click="handleUpdate">修改</a-button>
|
||||
</template>
|
||||
</a-table>
|
||||
<Modal v-model:visible="infoVisible" width="480px" title="修改企业名称" :okText="okText" @ok="handleOk">
|
||||
</Table>
|
||||
<Modal
|
||||
v-model:open="infoVisible"
|
||||
width="480px"
|
||||
centered
|
||||
title="修改企业名称"
|
||||
:okText="okText"
|
||||
@ok="handleOk"
|
||||
cancelText="取消"
|
||||
>
|
||||
<p class="tips">
|
||||
企业名称只能修改2次,请谨慎操作。<span
|
||||
>(剩余{{ enterpriseInfo!.update_name_quota - enterpriseInfo!.used_update_name_count }}次)
|
||||
</span>
|
||||
</p>
|
||||
<a-form
|
||||
<Form
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
class="form"
|
||||
:label-col-props="{ span: 6, offset: 0 }"
|
||||
:wrapper-col-props="{ span: 18, offset: 0 }"
|
||||
label-align="left"
|
||||
>
|
||||
<a-form-item required field="name" label="新企业名称">
|
||||
<a-input v-model.trim="form.name" size="small" :disabled="!canUpdate" placeholder="请输入新企业名称" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<FormItem required name="name" label="新企业名称">
|
||||
<Input v-model:value.trim="form.name" size="small" :disabled="!canUpdate" placeholder="请输入新企业名称" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
<CustomerServiceModal v-model:visible="customerServiceVisible" />
|
||||
<CustomerServiceModal v-model:open="customerServiceVisible" centered />
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Button, Form, FormItem, Input, Table, message } from 'ant-design-vue';
|
||||
import Container from '@/components/container.vue';
|
||||
import Modal from '@/components/modal.vue';
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
@ -48,6 +62,16 @@ const form = reactive({
|
||||
name: '',
|
||||
});
|
||||
|
||||
const rules = {
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入新企业名称',
|
||||
trigger: ['blur'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const enterpriseInfo = computed(() => {
|
||||
return store.enterpriseInfo ?? {};
|
||||
});
|
||||
@ -98,7 +122,7 @@ async function handleOk() {
|
||||
await updateEnterpriseName({ name: form.name });
|
||||
store.setEnterpriseName(form.name);
|
||||
store.incUsedUpdateNameCount();
|
||||
AMessage.success('修改成功!');
|
||||
message.success('修改成功!');
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,32 +1,37 @@
|
||||
<template>
|
||||
<div class="bg-#fff rounded-16px w-100% p-36px">
|
||||
<p class="title mb-32px">个人信息</p>
|
||||
<a-table :columns="columns" :data="dataSource" :pagination="false" class="mt-8px">
|
||||
<template #empty>
|
||||
<Table :dataSource="dataSource" :pagination="false" :showSorterTooltip="false" class="mt-8px">
|
||||
<Table.Column title="用户信息" dataIndex="info">
|
||||
<template #customRender="{ record }">
|
||||
<div class="pt-3px pb-3px">
|
||||
<Avatar :src="record.head_image" :size="32" />
|
||||
{{ record.name || '-' }}
|
||||
<icon-edit size="13" class="ml-8px" @click="openEditInfoModal" />
|
||||
</div>
|
||||
</template>
|
||||
</Table.Column>
|
||||
<Table.Column title="手机号" dataIndex="mobile">
|
||||
<template #customRender="{ record }">
|
||||
{{ record.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') }}
|
||||
<icon-edit size="13" class="ml-8px" @click="openEditMobileModal" />
|
||||
</template>
|
||||
</Table.Column>
|
||||
<template #emptyText>
|
||||
<NoData />
|
||||
</template>
|
||||
<template #info="{ record }">
|
||||
<div class="pt-3px pb-3px">
|
||||
<a-avatar :image-url="record.head_image" :size="32" />
|
||||
{{ record.name || '-' }}
|
||||
<icon-edit size="13" class="ml-8px" @click="openEditInfoModal" />
|
||||
</div>
|
||||
</template>
|
||||
<template #mobile="{ record }">
|
||||
{{ record.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') }}
|
||||
<icon-edit size="13" class="ml-8px" @click="openEditMobileModal" />
|
||||
</template>
|
||||
</a-table>
|
||||
<Modal v-model:visible="infoVisible" title="修改用户信息" @ok="handleSubmitUserInfo">
|
||||
<a-form
|
||||
</Table>
|
||||
<Modal v-model:open="infoVisible" centered title="修改用户信息" @ok="handleSubmitUserInfo">
|
||||
<Form
|
||||
class="form"
|
||||
:rules="rules"
|
||||
:model="userInfoForm"
|
||||
:label-col-props="{ span: 3, offset: 0 }"
|
||||
:wrapper-col-props="{ span: 21, offset: 0 }"
|
||||
>
|
||||
<a-form-item field="head_image" label="头像">
|
||||
<FormItem name="head_image" label="头像">
|
||||
<div class="flex items-center">
|
||||
<a-avatar :image-url="userInfoForm.file_url" :size="48" />
|
||||
<Avatar :src="userInfoForm.file_url" :size="48" />
|
||||
<span class="upload-button" @click="triggerFileInput">
|
||||
<input
|
||||
ref="uploadInputRef"
|
||||
@ -35,40 +40,40 @@
|
||||
style="display: none"
|
||||
@change="handleFileChange"
|
||||
/>
|
||||
<a-button><icon-upload />上传新头像</a-button>
|
||||
<Button><icon-upload />上传新头像</Button>
|
||||
</span>
|
||||
</div>
|
||||
</a-form-item>
|
||||
<a-form-item field="name" label="昵称">
|
||||
<a-input v-model.trim="userInfoForm.name" placeholder="请输入昵称" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</FormItem>
|
||||
<FormItem name="name" label="昵称">
|
||||
<Input v-model:value="userInfoForm.name" placeholder="请输入昵称" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
<Modal v-model:visible="imageVisible" title="头像裁剪">
|
||||
<Modal v-model:open="imageVisible" centered title="头像裁剪">
|
||||
<VueCropper></VueCropper>
|
||||
</Modal>
|
||||
<Modal v-model:visible="mobileVisible" title="修改手机号" @ok="handleUpdateMobile">
|
||||
<a-form
|
||||
<Modal v-model:open="mobileVisible" centered title="修改手机号" @ok="handleUpdateMobile">
|
||||
<Form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
class="form"
|
||||
:rules="formRules"
|
||||
:label-col-props="{ span: 5, offset: 0 }"
|
||||
:wrapper-col-props="{ span: 19, offset: 0 }"
|
||||
label-align="left"
|
||||
labelAlign="right"
|
||||
:labelCol="{ span: 4 }"
|
||||
:wrapperCol="{ span: 20 }"
|
||||
>
|
||||
<a-form-item required field="mobile" label="新手机号">
|
||||
<a-input v-model.trim="form.mobile" size="small" placeholder="请输入新的手机号" />
|
||||
</a-form-item>
|
||||
<a-form-item required field="captcha" label="获取验证码">
|
||||
<a-input v-model.trim="form.captcha" size="small" placeholder="请输入验证码">
|
||||
<FormItem required name="mobile" label="新手机号">
|
||||
<Input v-model:value="form.mobile" size="small" placeholder="请输入新的手机号" />
|
||||
</FormItem>
|
||||
<FormItem required name="captcha" label="获取验证码">
|
||||
<Input v-model:value="form.captcha" size="small" placeholder="请输入验证码">
|
||||
<template #suffix>
|
||||
<span v-if="countdown <= 0" @click="sendCaptcha">发送验证码</span>
|
||||
<span v-else>{{ countdown }}s</span>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</Input>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<PuzzleVerification
|
||||
:show="verificationVisible"
|
||||
@submit="handleVerificationSubmit"
|
||||
@ -78,6 +83,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Button, Form, FormItem, Input, Table, message, Avatar } from 'ant-design-vue';
|
||||
import Container from '@/components/container.vue';
|
||||
import Modal from '@/components/modal.vue';
|
||||
import PuzzleVerification from '@/views/login/components/PuzzleVerification.vue';
|
||||
@ -122,35 +128,32 @@ const dataSource = computed(() => {
|
||||
const formRules = {
|
||||
mobile: [
|
||||
{
|
||||
required: true,
|
||||
message: '请填写手机号',
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
{
|
||||
validator: (value: string, callback: (error?: string) => void) => {
|
||||
if (!/^1[3-9]\d{9}$/.test(value)) {
|
||||
callback('手机号格式不正确');
|
||||
} else {
|
||||
callback();
|
||||
validator: (_rule: any, value: string) => {
|
||||
if (!value) {
|
||||
return Promise.reject('请填写手机号');
|
||||
}
|
||||
if (!/^1[3-9]\d{9}$/.test(value)) {
|
||||
return Promise.reject('手机号格式不正确');
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
required: true,
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
captcha: [
|
||||
{
|
||||
required: true,
|
||||
message: '请填写验证码',
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
{
|
||||
validator: (value: string, callback: (error?: string) => void) => {
|
||||
if (!/^\d{6}$/.test(value)) {
|
||||
callback('验证码必须是6位数字');
|
||||
} else {
|
||||
callback();
|
||||
validator: (rule, value) => {
|
||||
if (!value) {
|
||||
return Promise.reject('请填写验证码');
|
||||
}
|
||||
if (!/^\d{6}$/.test(value)) {
|
||||
return Promise.reject('验证码必须是6位数字');
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
@ -203,7 +206,7 @@ function openEditMobileModal() {
|
||||
|
||||
async function handleSubmitUserInfo() {
|
||||
await updateMyInfo(userInfoForm);
|
||||
AMessage.success('修改成功!');
|
||||
message.success('修改成功!');
|
||||
}
|
||||
|
||||
async function sendCaptcha() {
|
||||
@ -213,7 +216,7 @@ async function sendCaptcha() {
|
||||
verificationVisible.value = true;
|
||||
isSendCaptcha.value = true;
|
||||
}
|
||||
AMessage.error('请填写正确的手机号!');
|
||||
message.error('请填写正确的手机号!');
|
||||
} catch (error) {
|
||||
console.log('手机号验证失败:', error);
|
||||
}
|
||||
@ -231,7 +234,7 @@ function beginCountdown() {
|
||||
|
||||
async function handleVerificationSubmit() {
|
||||
await sendUpdateMobileCaptcha({ mobile: form.mobile });
|
||||
AMessage.success('发送成功');
|
||||
message.success('发送成功');
|
||||
verificationVisible.value = false;
|
||||
countdown.value = 60;
|
||||
beginCountdown();
|
||||
@ -239,13 +242,13 @@ async function handleVerificationSubmit() {
|
||||
|
||||
async function handleUpdateMobile() {
|
||||
if (!isSendCaptcha.value) {
|
||||
AMessage.error('请先获取验证码!');
|
||||
message.error('请先获取验证码!');
|
||||
return false;
|
||||
}
|
||||
const res = await formRef.value.validate();
|
||||
if (res === true || res === undefined) {
|
||||
await updateMobile(form);
|
||||
AMessage.success('修改成功!');
|
||||
message.success('修改成功!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user