fix:慢慢改造

This commit is contained in:
MJ 2025-08-02 02:47:09 +08:00
parent 6460344c7a
commit 012c7c8c17
46 changed files with 2240 additions and 1446 deletions

1
.env
View File

@ -1,4 +1,3 @@
VITE_HOST = https://pi.xuexiaole.com
# VITE_HOST = http://192.168.0.103
VITE_OSS_HOST = https://xuexiaole-1313840333.cos.ap-guangzhou.myqcloud.com/xuexiaoleClient
VITE_WS_URL = wss://pi.xuexiaole.com/ws/device

View File

@ -1,3 +1,3 @@
VITE_HOST = https://test.pi.xuexiaole.com
VITE_HOST = http://127.0.0.1:9053
VITE_OSS_HOST = https://xuexiaole-1313840333.cos.ap-guangzhou.myqcloud.com/xuexiaoleClient
VITE_WS_URL = wss://test.pi.xuexiaole.com/ws/device

View File

@ -1,3 +1,3 @@
VITE_HOST = https://test.pi.xuexiaole.com
VITE_HOST = http://test.xuexiaole.com:8053
VITE_OSS_HOST = https://xuexiaole-1313840333.cos.ap-guangzhou.myqcloud.com/xuexiaoleClient
VITE_WS_URL = wss://test.pi.xuexiaole.com/ws/device

2
.gitignore vendored
View File

@ -6,6 +6,8 @@ yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.temp
*.gz
node_modules
.DS_Store

View File

@ -1,13 +1,14 @@
module.exports = {
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: true,
singleQuote: true,
jsxSingleQuote: true,
bracketSpacing: true,
bracketSameLine: false,
arrowParens: 'avoid',
vueIndentScriptAndStyle: false,
endOfLine: 'lf',
printWidth: 100,
tabWidth: 2,
useTabs: false,
semi: false,
singleQuote: true,
jsxSingleQuote: true,
bracketSpacing: true,
bracketSameLine: false,
arrowParens: 'avoid',
trailingComma: 'all',
vueIndentScriptAndStyle: false,
endOfLine: 'lf',
};

View File

@ -47,5 +47,6 @@
"src/uni_modules/uni-popup/components/uni-popup/i18n",
"src/uni_modules/uni-search-bar/components/uni-search-bar/i18n",
"src/uni_modules/z-paging/components/z-paging/i18n"
]
],
"cSpell.words": ["xuexiaole"]
}

Binary file not shown.

View File

@ -1,12 +1,13 @@
{
"name": "xuexiaole-client",
"name": "xuexiaole-mobile",
"version": "0.1.0",
"scripts": {
"dev:app": "uni -p app",
"dev:app-android": "uni -p app-android",
"dev:app-ios": "uni -p app-ios",
"dev:custom": "uni -p",
"dev:h5": "uni -p h5-test",
"dev:h5": "uni --mode dev",
"dev:h5-mp": "uni --mode mp",
"dev:h5:ssr": "uni --ssr",
"dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu",
@ -56,16 +57,17 @@
"@dcloudio/uni-mp-toutiao": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-weixin": "3.0.0-3081220230817001",
"@dcloudio/uni-quickapp-webview": "3.0.0-3081220230817001",
"@vueuse/core": "^10.11.0",
"code-inspector-plugin": "^0.10.1",
"dayjs": "^1.11.13",
"echarts": "^5.5.1",
"lint-staged": "^15.0.1",
"pinia": "^2.0.36",
"qs": "^6.14.0",
"sass": "^1.72.0",
"unplugin-vue-define-options": "^1.4.2",
"vue": "^3.3.4",
"vue-i18n": "^9.1.9",
"@vueuse/core": "^10.11.0",
"vue-qrcode-reader": "^5.5.7",
"weixin-js-sdk": "^1.6.5"
},
@ -102,25 +104,5 @@
"prettier --write",
"eslint --fix"
]
},
"uni-app": {
"scripts": {
"h5-test": {
"title": "h5-test",
"env": {
"UNI_PLATFORM": "h5",
"VITE_HOST": "https://test.pi.xuexiaole.com",
"VITE_WS_URL": "wss://test.pi.xuexiaole.com/ws/device"
}
},
"h5-prod": {
"title": "h5-prod",
"env": {
"UNI_PLATFORM": "h5",
"VITE_HOST": "https://pi.xuexiaole.com",
"VITE_WS_URL": "wss://pi.xuexiaole.com/ws/device"
}
}
}
}
}

