登录页面
Some checks are pending
Auto Merge Main to Other Branches / Merge main into i18n (push) Waiting to run
Auto Merge Main to Other Branches / Merge main into base-sard-ui (push) Waiting to run

This commit is contained in:
sjeam 2025-08-29 17:48:28 +08:00
parent 27ee3f56dd
commit 4b1baf31b3
21 changed files with 559 additions and 115 deletions

20
components.d.ts vendored Normal file
View File

@ -0,0 +1,20 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by vite-plugin-uni-components
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
AppTest: typeof import('./src/components/AppTest.vue')['default']
AppTest2: typeof import('./src/components/app-test-dir/AppTest2.vue')['default']
FlyContent: typeof import('./src/components/fly-content/fly-content.vue')['default']
FlyHeader: typeof import('./src/components/fly-header/fly-header.vue')['default']
FlyLogin: typeof import('./src/components/fly-login/fly-login.vue')['default']
FlyNavbar: typeof import('./src/components/fly-navbar/fly-navbar.vue')['default']
SvgIcon: typeof import('./src/components/SvgIcon.vue')['default']
}
}

20
env/.env vendored
View File

@ -2,7 +2,7 @@ VITE_APP_TITLE = 'unibest'
VITE_APP_PORT = 9000
VITE_UNI_APPID = '__UNI__D1E5001'
VITE_WX_APPID = 'wxa2abb91f64032a2b'
VITE_WX_APPID = 'wxe2428e8fe6767e45'
# h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE=/
@ -10,19 +10,19 @@ VITE_APP_PUBLIC_BASE=/
# 登录页面
VITE_LOGIN_URL = '/pages/login/index'
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
VITE_UPLOAD_BASEURL = 'https://ukw0y1.laf.run/upload'
VITE_SERVER_BASEURL = 'https://test.shop.lihaink.cn/'
VITE_UPLOAD_BASEURL = 'https://test.shop.lihaink.cn//upload'
# 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
# 下面的变量如果没有设置,会默认使用 VITE_SERVER_BASEURL or VITE_UPLOAD_BASEURL
VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run'
VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run'
VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run'
VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'https://test.shop.lihaink.cn/'
VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'https://test.shop.lihaink.cn/'
VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'https://test.shop.lihaink.cn/'
VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP = 'https://ukw0y1.laf.run/upload'
VITE_UPLOAD_BASEURL__WEIXIN_TRIAL = 'https://ukw0y1.laf.run/upload'
VITE_UPLOAD_BASEURL__WEIXIN_RELEASE = 'https://ukw0y1.laf.run/upload'
VITE_UPLOAD_BASEURL__WEIXIN_DEVELOP = 'https://test.shop.lihaink.cn//upload'
VITE_UPLOAD_BASEURL__WEIXIN_TRIAL = 'https://test.shop.lihaink.cn//upload'
VITE_UPLOAD_BASEURL__WEIXIN_RELEASE = 'https://test.shop.lihaink.cn//upload'
# h5是否需要配置代理
VITE_APP_PROXY=false
VITE_APP_PROXY=true
VITE_APP_PROXY_PREFIX = '/api'

View File

@ -0,0 +1,11 @@
<template>
<view class="fly-content">
<view v-for="n in line" :key="n" class="h-10 leading-10 text-center">
很多内容这里是第{{ n }}
</view>
</view>
</template>
<script lang="ts" setup>
withDefaults(defineProps<{ line?: number }>(), { line: 10 })
</script>

View File

@ -0,0 +1,3 @@
<template>
<view class="text-green-500">header</view>
</template>

View File

