refactor(store): 重构状态管理模块,迁移至pinia架构
将原有vuex状态管理迁移至pinia架构,包括用户、购物车、订单等核心模块 新增支付方式映射、验证工具函数等实用工具 优化状态持久化配置,统一使用uni-app存储API 重构企业微信登录逻辑,增加模拟登录功能
This commit is contained in:
parent
23041a62d2
commit
1b82b8baab
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { createPinia } from "pinia"
|
||||||
|
import { createPersistedState } from "pinia-plugin-persistedstate"
|
||||||
|
|
||||||
|
export const pinia = createPinia();
|
||||||
|
|
||||||
|
pinia.use(
|
||||||
|
createPersistedState({
|
||||||
|
storage: {
|
||||||
|
getItem: uni.getStorageSync,
|
||||||
|
setItem: uni.setStorageSync,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
import { pinia } from "@/pinia"
|
||||||
|
import { LoginData } from "@/api/ab98/types"
|
||||||
|
import { defineStore } from "pinia"
|
||||||
|
|
||||||
|
// 本地存储键名常量
|
||||||
|
const STORAGE_KEYS = {
|
||||||
|
FACE: 'ab98_face',
|
||||||
|
SEX: 'ab98_sex',
|
||||||
|
NAME: 'ab98_name',
|
||||||
|
USERID: 'ab98_userid',
|
||||||
|
REGISTERED: 'ab98_registered',
|
||||||
|
TEL: 'ab98_tel',
|
||||||
|
TOKEN: 'ab98_token',
|
||||||
|
LOGIN_CODE: 'ab98_login_code'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AB98用户信息存储
|
||||||
|
* @description 管理AB98系统用户相关状态信息
|
||||||
|
*/
|
||||||
|
export const useAb98UserStore = defineStore("ab98User", () => {
|
||||||
|
// 用户面部图像URL
|
||||||
|
const storedFace = localStorage.getItem(STORAGE_KEYS.FACE)
|
||||||
|
const face_img = ref<string>(storedFace ? decodeURIComponent(storedFace) : '')
|
||||||
|
// 用户性别(男/女)
|
||||||
|
const storedSex = localStorage.getItem(STORAGE_KEYS.SEX)
|
||||||
|
const sex = ref<string>(storedSex ? decodeURIComponent(storedSex) : '')
|
||||||
|
// 用户真实姓名
|
||||||
|
const storedName = localStorage.getItem(STORAGE_KEYS.NAME)
|
||||||
|
const name = ref<string>(storedName ? decodeURIComponent(storedName) : '')
|
||||||
|
// AB98系统用户唯一标识
|
||||||
|
const storedUserId = localStorage.getItem(STORAGE_KEYS.USERID)
|
||||||
|
const userid = ref<string>(storedUserId ? decodeURIComponent(storedUserId) : "")
|
||||||
|
// 是否已完成注册流程
|
||||||
|
const registered = ref<boolean>(JSON.parse(localStorage.getItem(STORAGE_KEYS.REGISTERED) || "false"))
|
||||||
|
// 用户绑定手机号
|
||||||
|
const storedTel = localStorage.getItem(STORAGE_KEYS.TEL)
|
||||||
|
const tel = ref<string>(storedTel ? decodeURIComponent(storedTel) : "")
|
||||||
|
// 用户认证令牌
|
||||||
|
const storedToken = localStorage.getItem(STORAGE_KEYS.TOKEN)
|
||||||
|
const token = ref<string>(storedToken ? decodeURIComponent(storedToken) : "");
|
||||||
|
|
||||||
|
const tokenLogin = ref<string>("");
|
||||||
|
// 登录验证码
|
||||||
|
const loginCode = '1'; // 默认验证码
|
||||||
|
// 用户登录状态
|
||||||
|
const isLogin = ref<boolean>(false);
|
||||||
|
const storedLoginCode = localStorage.getItem(STORAGE_KEYS.LOGIN_CODE);
|
||||||
|
isLogin.value = tel.value && storedLoginCode === String(loginCode) ? true : false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新用户基本信息
|
||||||
|
* @param data - 登录接口返回的用户数据
|
||||||
|
*/
|
||||||
|
const setUserInfo = (data: LoginData) => {
|
||||||
|
face_img.value = data.face_img
|
||||||
|
localStorage.setItem(STORAGE_KEYS.FACE, encodeURIComponent(data.face_img))
|
||||||
|
sex.value = data.sex
|
||||||
|
localStorage.setItem(STORAGE_KEYS.SEX, encodeURIComponent(data.sex))
|
||||||
|
name.value = data.name
|
||||||
|
localStorage.setItem(STORAGE_KEYS.NAME, encodeURIComponent(data.name))
|
||||||
|
userid.value = data.userid
|
||||||
|
localStorage.setItem(STORAGE_KEYS.USERID, encodeURIComponent(data.userid))
|
||||||
|
registered.value = data.registered
|
||||||
|
localStorage.setItem(STORAGE_KEYS.REGISTERED, JSON.stringify(data.registered))
|
||||||
|
tel.value = data.tel
|
||||||
|
localStorage.setItem(STORAGE_KEYS.TEL, encodeURIComponent(data.tel))
|
||||||
|
localStorage.setItem(STORAGE_KEYS.LOGIN_CODE, encodeURIComponent(loginCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空用户敏感信息
|
||||||
|
* @description 用于用户登出或会话过期时
|
||||||
|
*/
|
||||||
|
const clearUserInfo = () => {
|
||||||
|
face_img.value = ""
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.FACE)
|
||||||
|
sex.value = ""
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.SEX)
|
||||||
|
name.value = ""
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.NAME)
|
||||||
|
userid.value = ""
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.USERID)
|
||||||
|
registered.value = false
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.REGISTERED)
|
||||||
|
tel.value = ""
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.TEL)
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.TOKEN)
|
||||||
|
localStorage.removeItem(STORAGE_KEYS.LOGIN_CODE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置认证令牌
|
||||||
|
* @param value - JWT格式的认证令牌
|
||||||
|
*/
|
||||||
|
const setToken = (value: string) => {
|
||||||
|
localStorage.setItem(STORAGE_KEYS.TOKEN, encodeURIComponent(value))
|
||||||
|
token.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
const setTel = (value: string) => {
|
||||||
|
localStorage.setItem(STORAGE_KEYS.TEL, btoa(value))
|
||||||
|
tel.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
const setIsLogin = (value: boolean) => {
|
||||||
|
isLogin.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const setTokenLogin = (value: string) => {
|
||||||
|
tokenLogin.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
face_img,
|
||||||
|
sex,
|
||||||
|
name,
|
||||||
|
userid,
|
||||||
|
registered,
|
||||||
|
tel,
|
||||||
|
token,
|
||||||
|
isLogin,
|
||||||
|
tokenLogin,
|
||||||
|
setUserInfo,
|
||||||
|
setToken,
|
||||||
|
setTel,
|
||||||
|
setIsLogin,
|
||||||
|
clearUserInfo,
|
||||||
|
setTokenLogin
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 在非setup上下文或SSR场景中使用store
|
||||||
|
*/
|
||||||
|
export function useAb98UserStoreOutside() {
|
||||||
|
return useAb98UserStore(pinia)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import type { ReturnApprovalAssetDTO } from '@/api/approval/types'
|
||||||
|
|
||||||
|
export interface ApprovalDetail extends ReturnApprovalAssetDTO {
|
||||||
|
goodsName: string
|
||||||
|
coverImg: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useApprovalStore = defineStore('approval', () => {
|
||||||
|
const currentApproval = ref<ApprovalDetail | null>(null)
|
||||||
|
|
||||||
|
const setCurrentApproval = (approval: ApprovalDetail) => {
|
||||||
|
currentApproval.value = approval
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentApproval,
|
||||||
|
setCurrentApproval
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function useApprovalStoreOutside() {
|
||||||
|
return useApprovalStore()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import type { Product } from './product'
|
||||||
|
|
||||||
|
export const useCartStore = defineStore('cart', () => {
|
||||||
|
// 购物车商品列表
|
||||||
|
const cartItems = ref<Array<{ product: Product; quantity: number }>>([])
|
||||||
|
|
||||||
|
// 添加商品到购物车
|
||||||
|
const addToCart = (product: Product, quantity: number = 1): boolean => {
|
||||||
|
if (quantity > product.stock && product.stock !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const existingItem = cartItems.value.find(item => item.product.cellId === product.cellId)
|
||||||
|
if (existingItem) {
|
||||||
|
if (existingItem.quantity + quantity > product.stock && product.stock !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
existingItem.quantity += quantity
|
||||||
|
} else {
|
||||||
|
cartItems.value.push({ product, quantity })
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除商品
|
||||||
|
const removeFromCart = (cellId: number, quantity: number = 1) => {
|
||||||
|
const index = cartItems.value.findIndex(item => item.product.cellId === cellId)
|
||||||
|
if (index !== -1) {
|
||||||
|
if (cartItems.value[index].quantity <= quantity) {
|
||||||
|
cartItems.value.splice(index, 1)
|
||||||
|
} else {
|
||||||
|
cartItems.value[index].quantity -= quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算总价
|
||||||
|
const totalPrice = computed(() => {
|
||||||
|
return cartItems.value.reduce((sum, item) => {
|
||||||
|
return sum + (item.product.price || 0) * item.quantity
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
//计算总数
|
||||||
|
const totalQuantity = computed(() => {
|
||||||
|
return cartItems.value.reduce((sum, item) => {
|
||||||
|
return sum + item.quantity
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 清空购物车
|
||||||
|
const clearCart = () => {
|
||||||
|
cartItems.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
cartItems,
|
||||||
|
addToCart,
|
||||||
|
removeFromCart,
|
||||||
|
totalPrice,
|
||||||
|
totalQuantity,
|
||||||
|
clearCart
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 支持在setup外使用
|
||||||
|
export function useCartStoreOutside() {
|
||||||
|
return useCartStore()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import type { RouteLocationNormalizedGeneric } from "vue-router"
|
||||||
|
import { pinia } from "@/pinia"
|
||||||
|
import { defineStore } from "pinia"
|
||||||
|
import { isString } from "@/utils/validate"
|
||||||
|
|
||||||
|
export const useKeepAliveStore = defineStore("keep-alive", () => {
|
||||||
|
const cachedRoutes = ref<string[]>([])
|
||||||
|
|
||||||
|
const addCachedRoute = (route: RouteLocationNormalizedGeneric) => {
|
||||||
|
const keepAlive = route.meta.keepAlive
|
||||||
|
const name = route.name
|
||||||
|
if (keepAlive && name && isString(name) && !cachedRoutes.value.includes(name)) {
|
||||||
|
cachedRoutes.value.push(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const delAllCachedRoutes = () => {
|
||||||
|
cachedRoutes.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
return { cachedRoutes, addCachedRoute, delAllCachedRoutes }
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||||
|
* @description 在 SSR 应用中可用于在 setup 外使用 store
|
||||||
|
*/
|
||||||
|
export function useKeepAliveStoreOutside() {
|
||||||
|
return useKeepAliveStore(pinia)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { pinia } from "@/pinia"
|
||||||
|
import { getOrdersByOpenIdApi, getOrdersByQyUserIdApi } from "@/api/shop"
|
||||||
|
import type { ShopOrderEntity, ShopOrderGoodsEntity, Goods } from "@/api/shop/types"
|
||||||
|
import { defineStore } from "pinia"
|
||||||
|
|
||||||
|
export interface Order extends ShopOrderEntity {
|
||||||
|
goodsList: Array<OrderGoods>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderGoods {
|
||||||
|
goodsInfo: Goods
|
||||||
|
orderGoods: ShopOrderGoodsEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useOrderStore = defineStore("order", () => {
|
||||||
|
const orders = ref<Order[]>([])
|
||||||
|
const orderGoods = ref<ShopOrderGoodsEntity[]>([])
|
||||||
|
const goods = ref<Goods[]>([])
|
||||||
|
|
||||||
|
const getOrders = async (corpid: string, openid: string, qyUserId: number, hasReturn: number) => {
|
||||||
|
try {
|
||||||
|
const { data } = qyUserId ?
|
||||||
|
await getOrdersByQyUserIdApi(qyUserId, hasReturn)
|
||||||
|
: await getOrdersByOpenIdApi(corpid, openid, hasReturn);
|
||||||
|
|
||||||
|
// 重组订单结构
|
||||||
|
orders.value = data.orders.map(order => ({
|
||||||
|
...order,
|
||||||
|
goodsList: data.orderGoods
|
||||||
|
.filter(og => og.orderId === order.orderId)
|
||||||
|
.map(og => ({
|
||||||
|
orderGoods: og,
|
||||||
|
goodsInfo: data.goods.find(g => g.goodsId === og.goodsId)!
|
||||||
|
}))
|
||||||
|
}))
|
||||||
|
.sort((a, b) => b.orderId - a.orderId)
|
||||||
|
|
||||||
|
// 保留原始数据结构
|
||||||
|
orderGoods.value = data.orderGoods
|
||||||
|
goods.value = data.goods
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取订单数据失败:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { orders, orderGoods, goods, getOrders }
|
||||||
|
})
|
||||||
|
|
||||||
|
export function useOrderStoreOutside() {
|
||||||
|
return useOrderStore(pinia)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { ShopEntity } from "@/api/shop/types"
|
||||||
|
import { pinia } from "@/pinia"
|
||||||
|
import { getShopGoodsApi } from "@/api/shop"
|
||||||
|
import { defineStore } from "pinia"
|
||||||
|
|
||||||
|
export interface Product {
|
||||||
|
id: number // 商品ID
|
||||||
|
name: string // 商品名称
|
||||||
|
price: number // 商品价格
|
||||||
|
stock: number // 商品库存
|
||||||
|
description: string // 商品描述
|
||||||
|
image: string // 商品图片URL
|
||||||
|
label: number // 商品标签
|
||||||
|
cellId: number // 商品所在的格子ID
|
||||||
|
usageInstruction: string // 商品使用说明
|
||||||
|
belongType: number // 商品所属类型 0: 智借还 1: 固资通
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useProductStore = defineStore("product", () => {
|
||||||
|
// 商品数据
|
||||||
|
const labels = ref<{ id: number, name: string }[]>([]);
|
||||||
|
const categories = ref<Product[]>([]);
|
||||||
|
const shopId = ref<number|null>(null);
|
||||||
|
const selectedShop = ref<ShopEntity|null>(null);
|
||||||
|
|
||||||
|
const setSelectedShop = (shop: ShopEntity) => {
|
||||||
|
selectedShop.value = shop;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getGoods = async (shopId_?: number) => {
|
||||||
|
if (shopId_ && shopId_ > 0) {
|
||||||
|
shopId.value = shopId_;
|
||||||
|
} else {
|
||||||
|
shopId.value = null;
|
||||||
|
/* const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const shopIdParams = urlParams.get('shopId') || undefined;
|
||||||
|
if (shopIdParams) {
|
||||||
|
shopId.value = Number(shopIdParams);
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data } = await getShopGoodsApi(shopId.value);
|
||||||
|
|
||||||
|
// 转换分类标签
|
||||||
|
labels.value = data.categoryList.map(c => ({
|
||||||
|
id: c.categoryId, // 使用分类名称生成ID
|
||||||
|
name: c.categoryName
|
||||||
|
}))
|
||||||
|
|
||||||
|
// 转换商品数据
|
||||||
|
categories.value = data.goodsList.map(g => ({
|
||||||
|
id: g.goodsId,
|
||||||
|
name: g.goodsName,
|
||||||
|
price: g.price,
|
||||||
|
stock: g.stock,
|
||||||
|
description: g.goodsDetail || "暂无描述",
|
||||||
|
image: g.coverImg,
|
||||||
|
label: g.categoryId,
|
||||||
|
cellId: g.cellId,
|
||||||
|
usageInstruction: g.usageInstruction || "",
|
||||||
|
belongType: g.belongType
|
||||||
|
}))
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取商品数据失败:", error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { labels, categories, shopId, selectedShop,
|
||||||
|
getGoods, setSelectedShop }
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
|
||||||
|
* @description 在 SSR 应用中可用于在 setup 外使用 store
|
||||||
|
*/
|
||||||
|
export function useProductStoreOutside() {
|
||||||
|
return useProductStore(pinia)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { getRentingCabinetDetailApi } from '@/api/cabinet'
|
||||||
|
import type { CabinetCellEntity, RentingCabinetDetailDTO } from '@/api/cabinet/types'
|
||||||
|
|
||||||
|
export const useRentingCabinetStore = defineStore('rentingCabinet', () => {
|
||||||
|
const rentingCabinets = ref<RentingCabinetDetailDTO[]>([])
|
||||||
|
|
||||||
|
// 租用购物车列表
|
||||||
|
const rentingCartItems = ref<Array<{ cabinetCell: CabinetCellEntity; quantity: number }>>([])
|
||||||
|
|
||||||
|
const fetchRentingCabinetDetail = async (shopId: number) => {
|
||||||
|
const res = await getRentingCabinetDetailApi(shopId);
|
||||||
|
console.log(res)
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
rentingCabinets.value = res.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加到租用购物车
|
||||||
|
const addToRentingCart = (cabinetCell: CabinetCellEntity, quantity: number = 1): boolean => {
|
||||||
|
if (quantity <= 0) return false
|
||||||
|
const existingItem = rentingCartItems.value.find(item => item.cabinetCell.cellId === cabinetCell.cellId)
|
||||||
|
if (existingItem) {
|
||||||
|
existingItem.quantity += quantity
|
||||||
|
} else {
|
||||||
|
rentingCartItems.value.push({ cabinetCell, quantity })
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从购物车移除
|
||||||
|
const removeFromRentingCart = (cellId: number, quantity: number = 1) => {
|
||||||
|
const index = rentingCartItems.value.findIndex(item => item.cabinetCell.cellId === cellId)
|
||||||
|
if (index !== -1) {
|
||||||
|
if (rentingCartItems.value[index].quantity <= quantity) {
|
||||||
|
rentingCartItems.value.splice(index, 1)
|
||||||
|
} else {
|
||||||
|
rentingCartItems.value[index].quantity -= quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算租用总数
|
||||||
|
const rentingCartTotalQuantity = computed(() => {
|
||||||
|
return rentingCartItems.value.reduce((total, item) => total + item.quantity, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算租用总价
|
||||||
|
const rentingCartTotalPrice = computed(() => {
|
||||||
|
return rentingCartItems.value.reduce((sum, item) => {
|
||||||
|
return sum + (item.cabinetCell.cellPrice || 0) * item.quantity
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 清空租用购物车
|
||||||
|
const clearRentingCart = () => {
|
||||||
|
rentingCartItems.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
rentingCabinets,
|
||||||
|
rentingCartItems,
|
||||||
|
addToRentingCart,
|
||||||
|
removeFromRentingCart,
|
||||||
|
rentingCartTotalQuantity,
|
||||||
|
rentingCartTotalPrice,
|
||||||
|
clearRentingCart,
|
||||||
|
fetchRentingCabinetDetail
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export function useRentingCabinetStoreOutside() {
|
||||||
|
return useRentingCabinetStore()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
import { pinia } from "@/pinia"
|
||||||
|
import { getOpenIdApi, getBalanceApi, qyLogin, getBalanceByQyUserid, fakeQyLoginApi } from "@/api/shop"
|
||||||
|
import { ab98UserDTO, GetBalanceResponse } from "@/api/shop/types"
|
||||||
|
import { useAb98UserStore } from "./ab98-user"
|
||||||
|
import { defineStore } from "pinia"
|
||||||
|
|
||||||
|
|
||||||
|
export const useWxStore = defineStore("wx", () => {
|
||||||
|
// 微信授权 code
|
||||||
|
const code = ref<string>("")
|
||||||
|
// 防止 CSRF 攻击的 state 参数
|
||||||
|
const state = ref<string>("")
|
||||||
|
// 用户 openid
|
||||||
|
const openid = ref<string>("")
|
||||||
|
// 用户 userid
|
||||||
|
const userid = ref<string>("");
|
||||||
|
// 剩余借呗
|
||||||
|
const balance = ref<number>(0);
|
||||||
|
// 已用借呗
|
||||||
|
const useBalance = ref<number>(0);
|
||||||
|
// 借呗总额
|
||||||
|
const balanceLimit = ref<number>(0);
|
||||||
|
// 企业id
|
||||||
|
const corpid = ref<string>("");
|
||||||
|
// 是否企业微信登录
|
||||||
|
const corpidLogin = ref<boolean>(false);
|
||||||
|
// 是否是柜子管理员
|
||||||
|
const isCabinetAdmin = ref<boolean>(false);
|
||||||
|
// 企业微信用户姓名
|
||||||
|
const name = ref<string>("");
|
||||||
|
// 企业微信用户id
|
||||||
|
const qyUserId = ref<number>(0);
|
||||||
|
// 汇邦云用户信息
|
||||||
|
const ab98User = ref<ab98UserDTO | null>(null);
|
||||||
|
|
||||||
|
const isFakeQyLogin = ref<boolean>(false);
|
||||||
|
// handleWxCallback 是否完成
|
||||||
|
const isHandleWxCallbackComplete = ref<boolean>(false);
|
||||||
|
|
||||||
|
// 设置 openid
|
||||||
|
const setOpenid = (id: string) => {
|
||||||
|
openid.value = id
|
||||||
|
}
|
||||||
|
|
||||||
|
const setBalance = (amount: number) => {
|
||||||
|
balance.value = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
const setIsCabinetAdmin = (isAdmin: boolean) => {
|
||||||
|
isCabinetAdmin.value = isAdmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
const setAb98User = (user: ab98UserDTO) => {
|
||||||
|
ab98User.value = user;
|
||||||
|
const ab98UserStore = useAb98UserStore();
|
||||||
|
ab98UserStore.setUserInfo({
|
||||||
|
face_img: ab98User.value.faceImg || "",
|
||||||
|
success: true,
|
||||||
|
sex: ab98User.value.sex || "",
|
||||||
|
name: ab98User.value.name || "",
|
||||||
|
userid: ab98User.value.userid || "",
|
||||||
|
registered: true,
|
||||||
|
tel: ab98User.value.tel || "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const refreshBalance = async () => {
|
||||||
|
if (corpid.value && userid.value) {
|
||||||
|
const res = await getBalanceByQyUserid(corpid.value, userid.value);
|
||||||
|
if (res && res.code == 0) {
|
||||||
|
balance.value = res.data.balance;
|
||||||
|
useBalance.value = res.data.useBalance;
|
||||||
|
balanceLimit.value = res.data.balanceLimit;
|
||||||
|
|
||||||
|
if (res.data.ab98User) {
|
||||||
|
setAb98User(res.data.ab98User);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleWxCallback = async (params: { corpid?: string; code?: string; state?: string; }) => {
|
||||||
|
console.log('handleWxCallback:', params)
|
||||||
|
isHandleWxCallbackComplete.value = false; // 开始处理,标记为未完成
|
||||||
|
if (params.code) {
|
||||||
|
code.value = params.code
|
||||||
|
state.value = params.state || state.value
|
||||||
|
corpid.value = params.corpid || corpid.value
|
||||||
|
corpidLogin.value = !!corpid.value;
|
||||||
|
console.log('corpid:', corpid.value)
|
||||||
|
console.log('corpidLogin:', corpidLogin.value)
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!corpid.value) {
|
||||||
|
// 调用获取 openid 的接口
|
||||||
|
const res = await getOpenIdApi({ code: params.code });
|
||||||
|
if (res && res.code == 0) {
|
||||||
|
openid.value = res.data
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 企业微信登录
|
||||||
|
const res = await qyLogin({ corpid: corpid.value, code: params.code, state: params.state})
|
||||||
|
if (res && res.code == 0) {
|
||||||
|
userid.value = res.data.userid;
|
||||||
|
openid.value = res.data.openid;
|
||||||
|
isCabinetAdmin.value = res.data.isCabinetAdmin === 1;
|
||||||
|
name.value = res.data.name;
|
||||||
|
qyUserId.value = res.data.qyUserId;
|
||||||
|
setAb98User(res.data.ab98User);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openid.value) {
|
||||||
|
// 获取用户余额
|
||||||
|
let balanceRes: ApiResponseData<GetBalanceResponse> | null = null;
|
||||||
|
|
||||||
|
if(corpid.value) {
|
||||||
|
balanceRes = await getBalanceByQyUserid(corpid.value, userid.value);
|
||||||
|
} else {
|
||||||
|
corpid.value = "wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw";
|
||||||
|
balanceRes = await getBalanceApi(corpid.value, openid.value)
|
||||||
|
}
|
||||||
|
console.log('获取余额成功:', balanceRes)
|
||||||
|
if (balanceRes && balanceRes.code == 0) {
|
||||||
|
balance.value = balanceRes.data.balance;
|
||||||
|
useBalance.value = balanceRes.data.useBalance;
|
||||||
|
balanceLimit.value = balanceRes.data.balanceLimit;
|
||||||
|
if (!userid.value) {
|
||||||
|
userid.value = balanceRes.data.userid;
|
||||||
|
}
|
||||||
|
if (!ab98User.value && balanceRes.data.ab98User) {
|
||||||
|
setAb98User(balanceRes.data.ab98User);
|
||||||
|
}
|
||||||
|
/* if (!corpid.value) {
|
||||||
|
corpid.value = balanceRes.data.corpid;
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取 openid 失败:', err)
|
||||||
|
} finally {
|
||||||
|
isHandleWxCallbackComplete.value = true; // 处理完成,标记为已完成
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
isHandleWxCallbackComplete.value = true; // 没有code参数,直接标记为已完成
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fakeQyLogin = async () => {
|
||||||
|
isFakeQyLogin.value = true;
|
||||||
|
corpid.value = "wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw";
|
||||||
|
corpidLogin.value = true;
|
||||||
|
userid.value = "woZ1ZrEgAAV9AEdRt1MGQxSg-KDJrDlA";
|
||||||
|
const res = await fakeQyLoginApi({ corpid: corpid.value, userid: userid.value})
|
||||||
|
if (res && res.code == 0) {
|
||||||
|
userid.value = res.data.userid;
|
||||||
|
openid.value = "oMRxw6Eum0DB1IjI_pEX_yrawBHw";
|
||||||
|
isCabinetAdmin.value = res.data.isCabinetAdmin === 1;
|
||||||
|
name.value = res.data.name;
|
||||||
|
qyUserId.value = res.data.qyUserId;
|
||||||
|
setAb98User(res.data.ab98User);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检测 handleWxCallback 是否完成的异步函数
|
||||||
|
const waitForHandleWxCallbackComplete = async (timeout = 30000): Promise<boolean> => {
|
||||||
|
const startTime = Date.now();
|
||||||
|
while (!isHandleWxCallbackComplete.value) {
|
||||||
|
if (Date.now() - startTime > timeout) {
|
||||||
|
console.warn('等待 handleWxCallback 完成超时');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100)); // 每100ms检查一次
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { code, state, openid, corpid, userid, balance, useBalance,
|
||||||
|
balanceLimit, isCabinetAdmin, corpidLogin, name, ab98User, qyUserId, isFakeQyLogin,
|
||||||
|
isHandleWxCallbackComplete, setOpenid, setBalance, handleWxCallback, setIsCabinetAdmin,
|
||||||
|
refreshBalance, setAb98User, fakeQyLogin, waitForHandleWxCallbackComplete }
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 用于在 setup 外使用 store
|
||||||
|
*/
|
||||||
|
export function useWxStoreOutside() {
|
||||||
|
return useWxStore(pinia)
|
||||||
|
}
|
||||||
|
|
@ -1,160 +0,0 @@
|
||||||
import {defineStore} from 'pinia';
|
|
||||||
import {ref} from 'vue';
|
|
||||||
import {addCart, listCart, operateAmount} from '@/api/goods/shopping-cart';
|
|
||||||
|
|
||||||
// 商品类型定义
|
|
||||||
interface CartItem {
|
|
||||||
cartId: string; // 购物车唯一标识
|
|
||||||
id: string; // 商品原始id
|
|
||||||
name: string;
|
|
||||||
image?: string;
|
|
||||||
pictures?: string[];
|
|
||||||
price: number;
|
|
||||||
spec: string;
|
|
||||||
quantity: number;
|
|
||||||
selected: boolean;
|
|
||||||
originalPrice?: number;
|
|
||||||
listId?: string;
|
|
||||||
specs?: string;
|
|
||||||
type: string;
|
|
||||||
specification?: any;
|
|
||||||
status: number;
|
|
||||||
amount: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useCartStore = defineStore('cart', () => {
|
|
||||||
// 购物车商品列表
|
|
||||||
const items = ref<CartItem[]>([]);
|
|
||||||
// 购物车详情
|
|
||||||
const itemsDetail = ref<CartItem>()
|
|
||||||
|
|
||||||
//订单详情
|
|
||||||
const orderDetail = ref<CartItem[]>()
|
|
||||||
|
|
||||||
// 查询购物车列表
|
|
||||||
const getListCart = async () => {
|
|
||||||
return listCart().then((res: any) => {
|
|
||||||
if (res.data?.products){
|
|
||||||
items.value = res.data.products.map((item: any) => {
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
...item.product,
|
|
||||||
title: item.name,
|
|
||||||
price: item.price,
|
|
||||||
type: item.type === 1 ? 'product' : 'service',
|
|
||||||
status: item.status,
|
|
||||||
specs: selectSpecs(item.product.specificationPrices),
|
|
||||||
specsIds: selectSpecsIds(item.product.specificationPrices),
|
|
||||||
id: item.id,
|
|
||||||
selected:true,
|
|
||||||
listId: `${item.productId}_${item.type === 1 ? 'product' : 'service'}`,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加商品到购物车 type 用于区分是添加购物车还是恢复购物车
|
|
||||||
const addItem = (product: Omit<CartItem, 'selected'>) => {
|
|
||||||
//把一下数据异步返回
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
//加入购物车
|
|
||||||
addCart({
|
|
||||||
productId: product.id,
|
|
||||||
type: product.type === 'product' ? 1 : 0,
|
|
||||||
price:product.price,
|
|
||||||
amount:product.amount || 1,
|
|
||||||
selected:true,
|
|
||||||
specification:product.specs ? product.specification : undefined,
|
|
||||||
formId: new Date().getTime()
|
|
||||||
}).then(res => {
|
|
||||||
uni.showToast({ title: '加入购物车', icon: 'none' })
|
|
||||||
resolve(res)
|
|
||||||
}).catch(err => {
|
|
||||||
reject(err)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
// 从购物车移除商品
|
|
||||||
const removeItem = (cartId: string) => {
|
|
||||||
items.value = items.value.filter(item => item.id !== cartId);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 更新商品数量
|
|
||||||
const updateQuantity = (cartId: string, amount: number) => {
|
|
||||||
operateAmount({
|
|
||||||
id:cartId,
|
|
||||||
amount
|
|
||||||
}).then(res => {
|
|
||||||
if (res.data.operator === 'add') {
|
|
||||||
uni.showToast({ title: '加入购物车', icon: 'none' })
|
|
||||||
}
|
|
||||||
}).catch(err => {
|
|
||||||
uni.showToast({ title: err, icon: 'none' })
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
// 全选/取消全选
|
|
||||||
const toggleAllItems = (checked: boolean) => {
|
|
||||||
items.value = items.value.map(item => ({ ...item, selected: checked }));
|
|
||||||
};
|
|
||||||
|
|
||||||
// 切换商品选中状态
|
|
||||||
const toggleItemSelection = (cartId: string, selected?: boolean, item?: CartItem) => {
|
|
||||||
items.value = items.value.map(item =>
|
|
||||||
item.id === cartId ? { ...item, selected: selected ?? !item.selected } : item
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
// 清空购物车
|
|
||||||
const clearCart = () => {
|
|
||||||
items.value = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
items,
|
|
||||||
itemsDetail,
|
|
||||||
orderDetail,
|
|
||||||
getListCart,
|
|
||||||
addItem,
|
|
||||||
removeItem,
|
|
||||||
updateQuantity,
|
|
||||||
toggleAllItems,
|
|
||||||
toggleItemSelection,
|
|
||||||
clearCart
|
|
||||||
};
|
|
||||||
});
|
|
||||||
//取层级数据
|
|
||||||
//规格名称
|
|
||||||
const selectSpecs = ((row:any) => {
|
|
||||||
let result = '';
|
|
||||||
if (row) {
|
|
||||||
let row1 = row[0]
|
|
||||||
result = result + row1.value;
|
|
||||||
if(row1.child){
|
|
||||||
let row2 = row1.child[0]
|
|
||||||
result = result + ';' + row1.child[0].value;
|
|
||||||
if(row2.child){
|
|
||||||
result = result + ';' + row2.child[0].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
//取规格id
|
|
||||||
const selectSpecsIds = ((row:any)=>{
|
|
||||||
let result = '';
|
|
||||||
if (row) {
|
|
||||||
let row1 = row[0]
|
|
||||||
result = result + row1.id;
|
|
||||||
if(row1.child){
|
|
||||||
let row2 = row1.child[0]
|
|
||||||
result = result + ',' + row1.child[0].id;
|
|
||||||
if(row2.child){
|
|
||||||
result = result + ',' + row2.child[0].id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
})
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
import { createPinia } from 'pinia'
|
|
||||||
import { createPersistedState } from 'pinia-plugin-persistedstate' // 数据持久化
|
|
||||||
|
|
||||||
const store = createPinia()
|
|
||||||
store.use(
|
|
||||||
createPersistedState({
|
|
||||||
storage: {
|
|
||||||
getItem: uni.getStorageSync,
|
|
||||||
setItem: uni.setStorageSync,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
export default store
|
|
||||||
|
|
||||||
export * from './theme'
|
|
||||||
// 模块统一导出
|
|
||||||
export * from './user'
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
import type { ConfigProviderThemeVars } from 'wot-design-uni'
|
|
||||||
|
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useThemeStore = defineStore(
|
|
||||||
'theme-store',
|
|
||||||
() => {
|
|
||||||
/** 主题 */
|
|
||||||
const theme = ref<'light' | 'dark'>('light')
|
|
||||||
|
|
||||||
/** 主题变量 */
|
|
||||||
const themeVars = ref<ConfigProviderThemeVars>({
|
|
||||||
// colorTheme: 'red',
|
|
||||||
// buttonPrimaryBgColor: '#07c160',
|
|
||||||
// buttonPrimaryColor: '#07c160',
|
|
||||||
})
|
|
||||||
|
|
||||||
/** 设置主题变量 */
|
|
||||||
const setThemeVars = (partialVars: Partial<ConfigProviderThemeVars>) => {
|
|
||||||
themeVars.value = { ...themeVars.value, ...partialVars }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 切换主题 */
|
|
||||||
const toggleTheme = () => {
|
|
||||||
theme.value = theme.value === 'light' ? 'dark' : 'light'
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
/** 设置主题变量 */
|
|
||||||
setThemeVars,
|
|
||||||
/** 切换主题 */
|
|
||||||
toggleTheme,
|
|
||||||
/** 主题变量 */
|
|
||||||
themeVars,
|
|
||||||
/** 主题 */
|
|
||||||
theme,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
persist: true,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
@ -1,221 +0,0 @@
|
||||||
/**
|
|
||||||
* 登录用户状态管理
|
|
||||||
*/
|
|
||||||
import { defineStore } from 'pinia';
|
|
||||||
import type { User } from '@/api/system/user/model/';
|
|
||||||
import type { Menu } from '@/api/system/menu/model';
|
|
||||||
import { toTree,mapTree, isExternalLink } from '@/utils/dataTree';
|
|
||||||
import { getInfoByMember,getStoreSettings,getShopList } from '@/api/layout';
|
|
||||||
import store from "@/store/index";
|
|
||||||
import bus, {EVENT_KEY} from "@/utils/bus";
|
|
||||||
/**
|
|
||||||
* 菜单数据
|
|
||||||
*/
|
|
||||||
export interface MenuItem {
|
|
||||||
/** 路由名称 */
|
|
||||||
name?: string;
|
|
||||||
/** 菜单地址 */
|
|
||||||
path: string;
|
|
||||||
/** 路由组件 */
|
|
||||||
component?: string;
|
|
||||||
/** 路由重定向 */
|
|
||||||
redirect?: string;
|
|
||||||
/** 路由元数据 */
|
|
||||||
meta?: any;
|
|
||||||
/** 子路由 */
|
|
||||||
children?: Array<MenuItem>;
|
|
||||||
/** 临时子路由数据, 内部属性 */
|
|
||||||
tempChildren?: Array<MenuItem>;
|
|
||||||
/** 用户位置信息 */
|
|
||||||
location?: { latitude: number; longitude: number };
|
|
||||||
/** 是否弹出 门店选择 */
|
|
||||||
showPosition?: boolean;
|
|
||||||
|
|
||||||
}
|
|
||||||
/** 直接指定菜单数据 */
|
|
||||||
const USER_MENUS: Menu[] | null = null;
|
|
||||||
|
|
||||||
export interface UserState {
|
|
||||||
info: User | null;
|
|
||||||
menus: any[] | null;
|
|
||||||
authorities: (string | undefined)[];
|
|
||||||
roles: (string | undefined)[];
|
|
||||||
loginPromise: null ,// 初始化Promise为null
|
|
||||||
}
|
|
||||||
export const useUserStore = defineStore('user', {
|
|
||||||
state: (): {
|
|
||||||
settings: null;
|
|
||||||
loginPromise: null;
|
|
||||||
roles: any[];
|
|
||||||
location: {longitude:0,latitude:0};
|
|
||||||
menus: null;
|
|
||||||
authorities: any[];
|
|
||||||
info: null,
|
|
||||||
showPosition: boolean,
|
|
||||||
} => ({
|
|
||||||
/** 当前登录用户的信息 */
|
|
||||||
info: null,
|
|
||||||
/** 当前登录用户的菜单 */
|
|
||||||
menus: null,
|
|
||||||
/** 当前登录用户的权限 */
|
|
||||||
authorities: [],
|
|
||||||
/** 当前登录用户的角色 */
|
|
||||||
roles: [],
|
|
||||||
/** 登录用户信息请求Promise */
|
|
||||||
loginPromise: null ,//
|
|
||||||
/** 用户位置信息 */
|
|
||||||
location: null,
|
|
||||||
/** 当前登录用户的门店配置 */
|
|
||||||
settings: null,
|
|
||||||
/** 是否弹出 门店选择 */
|
|
||||||
showPosition:false
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
/**
|
|
||||||
* 请求登录用户的个人信息/权限/角色/菜单
|
|
||||||
*/
|
|
||||||
async fetchUserInfo() {
|
|
||||||
const result = await getInfoByMember().catch((e) => console.error(e));
|
|
||||||
//门店配置
|
|
||||||
const storeSettings = await getStoreSettings().catch((e) => console.error(e));
|
|
||||||
//更新门店配置
|
|
||||||
this.setSettings(storeSettings);
|
|
||||||
const store = uni.getStorageSync('store')
|
|
||||||
if (!store) {
|
|
||||||
//门店配置为0时, 表示不选择门店, 则获取用户位置。
|
|
||||||
if (storeSettings.choiceShopWay === 0){
|
|
||||||
await getLocationOnce().then((res:any) => {
|
|
||||||
console.log(res,'获取到用户位置信息')
|
|
||||||
this.setLocation({ latitude: res.latitude, longitude: res.longitude })
|
|
||||||
getShopList({longitude:res.longitude,latitude:res.latitude}).then((res:any) => {
|
|
||||||
if (res.shops.length > 0) {
|
|
||||||
//循环筛选出最近,并不是休息的门店
|
|
||||||
const validStores = res.shops.filter((shop: any) => shop.isBusinessTime);
|
|
||||||
if (validStores.length > 0) {
|
|
||||||
uni.setStorageSync('store', validStores[0] || null)
|
|
||||||
}
|
|
||||||
bus.emit(EVENT_KEY.REFRESH_SHOPPING_CART);
|
|
||||||
}else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '未查询到门店,请稍后再试',
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}).catch((e)=>{
|
|
||||||
console.log(e,'获取用户位置失败')
|
|
||||||
this.showPosition = true
|
|
||||||
})
|
|
||||||
}else if (storeSettings.choiceShopWay === 1){
|
|
||||||
this.showPosition = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!result) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
// 用户信息
|
|
||||||
this.setInfo(result.user);
|
|
||||||
// 用户权限
|
|
||||||
if (result.menus) {
|
|
||||||
this.authorities = result.menus.map((d) => d.authority).filter((a) => !!a) ?? [];
|
|
||||||
}
|
|
||||||
// 用户角色
|
|
||||||
this.roles = result.roles?.map?.((d) => d.roleCode) ?? [];
|
|
||||||
// 用户菜单, 过滤掉按钮类型并转为children形式
|
|
||||||
const { menus, homePath } = formatMenus(
|
|
||||||
USER_MENUS ??
|
|
||||||
toTree({
|
|
||||||
data: result.menus?.filter?.((d) => d.menuType !== 1),
|
|
||||||
idField: 'menuId',
|
|
||||||
parentIdField: 'parentId'
|
|
||||||
})
|
|
||||||
);
|
|
||||||
this.setMenus(menus);
|
|
||||||
return { menus, homePath };
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 更新用户信息
|
|
||||||
*/
|
|
||||||
setInfo(value: User) {
|
|
||||||
this.info = value;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 更新菜单数据
|
|
||||||
*/
|
|
||||||
setMenus(menus: any[] | null) {
|
|
||||||
this.menus = menus;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 更新用户位置信息
|
|
||||||
*/
|
|
||||||
setLocation(value: any) {
|
|
||||||
this.location = value;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 更新门店配置
|
|
||||||
*/
|
|
||||||
setSettings(settings: any) {
|
|
||||||
this.settings = settings;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
/**
|
|
||||||
* 菜单数据处理为EleProLayout所需要的格式
|
|
||||||
* @param data 菜单数据
|
|
||||||
* @param childField 子级的字段名称
|
|
||||||
*/
|
|
||||||
function formatMenus(data: Menu[], childField = 'children') {
|
|
||||||
let homePath: string | undefined;
|
|
||||||
let homeTitle: string | undefined;
|
|
||||||
const menus = mapTree(
|
|
||||||
data,
|
|
||||||
(item) => {
|
|
||||||
const meta: MenuItem['meta'] = typeof item.meta === 'string' ? JSON.parse(item.meta || '{}') : item.meta;
|
|
||||||
const menu: MenuItem = {
|
|
||||||
path: item.path,
|
|
||||||
component: item.component,
|
|
||||||
meta: { title: item.title, icon: item.icon, hide: !!item.hide, ...meta }
|
|
||||||
};
|
|
||||||
const children = item[childField] ? item[childField].filter((d: any) => !(d.meta?.hide ?? d.hide)) : void 0;
|
|
||||||
if (!children?.length) {
|
|
||||||
if (!homePath && menu.path && !isExternalLink(menu.path)) {
|
|
||||||
homePath = menu.path;
|
|
||||||
homeTitle = menu.meta?.title;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const childPath = children[0].path;
|
|
||||||
if (childPath) {
|
|
||||||
if (!menu.redirect) {
|
|
||||||
menu.redirect = childPath;
|
|
||||||
}
|
|
||||||
if (!menu.path) {
|
|
||||||
menu.path = childPath.substring(0, childPath.lastIndexOf('/'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!menu.path) {
|
|
||||||
console.error('菜单path不能为空且要唯一:', item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return menu;
|
|
||||||
},
|
|
||||||
childField
|
|
||||||
);
|
|
||||||
return { menus, homePath, homeTitle };
|
|
||||||
}
|
|
||||||
// 获取一次位置
|
|
||||||
function getLocationOnce() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
uni.getLocation({
|
|
||||||
type: 'wgs84',
|
|
||||||
altitude: true,
|
|
||||||
success: function (res) {
|
|
||||||
resolve(res)
|
|
||||||
},
|
|
||||||
fail: function (err) {
|
|
||||||
reject(err)
|
|
||||||
},
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
export const paymentMethodOptions = [
|
||||||
|
{ label: '微信支付', value: 0, type: 'primary' },
|
||||||
|
{ label: '借呗支付', value: 1, type: 'success' },
|
||||||
|
{ label: '要呗支付', value: 2, type: 'info' },
|
||||||
|
{ label: '余额支付', value: 3, type: 'warning' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const modeToPaymentMethodMap: Record<number, number[]> = {
|
||||||
|
0: [0],
|
||||||
|
1: [0, 1],
|
||||||
|
2: [0, 1],
|
||||||
|
3: [0],
|
||||||
|
4: [2],
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
/** 判断是否为数组 */
|
||||||
|
export function isArray<T>(arg: T) {
|
||||||
|
return Array.isArray ? Array.isArray(arg) : Object.prototype.toString.call(arg) === "[object Array]"
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判断是否为字符串 */
|
||||||
|
export function isString(str: unknown) {
|
||||||
|
return typeof str === "string" || str instanceof String
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 判断是否为外链 */
|
||||||
|
export function isExternal(path: string) {
|
||||||
|
const reg = /^(https?:|mailto:|tel:)/
|
||||||
|
return reg.test(path)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue