feat: 修改昵称,修改手机号
This commit is contained in:
@ -87,3 +87,8 @@ export const getMyEnterprises = () => {
|
|||||||
export const getMyPrimaryEnterprise = () => {
|
export const getMyPrimaryEnterprise = () => {
|
||||||
return Http.get('/v1/me/primary-enterprise');
|
return Http.get('/v1/me/primary-enterprise');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 发送修改手机号验证码
|
||||||
|
export const postUpdateMobileCaptcha = (params = {}) => {
|
||||||
|
return Http.post('/v1/sms/update-mobile-captcha', params);
|
||||||
|
};
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
color: #211f24;
|
color: #211f24;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 500;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,200 @@
|
|||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
class="change-mobile-modal"
|
||||||
|
centered
|
||||||
|
v-model:open="visible"
|
||||||
|
title="修改手机号"
|
||||||
|
@cancel="onClose"
|
||||||
|
:footer="null"
|
||||||
|
>
|
||||||
|
<Form
|
||||||
|
:model="form"
|
||||||
|
ref="formRef"
|
||||||
|
:rules="formRules"
|
||||||
|
labelAlign="right"
|
||||||
|
:labelCol="{ span: 5 }"
|
||||||
|
:wrapperCol="{ span: 19 }"
|
||||||
|
>
|
||||||
|
<FormItem label="手机号" name="mobile">
|
||||||
|
<Input v-model:value="form.mobile" placeholder="请输入新的手机号" size="large" />
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem label="获取验证码" name="captcha">
|
||||||
|
<Input v-model:value="form.captcha" placeholder="请输入验证码" size="large" :maxlength="6">
|
||||||
|
<template #suffix>
|
||||||
|
<div class="w-79px flex justify-center whitespace-nowrap">
|
||||||
|
<span
|
||||||
|
class="color-#939499 font-family-regular text-16px font-400 lh-24px cursor-not-allowed"
|
||||||
|
:class="{
|
||||||
|
'!color-#6D4CFE': isLegalMobile || countdown > 0,
|
||||||
|
'!cursor-pointer': canGetCaptcha,
|
||||||
|
}"
|
||||||
|
@click="getCode"
|
||||||
|
>{{ countdown > 0 ? `${countdown}s` : hasGetCode ? '重新发送' : '发送验证码' }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Input>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
<div class="flex justify-end mt-20px">
|
||||||
|
<Button class="mr-16px" size="large" @click="onClose">取消</Button>
|
||||||
|
<Button type="primary" size="large" @click="handleConfirm">确定</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed, onUnmounted, ref } from 'vue';
|
||||||
|
import { Button, Form, FormItem, Input, message, Modal } from 'ant-design-vue';
|
||||||
|
import { postUpdateMobileCaptcha } from '@/api/all/login';
|
||||||
|
import { updateMobile } from '@/api/all';
|
||||||
|
import { useUserStore } from '@/stores';
|
||||||
|
|
||||||
|
const store = useUserStore();
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
const visible = ref(false);
|
||||||
|
const timer = ref();
|
||||||
|
const isLegalMobile = ref(false);
|
||||||
|
const hasGetCode = ref(false);
|
||||||
|
|
||||||
|
const countdown = ref(0);
|
||||||
|
|
||||||
|
const formRules = {
|
||||||
|
mobile: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (_rule, value) => {
|
||||||
|
if (!value) {
|
||||||
|
isLegalMobile.value = false;
|
||||||
|
return Promise.reject('手机号不能为空');
|
||||||
|
}
|
||||||
|
if (value && !/^1[3-9]\d{9}$/.test(value)) {
|
||||||
|
isLegalMobile.value = false;
|
||||||
|
return Promise.reject('手机号格式不正确');
|
||||||
|
} else {
|
||||||
|
isLegalMobile.value = true;
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: ['blur'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
captcha: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (_rule, value) => {
|
||||||
|
if (!value) {
|
||||||
|
return Promise.reject('请输入验证码');
|
||||||
|
}
|
||||||
|
if (!/^\d{6}$/.test(value)) {
|
||||||
|
return Promise.reject('验证码必须是6位数字');
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: ['blur'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
mobile: '',
|
||||||
|
captcha: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const canGetCaptcha = computed(() => {
|
||||||
|
return isLegalMobile.value && countdown.value === 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const open = () => {
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 发送验证码
|
||||||
|
const getCode = async () => {
|
||||||
|
if (!canGetCaptcha.value) return;
|
||||||
|
|
||||||
|
formRef.value.validateFields('mobile').then(() => {
|
||||||
|
getCaptcha();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getCaptcha = async () => {
|
||||||
|
try {
|
||||||
|
const { code, message: msg } = await postUpdateMobileCaptcha({ mobile: form.value.mobile });
|
||||||
|
if (code === 200) {
|
||||||
|
startCountdown();
|
||||||
|
message.success(msg);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// 重置倒计时
|
||||||
|
countdown.value = 0;
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const startCountdown = () => {
|
||||||
|
countdown.value = 60;
|
||||||
|
hasGetCode.value = true;
|
||||||
|
timer.value = setInterval(() => {
|
||||||
|
countdown.value--;
|
||||||
|
if (countdown.value <= 0) {
|
||||||
|
clearInterval(timer.value);
|
||||||
|
timer.value = null;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确定按钮点击
|
||||||
|
const handleConfirm = () => {
|
||||||
|
formRef.value.validate().then(async () => {
|
||||||
|
const { code } = await updateMobile(form.value);
|
||||||
|
if (code === 200) {
|
||||||
|
message.success('修改成功!');
|
||||||
|
store.getUserInfo();
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消按钮点击
|
||||||
|
const onClose = () => {
|
||||||
|
form.value = {
|
||||||
|
mobile: '',
|
||||||
|
captcha: '',
|
||||||
|
};
|
||||||
|
countdown.value = 0;
|
||||||
|
visible.value = false;
|
||||||
|
|
||||||
|
formRef.value.resetFields();
|
||||||
|
formRef.value.clearValidate();
|
||||||
|
};
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timer.value) {
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 暴露方法供外部调用
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.change-mobile-modal {
|
||||||
|
.ant-modal-header {
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
.ant-modal-body {
|
||||||
|
padding: 20px 24px !important;
|
||||||
|
}
|
||||||
|
.ant-modal-footer {
|
||||||
|
height: 56px !important;
|
||||||
|
border-top: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<Modal
|
||||||
|
class="change-name-modal"
|
||||||
|
v-model:open="visible"
|
||||||
|
centered
|
||||||
|
:width="480"
|
||||||
|
title="修改昵称"
|
||||||
|
:footer="null"
|
||||||
|
@cancel="onClose"
|
||||||
|
>
|
||||||
|
<Form :model="form" ref="formRef">
|
||||||
|
<FormItem label="昵称" name="name">
|
||||||
|
<Input v-model:value="form.name" placeholder="请输入新昵称" size="large" />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
<div class="flex justify-end mt-20px">
|
||||||
|
<Button class="mr-16px" size="large" @click="onClose">取消</Button>
|
||||||
|
<Button type="primary" size="large" :loading="loading" @click="handleNicknameConfirm">确定</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { Button, Form, FormItem, Input, message, Modal } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { updateMyInfo } from '@/api/all';
|
||||||
|
import { useUserStore } from '@/stores';
|
||||||
|
|
||||||
|
const store = useUserStore();
|
||||||
|
const formRef = ref();
|
||||||
|
const visible = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const form = ref({
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
const open = (userName) => {
|
||||||
|
form.value.name = userName;
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确定按钮点击
|
||||||
|
const handleNicknameConfirm = async () => {
|
||||||
|
const { code } = await updateMyInfo(form.value);
|
||||||
|
if (code === 200) {
|
||||||
|
message.success('修改成功!');
|
||||||
|
store.getUserInfo();
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消按钮点击
|
||||||
|
const onClose = () => {
|
||||||
|
form.value.name = '';
|
||||||
|
visible.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暴露方法供外部调用
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.change-name-modal {
|
||||||
|
.ant-modal-header {
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
.ant-modal-body {
|
||||||
|
padding: 20px 24px !important;
|
||||||
|
}
|
||||||
|
.ant-modal-footer {
|
||||||
|
height: 56px !important;
|
||||||
|
border-top: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<Modal v-model:open="visible" :title="title" :width="400" centered :footer="null" class="safety-verification-modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="description">
|
||||||
|
<p class="title-text">安全验证</p>
|
||||||
|
<p class="desc-text">为进一步保证您的账号安全,确保为您本人操作,请先完成安全验证</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="verify-section">
|
||||||
|
<div class="phone-info">
|
||||||
|
<span class="label">请输入发送至</span>
|
||||||
|
<span class="phone-number">{{ formattedPhone }}</span>
|
||||||
|
<span class="label">的短信验证码</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="captcha-input">
|
||||||
|
<div class="input-group">
|
||||||
|
<Input
|
||||||
|
v-model:value="captcha"
|
||||||
|
type="password"
|
||||||
|
maxlength="6"
|
||||||
|
placeholder="请输入验证码"
|
||||||
|
@input="handleCaptchaInput"
|
||||||
|
@blur="handleCaptchaBlur"
|
||||||
|
@focus="handleCaptchaFocus"
|
||||||
|
class="captcha-input-field"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="countdown">
|
||||||
|
<span v-if="countdown > 0" class="countdown-text"> {{ countdown }}秒后可以再次发送验证码 </span>
|
||||||
|
<span v-else class="resend-btn" @click="sendCaptcha"> 发送验证码 </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-buttons">
|
||||||
|
<Button type="primary" @click="handleSubmit" :disabled="!captcha || captcha.length !== 6"> 确认验证 </Button>
|
||||||
|
<Button @click="handleCancel">取消</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue';
|
||||||
|
import { Button, Input, message, Modal } from 'ant-design-vue';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
onVerifySuccess?: (captcha: string) => void;
|
||||||
|
onVerifyCancel?: () => void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(['success', 'cancel']);
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const phone = ref('');
|
||||||
|
|
||||||
|
// 格式化手机号显示(隐藏中间4位)
|
||||||
|
const formattedPhone = computed(() => {
|
||||||
|
if (!phone.value) return '';
|
||||||
|
return phone.value.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 验证码输入相关
|
||||||
|
const captcha = ref('');
|
||||||
|
const countdown = ref(0);
|
||||||
|
const timer = ref<number | null>(null);
|
||||||
|
|
||||||
|
// 处理验证码输入
|
||||||
|
const handleCaptchaInput = (value: string) => {
|
||||||
|
// 只允许数字输入,且最多6位
|
||||||
|
const numericValue = value.replace(/[^0-9]/g, '');
|
||||||
|
captcha.value = numericValue.slice(0, 6);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理焦点事件
|
||||||
|
const handleCaptchaFocus = () => {
|
||||||
|
// 可以在这里添加焦点效果
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCaptchaBlur = () => {
|
||||||
|
// 可以在这里添加失焦效果
|
||||||
|
};
|
||||||
|
|
||||||
|
// 发送验证码
|
||||||
|
const sendCaptcha = async () => {
|
||||||
|
if (countdown.value > 0) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 这里应该调用实际的API发送验证码
|
||||||
|
// 示例:await sendCaptchaApi({ phone: phone.value });
|
||||||
|
|
||||||
|
// 模拟成功发送
|
||||||
|
message.success('验证码已发送,请注意查收');
|
||||||
|
|
||||||
|
// 开始倒计时
|
||||||
|
startCountdown();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('发送失败,请重试');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 开始倒计时
|
||||||
|
const startCountdown = () => {
|
||||||
|
countdown.value = 60;
|
||||||
|
timer.value = window.setInterval(() => {
|
||||||
|
countdown.value--;
|
||||||
|
if (countdown.value <= 0) {
|
||||||
|
clearInterval(timer.value as number);
|
||||||
|
timer.value = null;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交验证
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
if (!captcha.value || captcha.value.length !== 6) {
|
||||||
|
message.error('请输入正确的6位验证码');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 这里应该调用实际的API验证验证码
|
||||||
|
// 示例:await verifyCaptchaApi({ phone: phone.value, captcha: captcha.value });
|
||||||
|
|
||||||
|
// 模拟验证成功
|
||||||
|
message.success('验证成功!');
|
||||||
|
|
||||||
|
// 触发成功回调
|
||||||
|
if (props.onVerifySuccess) {
|
||||||
|
props.onVerifySuccess(captcha.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭弹窗
|
||||||
|
emit('success', captcha.value);
|
||||||
|
close();
|
||||||
|
} catch (error) {
|
||||||
|
message.error('验证失败,请检查验证码是否正确');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消验证
|
||||||
|
const handleCancel = () => {
|
||||||
|
close();
|
||||||
|
};
|
||||||
|
|
||||||
|
const open = (mobile) => {
|
||||||
|
phone.value = mobile;
|
||||||
|
visible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
visible.value = false;
|
||||||
|
phone.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
});
|
||||||
|
// 组件销毁时清理定时器
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timer.value) {
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import './style.scss';
|
||||||
|
</style>
|
||||||
@ -0,0 +1,110 @@
|
|||||||
|
.safety-verification-modal {
|
||||||
|
.modal-content {
|
||||||
|
padding: 24px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #211f24;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #737478;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.verify-section {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.phone-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #737478;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone-number {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #211f24;
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.captcha-input {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.captcha-input-field {
|
||||||
|
width: 200px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid var(--BG-400, rgba(215, 215, 217, 1));
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--Brand-Brand-6, rgba(109, 76, 254, 1));
|
||||||
|
box-shadow: 0 2px 4px 0 rgba(109, 76, 254, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.countdown {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #737478;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.countdown-text {
|
||||||
|
color: #737478;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resend-btn {
|
||||||
|
color: var(--Brand-Brand-6, rgba(109, 76, 254, 1));
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: color 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--Brand-Brand-7, rgba(95, 67, 238, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.arco-btn {
|
||||||
|
min-width: 100px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arco-btn-primary {
|
||||||
|
background-color: var(--Brand-Brand-6, rgba(109, 76, 254, 1));
|
||||||
|
border-color: var(--Brand-Brand-6, rgba(109, 76, 254, 1));
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--Brand-Brand-7, rgba(95, 67, 238, 1));
|
||||||
|
border-color: var(--Brand-Brand-7, rgba(95, 67, 238, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
src/views/components/management/person/img/icon1.png
Normal file
BIN
src/views/components/management/person/img/icon1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@ -1,26 +1,55 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="bg-#fff rounded-16px w-100% p-36px">
|
<div class="bg-#fff rounded-16px w-100% p-36px person-wrap">
|
||||||
<p class="title mb-32px">个人信息</p>
|
<p class="title mb-32px">个人信息</p>
|
||||||
<Table :dataSource="dataSource" :pagination="false" :showSorterTooltip="false" class="mt-8px">
|
<div class="flex items-center">
|
||||||
<Table.Column title="用户信息" dataIndex="info">
|
<div class="mr-60px relative cursor-pointer" @click="openEditInfoModal">
|
||||||
<template #customRender="{ record }">
|
<Avatar :src="dataSource.head_image" :size="100" />
|
||||||
<div class="pt-3px pb-3px">
|
<img :src="icon1" width="20" height="20" class="absolute right-5px bottom-4px" />
|
||||||
<Avatar :src="record.head_image" :size="32" />
|
|
||||||
{{ record.name || '-' }}
|
|
||||||
<icon-edit size="13" class="ml-8px" @click="openEditInfoModal" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<div class="flex-1 flex h-68px">
|
||||||
</Table.Column>
|
<div class="flex flex-1">
|
||||||
<Table.Column title="手机号" dataIndex="mobile">
|
<span class="cts mr-4p">昵称:</span>
|
||||||
<template #customRender="{ record }">
|
<span class="cts !color-#211F24 bold !font-500 mr-12px">{{ dataSource.name || '-' }}</span>
|
||||||
{{ record.mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') }}
|
<Button type="text" size="small" class="!p-0 !h-22px m-0" @click="openChangeNameModal">编辑</Button>
|
||||||
<icon-edit size="13" class="ml-8px" @click="openEditMobileModal" />
|
</div>
|
||||||
</template>
|
<div class="flex-1">
|
||||||
</Table.Column>
|
<div class="flex items-center mb-24px">
|
||||||
<template #emptyText>
|
<span class="cts mr-4px w-56px">手机号:</span>
|
||||||
<NoData />
|
<span class="cts !color-#211F24 bold !font-500 mr-12px">{{ mobile }}</span>
|
||||||
</template>
|
<Button type="text" size="small" class="!p-0 !h-22px m-0" @click="openChangeMobileModal">更改</Button>
|
||||||
</Table>
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="cts mr-4px w-56px">密码:</span>
|
||||||
|
<span
|
||||||
|
class="!bg-#211F24 bold !font-500 w-6px h-6px rounded-50% mr-2px"
|
||||||
|
v-for="(item, index) in new Array(10).fill(0)"
|
||||||
|
:key="index"
|
||||||
|
></span>
|
||||||
|
<Button type="text" size="small" class="!p-0 !h-22px ml-10px">更改</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <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>-->
|
||||||
|
<!-- </Table>-->
|
||||||
<Modal v-model:open="infoVisible" centered title="修改用户信息" @ok="handleSubmitUserInfo">
|
<Modal v-model:open="infoVisible" centered title="修改用户信息" @ok="handleSubmitUserInfo">
|
||||||
<Form
|
<Form
|
||||||
class="form"
|
class="form"
|
||||||
@ -80,21 +109,38 @@
|
|||||||
@cancel="verificationVisible = false"
|
@cancel="verificationVisible = false"
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<SafetyVerificationModal
|
||||||
|
ref="safetyVerificationModalRef"
|
||||||
|
@success="handleVerifySuccess"
|
||||||
|
@cancel="handleVerifyCancel"
|
||||||
|
/>
|
||||||
|
<ChangeNameModal ref="changeNameModalRef" />
|
||||||
|
<ChangeMobileModal ref="changeMobileModalRef" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Button, Form, FormItem, Input, Table, message, Avatar } from 'ant-design-vue';
|
import { Avatar, Button, Form, FormItem, Input, message } from 'ant-design-vue';
|
||||||
import Container from '@/components/container.vue';
|
|
||||||
import Modal from '@/components/modal.vue';
|
import Modal from '@/components/modal.vue';
|
||||||
import PuzzleVerification from '@/views/login/components/PuzzleVerification.vue';
|
import PuzzleVerification from '@/views/login/components/PuzzleVerification.vue';
|
||||||
import { ref, reactive } from 'vue';
|
import SafetyVerificationModal from './components/safety-verification-modal/index.vue';
|
||||||
|
import ChangeNameModal from './components/change-name-modal/index.vue';
|
||||||
|
import ChangeMobileModal from './components/change-mobile-modal/index.vue';
|
||||||
|
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
import 'vue-cropper/dist/index.css';
|
import 'vue-cropper/dist/index.css';
|
||||||
import { VueCropper } from 'vue-cropper';
|
import { VueCropper } from 'vue-cropper';
|
||||||
import { sendUpdateMobileCaptcha, updateMobile, fetchImageUploadFile, updateMyInfo } from '@/api/all';
|
import { fetchImageUploadFile, sendUpdateMobileCaptcha, updateMobile, updateMyInfo } from '@/api/all';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { useUserStore } from '@/stores';
|
import { useUserStore } from '@/stores';
|
||||||
|
|
||||||
|
import icon1 from './img/icon1.png';
|
||||||
|
|
||||||
const store = useUserStore();
|
const store = useUserStore();
|
||||||
|
const safetyVerificationModalRef = ref(null);
|
||||||
|
const changeNameModalRef = ref(null);
|
||||||
|
const changeMobileModalRef = ref(null);
|
||||||
|
|
||||||
// const userInfo = computed(() => {
|
// const userInfo = computed(() => {
|
||||||
// return store.userInfo ?? {};
|
// return store.userInfo ?? {};
|
||||||
// });
|
// });
|
||||||
@ -120,12 +166,16 @@ const formRef = ref();
|
|||||||
const isSendCaptcha = ref(false);
|
const isSendCaptcha = ref(false);
|
||||||
const uploadInputRef = ref();
|
const uploadInputRef = ref();
|
||||||
|
|
||||||
// console.log(userInfo.value)
|
|
||||||
const dataSource = computed(() => {
|
const dataSource = computed(() => {
|
||||||
return !isEmpty(store.userInfo) ? [store.userInfo] : [];
|
return store.userInfo;
|
||||||
|
});
|
||||||
|
const mobile = computed(() => {
|
||||||
|
const _mobile = dataSource.value.mobile;
|
||||||
|
if (!_mobile) return '-';
|
||||||
|
return _mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(dataSource.value)
|
console.log(store.userInfo);
|
||||||
|
|
||||||
// 表单校验规则
|
// 表单校验规则
|
||||||
const formRules = {
|
const formRules = {
|
||||||
@ -199,13 +249,13 @@ async function handleFileChange(event: Event) {
|
|||||||
userInfoForm.file_url = file_url;
|
userInfoForm.file_url = file_url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function openEditImageModal() {
|
|
||||||
imageVisible.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function openEditMobileModal() {
|
const openChangeNameModal = () => {
|
||||||
mobileVisible.value = true;
|
changeNameModalRef.value.open(dataSource.name);
|
||||||
}
|
};
|
||||||
|
const openChangeMobileModal = () => {
|
||||||
|
changeMobileModalRef.value.open();
|
||||||
|
};
|
||||||
|
|
||||||
async function handleSubmitUserInfo() {
|
async function handleSubmitUserInfo() {
|
||||||
await updateMyInfo(userInfoForm);
|
await updateMyInfo(userInfoForm);
|
||||||
@ -261,17 +311,23 @@ function getFileExtension(filename: string): string {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
@import './style.scss';
|
||||||
|
</style>
|
||||||
|
<style scoped lang="scss">
|
||||||
.form {
|
.form {
|
||||||
margin-top: 13px;
|
margin-top: 13px;
|
||||||
|
|
||||||
:deep(.arco-row) {
|
:deep(.arco-row) {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.arco-form-item-label) {
|
:deep(.arco-form-item-label) {
|
||||||
font-family: $font-family-medium;
|
font-family: $font-family-medium;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.arco-input-wrapper) {
|
:deep(.arco-input-wrapper) {
|
||||||
background: white;
|
background: white;
|
||||||
border: 1px solid var(--BG-400, rgba(215, 215, 217, 1));
|
border: 1px solid var(--BG-400, rgba(215, 215, 217, 1));
|
||||||
@ -279,6 +335,7 @@ function getFileExtension(filename: string): string {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
|
|
||||||
input::placeholder {
|
input::placeholder {
|
||||||
font-family: $font-family-medium;
|
font-family: $font-family-medium;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@ -286,24 +343,29 @@ function getFileExtension(filename: string): string {
|
|||||||
color: var(--Text-4, rgba(147, 148, 153, 1));
|
color: var(--Text-4, rgba(147, 148, 153, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.arco-input-disabled) {
|
:deep(.arco-input-disabled) {
|
||||||
background: var(--BG-200, rgba(242, 243, 245, 1));
|
background: var(--BG-200, rgba(242, 243, 245, 1));
|
||||||
border: 1px solid var(--BG-400, rgba(215, 215, 217, 1));
|
border: 1px solid var(--BG-400, rgba(215, 215, 217, 1));
|
||||||
|
|
||||||
.arco-input:disabled {
|
.arco-input:disabled {
|
||||||
font-family: $font-family-medium;
|
font-family: $font-family-medium;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.arco-input-focus) {
|
:deep(.arco-input-focus) {
|
||||||
border: 1px solid var(--Brand-Brand-6, rgba(109, 76, 254, 1));
|
border: 1px solid var(--Brand-Brand-6, rgba(109, 76, 254, 1));
|
||||||
box-shadow: 0 2px 4px 0 rgba(109, 76, 254, 0.2);
|
box-shadow: 0 2px 4px 0 rgba(109, 76, 254, 0.2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-button {
|
.upload-button {
|
||||||
width: 104px;
|
width: 104px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
|
|
||||||
:deep(.arco-btn) {
|
:deep(.arco-btn) {
|
||||||
width: 104px;
|
width: 104px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
@ -317,6 +379,7 @@ function getFileExtension(filename: string): string {
|
|||||||
color: var(--Text-2, rgba(60, 64, 67, 1));
|
color: var(--Text-2, rgba(60, 64, 67, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: var(--Text-1, #211f24);
|
color: var(--Text-1, #211f24);
|
||||||
font-family: $font-family-medium;
|
font-family: $font-family-medium;
|
||||||
|
|||||||
13
src/views/components/management/person/style.scss
Normal file
13
src/views/components/management/person/style.scss
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.person-wrap {
|
||||||
|
.cts {
|
||||||
|
color: var(--Text-4, #939499);
|
||||||
|
font-family: $font-family-regular;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 22px; /* 157.143% */
|
||||||
|
&.bold {
|
||||||
|
font-family: $font-family-medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user