498
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,17 @@
<script setup lang="ts">
import { onMounted, nextTick } from 'vue';
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app';
import { onMounted, nextTick } from 'vue'
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
import { parseUrlParams } from '@/utils/tool'
onLaunch(() => {
console.log('App Launch');
});
console.log('App Launch')
})
onShow(() => {
console.log('App Show');
});
console.log('App Show')
})
onHide(() => {
console.log('App Hide');
});
console.log('App Hide')
})
</script>
<style lang="scss">
page {

View File

@ -4,85 +4,88 @@ import $req from './request';
* @param data
*/
export const getBindPhoneTypeApi = data => {
$req({
method: 'post',
url: '/xcx/login/getBindRelationList',
data,
});
$req({
method: 'post',
url: '/xcx/login/getBindRelationList',
data,
});
};
/**
*
* @param data
*/
export const getAdminTypeByPhoneApi = (params: anyObj) =>
$req({
method: 'get',
url: '/sysUser/getAdminTypeByPhone',
params,
});
$req({
method: 'get',
url: '/sysUser/getAdminTypeByPhone',
params,
});
/**
*
* @param data
*/
export const sendCodeMessageApi = data =>
$req({
method: 'post',
url: `/sms/sendMessage?phoneNumbers=${data}`,
});
$req({
method: 'post',
url: `/sms/sendMessage?phoneNumbers=${data}`,
});
/**
*
* @param data
*/
export const smsLoginApi = data =>
$req({
method: 'post',
url: '/smsLogin',
data,
});
$req({
method: 'post',
url: '/smsLogin',
data: {
...data,
clientType: 'MOBILE',
},
});
/**
*
* @param data
*/
export const getUserInfoApi = () =>
$req({
method: 'get',
url: '/sysUser/selectUser',
});
$req({
method: 'get',
url: '/sysUser/selectUser',
});
/**
*
* @param data
*/
export const updateUserInfoApi = (data: anyObj) =>
$req({
method: 'post',
url: '/sysUser/updateInfo',
data,
});
$req({
method: 'post',
url: '/sysUser/updateInfo',
data,
});
/**
*
* @param data
*/
export const bindAuthInfoApi = data =>
$req({
method: 'post',
url: '/wechatPublic/bindAuthInfo',
data,
});
$req({
method: 'post',
url: '/wechatPublic/bindAuthInfo',
data,
});
/**
*
* @param data
*/
export const getAuthUrlApi = () =>
$req({
method: 'get',
url: '/wechatPublic/getAuthUrl',
});
$req({
method: 'get',
url: '/wechatPublic/getAuthUrl',
});
// 退出登录
export const logout = () =>
$req({
url: '/logout',
});
$req({
url: '/logout',
});

View File

@ -1,14 +1,15 @@
import $req from '../request';
import { storeToRefs } from 'pinia';
import { user } from '@/store';
import { getCache } from '@/utils';
import $req from '../request'
import { storeToRefs } from 'pinia'
import { user } from '@/store'
import { getCache } from '@/utils'
import db from '@/utils/db'
// 课表日历
export const getScheduleList = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: '/phone/inspectorTeacher/getCourseTableById',
data,
});
})
// 查询指定日期学生数据
export const getCourseDate = (data?: Record<string, any>): Promise<any> =>
@ -18,28 +19,28 @@ export const getCourseDate = (data?: Record<string, any>): Promise<any> =>
`/phone/inspectorTeacher/getCourseTabletStudentVoByTime` +
`${data.date ? `?courseDate=${data.date}` : ''}`,
// data,
});
})
// 开始督学
export const startInpector = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'post',
url: `/phone/inspectorTeacher/startInspector?courseDate=${data.courseDate}`,
});
})
// 结束督学
export const endInpector = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'post',
url: `/phone/inspectorTeacher/endInspector?courseDate=${data.courseDate}`,
});
})
// 督学实况
export const condition = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'post',
url: `/phone/inspectorTeacher/inspector_real?courseDate=${data.courseDate}`,
});
})
// 获取学员课表日历
export const getCourseData = (data?: Record<string, any>): Promise<any> =>
@ -47,33 +48,33 @@ export const getCourseData = (data?: Record<string, any>): Promise<any> =>
method: 'get',
url: `/phone/inspectorTeacher/getStuCourseTable?userId=${data.id}`,
// data,
});
})
// 获取学科
export const getSubject = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/subject/list/${data.gradeId}`,
});
})
// 获取学科教材
export const getBooks = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/userTextBook/list?gradeId=${data.gradeId}&subjectId=${data.subjectId}&userId=${data.userId}&current=${data.current}`,
});
})
// 获取教材章节
export const getChaper = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/subjectChapter/tree?textBookId=${data.textBookId}`,
});
})
// 获取教材章节知识点
export const getKnowledge = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/subjectKnowledge/tree?chapterId=${data.chapterId}`,
});
})
// 发布计划
export const publishPlan = (data?: Record<string, any>): Promise<any> =>
@ -81,25 +82,25 @@ export const publishPlan = (data?: Record<string, any>): Promise<any> =>
method: 'post',
url: `/phone/inspectorTeacher/publishPlan`,
data,
});
})
// 获取学员计划
export const getStuPlan = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/phone/inspectorTeacher/getStuPlanByDate?userId=${data.userId}&courseDate=${data.courseDate}`,
});
})
// 获取督学师信息
export const getUserInfo = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/phone/inspectorTeacher/getCurrentTeacher`,
});
})
// 文件上传
export const uploadFile = async (file): Promise<any> => {
const { token } = storeToRefs(user());
const { token } = storeToRefs(user())
const mergerToken = token.value || getCache('token');
const mergerToken = token.value || db.get('token')
const data = await uni.uploadFile({
url: `/api/main/sysFileInfo/tenUploadAll`, // ${import.meta.env.VITE_HOST}
@ -109,9 +110,9 @@ export const uploadFile = async (file): Promise<any> => {
// 'content-type': 'multipart/form-data',
Authorization: mergerToken ? `Bearer ${mergerToken}` : token,
},
});
return JSON.parse(data.data);
};
})
return JSON.parse(data.data)
}
// 完善督学师资料 /phone/inspectorTeacher/updateTeacherInfo
export const updateTeacherInfo = (data?: Record<string, any>): Promise<any> =>
@ -119,25 +120,25 @@ export const updateTeacherInfo = (data?: Record<string, any>): Promise<any> =>
method: 'post',
url: `/phone/inspectorTeacher/updateTeacherInfo`,
data,
});
})
// 沟通列表
export const getTalkList = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/phone/inspectorTeacher/inspectorTalkListPage?current=${data.current}`,
});
})
// 沟通详情
export const getTalkDetails = (data?: Record<string, any>): Promise<any> => {
const param = data.inspectorTalkRecordId
? `?inspectorTalkRecordId=${data.inspectorTalkRecordId}&userId=${data.userId}`
: `?userId=${data.userId}`;
: `?userId=${data.userId}`
return $req({
method: 'get',
url: `/phone/inspectorTeacher/studentInspectorTalkPage${param}`,
});
};
})
}
// 消息存储
export const saveTalk = (data?: Record<string, any>): Promise<any> =>
@ -145,7 +146,7 @@ export const saveTalk = (data?: Record<string, any>): Promise<any> =>
method: 'post',
url: `/inspectorStudent/sendInspectorTalkRecord`,
data,
});
})
// 验证码校验
export const validCode = (data?: Record<string, any>): Promise<any> =>
@ -153,13 +154,13 @@ export const validCode = (data?: Record<string, any>): Promise<any> =>
method: 'post',
url: `/sms/validateMessage?phoneNumbers=${data.phone}&code=${data.code}`,
data,
});
})
// 获取我的未读信息
export const getUnreadCount = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/phone/inspectorTeacher/myUnreadCount`,
});
})
// 消息标记为已读
export const readMsg = (data?: Record<string, any>): Promise<any> =>
@ -167,31 +168,31 @@ export const readMsg = (data?: Record<string, any>): Promise<any> =>
method: 'post',
url: `/inspectorStudent/readTalkRecord`,
data,
});
})
// 督学师是否已完善资料
export const needPerfectInfo = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/phone/inspectorTeacher/is_perfect`,
});
})
// 学生是否可以进行精准学判断
export const getPrecisionFlag = (data?: Record<string, any>): Promise<any> =>
$req({
method: 'get',
url: `/userTrainTitle/airPrecisionFlag?subjectId=${data.subjectId}&userId=${data.userId}`,
});
})
export const getKnowledgeFlag = (knowledgeId: string): Promise<boolean> => {
return $req({
method: 'get',
url: `/subjectKnowledge/titleFlag?id=${knowledgeId}`,
});
})
}
export const getKnowledgeVideo = (chapterId: string | number): Promise<any> => {
return $req({
method: 'get',
url: `/subjectChapterVideo/list?chapterId=${chapterId}`,
});
})
}

View File

@ -1,78 +1,73 @@
import $req from '../request';
import $req from '../request'
import { request } from '../request/request'
/**
*
* @param params
*/
export const getParentBindChildApi = (params: anyObj) =>
$req({
method: 'get',
url: '/parentBindChild/list',
params,
});
$req({
method: 'get',
url: '/parentBindChild/list',
params,
})
/**
*
* @param params
*/
export const getParentBindDeviceApi = (params: anyObj) =>
$req({
method: 'get',
url: '/parentBindDevice/list',
params,
});
export const getParentBindDeviceApi = async (params: anyObj) =>
await request.get<any>('/parentBindDevice/list', params)
/**
* -
* @param params
*/
export const parentBindChildApi = (id: string) =>
$req({
method: 'get',
url: `/parentBindChild/${id}`,
});
$req({
method: 'get',
url: `/parentBindChild/${id}`,
})
/**
* -
* @param params
*/
export const childUnBoundParentApi = (data: anyObj) =>
$req({
method: 'post',
url: '/parentBindChild/unBound',
data,
});
$req({
method: 'post',
url: '/parentBindChild/unBound',
data,
})
/**
* -
* @param params
*/
export const parentUnBoundDeviceApi = (data: anyObj) =>
$req({
method: 'post',
url: '/parentBindDevice/unBound',
data,
});
$req({
method: 'post',
url: '/parentBindDevice/unBound',
data,
})
/**
* -
* @param params
*/
export const parentDeviceCurrentLoginApi = (id: string) =>
$req({
method: 'get',
url: `/parentBindDevice/${id}`,
});
export const parentDeviceCurrentLoginApi = async (id: string) =>
await request.get<any>(`/parentBindDevice/${id}`)
/**
* -
* @param params
*/
export const applyBindInfoListApi = () =>
$req({
method: 'get',
url: '/parentBind/applyInfoList',
});
$req({
method: 'get',
url: '/parentBind/applyInfoList',
})
/**
* -
* @param params
*/
export const userInfoPermitApi = () =>
$req({
method: 'get',
url: '/parentBind/applyInfoPermit',
});
$req({
method: 'get',
url: '/parentBind/applyInfoPermit',
})

View File

@ -1,44 +1,44 @@
import { user } from '@/store';
import { storeToRefs } from 'pinia';
import { getCache } from '@/utils';
import { user } from '@/store'
import { storeToRefs } from 'pinia'
import { getCache } from '@/utils'
import db from '@/utils/db'
const CONFIG = {
// host: import.meta.env.VITE_HOST || '',
// baseURL: 'http://127.0.0.1:9053/api/main',
baseURL: '/api/main',
baseURL: `${import.meta.env.VITE_HOST}/api/main`,
// baseURL: '/api/main',
timeout: 60000,
method: 'GET',
};
}
export class HttpError extends Error {
data: any;
data: any
constructor(message: string, data: Record<string, any>) {
super(message);
this.data = data;
super(message)
this.data = data
}
}
const request = async (config: Record<string, any>): Promise<any> => {
const networkType = await uni.getNetworkType();
const networkType = await uni.getNetworkType()
if (networkType.networkType === 'none') {
uni.showModal({
content: '暂无网络,请恢复网络后使用',
confirmText: '知道了',
showCancel: false,
confirmColor: '#ffe60f',
});
})
return Promise.reject(
new HttpError('暂无网络,请恢复网络后使用', {
code: '-1',
}),
);
)
}
return new Promise((resolve, reject) => {
const { clear } = user();
const { token } = storeToRefs(user());
const mergerToken = token.value || getCache('token');
const method = (config.method || CONFIG.method).toUpperCase();
const { clear } = user()
const { token } = storeToRefs(user())
const mergerToken = token.value || db.get('token')
const method = (config.method || CONFIG.method).toUpperCase()
uni.request({
method,
@ -53,41 +53,41 @@ const request = async (config: Record<string, any>): Promise<any> => {
complete(res: anyObj) {
if (res.statusCode === 200) {
if (res.data.code === 200) {
return resolve(res.data);
return resolve(res.data)
} else {
if (!config.showToast) {
uni.showToast({
title: res.data?.message,
icon: 'none',
duration: 3000,
});
})
}
return reject(new HttpError(res.data?.message, res.data));
return reject(new HttpError(res.data?.message, res.data))
}
} else {
res.href = (config.baseURL || CONFIG.baseURL) + config.url;
res.href = (config.baseURL || CONFIG.baseURL) + config.url
if (res.statusCode === 401) {
clear();
clear()
uni.reLaunch({
url: '/pages/login/index',
});
})
} else {
uni.showToast({
icon: 'none',
title:
res.statusCode === 500 ? '服务异常' : res?.data?.message || '服务异常,请稍后重试',
});
})
}
return reject(
new HttpError(res.data?.message, {
code: res.statusCode,
data: res.data,
}),
);
)
}
},
});
});
};
})
})
}
export default request;
export default request

29
src/api/request/config.ts Normal file
View File

@ -0,0 +1,29 @@
// 基础配置
export const BASE_URL = `${import.meta.env.VITE_HOST}/api/main` // 基础URL
export const REQUEST_TIMEOUT = 10000 // 10秒超时
// 状态码
export const HTTP_STATUS = {
SUCCESS: 200,
CREATED: 201,
ACCEPTED: 202,
CLIENT_ERROR: 400,
AUTHENTICATE: 401,
FORBIDDEN: 403,
NOT_FOUND: 404,
SERVER_ERROR: 500,
BAD_GATEWAY: 502,
SERVICE_UNAVAILABLE: 503,
GATEWAY_TIMEOUT: 504,
}
// 错误信息
export const ERROR_MSG = {
NETWORK_ERROR: '网络异常,请检查网络连接',
TIMEOUT_ERROR: '请求超时,请稍后重试',
SERVER_ERROR: '服务器异常,请稍后重试',
AUTH_ERROR: '登录状态已过期,请重新登录',
FORBIDDEN_ERROR: '没有权限访问该资源',
NOT_FOUND_ERROR: '请求的资源不存在',
DEFAULT_ERROR: '请求失败,请稍后重试',
}

View File

@ -0,0 +1,98 @@
import { type RequestOptions, type ResponseData, type ErrorResponse } from './types'
import { HTTP_STATUS, ERROR_MSG } from './config'
import router from '@/router/router'
import db from '@/utils/db'
import toast from '@/utils/toast'
// 请求拦截器
export const requestInterceptor = async (options: RequestOptions): Promise<RequestOptions> => {
// 设置请求头
const header: any = {
...options?.header,
}
// 获取token
const token = db.get('token')
// 如果有token添加到请求头
if (token) {
header['Authorization'] = `Bearer ${token}`
}
return {
...options,
header,
}
}
// 响应拦截器
export const responseInterceptor = async <T>(
response: ResponseData<T>,
): Promise<ResponseData<T>> => {
const { statusCode, data } = response as any
console.log('response', response)
// 处理成功响应
if (statusCode === HTTP_STATUS.SUCCESS) {
if (data.code === 200) return response
throw {
statusCode,
errMsg: data.data,
}
} else {
throw {
statusCode,
}
}
}
// 错误拦截器
export const errorInterceptor = (error: any): Promise<ErrorResponse> => {
let message
const { statusCode, errMsg } = error
let toLogin = false
if (statusCode === HTTP_STATUS.SUCCESS) {
message = errMsg
} else {
// 处理特定状态码
switch (error.statusCode) {
case HTTP_STATUS.AUTHENTICATE:
toLogin = true
message = ERROR_MSG.AUTH_ERROR
break
case HTTP_STATUS.FORBIDDEN:
toLogin = true
message = ERROR_MSG.FORBIDDEN_ERROR
break
case HTTP_STATUS.NOT_FOUND:
message = ERROR_MSG.NOT_FOUND_ERROR
break
case HTTP_STATUS.SERVER_ERROR:
case HTTP_STATUS.BAD_GATEWAY:
case HTTP_STATUS.SERVICE_UNAVAILABLE:
case HTTP_STATUS.GATEWAY_TIMEOUT:
message = ERROR_MSG.SERVER_ERROR
break
default:
message = ERROR_MSG.DEFAULT_ERROR
break
}
}
// 显示错误提示
if (message) {
toast.error(message)
if (toLogin) {
router.toLogin()
}
}
return Promise.reject({
code: -1,
message,
data: error,
})
}

View File

@ -0,0 +1,75 @@
import { type RequestOptions, type ResponseData } from './types'
import { BASE_URL, REQUEST_TIMEOUT } from './config'
import { requestInterceptor, responseInterceptor, errorInterceptor } from './interceptor'
import obj from '@/utils/obj'
class HttpRequest {
private baseURL: string
private timeout: number
constructor() {
this.baseURL = BASE_URL
this.timeout = REQUEST_TIMEOUT
}
public async http<T>(options: RequestOptions): Promise<T> {
try {
obj.clearNullProps(options.data)
const interceptedOptions = await requestInterceptor(options)
// URL处理
let url = this.baseURL + interceptedOptions.url
const response = (await uni.request({
...interceptedOptions,
url,
timeout: this.timeout,
})) as unknown as ResponseData<T>
return (await responseInterceptor(response)).data
} catch (error) {
return errorInterceptor(error) as any
}
}
public async get<T>(url: string, data?: any, options: Partial<RequestOptions> = {}): Promise<T> {
return this.http<T>({
url,
data,
method: 'GET',
...options,
})
}
// 默认是json格式
public async post<T>(url: string, data?: any, options: Partial<RequestOptions> = {}): Promise<T> {
return this.http<T>({
url,
data,
method: 'POST',
...options,
header: {
'Content-Type': 'application/json',
...options.header,
},
})
}
// 表单格式
public async postForm<T>(
url: string,
data?: any,
options: Partial<RequestOptions> = {},
): Promise<T> {
return this.http<T>({
url,
data,
method: 'POST',
...options,
header: {
'Content-Type': 'application/x-www-form-urlencoded',
...options.header,
},
})
}
}
export const request = new HttpRequest()

28
src/api/request/types.ts Normal file
View File

@ -0,0 +1,28 @@
// 请求方法类型
export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE'
// 请求配置接口
export interface RequestOptions {
url: string
method: Method
data?: any
header?: Record<string, string>
timeout?: number
dataType?: string
responseType?: string
}
// 响应数据接口
export interface ResponseData<T = any> {
data: T
statusCode: number
header: Record<string, string>
errMsg?: string
}
// 错误响应接口
export interface ErrorResponse {
code: number
message: string
data?: any
}

View File

@ -22,91 +22,122 @@
</template>
<script setup lang="ts">
import { onShow } from '@dcloudio/uni-app';
import { onMounted, reactive, ref } from 'vue';
import { bindApplyStore } from '@/store';
import { onShow } from '@dcloudio/uni-app'
import { onMounted, reactive, ref } from 'vue'
import { bindApplyStore } from '@/store'
import { getCache } from '@/utils';
import { getCache } from '@/utils'
import db from '@/utils/db'
const props = withDefaults(
defineProps<{
selectedIndex: number;
selectedIndex: number
}>(),
{ selectedIndex: 0 },
);
const { getApplyBindInfoList } = bindApplyStore();
)
const { getApplyBindInfoList } = bindApplyStore()
const currentIndex = ref(0);
const list = ref([]);
const color = ref<string>('#8E8D9D');
const selectedColor = ref<string>('#625EFF');
const notice = ref(false);
const currentIndex = ref(0)
const list = ref([])
const color = ref<string>('#8E8D9D')
const selectedColor = ref<string>('#625EFF')
const notice = ref(false)
function switchTab(item, index) {
currentIndex.value = index;
let url = item.pagePath;
uni.redirectTo({ url: url });
currentIndex.value = index
let url = item.pagePath
uni.redirectTo({ url: url })
}
onMounted(async () => {
currentIndex.value = props.selectedIndex;
let adminType = getCache('userInfo').adminType;
if (adminType === 16) {
//
await getApplyBindInfoList();
notice.value = getCache('applyBindMsg');
list.value = [
{
pagePath: '/pages/home/index',
iconPath: '/static/tabBar/homeno.png',
selectedIconPath: '/static/tabBar/home.png',
text: '首页',
},
{
pagePath: '/pages/academicReport/index',
iconPath: '/static/tabBar/studyReportNo.png',
selectedIconPath: '/static/tabBar/studyReport.png',
text: '学情报告',
},
{
pagePath: '/pages/applicationManagement/index',
iconPath: '/static/tabBar/applicationNo.png',
selectedIconPath: '/static/tabBar/application.png',
text: '应用管控',
},
{
pagePath: '/pages/mine/index',
iconPath: '/static/tabBar/mineno.png',
selectedIconPath: '/static/tabBar/mine.png',
text: '我的',
},
];
} else if (adminType === 6) {
//
uni.reLaunch({
url: '/pages/inspector/schedule/index',
});
list.value = [
{
pagePath: '/pages/inspector/schedule/index',
iconPath: '/static/tabBar/scheduleNo.png',
selectedIconPath: '/static/tabBar/schedule.png',
text: '课表',
},
{
pagePath: '/pages/inspector/student/index',
iconPath: '/static/tabBar/studentNo.png',
selectedIconPath: '/static/tabBar/student.png',
text: '学员',
},
{
pagePath: '/pages/inspector/mine/index',
iconPath: '/static/tabBar/mineno.png',
selectedIconPath: '/static/tabBar/mine.png',
text: '我的',
},
];
}
});
currentIndex.value = props.selectedIndex
//
await getApplyBindInfoList()
notice.value = db.get('applyBindMsg')
list.value = [
{
pagePath: '/pages/home/index',
iconPath: '/static/tabBar/homeno.png',
selectedIconPath: '/static/tabBar/home.png',
text: '首页',
},
{
pagePath: '/pages/academicReport/index',
iconPath: '/static/tabBar/studyReportNo.png',
selectedIconPath: '/static/tabBar/studyReport.png',
text: '学情报告',
},
{
pagePath: '/pages/applicationManagement/index',
iconPath: '/static/tabBar/applicationNo.png',
selectedIconPath: '/static/tabBar/application.png',
text: '应用管控',
},
{
pagePath: '/pages/mine/index',
iconPath: '/static/tabBar/mineno.png',
selectedIconPath: '/static/tabBar/mine.png',
text: '我的',
},
]
// let adminType = getCache('userInfo').adminType;
// if (adminType === 16) {
// //
// await getApplyBindInfoList();
// notice.value = getCache('applyBindMsg');
// list.value = [
// {
// pagePath: '/pages/home/index',
// iconPath: '/static/tabBar/homeno.png',
// selectedIconPath: '/static/tabBar/home.png',
// text: '',
// },
// {
// pagePath: '/pages/academicReport/index',
// iconPath: '/static/tabBar/studyReportNo.png',
// selectedIconPath: '/static/tabBar/studyReport.png',
// text: '',
// },
// {
// pagePath: '/pages/applicationManagement/index',
// iconPath: '/static/tabBar/applicationNo.png',
// selectedIconPath: '/static/tabBar/application.png',
// text: '',
// },
// {
// pagePath: '/pages/mine/index',
// iconPath: '/static/tabBar/mineno.png',
// selectedIconPath: '/static/tabBar/mine.png',
// text: '',
// },
// ];
// } else if (adminType === 6) {
// //
// uni.reLaunch({
// url: '/pages/inspector/schedule/index',
// });
// list.value = [
// {
// pagePath: '/pages/inspector/schedule/index',
// iconPath: '/static/tabBar/scheduleNo.png',
// selectedIconPath: '/static/tabBar/schedule.png',
// text: '',
// },
// {
// pagePath: '/pages/inspector/student/index',
// iconPath: '/static/tabBar/studentNo.png',
// selectedIconPath: '/static/tabBar/student.png',
// text: '',
// },
// {
// pagePath: '/pages/inspector/mine/index',
// iconPath: '/static/tabBar/mineno.png',
// selectedIconPath: '/static/tabBar/mine.png',
// text: '',
// },
// ];
// }
})
</script>
<style lang="scss" scoped>

View File

@ -1,2 +1,2 @@
export * from './useKey';
export * from './useTools';
export * from './useKey'
export * from './useTools'

View File

@ -32,61 +32,61 @@
</view>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue';
import Empty from '@/components/Empty/index.vue';
import ChildrenBox from './components/childrenBox.vue';
import SubjectFilter from './components/subjectFilter.vue';
import TabBar from '@/components/Tabbar/index.vue';
import StudyTime from './components/studyTime.vue';
import VideoTime from './components/videoTime.vue';
import KnowledgeChart from './components/knowledgeChart.vue';
import ExerciseStatistics from './components/exerciseStatistics.vue';
import LanguageStatistics from './components/languageStatistics.vue';
import { ref, reactive, onMounted } from 'vue'
import Empty from '@/components/Empty/index.vue'
import ChildrenBox from './components/childrenBox.vue'
import SubjectFilter from './components/subjectFilter.vue'
import TabBar from '@/components/Tabbar/index.vue'
import StudyTime from './components/studyTime.vue'
import VideoTime from './components/videoTime.vue'
import KnowledgeChart from './components/knowledgeChart.vue'
import ExerciseStatistics from './components/exerciseStatistics.vue'
import LanguageStatistics from './components/languageStatistics.vue'
import type { ChildrenType } from '@/pages/mine/interface';
import type { SubjectType, StudyTimeType } from './interface';
import './index.scss';
import { getParentBindChildApi, subjectApi } from '@/api';
import { user } from '@/store';
import { storeToRefs } from 'pinia';
import type { ChildrenType } from '@/pages/mine/interface'
import type { SubjectType, StudyTimeType } from './interface'
import './index.scss'
import { getParentBindChildApi, subjectApi } from '@/api'
import { user } from '@/store'
import { storeToRefs } from 'pinia'
const { userInfo } = storeToRefs(user());
const { userInfo } = storeToRefs(user())
const childrenList = ref<ChildrenType[]>(); //
const empty = ref(false);
const showChildrenInfo = ref<ChildrenType>(); //
const subjectList = ref<SubjectType[]>(); //
const childrenList = ref<ChildrenType[]>() //
const empty = ref(false)
const showChildrenInfo = ref<ChildrenType>() //
const subjectList = ref<SubjectType[]>() //
const chooseSubject = ref<SubjectType>(); //
const chooseSubject = ref<SubjectType>() //
async function handleUpdateShowChild(val: ChildrenType) {
showChildrenInfo.value = val;
showChildrenInfo.value = val
chooseSubject.value = {
name: '',
pictureUrl: '',
subject: '',
subjectId: undefined,
};
}
try {
uni.showLoading({
title: '加载中...',
});
await getSubject();
})
await getSubject()
} finally {
uni.hideLoading();
uni.hideLoading()
}
}
//
function tapFilterSubject(i: SubjectType) {
chooseSubject.value = i;
chooseSubject.value = i
}
//
async function getParentBindChild() {
const { data } = await getParentBindChildApi({ parentId: userInfo.value.id, size: -1 });
empty.value = data.rows.length === 0 ? true : false;
childrenList.value = data.rows;
showChildrenInfo.value = data.rows[0];
const { data } = await getParentBindChildApi({ parentId: userInfo.value.id, size: -1 })
empty.value = data.rows.length === 0 ? true : false
childrenList.value = data.rows
showChildrenInfo.value = data.rows[0]
}
//
async function getSubject() {
@ -94,25 +94,25 @@ async function getSubject() {
uni.showToast({
title: '当前学生无年级,无法查看学情报告',
icon: 'none',
});
subjectList.value = [];
return;
})
subjectList.value = []
return
}
const { data } = await subjectApi(showChildrenInfo.value.gradeId);
subjectList.value = data;
chooseSubject.value = data[0];
const { data } = await subjectApi(showChildrenInfo.value.gradeId)
subjectList.value = data
chooseSubject.value = data[0]
}
onMounted(async () => {
try {
uni.showLoading({
title: '加载中...',
});
await getParentBindChild();
await getSubject();
})
await getParentBindChild()
await getSubject()
uni.hideLoading();
uni.hideLoading()
} catch (err) {
uni.hideLoading();
uni.hideLoading()
}
});
})
</script>

View File

@ -272,6 +272,8 @@ async function deviceCurrentLogin(id: string) {
}
//
async function fetchAppRecord() {
//
if (!showEquipment.value.simSerialNumber) return;
try {
uni.showLoading({
title: '加载中...',

View File

@ -77,21 +77,22 @@
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import { getParentBindDeviceApi, parentDeviceCurrentLoginApi } from '@/api';
import TabBar from '@/components/Tabbar/index.vue';
import { user } from '@/store';
import { storeToRefs } from 'pinia';
import HomeBanner from '@/pages/home/banner/HomeBanner.vue';
import { onMounted, reactive, ref } from 'vue'
import { getParentBindDeviceApi, parentDeviceCurrentLoginApi } from '@/api'
import TabBar from '@/components/Tabbar/index.vue'
import { user } from '@/store'
import { storeToRefs } from 'pinia'
import HomeBanner from '@/pages/home/banner/HomeBanner.vue'
import toast from '@/utils/toast'
const { userInfo } = storeToRefs(user());
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const scanQr = `${OSS_URL}/iconfont/scan_qr.png`;
const arrow = `${OSS_URL}/iconfont/down_arrow.png`;
const checked = `${OSS_URL}/iconfont/checked.png`;
const unchecked = `${OSS_URL}/iconfont/unchecked.png`;
const showAllDevice = ref(false);
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`;
const { userInfo } = storeToRefs(user())
const OSS_URL = import.meta.env.VITE_OSS_HOST
const scanQr = `${OSS_URL}/iconfont/scan_qr.png`
const arrow = `${OSS_URL}/iconfont/down_arrow.png`
const checked = `${OSS_URL}/iconfont/checked.png`
const unchecked = `${OSS_URL}/iconfont/unchecked.png`
const showAllDevice = ref(false)
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const functionList = reactive([
{
@ -122,91 +123,82 @@ const functionList = reactive([
developing: true,
type: 3,
},
]);
const equipmentList = ref([]);
const showEquipment = ref();
async function deviceCurrentLogin(id: string) {
const { data } = await parentDeviceCurrentLoginApi(id);
return data;
}
])
const equipmentList = ref([])
const showEquipment = ref()
//
function chooseEquipment(i) {
showEquipment.value = i;
showEquipment.value = i
}
function bindDevice() {
uni.navigateTo({
url: '/pages/home/bindDevice/index',
});
})
}
//
function change(i: any) {
console.log('equipmentList.value', equipmentList.value.length);
if (equipmentList.value.length === 0) {
// uni.showToast({
// title: '',
// icon: 'none',
// duration: 2000,
// });
uni.navigateTo({ url: '/pages/home/bindDevice/index' });
return;
uni.navigateTo({ url: '/pages/home/bindDevice/index' })
return
}
if (i.developing) return;
if (i.developing) return
switch (i.type) {
case 0:
//
uni.navigateTo({
url: '/pages/home/LockScreen/index?simSerialNumber=' + showEquipment.value.simSerialNumber,
});
break;
})
break
case 1:
//
uni.navigateTo({
url:
'/pages/home/DesktopPreview/index?simSerialNumber=' + showEquipment.value.simSerialNumber,
});
break;
})
break
case 2:
//
uni.navigateTo({
url:
'/pages/home/TimeManagement/index?simSerialNumber=' + showEquipment.value.simSerialNumber,
});
break;
})
break
case 3:
//
console.log('视频通话');
break;
console.log('视频通话')
break
}
}
//
async function getParentBindDevice() {
equipmentList.value = [];
equipmentList.value = []
try {
uni.showLoading({
title: '加载中...',
mask: true,
});
const { data } = await getParentBindDeviceApi({ parentId: userInfo.value.id, size: -1 });
toast.loading()
const data = await getParentBindDeviceApi({ parentId: userInfo.value.id, size: -1 })
for (let i in data.rows) {
const _r = await deviceCurrentLogin(data.rows[i].id);
const _r = await parentDeviceCurrentLoginApi(data.rows[i].id)
equipmentList.value.push({
...data.rows[i],
curDeviceUserName: _r.curDeviceUserName,
curDeviceUserAvatar: _r.curDeviceUserAvatar,
});
})
}
showEquipment.value = data.rows.length > 0 ? equipmentList.value[0] : {};
uni.hideLoading();
} catch (err) {
uni.hideLoading();
showEquipment.value = data.rows.length > 0 ? equipmentList.value[0] : {}
} finally {
toast.hide()
}
}
onMounted(async () => {
getParentBindDevice();
});
getParentBindDevice()
})
</script>
<style scoped lang="scss">

