This commit is contained in:
梁泽军 2025-03-13 18:33:23 +08:00
parent 25ea5f2781
commit 4213c2c9e0
19 changed files with 550 additions and 565 deletions

9
.env.development Normal file
View File

@ -0,0 +1,9 @@
#mode 环境
VITE_MODE = dev
#服务器域名
VITE_HOST = http://192.168.1.249:8084/
# 请求域名
VITE_APP_BASE_URL='http://192.168.1.249:8084/ai-agent-server/'

11
.env.production Normal file
View File

@ -0,0 +1,11 @@
#mode 环境
VITE_MODE = production
#服务器域名
VITE_HOST = https://test.szxgl.cn/
# 请求域名
VITE_APP_BASE_URL='https://test.szxgl.cn/ai-agent-server/'
#静态资源目录
VITE_CDN_DIR = 'https://cdn.xglpa.com/ai-agent-m/'

View File

@ -8,4 +8,4 @@ VITE_HOST = https://test.szxgl.cn/
VITE_APP_BASE_URL='https://test.szxgl.cn/ai-agent-admin-server'
#静态资源目录
VITE_CDN_DIR = 'https://agent-admin-test.szxgl.cn/'
VITE_CDN_DIR = './'

12
.gitignore vendored
View File

@ -15,17 +15,5 @@ coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.hbuilderx
# .env
.env.development
.env.production

View File

@ -33,6 +33,7 @@
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union",
"build:prod": "uni build h5 mobile --mode production",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {

View File

@ -9,6 +9,7 @@ import { SHARE_ID, USER_SN } from './enums/constantEnums'
import { strToParams } from './utils/util'
import cache from './utils/cache'
import Cookies from 'js-cookie'
import { client } from '@/utils/client'
const appStore = useAppStore()
const { getUser } = useUserStore()
@ -73,13 +74,11 @@ const setLocalStorage = async () => {
// cookie
const redirect = location.href
Cookies.set('redirect', redirect)
location.href = `${import.meta.env.VITE_APP_BASE_URL}/qywx/getWxUserByInside?terminal=3`
location.href = `${import.meta.env.VITE_APP_BASE_URL}/qywx/getWxUserByInside?terminal=${client}`
return
}
} else {
const obj = { expire: "", value: cookiesToken }
console.log('obj', obj);
console.log('写入前 token', token);
localStorage.setItem("app_token", JSON.stringify(obj));
}

View File

@ -1,58 +1,66 @@
import request from '@/utils/request'
import request from "@/utils/request";
export function getUserCenter(header?: any) {
return request.get({ url: '/user/center', header })
return request.get({ url: "/user/center", header });
}
// 个人信息
export function getUserInfo() {
return request.get({ url: '/user/info' }, { isAuth: true })
return request.get({ url: "/user/info" }, { isAuth: true });
}
// 个人编辑
export function userEdit(data: any) {
return request.post({ url: '/user/edit', data }, { isAuth: true })
return request.post({ url: "/user/edit", data }, { isAuth: true });
}
// 绑定手机
export function userBindMobile(data: any, header?: any) {
return request.post({ url: '/login/bindMobile', data, header }, { isAuth: true })
return request.post(
{ url: "/login/bindMobile", data, header },
{ isAuth: true }
);
}
// 微信电话
export function userMnpMobile(data: any, header?: any) {
return request.post({ url: '/user/mnpMobile', data, header }, { isAuth: true })
return request.post(
{ url: "/user/mnpMobile", data, header },
{ isAuth: true }
);
}
export function userChangePwd(data: any) {
return request.post({ url: '/user/changePwd', data }, { isAuth: true })
console.log("data", data);
return request.post({ url: "/user/changePwd", data }, { isAuth: true });
}
// 绑定小程序
export function mnpAuthBind(data: any) {
return request.post({ url: '/user/bindMnp', data })
return request.post({ url: "/user/bindMnp", data });
}
// 绑定公众号
export function oaAuthBind(data: any) {
return request.post({ url: '/user/bindOa', data })
return request.post({ url: "/user/bindOa", data });
}
//更新微信小程序头像昵称
export function updateUser(data: Record<string, any>, header: any) {
return request.post({ url: '/user/updateUser', data, header })
return request.post({ url: "/user/updateUser", data, header });
}
//余额明细
export function accountLog(data: any) {
return request.get({ url: '/logs/userMoney', data })
return request.get({ url: "/logs/userMoney", data });
}
//一键反馈
export function feedbackPost(data: any) {
return request.post({ url: '/feedback/add', data })
return request.post({ url: "/feedback/add", data });
}
//注销账号
export function cancelled(data?: any) {
return request.post({ url: '/login/cancelled', data })
return request.post({ url: "/login/cancelled", data });
}

