Merge branch 'base' into i18n

This commit is contained in:
菲鸽 2024-05-18 17:51:05 +08:00
commit a7b0c536a7
22 changed files with 164 additions and 442 deletions

13
env/.env vendored
View File

@ -1,14 +1,15 @@
VITE_APP_TITLE = 'unibest'
VITE_APP_PORT = 9000
# h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE=/
VITE_UNI_APPID = 'H57F2ACE4'
VITE_WX_APPID = 'wxa2abb91f64032a2b'
# 非h5端只能使用完整的baseurl否则无法请求本地proxy只支持h5端
# VITE_SERVER_BASEURL = '/api'
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
# h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE=/
VITE_SERVER_BASEURL = 'https://ukw0y1.laf.run'
VITE_UPLOAD_BASEURL = 'https://ukw0y1.laf.run/upload'
# h5是否需要配置代理
VITE_APP_PROXY=true
VITE_APP_PROXY_PREFIX = '/api'

View File

@ -32,6 +32,9 @@ export default defineManifestConfig({
usingComponents: true,
nvueStyleCompiler: 'uni-app',
compilerVersion: 3,
compatible: {
ignoreVersion: true,
},
splashscreen: {
alwaysShowBeforeRender: true,
waiting: true,

View File

@ -109,7 +109,10 @@
"@dcloudio/uni-cli-shared": "3.0.0-4010420240430001",
"@dcloudio/uni-stacktracey": "3.0.0-4010420240430001",
"@dcloudio/vite-plugin-uni": "3.0.0-4010420240430001",
"@esbuild/darwin-arm64": "0.20.2",
"@esbuild/darwin-x64": "0.20.2",
"@iconify-json/carbon": "^1.1.27",
"@rollup/rollup-darwin-x64": "^4.17.2",
"@types/node": "^20.11.5",
"@types/wechat-miniprogram": "^3.4.7",
"@typescript-eslint/eslint-plugin": "^6.15.0",

View File

@ -35,7 +35,7 @@ export default defineUniPages({
{
iconPath: 'static/tabbar/example.png',
selectedIconPath: 'static/tabbar/exampleHL.png',
pagePath: 'pages/index/about',
pagePath: 'pages/about/about',
text: '%tabbar.about%',
},
],

4
src/env.d.ts vendored
View File

@ -15,6 +15,10 @@ interface ImportMetaEnv {
readonly VITE_SERVER_PORT: string
/** 后台接口地址 */
readonly VITE_SERVER_BASEURL: string
/** H5是否需要代理 */
readonly VITE_APP_PROXY: 'true' | 'false'
/** H5是否需要代理需要的话有个前缀 */
readonly VITE_APP_PROXY_PREFIX: string // 一般是/api
/** 上传图片地址 */
readonly VITE_UPLOAD_BASEURL: string
/** 是否清除console */

View File

@ -1,13 +1,15 @@
// TODO: 别忘加更改环境变量的 VITE_UPLOAD_BASEURL 地址。
const VITE_UPLOAD_BASEURL = import.meta.env.VITE_UPLOAD_BASEURL
/**
* useUpload
* @param formData {name: '菲鸽'}
* @returns {loading, error, data, run}
*/
export default function useUpload<T>(formData: Record<string, any> = {}) {
export default function useUpload<T = string>(formData: Record<string, any> = {}) {
const loading = ref(false)
const error = ref(false)
const data = ref<T>()
const url = import.meta.env.VITE_UPLOAD_BASEURL
const run = () => {
// #ifdef MP-WEIXIN
// 微信小程序从基础库 2.21.0 开始, wx.chooseImage 停止维护,请使用 uni.chooseMedia 代替。
@ -16,26 +18,9 @@ export default function useUpload<T>(formData: Record<string, any> = {}) {
count: 1,
mediaType: ['image'],
success: (res) => {
console.log(res)
loading.value = true
const tempFilePath = res.tempFiles[0].tempFilePath
uni.uploadFile({
url,
filePath: tempFilePath,
name: 'file',
formData,
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
data.value = uploadFileRes.data as T
},
fail: (err) => {
console.log('uni.uploadFile err->', err)
error.value = true
},
complete: () => {
loading.value = false
},
})
uploadFile<T>({ tempFilePath, formData, data, error, loading })
},
fail: (err) => {
console.log('uni.chooseMedia err->', err)
@ -47,26 +32,9 @@ export default function useUpload<T>(formData: Record<string, any> = {}) {
uni.chooseImage({
count: 1,
success: (res) => {
console.log(res)
loading.value = true
const tempFilePath = res.tempFilePaths[0]
uni.uploadFile({
url,
filePath: tempFilePath,
name: 'file',
formData,
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
data.value = uploadFileRes.data as T
},
fail: (err) => {
console.log('uni.uploadFile err->', err)
error.value = true
},
complete: () => {
loading.value = false
},
})
uploadFile<T>({ tempFilePath, formData, data, error, loading })
},
fail: (err) => {
console.log('uni.chooseImage err->', err)
@ -78,3 +46,22 @@ export default function useUpload<T>(formData: Record<string, any> = {}) {
return { loading, error, data, run }
}
function uploadFile<T>({ tempFilePath, formData, data, error, loading }) {
uni.uploadFile({
url: VITE_UPLOAD_BASEURL,
filePath: tempFilePath,
name: 'file',
formData,
success: (uploadFileRes) => {
data.value = uploadFileRes.data as T
},
fail: (err) => {
console.log('uni.uploadFile err->', err)
error.value = true
},
complete: () => {
loading.value = false
},
})
}

View File

@ -1,82 +0,0 @@
/**
* useUpload
* @param url https://ukw0y1.laf.run/upload。
* .env
* @param formData {name: '菲鸽'}
* @returns {loading, error, data, run}
*/
export default function useUpload<T>(url: string, formData: Record<string, any> = {}) {
const loading = ref(false)
const error = ref(false)
const data = ref<T>()
const run = () => {
// #ifdef MP-WEIXIN
// 微信小程序从基础库 2.21.0 开始, wx.chooseImage 停止维护,请使用 uni.chooseMedia 代替。
// 微信小程序在2023年10月17日之后使用本API需要配置隐私协议
uni.chooseMedia({
count: 1,
mediaType: ['image'],
success: (res) => {
console.log(res)
loading.value = true
const tempFilePath = res.tempFiles[0].tempFilePath
uni.uploadFile({
url,
filePath: tempFilePath,
name: 'file',
formData,
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
data.value = uploadFileRes.data as T
},
fail: (err) => {
console.log('uni.uploadFile err->', err)
error.value = true
},
complete: () => {
loading.value = false
},
})
},
fail: (err) => {
console.log('uni.chooseMedia err->', err)
error.value = true
},
})
// #endif
// #ifndef MP-WEIXIN
uni.chooseImage({
count: 1,
success: (res) => {
console.log(res)
loading.value = true
const tempFilePath = res.tempFilePaths[0]
uni.uploadFile({
url,
filePath: tempFilePath,
name: 'file',
formData,
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
data.value = uploadFileRes.data as T
},
fail: (err) => {
console.log('uni.uploadFile err->', err)
error.value = true
},
complete: () => {
loading.value = false
},
})
},
fail: (err) => {
console.log('uni.chooseImage err->', err)
error.value = true
},
})
// #endif
}
return { loading, error, data, run }
}

View File

@ -27,7 +27,18 @@ const httpInterceptor = {
}
// 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
// #ifdef H5
console.log(__VITE_APP_PROXY__)
if (JSON.parse(__VITE_APP_PROXY__)) {
// 啥都不需要做
} else {
options.url = baseUrl + options.url
}
// #endif
// 非H5正常拼接
// #ifndef H5
options.url = baseUrl + options.url
// #endif
// TIPS: 如果需要对接多个后端服务,也可以在这里处理,拼接成所需要的地址
}
// 1. 请求超时

View File

@ -48,6 +48,9 @@
"android": {},
"ios": {}
}
},
"compatible": {
"ignoreVersion": true
}
},
"quickapp": {},

View File

@ -32,7 +32,7 @@
{
"iconPath": "static/tabbar/example.png",
"selectedIconPath": "static/tabbar/exampleHL.png",
"pagePath": "pages/index/about",
"pagePath": "pages/about/about",
"text": "%tabbar.about%"
}
]
@ -47,7 +47,7 @@
}
},
{
"path": "pages/index/about",
"path": "pages/about/about",
"type": "page",
"style": {
"navigationBarTitleText": "关于"
@ -59,38 +59,6 @@
"style": {
"navigationBarTitleText": "%app.name%"
}
},
{
"path": "pages/index/request",
"type": "page",
"layout": "demo",
"style": {
"navigationBarTitleText": "请求"
}
},
{
"path": "pages/index/request2",
"type": "page",
"layout": "demo",
"style": {
"navigationBarTitleText": "请求-状态一体化"
}
},
{
"path": "pages/index/upload",
"type": "page",
"layout": "default",
"style": {
"navigationBarTitleText": "上传"
}
},
{
"path": "pages/index/upload2",
"type": "page",
"layout": "default",
"style": {
"navigationBarTitleText": "上传-状态一体化"
}
}
],
"subPackages": []

36
src/pages/about/about.vue Normal file
View File

@ -0,0 +1,36 @@
<route lang="json5">
{
style: {
navigationBarTitleText: '关于',
},
}
</route>
<template>
<view
class="bg-white overflow-hidden pt-2 px-4"
:style="{ marginTop: safeAreaInsets?.top + 'px' }"
>
<view class="text-center text-3xl mt-8">
鸽友们好我是
<text class="text-red-500">菲鸽</text>
</view>
<RequestComp />
<UploadComp />
</view>
</template>
<script lang="ts" setup>
import RequestComp from './components/request.vue'
import UploadComp from './components/upload.vue'
//
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>
<style lang="scss" scoped>
.test-css {
// mt-4=>1rem=>16px;
margin-top: 16px;
}
</style>

View File

@ -0,0 +1,43 @@
<route lang="json5">
{
layout: 'demo',
style: {
navigationBarTitleText: '请求',
},
}
</route>
<template>
<view class="p-6 text-center">
<view class="my-2">使用的是 laf 云后台</view>
<view class="text-green-400">我的推荐码可以获得佣金</view>
<!-- #ifdef H5 -->
<view class="my-2">
<a class="my-2" :href="recommendUrl" target="_blank">{{ recommendUrl }}</a>
</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="my-2 text-left text-sm">{{ recommendUrl }}</view>
<!-- #endif -->
<!-- http://localhost:9000/#/pages/index/request -->
<button @click="run" class="my-6">发送请求</button>
<view class="text-xl">请求数据如下</view>
<view class="text-green h-6">{{ JSON.stringify(data) }}</view>
<button type="warn" @click="reset" class="my-6">清除数据</button>
</view>
</template>
<script lang="ts" setup>
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
const recommendUrl = ref('http://laf.run/signup?code=ohaOgIX')
// Service
const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI('菲鸽'))
const reset = () => {
data.value = undefined
}
</script>

View File

@ -12,18 +12,17 @@
<wd-button @click="run">选择图片并上传</wd-button>
<view v-if="loading" class="text-blue h-10">上传...</view>
<template v-else>
<view class="m-2">上传后返回的图片地址</view>
<view class="m-2">上传后返回的接口数据</view>
<view class="m-2">{{ data }}</view>
<view class="h-80 w-full">
<image v-if="data" :src="data" mode="scaleToFill" />
<image v-if="data" :src="data || data" mode="scaleToFill" />
</view>
</template>
</view>
</template>
<script lang="ts" setup>
// const { loading, data, run } = useUpload2<string>('https://ukw0y1.laf.run/upload', { user: '' })
const { loading, data, run } = useUpload<string>({ user: '菲鸽' })
const { loading, data, run } = useUpload({ user: '菲鸽' })
</script>
<style lang="scss" scoped>

View File

@ -1,65 +0,0 @@
<route lang="json5">
{
style: {
navigationBarTitleText: '关于',
},
}
</route>
<template>
<view
class="bg-white overflow-hidden pt-2 px-4"
:style="{ marginTop: safeAreaInsets?.top + 'px' }"
>
<view class="text-center text-3xl mt-4 test-css">关于页面</view>
<view class="text-center text-3xl mt-8">
鸽友们好我是
<text class="text-red-500">菲鸽</text>
</view>
<view class="text-center mt-8 text-#fff">
<wd-button type="success" @click="gotoPage('i18n')">进入多语言页面</wd-button>
</view>
<view class="text-center mt-8 text-#fff">
<wd-button type="primary" @click="gotoPage('request')">去请求页</wd-button>
<wd-button type="primary" @click="gotoPage('request2')" custom-class="ml-2">
去请求页2 (状态一体)
</wd-button>
</view>
<view class="text-center mt-8 text-#fff">
<wd-button type="primary" @click="gotoPage('upload')">上传demo</wd-button>
<wd-button type="primary" @click="gotoPage('upload2')" custom-class="ml-2">
上传demo2(状态一体)
</wd-button>
</view>
<view class="text-center mt-8">
<text class="mr-2">iconfont:</text>
<view class="inline-flex gap-2 text-red">
<view class="iconfont icon-my" />
<view class="iconfont icon-chat" />
<view class="iconfont icon-package" />
</view>
</view>
</view>
</template>
<script lang="ts" setup>
//
const { safeAreaInsets } = uni.getSystemInfoSync()
const gotoPage = (page: string) => {
uni.navigateTo({
url: `/pages/index/${page}`,
})
}
</script>
<style lang="scss" scoped>
.test-css {
// mt-4=>1rem=>16px;
margin-top: 16px;
}
</style>

View File

@ -1,67 +0,0 @@
<route lang="json5">
{
layout: 'demo',
style: {
navigationBarTitleText: '请求',
},
}
</route>
<template>
<view class="p-6 text-center">
<view class="my-2">使用的是 laf 云后台</view>
<view class="text-green-400">我的推荐码可以获得佣金</view>
<!-- #ifdef H5 -->
<view class="my-2">
<a class="my-2" :href="recommendUrl" target="_blank">{{ recommendUrl }}</a>
</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="my-2 text-left text-sm">{{ recommendUrl }}</view>
<!-- #endif -->
<!-- http://localhost:9000/#/pages/index/request -->
<button @click="getFoo" class="my-6">1.测试 GET 请求</button>
<view class="text-xl">请求数据如下</view>
<view class="text-green h-10">{{ JSON.stringify(data) }}</view>
<view class="text-xl">完整数据</view>
<view class="text-green h-16">{{ JSON.stringify(originalData) }}</view>
<button @click="postFoo" class="my-6">2.测试 POST 请求</button>
<view class="text-xl">请求数据如下</view>
<view class="text-green h-10">{{ JSON.stringify(data2) }}</view>
<button class="my-6" type="warn" @click="reset">3.一键清空数据</button>
</view>
</template>
<script lang="ts" setup>
import { getFooAPI, postFooAPI, IFooItem } from '@/service/index/foo'
const recommendUrl = ref('http://laf.run/signup?code=ohaOgIX')
onLoad(() => {
getFoo()
postFoo()
})
const originalData = ref<IResData<IFooItem>>()
const data = ref<IFooItem>()
const getFoo = async () => {
const res = await getFooAPI('菲鸽')
data.value = res.data
originalData.value = res
}
const data2 = ref<IFooItem>()
const postFoo = async () => {
const res = await postFooAPI('菲鸽2')
data2.value = res.data
}
const reset = () => {
data.value = undefined
data2.value = undefined
originalData.value = undefined
}
</script>

View File

@ -1,35 +0,0 @@
<route lang="json5">
{
layout: 'demo',
style: {
navigationBarTitleText: '请求-状态一体化',
},
}
</route>
<template>
<view class="p-6 text-center">
<!-- http://localhost:9000/#/pages/index/request -->
<button @click="getFoo" class="my-6">测试 GET 请求</button>
<view class="text-xl">请求数据如下</view>
<view v-if="loading" class="text-blue h-10">加载中...</view>
<view v-if="error" class="text-red h-10">请求错误</view>
<view v-else class="text-green h-10">{{ JSON.stringify(data) }}</view>
<button class="my-6" type="warn" @click="reset">一键清空数据</button>
</view>
</template>
<script lang="ts" setup>
import { getFooAPI2, IFooItem } from '@/service/index/foo'
import { httpGet } from '@/utils/http'
// Service
const { loading, error, data, run } = useRequest<IFooItem>(() => getFooAPI2('菲鸽'))
// 便
// const { loading, error, data, run } = useRequest<IFooItem>(() => httpGet('/foo', { name: '' }))
const getFoo = () => run()
const reset = () => {
data.value = undefined
}
</script>

View File

@ -1,75 +0,0 @@
<route lang="json5" type="page">
{
layout: 'default',
style: {
navigationBarTitleText: '上传',
},
}
</route>
<template>
<view class="p-4 text-center">
<wd-button @click="chooseImage">选择图片并上传</wd-button>
<view class="m-2">上传后返回的图片地址</view>
<view class="m-2">{{ imgStr }}</view>
<view class="h-80 w-full">
<image v-if="imgStr" :src="imgStr" mode="scaleToFill" />
</view>
</view>
</template>
<script lang="ts" setup>
const imgStr = ref('')
const chooseImage = () => {
// #ifdef MP-WEIXIN
// 2.21.0 wx.chooseImage 使 uni.chooseMedia
// 20231017使API
uni.chooseMedia({
count: 1,
mediaType: ['image'],
success: (res) => {
console.log(res)
const tempFilePath = res.tempFiles[0].tempFilePath
uni.uploadFile({
url: 'https://ukw0y1.laf.run/upload',
filePath: tempFilePath,
name: 'file',
formData: {
user: '菲鸽',
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
imgStr.value = uploadFileRes.data
},
})
},
})
// #endif
// #ifndef MP-WEIXIN
uni.chooseImage({
count: 1,
success: (res) => {
console.log(res)
const tempFilePath = res.tempFilePaths[0]
uni.uploadFile({
url: 'https://ukw0y1.laf.run/upload',
filePath: tempFilePath,
name: 'file',
formData: {
user: '菲鸽',
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data)
imgStr.value = uploadFileRes.data
},
})
},
})
// #endif
}
</script>
<style lang="scss" scoped>
//
</style>

View File

@ -6,28 +6,10 @@ export interface IFooItem {
/** GET 请求 */
export const getFooAPI = (name: string) => {
return http<IFooItem>({
url: `/foo`,
method: 'GET',
query: { name },
})
}
/** GET 请求 - 再次简化,看大家是否喜欢这种简化 */
export const getFooAPI2 = (name: string) => {
return http.get<IFooItem>('/foo', { name })
}
/** POST 请求 */
export const postFooAPI = (name: string) => {
return http<IFooItem>({
url: `/foo`,
method: 'POST',
query: { name }, // post 请求也支持 query
data: { name },
})
}
/** POST 请求 - 再次简化,看大家是否喜欢这种简化 */
export const postFooAPI2 = (name: string) => {
return http.post<IFooItem>('/foo', { name }, { name })
}

View File

@ -170,7 +170,6 @@ declare module 'vue' {
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
readonly useRequest: UnwrapRef<typeof import('../hooks/useRequest')['default']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useUpload2: UnwrapRef<typeof import('../hooks/useUpload2')['default']>
readonly useUpload: UnwrapRef<typeof import('../hooks/useUpload')['default']>
readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
@ -254,7 +253,6 @@ declare module '@vue/runtime-core' {
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
readonly useRequest: UnwrapRef<typeof import('../hooks/useRequest')['default']>
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
readonly useUpload2: UnwrapRef<typeof import('../hooks/useUpload2')['default']>
readonly useUpload: UnwrapRef<typeof import('../hooks/useUpload')['default']>
readonly watch: UnwrapRef<typeof import('vue')['watch']>
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>

View File

@ -12,3 +12,5 @@ declare const __UNI_PLATFORM__:
| 'quickapp-webview'
| 'quickapp-webview-huawei'
| 'quickapp-webview-union'
declare const __VITE_APP_PROXY__: 'true' | 'false'

View File

@ -5,17 +5,13 @@
interface NavigateToOptions {
url: "/pages/index/index" |
"/pages/index/about" |
"/pages/index/i18n" |
"/pages/index/request" |
"/pages/index/request2" |
"/pages/index/upload" |
"/pages/index/upload2";
"/pages/about/about" |
"/pages/index/i18n";
}
interface RedirectToOptions extends NavigateToOptions {}
interface SwitchTabOptions {
url: "/pages/index/index" | "/pages/index/about"
url: "/pages/index/index" | "/pages/about/about"
}
type ReLaunchOptions = NavigateToOptions | SwitchTabOptions;

View File

@ -35,7 +35,14 @@ export default ({ command, mode }) => {
console.log('UNI_PLATFORM -> ', UNI_PLATFORM) // 得到 mp-weixin, h5, app 等
const env = loadEnv(mode, path.resolve(process.cwd(), 'env'))
const { VITE_APP_PORT, VITE_SERVER_BASEURL, VITE_DELETE_CONSOLE, VITE_SHOW_SOURCEMAP } = env
const {
VITE_APP_PORT,
VITE_SERVER_BASEURL,
VITE_DELETE_CONSOLE,
VITE_SHOW_SOURCEMAP,
VITE_APP_PROXY,
VITE_APP_PROXY_PREFIX,
} = env
console.log('环境变量 env -> ', env)
return defineConfig({
@ -87,6 +94,7 @@ export default ({ command, mode }) => {
],
define: {
__UNI_PLATFORM__: JSON.stringify(UNI_PLATFORM),
__VITE_APP_PROXY__: JSON.stringify(VITE_APP_PROXY),
},
css: {
postcss: {
@ -110,13 +118,15 @@ export default ({ command, mode }) => {
hmr: true,
port: Number.parseInt(VITE_APP_PORT, 10),
// 仅 H5 端生效其他端不生效其他端走build不走devServer)
// proxy: {
// '/api': {
// target: VITE_SERVER_BASEURL,
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, ''),
// },
// },
proxy: JSON.parse(VITE_APP_PROXY)
? {
[VITE_APP_PROXY_PREFIX]: {
target: VITE_SERVER_BASEURL,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp(`^${VITE_APP_PROXY_PREFIX}`), ''),
},
}
: undefined,
},
build: {
// 方便非h5端调试