View File

@ -41,46 +41,47 @@
</view>
</template>
<script setup lang="ts">
import CustomPopup from '@/components/CustomPopup/index.vue';
import { formatDate, getAvatarUrl, getCache } from '@/utils';
import { onShow, onLoad, onPullDownRefresh } from '@dcloudio/uni-app';
import { onMounted, ref, watch, computed, nextTick } from 'vue';
import leftIcon from '@/static/svg/icon-left.svg';
import rightIcon from '@/static/svg/icon-right.svg';
import { getTalkDetails, saveTalk, readMsg } from '@/api/modules/inspector';
import { useSocket } from '@/hooks/useSocket';
import dayjs from 'dayjs';
import Notice from '@/static/svg/notice.svg';
import CustomPopup from '@/components/CustomPopup/index.vue'
import { formatDate, getAvatarUrl, getCache } from '@/utils'
import { onShow, onLoad, onPullDownRefresh } from '@dcloudio/uni-app'
import { onMounted, ref, watch, computed, nextTick } from 'vue'
import leftIcon from '@/static/svg/icon-left.svg'
import rightIcon from '@/static/svg/icon-right.svg'
import { getTalkDetails, saveTalk, readMsg } from '@/api/modules/inspector'
import { useSocket } from '@/hooks/useSocket'
import dayjs from 'dayjs'
import Notice from '@/static/svg/notice.svg'
import db from '@/utils/db'
const row = ref('');
const scrollContainerRef = ref();
const showNotice = ref(false);
const { init: socketInit, inspectorMessage, sendMsg } = useSocket();
const stuData = ref<anyObj>({});
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`;
const current = ref(1);
const userInfo = ref<anyObj>({});
const chatList = ref<any[]>([]);
const noticeText = ref<string>('');
const row = ref('')
const scrollContainerRef = ref()
const showNotice = ref(false)
const { init: socketInit, inspectorMessage, sendMsg } = useSocket()
const stuData = ref<anyObj>({})
const OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const current = ref(1)
const userInfo = ref<anyObj>({})
const chatList = ref<any[]>([])
const noticeText = ref<string>('')
interface userInfoType {
userName: string;
userId: string;
userName: string
userId: string
}
const FIVE_MINUTES = 5 * 60 * 1000;
const lastMessageTs = computed(() => dayjs(chatList.value.at(-2)?.createTime).valueOf() ?? 0);
const content = ref('');
const FIVE_MINUTES = 5 * 60 * 1000
const lastMessageTs = computed(() => dayjs(chatList.value.at(-2)?.createTime).valueOf() ?? 0)
const content = ref('')
const inputFouse = async () => {
row.value = '';
row.value = ''
nextTick(() => {
setTimeout(() => {
row.value = 'item-' + (chatList.value.length - 1);
}, 300);
});
};
row.value = 'item-' + (chatList.value.length - 1)
}, 300)
})
}
async function send() {
const { code, data } = await saveTalk({
@ -90,7 +91,7 @@ async function send() {
messageType: 1,
sender: 1,
messageContent: content.value,
});
})
if (code === 200) {
const msg = {
id: data.id,
@ -103,14 +104,14 @@ async function send() {
avatarUrl: userInfo.value.avatarUrl,
senderName: userInfo.value.nickName,
senderAvatarUrl: userInfo.value.avatarUrl,
};
}
const newMessage = {
sender: 1,
messageContent: content.value,
avatar: '',
avatarUrl: userInfo.value.avatarUrl,
createTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
};
}
chatList.value = [
...chatList.value,
lastMessageTs.value === 0 ||
@ -118,22 +119,22 @@ async function send() {
? { timeDate: formatDate(newMessage.createTime), type: 'divider' }
: null,
newMessage,
].filter(Boolean) as anyObj[];
].filter(Boolean) as anyObj[]
sendMsg({ type: 'inspectorTalkMessage', msg });
content.value = '';
sendMsg({ type: 'inspectorTalkMessage', msg })
content.value = ''
nextTick(() => {
setTimeout(() => {
row.value = 'item-' + (chatList.value.length - 1);
}, 500);
});
row.value = 'item-' + (chatList.value.length - 1)
}, 500)
})
}
}
//
function notice(row: anyObj) {
showNotice.value = true;
noticeText.value = row.messageContent;
showNotice.value = true
noticeText.value = row.messageContent
}
//
@ -142,114 +143,114 @@ function confirmNotice() {
type: 'systemMessage',
userId: stuData.value.sender === 2 ? stuData.value.senderId : stuData.value.receiverId,
msg: noticeText.value,
};
sendMsg(msg);
showNotice.value = false;
}
sendMsg(msg)
showNotice.value = false
}
async function getDetails() {
try {
uni.showLoading({
title: '加载中...',
});
})
const { code, data } = await getTalkDetails({
inspectorTalkRecordId: chatList.value[0]?.id ?? (chatList.value[1]?.id || undefined),
userId: stuData.value.sender === 2 ? stuData.value.senderId : stuData.value.receiverId,
});
uni.hideLoading();
uni.stopPullDownRefresh();
})
uni.hideLoading()
uni.stopPullDownRefresh()
if (code === 200) {
const ids = chatList.value.filter(item => item.status === 1).map(item => item.id);
const ids = chatList.value.filter(item => item.status === 1).map(item => item.id)
if (ids.length) {
readMsg({
receiverId: userInfo.value.userId,
senderId: stuData.value.sender === 2 ? stuData.value.senderId : stuData.value.receiverId,
});
})
}
const newChat = insertDividers(data);
chatList.value = [...newChat, ...chatList.value];
const newChat = insertDividers(data)
chatList.value = [...newChat, ...chatList.value]
chatList.value = chatList.value.map((v: any) => {
if (v.sender === 1) {
return { ...v, avatarUrl: userInfo.value.avatarUrl };
return { ...v, avatarUrl: userInfo.value.avatarUrl }
}
return { ...v };
});
return { ...v }
})
}
} catch (error) {
uni.hideLoading();
uni.stopPullDownRefresh();
uni.hideLoading()
uni.stopPullDownRefresh()
}
}
function insertDividers(messages: anyObj[]) {
const result = [];
const result = []
if (messages.length > 0) {
result.push({ timeDate: formatDate(messages[0].createTime), type: 'divider' });
result.push({ timeDate: formatDate(messages[0].createTime), type: 'divider' })
}
return messages.reduce((acc, currentMessage, index) => {
acc.push(currentMessage);
acc.push(currentMessage)
if (index < messages.length - 1 && currentMessage.type !== 'divider') {
const nextMessage = messages[index + 1];
const nextMessage = messages[index + 1]
if (
dayjs(nextMessage.createTime).valueOf() - dayjs(currentMessage.createTime).valueOf() >=
FIVE_MINUTES
) {
acc.push({ timeDate: formatDate(nextMessage.createTime), type: 'divider' });
acc.push({ timeDate: formatDate(nextMessage.createTime), type: 'divider' })
}
}
return acc;
}, result) as anyObj[];
return acc
}, result) as anyObj[]
}
watch(inspectorMessage, msg => {
if (!msg) return;
const newMsgTs = dayjs(msg.createTime).valueOf();
console.log('msg1', msg);
if (!msg) return
const newMsgTs = dayjs(msg.createTime).valueOf()
console.log('msg1', msg)
const newMsg = {
sender: 2,
avatarUrl: msg.senderAvatarUrl || defaultAvatar,
createTime: msg.createTime,
messageContent: msg.messageContent,
};
chatList.value.push(newMsg);
}
chatList.value.push(newMsg)
chatList.value = [
...chatList.value,
lastMessageTs.value === 0 || newMsgTs - lastMessageTs.value > FIVE_MINUTES
? { timeDate: formatDate(msg.createTime), type: 'divider' }
: null,
];
readMsg({ receiverId: msg.receiverId, senderId: msg.senderId });
]
readMsg({ receiverId: msg.receiverId, senderId: msg.senderId })
nextTick(() => {
row.value = 'item-' + (chatList.value.length - 1);
});
});
row.value = 'item-' + (chatList.value.length - 1)
})
})
onMounted(() => {
// userInfo.value = uni.getStorageSync('QY_USERINFO');
userInfo.value = getCache('dxs_userInfo');
socketInit();
userInfo.value = db.get('dxs_userInfo')
socketInit()
nextTick(() => {
setTimeout(() => {
row.value = 'item-' + (chatList.value.length - 1);
}, 500);
});
row.value = 'item-' + (chatList.value.length - 1)
}, 500)
})
readMsg({
receiverId: userInfo.value.userId,
senderId: stuData.value.sender === 2 ? stuData.value.senderId : stuData.value.receiverId,
});
});
})
})
onShow(() => {
stuData.value = uni.getStorageSync('stu');
});
stuData.value = uni.getStorageSync('stu')
})
onPullDownRefresh(() => {
getDetails();
});
getDetails()
})
onLoad(() => {
nextTick(() => {
// uni.startPullDownRefresh();
getDetails();
});
});
getDetails()
})
})
</script>
<style lang="scss" scoped>
.page {

View File

@ -29,65 +29,66 @@
</view>
</template>
<script setup lang="ts">
import { onShow } from '@dcloudio/uni-app';
import { ref, onMounted, watch } from 'vue';
import dayjs from 'dayjs';
import { getTalkList } from '@/api/modules/inspector';
import Empty from '@/components/Empty/index.vue';
import { formatDate, getCache } from '@/utils';
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`;
const list = ref<any[]>([]);
const state = ref<string>('loading');
import { useSocket } from '@/hooks/useSocket';
const current = ref(1);
const userInfo = ref<anyObj>({});
const { init: socketInit, inspectorMessage } = useSocket();
import { onShow } from '@dcloudio/uni-app'
import { ref, onMounted, watch } from 'vue'
import dayjs from 'dayjs'
import { getTalkList } from '@/api/modules/inspector'
import Empty from '@/components/Empty/index.vue'
import { formatDate, getCache } from '@/utils'
const OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const list = ref<any[]>([])
const state = ref<string>('loading')
import { useSocket } from '@/hooks/useSocket'
import db from '@/utils/db'
const current = ref(1)
const userInfo = ref<anyObj>({})
const { init: socketInit, inspectorMessage } = useSocket()
async function getTalkData() {
try {
uni.showLoading({
title: '加载中...',
});
const { code, data } = await getTalkList({ current: current.value });
uni.hideLoading();
})
const { code, data } = await getTalkList({ current: current.value })
uni.hideLoading()
if (code === 200) {
list.value = data.rows;
list.value = data.rows
if (data.rows.length < 10) {
state.value = 'finished';
state.value = 'finished'
}
}
} catch (error) {}
}
//
function toDetails(row: anyObj) {
uni.setStorageSync('stu', row);
uni.setStorageSync('stu', row)
uni.navigateTo({
url: '/pages/inspector/chat/chatDetails',
});
})
}
function loadmore() {
current.value++;
getTalkData();
current.value++
getTalkData()
}
watch(
inspectorMessage,
msg => {
if (!msg) return;
const index = list.value.findIndex(e => e.senderId === msg.senderId);
if (!msg) return
const index = list.value.findIndex(e => e.senderId === msg.senderId)
if (index !== -1) {
list.value[index].messageContent = msg.messageContent;
list.value[index].messageContent = msg.messageContent
list.value[index].createTime = msg.createTime
? msg.createTime
: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
list.value[index].unreadCount++;
: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')
list.value[index].unreadCount++
} else {
const newMsg = {
messageContent: msg.messageContent,
createTime: msg.createTime,
unreadCount: 1,
avatarUrl: msg.avatarUrl || defaultAvatar,
};
list.value.unshift(newMsg);
}
list.value.unshift(newMsg)
}
if (msg.senderId === userInfo.value.userId) {
//
@ -97,15 +98,15 @@ watch(
immediate: true,
deep: true,
},
);
)
onShow(() => {
getTalkData();
});
getTalkData()
})
onMounted(() => {
// userInfo.value = uni.getStorageSync('QY_USERINFO');
userInfo.value = getCache('dxs_userInfo');
socketInit();
});
userInfo.value = db.get('dxs_userInfo')
socketInit()
})
</script>
<style lang="scss" scoped>
.page {

View File

@ -53,33 +53,34 @@
</template>
<script setup lang="ts">
import { computed, inject, onBeforeMount, type Ref, ref } from 'vue';
import type { UserInfo } from '@/types/inspector/mine';
import { getUserInfo, queryUserRoles, switchRole } from '@/api/inspector/mine';
import { getAvatarUrl, getCache, setCache } from '@/utils';
import { getAuthUrlApi } from '@/api/login';
import { user } from '@/store';
import { computed, inject, onBeforeMount, type Ref, ref } from 'vue'
import type { UserInfo } from '@/types/inspector/mine'
import { getUserInfo, queryUserRoles, switchRole } from '@/api/inspector/mine'
import { getAvatarUrl, getCache, setCache } from '@/utils'
import { getAuthUrlApi } from '@/api/login'
import { user } from '@/store'
import db from '@/utils/db'
const roleRef = ref(null);
const roleRef = ref(null)
const userInfo = inject<Ref<UserInfo>>('userInfo');
const userInfo = inject<Ref<UserInfo>>('userInfo')
const roleList = ref<any[]>([]);
const roleList = ref<any[]>([])
const { getUserInfo: getLoginUserInfo } = user();
const { getUserInfo: getLoginUserInfo } = user()
const queryRole = async () => {
const { data } = await queryUserRoles({ phone: userInfo.value.phone });
const { data } = await queryUserRoles({ phone: userInfo.value.phone })
roleList.value = (data ?? []).map(item => {
return {
text: item.adminType === 16 ? '家长' : '督学师',
text: '家长', // item.adminType === 16 ? '' : '',
value: item.adminType,
};
});
};
}
})
}
onBeforeMount(() => {
queryRole();
});
queryRole()
})
const colors = [
{
@ -102,58 +103,65 @@ const colors = [
color: '#328EFF',
bgColor: '#FFF7F0',
},
];
]
const userLabels = computed(() => {
return (userInfo.value.label ?? '').split(',').map((label, index) => {
const _colorObj = colors[index % colors.length];
const _colorObj = colors[index % colors.length]
return {
text: label,
color: _colorObj.color,
bgColor: _colorObj.bgColor,
};
});
});
}
})
})
const showRole = () => {
if (roleList.value.length === 1 || roleList.value.length === 0) {
return;
return
}
roleRef.value.open('bottom');
};
roleRef.value.open('bottom')
}
const selectRole = async item => {
userInfo.value.role = item.text;
const res = await switchRole(item.value);
setCache('token', res.data);
const data = await getLoginUserInfo();
userInfo.value.role = item.text
const res = await switchRole(item.value)
db.set('token', res.data)
const data = await getLoginUserInfo()
if (!data.openid) {
//
if (data.adminType === 16) {
const authRes = await getAuthUrlApi();
// #ifdef H5
window.location.href = authRes.data;
// #endif
} else {
uni.reLaunch({
url: '/pages/inspector/schedule/index',
});
}
const authRes = await getAuthUrlApi()
// #ifdef H5
window.location.href = authRes.data
// #endif
// if (data.adminType === 16) {
// const authRes = await getAuthUrlApi();
// // #ifdef H5
// window.location.href = authRes.data;
// // #endif
// } else {
// uni.reLaunch({
// url: '/pages/inspector/schedule/index',
// });
// }
} else {
let adminType = getCache('userInfo').adminType;
if (adminType === 16) {
uni.reLaunch({
url: '/pages/home/index',
});
} else if (adminType === 6) {
uni.reLaunch({
url: '/pages/inspector/schedule/index',
});
}
let adminType = db.get('userInfo').adminType
uni.reLaunch({
url: '/pages/home/index',
})
// if (adminType === 16) {
// uni.reLaunch({
// url: '/pages/home/index',
// });
// } else if (adminType === 6) {
// uni.reLaunch({
// url: '/pages/inspector/schedule/index',
// });
// }
}
roleRef.value.close();
};
roleRef.value.close()
}
</script>
<style scoped lang="scss">