@ -0,0 +1,7 @@
# fly-login
点击“点击显示微信头像”按钮后,出现的半屏登录弹窗,可以在任意页面引入。
仿“掘金小册”小程序。
![掘金小册登录](screenshot.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,128 @@
<template>
<view class="fly-login" v-if="modelValue">
<view class="fly-login-mask" @click="onClose" />
<view class="fly-login-content px-4">
<view class="font-bold h-16 leading-16">获取您的昵称头像</view>
<view
class="rounded-full bg-light-600 w-6 h-6 text-center absolute top-4 right-4"
@click="onClose"
>
<view class="i-carbon-close text-gray-700" />
</view>
<view
class="flex items-center h-16 leading-16 border-b-gray-400 border-b-solid border-[0rpx]"
>
<text class="mr-4 flex-shrink-0">头像</text>
<button
class="bg-transparent flex items-center after:b-none w-full h-12 leading-12"
open-type="chooseAvatar"
@chooseavatar="onChooseAvatar"
>
<image class="w-8 h-8 rounded-full" :src="avatarUrl"></image>
<!-- <text class="ml-auto i-carbon-chevron-right"></text> -->
</button>
</view>
<view
class="flex items-center h-16 leading-16 border-b-gray-400 border-b-solid border-[0rpx] mt-2"
>
<text class="mr-4 flex-shrink-0">昵称</text>
<input
type="nickname"
placeholder="请输入昵称"
v-model="nickname"
@change="onChange"
@blur="onChange"
/>
</view>
<button
size="default"
type="default"
style="color: #fff; background-color: #1aad19; border-color: #1aad19"
class="text-center leading-12 w-40 my-4"
@click="onSubmit"
>
授权登录
</button>
</view>
</view>
</template>
<script lang="ts" setup>
import { useUserStore } from '@/store'
import defaultAvatarUrl from './defaultAvatar.png'
const emit = defineEmits(['update:modelValue'])
defineProps<{ modelValue: boolean }>()
const userStore = useUserStore()
const avatarUrl = ref(defaultAvatarUrl)
const nickname = ref('123')
const onClose = () => {
emit('update:modelValue', false)
}
const onChooseAvatar = (e) => {
const { avatarUrl: url } = e.detail
avatarUrl.value = url
//
console.log(url)
}
const onChange = (e) => {
const { value } = e.detail
nickname.value = value
console.log(value)
}
const onSubmit = () => {
// 1
// 2
// if (avatarUrl.value === defaultAvatarUrl) {
// uni.showToast({
// title: '',
// icon: 'none',
// })
// return
// }
// if (!nickname.value) {
// uni.showToast({
// title: '',
// icon: 'none',
// })
// return
// }
emit('update:modelValue', false)
console.log('保存用户信息')
userStore.setUserInfo({ nickname: nickname.value, avatar: avatarUrl.value })
// userStore.wxLogin()
}
</script>
<style lang="scss" scoped>
.fly-login {
z-index: 1;
position: fixed;
inset: 0;
.fly-login-mask {
position: fixed;
inset: 0;
background-color: rgb(0 0 0 / 30%);
}
.fly-login-content {
position: fixed;
right: 0;
bottom: var(--window-bottom);
left: 0;
background-color: #fff;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

View File

@ -0,0 +1,3 @@
# fly-navbar
建议本导航栏组件在设置 `"navigationStyle": "custom"` 的页面使用,目前支持微信小程序的页面滚动动画。

View File

@ -0,0 +1,71 @@
<template>
<!-- 自定义导航栏: 默认透明不可见, scroll-view 滚动到 50 时展示 -->
<view class="fly-navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
<!-- 1/3多于1个页面用返回图标 -->
<navigator v-if="pages.length > 1" open-type="navigateBack" class="left-icon">
<view class="bg-gray-500/80 rounded-full w-8 h-8 flex items-center justify-center">
<button class="i-carbon-chevron-left text-white w-7 h-7"></button>
</view>
</navigator>
<!-- 2/3只有1个页面如果不是tabbar需要首页图标 -->
<!-- 这种情况一般出现在用户直接打开分享出去的详情页面或者使用redirectTo等API -->
<navigator
v-else-if="!isTabbar"
open-type="switchTab"
url="/pages/index/index"
class="left-icon"
>
<view class="bg-gray-500/80 rounded-full w-8 h-8 flex items-center justify-center">
<button class="i-carbon-home text-white w-6 h-6"></button>
</view>
</navigator>
<!-- 3/3如果当前页就是tabbar页不用去首页也就是什么图标都不需要 -->
<view class="title">{{ title || '' }}</view>
</view>
</template>
<script lang="ts" setup>
import { getIsTabbar } from '@/utils/index'
defineProps<{ title?: string }>()
//
const pages = getCurrentPages()
const isTabbar = getIsTabbar()
console.log({ isTabbar, pagesLen: pages.length })
//
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>
<style lang="scss" scoped>
.fly-navbar {
position: fixed;
top: 0;
left: 0;
z-index: 9;
width: 750rpx;
color: #000;
background-color: transparent;
.left-icon {
position: absolute;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
font-size: 44rpx;
color: #000;
}
.title {
display: flex;
align-items: center;
justify-content: center;
height: 44px;
font-size: 32rpx;
color: transparent;
}
}
</style>

View File

@ -29,17 +29,17 @@ export const tabbarList = [
{
iconPath: 'static/images/2-001.png',
selectedIconPath: 'static/images/2-002.png',
pagePath: 'pages/about/about',
text: '关于',
pagePath: 'pages/index/home',
text: '榜单',
// icon: 'i-carbon-code',
// // 注意 unocss 的图标需要在 页面上引入一下,或者配置到 unocss.config.ts 的 safelist 中
// iconType: 'unocss',
},
{
pagePath: 'pages/order_addcart/order_addcart',
pagePath: 'pages/about/about',
iconPath: 'static/images/3-001.png',
selectedIconPath: 'static/images/3-002.png',
text: '购物车',
text: '服务',
},
{
pagePath: 'pages/my/index',

View File

@ -83,7 +83,7 @@
},
"quickapp": {},
"mp-weixin": {
"appid": "wxa2abb91f64032a2b",
"appid": "wxe2428e8fe6767e45",
"setting": {
"urlCheck": false,
"es6": true,

View File

@ -33,14 +33,14 @@
{
"iconPath": "static/images/2-001.png",
"selectedIconPath": "static/images/2-002.png",
"pagePath": "pages/about/about",
"text": "关于"
"pagePath": "pages/index/home",
"text": "榜单"
},
{
"pagePath": "pages/order_addcart/order_addcart",
"pagePath": "pages/about/about",
"iconPath": "static/images/3-001.png",
"selectedIconPath": "static/images/3-002.png",
"text": "购物车"
"text": "服务"
},
{
"pagePath": "pages/my/index",
@ -65,7 +65,8 @@
"type": "page",
"layout": "tabbar",
"style": {
"navigationBarTitleText": "关于"
"navigationStyle": "custom",
"navigationBarTitleText": "服务"
}
},
{
@ -97,6 +98,7 @@
"path": "pages/my/index",
"type": "page",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "我的"
}
},

View File

@ -2,14 +2,15 @@
{
layout: 'tabbar',
style: {
navigationBarTitleText: '关于',
navigationStyle: 'custom',
navigationBarTitleText: '服务',
},
}
</route>
<script lang="ts" setup>
import RequestComp from './components/request.vue'
import UploadComp from './components/upload.vue'
// import RequestComp from './components/request.vue'
// import UploadComp from './components/upload.vue'
//
const { safeAreaInsets } = uni.getSystemInfoSync()
@ -23,15 +24,137 @@ console.log('about')
</script>
<template>
<view>
<view class="mt-8 text-center text-3xl">
鸽友们好我是
<text class="text-red-500">
菲鸽
</text>
<view class="">
<view class="p-2 background_home">
<wd-card>
<view class="p-2">
<wd-card custom-class="background-none">
<template #title>
<view class="title">
<view>
<text class="text-xl text-sm font-size-4">看看附近</text>
<text class="ps-2 text-xl text-sm font-size-3 color-gray-500">
好物上新季特产抢先购
</text>
</view>
<!-- <wd-button type="primary" size="small">
<wd-text text="更多" color="#ffffff" size="24rpx"></wd-text>
</wd-button> -->
</view>
</template>
</wd-card>
</view>
<wd-grid :gutter="2" :column="4">
<view
@click="more"
v-for="item in [
{ name: '特产产品', icon: '/static/icons/village_service.png', color: 'green' },
{ name: '特色美食', icon: '/static/icons/agriculture_service.png', color: 'blue' },
{ name: '当季产品', icon: '/static/icons/agriculture_course.png', color: 'orange' },
{ name: '美丽乡村', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
{ name: '景区景色', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
]"
>
<wd-grid-item use-slot>
<view class="p-2">
<wd-img radius="10rpx" :width="'100rpx'" :height="'100rpx'" :src="item.icon" />
<view class="ps-2 pt-2 pb-2 text-center text-gray-500 font-size-3">
{{ item.name }}
</view>
</view>
</wd-grid-item>
</view>
</wd-grid>
</wd-card>
</view>
<RequestComp />
<UploadComp />
<view class="p-2">
<wd-card>
<view class="p-2">
<wd-card custom-class="background-none">
<template #title>
<view class="title">
<view>
<text class="text-xl text-sm font-size-4">游玩必备</text>
<text class="ps-2 text-xl text-sm font-size-3 color-gray-500">
好物上新季特产抢先购
</text>
</view>
<!-- <wd-button type="primary" size="small">
<wd-text text="更多" color="#ffffff" size="24rpx"></wd-text>
</wd-button> -->
</view>
</template>
</wd-card>
</view>
<wd-grid :gutter="2" :column="4">
<view
@click="more"
v-for="item in [
{ name: '特产产品', icon: '/static/icons/village_service.png', color: 'green' },
{ name: '特色美食', icon: '/static/icons/agriculture_service.png', color: 'blue' },
{ name: '当季产品', icon: '/static/icons/agriculture_course.png', color: 'orange' },
{ name: '美丽乡村', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
{ name: '景区景色', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
]"
>
<wd-grid-item use-slot>
<view class="p-2">
<wd-img radius="10rpx" :width="'100rpx'" :height="'100rpx'" :src="item.icon" />
<view class="ps-2 pt-2 pb-2 text-center text-gray-500 font-size-3">
{{ item.name }}
</view>
</view>
</wd-grid-item>
</view>
</wd-grid>
</wd-card>
</view>
<view class="p-2">
<wd-card>
<view class="p-2">
<wd-card custom-class="background-none">
<template #title>
<view class="title">
<view>
<text class="text-xl text-sm font-size-4">公共交通</text>
<text class="ps-2 text-xl text-sm font-size-3 color-gray-500">
好物上新季特产抢先购
</text>
</view>
<!-- <wd-button type="primary" size="small">
<wd-text text="更多" color="#ffffff" size="24rpx"></wd-text>
</wd-button> -->
</view>
</template>
</wd-card>
</view>
<wd-grid :gutter="2" :column="4">
<view
@click="more"
v-for="item in [
{ name: '特产产品', icon: '/static/icons/village_service.png', color: 'green' },
{ name: '特色美食', icon: '/static/icons/agriculture_service.png', color: 'blue' },
{ name: '当季产品', icon: '/static/icons/agriculture_course.png', color: 'orange' },
{ name: '美丽乡村', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
{ name: '景区景色', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
]"
>
<wd-grid-item use-slot>
<view class="p-2">
<wd-img radius="10rpx" :width="'100rpx'" :height="'100rpx'" :src="item.icon" />
<view class="ps-2 pt-2 pb-2 text-center text-gray-500 font-size-3">
{{ item.name }}
</view>
</view>
</wd-grid-item>
</view>
</wd-grid>
</wd-card>
</view>
<view class="p-2"></view>
<!-- <RequestComp />
<UploadComp /> -->
</view>
</template>

View File

@ -41,12 +41,8 @@ function reset() {
<template>
<view class="p-6 text-center">
<view class="my-2">
使用的是 laf 云后台
</view>
<view class="text-green-400">
我的推荐码可以获得佣金
</view>
<view class="my-2">使用的是 laf 云后台</view>
<view class="text-green-400">我的推荐码可以获得佣金</view>
<!-- #ifdef H5 -->
<view class="my-2">
@ -61,24 +57,16 @@ function reset() {
<!-- #endif -->
<!-- http://localhost:9000/#/pages/index/request -->
<wd-button class="my-6" @click="run">
发送请求
</wd-button>
<wd-button class="my-6" @click="run">发送请求</wd-button>
<view class="h-16">
<view v-if="loading">
loading...
</view>
<view v-if="loading">loading...</view>
<block v-else>
<view class="text-xl">
请求数据如下
</view>
<view class="text-xl">请求数据如下</view>
<view class="text-green leading-8">
{{ JSON.stringify(data) }}
</view>
</block>
</view>
<wd-button type="error" class="my-6" :disabled="!data" @click="reset">
重置数据
</wd-button>
<wd-button type="error" class="my-6" :disabled="!data" @click="reset">重置数据</wd-button>
</view>
</template>

View File

@ -24,9 +24,9 @@
autoplay
:indicator="{ type: 'dots-bar' }"
v-model:current="current"
@click="handleClick"
@change="onChange"
></wd-swiper>
<!-- @click="handleClick" -->
<!-- 横幅广告 -->
</view>
@ -57,7 +57,7 @@
</wd-grid> -->
<view class="p-2">
<wd-card>
<wd-grid :gutter="2" :column="5">
<wd-grid :gutter="2" :column="4">
<view
@click="more"
v-for="item in [
@ -65,11 +65,10 @@
{ name: '特色美食', icon: '/static/icons/agriculture_service.png', color: 'blue' },
{ name: '当季产品', icon: '/static/icons/agriculture_course.png', color: 'orange' },
{ name: '美丽乡村', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
{ name: '景区景色', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
]"
>
<wd-grid-item use-slot>
<view class="detail-box" style="border: none; padding: 0; margin: 0">
<view class="p-2">
<wd-img radius="10rpx" :width="'100rpx'" :height="'100rpx'" :src="item.icon" />
<view class="ps-2 pt-2 pb-2 text-center text-gray-500 font-size-3">
{{ item.name }}
@ -103,47 +102,13 @@
class="p-1"
style="display: inline-block; width: 300rpx"
@click="goToShop('https://shop.lihaink.cn/')"
v-for="item in [
{
name: '农产品',
id: 1,
icon: 'https://img95.699pic.com/photo/50384/2866.jpg_wh860.jpg',
price: '320',
line_price: '320',
},
{
name: '农资供应',
id: 2,
icon: 'https://img95.699pic.com/photo/50384/2866.jpg_wh860.jpg',
price: '320',
line_price: '320',
},
{
name: '土地流转',
id: 3,
icon: 'https://img95.699pic.com/photo/50384/2866.jpg_wh860.jpg',
price: '320',
line_price: '320',
},
{
name: '技术服务',
id: 4,
icon: 'https://img95.699pic.com/photo/50384/2866.jpg_wh860.jpg',
price: '320',
line_price: '320',
},
]"
v-for="item in product_30.list"
>
<wd-card custom-class="card-content">
<view style="height: 200rpx">
<wd-img
radius="10rpx"
:width="'100%'"
:height="'100%'"
src="https://img95.699pic.com/photo/50384/2866.jpg_wh860.jpg"
/>
<wd-img radius="10rpx" :width="'100%'" :height="'100%'" :src="item.image" />
</view>
<view class="ps-2 pt-2 font-size-4 font-bold">xxx蔬菜基地</view>
<view class="ps-2 pt-2 font-size-4 font-bold">{{ item.store_name }}</view>
<view class="ps-2 pt-2 font-size-3">我们这里的食物很新鲜</view>
<view class="ps-2 pt-2 pb-2">
<view class="text-sm text-gray-500 text-left">
@ -461,6 +426,30 @@
<script lang="ts" setup>
// import { toLogin } from '@/libs/login.js'
import { getProductAPI } from '@/service/crmeb/product'
onLoad(() => {
getProduct(30)
// postFoo()
})
const product_30 = ref([])
const getProduct = async (id) => {
const res = await getProductAPI(id)
product_30.value = res.data
// // console.log(res.data)
// console.log(product_30.value)
}
// const data2 = ref<IFooItem>()
// const postFoo = async () => {
// const res = await postFooAPI('2')
// }
// const { loading, error, data, run } = useRequest<IFooItem>(() => getProductAPI(30), {
// immediate: true,
// initialData,
// })
const currentTab = ref(1)
function changeTab(e) {

View File

@ -7,16 +7,22 @@
<template>
<view class="p-4">
<view class="flex items-center leading-6" v-if="hasLogin">
<image class="w-8 h-8 rounded-full" :src="userStore.userInfo?.avatar"></image>
<view class="ml-2">{{ userStore.userInfo?.nickname }}</view>
<image class="w-18 h-18 rounded-full" :src="userStore.userInfo?.avatar"></image>
<view class="ml-2 flex-content-column">
<view class="ps-1 font-size-4 font-bold">微信用户{{ userStore.userInfo?.nickname }}</view>
<view class="ml-1 font-size-3" style="align-items: end">
<text class="pe-2 font-size-3">账号{{ userStore.userInfo?.nickname }}</text>
</view>
</view>
</view>
<view class="flex items-center leading-6" v-else @click="show = true">
<view class="i-carbon-user-avatar"></view>
<view class="ml-2">点击显示微信头像</view>
<image class="w-18 h-18 rounded-full" :src="userStore.userInfo?.avatar"></image>
<view class="ml-2 font-size-4">去登录</view>
</view>
<fly-login v-model="show" />
<fly-content :line="10" />
<button v-if="hasLogin" class="mt-2" @click="logout">退出登录</button>
<!-- <fly-content :line="10" /> -->
<!-- <button v-if="hasLogin" class="mt-2" @click="logout">退出登录</button> -->
</view>
</template>

View File

@ -1,12 +1,43 @@
<route lang="json5">
{
style: { navigationBarTitleText: '我的' },
style: { navigationStyle: 'custom', navigationBarTitleText: '我的' },
}
</route>
<template>
<view class="ml-4">wx的openid:</view>
<view class="ml-4">{{ openId }}</view>
<wx-login />
<view class="background_home">
<!-- <view class="ml-4">wx的openid:</view> -->
<!-- <view class="ml-4">{{ openId }}</view> -->
<wx-login />
<view class="p-2">
<wd-card>
<wd-grid :gutter="2" :column="4">
<view
@click="more"
v-for="item in [
{ name: '我的订单', icon: '/static/icons/village_service.png', color: 'green' },
{ name: '我的收藏', icon: '/static/icons/agriculture_service.png', color: 'blue' },
{ name: '我的评论', icon: '/static/icons/agriculture_course.png', color: 'orange' },
{ name: '我的点赞', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
{ name: '我的券包', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
{ name: '我的预约', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
{ name: '设置', icon: '/static/icons/rural_ecommerce.png', color: 'red' },
]"
>
<wd-grid-item use-slot>
<view class="p-2">
<wd-img radius="10rpx" :width="'100rpx'" :height="'100rpx'" :src="item.icon" />
<view class="ps-2 pt-2 pb-2 text-center text-gray-500 font-size-3">
{{ item.name }}
</view>
</view>
</wd-grid-item>
</view>
</wd-grid>
</wd-card>
<button v-if="hasLogin" class="mt-2" @click="logout">退出登录</button>
</view>
</view>
</template>
<script lang="ts" setup>
@ -14,9 +45,22 @@ import { useUserStore } from '@/store'
import { http } from '@/utils/http'
import WxLogin from './components/wx-login.vue'
const hasLogin = computed(() => userStore.userInfo?.nickname)
const userStore = useUserStore()
const openId = ref('')
const logout = () => {
uni.showModal({
title: '确认退出当前账号?',
success: (res) => {
if (res.confirm) {
userStore.logout()
}
},
})
}
// openId
uni.login({
provider: 'weixin',

View File

@ -0,0 +1,29 @@
import { http } from '@/utils/http'
export interface IFooItem {
cate_pid: string
// name: string
// any: any
}
/** GET 请求 */
export function getProductAPI(cate_pid: string) {
return http.get<IFooItem>('/api/product/spu/lst', { cate_pid })
}
/** GET 请求;支持 传递 header 的范例 */
export function getFooAPI2(name: string) {
return http.get<IFooItem>('/foo', { name }, { 'Content-Type-100': '100' })
}
/** POST 请求 */
export function postFooAPI(name: string) {
return http.post<IFooItem>('/foo', { name })
}
/** POST 请求;需要传递 query 参数的范例微信小程序经常有同时需要query参数和body参数的场景 */
export function postFooAPI2(name: string) {
return http.post<IFooItem>('/foo', { name })
}
/** POST 请求;支持 传递 header 的范例 */
export function postFooAPI3(name: string) {
return http.post<IFooItem>('/foo', { name }, { name }, { 'Content-Type-100': '100' })
}

View File

@ -29,8 +29,7 @@ export const useUserStore = defineStore(
// 若头像为空 则使用默认头像
if (!val.avatar) {
val.avatar = userInfoState.avatar
}
else {
} else {
val.avatar = 'https://oss.laf.run/ukw0y1-site/avatar.jpg?feige'
}
userInfo.value = val
@ -98,6 +97,7 @@ export const useUserStore = defineStore(
return {
userInfo,
setUserInfo,
login,
wxLogin,
getUserInfo,

View File

@ -15,20 +15,18 @@ export function http<T>(options: CustomRequestOptions) {
if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1 提取核心数据 res.data
resolve(res.data as IResData<T>)
}
else if (res.statusCode === 401) {
} else if (res.statusCode === 401) {
// 401错误 -> 清理用户信息,跳转到登录页
// userStore.clearUserInfo()
// uni.navigateTo({ url: '/pages/login/login' })
reject(res)
}
else {
} else {
// 其他错误 -> 根据后端错误信息轻提示
!options.hideErrorToast
&& uni.showToast({
icon: 'none',
title: (res.data as IResData<T>).msg || '请求错误',
})
!options.hideErrorToast &&
uni.showToast({
icon: 'none',
title: (res.data as IResData<T>).msg || '请求错误',
})
reject(res)
}
},
@ -51,7 +49,12 @@ export function http<T>(options: CustomRequestOptions) {
* @param header json格式
* @returns
*/
export function httpGet<T>(url: string, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
export function httpGet<T>(
url: string,
query?: Record<string, any>,
header?: Record<string, any>,
options?: Partial<CustomRequestOptions>,
) {
return http<T>({
url,
query,
@ -69,7 +72,13 @@ export function httpGet<T>(url: string, query?: Record<string, any>, header?: Re
* @param header json格式
* @returns
*/
export function httpPost<T>(url: string, data?: Record<string, any>, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
export function httpPost<T>(
url: string,
data?: Record<string, any>,
query?: Record<string, any>,
header?: Record<string, any>,
options?: Partial<CustomRequestOptions>,
) {
return http<T>({
url,
query,
@ -82,7 +91,13 @@ export function httpPost<T>(url: string, data?: Record<string, any>, query?: Rec
/**
* PUT
*/
export function httpPut<T>(url: string, data?: Record<string, any>, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
export function httpPut<T>(
url: string,
data?: Record<string, any>,
query?: Record<string, any>,
header?: Record<string, any>,
options?: Partial<CustomRequestOptions>,
) {
return http<T>({
url,
data,
@ -96,7 +111,12 @@ export function httpPut<T>(url: string, data?: Record<string, any>, query?: Reco
/**
* DELETE query
*/
export function httpDelete<T>(url: string, query?: Record<string, any>, header?: Record<string, any>, options?: Partial<CustomRequestOptions>) {
export function httpDelete<T>(
url: string,
query?: Record<string, any>,
header?: Record<string, any>,
options?: Partial<CustomRequestOptions>,
) {
return http<T>({
url,
query,