feat(user): 新增短信验证码发送功能- 在 user.js 中添加 send_sms 方法- 在 system.js 中添加 verifyUpdatePassword 方法- 新增 send-phone-code.vue 组件,用于发送和验证短信验证码- 修改 login.vue,使用新的 send-phone-code 组件替换原有短信验证逻辑- 更新 ResetPasswordDialog.vue,集成短信验证码验证功能

This commit is contained in:
陈昱达
2025-08-13 15:50:14 +08:00
parent 8ec1ea2d6a
commit 0e625655fa
6 changed files with 345 additions and 176 deletions

View File

@@ -49,6 +49,12 @@ export function sendPhoneCodeLogin(data) {
data
})
}
export function send_sms() {
return request({
url: getUrl('/sysUserEx/send_sms'),
method: 'get'
})
}
export function verify_login(data) {
return request({
url: getUrl('/sysUserEx/verify_login'),

View File

@@ -62,6 +62,14 @@ export function updatePassword(data) {
return request({
url: getUrl(`/sysUserEx/updatePassword`),
method: 'post',
data,
back: true
})
}
export function verifyUpdatePassword(data) {
return request({
url: getUrl(`/sysUserEx/verifyUpdatePassword`),
method: 'post',
data
})
}

View File

@@ -0,0 +1,197 @@
<template>
<r-dialog
:visible.sync="visible"
title="发送短信验证码"
width="550px"
append-to-body
class="send-chat-phone-dialog"
>
<el-form
label-width="100px"
:model="phoneForm"
:rules="phoneRules"
class="phone-form"
ref="phoneForm"
>
<!-- <el-form-item label="手机号" prop="phone">-->
<!-- <div class="flex">-->
<!-- <el-input-->
<!-- v-model="phoneForm.phone"-->
<!-- placeholder="请输入手机号"-->
<!-- style="color:#000"-->
<!-- ></el-input>-->
<!-- <el-button-->
<!-- class="ml10 render-button pv5 ph10"-->
<!-- type="primary"-->
<!-- size="medium"-->
<!-- @click="sendPhoneCode"-->
<!-- :disabled="!sendCode"-->
<!-- >{{ !sendCode ? minute + '秒后重新发送' : '发送验证码' }}-->
<!-- </el-button>-->
<!-- </div>-->
<!-- </el-form-item>-->
<el-form-item label="短信验证码" prop="code" class="mr30">
<div class="flex">
<el-input
v-model="phoneForm.code"
placeholder="请输入短信验证码"
style="color:#000"
size="medium"
>
<template slot="append">
<el-button
class="ml10"
type="primary"
size="medium"
@click="sendPhoneCode"
:disabled="!sendCode"
>{{ !sendCode ? minute + '秒后重新发送' : '发送短信验证码' }}
</el-button>
</template>
</el-input>
</div>
<!-- <el-input-->
<!-- v-model="phoneForm.code"-->
<!-- placeholder="请输入验证码"-->
<!-- ></el-input>-->
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel" size="medium">取消</el-button>
<el-button type="primary" @click="handleSubmit" size="medium"
>确定</el-button
>
</div>
</r-dialog>
</template>
<script>
import { sendPhoneCodeLogin, send_sms } from '@/api/app/user'
import { setToken } from '@/assets/js/utils/auth'
export default {
name: 'send-phone-code',
data() {
const validatePhone = (rule, value, callback) => {
// 手机号正则
const validPhone = phone => {
return /^1[3456789]\d{9}$/.test(phone)
}
if (!validPhone(value)) {
callback(new Error('请输入正确的手机号'))
} else {
callback()
}
}
return {
sendCode: true,
phoneRules: {
phone: [
{ required: true, message: '请输入手机号', trigger: 'change' },
{ validator: validatePhone, trigger: 'change' }
],
code: [{ required: true, message: '请输入验证码', trigger: 'change' }]
},
phoneForm: {
phone: '',
code: ''
},
minute: 120 // 默认120秒 发送间隔
}
},
props: {
visible: {
type: Boolean,
default: false
},
userName: {
type: String,
default: ''
},
resetPassword: {
type: Boolean,
default: false
}
},
watch: {
visible(newVal) {
if (!newVal) {
// 重置表单
this.phoneForm = {
phone: '',
code: ''
}
// this.sendCode = true
// clearInterval(this.timer)
}
}
},
components: {},
filters: {},
methods: {
sendCodeText() {
// 倒计时 60S
this.minute = 120
this.timer = setInterval(() => {
this.minute--
if (this.minute <= 0) {
this.sendCode = true
clearInterval(this.timer)
}
}, 1000)
return this.minute
},
sendPhoneCode() {
let api = this.resetPassword ? send_sms : sendPhoneCodeLogin
api({
userName: !this.resetPassword ? this.userName : undefined
}).then(res => {
if (Number(res.code) === 0) {
this.sendCode = false
this.sendCodeText()
}
})
},
handleSubmit() {
this.$refs.phoneForm.validate(valid => {
if (valid) {
this.$emit('handleSubmit', this.phoneForm.code)
}
})
},
cancel() {
this.$emit('update:visible', false)
}
},
created() {
console.log(this.sendCode, 231)
},
mounted() {},
computed: {}
}
</script>
<style lang="scss">
@import '../assets/sass/renderSass/theme.scss';
.send-chat-phone-dialog {
.phone-form {
& .el-input-group__append {
background: $--color-primary;
color: #fff;
border-color: $--color-primary;
& .el-button {
&.is-disabled {
& ~ .el-input-group__append {
background: $--color-primary-disabled;
}
}
}
}
}
}
</style>

View File

@@ -112,68 +112,11 @@
<!-- <p>京公网安备 ICP许可证号津ICP备14004859号-4</p>-->
</div>
<r-dialog
<send-phone-code
:visible.sync="dialogVisible"
title="发送短信验证码"
width="550px"
>
<el-form
label-width="100px"
:model="phoneForm"
:rules="phoneRules"
class="phone-form"
ref="phoneForm"
>
<!-- <el-form-item label="手机号" prop="phone">-->
<!-- <div class="flex">-->
<!-- <el-input-->
<!-- v-model="phoneForm.phone"-->
<!-- placeholder="请输入手机号"-->
<!-- style="color:#000"-->
<!-- ></el-input>-->
<!-- <el-button-->
<!-- class="ml10 render-button pv5 ph10"-->
<!-- type="primary"-->
<!-- size="medium"-->
<!-- @click="sendPhoneCode"-->
<!-- :disabled="!sendCode"-->
<!-- >{{ !sendCode ? minute + '秒后重新发送' : '发送验证码' }}-->
<!-- </el-button>-->
<!-- </div>-->
<!-- </el-form-item>-->
<el-form-item label="短信验证码" prop="code" class="mr30">
<div class="flex">
<el-input
v-model="phoneForm.code"
placeholder="请输入短信验证码"
style="color:#000"
size="medium"
>
<template slot="append">
<el-button
class="ml10"
type="primary"
size="medium"
@click="sendPhoneCode"
:disabled="!sendCode"
>{{ !sendCode ? minute + '秒后重新发送' : '发送短信验证码' }}
</el-button>
</template>
</el-input>
</div>
<!-- <el-input-->
<!-- v-model="phoneForm.code"-->
<!-- placeholder="请输入验证码"-->
<!-- ></el-input>-->
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false" size="medium">取消</el-button>
<el-button type="primary" @click="handleSubmit" size="medium"
>确定</el-button
>
</div>
</r-dialog>
:user-name="loginForm.userName"
@handleSubmit="handleSubmit"
></send-phone-code>
</div>
</template>
@@ -306,11 +249,9 @@ export default {
}
})
},
handleSubmit() {
this.$refs.phoneForm.validate(valid => {
if (valid) {
handleSubmit(code) {
verify_login({
smsCode: this.phoneForm.code,
smsCode: code,
userName: this.loginForm.userName
}).then(vali => {
if (Number(vali.code) === 0) {
@@ -321,8 +262,6 @@ export default {
this.loading = false
}
})
}
})
},
showPwd() {
if (this.passwordType === 'password') {
@@ -428,20 +367,7 @@ $cursor: #fff;
font-style: normal;
}
}
.phone-form {
& .el-input-group__append {
background: $--color-primary;
color: #fff;
border-color: $--color-primary;
& .el-button {
&.is-disabled {
& ~ .el-input-group__append {
background: $--color-primary-disabled;
}
}
}
}
}
.login-input {
position: relative;
border: 1px solid #eaecf5;

View File

@@ -238,14 +238,30 @@ export default {
}
},
// 获取规则列表数据
getList(queryParams) {
getList() {
const queryParams = Object.assign({}, this.queryParams)
this.loading = true
const params = Object.assign(
{},
queryParams ? queryParams : this.queryParams
// 如果ruleType是中文转换为编码值
if (queryParams && queryParams.ruleType) {
const ruleTypeItem = this.ruleTypeList.find(
item => item.typeCode === queryParams.ruleType
)
getRulePage(params)
if (queryParams && ruleTypeItem) {
queryParams.ruleType = ruleTypeItem.typeName
}
}
// 如果ruleField是中文转换为编码值
if (queryParams && queryParams.ruleField) {
const fieldTypeItem = this.fieldTypeList.find(
item => item.fieldName === queryParams.ruleField
)
if (queryParams && fieldTypeItem) {
queryParams.ruleField = fieldTypeItem.fieldComment
}
}
getRulePage(queryParams)
.then(response => {
// 根据实际API返回结构调整兼容Vue2语法
var content = response.content.content || {}
@@ -331,25 +347,6 @@ export default {
this.queryParams.page = 1
// 创建查询参数的副本
const queryParams = Object.assign({}, this.queryParams)
// 如果ruleType是中文转换为编码值
if (queryParams.ruleType) {
const ruleTypeItem = this.ruleTypeList.find(
item => item.typeCode === queryParams.ruleType
)
if (ruleTypeItem) {
queryParams.ruleType = ruleTypeItem.typeName
}
}
// 如果ruleField是中文转换为编码值
if (queryParams.ruleField) {
const fieldTypeItem = this.fieldTypeList.find(
item => item.fieldName === queryParams.ruleField
)
if (fieldTypeItem) {
queryParams.ruleField = fieldTypeItem.fieldComment
}
}
// 使用转换后的参数进行查询
// this.queryParams = queryParams

View File

@@ -1,5 +1,7 @@
<template>
<el-dialog
<div>
{{ minute }}
<r-dialog
title="修改密码"
:visible.sync="visible"
width="500px"
@@ -48,21 +50,29 @@
<div slot="footer" class="dialog-footer">
<el-button
type="primary"
size="small"
size="medium"
:loading="loading"
@click="submitForm"
> </el-button
>
<el-button size="small" @click="handleClose"> </el-button>
<el-button size="medium" @click="handleClose"> </el-button>
</div>
</r-dialog>
<send-phone-code
:visible.sync="phoneVisabled"
:resetPassword="true"
@handleSubmit="handleSubmit"
></send-phone-code>
</div>
</el-dialog>
</template>
<script>
import { updatePassword } from '@/api/generatedApi/system'
import { updatePassword, verifyUpdatePassword } from '@/api/generatedApi/system'
import SendPhoneCode from '@/generatedComponents/send-phone-code.vue'
export default {
name: 'ResetPasswordDialog',
components: { SendPhoneCode },
props: {
visible: {
type: Boolean,
@@ -83,6 +93,8 @@ export default {
}
}
return {
phoneVisabled: false,
minute: 120,
form: {
userPassword: '',
newPassword: '',
@@ -105,6 +117,19 @@ export default {
}
},
methods: {
handleSubmit(code) {
verifyUpdatePassword({
userPassword: this.form.userPassword,
newPassword: this.form.newPassword,
smsCode: code
}).then(async res => {
if (res) {
this.$message.success('密码修改成功')
await this.$store.dispatch('user/logout')
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
}
})
},
handleClose() {
this.$refs.form.resetFields()
this.$emit('update:visible', false)
@@ -119,13 +144,23 @@ export default {
}
updatePassword(data)
.then(async () => {
.then(async res => {
let number = Number(res.content.result)
switch (number) {
case 0:
this.$message.success('密码修改成功')
await this.$store.dispatch('user/logout')
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
break
case 51001:
this.phoneVisabled = true
break
default:
this.$message.error(res.content.resultMessage)
}
})
.catch(() => {
this.$message.error('密码修改出错')
this.$message.error('系统异常,请联系管理员')
})
.finally(() => {
this.loading = false