View File

@ -155,116 +155,117 @@
</view>
</template>
<script setup lang="ts">
import { onLaunch, onShow, onHide, onLoad } from '@dcloudio/uni-app';
import { onMounted, reactive, ref, computed } from 'vue';
import Picker from './components/picker.vue';
import DatePicker from './components/datePicker.vue';
import DateTimePicker from './components/dateTimePicker.vue';
import CustomPopup from '@/components/CustomPopup/index.vue';
import { getCourseData, getSubject, publishPlan, getStuPlan } from '@/api/modules/inspector';
import dayjs from 'dayjs';
import { getCache } from '@/utils';
const pageTitle = ref('');
const minHour = ref<number>(0);
const minMinute = ref<number>(0);
const maxHour = ref<number>(23);
const maxMinute = ref<number>(59);
const form = ref<anyObj>({});
const plan = ref<anyObj>({});
const user = ref<anyObj>({});
const showStuPopup = ref(false);
const showDatePicker = ref(false);
const showRemovePopup = ref(false);
const showDateTimePicker = ref(false);
const studyPlanIndex = ref(0); //
const currentType = ref(''); //
const canlenderList = ref<any[]>([]);
const subjectData = ref<any[]>([]);
const titleText = ref('');
const rangeType = ref('start');
import { onLaunch, onShow, onHide, onLoad } from '@dcloudio/uni-app'
import { onMounted, reactive, ref, computed } from 'vue'
import Picker from './components/picker.vue'
import DatePicker from './components/datePicker.vue'
import DateTimePicker from './components/dateTimePicker.vue'
import CustomPopup from '@/components/CustomPopup/index.vue'
import { getCourseData, getSubject, publishPlan, getStuPlan } from '@/api/modules/inspector'
import dayjs from 'dayjs'
import { getCache } from '@/utils'
import db from '@/utils/db'
const pageTitle = ref('')
const minHour = ref<number>(0)
const minMinute = ref<number>(0)
const maxHour = ref<number>(23)
const maxMinute = ref<number>(59)
const form = ref<anyObj>({})
const plan = ref<anyObj>({})
const user = ref<anyObj>({})
const showStuPopup = ref(false)
const showDatePicker = ref(false)
const showRemovePopup = ref(false)
const showDateTimePicker = ref(false)
const studyPlanIndex = ref(0) //
const currentType = ref('') //
const canlenderList = ref<any[]>([])
const subjectData = ref<any[]>([])
const titleText = ref('')
const rangeType = ref('start')
const tagClass = {
0: 'yellow',
1: 'yellow',
2: 'blue',
3: 'red',
};
}
const tagName = {
0: '自由学',
1: '自由学',
2: '精准学',
3: '语感训练',
};
}
//
const planList = ref<any[]>([]);
const stuList = ref([]);
const planList = ref<any[]>([])
const stuList = ref([])
const columns = computed(() => {
return currentType.value === 'plan' ? subjectData.value : [];
});
return currentType.value === 'plan' ? subjectData.value : []
})
//
function select(type: string, index?: number, dateType?: string) {
currentType.value = type;
studyPlanIndex.value = index;
currentType.value = type
studyPlanIndex.value = index
switch (type) {
case 'stundent':
showStuPopup.value = true;
break;
showStuPopup.value = true
break
case 'plan':
showStuPopup.value = true;
break;
showStuPopup.value = true
break
case 'date':
if (!user.value.courseDate) {
showDatePicker.value = true;
showDatePicker.value = true
}
break;
break
case 'rangeDate':
if (dateType === 'start') {
titleText.value = '开始时间';
rangeType.value = 'start';
setRange();
titleText.value = '开始时间'
rangeType.value = 'start'
setRange()
} else {
titleText.value = '结束时间';
rangeType.value = 'end';
setRange();
titleText.value = '结束时间'
rangeType.value = 'end'
setRange()
}
showDateTimePicker.value = true;
break;
showDateTimePicker.value = true
break
}
}
function setRange() {
let minute = 0;
let hour = 0;
let minute = 0
let hour = 0
const key = rangeType.value === 'start' ? 'inspectorTimeEnd' : 'inspectorTimeStart';
const time = planList.value[studyPlanIndex.value]?.[key].split(':') || [];
minute = Number(time?.[1] || 0);
hour = Number(time?.[0] || 0);
const key = rangeType.value === 'start' ? 'inspectorTimeEnd' : 'inspectorTimeStart'
const time = planList.value[studyPlanIndex.value]?.[key].split(':') || []
minute = Number(time?.[1] || 0)
hour = Number(time?.[0] || 0)
if (rangeType.value === 'start') {
if (time.length === 2) {
minute = minute - 1 > 0 ? minute - 1 : 1;
minute = minute - 1 > 0 ? minute - 1 : 1
} else {
hour = 23;
minute = 58;
hour = 23
minute = 58
}
maxHour.value = hour;
maxMinute.value = minute;
maxHour.value = hour
maxMinute.value = minute
} else {
minute = minute + 1;
minHour.value = hour;
minMinute.value = minute;
maxHour.value = 23;
maxMinute.value = 59;
minute = minute + 1
minHour.value = hour
minMinute.value = minute
maxHour.value = 23
maxMinute.value = 59
}
}
//
function confirmSelect(val: any) {
let row = planList.value[studyPlanIndex.value];
let row = planList.value[studyPlanIndex.value]
if (currentType.value === 'plan') {
row.subjectId = val.value;
row.subjectName = val.name;
row.gradeId = user.value.gradeId;
row.subjectId = val.value;
row.subjectId = val.value
row.subjectName = val.name
row.gradeId = user.value.gradeId
row.subjectId = val.value
uni.setStorageSync('plan', {
planList: planList.value,
userId: user.value.userId,
@ -272,113 +273,113 @@ function confirmSelect(val: any) {
row: row,
date: form.value.date,
courseId: form.value.courseId,
});
uni.navigateTo({ url: '/pages/inspector/releasePlan/selectPlan' });
})
uni.navigateTo({ url: '/pages/inspector/releasePlan/selectPlan' })
}
showStuPopup.value = false;
showStuPopup.value = false
}
function addPlan() {
planList.value.push({});
planList.value.push({})
}
function removePlan(index: number) {
showRemovePopup.value = true;
studyPlanIndex.value = index;
showRemovePopup.value = true
studyPlanIndex.value = index
}
//
function handleConfirm(row: any) {
form.value.date = row.courseDate;
form.value.courseId = row.courseId;
form.value.date = row.courseDate
form.value.courseId = row.courseId
//
}
//
function confirmDateTime(date: string) {
let row = planList.value[studyPlanIndex.value];
let row = planList.value[studyPlanIndex.value]
if (rangeType.value === 'start') {
row.inspectorTimeStart = date;
row.inspectorTimeStart = date
} else if (rangeType.value === 'end') {
row.inspectorTimeEnd = date;
row.inspectorTimeEnd = date
}
}
function removeConfirm() {
planList.value.splice(studyPlanIndex.value, 1);
showRemovePopup.value = false;
planList.value.splice(studyPlanIndex.value, 1)
showRemovePopup.value = false
}
//
async function getDate() {
const { code, data } = await getCourseData({ id: user.value.userId });
const { code, data } = await getCourseData({ id: user.value.userId })
if (code === 200) {
canlenderList.value = data || [];
canlenderList.value = data || []
}
}
//
async function getSubjectList() {
const { code, data } = await getSubject({ gradeId: user.value.gradeId });
const { code, data } = await getSubject({ gradeId: user.value.gradeId })
if (code === 200) {
subjectData.value = data.map((item: any) => {
return {
name: item.subject,
value: item.subjectId,
};
});
}
})
}
}
//
async function getStuPlanData() {
try {
uni.showLoading({ title: '加载中...' });
uni.showLoading({ title: '加载中...' })
const { code, data } = await getStuPlan({
userId: user.value.userId,
courseDate: user.value.courseDate ?? '',
});
uni.hideLoading();
})
uni.hideLoading()
if (code === 200) {
form.value.courseId = data.courseId ? data.courseId : plan.value.courseId;
form.value.courseId = data.courseId ? data.courseId : plan.value.courseId
form.value.date = data.courseDate
? dayjs(data.courseDate).format('YYYY-MM-DD')
: plan.value.date;
: plan.value.date
if (data.tasks && Object.keys(plan.value).length === 0) {
planList.value = data.tasks.map(item => {
const taskInfo = JSON.parse(item.taskInfoJson);
const taskInfo = JSON.parse(item.taskInfoJson)
return {
...taskInfo,
...item,
id: item.id,
inspectorTimeStart: dayjs(item.inspectorTimeStart).format('HH:mm'),
inspectorTimeEnd: dayjs(item.inspectorTimeEnd).format('HH:mm'),
};
});
}
})
const storegePlan = {
index: 0,
date: form.value.date,
courseId: form.value.courseId,
planList: planList.value,
row: planList.value[0],
};
plan.value = storegePlan;
uni.setStorageSync('plan', storegePlan);
}
plan.value = storegePlan
uni.setStorageSync('plan', storegePlan)
} else {
uni.removeStorageSync('plan');
uni.removeStorageSync('plan')
}
}
} catch (error) {
uni.hideLoading();
uni.hideLoading()
}
}
//
async function submitPublish() {
const fields = ['chapterId', 'bookId', 'courseTimeId', 'inspectorTimeStart', 'inspectorTimeEnd'];
let valid = true;
const fields = ['chapterId', 'bookId', 'courseTimeId', 'inspectorTimeStart', 'inspectorTimeEnd']
let valid = true
const tasks = planList.value.map(item => {
if (item.taskType >= 0) {
if ([0, 1].includes(item.taskType)) {
fields.forEach(field => {
if (!item[field]) valid = false;
});
if (!item[field]) valid = false
})
}
} else {
valid = false;
valid = false
}
return {
@ -389,70 +390,70 @@ async function submitPublish() {
inspectorTimeStart: item.inspectorTimeStart
? form.value.date + ' ' + item.inspectorTimeStart + ':00'
: undefined,
};
});
}
})
if (!valid) {
return uni.showToast({
title: '请确认学习任务中的教材/章节/知识点/督学时段是否完整',
icon: 'none',
});
})
}
try {
uni.showLoading({ title: '发布中...' });
uni.showLoading({ title: '发布中...' })
const params = {
courseId: form.value.courseId,
tasks: tasks,
};
const { code } = await publishPlan(params);
uni.hideLoading();
}
const { code } = await publishPlan(params)
uni.hideLoading()
if (code === 200) {
uni.showToast({
title: '发布成功',
});
})
setTimeout(() => {
uni.redirectTo({
url: `/pages/inspector/student-detail/index?orderId=${user.value.orderId}&courseDate=${form.value.date}`,
});
}, 1500);
reload();
})
}, 1500)
reload()
}
} catch (error) {
uni.hideLoading();
uni.hideLoading()
}
}
function reload() {
uni.removeStorageSync('plan');
uni.removeStorageSync('user');
uni.removeStorageSync('plan')
uni.removeStorageSync('user')
}
const studentDetail = ref();
const studentDetail = ref()
const back = () => {
uni.navigateTo({
url: `/pages/inspector/student-detail/index?orderId=${studentDetail.value.orderId}&courseDate=${studentDetail.value.courseDate}`,
});
reload();
};
})
reload()
}
window.addEventListener('popstate', event => {
reload();
});
reload()
})
onMounted(() => {
user.value = uni.getStorageSync('user') || {};
getStuPlanData();
getSubjectList();
getDate();
});
user.value = uni.getStorageSync('user') || {}
getStuPlanData()
getSubjectList()
getDate()
})
onShow(() => {
studentDetail.value = getCache('student_detail');
plan.value = uni.getStorageSync('plan') || {};
planList.value = plan.value.planList || [{}];
plan.value.date && (form.value.date = plan.value.date);
});
studentDetail.value = db.get('student_detail')
plan.value = uni.getStorageSync('plan') || {}
planList.value = plan.value.planList || [{}]
plan.value.date && (form.value.date = plan.value.date)
})
onLoad(option => {
pageTitle.value = Number(option.type) === 1 ? '修改计划' : '发布计划';
pageTitle.value = Number(option.type) === 1 ? '修改计划' : '发布计划'
uni.setNavigationBarTitle({
title: Number(option.type) === 1 ? '修改计划' : '发布计划',
});
});
})
})
</script>
<style lang="scss" scoped>
.page {

View File

@ -127,154 +127,155 @@
</view>
</template>
<script setup lang="ts">
import dayjs from 'dayjs';
import { onShow } from '@dcloudio/uni-app';
import { computed, onMounted, ref, watch, onUnmounted } from 'vue';
import DuxueTipsModal from './components/duxueTipsModal.vue';
import CusCalender from '@/components/customCalender/index.vue';
import dayjs from 'dayjs'
import { onShow } from '@dcloudio/uni-app'
import { computed, onMounted, ref, watch, onUnmounted } from 'vue'
import DuxueTipsModal from './components/duxueTipsModal.vue'
import CusCalender from '@/components/customCalender/index.vue'
import { useSocket } from '@/hooks/useSocket';
import { useSocket } from '@/hooks/useSocket'
import {
endInpector,
getCourseDate,
getScheduleList,
getUnreadCount,
startInpector,
} from '@/api/modules/inspector';
import { getAvatarUrl, setCache } from '@/utils';
} from '@/api/modules/inspector'
import { getAvatarUrl, setCache } from '@/utils'
import db from '@/utils/db'
const { init: socketInit, sendMsg, inspectorMessage } = useSocket();
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const { init: socketInit, sendMsg, inspectorMessage } = useSocket()
const OSS_URL = import.meta.env.VITE_OSS_HOST
const showTipsModal = ref(false);
const calendarData = ref<any[]>([]);
const titleText = ref('');
const unreadCount = ref(0);
const modalContent = ref('');
const courseData = ref<any>({}); //
const currentDate = ref(dayjs().format('YYYY-MM-DD'));
const today = ref(dayjs().format('YYYY-MM-DD'));
const currentDateIndex = ref(0); //
const inspectorTimeStart = ref<string>(); //
const time = ref<string>('');
const studentList = ref<any[]>([]);
const showTipsModal = ref(false)
const calendarData = ref<any[]>([])
const titleText = ref('')
const unreadCount = ref(0)
const modalContent = ref('')
const courseData = ref<any>({}) //
const currentDate = ref(dayjs().format('YYYY-MM-DD'))
const today = ref(dayjs().format('YYYY-MM-DD'))
const currentDateIndex = ref(0) //
const inspectorTimeStart = ref<string>() //
const time = ref<string>('')
const studentList = ref<any[]>([])
const tagColor = {
1: 'green',
2: 'grey',
};
}
const stateCorlo = {
0: 'plan',
1: 'green',
2: 'grey',
3: 'grey',
};
}
const stateName = {
'-1': '待发计划',
0: '待开课',
1: '督学中',
2: '已督学',
3: '已过期',
};
const currentType = ref('');
const showList = ref(false);
}
const currentType = ref('')
const showList = ref(false)
//
const canStart = () => {
return (
today.value === currentDate.value &&
new Date().getTime() >= new Date(courseData.value.courseStartDate).getTime() - 30 * 1000 * 60
);
};
)
}
//
const endDX = ref(false);
let timer: any;
const endDX = ref(false)
let timer: any
const endCount = () => {
let duration = new Date().getTime() - new Date(inspectorTimeStart.value).getTime();
const hours = Math.floor(duration / 3600000);
const minutes = Math.floor((duration % 3600000) / 60000);
const seconds = Math.floor((duration % 60000) / 1000);
let duration = new Date().getTime() - new Date(inspectorTimeStart.value).getTime()
const hours = Math.floor(duration / 3600000)
const minutes = Math.floor((duration % 3600000) / 60000)
const seconds = Math.floor((duration % 60000) / 1000)
time.value = `${hours.toString().padStart(2, '0')}:${minutes
.toString()
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
};
.padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`
}
const canEnd = () => {
endCount();
clearInterval(timer);
endCount()
clearInterval(timer)
if (inspectorTimeStart.value) {
timer = setInterval(() => {
endCount();
endCount()
endDX.value =
today.value === currentDate.value &&
new Date().getTime() > new Date(courseData.value.courseEndDate).getTime();
}, 1000);
new Date().getTime() > new Date(courseData.value.courseEndDate).getTime()
}, 1000)
}
};
}
//
const noPlan = computed(() => {
let flag = false;
let flag = false
studentList.value.forEach(e => {
if (!e.planNum) {
flag = true;
flag = true
}
});
return flag;
});
})
return flag
})
//
function startSubmit() {
if (noPlan.value) {
titleText.value = '无法开始督学';
modalContent.value = '存在学员没有学习计划,请发布学习计划后再开始督学!';
currentType.value = 'none';
titleText.value = '无法开始督学'
modalContent.value = '存在学员没有学习计划,请发布学习计划后再开始督学!'
currentType.value = 'none'
} else {
titleText.value = '温馨提示';
modalContent.value = '确定开始督学?';
currentType.value = 'start';
titleText.value = '温馨提示'
modalContent.value = '确定开始督学?'
currentType.value = 'start'
}
showTipsModal.value = true;
showTipsModal.value = true
}
//
function endSubmit() {
titleText.value = '温馨提示';
modalContent.value = '确认结束督学';
currentType.value = 'end';
showTipsModal.value = true;
titleText.value = '温馨提示'
modalContent.value = '确认结束督学'
currentType.value = 'end'
showTipsModal.value = true
}
//
const confirmEnd = async () => {
try {
uni.showLoading({ title: '请稍后...' });
const { code } = await endInpector({ courseDate: currentDate.value });
uni.hideLoading();
uni.showLoading({ title: '请稍后...' })
const { code } = await endInpector({ courseDate: currentDate.value })
uni.hideLoading()
if (code === 200) {
uni.showToast({
title: '结束督学成功',
});
})
sendMsg({
type: 'inspectorEnd',
msg: {
receiverIds: studentList.value.map(item => item.id),
},
});
showTipsModal.value = false;
getDate(currentDate.value);
})
showTipsModal.value = false
getDate(currentDate.value)
}
} catch (error) {
uni.hideLoading();
uni.hideLoading()
}
};
}
//
const confirmStart = async () => {
showTipsModal.value = false;
showTipsModal.value = false
if (!canStart()) {
uni.showToast({
title: '最多提前30分钟开始督学',
icon: 'none',
});
return;
})
return
}
try {
uni.showLoading({ title: '请稍后...' });
const { code } = await startInpector({ courseDate: currentDate.value });
uni.hideLoading();
uni.showLoading({ title: '请稍后...' })
const { code } = await startInpector({ courseDate: currentDate.value })
uni.hideLoading()
if (code === 200) {
sendMsg({
type: 'inspectorStart',
@ -282,125 +283,123 @@ const confirmStart = async () => {
receiverIds: studentList.value.map(item => item.id),
courseDate: currentDate.value,
},
});
})
uni.showToast({
title: '开始督学成功',
});
getDate(currentDate.value);
})
getDate(currentDate.value)
}
} catch (error) {
uni.hideLoading();
uni.hideLoading()
}
};
}
const confirmModal = () => {
if (currentType.value === 'start') {
confirmStart();
confirmStart()
} else if (currentType.value === 'end') {
confirmEnd();
confirmEnd()
}
};
}
//
function selectedDay(date: any) {
currentDate.value = date.courseDate;
getDate(currentDate.value);
showList.value = false;
currentDate.value = date.courseDate
getDate(currentDate.value)
showList.value = false
}
//
const studentDetail = (_student: any) => {
setCache('student_detail', {
db.set('student_detail', {
orderId: _student.orderId,
courseDate: currentDate.value,
backType: 1,
});
})
uni.navigateTo({
url: `/pages/inspector/student-detail/index?orderId=${_student.orderId}&courseDate=${currentDate.value}`,
});
};
})
}
//
function jumpPage(path: string) {
uni.setStorageSync('courseDate', currentDate.value);
uni.setStorageSync('courseDate', currentDate.value)
uni.navigateTo({
url: path,
});
})
}
//
function changeDay(type: string) {
switch (type) {
case 'prev':
if (currentDateIndex.value > 0) {
currentDate.value = calendarData.value[currentDateIndex.value - 1].courseDate;
currentDate.value = calendarData.value[currentDateIndex.value - 1].courseDate
}
break;
break
case 'next':
if (currentDateIndex.value < calendarData.value.length - 1)
currentDate.value = calendarData.value[currentDateIndex.value + 1].courseDate;
currentDate.value = calendarData.value[currentDateIndex.value + 1].courseDate
break;
break
}
currentDateIndex.value = calendarData.value.findIndex(e => e.courseDate === currentDate.value);
getDate(currentDate.value);
currentDateIndex.value = calendarData.value.findIndex(e => e.courseDate === currentDate.value)
getDate(currentDate.value)
}
//
async function getDate(date?: string) {
uni.showLoading({ title: '加载中...' });
uni.showLoading({ title: '加载中...' })
try {
const { code, data, message } = await getCourseDate({ date });
const { code, data, message } = await getCourseDate({ date })
if (code === 200) {
currentDate.value =
dayjs(data.courseDate).format('YYYY-MM-DD') || dayjs().format('YYYY-MM-DD');
courseData.value = data || {};
currentDateIndex.value = calendarData.value.findIndex(
e => e.courseDate === currentDate.value,
);
inspectorTimeStart.value = data.inspectorTimeStart ? data.inspectorTimeStart : '';
studentList.value = data.studentDetails || [];
dayjs(data.courseDate).format('YYYY-MM-DD') || dayjs().format('YYYY-MM-DD')
courseData.value = data || {}
currentDateIndex.value = calendarData.value.findIndex(e => e.courseDate === currentDate.value)
inspectorTimeStart.value = data.inspectorTimeStart ? data.inspectorTimeStart : ''
studentList.value = data.studentDetails || []
if (data.planState === 1) {
canEnd();
canEnd()
}
}
} catch (e) {
} finally {
uni.hideLoading();
uni.hideLoading()
}
}
//
async function getList() {
try {
uni.showLoading({ title: '加载中...' });
const { code, data, message } = await getScheduleList();
uni.showLoading({ title: '加载中...' })
const { code, data, message } = await getScheduleList()
if (code === 200) {
calendarData.value = data || [];
calendarData.value = data || []
} else {
uni.showToast({ title: message, icon: 'none' });
uni.showToast({ title: message, icon: 'none' })
}
uni.hideLoading();
uni.hideLoading()
} catch (error) {
uni.hideLoading();
uni.hideLoading()
}
}
//
async function getMyUnreadCount() {
const { code, data } = await getUnreadCount();
const { code, data } = await getUnreadCount()
if (code === 200) {
unreadCount.value = data;
unreadCount.value = data
}
}
watch(inspectorMessage, msg => {
if (!msg) return;
unreadCount.value++;
});
if (!msg) return
unreadCount.value++
})
onMounted(async () => {
socketInit();
socketInit()
await getList();
getDate();
});
await getList()
getDate()
})
onUnmounted(() => {
clearInterval(timer);
});
clearInterval(timer)
})
onShow(() => {
getMyUnreadCount();
});
getMyUnreadCount()
})
</script>
<style lang="scss" scoped>
.page {

View File

@ -16,33 +16,34 @@
</template>
<script setup lang="ts">
import { onReachBottom } from '@dcloudio/uni-app';
import DetailStudentInfo from '@/pages/inspector/student-detail/detail-student-info.vue';
import StudentDetailData from '@/pages/inspector/student-detail/student-detail-data.vue';
import { getCurrentInstance, onMounted, provide, ref } from 'vue';
import { getStudentDetail } from '@/api/inspector/student-detail';
import dayjs from '@/plugins/dayjs';
import IspDataLoad from '@/components/inspector/isp-data-load.vue';
import SvgsAddPlan from '@/components/svgs/svgs-add-plan.vue';
import { removeCache, getCache } from '@/utils';
const studentInfo = ref<any>({});
const routeData = ref({});
const loadingData = ref(true);
import { onReachBottom } from '@dcloudio/uni-app'
import DetailStudentInfo from '@/pages/inspector/student-detail/detail-student-info.vue'
import StudentDetailData from '@/pages/inspector/student-detail/student-detail-data.vue'
import { getCurrentInstance, onMounted, provide, ref } from 'vue'
import { getStudentDetail } from '@/api/inspector/student-detail'
import dayjs from '@/plugins/dayjs'
import IspDataLoad from '@/components/inspector/isp-data-load.vue'
import SvgsAddPlan from '@/components/svgs/svgs-add-plan.vue'
import { removeCache, getCache } from '@/utils'
import db from '@/utils/db'
const studentInfo = ref<any>({})
const routeData = ref({})
const loadingData = ref(true)
provide('studentInfo', studentInfo);
provide('routeData', routeData);
provide('studentInfo', studentInfo)
provide('routeData', routeData)
const queryData = async _params => {
loadingData.value = true;
loadingData.value = true
try {
const { data } = await getStudentDetail(_params);
studentInfo.value = data;
const { data } = await getStudentDetail(_params)
studentInfo.value = data
} finally {
loadingData.value = false;
loadingData.value = false
}
};
}
const orderId = ref('');
const orderId = ref('')
const toAddPlan = () => {
uni.setStorageSync('user', {
@ -51,32 +52,32 @@ const toAddPlan = () => {
gradeId: studentInfo.value.gradeId,
orderId: orderId.value,
// courseDate: routeData.value.courseDate,
});
})
uni.navigateTo({
url: `/pages/inspector/releasePlan/index`,
});
};
})
}
const back = () => {
let info = getCache('student_detail');
let info = db.get('student_detail')
uni.navigateTo({
url: `${
info.backType === 1 ? '/pages/inspector/schedule/index' : '/pages/inspector/student/index'
}`,
});
removeCache('student_detail');
};
})
removeCache('student_detail')
}
onReachBottom(() => {
console.log('触底加载');
});
console.log('触底加载')
})
onMounted(() => {
const data = getCurrentInstance().proxy.$page.options;
routeData.value = data;
orderId.value = data.orderId;
const data = getCurrentInstance().proxy.$page.options
routeData.value = data
orderId.value = data.orderId
queryData({
orderId: data.orderId,
courseDate: data.courseDate ? dayjs(data.courseDate).format('YYYY-MM-DD') : '',
});
});
})
})
</script>
<style scoped lang="scss">

