支付及优惠券页面更新
This commit is contained in:
BIN
public/imgs/shop/coupon/background.png
Normal file
BIN
public/imgs/shop/coupon/background.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 187 KiB |
BIN
public/imgs/shop/coupon/bg_useful1.png
Normal file
BIN
public/imgs/shop/coupon/bg_useful1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
public/imgs/shop/coupon/bg_useful2.png
Normal file
BIN
public/imgs/shop/coupon/bg_useful2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/imgs/shop/coupon/bg_useless1.png
Normal file
BIN
public/imgs/shop/coupon/bg_useless1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/imgs/shop/coupon/bg_useless2.png
Normal file
BIN
public/imgs/shop/coupon/bg_useless2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -44,7 +44,7 @@
|
|||||||
import { ref, onMounted, watch } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { Refresh, Loading } from '@element-plus/icons-vue'
|
import { Refresh, Loading } from '@element-plus/icons-vue'
|
||||||
import api from '@/utils/api'
|
import api,{captchaAPI} from '@/utils/api'
|
||||||
|
|
||||||
// Props
|
// Props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -81,7 +81,7 @@ const loading = ref(false)
|
|||||||
const getCaptcha = async () => {
|
const getCaptcha = async () => {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const response = await api.get('/captcha/generate')
|
const response = await captchaAPI.generate()
|
||||||
|
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
captchaImage.value = response.data.data.image
|
captchaImage.value = response.data.data.image
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 普通用户页面认证逻辑
|
// 普通用户页面认证逻辑
|
||||||
console.log(userStore.isAuthenticated, 'isAuthenticated');
|
// console.log(userStore.isAuthenticated, 'isAuthenticated');
|
||||||
|
|
||||||
if (!userStore.isAuthenticated) {
|
if (!userStore.isAuthenticated) {
|
||||||
// 尝试从本地存储恢复登录状态
|
// 尝试从本地存储恢复登录状态
|
||||||
@@ -328,10 +328,10 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查支付状态(管理员除外)
|
// 检查支付状态(管理员除外)
|
||||||
console.log(userStore.user);
|
// console.log(userStore.user);
|
||||||
|
|
||||||
if (userStore.user && userStore.user.role !== 'admin' && userStore.user.payment_status === 'unpaid') {
|
if (userStore.user && userStore.user.role !== 'admin' && userStore.user.payment_status === 'unpaid') {
|
||||||
console.log('进来了');
|
// console.log('进来了');
|
||||||
|
|
||||||
// 如果当前不在支付页面,静默重定向到支付页面(不显示额外通知)
|
// 如果当前不在支付页面,静默重定向到支付页面(不显示额外通知)
|
||||||
if (to.name !== 'Payment') {
|
if (to.name !== 'Payment') {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import api from '@/utils/api'
|
import api,{authAPI} from '@/utils/api'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
export const useUserStore = defineStore('user', () => {
|
export const useUserStore = defineStore('user', () => {
|
||||||
@@ -23,10 +23,9 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
token.value = newToken
|
token.value = newToken
|
||||||
if (newToken) {
|
if (newToken) {
|
||||||
localStorage.setItem('token', newToken)
|
localStorage.setItem('token', newToken)
|
||||||
api.defaults.headers.common['Authorization'] = `Bearer ${newToken}`
|
|
||||||
} else {
|
} else {
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
delete api.defaults.headers.common['Authorization']
|
console.log('token已移除');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +38,9 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const login = async (credentials) => {
|
const login = async (credentials) => {
|
||||||
try {
|
try {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const response = await api.post('/auth/login', credentials)
|
const response = await authAPI.login(credentials)
|
||||||
|
|
||||||
|
console.log('response',response);
|
||||||
|
|
||||||
if (response.data.success && response.data.token) {
|
if (response.data.success && response.data.token) {
|
||||||
setToken(response.data.token)
|
setToken(response.data.token)
|
||||||
@@ -72,6 +73,7 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
return { success: false, message }
|
return { success: false, message }
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error,'error');
|
||||||
const errorData = error.response?.data
|
const errorData = error.response?.data
|
||||||
if (errorData?.needPayment) {
|
if (errorData?.needPayment) {
|
||||||
// 处理403状态码返回的需要支付情况
|
// 处理403状态码返回的需要支付情况
|
||||||
@@ -146,15 +148,13 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 确保请求头已设置
|
// 确保请求头已设置
|
||||||
if (token.value && !api.defaults.headers.common['Authorization']) {
|
|
||||||
api.defaults.headers.common['Authorization'] = `Bearer ${token.value}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await api.get('/auth/me')
|
const response = await api.get('/auth/me')
|
||||||
setUser(response.data.user)
|
setUser(response.data.user)
|
||||||
return true
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// token无效,清除本地存储
|
// token无效,清除本地存储
|
||||||
|
console.log('token无效,清除本地存储',error);
|
||||||
setToken('')
|
setToken('')
|
||||||
setUser(null)
|
setUser(null)
|
||||||
return false
|
return false
|
||||||
|
|||||||
184
src/utils/api.js
184
src/utils/api.js
@@ -1,65 +1,66 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { ElMessage, ElLoading } from 'element-plus'
|
import { ElMessage, ElLoading } from 'element-plus'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
import NProgress from 'nprogress'
|
||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const api = axios.create({
|
// 工厂函数(复用拦截器逻辑)
|
||||||
baseURL: '/api',
|
export const createRequest = (baseURL) => {
|
||||||
|
const request = axios.create({
|
||||||
|
baseURL,
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 初始化时设置token
|
// 初始化时设置token
|
||||||
const token = localStorage.getItem('token')
|
const token = localStorage.getItem('token')
|
||||||
if (token) {
|
if (token) {
|
||||||
api.defaults.headers.common['Authorization'] = `Bearer ${token}`
|
request.defaults.headers.common['Authorization'] = `Bearer ${token}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求拦截器
|
// 请求拦截器
|
||||||
let loadingInstance = null
|
request.interceptors.request.use(
|
||||||
api.interceptors.request.use(
|
|
||||||
(config) => {
|
(config) => {
|
||||||
// 从localStorage获取token
|
// 开始进度条
|
||||||
|
NProgress.start()
|
||||||
|
|
||||||
|
// 显示加载动画(除了某些不需要的请求)
|
||||||
|
if (!config.hideLoading) {
|
||||||
|
showLoading()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加认证token
|
||||||
const token = localStorage.getItem('token')
|
const token = localStorage.getItem('token')
|
||||||
if (token) {
|
if (token) {
|
||||||
config.headers.Authorization = `Bearer ${token}`
|
config.headers.Authorization = `Bearer ${token}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示加载动画(可选)
|
|
||||||
if (config.showLoading !== false) {
|
|
||||||
loadingInstance = ElLoading.service({
|
|
||||||
text: '加载中...',
|
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return config
|
return config
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
if (loadingInstance) {
|
hideLoading()
|
||||||
loadingInstance.close()
|
NProgress.done()
|
||||||
}
|
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 响应拦截器
|
// 响应拦截器
|
||||||
api.interceptors.response.use(
|
request.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
if (loadingInstance) {
|
hideLoading()
|
||||||
loadingInstance.close()
|
NProgress.done()
|
||||||
}
|
|
||||||
return response
|
return response
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
if (loadingInstance) {
|
hideLoading()
|
||||||
loadingInstance.close()
|
NProgress.done()
|
||||||
}
|
|
||||||
|
const { response } = error
|
||||||
|
|
||||||
// 处理不同的错误状态码
|
// 处理不同的错误状态码
|
||||||
if (error.response) {
|
if (response) {
|
||||||
const { status, data } = error.response
|
const { status, data } = error.response
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -136,13 +137,53 @@ api.interceptors.response.use(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
|
||||||
|
let loadingInstance = null
|
||||||
|
let requestCount = 0
|
||||||
|
let isLoggingOut = false // 防止重复登出
|
||||||
|
|
||||||
|
// 显示加载
|
||||||
|
const showLoading = () => {
|
||||||
|
if (requestCount === 0) {
|
||||||
|
loadingInstance = ElLoading.service({
|
||||||
|
text: '加载中...',
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
requestCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
// 隐藏加载
|
||||||
|
const hideLoading = () => {
|
||||||
|
requestCount--
|
||||||
|
if (requestCount <= 0) {
|
||||||
|
requestCount = 0
|
||||||
|
if (loadingInstance) {
|
||||||
|
loadingInstance.close()
|
||||||
|
loadingInstance = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成不同的实例
|
||||||
|
export const apiRequest = createRequest('/api')
|
||||||
|
export const midRequest = createRequest('/mid')
|
||||||
|
|
||||||
|
// 初始化时设置token
|
||||||
|
const token = localStorage.getItem('token')
|
||||||
|
if (token) {
|
||||||
|
apiRequest.defaults.headers.common['Authorization'] = `Bearer ${token}`
|
||||||
|
}
|
||||||
|
|
||||||
// 封装常用的请求方法
|
// 封装常用的请求方法
|
||||||
export const request = {
|
const api = {
|
||||||
get: (url, config = {}) => api.get(url, config),
|
get: (url, config = {}) => apiRequest.get(url, config),
|
||||||
post: (url, data = {}, config = {}) => api.post(url, data, config),
|
post: (url, data = {}, config = {}) => apiRequest.post(url, data, config),
|
||||||
put: (url, data = {}, config = {}) => api.put(url, data, config),
|
put: (url, data = {}, config = {}) => apiRequest.put(url, data, config),
|
||||||
delete: (url, config = {}) => api.delete(url, config),
|
delete: (url, config = {}) => apiRequest.delete(url, config),
|
||||||
patch: (url, data = {}, config = {}) => api.patch(url, data, config)
|
patch: (url, data = {}, config = {}) => apiRequest.patch(url, data, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -150,43 +191,43 @@ export const request = {
|
|||||||
// 用户相关API
|
// 用户相关API
|
||||||
export const userAPI = {
|
export const userAPI = {
|
||||||
// 获取用户列表
|
// 获取用户列表
|
||||||
getList: (params = {}) => request.get('/users', { params }),
|
getList: (params = {}) => apiRequest.get('/users', { params }),
|
||||||
|
|
||||||
// 获取用户详情
|
// 获取用户详情
|
||||||
getDetail: (id) => request.get(`/users/${id}`),
|
getDetail: (id) => apiRequest.get(`/users/${id}`),
|
||||||
|
|
||||||
// 更新用户信息
|
// 更新用户信息
|
||||||
update: (id, data) => request.put(`/users/${id}`, data),
|
update: (id, data) => apiRequest.put(`/users/${id}`, data),
|
||||||
|
|
||||||
// 删除用户
|
// 删除用户
|
||||||
delete: (id) => request.delete(`/users/${id}`),
|
delete: (id) => apiRequest.delete(`/users/${id}`),
|
||||||
|
|
||||||
// 获取用户统计
|
// 获取用户统计
|
||||||
getStats: () => request.get('/users/stats/overview')
|
getStats: () => apiRequest.get('/users/stats/overview')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 认证相关API
|
// 认证相关API
|
||||||
export const authAPI = {
|
export const authAPI = {
|
||||||
// 登录
|
// 登录
|
||||||
login: (data) => request.post('/auth/login', data),
|
login: (data) => midRequest.post('/auth/login', data),
|
||||||
|
|
||||||
// 注册
|
// 注册
|
||||||
register: (data) => request.post('/auth/register', data),
|
register: (data) => midRequest.post('/auth/register', data),
|
||||||
|
|
||||||
// 获取当前用户信息
|
// 获取当前用户信息
|
||||||
me: () => request.get('/auth/me'),
|
me: () => apiRequest.get('/auth/me'),
|
||||||
|
|
||||||
// 修改密码
|
// 修改密码
|
||||||
changePassword: (data) => request.put('/auth/change-password', data)
|
changePassword: (data) => apiRequest.put('/auth/change-password', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证码相关API
|
// 验证码相关API
|
||||||
export const captchaAPI = {
|
export const captchaAPI = {
|
||||||
// 生成验证码
|
// 生成验证码
|
||||||
generate: () => request.get('/captcha/generate'),
|
generate: () => midRequest.get('/captcha/generate'),
|
||||||
|
|
||||||
// 验证验证码
|
// 验证验证码
|
||||||
verify: (data) => request.post('/captcha/verify', data)
|
verify: (data) => midRequest.post('/captcha/verify', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文件上传API
|
// 文件上传API
|
||||||
@@ -195,7 +236,7 @@ export const uploadAPI = {
|
|||||||
uploadImage: (file) => {
|
uploadImage: (file) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('image', file)
|
formData.append('image', file)
|
||||||
return request.post('/upload/image', formData, {
|
return midRequest.post('/upload/image', formData, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data'
|
'Content-Type': 'multipart/form-data'
|
||||||
}
|
}
|
||||||
@@ -206,7 +247,7 @@ export const uploadAPI = {
|
|||||||
uploadFile: (file) => {
|
uploadFile: (file) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
return request.post('/upload/file', formData, {
|
return midRequest.post('/upload/file', formData, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data'
|
'Content-Type': 'multipart/form-data'
|
||||||
}
|
}
|
||||||
@@ -217,24 +258,29 @@ export const uploadAPI = {
|
|||||||
// 支付相关API
|
// 支付相关API
|
||||||
export const paymentAPI = {
|
export const paymentAPI = {
|
||||||
// 获取支付方式
|
// 获取支付方式
|
||||||
getMethods: () => request.get('/payment/methods'),
|
getMethods: () => apiRequest.get('/payment/methods'),
|
||||||
|
|
||||||
// 创建支付订单
|
// 创建支付订单
|
||||||
createOrder: (data) => request.post('/payment/create-order', data),
|
createOrder: (data) => apiRequest.post('/payment/create-order', data),
|
||||||
|
|
||||||
// 查询支付状态
|
// 查询支付状态
|
||||||
queryStatus: (outTradeNo) => request.get(`/payment/query-status/${outTradeNo}`),
|
queryStatus: (outTradeNo) => apiRequest.get(`/payment/query-status/${outTradeNo}`),
|
||||||
|
|
||||||
getOrder: () => request.get('/payment/check-status'),
|
getOrder: () => apiRequest.get('/payment/check-status'),
|
||||||
|
|
||||||
// 获取支付记录
|
// 获取支付记录
|
||||||
getOrders: (params = {}) => request.get('/payment/orders', { params })
|
getOrders: (params = {}) => apiRequest.get('/payment/orders', { params })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 购买商品
|
||||||
|
export const buyAPI = {
|
||||||
|
buy: (data) => midRequest.post('/payment/create-order', data),
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转账相关API
|
// 转账相关API
|
||||||
export const transferAPI = {
|
export const transferAPI = {
|
||||||
// 获取公户信息
|
// 获取公户信息
|
||||||
getPublicAccount: () => request.get('/transfers/public-account'),
|
getPublicAccount: () => apiRequest.get('/transfers/public-account'),
|
||||||
|
|
||||||
// 创建转账记录
|
// 创建转账记录
|
||||||
create: (data) => {
|
create: (data) => {
|
||||||
@@ -242,7 +288,7 @@ export const transferAPI = {
|
|||||||
Object.keys(data).forEach(key => {
|
Object.keys(data).forEach(key => {
|
||||||
formData.append(key, data[key])
|
formData.append(key, data[key])
|
||||||
})
|
})
|
||||||
return request.post('/transfers', formData, {
|
return apiRequest.post('/transfers', formData, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data'
|
'Content-Type': 'multipart/form-data'
|
||||||
}
|
}
|
||||||
@@ -250,38 +296,38 @@ export const transferAPI = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 确认转账
|
// 确认转账
|
||||||
confirm: (id) => request.put(`/transfers/${id}/confirm`),
|
confirm: (id) => apiRequest.put(`/transfers/${id}/confirm`),
|
||||||
|
|
||||||
// 拒绝转账
|
// 拒绝转账
|
||||||
reject: (id) => request.put(`/transfers/${id}/reject`),
|
reject: (id) => apiRequest.put(`/transfers/${id}/reject`),
|
||||||
|
|
||||||
// 确认收款
|
// 确认收款
|
||||||
confirmReceived: (id) => request.post('/transfers/confirm-received', { transfer_id: id }),
|
confirmReceived: (id) => apiRequest.post('/transfers/confirm-received', { transfer_id: id }),
|
||||||
|
|
||||||
// 确认未收到款
|
// 确认未收到款
|
||||||
confirmNotReceived: (id) => request.post('/transfers/confirm-not-received', { transfer_id: id }),
|
confirmNotReceived: (id) => apiRequest.post('/transfers/confirm-not-received', { transfer_id: id }),
|
||||||
|
|
||||||
// 获取用户转账记录
|
// 获取用户转账记录
|
||||||
getUserTransfers: (params = {}) => request.get('/transfers/user', { params }),
|
getUserTransfers: (params = {}) => apiRequest.get('/transfers/user', { params }),
|
||||||
|
|
||||||
// 获取指定用户的转账记录
|
// 获取指定用户的转账记录
|
||||||
getUserTransfersByUserId: (userId, params = {}) => request.get(`/transfers/user/${userId}`, { params }),
|
getUserTransfersByUserId: (userId, params = {}) => apiRequest.get(`/transfers/user/${userId}`, { params }),
|
||||||
|
|
||||||
// 获取待确认转账
|
// 获取待确认转账
|
||||||
getPendingTransfers: (params = {}) => request.get('/transfers/pending', { params }),
|
getPendingTransfers: (params = {}) => apiRequest.get('/transfers/pending', { params }),
|
||||||
|
|
||||||
// 获取用户账户信息
|
// 获取用户账户信息
|
||||||
getUserAccount: () => request.get('/transfers/account'),
|
getUserAccount: () => apiRequest.get('/transfers/account'),
|
||||||
|
|
||||||
// 获取转账列表(管理员)
|
// 获取转账列表(管理员)
|
||||||
getList: (params = {}) => request.get('/transfers', { params }),
|
getList: (params = {}) => apiRequest.get('/transfers', { params }),
|
||||||
|
|
||||||
// 获取转账统计
|
// 获取转账统计
|
||||||
getStats: () => request.get('/transfers/stats')
|
getStats: () => apiRequest.get('/transfers/stats')
|
||||||
}
|
}
|
||||||
|
|
||||||
export const distributionAPI = {
|
export const distributionAPI = {
|
||||||
getLowerUsers: (params) => request.get('/agents/distribution', { params }),
|
getLowerUsers: (params) => apiRequest.get('/agents/distribution', { params }),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default api
|
export default api
|
||||||
@@ -2,20 +2,70 @@
|
|||||||
<div class="coupon-container">
|
<div class="coupon-container">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="back-btn" @click="$router.go(-1)"><</div>
|
<div class="back-btn" @click="$router.go(-1)"><</div>
|
||||||
<div class="text">
|
<div class="header-text">
|
||||||
优惠券包
|
优惠券包
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="coupon-content">
|
<div class="coupon-content">
|
||||||
<div class="coupon-item" @click="getCoupon('1')">
|
<div class="discount_for_a_amount_container">
|
||||||
领满减
|
<div class="container-title">
|
||||||
|
满减券限量
|
||||||
|
</div>
|
||||||
|
<div class="coupons-content">
|
||||||
|
<div class="coupon-item" v-for="coupon in coupons" :key="coupon.id">
|
||||||
|
<div class="coupon-filtered-item" v-if="coupon.type === 'discount_for_a_amount'"
|
||||||
|
:style="{
|
||||||
|
backgroundImage: coupon.got
|
||||||
|
? 'url(/imgs/shop/coupon/bg_useless1.png)'
|
||||||
|
: 'url(/imgs/shop/coupon/bg_useful1.png)'
|
||||||
|
}">
|
||||||
|
<div class="text-left">¥{{ coupon.discount }}</div>
|
||||||
|
<div class="text-mid-w">满{{ coupon.for_a_amount }}可用</div>
|
||||||
|
<div class="text-right" @click="getCoupon('discount_for_a_amount',coupon.id)" v-if="!coupon.got">立即领取</div>
|
||||||
|
<div class="text-right" v-else>已领取</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="discount_container">
|
||||||
|
<div class="container-title" style="margin-bottom: 10px;">
|
||||||
|
抵扣券限量
|
||||||
|
</div>
|
||||||
|
<div class="coupons-content grid-container">
|
||||||
|
<div class="coupon-item" v-for="coupon in coupons" :key="coupon.id">
|
||||||
|
<div class="coupon-filtered-item2" v-if="coupon.type === 'deduction'"
|
||||||
|
:style="{
|
||||||
|
backgroundImage: coupon.got
|
||||||
|
? 'url(/imgs/shop/coupon/bg_useless2.png)'
|
||||||
|
: 'url(/imgs/shop/coupon/bg_useful2.png)'
|
||||||
|
}">
|
||||||
|
<div class="text-top">¥{{ coupon.price }}</div>
|
||||||
|
<div class="text-mid-h">无门槛</div>
|
||||||
|
<div class="text-bottom" @click="getCoupon('deduction',coupon.id)" v-if="!coupon.got">立即领取</div>
|
||||||
|
<div class="text-bottom" v-else>已领取</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="deduction_container">
|
||||||
|
<div class="container-title">
|
||||||
|
折扣券限量
|
||||||
|
</div>
|
||||||
|
<div class="coupons-content">
|
||||||
|
<div class="coupon-item" v-for="coupon in coupons" :key="coupon.id">
|
||||||
|
<div class="coupon-filtered-item" v-if="coupon.type === 'discount'"
|
||||||
|
:style="{
|
||||||
|
backgroundImage: coupon.got
|
||||||
|
? 'url(/imgs/shop/coupon/bg_useless1.png)'
|
||||||
|
: 'url(/imgs/shop/coupon/bg_useful1.png)'
|
||||||
|
}">
|
||||||
|
<div class="text-left">{{ coupon.precent/10 }}折</div>
|
||||||
|
<div class="text-right" @click="getCoupon('discount',coupon.id)" v-if="!coupon.got">立即领取</div>
|
||||||
|
<div class="text-right" v-else>已领取</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="coupon-item" @click="getCoupon('2')">
|
|
||||||
领折扣
|
|
||||||
</div>
|
</div>
|
||||||
<div class="coupon-item" @click="getCoupon('3')">
|
|
||||||
领抵扣
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -30,11 +80,27 @@ import { ElMessage } from 'element-plus'
|
|||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const getCoupon = async (coupon_id) => {
|
const coupons = ref([])
|
||||||
|
|
||||||
|
const getAllCoupons = async () => {
|
||||||
|
const {data} = await api.get('/coupon',{
|
||||||
|
params: {
|
||||||
|
user_id: userStore.user.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (data.success) {
|
||||||
|
coupons.value = data.coupon
|
||||||
|
console.log(123,coupons.value)
|
||||||
|
} else {
|
||||||
|
ElMessage.error(data.message || '优惠券领取失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCoupon = async (coupon_type,coupon_id) => {
|
||||||
try {
|
try {
|
||||||
console.log(userStore)
|
|
||||||
const {data} = await api.get(`/coupon/${userStore.user.id}`,{
|
const {data} = await api.get(`/coupon/${userStore.user.id}`,{
|
||||||
params: {
|
params: {
|
||||||
|
coupon_type: coupon_type,
|
||||||
coupon_id: coupon_id
|
coupon_id: coupon_id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -50,18 +116,23 @@ const getCoupon = async (coupon_id) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// getCoupon()
|
getAllCoupons()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.coupon-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
background-image: url(/imgs/shop/coupon/background.png);
|
||||||
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 25px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-btn {
|
.back-btn {
|
||||||
@@ -77,19 +148,158 @@ onMounted(() => {
|
|||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.header-text {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
angle: 0 deg;
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
font-family: SF Pro;
|
font-family: SF Pro;
|
||||||
font-weight: 650;
|
font-weight: 650;
|
||||||
font-style: Expanded Semibold;
|
font-style: Expanded Semibold;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
leading-trim: NONE;
|
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
letter-spacing: 0%;
|
letter-spacing: 0%;
|
||||||
color: #2F4FB5;
|
color: #2F4FB5;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.coupon-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.discount_for_a_amount_container,
|
||||||
|
.discount_container,
|
||||||
|
.deduction_container {
|
||||||
|
background: white;
|
||||||
|
width: 348px;
|
||||||
|
padding: 10px;
|
||||||
|
top: 32px;
|
||||||
|
opacity: 1;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-title {
|
||||||
|
width: 96;
|
||||||
|
height: 20;
|
||||||
|
top: 324px;
|
||||||
|
left: 105px;
|
||||||
|
opacity: 1;
|
||||||
|
font-family: SF Pro;
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: Bold;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0%;
|
||||||
|
color: #2F4FB5;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coupon-filtered-item {
|
||||||
|
width: 324px;
|
||||||
|
height: 66px;
|
||||||
|
top: 58px;
|
||||||
|
left: 12px;
|
||||||
|
opacity: 1;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-left {
|
||||||
|
font-size: 25px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #305DEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-mid-w {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #305DEF;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
font-family: SF Pro;
|
||||||
|
font-weight: 590;
|
||||||
|
font-style: Semibold;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-right {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ffffff;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 100px;
|
||||||
|
background: #305DEF;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
margin-right: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-right:hover {
|
||||||
|
background-color: #305DEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coupon-item {
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coupon-filtered-item2 {
|
||||||
|
width: 83px;
|
||||||
|
height: 94px;
|
||||||
|
opacity: 1;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-top {
|
||||||
|
font-family: SF Pro;
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: Bold;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0%;
|
||||||
|
color: #305DEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-mid-h {
|
||||||
|
font-family: SF Pro;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: Regular;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0%;
|
||||||
|
color: #305DEF;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-bottom {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #305DEF;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 100px;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -384,7 +384,7 @@ import {
|
|||||||
Orange,
|
Orange,
|
||||||
Check
|
Check
|
||||||
} from '@element-plus/icons-vue'
|
} from '@element-plus/icons-vue'
|
||||||
import api from '@/utils/api'
|
import api, { buyAPI } from '@/utils/api'
|
||||||
import { getImageUrl } from '@/config'
|
import { getImageUrl } from '@/config'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -418,10 +418,10 @@ const totalPointsPrice = computed(() => {
|
|||||||
}, 0)
|
}, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 计算人民币价格(融豆价格1:1换算)
|
// 计算人民币价格(1融豆 = 1元)
|
||||||
const getRMBPrice = () => {
|
const getRMBPrice = () => {
|
||||||
const totalRongdou = totalRongdouPrice.value
|
const totalRongdou = totalRongdouPrice.value
|
||||||
return (totalRongdou).toFixed(2) // 假设1融豆=0.01元,可根据实际汇率调整
|
return (totalRongdou).toFixed(2)
|
||||||
}
|
}
|
||||||
// 用户余额数据
|
// 用户余额数据
|
||||||
const userBalance = ref({
|
const userBalance = ref({
|
||||||
@@ -747,7 +747,27 @@ const confirmPayment = async () => {
|
|||||||
|
|
||||||
paying.value = true
|
paying.value = true
|
||||||
|
|
||||||
// 创建订单数据
|
if (selectedPaymentMethod.value === 'wechat_h5' || selectedPaymentMethod.value === 'alipay_wap') {
|
||||||
|
const amount = Number(getRMBPrice())
|
||||||
|
const response = await buyAPI.buy({
|
||||||
|
paymentMethod: selectedPaymentMethod.value,
|
||||||
|
amount: amount*100
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response?.data?.success) {
|
||||||
|
const payUrl = response.data.data?.payUrl
|
||||||
|
if (payUrl) {
|
||||||
|
window.location.href = payUrl
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
throw new Error('未获取到支付链接')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(response?.data?.message || '创建支付订单失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其他支付方式:走原订单确认流程
|
||||||
const orderData = {
|
const orderData = {
|
||||||
orderId: paymentData.value.orderId,
|
orderId: paymentData.value.orderId,
|
||||||
addressId: selectedAddress.value.id,
|
addressId: selectedAddress.value.id,
|
||||||
@@ -756,40 +776,12 @@ const confirmPayment = async () => {
|
|||||||
beansAmount: paymentData.value.beansAmount
|
beansAmount: paymentData.value.beansAmount
|
||||||
}
|
}
|
||||||
|
|
||||||
// 向后端发送订单支付请求
|
|
||||||
const response = await api.post('/orders/confirm-payment', orderData)
|
const response = await api.post('/orders/confirm-payment', orderData)
|
||||||
|
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
// 微信支付
|
|
||||||
if (selectedPaymentMethod.value === 'wechat_h5') {
|
|
||||||
// 获取支付URL并跳转
|
|
||||||
const payUrl = response.data.data?.payUrl
|
|
||||||
if (payUrl) {
|
|
||||||
// 跳转到第三方支付页面
|
|
||||||
window.location.href = payUrl
|
|
||||||
return // 不再执行后续代码
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支付宝支付
|
|
||||||
if (selectedPaymentMethod.value === 'alipay_wap') {
|
|
||||||
// 获取支付URL并跳转
|
|
||||||
const payUrl = response.data.data?.payUrl
|
|
||||||
if (payUrl) {
|
|
||||||
// 跳转到支付宝支付页面
|
|
||||||
window.location.href = payUrl
|
|
||||||
return // 不再执行后续代码
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ElMessage.success('订单创建成功!')
|
ElMessage.success('订单创建成功!')
|
||||||
|
|
||||||
// 跳转到PayLoading页面,传递订单ID
|
|
||||||
router.push({
|
router.push({
|
||||||
path: '/payloading',
|
path: '/payloading',
|
||||||
query: {
|
query: { orderId: paymentData.value.orderId }
|
||||||
orderId: paymentData.value.orderId
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.data.message || '创建订单失败')
|
throw new Error(response.data.message || '创建订单失败')
|
||||||
|
|||||||
@@ -309,6 +309,7 @@ const getProductDetail = async () => {
|
|||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error('获取商品详情失败')
|
ElMessage.error('获取商品详情失败')
|
||||||
|
console.log('获取商品详情失败',error);
|
||||||
router.go(-1)
|
router.go(-1)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ export default defineConfig({
|
|||||||
proxy: {
|
proxy: {
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://192.168.0.26:3000',
|
target: 'http://192.168.0.26:3000',
|
||||||
changeOrigin: true
|
changeOrigin: true,
|
||||||
|
},
|
||||||
|
'/mid': {
|
||||||
|
target: 'http://192.168.0.12:3005',
|
||||||
|
changeOrigin: true,
|
||||||
|
// rewrite: (path) => path.replace(/^\/mid/, '')
|
||||||
},
|
},
|
||||||
'/uploads': {
|
'/uploads': {
|
||||||
target: 'http://192.168.0.26:3000',
|
target: 'http://192.168.0.26:3000',
|
||||||
|
|||||||
Reference in New Issue
Block a user