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_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 *.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files # 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": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei", "build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union", "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" "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
}, },
"dependencies": { "dependencies": {

View File

@ -9,6 +9,7 @@ import { SHARE_ID, USER_SN } from './enums/constantEnums'
import { strToParams } from './utils/util' import { strToParams } from './utils/util'
import cache from './utils/cache' import cache from './utils/cache'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import { client } from '@/utils/client'
const appStore = useAppStore() const appStore = useAppStore()
const { getUser } = useUserStore() const { getUser } = useUserStore()
@ -73,13 +74,11 @@ const setLocalStorage = async () => {
// cookie // cookie
const redirect = location.href const redirect = location.href
Cookies.set('redirect', redirect) 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 return
} }
} else { } else {
const obj = { expire: "", value: cookiesToken } const obj = { expire: "", value: cookiesToken }
console.log('obj', obj);
console.log('写入前 token', token);
localStorage.setItem("app_token", JSON.stringify(obj)); 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) { export function getUserCenter(header?: any) {
return request.get({ url: '/user/center', header }) return request.get({ url: "/user/center", header });
} }
// 个人信息 // 个人信息
export function getUserInfo() { export function getUserInfo() {
return request.get({ url: '/user/info' }, { isAuth: true }) return request.get({ url: "/user/info" }, { isAuth: true });
} }
// 个人编辑 // 个人编辑
export function userEdit(data: any) { 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) { 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) { 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) { 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) { export function mnpAuthBind(data: any) {
return request.post({ url: '/user/bindMnp', data }) return request.post({ url: "/user/bindMnp", data });
} }
// 绑定公众号 // 绑定公众号
export function oaAuthBind(data: any) { 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) { 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) { export function accountLog(data: any) {
return request.get({ url: '/logs/userMoney', data }) return request.get({ url: "/logs/userMoney", data });
} }
//一键反馈 //一键反馈
export function feedbackPost(data: any) { export function feedbackPost(data: any) {
return request.post({ url: '/feedback/add', data }) return request.post({ url: "/feedback/add", data });
} }
//注销账号 //注销账号
export function cancelled(data?: any) { 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"> <view class="floating-menu">
<!-- #endif --> <!-- #endif -->
<movable-area class="movable-area" :scale-area="false"> <movable-area class="movable-area" :scale-area="false">
<movable-view <movable-view class="movable-view" :class="!menuData.isRemove ? 'animation-info' : ''"
class="movable-view" style="pointer-events: auto" @touchstart="touchstart" @touchend="touchend" @change="onChange"
:class="!menuData.isRemove ? 'animation-info' : ''" direction="all" inertia="true" :x="menuData.x" :y="menuData.y" :disabled="disabled"
style="pointer-events: auto" :out-of-bounds="true" :damping="200" :friction="100">
@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"> <view class="item-main" @click="openMenu">
<u-icon :name="UnfoldIcon" size="36" /> <u-icon :name="UnfoldIcon" size="36" />
</view> </view>
<view <view v-if="menuData.showBtn" class="menu-box" :class="menuData.isLeft ? 'leftOut1' : 'rightOut1'">
v-if="menuData.showBtn" <view v-for="(item, index) in list" :key="index" @click="onJump(item)" class="item-main">
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" /> <u-icon :name="item.icon" size="36" />
</view> </view>
</view> </view>
@ -63,7 +42,7 @@ const props = withDefaults(
list: [ list: [
{ {
icon: HomeIcon, icon: HomeIcon,
pages: '/pages/index/index' pages: '/pages/ai_creation/ai_creation'
}, },
{ {
icon: UserIcon, icon: UserIcon,
@ -201,10 +180,12 @@ const onJump = (item: any) => {
box-shadow: 0 4rpx 12rpx 0 rgba(0, 0, 0, 0.3); box-shadow: 0 4rpx 12rpx 0 rgba(0, 0, 0, 0.3);
border-radius: 50rpx; border-radius: 50rpx;
} }
.leftOut1 { .leftOut1 {
left: 110rpx; left: 110rpx;
animation: leftOut 0.4s; animation: leftOut 0.4s;
} }
.rightOut1 { .rightOut1 {
right: 110rpx; right: 110rpx;
animation: rightOut 0.4s; 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>) { export function useLockFn(fn: (...args: any[]) => Promise<any>) {
const isLock = ref(false) const isLock = ref(false);
const lockFn = async (...args: any[]) => { const lockFn = async (...args: any[]) => {
if (isLock.value) return if (isLock.value) return;
isLock.value = true isLock.value = true;
try { try {
const res = await fn(...args) const res = await fn(...args);
isLock.value = false isLock.value = false;
return res return res;
} catch (e) { } catch (e) {
isLock.value = false isLock.value = false;
throw e throw e;
}
} }
};
return { return {
isLock, isLock,
lockFn lockFn,
} };
} }

View File

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

View File

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

View File

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

View File

@ -148,15 +148,17 @@ const sendSms = async () => {
const handleConfirm = async () => { const handleConfirm = async () => {
if (!formData.mobile && isMobile.value) return uni.$u.toast('请输入手机号码') 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.password) return uni.$u.toast('请输入密码')
if (!formData.password2) return uni.$u.toast('请输入确认密码') if (!formData.password2) return uni.$u.toast('请输入确认密码')
if (formData.password != 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) await emailForgotPassword(formData)
} // if (formData.scene === ForgotPwdSceneEnum.MOBILE) {
// await forgotPassword(formData)
// } else if (formData.scene === ForgotPwdSceneEnum.MAILBOX) {
// await emailForgotPassword(formData)
// }
uni.$u.toast('操作成功') uni.$u.toast('操作成功')
setTimeout(() => { setTimeout(() => {
uni.navigateBack() uni.navigateBack()

View File

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

View File

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

View File

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

View File

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

View File

@ -1,43 +1,61 @@
import { defineConfig } from 'vite' import { defineConfig, loadEnv } from "vite";
import uni from '@dcloudio/vite-plugin-uni' import uni from "@dcloudio/vite-plugin-uni";
import tailwindcss from 'tailwindcss' import tailwindcss from "tailwindcss";
import autoprefixer from 'autoprefixer' import autoprefixer from "autoprefixer";
import postcssRemToResponsivePixel from 'postcss-rem-to-responsive-pixel' import postcssRemToResponsivePixel from "postcss-rem-to-responsive-pixel";
import postcssWeappTailwindcssRename from 'weapp-tailwindcss-webpack-plugin/postcss' import postcssWeappTailwindcssRename from "weapp-tailwindcss-webpack-plugin/postcss";
import vwt from 'weapp-tailwindcss-webpack-plugin/vite' import vwt from "weapp-tailwindcss-webpack-plugin/vite";
import uniRouter from 'unplugin-uni-router/vite' import uniRouter from "unplugin-uni-router/vite";
const isH5 = process.env.UNI_PLATFORM === 'h5' const isH5 = process.env.UNI_PLATFORM === "h5";
const isApp = process.env.UNI_PLATFORM === 'app' const isApp = process.env.UNI_PLATFORM === "app";
const weappTailwindcssDisabled = isH5 || isApp const weappTailwindcssDisabled = isH5 || isApp;
const postcssPlugin = [autoprefixer(), tailwindcss()] const postcssPlugin = [autoprefixer(), tailwindcss()];
if (!weappTailwindcssDisabled) { if (!weappTailwindcssDisabled) {
postcssPlugin.push( postcssPlugin.push(
postcssRemToResponsivePixel({ postcssRemToResponsivePixel({
rootValue: 32, rootValue: 32,
propList: ['*'], propList: ["*"],
transformUnit: 'rpx' transformUnit: "rpx",
}) })
) );
postcssPlugin.push(postcssWeappTailwindcssRename()) postcssPlugin.push(postcssWeappTailwindcssRename());
} }
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig(({ command, mode }) => {
console.log("mode:", mode);
const env = loadEnv(mode, process.cwd(), "");
return {
plugins: [ plugins: [
uni(), uni(),
uniRouter({ uniRouter({
includes: ['style'] includes: ["style"],
}), }),
weappTailwindcssDisabled ? undefined : vwt() weappTailwindcssDisabled ? undefined : vwt(),
], ],
css: { css: {
postcss: { postcss: {
plugins: postcssPlugin plugins: postcssPlugin,
} },
}, },
server: { 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";
} }
}) },
},
},
},
};
});