View File

@ -33,15 +33,16 @@
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { queryStudentList } from '@/api/inspector/student';
import IspDataLoad from '@/components/inspector/isp-data-load.vue';
import { getAvatarUrl, setCache } from '@/utils';
import { computed, ref } from 'vue'
import { queryStudentList } from '@/api/inspector/student'
import IspDataLoad from '@/components/inspector/isp-data-load.vue'
import { getAvatarUrl, setCache } from '@/utils'
import db from '@/utils/db'
const currentTab = ref<string>('all');
const queryResult = ref<any>({});
const studentList = ref([]);
const queryLoading = ref(true);
const currentTab = ref<string>('all')
const queryResult = ref<any>({})
const studentList = ref([])
const queryLoading = ref(true)
const stateObj = {
true: {
@ -52,33 +53,33 @@ const stateObj = {
text: '离线',
color: '#cccccc',
},
};
}
const queryList = async (courseDate: string) => {
queryLoading.value = true;
queryLoading.value = true
try {
const { data } = await queryStudentList({ courseDate });
queryResult.value = data ?? {};
studentList.value = data?.studentDetails ?? [];
const { data } = await queryStudentList({ courseDate })
queryResult.value = data ?? {}
studentList.value = data?.studentDetails ?? []
} finally {
queryLoading.value = false;
queryLoading.value = false
}
};
}
const studentListShow = computed(() => {
return studentList.value.filter(item => {
if (currentTab.value === 'all') {
return true;
return true
}
return item.gradeName === currentTab.value;
});
});
return item.gradeName === currentTab.value
})
})
const grades = computed(() => {
let gradeList = studentList.value
.filter(item => (item.gradeName ?? '') !== '')
.map(item => item.gradeName);
gradeList = [...new Set(gradeList)];
.map(item => item.gradeName)
gradeList = [...new Set(gradeList)]
return [
{
title: '全部',
@ -88,27 +89,27 @@ const grades = computed(() => {
return {
title: item,
value: item,
};
}
}),
];
});
]
})
const studentDetail = (_student: any) => {
setCache('student_detail', {
db.set('student_detail', {
orderId: _student.orderId,
courseDate: queryResult.value.courseDate ? queryResult.value.courseDate : '',
backType: 2,
});
})
uni.navigateTo({
url: `/pages/inspector/student-detail/index?orderId=${_student.orderId}&courseDate=${
queryResult.value.courseDate ? queryResult.value.courseDate : ''
}`,
});
};
})
}
defineExpose({
queryList,
});
})
</script>
<style scoped lang="scss">

