feat(user): 添加支付密码设置功能
This commit is contained in:
parent
de509c7e14
commit
e16e1e3bdc
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 用户信息相关接口
|
||||
*/
|
||||
import type { CouponBean, LoginParams, LoginResult, RegisterParams, TerminalBean } from './types';
|
||||
import type { CouponBean, LoginParams, LoginResult, RegisterParams, TerminalBean, SetPayPasswordParams, PayPasswordResponse } from './types';
|
||||
import { get, post } from '@/utils/request';
|
||||
import { UserBean } from '@/store/modules/user/types';
|
||||
|
||||
@ -33,7 +33,9 @@ enum URL {
|
||||
tradeList = '/memberIncoming/wx_balance_records',
|
||||
terminal = 'wechat/coupons/terminal?companyId=',
|
||||
cardLink = '/wc/wechat/get_card_url',
|
||||
registerCoupon = '/couponsStrategy/wx_register_coupon'
|
||||
registerCoupon = '/couponsStrategy/wx_register_coupon',
|
||||
setPayPassword = '/app/pay/set_paypwd',
|
||||
payPasswordStatus = '/user/pay-password/status',
|
||||
}
|
||||
|
||||
export const getUserProfile = () => get<UserBean>({ url: URL.profile });
|
||||
@ -76,3 +78,18 @@ export const getTradeList = (data: any) => post<any>({ url: URL.tradeList, data
|
||||
export const getCardLink = () => get<string>({ url: URL.cardLink });
|
||||
|
||||
export const getRegisterCoupon = () => get<any>({ url: URL.registerCoupon });
|
||||
|
||||
/**
|
||||
* 设置支付密码
|
||||
*/
|
||||
export const setPayPassword = (data: SetPayPasswordParams) => post<PayPasswordResponse>({
|
||||
url: URL.setPayPassword,
|
||||
data
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取支付密码状态
|
||||
*/
|
||||
export const getPayPasswordStatus = () => get<{ hasPassword: boolean }>({
|
||||
url: URL.payPasswordStatus
|
||||
});
|
||||
|
@ -118,3 +118,14 @@ export interface TerminalBean {
|
||||
token: string;
|
||||
type: number;
|
||||
}
|
||||
|
||||
export interface SetPayPasswordParams {
|
||||
paywithpwd: number
|
||||
oldpwd: string,
|
||||
newpwd: string
|
||||
}
|
||||
|
||||
export interface PayPasswordResponse {
|
||||
success: boolean
|
||||
message: string
|
||||
}
|
||||
|
240
src/components/pay-password-dialog.vue
Normal file
240
src/components/pay-password-dialog.vue
Normal file
@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<uni-popup ref="popup" type="center" :safe-area="true" :mask-click="false">
|
||||
<view class="pay-password-dialog">
|
||||
<view class="dialog-header">
|
||||
<text class="title">设置支付密码</text>
|
||||
<u-icon name="close" size="20" color="#999" @click="hide" />
|
||||
</view>
|
||||
|
||||
<view class="form-container">
|
||||
<!-- 旧密码 -->
|
||||
<view class="form-item">
|
||||
<text class="label">旧密码:</text>
|
||||
<view class="input-wrapper">
|
||||
<u-input
|
||||
v-model="oldPassword"
|
||||
:type="showOldPassword ? 'text' : 'password'"
|
||||
placeholder="请输入旧密码"
|
||||
:maxlength="6"
|
||||
:border="false"
|
||||
fontSize="28rpx"
|
||||
/>
|
||||
<u-icon
|
||||
:name="showOldPassword ? 'eye-fill' : 'eye-off'"
|
||||
size="22"
|
||||
color="#999"
|
||||
@click="showOldPassword = !showOldPassword"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 新密码 -->
|
||||
<view class="form-item">
|
||||
<text class="label">新密码:</text>
|
||||
<view class="input-wrapper">
|
||||
<u-input
|
||||
v-model="newPassword"
|
||||
:type="showNewPassword ? 'text' : 'password'"
|
||||
placeholder="请输入6位数字密码"
|
||||
maxlength="6"
|
||||
:border="false"
|
||||
fontSize="28rpx"
|
||||
@input="validateInput"
|
||||
/>
|
||||
<u-icon
|
||||
:name="showNewPassword ? 'eye-fill' : 'eye-off'"
|
||||
size="22"
|
||||
color="#999"
|
||||
@click="showNewPassword = !showNewPassword"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认密码 -->
|
||||
<view class="form-item">
|
||||
<text class="label">确认密码:</text>
|
||||
<view class="input-wrapper">
|
||||
<u-input
|
||||
v-model="confirmPassword"
|
||||
:type="showConfirmPassword ? 'text' : 'password'"
|
||||
placeholder="请再次输入密码"
|
||||
maxlength="6"
|
||||
:border="false"
|
||||
fontSize="28rpx"
|
||||
@input="validateInput"
|
||||
/>
|
||||
<u-icon
|
||||
:name="showConfirmPassword ? 'eye-fill' : 'eye-off'"
|
||||
size="22"
|
||||
color="#999"
|
||||
@click="showConfirmPassword = !showConfirmPassword"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="footer">
|
||||
<button
|
||||
:class="{'primary-button': isValid, 'disabled-button': !isValid}"
|
||||
:disabled="!isValid"
|
||||
@click.stop='handleConfirm'
|
||||
>
|
||||
完成
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const popup = ref<any>(null)
|
||||
|
||||
// 密码显示状态
|
||||
const showOldPassword = ref(false)
|
||||
const showNewPassword = ref(false)
|
||||
const showConfirmPassword = ref(false)
|
||||
|
||||
// 表单数据
|
||||
const oldPassword = ref('')
|
||||
const newPassword = ref('')
|
||||
const confirmPassword = ref('')
|
||||
|
||||
// 是否有旧密码
|
||||
const hasOldPassword = computed(() => userStore.userInfo.hasPayPassword)
|
||||
|
||||
// 表单验证
|
||||
const isValid = computed(() => {
|
||||
if (!newPassword.value || !confirmPassword.value) return false
|
||||
if (newPassword.value.length !== 6 || confirmPassword.value.length !== 6) return false
|
||||
return newPassword.value === confirmPassword.value
|
||||
})
|
||||
|
||||
// 输入验证(只允许数字)
|
||||
const validateInput = (value: string) => {
|
||||
const numericValue = value.replace(/\D/g, '')
|
||||
if (value !== numericValue) {
|
||||
newPassword.value = numericValue
|
||||
confirmPassword.value = numericValue
|
||||
}
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
oldPassword.value = ''
|
||||
newPassword.value = ''
|
||||
confirmPassword.value = ''
|
||||
showOldPassword.value = false
|
||||
showNewPassword.value = false
|
||||
showConfirmPassword.value = false
|
||||
}
|
||||
|
||||
// 显示弹框
|
||||
const show = () => {
|
||||
console.log('show pay password dialog')
|
||||
popup.value?.open('center')
|
||||
}
|
||||
|
||||
// 隐藏弹框
|
||||
const hide = () => {
|
||||
console.log('hide pay password dialog')
|
||||
popup.value?.close()
|
||||
resetForm()
|
||||
}
|
||||
|
||||
// 取消
|
||||
const handleCancel = () => {
|
||||
hide()
|
||||
resetForm()
|
||||
}
|
||||
|
||||
// 确认
|
||||
const handleConfirm = async () => {
|
||||
try {
|
||||
await userStore.setPayPassword({
|
||||
paywithpwd:'0',
|
||||
oldpwd: oldPassword.value,
|
||||
newpwd: newPassword.value,
|
||||
})
|
||||
uni.showToast({
|
||||
title: '设置成功',
|
||||
icon: 'success',
|
||||
})
|
||||
hide()
|
||||
resetForm()
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '设置失败',
|
||||
icon: 'error',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露方法给父组件使用
|
||||
defineExpose({
|
||||
show,
|
||||
hide
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pay-password-dialog {
|
||||
width: 600rpx;
|
||||
padding: 40rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 24rpx;
|
||||
position: relative;
|
||||
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.form-container {
|
||||
.form-item {
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.label {
|
||||
font-size: 30rpx;
|
||||
color: #333;
|
||||
margin-bottom: 16rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx;
|
||||
height: 50rpx;
|
||||
|
||||
:deep(.u-input) {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:deep(.u-input__input) {
|
||||
height: 100%;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -18,7 +18,7 @@
|
||||
"modules": {}
|
||||
},
|
||||
"mp-weixin": {
|
||||
"appid": "wx67a750d0ceed4d88",
|
||||
"appid": "wx92e663dc11d0c0a8",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
},
|
||||
|
@ -59,8 +59,11 @@
|
||||
<text>{{ item.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
<!-- 支付密码设置弹框 -->
|
||||
<pay-password-dialog ref="payPasswordDialogRef" />
|
||||
<official-account-dialog ref='officialAccountDialogRef' />
|
||||
</template>
|
||||
|
||||
@ -71,10 +74,12 @@ import { isPending } from '@/utils/order';
|
||||
import { getCardLink } from '@/api/user';
|
||||
import { getOrderList } from '@/api/order';
|
||||
import OfficialAccountDialog from '@/components/official-account-dialog.vue';
|
||||
import PayPasswordDialog from '@/components/pay-password-dialog.vue';
|
||||
import { useUserStore } from '@/store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const officialAccountDialogRef = ref();
|
||||
const payPasswordDialogRef = ref<any>(null);
|
||||
|
||||
const orderActionList = ref([{
|
||||
title: '未支付',
|
||||
@ -114,6 +119,11 @@ const serviceList = [
|
||||
title: '联系商家',
|
||||
icon: assetsUrl('ic_member_service_contact.png'),
|
||||
path: '/pages/mine/subs/contact/index'
|
||||
},
|
||||
{
|
||||
title: '支付密码',
|
||||
icon: '/static/images/ic_member_pay_password.png',
|
||||
path: 'pay_password'
|
||||
}
|
||||
// ,{
|
||||
// title: '推广中心',
|
||||
@ -146,6 +156,7 @@ onShow(async () => {
|
||||
const { cardurl } = await getCardLink();
|
||||
cardLink.value = cardurl;
|
||||
await userStore.getProfile();
|
||||
await userStore.getPayPasswordStatus();
|
||||
}
|
||||
});
|
||||
|
||||
@ -163,9 +174,19 @@ const openCard = () => {
|
||||
// });
|
||||
};
|
||||
|
||||
const showOfficialAccountDialog = () => {
|
||||
officialAccountDialogRef.value.show();
|
||||
};
|
||||
|
||||
const showPayPasswordDialog = () => {
|
||||
payPasswordDialogRef.value?.show();
|
||||
};
|
||||
|
||||
const gotoPath = (path: string) => {
|
||||
if(path === 'follow_official_account') {
|
||||
showOfficialAccountDialog();
|
||||
} else if(path === 'pay_password') {
|
||||
showPayPasswordDialog();
|
||||
} else if(path === 'qrcode') {
|
||||
uni.switchTab({
|
||||
url: '/pages/qrcode/index'
|
||||
@ -178,10 +199,6 @@ const gotoPath = (path: string) => {
|
||||
goPath(path, true);
|
||||
}
|
||||
};
|
||||
|
||||
const showOfficialAccountDialog = () => {
|
||||
officialAccountDialogRef.value.show();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
|
28
src/pages/tab/user/index.vue
Normal file
28
src/pages/tab/user/index.vue
Normal file
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<view class="user-page">
|
||||
<!-- 其他现有内容 -->
|
||||
|
||||
<!-- 在联系商家后面添加支付密码设置入口 -->
|
||||
<u-cell-group>
|
||||
<!-- 现有的联系商家单元格 -->
|
||||
<u-cell
|
||||
title="支付密码"
|
||||
is-link
|
||||
@click="navigateToPayPassword"
|
||||
/>
|
||||
</u-cell-group>
|
||||
|
||||
<!-- 其他现有内容 -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// ... 其他导入 ...
|
||||
|
||||
// 跳转到支付密码设置页面
|
||||
const navigateToPayPassword = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/common/pay-password/index'
|
||||
})
|
||||
}
|
||||
</script>
|
BIN
src/static/images/ic_member_pay_password.png
Normal file
BIN
src/static/images/ic_member_pay_password.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.3 KiB |
@ -77,3 +77,8 @@ page {
|
||||
min-width: 80%;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.disabled-button {
|
||||
@extend .primary-button;
|
||||
background: #cccccc;
|
||||
}
|
@ -10,8 +10,9 @@ import {
|
||||
setSessionKey,
|
||||
setToken
|
||||
} from '@/utils/auth';
|
||||
import type { RegisterParams, TerminalBean } from '@/api/user/types';
|
||||
import type { RegisterParams, TerminalBean,SetPayPasswordParams } from '@/api/user/types';
|
||||
import { getCompanyInfo } from '@/api/company';
|
||||
import { setPayPassword, getPayPasswordStatus } from '@/api/user'
|
||||
|
||||
const useUserStore = defineStore('user', {
|
||||
state: () => ({
|
||||
@ -36,7 +37,7 @@ const useUserStore = defineStore('user', {
|
||||
mobile: '',
|
||||
addr: '',
|
||||
defaultstatus: 0
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
persist: {
|
||||
@ -197,7 +198,23 @@ const useUserStore = defineStore('user', {
|
||||
await userLogout();
|
||||
this.resetInfo();
|
||||
clearToken();
|
||||
}
|
||||
},
|
||||
|
||||
// 设置支付密码
|
||||
async setPayPassword(params: SetPayPasswordParams) {
|
||||
const res = await setPayPassword(params)
|
||||
if (res.success) {
|
||||
this.userInfo.hasPayPassword = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
|
||||
// 获取支付密码状态
|
||||
async getPayPasswordStatus() {
|
||||
const res = await getPayPasswordStatus()
|
||||
this.userInfo.hasPayPassword = res.hasPassword
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -52,7 +52,8 @@ export interface UserBean {
|
||||
updateTime: string;
|
||||
useCouponsPrice: number;
|
||||
wirelinedTelephone: string;
|
||||
userDiscount:number
|
||||
userDiscount: number;
|
||||
hasPayPassword: boolean;
|
||||
}
|
||||
|
||||
export type providerType =
|
||||
|
@ -28,10 +28,6 @@
|
||||
"types/**/*.d.ts",
|
||||
"types/**/*.ts"
|
||||
],
|
||||
"exclude": ["dist", "node_modules", "uni_modules"],
|
||||
// uni-app Component type prompt
|
||||
"vueCompilerOptions": {
|
||||
"nativeTags": ["block", "component", "template", "slot"]
|
||||
}
|
||||
"exclude": ["dist", "node_modules", "uni_modules"]
|
||||
}
|
||||
|
||||
|
1
types/components.d.ts
vendored
1
types/components.d.ts
vendored
@ -12,6 +12,7 @@ declare module 'vue' {
|
||||
PageNav: typeof import('./../src/components/page-nav/page-nav.vue')['default']
|
||||
PaymentButton: typeof import('./../src/components/payment-button.vue')['default']
|
||||
PaymentDialog: typeof import('./../src/components/payment-dialog.vue')['default']
|
||||
PayPasswordDialog: typeof import('./../src/components/pay-password-dialog.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SkuDialog: typeof import('./../src/components/sku-dialog.vue')['default']
|
||||
|
Loading…
Reference in New Issue
Block a user