View File

@ -6,36 +6,15 @@
<view class="floating-menu">
<!-- #endif -->
<movable-area class="movable-area" :scale-area="false">
<movable-view
class="movable-view"
:class="!menuData.isRemove ? 'animation-info' : ''"
style="pointer-events: auto"
@touchstart="touchstart"
@touchend="touchend"
@change="onChange"
direction="all"
inertia="true"
:x="menuData.x"
:y="menuData.y"
:disabled="disabled"
:out-of-bounds="true"
:damping="200"
:friction="100"
>
<movable-view class="movable-view" :class="!menuData.isRemove ? 'animation-info' : ''"
style="pointer-events: auto" @touchstart="touchstart" @touchend="touchend" @change="onChange"
direction="all" inertia="true" :x="menuData.x" :y="menuData.y" :disabled="disabled"
:out-of-bounds="true" :damping="200" :friction="100">
<view class="item-main" @click="openMenu">
<u-icon :name="UnfoldIcon" size="36" />
</view>
<view
v-if="menuData.showBtn"
class="menu-box"
:class="menuData.isLeft ? 'leftOut1' : 'rightOut1'"
>
<view
v-for="(item, index) in list"
:key="index"
@click="onJump(item)"
class="item-main"
>
<view v-if="menuData.showBtn" class="menu-box" :class="menuData.isLeft ? 'leftOut1' : 'rightOut1'">
<view v-for="(item, index) in list" :key="index" @click="onJump(item)" class="item-main">
<u-icon :name="item.icon" size="36" />
</view>
</view>
@ -63,7 +42,7 @@ const props = withDefaults(
list: [
{
icon: HomeIcon,
pages: '/pages/index/index'
pages: '/pages/ai_creation/ai_creation'
},
{
icon: UserIcon,
@ -201,10 +180,12 @@ const onJump = (item: any) => {
box-shadow: 0 4rpx 12rpx 0 rgba(0, 0, 0, 0.3);
border-radius: 50rpx;
}
.leftOut1 {
left: 110rpx;
animation: leftOut 0.4s;
}
.rightOut1 {
right: 110rpx;
animation: rightOut 0.4s;

View File

@ -1,21 +1,21 @@
import { ref } from 'vue'
import { ref } from "vue";
export function useLockFn(fn: (...args: any[]) => Promise<any>) {
const isLock = ref(false)
const isLock = ref(false);
const lockFn = async (...args: any[]) => {
if (isLock.value) return
isLock.value = true
if (isLock.value) return;
isLock.value = true;
try {
const res = await fn(...args)
isLock.value = false
return res
const res = await fn(...args);
isLock.value = false;
return res;
} catch (e) {
isLock.value = false
throw e
}
isLock.value = false;
throw e;
}
};
return {
isLock,
lockFn
}
lockFn,
};
}

View File

@ -1,43 +1,43 @@
import router from '@/router'
import appConfig from '@/config'
import { getShareId, shareClick } from '@/api/task'
import { paramsToStr } from '@/utils/util'
import { useNavigationBarTitleStore } from '@/stores/navigationBarTitle'
import { useAppStore } from '@/stores/app'
import shareMixin from '@/mixins/share'
import router from "@/router";
import appConfig from "@/config";
import { getShareId, shareClick } from "@/api/task";
import { paramsToStr } from "@/utils/util";
import { useNavigationBarTitleStore } from "@/stores/navigationBarTitle";
import { useAppStore } from "@/stores/app";
import shareMixin from "@/mixins/share";
export interface ShareOptions {
desc: string
title: string
imageUrl: string
path: string
desc: string;
title: string;
imageUrl: string;
path: string;
}
export type UserShareOptions = Partial<ShareOptions>
export type UserShareOptions = Partial<ShareOptions>;
//生成分享路径,首页和当前页面两种
export async function generateSharePath(isHome = false) {
const route = router.currentRoute.value
let origin = ''
const route = router.currentRoute.value;
let origin = "";
//#ifdef H5
origin = `${window.location.origin}/mobile`
origin = `${window.location.origin}/mobile`;
//#endif
//#ifdef APP-PLUS
origin = `${appConfig.baseUrl}mobile`
origin = `${appConfig.baseUrl}mobile`;
//#endif
const config = {
path: isHome ? '/pages/index/index' : route.path,
query: isHome ? {} : route.query
}
const path = `${origin}${config.path}`
const options: any = config.query
path: isHome ? "/" : route.path,
query: isHome ? {} : route.query,
};
const path = `${origin}${config.path}`;
const options: any = config.query;
try {
const { shareId } = await getShareId()
const { shareId } = await getShareId();
if (shareId) {
options.share_id = shareId
options.share_id = shareId;
}
} catch (error) {}
return `${path}${paramsToStr(options)}`
return `${path}${paramsToStr(options)}`;
}
export function useShareMessage() {
@ -46,17 +46,17 @@ export function useShareMessage() {
desc: options.desc,
image_url: options.imageUrl,
link: options.path,
title: options.title
}
}
title: options.title,
};
};
const resolvedMpOptions = (options: ShareOptions) => {
return {
imageUrl: options.imageUrl,
path: options.path,
title: options.title
}
}
title: options.title,
};
};
/**
* @description
* @param options
@ -65,39 +65,39 @@ export function useShareMessage() {
const resolveOptions = async (
options: UserShareOptions = {}
): Promise<ShareOptions> => {
const navigationBarTitleStore = useNavigationBarTitleStore()
const route = router.currentRoute.value
const appStore = useAppStore()
const navigationBarTitleStore = useNavigationBarTitleStore();
const route = router.currentRoute.value;
const appStore = useAppStore();
const { style } =
(router.routeMatcher.getRouteByPath(route.path) as any) || {}
(router.routeMatcher.getRouteByPath(route.path) as any) || {};
uni.showLoading({
title: '请稍后...'
})
title: "请稍后...",
});
const { shareTitle, shareImage, shareContent, sharePage } =
appStore.getShareConfig
const { name, logo } = appStore.getWebsiteConfig
appStore.getShareConfig;
const { name, logo } = appStore.getWebsiteConfig;
// 分享为首页
const isShareWithHome = sharePage == 2
const link = await generateSharePath(isShareWithHome)
const isShareWithHome = sharePage == 2;
const link = await generateSharePath(isShareWithHome);
let resolved = {
title: shareTitle,
path: link,
desc: shareContent,
image_url: shareImage
}
image_url: shareImage,
};
// 非首页可以合并外部参数
if (!isShareWithHome) {
resolved = {
...resolved,
...options
}
...options,
};
}
if (!resolved.title) {
if (isShareWithHome) {
resolved.title = name
resolved.title = name;
} else {
// 1. 用户点击进入页面的后台配置标题
// 2. 页面内pagesjson组册的页面标题
@ -105,72 +105,68 @@ export function useShareMessage() {
resolved.title =
navigationBarTitleStore.getTitle ||
style?.navigationBarTitleText ||
name
name;
}
}
if (!resolved.imageUrl) {
resolved.imageUrl = logo
resolved.imageUrl = logo;
}
console.log(resolved)
console.log(resolved);
// #ifdef H5
resolved = resolvedH5Options(resolved) as any
resolved = resolvedH5Options(resolved) as any;
// #endif
// #ifdef MP-WEIXIN
resolved = resolvedMpOptions(resolved) as any
resolved = resolvedMpOptions(resolved) as any;
// #endif
uni.hideLoading()
return resolved as ShareOptions
}
uni.hideLoading();
return resolved as ShareOptions;
};
// 使用分享,可以单独在页面中使用
const useShare = (options: UserShareOptions = {}) => {
// #ifdef H5
const registerEvent = () => {
//@ts-ignore
WeixinJSBridge.on('menu:share:appmessage', async function () {
const resolved = await resolveOptions(options)
WeixinJSBridge.on("menu:share:appmessage", async function () {
const resolved = await resolveOptions(options);
//@ts-ignore
WeixinJSBridge.invoke('sendAppMessage', resolved)
})
WeixinJSBridge.invoke("sendAppMessage", resolved);
});
//@ts-ignore
WeixinJSBridge.on('menu:share:timeline', async function () {
const resolved = await resolveOptions(options)
WeixinJSBridge.on("menu:share:timeline", async function () {
const resolved = await resolveOptions(options);
//@ts-ignore
WeixinJSBridge.invoke('shareTimeline', resolved)
})
}
WeixinJSBridge.invoke("shareTimeline", resolved);
});
};
//@ts-ignore
if (typeof WeixinJSBridge === 'object') {
registerEvent()
if (typeof WeixinJSBridge === "object") {
registerEvent();
} else {
document.addEventListener(
'WeixinJSBridgeReady',
registerEvent,
false
)
document.addEventListener("WeixinJSBridgeReady", registerEvent, false);
}
// #endif
}
};
const removeMixinShare = () => {
;(shareMixin as any).onShareAppMessage = undefined
}
(shareMixin as any).onShareAppMessage = undefined;
};
return {
resolveOptions,
useShare,
removeMixinShare
}
removeMixinShare,
};
}
export async function useSharedId() {
const options = uni.getEnterOptionsSync()
const share_id = options.query.share_id
const options = uni.getEnterOptionsSync();
const share_id = options.query.share_id;
if (share_id) {
await shareClick({
share_id
})
share_id,
});
}
}

View File

@ -6,10 +6,7 @@
</page-meta>
<view class="p-[40rpx]">
<view class="flex flex-col bg-white w-full p-[40rpx] rounded-lg">
<image
src="@/packages/static/images/cancel.png"
class="w-[60rpx] h-[60rpx] mx-[auto]"
></image>
<image src="@/packages/static/images/cancel.png" class="w-[60rpx] h-[60rpx] mx-[auto]"></image>
<view class="font-medium text-[32rpx] text-center mt-[30rpx]">
注销账号将永久失效且不可恢复并且放弃以下权益资产和服务
</view>
@ -25,16 +22,12 @@
</view>
</view>
</view>
<u-button
type="primary"
:custom-style="{
<u-button type="primary" :custom-style="{
width: '700rpx',
height: '100rpx',
borderRadius: '200rpx',
color: 'black'
}"
@click="handlecancel"
>
}" @click="handlecancel">
确认注销
</u-button>
@ -61,7 +54,7 @@ const handlecancel = async () => {
await cancelled({
remark: cancelledRemark.value
})
router.reLaunch('/pages/index/index')
router.reLaunch('/')
}
}
</script>

View File

@ -1,38 +1,21 @@
<template>
<view
class="register bg-white min-h-full flex flex-col items-center px-[40rpx] pt-[100rpx] box-border"
>
<view class="register bg-white min-h-full flex flex-col items-center px-[40rpx] pt-[100rpx] box-border">
<view class="w-full">
<view class="text-2xl font-medium mb-[60rpx]">
{{ type == 'set' ? '设置登录密码' : '修改登录密码' }}
</view>
<u-form borderBottom :label-width="150">
<u-form-item label="原密码" borderBottom v-if="type != 'set'">
<u-input
class="flex-1"
type="password"
v-model="formData.oldPassword"
:border="false"
placeholder="请输入原来的密码"
/>
<u-input class="flex-1" type="password" v-model="formData.oldPassword" :border="false"
placeholder="请输入原来的密码" />
</u-form-item>
<u-form-item label="新密码" borderBottom>
<u-input
class="flex-1"
type="password"
v-model="formData.password"
placeholder="6-20位数字+字母或符号组合"
:border="false"
/>
<u-input class="flex-1" type="password" v-model="formData.password" placeholder="6-20位数字+字母或符号组合"
:border="false" />
</u-form-item>
<u-form-item label="确认密码" borderBottom>
<u-input
class="flex-1"
type="password"
v-model="formData.password2"
placeholder="再次输入新密码"
:border="false"
/>
<u-input class="flex-1" type="password" v-model="formData.password2" placeholder="再次输入新密码"
:border="false" />
</u-form-item>
</u-form>
<view class="mt-[100rpx]">

View File

@ -148,15 +148,17 @@ const sendSms = async () => {
const handleConfirm = async () => {
if (!formData.mobile && isMobile.value) return uni.$u.toast('请输入手机号码')
if (!formData.email && isMailbox.value) return uni.$u.toast('请输入邮箱')
if (!formData.email) return uni.$u.toast('请输入邮箱')
if (!formData.password) return uni.$u.toast('请输入密码')
if (!formData.password2) return uni.$u.toast('请输入确认密码')
if (formData.password != formData.password2) return uni.$u.toast('两次输入的密码不一致')
if (formData.scene === ForgotPwdSceneEnum.MOBILE) {
await forgotPassword(formData)
} else if (formData.scene === ForgotPwdSceneEnum.MAILBOX) {
await emailForgotPassword(formData)
}
// if (formData.scene === ForgotPwdSceneEnum.MOBILE) {
// await forgotPassword(formData)
// } else if (formData.scene === ForgotPwdSceneEnum.MAILBOX) {
// await emailForgotPassword(formData)
// }
uni.$u.toast('操作成功')
setTimeout(() => {
uni.navigateBack()

View File

@ -22,55 +22,33 @@
</template>
</view>
</view>
<view
class="p-[40rpx]"
:class="{
<view class="p-[40rpx]" :class="{
'mt-[140rpx]': isWeixinLogin
}"
v-if="showOtherWayBtn"
>
}" v-if="showOtherWayBtn">
<u-divider>其他登录方式</u-divider>
<div class="flex justify-around mt-[40rpx] px-[80rpx]">
<div
class="flex flex-col items-center"
v-if="hasWeixinLogin && !isWeixinLogin"
@click="changeLoginWay(LoginWayEnum.WEIXIN)"
>
<div class="flex flex-col items-center" v-if="hasWeixinLogin && !isWeixinLogin"
@click="changeLoginWay(LoginWayEnum.WEIXIN)">
<u-icon name="/static/images/icon/icon_wx.png" :size="80" />
<div class="text-sm mt-[10px]">微信登录</div>
</div>
<div
class="flex flex-col items-center"
v-if="hasMobileLogin && !isMobileLogin"
@click="changeLoginWay(LoginWayEnum.MOBILE)"
>
<div class="flex flex-col items-center" v-if="hasMobileLogin && !isMobileLogin"
@click="changeLoginWay(LoginWayEnum.MOBILE)">
<u-icon name="/static/images/icon/icon_phone.png" :size="80" />
<div class="text-sm mt-[10px]">手机号登录</div>
</div>
<div
class="flex flex-col items-center"
v-if="hasMailboxLogin && !isMailboxLogin"
@click="changeLoginWay(LoginWayEnum.MAILBOX)"
>
<div class="flex flex-col items-center" v-if="hasMailboxLogin && !isMailboxLogin"
@click="changeLoginWay(LoginWayEnum.MAILBOX)">
<u-icon name="/static/images/icon/icon_email.png" :size="80" />
<div class="text-sm mt-[10px]">邮箱登录</div>
</div>
</div>
<!-- <agreement /> -->
</view>
<update-user-info
v-model:show="showLoginPopup"
:logo="websiteConfig?.logo"
:title="websiteConfig?.name"
:userInfo="loginData"
@update="handleUpdateUser"
/>
<bind-mobile
v-model:show="showBindMobilePopup"
:userInfo="loginData"
@success="bindMobileSuccess"
@close="removeWxQuery"
/>
<update-user-info v-model:show="showLoginPopup" :logo="websiteConfig?.logo" :title="websiteConfig?.name"
:userInfo="loginData" @update="handleUpdateUser" />
<bind-mobile v-model:show="showBindMobilePopup" :userInfo="loginData" @success="bindMobileSuccess"
@close="removeWxQuery" />
</view>
</template>
@ -201,7 +179,7 @@ const loginHandle = async () => {
router.switchTab(cache.get(BACK_URL))
}
} else {
router.reLaunch('/pages/index/index')
router.reLaunch('/')
}
cache.remove(BACK_URL)
}
@ -230,7 +208,7 @@ const loginAfter = (() => {
cache.remove(SHARE_ID)
cache.remove(USER_SN)
}
} catch (error) {}
} catch (error) { }
}
const updateUsers = async () => {
if (loginData.value.isNew && !showLoginPopup.value) {
@ -242,7 +220,7 @@ const loginAfter = (() => {
},
{ token: loginData.value.token }
)
} catch (error) {}
} catch (error) { }
} else if (showLoginPopup.value) {
return Promise.reject()
}

View File

@ -1,43 +1,43 @@
import { getUserCenter } from '@/api/user'
import { TOKEN_KEY } from '@/enums/constantEnums'
import { useSharedId } from '@/hooks/useShareMessage'
import { getToken } from '@/utils/auth'
import cache from '@/utils/cache'
import { defineStore } from 'pinia'
import { getUserCenter } from "@/api/user";
import { TOKEN_KEY } from "@/enums/constantEnums";
import { useSharedId } from "@/hooks/useShareMessage";
import { getToken } from "@/utils/auth";
import cache from "@/utils/cache";
import { defineStore } from "pinia";
interface UserSate {
userInfo: Record<string, any>
token: string | null
client: string | null
temToken: string | null
userInfo: Record<string, any>;
token: string | null;
client: string | null;
temToken: string | null;
}
export const useUserStore = defineStore({
id: 'userStore',
id: "userStore",
state: (): UserSate => ({
userInfo: {},
token: getToken() || null,
client: null,
temToken: null
temToken: null,
}),
getters: {
isLogin: (state) => !!state.token
isLogin: (state) => !!state.token,
},
actions: {
async getUser() {
const data = await getUserCenter({
token: this.token
})
this.userInfo = data
token: this.token,
});
this.userInfo = data;
},
login(token: string) {
cache.set(TOKEN_KEY, token)
this.token = token
useSharedId()
cache.set(TOKEN_KEY, token);
this.token = token;
useSharedId();
},
logout() {
this.token = ''
this.userInfo = {}
cache.remove(TOKEN_KEY)
}
}
})
this.token = "";
this.userInfo = {};
cache.remove(TOKEN_KEY);
},
},
});

View File

@ -1,6 +1,20 @@
import { TOKEN_KEY } from '@/enums/cacheEnums'
import cache from './cache'
import { TOKEN_KEY } from "@/enums/cacheEnums";
import cache from "./cache";
import Cookies from "js-cookie";
// 判断是否为企微环境
const isWechatWork = () => {
const ua = navigator.userAgent.toLowerCase();
return ua.includes("micromessenger") && ua.includes("wxwork");
};
export function getToken() {
return cache.get(TOKEN_KEY) || ''
if (isWechatWork()) {
const token = Cookies.get("token");
const obj = { expire: "", value: token };
localStorage.setItem("app_token", JSON.stringify(obj));
return token || "";
} else {
return cache.get(TOKEN_KEY) || "";
}
}

View File

@ -1,69 +1,70 @@
import HttpRequest from './http'
import { merge } from 'lodash-es'
import HttpRequest from "./http";
import { merge } from "lodash-es";
import {
HttpRequestOptions,
RequestHooks,
RequestConfig,
RequestEventStreamConfig,
RequestOptions,
UploadFileOption
} from './type'
import { getToken } from '../auth'
import { RequestCodeEnum, RequestMethodsEnum } from '@/enums/requestEnums'
import { useUserStore } from '@/stores/user'
import { client } from '../client'
import router from '@/router'
import appConfig from '@/config'
UploadFileOption,
} from "./type";
import { getToken } from "../auth";
import { RequestCodeEnum, RequestMethodsEnum } from "@/enums/requestEnums";
import { useUserStore } from "@/stores/user";
import { client } from "../client";
import router from "@/router";
import appConfig from "@/config";
import Cookies from "js-cookie";
export type {
RequestConfig,
RequestEventStreamConfig,
RequestOptions,
UploadFileOption
}
UploadFileOption,
};
const requestHooks: RequestHooks = {
requestInterceptorsHook(options, config) {
const { urlPrefix, baseUrl, withToken } = config
options.header = options.header ?? {}
const { urlPrefix, baseUrl, withToken } = config;
options.header = options.header ?? {};
if (urlPrefix) {
options.url = `${urlPrefix}${options.url}`
options.url = `${urlPrefix}${options.url}`;
}
if (baseUrl) {
options.url = `${baseUrl}${options.url}`
options.url = `${baseUrl}${options.url}`;
}
//#ifndef APP-PLUS
const token = useUserStore().token || null
const token = useUserStore().token || null;
//#endif
//#ifdef APP-PLUS
const token = useUserStore().token || 'null'
const token = useUserStore().token || "null";
//#endif
// 添加token
if (withToken) {
options.header['ai-token'] = options.header.token || token
options.header["ai-token"] = options.header.token || token;
}
// 添加终端类型
options.header['terminal'] = useUserStore().client || client
delete options.header.token
options.header.version = appConfig.version
return options
options.header["terminal"] = useUserStore().client || client;
delete options.header.token;
options.header.version = appConfig.version;
return options;
},
async responseInterceptorsHook(response, config, options) {
const { isTransformResponse, isReturnDefaultResponse, isAuth } = config
const { isTransformResponse, isReturnDefaultResponse, isAuth } = config;
//返回默认响应,当需要获取响应头及其他数据时可使用
if (isReturnDefaultResponse) {
return response
return response;
}
// 是否需要对数据进行处理
if (!isTransformResponse) {
return response.data
return response.data;
}
const { logout } = useUserStore()
const { code, data, msg, show } = response.data as any
const { logout } = useUserStore();
const { code, data, msg, show } = response.data as any;
switch (code) {
case RequestCodeEnum.SUCCESS:
return data
return data;
case RequestCodeEnum.PARAMS_TYPE_ERROR:
case RequestCodeEnum.PARAMS_VALID_ERROR:
case RequestCodeEnum.REQUEST_METHOD_ERROR:
@ -75,40 +76,40 @@ const requestHooks: RequestHooks = {
case RequestCodeEnum.FAILED:
case RequestCodeEnum.SYSTEM_ERROR:
case RequestCodeEnum.DRAW_ERROR:
uni.$u.toast(msg)
return Promise.reject(msg)
uni.$u.toast(msg);
return Promise.reject(msg);
case RequestCodeEnum.REQUEST_404_ERROR:
uni.$u.toast(msg)
return Promise.reject(msg)
uni.$u.toast(msg);
return Promise.reject(msg);
case RequestCodeEnum.TOKEN_INVALID:
logout()
if (isAuth && options.method?.toUpperCase() !== 'GET') {
router.navigateTo({ path: '/pages/login/login' })
logout();
if (isAuth && options.method?.toUpperCase() !== "GET") {
router.navigateTo({ path: "/pages/login/login" });
}
return Promise.reject(msg)
return Promise.reject(msg);
case RequestCodeEnum.TOKEN_EMPTY:
logout()
logout();
if (isAuth && !getToken()) {
router.navigateTo('/pages/login/login')
router.navigateTo("/pages/login/login");
}
return Promise.reject()
return Promise.reject();
default:
return data
return data;
}
},
async responseInterceptorsCatchHook(options, error) {
if (options.method?.toUpperCase() == RequestMethodsEnum.POST) {
uni.$u.toast('请求失败,请重试')
uni.$u.toast("请求失败,请重试");
}
return Promise.reject(error)
}
}
return Promise.reject(error);
},
};
const defaultOptions: HttpRequestOptions = {
requestOptions: {
timeout: appConfig.timeout
timeout: appConfig.timeout,
},
baseUrl: appConfig.baseUrl,
//是否返回默认的响应
@ -124,14 +125,14 @@ const defaultOptions: HttpRequestOptions = {
isAuth: false,
retryCount: 2,
retryTimeout: 1000,
requestHooks: requestHooks
}
requestHooks: requestHooks,
};
function createRequest(opt?: HttpRequestOptions) {
return new HttpRequest(
// 深度合并
merge(defaultOptions, opt || {})
)
);
}
const request = createRequest()
export default request
const request = createRequest();
export default request;

View File

@ -1,42 +1,45 @@
export type RequestOptions = UniApp.RequestOptions
export type RequestOptions = UniApp.RequestOptions;
export type ResponseResult =
| UniApp.RequestSuccessCallbackResult
| UniApp.UploadFileSuccessCallbackResult
export type RequestOptionsResponseError = UniApp.GeneralCallbackResult
export type RequestTask = UniApp.RequestTask
export type UploadFileOption = UniApp.UploadFileOption
| UniApp.UploadFileSuccessCallbackResult;
export type RequestOptionsResponseError = UniApp.GeneralCallbackResult;
export type RequestTask = UniApp.RequestTask;
export type UploadFileOption = UniApp.UploadFileOption;
export interface HttpRequestOptions extends RequestConfig {
requestOptions: Partial<RequestOptions>
requestOptions: Partial<RequestOptions>;
}
export interface RequestConfig {
baseUrl: string
requestHooks: RequestHooks
isReturnDefaultResponse: boolean
isTransformResponse: boolean
urlPrefix: string
ignoreCancel: boolean
withToken: boolean
isAuth: boolean
retryCount: number
retryTimeout: number
hasRetryCount?: number
baseUrl: string;
requestHooks: RequestHooks;
isReturnDefaultResponse: boolean;
isTransformResponse: boolean;
urlPrefix: string;
ignoreCancel: boolean;
withToken: boolean;
isAuth: boolean;
retryCount: number;
retryTimeout: number;
hasRetryCount?: number;
//上传文件独有
onProgress?: (progress: number) => void
onProgress?: (progress: number) => void;
}
export interface RequestEventStreamConfig extends Partial<RequestConfig> {
onstart?: (event: AbortController | UniApp.RequestTask) => void
onmessage?: (value: string) => void
onclose?: () => void
onstart?: (event: AbortController | UniApp.RequestTask) => void;
onmessage?: (value: string) => void;
onclose?: () => void;
}
export interface RequestHooks {
requestInterceptorsHook?(options: RequestOptions, config: RequestConfig): RequestOptions
requestInterceptorsHook?(
options: RequestOptions,
config: RequestConfig
): RequestOptions;
responseInterceptorsHook?(
response: ResponseResult,
config: RequestConfig,
options: RequestOptions
): any
responseInterceptorsCatchHook?(options: RequestOptions, error: any): any
): any;
responseInterceptorsCatchHook?(options: RequestOptions, error: any): any;
}

View File

@ -1,43 +1,61 @@
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
import postcssRemToResponsivePixel from 'postcss-rem-to-responsive-pixel'
import postcssWeappTailwindcssRename from 'weapp-tailwindcss-webpack-plugin/postcss'
import vwt from 'weapp-tailwindcss-webpack-plugin/vite'
import uniRouter from 'unplugin-uni-router/vite'
import { defineConfig, loadEnv } from "vite";
import uni from "@dcloudio/vite-plugin-uni";
import tailwindcss from "tailwindcss";
import autoprefixer from "autoprefixer";
import postcssRemToResponsivePixel from "postcss-rem-to-responsive-pixel";
import postcssWeappTailwindcssRename from "weapp-tailwindcss-webpack-plugin/postcss";
import vwt from "weapp-tailwindcss-webpack-plugin/vite";
import uniRouter from "unplugin-uni-router/vite";
const isH5 = process.env.UNI_PLATFORM === 'h5'
const isApp = process.env.UNI_PLATFORM === 'app'
const weappTailwindcssDisabled = isH5 || isApp
const isH5 = process.env.UNI_PLATFORM === "h5";
const isApp = process.env.UNI_PLATFORM === "app";
const weappTailwindcssDisabled = isH5 || isApp;
const postcssPlugin = [autoprefixer(), tailwindcss()]
const postcssPlugin = [autoprefixer(), tailwindcss()];
if (!weappTailwindcssDisabled) {
postcssPlugin.push(
postcssRemToResponsivePixel({
rootValue: 32,
propList: ['*'],
transformUnit: 'rpx'
propList: ["*"],
transformUnit: "rpx",
})
)
postcssPlugin.push(postcssWeappTailwindcssRename())
);
postcssPlugin.push(postcssWeappTailwindcssRename());
}
// https://vitejs.dev/config/
export default defineConfig({
export default defineConfig(({ command, mode }) => {
console.log("mode:", mode);
const env = loadEnv(mode, process.cwd(), "");
return {
plugins: [
uni(),
uniRouter({
includes: ['style']
includes: ["style"],
}),
weappTailwindcssDisabled ? undefined : vwt()
weappTailwindcssDisabled ? undefined : vwt(),
],
css: {
postcss: {
plugins: postcssPlugin
}
plugins: postcssPlugin,
},
},
server: {
port: 8991
port: 8991,
},
base: mode != "dev" ? env.VITE_CDN_DIR : "./",
build: {
assetsDir: "static", // 静态资源存放目录(默认是 assets
rollupOptions: {
output: {
// 代码分割配置
manualChunks: (id) => {
if (id.includes("node_modules")) {
return "vendor";
}
})
},
},
},
},
};
});