View File

@ -69,7 +69,7 @@
</template>
<script setup lang="tsx">
import { ref, computed, nextTick, onMounted } from 'vue';
import { ref, computed, nextTick, onMounted } from 'vue'
import {
getBindPhoneTypeApi,
@ -78,78 +78,77 @@ import {
smsLoginApi,
getUserInfoApi,
getAuthUrlApi,
} from '@/api';
import { setCache, getCache } from '@/utils';
import { getUserInfo as dx_getUserInfoApi } from '@/api/inspector/mine';
import { user } from '@/store';
} from '@/api'
import { setCache, getCache } from '@/utils'
import { getUserInfo as dx_getUserInfoApi } from '@/api/inspector/mine'
import { user } from '@/store'
import db from '@/utils/db'
import toast from '@/utils/toast'
const emits = defineEmits(['reloadFun']);
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const { getUserInfo, setToken } = user();
const emits = defineEmits(['reloadFun'])
const OSS_URL = import.meta.env.VITE_OSS_HOST
const { getUserInfo, setToken } = user()
const formatPhone = ref('');
const adminPopup = ref();
const userAdmin = ref([]); //
const formatPhone = ref('')
const adminPopup = ref()
const userAdmin = ref([]) //
const loginForm = ref({
adminType: 16, //
clientType: 'MOBILE',
phone: '',
verifyCode: '',
});
const codeTime = ref(0);
})
const codeTime = ref(0)
const codeTimeContet = computed(() => {
return codeTime.value;
});
return codeTime.value
})
function validatePhone() {
loginForm.value.phone = formatPhone.value.replace(/\s+/g, '');
let reg = /^[1][0,1,2,3, 4, 5, 6, 7, 8, 9][0-9]{9}$/;
return reg.test(loginForm.value.phone);
loginForm.value.phone = formatPhone.value.replace(/\s+/g, '')
let reg = /^[1][0,1,2,3, 4, 5, 6, 7, 8, 9][0-9]{9}$/
return reg.test(loginForm.value.phone)
}
// 344
function phoneDivision() {
nextTick(() => {
let value = formatPhone.value.replace(/\D/g, '').substr(0, 11);
let len = value.length; //
let value = formatPhone.value.replace(/\D/g, '').substr(0, 11)
let len = value.length //
if (len > 3 && len < 8) {
value = value.replace(/^(\d{3})/g, '$1 ');
value = value.replace(/^(\d{3})/g, '$1 ')
} else if (len >= 8) {
value = value.replace(/^(\d{3})(\d{4})/g, '$1 $2 ');
value = value.replace(/^(\d{3})(\d{4})/g, '$1 $2 ')
}
formatPhone.value = value;
});
formatPhone.value = value
})
}
//
async function fetchDXUserInfo() {
const { data } = await dx_getUserInfoApi();
setCache('dxs_userInfo', data);
const { data } = await dx_getUserInfoApi()
db.set('dxs_userInfo', data)
}
//
async function getCode() {
loginForm.value.phone = formatPhone.value.replace(/\s+/g, '');
loginForm.value.phone = formatPhone.value.replace(/\s+/g, '')
if (!loginForm.value.phone) {
uni.showToast({
icon: 'none',
title: '请输入手机号',
});
return;
})
return
}
try {
const res = await sendCodeMessageApi(loginForm.value.phone);
uni.showToast({
title: '发送成功!',
icon: 'none',
});
codeTime.value = 60;
await sendCodeMessageApi(loginForm.value.phone)
toast.success('发送成功!')
codeTime.value = 60
let timer = setInterval(() => {
codeTime.value--;
codeTime.value--
if (codeTime.value < 1) {
clearInterval(timer);
codeTime.value = 0;
clearInterval(timer)
codeTime.value = 0
}
}, 1000);
}, 1000)
} catch (err) {
console.log(err);
console.log(err)
}
}
//
@ -158,73 +157,80 @@ async function handleLogin() {
uni.showToast({
icon: 'none',
title: '账号或验证码不正确',
});
return;
})
return
}
uni.showLoading({
title: '登录中...',
});
getAdminTypeByPhone();
})
getAdminTypeByPhone()
}
//
async function getAdminTypeByPhone() {
const res = await getAdminTypeByPhoneApi({
phone: loginForm.value.phone,
});
userAdmin.value = res.data;
})
userAdmin.value = res.data
if (userAdmin.value.length <= 1) {
//
loginForm.value.adminType = userAdmin.value[0].adminType;
await smsLogin();
if (loginForm.value.adminType === 6) return;
loginForm.value.adminType = userAdmin.value[0].adminType
await smsLogin()
if (loginForm.value.adminType === 6) return
} else {
//
uni.hideLoading();
uni.hideLoading()
adminPopup.value = true;
adminPopup.value = true
}
}
async function smsLogin() {
uni.showLoading({
title: '登录中...',
});
const res = await smsLoginApi(loginForm.value);
setToken(res.data);
const data = await getUserInfo();
})
const res = await smsLoginApi(loginForm.value)
setToken(res.data)
const data = await getUserInfo()
if (!data.openid) {
//
if (data.adminType === 16) {
const authRes = await getAuthUrlApi();
// #ifdef H5
window.location.href = authRes.data;
// #endif
} else {
fetchDXUserInfo();
uni.reLaunch({
url: '/pages/inspector/schedule/index',
});
}
const authRes = await getAuthUrlApi()
// #ifdef H5
window.location.href = authRes.data
// #endif
// if (data.adminType === 16) {
// const authRes = await getAuthUrlApi();
// // #ifdef H5
// window.location.href = authRes.data;
// // #endif
// } else {
// fetchDXUserInfo();
// uni.reLaunch({
// url: '/pages/inspector/schedule/index',
// });
// }
} else {
let adminType = getCache('userInfo').adminType;
if (adminType === 16) {
uni.reLaunch({
url: '/pages/home/index',
});
} else if (adminType === 6) {
fetchDXUserInfo();
uni.reLaunch({
url: '/pages/inspector/schedule/index',
});
}
uni.reLaunch({
url: '/pages/home/index',
})
// let adminType = getCache('userInfo').adminType;
// if (adminType === 16) {
// uni.reLaunch({
// url: '/pages/home/index',
// });
// } else if (adminType === 6) {
// fetchDXUserInfo();
// uni.reLaunch({
// url: '/pages/inspector/schedule/index',
// });
// }
}
uni.hideLoading();
uni.hideLoading()
}
async function chooseAdmin(i) {
loginForm.value.adminType = i.adminType;
adminPopup.value = false;
await smsLogin();
if (loginForm.value.adminType === 6) return;
loginForm.value.adminType = i.adminType
adminPopup.value = false
await smsLogin()
if (loginForm.value.adminType === 6) return
}
</script>

View File

@ -3,7 +3,7 @@
<z-paging
ref="paging"
v-model="dataList"
:paging-style="{ margin: isAdmin ? '562rpx 30rpx 0 30rpx' : '386rpx 30rpx 0 30rpx' }"
:paging-style="{ margin: isAdmin ? '402rpx 30rpx 0 30rpx' : '226rpx 30rpx 0 30rpx' }"
:style="{
height: isAdmin
? `calc(100% - 532rpx - 120rpx - 52rpx)`
@ -80,24 +80,25 @@
</template>
<script setup lang="ts">
import { reactive, ref, onMounted, nextTick } from 'vue';
import { onShow } from '@dcloudio/uni-app';
import { getParentBindChildApi, getParentBindDeviceApi } from '@/api';
import { user } from '@/store';
import { storeToRefs } from 'pinia';
import { getCache } from '@/utils';
import type { ChildrenType, DeviceType } from './interface';
import dayjs from 'dayjs';
const { userInfo } = storeToRefs(user());
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`;
const empty = `${OSS_URL}/empty.png`;
const isAdmin = ref(false);
import { reactive, ref, onMounted, nextTick } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { getParentBindChildApi, getParentBindDeviceApi } from '@/api'
import { user } from '@/store'
import { storeToRefs } from 'pinia'
import { getCache } from '@/utils'
import type { ChildrenType, DeviceType } from './interface'
import dayjs from 'dayjs'
import db from '@/utils/db'
const { userInfo } = storeToRefs(user())
const OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const empty = `${OSS_URL}/empty.png`
const isAdmin = ref(false)
//
const activeNav = ref({
title: '我的孩子',
type: 1,
});
})
const navList = reactive([
{
@ -108,67 +109,67 @@ const navList = reactive([
title: '我的设备',
type: 2,
},
]);
const dataList = ref<any[]>([]);
const paging = ref(null);
])
const dataList = ref<any[]>([])
const paging = ref(null)
function swicthNav(i) {
paging.value.reload(true);
activeNav.value = i;
paging.value.reload(true)
activeNav.value = i
}
const queryList = (pageNo: number, pageSize: number) => {
if (activeNav.value.type === 1) {
getParentBindChildApi({ parentId: userInfo.value.id, current: pageNo, size: pageSize })
.then(res => {
paging.value.complete(res.data.rows);
paging.value.complete(res.data.rows)
})
.catch(res => {
paging.value.complete(false);
});
paging.value.complete(false)
})
} else {
getParentBindDeviceApi({ parentId: userInfo.value.id, current: pageNo, size: pageSize })
.then(res => {
paging.value.complete(res.data.rows);
paging.value.complete(res.data.rows)
})
.catch(res => {
paging.value.complete(false);
});
paging.value.complete(false)
})
}
};
}
//
function handleDetialPage(type: number, obj: any) {
let details = encodeURIComponent(JSON.stringify(obj));
let details = encodeURIComponent(JSON.stringify(obj))
switch (type) {
case 1:
uni.navigateTo({ url: `/pages/mine/details/childrenDetails?details=${details}` });
break;
uni.navigateTo({ url: `/pages/mine/details/childrenDetails?details=${details}` })
break
case 2:
uni.navigateTo({ url: `/pages/mine/details/deviceDetails?details=${details}` });
break;
uni.navigateTo({ url: `/pages/mine/details/deviceDetails?details=${details}` })
break
}
}
//
function handleBindDevice() {
uni.navigateTo({
url: '/pages/home/bindDevice/index',
});
})
}
const toMySupervisionService = child => {
uni.navigateTo({
url: `/pages/parents/mySupervisionService/index?id=${child.childId}`,
});
};
})
}
onShow(() => {
if (paging.value) {
paging.value.refresh();
paging.value.refresh()
}
});
})
onMounted(() => {
isAdmin.value = getCache('userAdmin');
});
isAdmin.value = db.get('userAdmin')
})
</script>
<style lang="scss" scoped>

View File

@ -9,7 +9,7 @@
<text class="name">{{ userInfo.nickName }}</text>
<text class="identity">家长</text>
</view>
<view class="function">
<!-- <view class="function">
<template v-for="i in list" :key="i.title">
<view v-if="i.show" class="function_item" @click="handleJump(i)">
<view class="photo_box">
@ -19,20 +19,21 @@
<text class="title">{{ i.title }}</text>
</view>
</template>
</view>
</view> -->
</view>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { user } from '@/store';
import { storeToRefs } from 'pinia';
import { getCache } from '@/utils';
import { onMounted, ref } from 'vue'
import { user } from '@/store'
import { storeToRefs } from 'pinia'
import { getCache } from '@/utils'
import db from '@/utils/db'
const { userInfo } = storeToRefs(user());
const { userInfo } = storeToRefs(user())
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`;
const OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const list = ref([
{
title: '扫码绑定',
@ -70,22 +71,22 @@ const list = ref([
show: true,
url: '/pages/mine/awardManage/index',
},
]);
])
function handleJump(i: AnyObject) {
uni.navigateTo({
url: i.url,
});
})
}
//
function handlePrefectInfo() {
uni.navigateTo({
url: `/pages/mine/prefectInformation/index?type=1`,
});
})
}
onMounted(() => {
list.value[1].show = getCache('userAdmin');
});
list.value[1].show = db.get('userAdmin')
})
</script>
<style lang="scss" scoped>

