Compare commits

...

10 Commits

Author SHA1 Message Date
dongmu 67859c569f 123
1 year ago
dongmu 3ee987f1f9 请求类型传输
1 year ago
dongmu 6da146785a 组件类型声明
1 year ago
dongmu d859691873 2023.11.15封装请求
1 year ago
dongmu be12953e05 2
1 year ago
dongmu ee9b78f42d 2
1 year ago
dongmu 3e012d89f8 1
1 year ago
dongmu 2f6fed858a 1
1 year ago
苏杰豪 a0933c6d1d chore: update deps
1 year ago
苏杰豪 c84c34e3df chore: add README
1 year ago

@ -1,39 +1,98 @@
# Vue3Ts
## 项目简介
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
小兔鲜儿项目包含从首页浏览商品,商品详情,微信登录,加入购物车,提交订单,微信支付,订单管理等功能。
#### 软件架构
软件架构说明
当前仓库为小兔鲜儿的**项目模板**。
### 技术栈
#### 安装教程
- 前端框架:[uni-app](https://uniapp.dcloud.net.cn/) (Vue3 + TS + Setup)
- 状态管理:[pinia](https://pinia.vuejs.org/zh/)
- 组件库:[uni-ui](https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html)
1. xxxx
2. xxxx
3. xxxx
## 资料说明
#### 使用说明
### 📀 视频学习
1. xxxx
2. xxxx
3. xxxx
[https://www.bilibili.com/video/BV1Bp4y1379L/](https://www.bilibili.com/video/BV1Bp4y1379L/?share_source=copy_web&vd_source=2ac50d29193927b3c8597537dc4bc81d)
#### 参与贡献
### 📗 接口文档
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
[https://www.apifox.cn/apidoc/shared-0e6ee326-d646-41bd-9214-29dbf47648fa/](https://www.apifox.cn/apidoc/shared-0e6ee326-d646-41bd-9214-29dbf47648fa/)
### ✏️ 在线笔记
#### 特技
[https://megasu.gitee.io/uni-app-shop-note/](https://megasu.gitee.io/uni-app-shop-note/)
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
### 📦 项目源码
[https://gitee.com/Megasu/uniapp-shop-vue3-ts/](https://gitee.com/Megasu/uniapp-shop-vue3-ts/)
## 运行程序
1. 安装依赖
```shell
# npm
npm i --registry=https://registry.npmmirror.com
# pnpm
pnpm i --registry=https://registry.npmmirror.com
```
2. 运行程序
```shell
# 微信小程序端
npm run dev:mp-weixin
# H5端
npm run dev:h5
# App端
需 HbuilderX 工具,运行 - 运行到手机或模拟器
```
3. 微信开发者工具导入 `/dist/dev/mp-weixin` 目录
### 工程结构解析
```
├── .husky # Git Hooks
├── .vscode # VS Code 插件 + 设置
├── dist # 打包文件夹(可删除重新打包)
├── src # 源代码
│ ├── components # 全局组件
│ ├── composables # 组合式函数
│ ├── pages # 主包页面
│ ├── index # 首页
│ ├── category # 分类页
│ ├── cart # 购物车
│ ├── my # 我的
│ └── login # 登录页
│ ├── services # 所有请求
│ ├── static # 存放应用引用的本地静态资源的目录
│ ├── images # 普通图片
│ └── tabs # tabBar 图片
│ ├── stores # 全局 pinia store
│ ├── modules # 模块
│ └── index.ts # store 入口
│ ├── styles # 全局样式
│ └── fonts.scss # 字体图标
│ ├── types # 类型声明文件
│ └── component.d.ts # 全局组件类型声明
│ ├── utils # 全局方法
│ ├── App.vue # 入口页面
│ ├── main.ts # Vue初始化入口文件
│ ├── pages.json # 配置页面路由等页面类信息
│ ├── manifest.json # 配置appid等打包信息
│ └── uni.scss # uni-app 内置的常用样式变量
├── .editorconfig # editorconfig 配置
├── .eslintrc.cjs # eslint 配置
├── .prettierrc.json # prettier 配置
├── .gitignore # git 忽略文件
├── index.html # H5 端首页
├── package.json # package.json 依赖
├── tsconfig.json # typescript 配置
└── vite.config.ts # vite 配置
```

@ -63,6 +63,7 @@
"@dcloudio/uni-mp-weixin": "3.0.0-alpha-3081220230802001",
"@dcloudio/uni-mp-xhs": "3.0.0-alpha-3081220230802001",
"@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3081220230802001",
"@dcloudio/uni-ui": "^1.4.28",
"pinia": "2.0.27",
"pinia-plugin-persistedstate": "^3.2.0",
"vue": "^3.2.47",
@ -87,7 +88,7 @@
"eslint-plugin-vue": "^9.3.0",
"husky": "^8.0.0",
"lint-staged": "^13.0.3",
"miniprogram-api-typings": "^3.9.1",
"miniprogram-api-typings": "^3.12.0",
"prettier": "^2.7.1",
"sass": "^1.56.1",
"typescript": "^5.1.6",

File diff suppressed because it is too large Load Diff

@ -0,0 +1,77 @@
<script setup lang="ts">
import type { BannerItem } from '@/types/home'
import { ref } from 'vue'
const activeIndex = ref(0)
const onchange: UniHelper.SwiperOnChange = (ev) => {
//
activeIndex.value = ev.detail!.current
}
// props --- ()
defineProps<{
list: BannerItem[]
}>()
// const props = defineProps<{
// list: BannerItem[]
// }>()
// console.log(props, 'props')
</script>
<template>
<view class="carousel">
<swiper @change="onchange" :circular="true" :autoplay="false" :interval="3000">
<swiper-item v-for="item in list" :key="item.id">
<navigator url="/pages/index/index" hover-class="none" class="navigator">
<image mode="aspectFill" class="image" :src="item.imgUrl"></image>
</navigator>
</swiper-item>
</swiper>
<!-- 指示点 -->
<view class="indicator">
<text
v-for="(item, index) in list.length"
:key="item"
class="dot"
:class="{ active: index === activeIndex }"
></text>
</view>
</view>
</template>
<style lang="scss">
/* 轮播图 */
.carousel {
height: 280rpx;
position: relative;
overflow: hidden;
transform: translateY(0);
background-color: #efefef;
.indicator {
position: absolute;
left: 0;
right: 0;
bottom: 16rpx;
display: flex;
justify-content: center;
.dot {
width: 30rpx;
height: 6rpx;
margin: 0 8rpx;
border-radius: 6rpx;
background-color: rgba(255, 255, 255, 0.4);
}
.active {
background-color: #fff;
}
}
.navigator,
.image {
width: 100%;
height: 100%;
}
}
</style>

@ -0,0 +1,8 @@
// src/components.d.ts 添加组件的类型声明
import XtxSwiper from './XtxSwiper.vue'
declare module 'vue' {
export interface GlobalComponents {
//组件名XtxSwiper 付给的类型typeof XtxSwiper 这样鼠标移入组件名位置就显示出提示不是包unkon
XtxSwiper: typeof XtxSwiper
}
}

@ -0,0 +1,8 @@
export const environment = {
ENV: 'development',
APP_TITLE: '鸿森通货运平台',
APP_TARGET: 'http://192.168.0.166',
APP_PORT: ':8080',
APP_FILE_URL: 'http://106.58.179.30:19005/',
ENCRYPT: '',
}

@ -0,0 +1,8 @@
export const environment = {
ENV: 'production',
APP_TITLE: '鸿森通货运平台',
APP_TARGET: 'https://hongsentong.com',
APP_PORT: '',
APP_FILE_URL: 'https://hongsentong.com/minio/',
ENCRYPT: 'encrypt',
}

8
src/env/test.ts vendored

@ -0,0 +1,8 @@
export const environment = {
ENV: 'test',
APP_TITLE: '鸿森通货运平台',
APP_TARGET: 'http://112.112.149.146/',
APP_PORT: '18010',
APP_FILE_URL: 'http://112.112.149.146:19005/',
ENCRYPT: true,
}

@ -1,6 +1,6 @@
{
"name": "小兔鲜儿",
"appid": "",
"name": "鸿森通货运",
"appid": "__UNI__D787228",
"description": "",
"versionName": "1.0.0",
"versionCode": 1,
@ -50,7 +50,7 @@
"quickapp": {},
/* */
"mp-weixin": {
"appid": "",
"appid": "wx79b61e386979fc3a",
"setting": {
"urlCheck": false
},

@ -1,10 +1,22 @@
{
//
"easycom": {
"autoscan": true,
"custom": {
// uni-ui
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
// Xtx,@srccomponents $1
"^Xtx(.*)": "@/components/Xtx$1.vue"
}
},
"pages": [
//pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
"navigationBarTitleText": "首页",
"navigationStyle": "custom",
"navigationBarTextStyle": "white"
}
},
{

@ -0,0 +1,73 @@
<script setup lang="ts">
//
const { safeAreaInsets } = uni.getSystemInfoSync()
console.log(safeAreaInsets, '安全区域')
</script>
<template>
<view class="navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
<!-- logo文字 -->
<view class="logo">
<image class="logo-image" src="@/static/images/logo.png"></image>
<text class="logo-text">新鲜 · 亲民 · 快捷</text>
</view>
<!-- 搜索条 -->
<view class="search">
<text class="icon-search">搜索商品</text>
<text class="icon-scan"></text>
</view>
</view>
</template>
<style lang="scss">
/* 自定义导航条 */
.navbar {
background-image: url(@/static/images/navigator_bg.png);
background-size: cover;
position: relative;
display: flex;
flex-direction: column;
padding-top: 20px;
.logo {
display: flex;
align-items: center;
height: 64rpx;
padding-left: 30rpx;
padding-top: 20rpx;
.logo-image {
width: 166rpx;
height: 39rpx;
}
.logo-text {
flex: 1;
line-height: 28rpx;
color: #fff;
margin: 2rpx 0 0 20rpx;
padding-left: 20rpx;
border-left: 1rpx solid #fff;
font-size: 26rpx;
}
}
.search {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10rpx 0 26rpx;
height: 64rpx;
margin: 16rpx 20rpx;
color: #fff;
font-size: 28rpx;
border-radius: 32rpx;
background-color: rgba(255, 255, 255, 0.5);
}
.icon-search {
&::before {
margin-right: 10rpx;
}
}
.icon-scan {
font-size: 30rpx;
padding: 15rpx;
}
}
</style>

@ -1,8 +1,42 @@
<script setup lang="ts">
//
import { getHomeBannerAPI, queryList } from '@/services/home'
import CustomNavbar from './componets/CustomNavbar.vue'
import { onLoad } from '@dcloudio/uni-app' // -----
import { ref } from 'vue'
import type { BannerItem } from '@/types/home'
// --
onLoad(() => {
// getHomeBannerData()
queryLists()
})
//
const queryLists = async () => {
const res = await queryList()
console.log(res)
}
//
// queryLists() {
// queryList().then((res) => {
// this.VicItems = res.data;
// // console.log(res, 'queryList')
// if (res.data.length != 0) {
// let e = this.VicItems[0];
// this.vehicle = e; //
// this.vehicleId = e.id;
// }
// });
// },
</script>
<template>
<CustomNavbar></CustomNavbar>
<!-- 自定义轮播图 ctrl+点击 后先进入的是组件类型 声明文件 可以看到组件引入的路径-->
<view class="index">index</view>
</template>

@ -1,7 +1,17 @@
<script setup lang="ts">
import { useMemberStore } from '@/stores'
import { http } from '@/utils/http'
const memberStore = useMemberStore()
//
const getData = async () => {
const res = await http<string[]>({
url: '/home/banner',
method: 'GET',
})
console.log(res, 'res')
}
</script>
<template>
@ -10,7 +20,7 @@ const memberStore = useMemberStore()
<button
@tap="
memberStore.setProfile({
nickname: '黑马先锋',
nickname: '先锋',
})
"
size="mini"
@ -20,6 +30,7 @@ const memberStore = useMemberStore()
保存用户信息
</button>
<button @tap="memberStore.clearProfile()" size="mini" plain type="warn">清理用户信息</button>
<button @click="getData" size="mini" plain type="warn">请求测试</button>
</view>
</template>

@ -0,0 +1,33 @@
// 存放路径: src/services/home.ts
import type { BannerItem } from '@/types/home'
import { http } from '@/utils/http'
/**
* -广-
* @param distributionSite 广 12 1
*/
export const getHomeBannerAPI = (distributionSite = 1) => {
return http<BannerItem[]>({
method: 'GET',
url: '/home/banner',
data: {
distributionSite,
},
})
}
// 查询车型
export const queryList = () => {
return http({
method: 'GET',
url: '/system/vehicleDic/queryList',
})
}
// 查询车型
// export function queryList() {
// return requests({
// method: 'get',
// url: "/system/vehicleDic/queryList"
// })
// }

@ -27,6 +27,17 @@ export const useMemberStore = defineStore(
},
// TODO: 持久化
{
persist: true,
// 网页端配置
// persist: true,
persist: {
storage: {
getItem(key) {
return uni.getStorageSync(key)
},
setItem(key, value) {
uni.setStorageSync(key, value)
},
},
},
},
)

@ -0,0 +1,11 @@
/** 首页-广告区域数据类型 */
export type BannerItem = {
/** 跳转链接 */
hrefUrl: string
/** id */
id: string
/** 图片链接 */
imgUrl: string
/** 跳转类型 */
type: number
}

@ -0,0 +1,5 @@
import { environment } from '@/env/development'
// import { environment } from '@/env/production'
// import { environment } from '@/env/test'
export const ENV = environment

@ -0,0 +1,91 @@
// src/utils/http.ts
import { useMemberStore } from '@/stores'
import { ENV } from '@/utils/env'
// 请求基地址 -- 基础路径+网口端
const baseURL = ENV.APP_TARGET + ENV.APP_PORT
// 拦截器配置
const httpInterceptor = {
// 拦截前触发
invoke(options: UniApp.RequestOptions) {
// 1. 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 2. 请求超时
options.timeout = 10000
// 3. 添加小程序端请求头标识
options.header = {
'source-client': 'miniapp',
...options.header,
}
// 4. 添加 token 请求头标识
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
},
}
// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)
/**
*
* @param UniApp.RequestOptions
* @returns Promise
* 1. Promise
* 2.
* 2.1 res.data
* 2.2
* 3.
* 3.1 401 ->
* 3.2 ->
* 3.3 ->
*/
type Data<T> = {
code: string
msg: string
data: T
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
// 1. 返回 Promise 对象
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 响应成功
success(res) {
// 状态码 2xx参考 axios 的设计
if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1 提取核心数据 res.data
resolve(res.data as Data<T>)
} else if (res.statusCode === 401) {
// 401错误 -> 清理用户信息,跳转到登录页
const memberStore = useMemberStore()
memberStore.clearProfile()
uni.navigateTo({ url: '/pages/login/login' })
reject(res)
} else {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: (res.data as Data<T>).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试',
})
reject(err)
},
})
})
}

@ -8,7 +8,12 @@
"@/*": ["./src/*"]
},
"lib": ["esnext", "dom"],
"types": ["@dcloudio/types", "miniprogram-api-typings", "@uni-helper/uni-app-types"]
"types": [
"@dcloudio/types",
"miniprogram-api-typings",
"@uni-helper/uni-app-types",
"@uni-helper/uni-ui-types"
]
},
"vueCompilerOptions": {
// experimentalRuntimeMode nativeTags Volar

Loading…
Cancel
Save