@ -1,5 +1,5 @@ |
|||||
ENV='development' |
ENV='development' |
||||
# base api |
# base api |
||||
VITE_APP_BASE_URL = 'http://pos-api.lingji.vip' |
VITE_APP_BASE_URL = 'https://evote.truescloud.com' |
||||
VITE_APP_BASE_PRE = '/shenname' |
VITE_APP_BASE_PRE = '/dev-api' |
||||
VITE_APP_BASE_NAME = 'POS' |
VITE_APP_BASE_NAME = 'POS' |
||||
|
|||||
@ -1,98 +0,0 @@ |
|||||
import { request } from '@/utils/http' |
|
||||
|
|
||||
export interface sendCodeType { |
|
||||
phone: number | string |
|
||||
} |
|
||||
|
|
||||
export function sendCode(data: sendCodeType) { |
|
||||
return request.http({ |
|
||||
url: '/api/t.sms/sendCode', |
|
||||
data |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 上传图片
|
|
||||
export function uploadFile(file: any) { |
|
||||
let url = '' |
|
||||
// #ifdef APP-PLUS
|
|
||||
url = import.meta.env.VITE_APP_BASE_URL |
|
||||
// #endif
|
|
||||
// #ifdef H5
|
|
||||
url = import.meta.env.VITE_APP_BASE_PRE |
|
||||
// #endif
|
|
||||
return new Promise((resolve, reject) => { |
|
||||
uni.uploadFile({ |
|
||||
url: `${url}/api/resources/upload`, |
|
||||
filePath: file, |
|
||||
name: 'file', |
|
||||
success: (res) => { |
|
||||
resolve(JSON.parse(res.data)) |
|
||||
}, |
|
||||
fail: (res) => { |
|
||||
reject(res) |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 根据 KEY 获取对应数据
|
|
||||
export function getKeyData(key: string) { |
|
||||
return request.http({ |
|
||||
url: '/api/t.systemData/getCategoryByKey', |
|
||||
data: { key: key } |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 根据 KEY 获取对应系统设置
|
|
||||
export function getKeySetting(key: string) { |
|
||||
return request.http({ |
|
||||
url: '/api/t.systemData/getSettingByKey', |
|
||||
data: { key: key } |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 获取无限极分类数据
|
|
||||
export function getCategoryData() { |
|
||||
return request.http({ |
|
||||
url: '/api/t.systemData/categoryTree' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 意见反馈
|
|
||||
export interface feedbackType { |
|
||||
type: useType |
|
||||
category_id: number |
|
||||
content: string |
|
||||
image?: string |
|
||||
contact_information: string |
|
||||
} |
|
||||
|
|
||||
export function feedback(data: feedbackType) { |
|
||||
return request.http({ |
|
||||
url: '/api/t.feedback/add', |
|
||||
data |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 购买支付接口
|
|
||||
export function pay(data: { policy_id: number; uid: number; pay_amount: number; version: string }) { |
|
||||
return request.http({ |
|
||||
url: '/api/t.notify/buyAgentPolicyNotify', |
|
||||
data |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 直采列表
|
|
||||
export function voucherQuery() { |
|
||||
return request.http({ |
|
||||
url: '/api/d.pickGiftBag/query' |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// 直采支付
|
|
||||
export function voucherPay(data: { id: number }) { |
|
||||
return request.http({ |
|
||||
url: '/api/d.pickGiftBag/buy', |
|
||||
data |
|
||||
}) |
|
||||
} |
|
||||
@ -0,0 +1,23 @@ |
|||||
|
import { request } from '@/utils/http' |
||||
|
|
||||
|
export function getOpenid(data: { code: string }) { |
||||
|
return request.http({ |
||||
|
url: '/api/openid', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
export function getMobile(data: { code: string; openid: string }) { |
||||
|
return request.http({ |
||||
|
url: '/api/mobile', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
export function getUserInfo(data: { mobile: string }) { |
||||
|
return request.http({ |
||||
|
url: '/api/member_mobile', |
||||
|
method: 'GET', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
import { request } from '@/utils/http' |
||||
|
|
||||
|
export function getUserList(data: { name: string }) { |
||||
|
return request.http({ |
||||
|
url: '/api/openid', |
||||
|
method: 'GET', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
@ -1,128 +0,0 @@ |
|||||
/* |
|
||||
* @description: 分页请求 |
|
||||
* @fileName: useListLoadClass.ts |
|
||||
* @author: lxx |
|
||||
* @date: 2023-07-08 08:55:52 |
|
||||
* @version: V1.0.0 |
|
||||
*/ |
|
||||
import { ref } from 'vue' |
|
||||
|
|
||||
class PaginationLoader<T> { |
|
||||
// 分页数据
|
|
||||
private data = ref<T[]>([]) |
|
||||
|
|
||||
// 分页基础参数
|
|
||||
private requestParams = { |
|
||||
page: 1, |
|
||||
limit: 10 |
|
||||
} |
|
||||
|
|
||||
// 是否正在加载
|
|
||||
private isLoading = ref(false) |
|
||||
|
|
||||
// 是否还有更多数据
|
|
||||
private hasMore = ref(true) |
|
||||
|
|
||||
// 请求函数(由外部传入)
|
|
||||
private fetchFn: (formData: Object, onSuccess: Function) => Function |
|
||||
|
|
||||
constructor(fetchFn: (formData: Object, onSuccess: Function) => Function) { |
|
||||
this.fetchFn = fetchFn |
|
||||
} |
|
||||
|
|
||||
// 获取当前数据
|
|
||||
get dataList() { |
|
||||
return this.data.value |
|
||||
} |
|
||||
|
|
||||
// 获取是否正在加载
|
|
||||
get loading() { |
|
||||
return this.isLoading.value |
|
||||
} |
|
||||
|
|
||||
// 获取是否还有更多数据
|
|
||||
get more() { |
|
||||
return this.hasMore.value |
|
||||
} |
|
||||
|
|
||||
// 加载下一页数据
|
|
||||
async loadNextPage() { |
|
||||
// if (this.isLoading.value || !this.hasMore.value) return
|
|
||||
|
|
||||
// uni.showLoading({ title: '加载中...' })
|
|
||||
|
|
||||
// this.isLoading.value = true
|
|
||||
|
|
||||
// try {
|
|
||||
// const result = await this.fetchFn(this.currentPage.value, this.pageSize)
|
|
||||
|
|
||||
// if (result.length > 0) {
|
|
||||
// this.data.value = [...this.data.value, ...result]
|
|
||||
// this.currentPage.value += 1
|
|
||||
// } else {
|
|
||||
// this.hasMore.value = false // 没有更多数据
|
|
||||
// }
|
|
||||
// } catch (error) {
|
|
||||
// console.error('加载数据失败:', error)
|
|
||||
// } finally {
|
|
||||
// this.isLoading.value = false
|
|
||||
// }
|
|
||||
uni.showLoading({ title: '数据加载中' }) |
|
||||
this.isLoading.value = false |
|
||||
const params = { ...this.requestParams } as { [n: string]: string | number | boolean } |
|
||||
|
|
||||
setTimeout(() => { |
|
||||
this.fetchFn(params, ({ data }: { data: { data: any; total: number } }) => { |
|
||||
this.isLoading.value = true |
|
||||
this.requestParams.page = params.page as number |
|
||||
this.requestParams.limit = params.limit as number |
|
||||
this.data.value = [...this.data.value, ...data.data] |
|
||||
uni.hideLoading() |
|
||||
}) |
|
||||
}, 100) |
|
||||
} |
|
||||
|
|
||||
// 重置分页状态
|
|
||||
reset() { |
|
||||
this.data.value = [] |
|
||||
this.requestParams.page = 1 |
|
||||
this.hasMore.value = true |
|
||||
this.isLoading.value = false |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// export default PaginationLoader
|
|
||||
|
|
||||
const fetchData = async (formData: any, onSuccess: Function) => { |
|
||||
const submitData = { ...formData } |
|
||||
point_order_list(submitData).then((res) => { |
|
||||
const { data } = res as { data: { data: any; total: number } } |
|
||||
onSuccess({ data }) |
|
||||
}) |
|
||||
// // 模拟接口请求
|
|
||||
// return new Promise<{ id: number; name: string }[]>((resolve) => {
|
|
||||
// setTimeout(() => {
|
|
||||
// const data = Array.from({ length: pageSize }, (_, index) => ({
|
|
||||
// id: (page - 1) * pageSize + index,
|
|
||||
// name: `Item ${(page - 1) * pageSize + index}`
|
|
||||
// }))
|
|
||||
// resolve(data)
|
|
||||
// }, 1000)
|
|
||||
// })
|
|
||||
} |
|
||||
|
|
||||
// 创建分页加载实例
|
|
||||
const paginationLoader = new PaginationLoader(fetchData) |
|
||||
|
|
||||
// 加载下一页数据
|
|
||||
paginationLoader.loadNextPage(formDate.value) |
|
||||
|
|
||||
// 初始化加载第一页数据
|
|
||||
paginationLoader.loadNextPage() |
|
||||
|
|
||||
return { |
|
||||
dataList: paginationLoader.dataList, |
|
||||
loading: paginationLoader.loading, |
|
||||
more: paginationLoader.more, |
|
||||
loadNextPage |
|
||||
} |
|
||||
@ -1,125 +0,0 @@ |
|||||
/* |
|
||||
* @description: 分页请求 |
|
||||
* @fileName: useListLoadClass.ts |
|
||||
* @author: lxx |
|
||||
* @date: 2023-07-08 08:55:52 |
|
||||
* @version: V1.0.0 |
|
||||
*/ |
|
||||
import { ref, computed } from 'vue' |
|
||||
import { onReachBottom } from '@dcloudio/uni-app' |
|
||||
|
|
||||
class LoadDataClass { |
|
||||
// 请求参数
|
|
||||
static queryParams = { |
|
||||
page: 1, |
|
||||
limit: 10 |
|
||||
} |
|
||||
// 列表数据
|
|
||||
list = ref<any[]>([]) |
|
||||
total = ref(0) |
|
||||
// 前置处理方法
|
|
||||
afterLoadData: Function | undefined |
|
||||
// 请求方法
|
|
||||
Query: Function |
|
||||
// 加载状态参数
|
|
||||
isLoading = ref(false) |
|
||||
// 无更多数据了
|
|
||||
isNoData = computed(() => { |
|
||||
if (LoadDataClass.queryParams.page * LoadDataClass.queryParams.limit >= this.total.value) { |
|
||||
return true |
|
||||
} else { |
|
||||
return false |
|
||||
} |
|
||||
}) |
|
||||
// 显示暂无数据
|
|
||||
isEmpty = computed(() => { |
|
||||
if (this.total.value === 0) { |
|
||||
return true |
|
||||
} else { |
|
||||
return false |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
constructor(apiFunctions: Function, afterLoadData?: Function, options?: any) { |
|
||||
this.Query = apiFunctions |
|
||||
this.afterLoadData = afterLoadData |
|
||||
// 存在额外参数拼接
|
|
||||
if (options) { |
|
||||
LoadDataClass.queryParams = { ...LoadDataClass.queryParams, ...options } |
|
||||
} |
|
||||
// 加载数据
|
|
||||
this.LoadData() |
|
||||
} |
|
||||
// 加载数据
|
|
||||
LoadData = async () => { |
|
||||
uni.showLoading({ |
|
||||
title: '加载中...' |
|
||||
}) |
|
||||
this.isLoading.value = true |
|
||||
const res = await this.Query(LoadDataClass.queryParams) |
|
||||
this.afterLoadData && this.afterLoadData(res) |
|
||||
this.total.value = res.data.total |
|
||||
this.list.value = this.list.value.concat(res.data.data) |
|
||||
|
|
||||
uni.hideLoading() |
|
||||
uni.stopPullDownRefresh() |
|
||||
this.isLoading.value = false |
|
||||
} |
|
||||
// 加载更多
|
|
||||
LoadMore = () => { |
|
||||
if (this.isNoData.value || this.isLoading.value) return // 无数据或者加载中不进行加载
|
|
||||
LoadDataClass.queryParams.page += 1 |
|
||||
this.LoadData() |
|
||||
} |
|
||||
// 重置参数
|
|
||||
queryParamsReset = () => { |
|
||||
LoadDataClass.queryParams = { |
|
||||
page: 1, |
|
||||
limit: 10 |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 刷新 |
|
||||
* @param isClear: 是否清空数据 |
|
||||
*/ |
|
||||
ReLoad = (isClear: boolean = true) => { |
|
||||
this.isLoading.value = false |
|
||||
this.list.value = [] |
|
||||
if (isClear) { |
|
||||
this.queryParamsReset() |
|
||||
} else { |
|
||||
LoadDataClass.queryParams.page = 1 |
|
||||
} |
|
||||
|
|
||||
this.LoadData() |
|
||||
} |
|
||||
} |
|
||||
/** |
|
||||
* 分页加载数据方法 |
|
||||
* @param api: ListAPI 方法 |
|
||||
* @param afterLoadData: res数据前置处理方法 |
|
||||
* @returns |
|
||||
*/ |
|
||||
interface LoadDataInt { |
|
||||
api: Function |
|
||||
afterLoadData?: Function |
|
||||
options?: any |
|
||||
} |
|
||||
|
|
||||
export function LoadData({ api, afterLoadData, options }: LoadDataInt) { |
|
||||
const data = new LoadDataClass(api, afterLoadData, options) |
|
||||
|
|
||||
// 下拉加载
|
|
||||
onReachBottom(() => { |
|
||||
console.log('onReachBottom') |
|
||||
data.LoadMore() |
|
||||
}) |
|
||||
return { |
|
||||
list: data.list, |
|
||||
isLoading: data.isLoading, |
|
||||
isNoData: data.isNoData, |
|
||||
isEmpty: data.isEmpty, |
|
||||
ReLoad: data.ReLoad |
|
||||
} |
|
||||
} |
|
||||
@ -1,127 +0,0 @@ |
|||||
import { ref, reactive, computed } from 'vue' |
|
||||
import { onReachBottom } from '@dcloudio/uni-app' |
|
||||
/* |
|
||||
* @description: 分页请求 |
|
||||
* @fileName: useListLoadClass.ts |
|
||||
* @author: lxx |
|
||||
* @date: 2023-07-08 08:55:52 |
|
||||
* @version: V1.0.0 |
|
||||
* loading状态 |
|
||||
* @param {*} Query 请求函数 |
|
||||
* @param {*} LoadData 加载数据方法 |
|
||||
* @param {*} ReLoad (isClear?: boolean) 刷新列表数据 isClear 传入true时将请求参数(queryParams)还原初始化状态 |
|
||||
*/ |
|
||||
|
|
||||
export function usePagingLoad(Query: any) { |
|
||||
// 下拉加载
|
|
||||
onReachBottom(() => { |
|
||||
console.log('onReachBottom') |
|
||||
loadMore() |
|
||||
}) |
|
||||
|
|
||||
const isLoading = ref(false) |
|
||||
let queryParams = reactive({} as any) |
|
||||
|
|
||||
queryParams = { |
|
||||
page: 1, |
|
||||
limit: 10 |
|
||||
} |
|
||||
|
|
||||
const total = ref(0) |
|
||||
|
|
||||
const list = ref([]) |
|
||||
// 无更多数据了
|
|
||||
const isNoData = computed(() => { |
|
||||
if (queryParams.page * queryParams.limit >= total.value) { |
|
||||
return true |
|
||||
} else { |
|
||||
return false |
|
||||
} |
|
||||
}) |
|
||||
// 显示暂无数据
|
|
||||
const isEmpty = computed(() => { |
|
||||
if (total.value === 0) { |
|
||||
return true |
|
||||
} else { |
|
||||
return false |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
interface optionInt { |
|
||||
key: string |
|
||||
val: any |
|
||||
} |
|
||||
|
|
||||
const LoadData = async (afterLoadData?: any, option?: optionInt[]) => { |
|
||||
const obj: any = {} |
|
||||
console.log('option', option) |
|
||||
if (option && option?.length > 0) { |
|
||||
option?.map((item) => { |
|
||||
obj[item?.key] = item.val |
|
||||
}) |
|
||||
} |
|
||||
// , ...rest: any[]
|
|
||||
// if (rest.length > 0) {
|
|
||||
// rest.map((item) => {
|
|
||||
// obj[item?.key] = item?.val;
|
|
||||
// });
|
|
||||
// }
|
|
||||
queryParams = reactive({ ...queryParams, ...obj }) |
|
||||
|
|
||||
uni.showLoading({ |
|
||||
title: '加载中...' |
|
||||
}) |
|
||||
isLoading.value = true |
|
||||
const res = await Query(queryParams) |
|
||||
total.value = res?.data?.total |
|
||||
|
|
||||
// 数据加载完成后 设置 after 钩子
|
|
||||
afterLoadData && afterLoadData(res.data) |
|
||||
console.log('res.data', res.data) |
|
||||
|
|
||||
list.value = list.value.concat(res?.data?.data) |
|
||||
uni.hideLoading() |
|
||||
uni.stopPullDownRefresh() |
|
||||
isLoading.value = false |
|
||||
} |
|
||||
|
|
||||
// const afterLoadData = (data: any) => {
|
|
||||
// console.log(data);
|
|
||||
// };
|
|
||||
|
|
||||
const ReLoad = (option?: optionInt[], isClear?: boolean) => { |
|
||||
isLoading.value = false |
|
||||
list.value = [] |
|
||||
if (isClear) { |
|
||||
queryParams = reactive({ |
|
||||
page: 1, |
|
||||
limit: 10 |
|
||||
}) |
|
||||
} else { |
|
||||
queryParams.page = 1 |
|
||||
} |
|
||||
const obj: any = {} |
|
||||
if (option && option?.length > 0) { |
|
||||
option?.map((item) => { |
|
||||
obj[item?.key] = item.val |
|
||||
}) |
|
||||
} |
|
||||
queryParams = reactive({ ...queryParams, ...obj }) |
|
||||
LoadData() |
|
||||
} |
|
||||
|
|
||||
const loadMore = () => { |
|
||||
if (isNoData.value || isLoading.value) return // 无数据或者加载中不进行加载
|
|
||||
queryParams.page += 1 |
|
||||
LoadData() |
|
||||
} |
|
||||
|
|
||||
return { |
|
||||
list, |
|
||||
LoadData, |
|
||||
ReLoad, |
|
||||
isNoData, |
|
||||
isEmpty, |
|
||||
isLoading |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,105 @@ |
|||||
|
<script setup lang="ts"> |
||||
|
import { debounce } from 'feng-uniapp-exploit/utils/index' |
||||
|
import { getMobile } from '@/api/login' |
||||
|
|
||||
|
import useUserStore from '@/store/user' |
||||
|
const userStore = useUserStore() |
||||
|
|
||||
|
const loginCode = ref('') |
||||
|
|
||||
|
// 获取微信登录 code |
||||
|
const getLoginCode = async (): Promise<string> => { |
||||
|
try { |
||||
|
const res = await uni.login({ provider: 'weixin' }) |
||||
|
loginCode.value = res.code |
||||
|
return res.code |
||||
|
} catch (error) { |
||||
|
console.error('获取登录code失败:', error) |
||||
|
throw error |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 处理获取手机号 |
||||
|
|
||||
|
interface phoneEvent { |
||||
|
detail: { errMsg: string; iv: string; encryptedData: string; code: string } |
||||
|
} |
||||
|
const onGetPhoneNumber = debounce(async (e: phoneEvent) => { |
||||
|
if (e.detail.errMsg.includes('fail')) { |
||||
|
uni.showToast({ title: '用户拒绝授权', icon: 'none' }) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
try { |
||||
|
if (!loginCode.value) { |
||||
|
await getLoginCode() |
||||
|
} |
||||
|
|
||||
|
if (!userStore.openId) { |
||||
|
await userStore.getopenid({ code: loginCode.value }) |
||||
|
} |
||||
|
|
||||
|
const { data: phone } = (await getMobile({ openid: userStore.openId, code: e.detail.code })) as { data: string } |
||||
|
userStore.userInfo.mobile = phone |
||||
|
|
||||
|
userStore.getUserInfo({ mobile: phone }) |
||||
|
|
||||
|
onLoginSuccess() |
||||
|
} catch (error) { |
||||
|
uni.showToast({ title: '登录失败', icon: 'none' }) |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
const onLoginSuccess = () => { |
||||
|
uni.showToast({ |
||||
|
title: '登录成功', |
||||
|
icon: 'none', |
||||
|
success: () => { |
||||
|
setTimeout(() => { |
||||
|
uni.reLaunch({ url: '/pages/votingElection/index' }) |
||||
|
}, 1000) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onShow(() => { |
||||
|
if (userStore.userInfo.mobile) { |
||||
|
onLoginSuccess() |
||||
|
} |
||||
|
}) |
||||
|
</script> |
||||
|
<template> |
||||
|
<view class="login"> |
||||
|
<image class="logo-img" src="@/static/logo.png" mode="widthFix" /> |
||||
|
|
||||
|
<view class="btn_box"> |
||||
|
<u-button |
||||
|
@getphonenumber="onGetPhoneNumber" |
||||
|
text="微信一键登录" |
||||
|
icon="weixin-fill" |
||||
|
icon-color="#fff" |
||||
|
open-type="getPhoneNumber" |
||||
|
color="linear-gradient(270deg, rgba(232, 123, 7, 1) 0%, rgba(247, 205, 77, 1) 100%)" |
||||
|
shape="circle" |
||||
|
/> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.login { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
text-align: center; |
||||
|
box-sizing: border-box; |
||||
|
padding: 500rpx 30rpx 0; |
||||
|
background-color: #fff; |
||||
|
|
||||
|
.logo-img { |
||||
|
width: 220rpx; |
||||
|
margin-bottom: 60rpx; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 893 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 521 B |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 541 B |