136
src/router/router.ts Normal file
View File

@ -0,0 +1,136 @@
import db from '../utils/db'
import dict from '../utils/dict'
import page from '../utils/page'
import qs from 'qs'
// 页面路径常量
export const route_login = '/pages/login/index'
export const route_home = '/pages/home/index'
// 免token的路由
const noTokenRoutes = [route_login]
export type _RouterNoPathOptions = {
query?: any
}
export type _RouterOptions = {
path: string
} & _RouterNoPathOptions
export type RouterOptions = _RouterOptions | string
// 封装 navigateTo
function navigateTo(options: RouterOptions) {
const to = beforeEach(options)
if (!to) return
uni.navigateTo(to)
}
// 封装 redirectTo
function redirectTo(options: RouterOptions) {
const to = beforeEach(options)
if (!to) return
uni.redirectTo(to)
}
// 封装 switchTab
function switchTab(options: RouterOptions) {
const to = beforeEach(options)
if (!to) return
uni.switchTab(to)
}
// 封装 reLaunch
function reLaunch(options: RouterOptions) {
const to = beforeEach(options)
if (!to) return
uni.reLaunch(to)
}
// 封装 navigateBack
function navigateBack(options: RouterOptions) {
const to = beforeEach(options)
if (!to) return
uni.navigateBack()
}
// 去登录页面
function toLogin(options?: _RouterNoPathOptions) {
// db.pop('token')
reLaunch({
...options,
path: route_login,
})
}
// 去首页
function toHome(options?: _RouterNoPathOptions) {
reLaunch({
...options,
path: route_home,
})
}
interface RouterBeforeOptions {
from: _RouterOptions
to: _RouterOptions
}
// 自定义路由守卫函数
function beforeEach(options: RouterOptions) {
const beforeOptions: RouterBeforeOptions = {} as any
if (typeof options === 'string') {
// 对字符串参数进行处理
options = {
path: options,
}
}
if (options.path) {
beforeOptions.to = options
}
// 对from进行处理
beforeOptions.from = {
path: page.getPagePath(),
}
// 最终封装成options = {from:{url}, to:{url}}
const { from, to } = beforeOptions
// 登录页面下跳转登录页面,跳转到首页
if (from.path === to.path && to.path === route_login) {
return false
}
console.log('beforeEach', from, to)
// 执行跳转
const token = db.get('token')
if (!noTokenRoutes.includes(to.path) && !token) {
console.log('token 过期')
toLogin(to)
return false
}
let toUrl = to.path
if (to.query) {
toUrl += '?' + qs.stringify(to.query)
}
const pageObj = {
...to,
url: toUrl,
}
console.log('跳转', pageObj)
return pageObj
}
// 导出封装的方法
export default {
navigateTo,
redirectTo,
switchTab,
reLaunch,
navigateBack,
toLogin,
toHome,
}

View File

@ -1,56 +1,57 @@
import { getCache, setCache } from '@/utils';
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { user } from '@/store';
import { bindAuthInfoApi } from '@/api';
const { afterLogin, getUserInfo } = user();
import { getCache, setCache } from '@/utils'
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { user } from '@/store'
import { bindAuthInfoApi } from '@/api'
import db from '@/utils/db'
const { afterLogin, getUserInfo } = user()
// const { } = user();
export const h5Authorization = defineStore('h5Authorization', () => {
const H5Openid = ref('');
const H5Openid = ref('')
const authorizedLogin = async () => {
// if (getCache('userInfo')) {
// await getUserInfo();
// }
const code = getQueryString('code');
const state = getQueryString('state');
console.log('进入授权code和state', code, state);
if (code) {
const userInfo = getCache('userInfo');
console.log('code----', code, state);
bindAuthInfoApi({
code: code,
userId: state,
}).then(async res => {
// H5Openid.value = res.data.openId;
// setCache('H5_OPENID', res.data.openId);
// setCache('H5_UNIONID', res.data.unionId);
// setCache('token', res.data.token);
await afterLogin();
});
} else {
console.log('正常进入');
// setCache('H5_OPENID', 'oz5g76wH2PLF9_KcbU5ztfYp6ySI');
// setCache('H5_UNIONID', 'oZnpF6aZjben0hSMvbYP4fVKyndc');
// setCache('token', 'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VySWQiOjE2ODA0MTU3NjUwOTA1OTQ4MTcsImFjY291bnQiOiIxNzY3MTYxNzkwOSIsInV1aWQiOiIzZWZhMThmMC1iOWYzLTQxYTctODkyZC1lNGY5ZDQ4MTVkYjMiLCJjbGllbnRUeXBlRW51bSI6Ik9GRklDSUFMIiwic3ViIjoiMTY4MDQxNTc2NTA5MDU5NDgxNyIsImlhdCI6MTcxNjE4ODU3NiwiZXhwIjoxNzE2NzkzMzc2fQ._1ijks84fNWBmBSPwpFwy8SR7-QOaOJRAO49H63awCxzwIB4kLhdsZPdR61h0PoF5vDzLjIV2CSw9faT0HVkGw');
// await afterLogin();
const authorizedLogin = async () => {
// if (getCache('userInfo')) {
// await getUserInfo();
// }
const code = getQueryString('code')
const state = getQueryString('state')
console.log('进入授权code和state', code, state)
if (code) {
const userInfo = db.get('userInfo')
console.log('code----', code, state)
bindAuthInfoApi({
code: code,
userId: state,
}).then(async res => {
// H5Openid.value = res.data.openId;
// setCache('H5_OPENID', res.data.openId);
// setCache('H5_UNIONID', res.data.unionId);
// setCache('token', res.data.token);
await afterLogin()
})
} else {
console.log('正常进入')
// setCache('H5_OPENID', 'oz5g76wH2PLF9_KcbU5ztfYp6ySI');
// setCache('H5_UNIONID', 'oZnpF6aZjben0hSMvbYP4fVKyndc');
// setCache('token', 'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VySWQiOjE2ODA0MTU3NjUwOTA1OTQ4MTcsImFjY291bnQiOiIxNzY3MTYxNzkwOSIsInV1aWQiOiIzZWZhMThmMC1iOWYzLTQxYTctODkyZC1lNGY5ZDQ4MTVkYjMiLCJjbGllbnRUeXBlRW51bSI6Ik9GRklDSUFMIiwic3ViIjoiMTY4MDQxNTc2NTA5MDU5NDgxNyIsImlhdCI6MTcxNjE4ODU3NiwiZXhwIjoxNzE2NzkzMzc2fQ._1ijks84fNWBmBSPwpFwy8SR7-QOaOJRAO49H63awCxzwIB4kLhdsZPdR61h0PoF5vDzLjIV2CSw9faT0HVkGw');
// await afterLogin();
// let thisUrl = encodeURIComponent(
// `${import.meta.env.VITE_H5_PATH}/#/pages/subpackage/pages/meet/VoucherCenter`,
// );
// window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd13aabeb40898e1d&redirect_uri=${thisUrl}&response_type=code&scope=snsapi_userinfo&state=123&connect_redirect=1#wechat_redirect`;
}
};
// let thisUrl = encodeURIComponent(
// `${import.meta.env.VITE_H5_PATH}/#/pages/subpackage/pages/meet/VoucherCenter`,
// );
// window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd13aabeb40898e1d&redirect_uri=${thisUrl}&response_type=code&scope=snsapi_userinfo&state=123&connect_redirect=1#wechat_redirect`;
}
}
const getQueryString = (name: string) => {
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i');
const r = window.location.search.substring(1).match(reg);
if (r !== null) return decodeURI(r[2]);
return null;
};
const getQueryString = (name: string) => {
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i')
const r = window.location.search.substring(1).match(reg)
if (r !== null) return decodeURI(r[2])
return null
}
return {
authorizedLogin,
};
});
return {
authorizedLogin,
}
})

View File

@ -1,26 +1,27 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { setCache } from '@/utils';
import { applyBindInfoListApi } from '@/api';
import type { BindApplyItemType } from '@/pages/mine/interface';
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { setCache } from '@/utils'
import { applyBindInfoListApi } from '@/api'
import type { BindApplyItemType } from '@/pages/mine/interface'
import db from '@/utils/db'
export const bindApplyStore = defineStore('bindApplyStore', () => {
const bindApplyList = ref<BindApplyItemType[]>();
const bindApplyList = ref<BindApplyItemType[]>()
// 未处理的绑定申请列表
const getApplyBindInfoList = async () => {
try {
const { data } = await applyBindInfoListApi();
bindApplyList.value = data;
const { data } = await applyBindInfoListApi()
bindApplyList.value = data
if (bindApplyList.value.length === 0) {
setCache('applyBindMsg', false);
db.set('applyBindMsg', false)
} else {
setCache('applyBindMsg', true);
db.set('applyBindMsg', true)
}
} catch (err) {
console.log(err);
console.log(err)
}
};
}
return {
bindApplyList,
getApplyBindInfoList,
};
});
}
})

View File

@ -1,41 +1,42 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { getDict as getDictApi, getUnreadNum } from '@/api';
import { setCache, getCache, removeCache, ArrToObj } from '@/utils';
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { getDict as getDictApi, getUnreadNum } from '@/api'
import { setCache, getCache, removeCache, ArrToObj } from '@/utils'
// import { SOCKET_STATUS } from '@/types';
import { user } from '@/store';
import { user } from '@/store'
import db from '@/utils/db'
export const global = defineStore('global', () => {
const dict = ref(getCache('dict') || {});
const dict = ref(db.get('dict') || {})
// 获取字典列表
const getDicts = async () => {
const res = await getDictApi();
dict.value = res.data;
setCache('dict', res.data);
};
const res = await getDictApi()
dict.value = res.data
db.set('dict', res.data)
}
// 获取字典
const getDict = (key: string, full = false) => {
const d = dict.value.find((i: anyObj) => i.code === key);
const child = d ? d.children : [];
const d = dict.value.find((i: anyObj) => i.code === key)
const child = d ? d.children : []
if (full) {
return {
dict: child,
dictObj: ArrToObj(child, 'value', 'code'),
};
}
}
return child;
};
return child
}
const clear = () => {
dict.value = {};
removeCache('dict');
};
dict.value = {}
removeCache('dict')
}
return {
dict,
getDicts,
getDict,
clear,
};
});
}
})

View File

@ -1,97 +1,98 @@
import { defineStore, storeToRefs } from 'pinia';
import { ref } from 'vue';
import { defineStore, storeToRefs } from 'pinia'
import { ref } from 'vue'
import { global } from './global';
import { getCache, setCache } from '@/utils';
import { global } from './global'
import { getCache, setCache } from '@/utils'
import db from '@/utils/db'
export const socket = defineStore('socket', () => {
const socket = ref();
const status = ref(true); // true在线 false离线
let hbTimer: any;
const hbDelay = 25000;
let rcTimer: any;
let count = 0;
let socketStatus = 0;
const channelId = '';
const rcDelay = 10000;
const socket = ref()
const status = ref(true) // true在线 false离线
let hbTimer: any
const hbDelay = 25000
let rcTimer: any
let count = 0
let socketStatus = 0
const channelId = ''
const rcDelay = 10000
const callBackList = ref<((...args: []) => void)[]>([]);
const callBackList = ref<((...args: []) => void)[]>([])
function beforeInit() {
if (socketStatus > 0) return false;
socket.value?.close(); // 关闭之前的socket
return true;
if (socketStatus > 0) return false
socket.value?.close() // 关闭之前的socket
return true
}
async function initSocket(simSerialNumber: string) {
const token = getCache('token');
init();
const token = db.get('token')
init()
function init() {
if (!beforeInit()) return;
if (!beforeInit()) return
socket.value = uni.connectSocket({
url: `${process.env.VITE_WS_URL}?accessToken=${token}`,
complete: () => {},
});
})
socket.value.onOpen(() => {
console.log('Socket已打开', simSerialNumber);
count = 0;
socketStatus = 10;
clearInterval(hbTimer);
clearInterval(rcTimer);
heartBeat(); // 心跳
socketSend({ type: 'desktopPreview', simSerialNumber: simSerialNumber });
console.log('Socket已打开', simSerialNumber)
count = 0
socketStatus = 10
clearInterval(hbTimer)
clearInterval(rcTimer)
heartBeat() // 心跳
socketSend({ type: 'desktopPreview', simSerialNumber: simSerialNumber })
// status.value = SOCKET_STATUS.CONNECTED;
});
})
socket.value.onError((err: any) => {
// console.log('Socket打开失败');
console.error(err);
socketStatus = 0;
console.error(err)
socketStatus = 0
// status.value = SOCKET_STATUS.OFFLINE;
reconnect();
});
reconnect()
})
socket.value.onClose((err: any) => {
// console.log('Socket已断开');
console.error(err);
socketStatus = 0;
console.error(err)
socketStatus = 0
// status.value = SOCKET_STATUS.OFFLINE;
reconnect();
});
reconnect()
})
socket.value.onMessage((res: anyObj) => {
// 接收服务器返回信息
const info = JSON.parse(res.data);
console.log('socketMsg', info);
uni.$emit('socketMsg', info);
});
const info = JSON.parse(res.data)
console.log('socketMsg', info)
uni.$emit('socketMsg', info)
})
}
// 心跳
function _heartBeat() {
// console.log('心跳')
if (!getCache('token')) {
socket.value?.close();
clearInterval(hbTimer);
return;
if (!db.get('token')) {
socket.value?.close()
clearInterval(hbTimer)
return
}
socketSend({
message: 'ping',
});
})
}
function heartBeat() {
_heartBeat(); // 首次连上必须ping才建立通道
hbTimer = setInterval(() => _heartBeat(), hbDelay);
_heartBeat() // 首次连上必须ping才建立通道
hbTimer = setInterval(() => _heartBeat(), hbDelay)
}
// 重连
function reconnect(leading = false) {
clearInterval(hbTimer);
clearInterval(hbTimer)
if (leading) {
init();
return;
init()
return
}
rcTimer = setTimeout(() => {
count++;
console.error(`Socket尝试重连${count}次)`);
init();
}, 10000);
count++
console.error(`Socket尝试重连${count}次)`)
init()
}, 10000)
}
}
@ -102,31 +103,31 @@ export const socket = defineStore('socket', () => {
// 发送消息
function socketSend(value: any) {
console.log('send', value);
console.log('send', value)
socket.value.send({
data: JSON.stringify(value),
success: () => {
console.log('发送成功');
console.log('发送成功')
},
});
})
}
// 增加回调
function addCallBack(cb: any) {
if (callBackList.value.some(i => i === cb)) return;
callBackList.value.push(cb);
if (callBackList.value.some(i => i === cb)) return
callBackList.value.push(cb)
}
// 删除回调
function removeCallBack(cb: any) {
const idx = callBackList.value.findIndex(i => i === cb);
if (idx === -1) return;
callBackList.value.splice(idx, 1);
const idx = callBackList.value.findIndex(i => i === cb)
if (idx === -1) return
callBackList.value.splice(idx, 1)
}
// 关闭socket
function closeSocket() {
socket.value?.close();
socket.value?.close()
}
return {
@ -139,5 +140,5 @@ export const socket = defineStore('socket', () => {
removeCallBack,
closeSocket,
callback,
};
});
}
})

View File

@ -1,5 +1,5 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { defineStore } from 'pinia'
import { ref } from 'vue'
import {
// phoneLogin as phoneLoginApi,
getUserInfo as getUserInfoApi,
@ -9,96 +9,71 @@ import {
bindRegId,
userInfoPermitApi,
// updatePwdByPhone,
} from '@/api';
} from '@/api'
// import type { smsLoginType, accountLoginType, updatePasswordType } from '@/api';
// import defaultAvatar from "@/static/default_avatar.png";
import { setCache, getCache } from '@/utils';
import { global } from '@/store';
import { setCache, getCache } from '@/utils'
import { global } from '@/store'
import db from '@/utils/db'
export const user = defineStore('user', () => {
const userInfo = ref(getCache('userInfo') || {});
const csInfo = ref(getCache('csInfo') || {});
const token = ref(getCache('token') || '');
// const { clear: chatClear } = chat();
const { getDicts } = global();
// const phoneLogin = async (data: smsLoginType) => {
// await beforeLogin();
// const res = await phoneLoginApi(data);
// token.value = res.data;
// setCache('token', res.data);
// await afterLogin();
// };
// const accordLogin = async (data: accountLoginType) => {
// await beforeLogin();
// const res = await psdLoginApi(data);
// token.value = res.data;
// setCache('token', res.data);
// await afterLogin();
// };
// const updatePassword = async (data: updatePasswordType) => {
// await updatePwdByPhone(data);
// };
// const beforeLogin = async () => {
// // chatClear();
// await clear();
// };
const userInfo = ref(db.get('userInfo') || ({} as any))
const csInfo = ref(db.get('csInfo') || {})
const token = ref(db.get('token') || '')
const { getDicts } = global()
const afterLogin = async () => {
await Promise.allSettled([getUserInfo(), getDicts()]);
await Promise.allSettled([getUserInfo(), getDicts()])
// getCsInfo(); // 需等待用户信息加载完毕
};
}
const logout = async () => {
// #ifdef APP-PLUS
if (getCache('registerID')) {
if (db.get('registerID')) {
await bindRegId({
registrationId: getCache('registerID'),
registrationId: db.get('registerID'),
type: 2,
});
})
}
// #endif
await logoutApi();
clear();
await logoutApi()
clear()
uni.reLaunch({
url: '/pages/login/index',
});
};
})
}
const getUserInfo = async () => {
const res = await getUserInfoApi();
console.log('userInfo', res.data);
userInfo.value = res.data;
setCache('userInfo', res.data);
getUserInfoPermit();
return res.data;
};
const res = await getUserInfoApi()
console.log('userInfo', res.data)
userInfo.value = res.data
db.set('userInfo', res.data)
getUserInfoPermit()
return res.data
}
// 当前登录用户是否管理员身份
async function getUserInfoPermit() {
const { data } = await userInfoPermitApi();
setCache('userAdmin', data);
const { data } = await userInfoPermitApi()
db.set('userAdmin', data)
}
const getCsInfo = async () => {
const res = await getCsInfoApi(userInfo.value.id);
csInfo.value = res.data;
setCache('csInfo', res.data);
return res.data;
};
const res = await getCsInfoApi(userInfo.value.id)
csInfo.value = res.data
db.set('csInfo', res.data)
return res.data
}
const clear = async () => {
token.value = '';
userInfo.value = {};
csInfo.value = {};
await uni.clearStorageSync();
};
token.value = ''
userInfo.value = {}
csInfo.value = {}
await db.clear()
}
const setToken = (data: string) => {
token.value = data;
setCache('token', data);
};
token.value = data
db.set('token', data)
}
return {
userInfo,
@ -115,5 +90,5 @@ export const user = defineStore('user', () => {
clear,
afterLogin,
setToken,
};
});
}
})

37
src/utils/db.ts Normal file
View File

@ -0,0 +1,37 @@
import page from './page'
// 可以在不同的地方共享数据、传参
function get<T>(key?: string, defaultValue?: T): T {
if (!key) {
key = page.getPagePath()
}
const val = uni.getStorageSync(key)
return (val === undefined ? defaultValue : val) as T
}
// 设值
function set(key: string, value: any) {
uni.setStorageSync(key, value)
}
// 弹出值
function pop<T>(key?: string, defaultValue?: T): T {
if (!key) {
key = page.getPagePath()
}
const value = uni.getStorageSync(key)
uni.removeStorageSync(key)
return value || defaultValue
}
// 清空
function clear() {
uni.clearStorageSync()
}
export default {
get,
set,
pop,
clear,
}

79
src/utils/dict.ts Normal file
View File

@ -0,0 +1,79 @@
import page from './page'
// 可以在不同的地方共享数据、传参
let _DATA: { [key: string]: any } = {}
function get<T>(key?: string, defaultValue?: T): T {
if (!key) {
key = page.getPagePath()
}
const val = _DATA[key]
return (val === undefined ? defaultValue : val) as T
}
// 设值
function set(key: string, value: any) {
_DATA[key] = value
}
// 弹出值
function pop<T>(key?: string, defaultValue?: T): T {
if (!key) {
key = page.getPagePath()
}
const value = _DATA[key]
delete _DATA[key]
return value || defaultValue
}
// 清空
function clear() {
_DATA = {}
}
// 函数的key
function _pageFnObjKey(pageUrl: string) {
return pageUrl + '_mj_fn_obj'
}
function _getPageFnObj(pageUrl: string) {
const key = _pageFnObjKey(pageUrl)
let fnObj = _DATA[key]
if (!fnObj) {
fnObj = {}
_DATA[key] = fnObj
}
return fnObj
}
// 调用函数
function callFn(key: string, ...args: any) {
// 函数对象
const fn = _getPageFnObj(page.getPagePath())[key]
if (fn) {
// 直接调用
return fn(...args)
}
// console.log('callFn', _DATA)
}
// 存储函数
function setFn(key: string, fn: any) {
_getPageFnObj(page.getPagePath())[key] = fn
// console.log('setFn', _DATA)
}
function popPageFns(pageUrl: string) {
delete _DATA[_pageFnObjKey(pageUrl)]
// console.log('popPageFns', _DATA)
}
export default {
get,
set,
pop,
clear,
callFn,
setFn,
popPageFns,
}

25
src/utils/obj.ts Normal file
View File

@ -0,0 +1,25 @@
// 对象相关处理
function clearNullProps(obj: any) {
for (const key in obj) {
if (obj[key] === null || obj[key] === undefined) {
delete obj[key]
}
}
}
// 计算父节点和子节点的总数
function getNodesSize(nodes: any[], childrenKey = 'children') {
let size = 0
for (const node of nodes) {
size += 1
if (node[childrenKey]?.length > 0) {
size += getNodesSize(node.children, childrenKey)
}
}
return size
}
export default {
clearNullProps,
getNodesSize,
}

15
src/utils/page.ts Normal file
View File

@ -0,0 +1,15 @@
const DATA: { [key: string]: any } = {}
function getPage() {
const pages = getCurrentPages()
return pages[pages.length - 1]
}
function getPagePath() {
return '/' + getPage().route
}
export default {
getPage,
getPagePath,
}

51
src/utils/toast.ts Normal file
View File

@ -0,0 +1,51 @@
export async function info(text: string, duration?: number) {}
export async function error(text: string, duration?: number) {
uni.showToast({
title: text,
icon: 'none',
duration,
})
}
export async function warn(text: string, duration?: number) {}
export async function success(text: string, duration?: number) {
uni.showToast({
title: text,
icon: 'none',
duration,
})
}
export async function primary(text: string, duration?: number) {}
export function loading(text: string = '加载中...') {
uni.showLoading({
title: text,
mask: true,
})
}
export function dialog(text: string) {
uni.showModal({
content: text,
confirmText: '知道了',
showCancel: false,
})
}
export function hide() {
uni.hideLoading()
}
export default {
info,
success,
error,
loading,
warn,
primary,
hide,
dialog,
}

View File

@ -1,29 +1,30 @@
import dayjs from 'dayjs';
import isToday from 'dayjs/plugin/isToday';
import isYesterday from 'dayjs/plugin/isYesterday';
import dayjs from 'dayjs'
import isToday from 'dayjs/plugin/isToday'
import isYesterday from 'dayjs/plugin/isYesterday'
import db from './db'
const OSS_URL = import.meta.env.VITE_OSS_HOST;
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`;
const OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
dayjs.extend(isToday);
dayjs.extend(isYesterday);
dayjs.extend(isToday)
dayjs.extend(isYesterday)
// store统一设置
export const setCache = (key: string, value: any) => {
if (!key) throw new Error('key is required');
uni.setStorageSync(`QY_${key?.toUpperCase()}`, value);
};
if (!key) throw new Error('key is required')
uni.setStorageSync(`QY_${key?.toUpperCase()}`, value)
}
export const getCache = (key: string) => {
if (!key) throw new Error('key is required');
return uni.getStorageSync(`QY_${key?.toUpperCase()}`);
};
if (!key) throw new Error('key is required')
return uni.getStorageSync(`QY_${key?.toUpperCase()}`)
}
export const removeCache = (key: string) => {
if (!key) throw new Error('key is required');
uni.removeStorageSync(`QY_${key?.toUpperCase()}`);
};
if (!key) throw new Error('key is required')
uni.removeStorageSync(`QY_${key?.toUpperCase()}`)
}
// 随机ID
export const genId = (prefix?: number | string) =>
`${prefix || ''}${Math.random().toString(16).slice(2)}`;
`${prefix || ''}${Math.random().toString(16).slice(2)}`
// 将数组映射为对象
export const ArrToObj = (
@ -31,61 +32,61 @@ export const ArrToObj = (
key = 'code',
value = 'value',
): { [key: string]: string } => {
const obj: anyObj = {};
let i = 0;
const obj: anyObj = {}
let i = 0
for (i; i < arr.length; i++) {
obj[arr[i][key]] = arr[i][value];
obj[arr[i][key]] = arr[i][value]
}
return obj;
};
return obj
}
// 延迟运行
export const $sleep = (time: number) => {
return new Promise(res => {
const timeout = setTimeout(() => {
res(0);
clearTimeout(timeout);
}, time);
});
};
res(0)
clearTimeout(timeout)
}, time)
})
}
export function formCheck(rules: anyObj[], data: anyObj) {
let res = true;
let res = true
for (const i of rules) {
if (i instanceof Array) {
for (const j of i) {
if (j.required && !data[j.prop]) {
res = false;
res = false
uni.showToast({
title: j.message,
icon: 'none',
});
break;
})
break
}
if (j.validator) {
j.validator(data, data[j.prop], (result: any) => {
if (result instanceof Error) {
res = false;
res = false
uni.showToast({
title: j.message,
icon: 'none',
});
})
}
});
})
}
}
} else {
if (i.required && !data[i.prop]) {
res = false;
res = false
uni.showToast({
title: i.message,
icon: 'none',
});
break;
})
break
}
}
}
return res;
return res
}
// // uniApi转换成同步
@ -121,46 +122,77 @@ export const uploadFile = path =>
filePath: path,
name: 'file',
header: {
Authorization: `Bearer ${getCache('token')}`,
Authorization: `Bearer ${db.get('token')}`,
},
success: uploadFileRes => {
const data = JSON.parse(uploadFileRes.data);
const data = JSON.parse(uploadFileRes.data)
if (uploadFileRes.statusCode === 200) {
resolve(data.data);
resolve(data.data)
} else {
reject(data.message);
reject(data.message)
}
},
fail: error => {
reject(error);
reject(error)
},
});
});
})
})
/**
*
*/
export const minToHour = (min: number) => {
const h = Math.floor(min / 60);
const m = min % 60;
return [h, m];
};
const h = Math.floor(min / 60)
const m = min % 60
return [h, m]
}
export const formatDate = (time: string) => {
const timestamp = new Date(time).getTime();
const date = dayjs(timestamp);
if (date.isToday()) return date.format('HH:mm');
if (date.isYesterday()) return `昨天 ${date.format('HH:mm')}`;
const timestamp = new Date(time).getTime()
const date = dayjs(timestamp)
if (date.isToday()) return date.format('HH:mm')
if (date.isYesterday()) return `昨天 ${date.format('HH:mm')}`
if (date.isSame(dayjs(), 'week') && (date.day() !== 0 || dayjs().day() === 0)) {
const daysOfWeek = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
return `${daysOfWeek[date.day()]} ${date.format('HH:mm')}`;
const daysOfWeek = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
return `${daysOfWeek[date.day()]} ${date.format('HH:mm')}`
}
return date.format('YYYY年M月D日 HH:mm');
};
return date.format('YYYY年M月D日 HH:mm')
}
export const getAvatarUrl = (url: string) => {
if (url && url.includes('http')) {
return url;
return url
}
return defaultAvatar;
};
return defaultAvatar
}
/**
* URL
*/
// 手动解析 URL 参数 (兼容性更好)
export const parseUrlParams = (url?: string): Record<string, string> => {
const targetUrl = url || (typeof location !== 'undefined' ? location.href : '')
const params: Record<string, string> = {}
if (!targetUrl) return params
try {
// 获取查询字符串部分
const queryString = targetUrl.split('?')[1]
if (!queryString) return params
// 分割参数
const pairs = queryString.split('&')
pairs.forEach(pair => {
const [key, value] = pair.split('=')
if (key) {
params[decodeURIComponent(key)] = decodeURIComponent(value || '')
}
})
return params
} catch (error) {
console.warn('URL 参数解析失败:', error)
return params
}
}

View File

@ -29,14 +29,18 @@ export default defineConfig({
},
},
server: {
port: 5173,
port: 1234,
open: true,
proxy: {
'/api': {
target: 'http://127.0.0.1:9053',
// target: 'https://test.pi.xuexiaole.com',
changeOrigin: true,
},
},
},
// server: {
// port: 5173,
// open: true,
// proxy: {
// '/api': {
// target: 'http://127.0.0.1:9053',
// // target: 'https://test.pi.xuexiaole.com',
// changeOrigin: true,
// },
// },
// },
});