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 = https://pi.xuexiaole.com
# VITE_HOST = http://192.168.0.103
VITE_OSS_HOST = https://xuexiaole-1313840333.cos.ap-guangzhou.myqcloud.com/xuexiaoleClient VITE_OSS_HOST = https://xuexiaole-1313840333.cos.ap-guangzhou.myqcloud.com/xuexiaoleClient
VITE_WS_URL = wss://pi.xuexiaole.com/ws/device 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_OSS_HOST = https://xuexiaole-1313840333.cos.ap-guangzhou.myqcloud.com/xuexiaoleClient
VITE_WS_URL = wss://test.pi.xuexiaole.com/ws/device 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_OSS_HOST = https://xuexiaole-1313840333.cos.ap-guangzhou.myqcloud.com/xuexiaoleClient
VITE_WS_URL = wss://test.pi.xuexiaole.com/ws/device 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* yarn-error.log*
pnpm-debug.log* pnpm-debug.log*
lerna-debug.log* lerna-debug.log*
.temp
*.gz
node_modules node_modules
.DS_Store .DS_Store

View File

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

View File

@ -47,5 +47,6 @@
"src/uni_modules/uni-popup/components/uni-popup/i18n", "src/uni_modules/uni-popup/components/uni-popup/i18n",
"src/uni_modules/uni-search-bar/components/uni-search-bar/i18n", "src/uni_modules/uni-search-bar/components/uni-search-bar/i18n",
"src/uni_modules/z-paging/components/z-paging/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", "version": "0.1.0",
"scripts": { "scripts": {
"dev:app": "uni -p app", "dev:app": "uni -p app",
"dev:app-android": "uni -p app-android", "dev:app-android": "uni -p app-android",
"dev:app-ios": "uni -p app-ios", "dev:app-ios": "uni -p app-ios",
"dev:custom": "uni -p", "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:h5:ssr": "uni --ssr",
"dev:mp-alipay": "uni -p mp-alipay", "dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu", "dev:mp-baidu": "uni -p mp-baidu",
@ -56,16 +57,17 @@
"@dcloudio/uni-mp-toutiao": "3.0.0-3081220230817001", "@dcloudio/uni-mp-toutiao": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-weixin": "3.0.0-3081220230817001", "@dcloudio/uni-mp-weixin": "3.0.0-3081220230817001",
"@dcloudio/uni-quickapp-webview": "3.0.0-3081220230817001", "@dcloudio/uni-quickapp-webview": "3.0.0-3081220230817001",
"@vueuse/core": "^10.11.0",
"code-inspector-plugin": "^0.10.1", "code-inspector-plugin": "^0.10.1",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"echarts": "^5.5.1", "echarts": "^5.5.1",
"lint-staged": "^15.0.1", "lint-staged": "^15.0.1",
"pinia": "^2.0.36", "pinia": "^2.0.36",
"qs": "^6.14.0",
"sass": "^1.72.0", "sass": "^1.72.0",
"unplugin-vue-define-options": "^1.4.2", "unplugin-vue-define-options": "^1.4.2",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-i18n": "^9.1.9", "vue-i18n": "^9.1.9",
"@vueuse/core": "^10.11.0",
"vue-qrcode-reader": "^5.5.7", "vue-qrcode-reader": "^5.5.7",
"weixin-js-sdk": "^1.6.5" "weixin-js-sdk": "^1.6.5"
}, },
@ -102,25 +104,5 @@
"prettier --write", "prettier --write",
"eslint --fix" "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"> <script setup lang="ts">
import { onMounted, nextTick } from 'vue'; import { onMounted, nextTick } from 'vue'
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'; import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
import { parseUrlParams } from '@/utils/tool'
onLaunch(() => { onLaunch(() => {
console.log('App Launch'); console.log('App Launch')
}); })
onShow(() => { onShow(() => {
console.log('App Show'); console.log('App Show')
}); })
onHide(() => { onHide(() => {
console.log('App Hide'); console.log('App Hide')
}); })
</script> </script>
<style lang="scss"> <style lang="scss">
page { page {

View File

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

View File

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

View File

@ -1,44 +1,44 @@
import { user } from '@/store'; import { user } from '@/store'
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia'
import { getCache } from '@/utils'; import { getCache } from '@/utils'
import db from '@/utils/db'
const CONFIG = { const CONFIG = {
// host: import.meta.env.VITE_HOST || '', baseURL: `${import.meta.env.VITE_HOST}/api/main`,
// baseURL: 'http://127.0.0.1:9053/api/main', // baseURL: '/api/main',
baseURL: '/api/main',
timeout: 60000, timeout: 60000,
method: 'GET', method: 'GET',
}; }
export class HttpError extends Error { export class HttpError extends Error {
data: any; data: any
constructor(message: string, data: Record<string, any>) { constructor(message: string, data: Record<string, any>) {
super(message); super(message)
this.data = data; this.data = data
} }
} }
const request = async (config: Record<string, any>): Promise<any> => { const request = async (config: Record<string, any>): Promise<any> => {
const networkType = await uni.getNetworkType(); const networkType = await uni.getNetworkType()
if (networkType.networkType === 'none') { if (networkType.networkType === 'none') {
uni.showModal({ uni.showModal({
content: '暂无网络,请恢复网络后使用', content: '暂无网络,请恢复网络后使用',
confirmText: '知道了', confirmText: '知道了',
showCancel: false, showCancel: false,
confirmColor: '#ffe60f', confirmColor: '#ffe60f',
}); })
return Promise.reject( return Promise.reject(
new HttpError('暂无网络,请恢复网络后使用', { new HttpError('暂无网络,请恢复网络后使用', {
code: '-1', code: '-1',
}), }),
); )
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const { clear } = user(); const { clear } = user()
const { token } = storeToRefs(user()); const { token } = storeToRefs(user())
const mergerToken = token.value || getCache('token'); const mergerToken = token.value || db.get('token')
const method = (config.method || CONFIG.method).toUpperCase(); const method = (config.method || CONFIG.method).toUpperCase()
uni.request({ uni.request({
method, method,
@ -53,41 +53,41 @@ const request = async (config: Record<string, any>): Promise<any> => {
complete(res: anyObj) { complete(res: anyObj) {
if (res.statusCode === 200) { if (res.statusCode === 200) {
if (res.data.code === 200) { if (res.data.code === 200) {
return resolve(res.data); return resolve(res.data)
} else { } else {
if (!config.showToast) { if (!config.showToast) {
uni.showToast({ uni.showToast({
title: res.data?.message, title: res.data?.message,
icon: 'none', icon: 'none',
duration: 3000, duration: 3000,
}); })
} }
return reject(new HttpError(res.data?.message, res.data)); return reject(new HttpError(res.data?.message, res.data))
} }
} else { } else {
res.href = (config.baseURL || CONFIG.baseURL) + config.url; res.href = (config.baseURL || CONFIG.baseURL) + config.url
if (res.statusCode === 401) { if (res.statusCode === 401) {
clear(); clear()
uni.reLaunch({ uni.reLaunch({
url: '/pages/login/index', url: '/pages/login/index',
}); })
} else { } else {
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: title:
res.statusCode === 500 ? '服务异常' : res?.data?.message || '服务异常,请稍后重试', res.statusCode === 500 ? '服务异常' : res?.data?.message || '服务异常,请稍后重试',
}); })
} }
return reject( return reject(
new HttpError(res.data?.message, { new HttpError(res.data?.message, {
code: res.statusCode, code: res.statusCode,
data: res.data, 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> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onShow } from '@dcloudio/uni-app'; import { onShow } from '@dcloudio/uni-app'
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue'
import { bindApplyStore } from '@/store'; import { bindApplyStore } from '@/store'
import { getCache } from '@/utils'; import { getCache } from '@/utils'
import db from '@/utils/db'
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
selectedIndex: number; selectedIndex: number
}>(), }>(),
{ selectedIndex: 0 }, { selectedIndex: 0 },
); )
const { getApplyBindInfoList } = bindApplyStore(); const { getApplyBindInfoList } = bindApplyStore()
const currentIndex = ref(0); const currentIndex = ref(0)
const list = ref([]); const list = ref([])
const color = ref<string>('#8E8D9D'); const color = ref<string>('#8E8D9D')
const selectedColor = ref<string>('#625EFF'); const selectedColor = ref<string>('#625EFF')
const notice = ref(false); const notice = ref(false)
function switchTab(item, index) { function switchTab(item, index) {
currentIndex.value = index; currentIndex.value = index
let url = item.pagePath; let url = item.pagePath
uni.redirectTo({ url: url }); uni.redirectTo({ url: url })
} }
onMounted(async () => { onMounted(async () => {
currentIndex.value = props.selectedIndex; currentIndex.value = props.selectedIndex
let adminType = getCache('userInfo').adminType; //
if (adminType === 16) { await getApplyBindInfoList()
// notice.value = db.get('applyBindMsg')
await getApplyBindInfoList(); list.value = [
notice.value = getCache('applyBindMsg'); {
list.value = [ pagePath: '/pages/home/index',
{ iconPath: '/static/tabBar/homeno.png',
pagePath: '/pages/home/index', selectedIconPath: '/static/tabBar/home.png',
iconPath: '/static/tabBar/homeno.png', text: '首页',
selectedIconPath: '/static/tabBar/home.png', },
text: '首页', {
}, pagePath: '/pages/academicReport/index',
{ iconPath: '/static/tabBar/studyReportNo.png',
pagePath: '/pages/academicReport/index', selectedIconPath: '/static/tabBar/studyReport.png',
iconPath: '/static/tabBar/studyReportNo.png', text: '学情报告',
selectedIconPath: '/static/tabBar/studyReport.png', },
text: '学情报告', {
}, pagePath: '/pages/applicationManagement/index',
{ iconPath: '/static/tabBar/applicationNo.png',
pagePath: '/pages/applicationManagement/index', selectedIconPath: '/static/tabBar/application.png',
iconPath: '/static/tabBar/applicationNo.png', text: '应用管控',
selectedIconPath: '/static/tabBar/application.png', },
text: '应用管控', {
}, pagePath: '/pages/mine/index',
{ iconPath: '/static/tabBar/mineno.png',
pagePath: '/pages/mine/index', selectedIconPath: '/static/tabBar/mine.png',
iconPath: '/static/tabBar/mineno.png', text: '我的',
selectedIconPath: '/static/tabBar/mine.png', },
text: '我的', ]
},
]; // let adminType = getCache('userInfo').adminType;
} else if (adminType === 6) { // if (adminType === 16) {
// // //
uni.reLaunch({ // await getApplyBindInfoList();
url: '/pages/inspector/schedule/index', // notice.value = getCache('applyBindMsg');
}); // list.value = [
list.value = [ // {
{ // pagePath: '/pages/home/index',
pagePath: '/pages/inspector/schedule/index', // iconPath: '/static/tabBar/homeno.png',
iconPath: '/static/tabBar/scheduleNo.png', // selectedIconPath: '/static/tabBar/home.png',
selectedIconPath: '/static/tabBar/schedule.png', // text: '',
text: '课表', // },
}, // {
{ // pagePath: '/pages/academicReport/index',
pagePath: '/pages/inspector/student/index', // iconPath: '/static/tabBar/studyReportNo.png',
iconPath: '/static/tabBar/studentNo.png', // selectedIconPath: '/static/tabBar/studyReport.png',
selectedIconPath: '/static/tabBar/student.png', // text: '',
text: '学员', // },
}, // {
{ // pagePath: '/pages/applicationManagement/index',
pagePath: '/pages/inspector/mine/index', // iconPath: '/static/tabBar/applicationNo.png',
iconPath: '/static/tabBar/mineno.png', // selectedIconPath: '/static/tabBar/application.png',
selectedIconPath: '/static/tabBar/mine.png', // text: '',
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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@
<text class="name">{{ userInfo.nickName }}</text> <text class="name">{{ userInfo.nickName }}</text>
<text class="identity">家长</text> <text class="identity">家长</text>
</view> </view>
<view class="function"> <!-- <view class="function">
<template v-for="i in list" :key="i.title"> <template v-for="i in list" :key="i.title">
<view v-if="i.show" class="function_item" @click="handleJump(i)"> <view v-if="i.show" class="function_item" @click="handleJump(i)">
<view class="photo_box"> <view class="photo_box">
@ -19,20 +19,21 @@
<text class="title">{{ i.title }}</text> <text class="title">{{ i.title }}</text>
</view> </view>
</template> </template>
</view> </view> -->
</view> </view>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue'
import { user } from '@/store'; import { user } from '@/store'
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia'
import { getCache } from '@/utils'; 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 OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`; const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const list = ref([ const list = ref([
{ {
title: '扫码绑定', title: '扫码绑定',
@ -70,22 +71,22 @@ const list = ref([
show: true, show: true,
url: '/pages/mine/awardManage/index', url: '/pages/mine/awardManage/index',
}, },
]); ])
function handleJump(i: AnyObject) { function handleJump(i: AnyObject) {
uni.navigateTo({ uni.navigateTo({
url: i.url, url: i.url,
}); })
} }
// //
function handlePrefectInfo() { function handlePrefectInfo() {
uni.navigateTo({ uni.navigateTo({
url: `/pages/mine/prefectInformation/index?type=1`, url: `/pages/mine/prefectInformation/index?type=1`,
}); })
} }
onMounted(() => { onMounted(() => {
list.value[1].show = getCache('userAdmin'); list.value[1].show = db.get('userAdmin')
}); })
</script> </script>
<style lang="scss" scoped> <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 { getCache, setCache } from '@/utils'
import { defineStore } from 'pinia'; import { defineStore } from 'pinia'
import { ref } from 'vue'; import { ref } from 'vue'
import { user } from '@/store'; import { user } from '@/store'
import { bindAuthInfoApi } from '@/api'; import { bindAuthInfoApi } from '@/api'
const { afterLogin, getUserInfo } = user(); import db from '@/utils/db'
const { afterLogin, getUserInfo } = user()
// const { } = user(); // const { } = user();
export const h5Authorization = defineStore('h5Authorization', () => { export const h5Authorization = defineStore('h5Authorization', () => {
const H5Openid = ref(''); const H5Openid = ref('')
const authorizedLogin = async () => { const authorizedLogin = async () => {
// if (getCache('userInfo')) { // if (getCache('userInfo')) {
// await getUserInfo(); // await getUserInfo();
// } // }
const code = getQueryString('code'); const code = getQueryString('code')
const state = getQueryString('state'); const state = getQueryString('state')
console.log('进入授权code和state', code, state); console.log('进入授权code和state', code, state)
if (code) { if (code) {
const userInfo = getCache('userInfo'); const userInfo = db.get('userInfo')
console.log('code----', code, state); console.log('code----', code, state)
bindAuthInfoApi({ bindAuthInfoApi({
code: code, code: code,
userId: state, userId: state,
}).then(async res => { }).then(async res => {
// H5Openid.value = res.data.openId; // H5Openid.value = res.data.openId;
// setCache('H5_OPENID', res.data.openId); // setCache('H5_OPENID', res.data.openId);
// setCache('H5_UNIONID', res.data.unionId); // setCache('H5_UNIONID', res.data.unionId);
// setCache('token', res.data.token); // setCache('token', res.data.token);
await afterLogin(); await afterLogin()
}); })
} else { } else {
console.log('正常进入'); console.log('正常进入')
// setCache('H5_OPENID', 'oz5g76wH2PLF9_KcbU5ztfYp6ySI'); // setCache('H5_OPENID', 'oz5g76wH2PLF9_KcbU5ztfYp6ySI');
// setCache('H5_UNIONID', 'oZnpF6aZjben0hSMvbYP4fVKyndc'); // setCache('H5_UNIONID', 'oZnpF6aZjben0hSMvbYP4fVKyndc');
// setCache('token', 'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VySWQiOjE2ODA0MTU3NjUwOTA1OTQ4MTcsImFjY291bnQiOiIxNzY3MTYxNzkwOSIsInV1aWQiOiIzZWZhMThmMC1iOWYzLTQxYTctODkyZC1lNGY5ZDQ4MTVkYjMiLCJjbGllbnRUeXBlRW51bSI6Ik9GRklDSUFMIiwic3ViIjoiMTY4MDQxNTc2NTA5MDU5NDgxNyIsImlhdCI6MTcxNjE4ODU3NiwiZXhwIjoxNzE2NzkzMzc2fQ._1ijks84fNWBmBSPwpFwy8SR7-QOaOJRAO49H63awCxzwIB4kLhdsZPdR61h0PoF5vDzLjIV2CSw9faT0HVkGw'); // setCache('token', 'eyJhbGciOiJIUzUxMiJ9.eyJ1c2VySWQiOjE2ODA0MTU3NjUwOTA1OTQ4MTcsImFjY291bnQiOiIxNzY3MTYxNzkwOSIsInV1aWQiOiIzZWZhMThmMC1iOWYzLTQxYTctODkyZC1lNGY5ZDQ4MTVkYjMiLCJjbGllbnRUeXBlRW51bSI6Ik9GRklDSUFMIiwic3ViIjoiMTY4MDQxNTc2NTA5MDU5NDgxNyIsImlhdCI6MTcxNjE4ODU3NiwiZXhwIjoxNzE2NzkzMzc2fQ._1ijks84fNWBmBSPwpFwy8SR7-QOaOJRAO49H63awCxzwIB4kLhdsZPdR61h0PoF5vDzLjIV2CSw9faT0HVkGw');
// await afterLogin(); // await afterLogin();
// let thisUrl = encodeURIComponent( // let thisUrl = encodeURIComponent(
// `${import.meta.env.VITE_H5_PATH}/#/pages/subpackage/pages/meet/VoucherCenter`, // `${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`; // 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 getQueryString = (name: string) => {
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i'); const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`, 'i')
const r = window.location.search.substring(1).match(reg); const r = window.location.search.substring(1).match(reg)
if (r !== null) return decodeURI(r[2]); if (r !== null) return decodeURI(r[2])
return null; return null
}; }
return { return {
authorizedLogin, authorizedLogin,
}; }
}); })

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
import { defineStore } from 'pinia'; import { defineStore } from 'pinia'
import { ref } from 'vue'; import { ref } from 'vue'
import { import {
// phoneLogin as phoneLoginApi, // phoneLogin as phoneLoginApi,
getUserInfo as getUserInfoApi, getUserInfo as getUserInfoApi,
@ -9,96 +9,71 @@ import {
bindRegId, bindRegId,
userInfoPermitApi, userInfoPermitApi,
// updatePwdByPhone, // updatePwdByPhone,
} from '@/api'; } from '@/api'
// import type { smsLoginType, accountLoginType, updatePasswordType } from '@/api'; // import type { smsLoginType, accountLoginType, updatePasswordType } from '@/api';
// import defaultAvatar from "@/static/default_avatar.png"; // import defaultAvatar from "@/static/default_avatar.png";
import { setCache, getCache } from '@/utils'; import { setCache, getCache } from '@/utils'
import { global } from '@/store'; import { global } from '@/store'
import db from '@/utils/db'
export const user = defineStore('user', () => { export const user = defineStore('user', () => {
const userInfo = ref(getCache('userInfo') || {}); const userInfo = ref(db.get('userInfo') || ({} as any))
const csInfo = ref(getCache('csInfo') || {}); const csInfo = ref(db.get('csInfo') || {})
const token = ref(getCache('token') || ''); const token = ref(db.get('token') || '')
// const { clear: chatClear } = chat(); const { getDicts } = global()
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 afterLogin = async () => { const afterLogin = async () => {
await Promise.allSettled([getUserInfo(), getDicts()]); await Promise.allSettled([getUserInfo(), getDicts()])
// getCsInfo(); // 需等待用户信息加载完毕 // getCsInfo(); // 需等待用户信息加载完毕
}; }
const logout = async () => { const logout = async () => {
// #ifdef APP-PLUS // #ifdef APP-PLUS
if (getCache('registerID')) { if (db.get('registerID')) {
await bindRegId({ await bindRegId({
registrationId: getCache('registerID'), registrationId: db.get('registerID'),
type: 2, type: 2,
}); })
} }
// #endif // #endif
await logoutApi(); await logoutApi()
clear(); clear()
uni.reLaunch({ uni.reLaunch({
url: '/pages/login/index', url: '/pages/login/index',
}); })
}; }
const getUserInfo = async () => { const getUserInfo = async () => {
const res = await getUserInfoApi(); const res = await getUserInfoApi()
console.log('userInfo', res.data); console.log('userInfo', res.data)
userInfo.value = res.data; userInfo.value = res.data
setCache('userInfo', res.data); db.set('userInfo', res.data)
getUserInfoPermit(); getUserInfoPermit()
return res.data; return res.data
}; }
// 当前登录用户是否管理员身份 // 当前登录用户是否管理员身份
async function getUserInfoPermit() { async function getUserInfoPermit() {
const { data } = await userInfoPermitApi(); const { data } = await userInfoPermitApi()
setCache('userAdmin', data); db.set('userAdmin', data)
} }
const getCsInfo = async () => { const getCsInfo = async () => {
const res = await getCsInfoApi(userInfo.value.id); const res = await getCsInfoApi(userInfo.value.id)
csInfo.value = res.data; csInfo.value = res.data
setCache('csInfo', res.data); db.set('csInfo', res.data)
return res.data; return res.data
}; }
const clear = async () => { const clear = async () => {
token.value = ''; token.value = ''
userInfo.value = {}; userInfo.value = {}
csInfo.value = {}; csInfo.value = {}
await uni.clearStorageSync(); await db.clear()
}; }
const setToken = (data: string) => { const setToken = (data: string) => {
token.value = data; token.value = data
setCache('token', data); db.set('token', data)
}; }
return { return {
userInfo, userInfo,
@ -115,5 +90,5 @@ export const user = defineStore('user', () => {
clear, clear,
afterLogin, afterLogin,
setToken, 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 dayjs from 'dayjs'
import isToday from 'dayjs/plugin/isToday'; import isToday from 'dayjs/plugin/isToday'
import isYesterday from 'dayjs/plugin/isYesterday'; import isYesterday from 'dayjs/plugin/isYesterday'
import db from './db'
const OSS_URL = import.meta.env.VITE_OSS_HOST; const OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`; const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
dayjs.extend(isToday); dayjs.extend(isToday)
dayjs.extend(isYesterday); dayjs.extend(isYesterday)
// store统一设置 // store统一设置
export const setCache = (key: string, value: any) => { export const setCache = (key: string, value: any) => {
if (!key) throw new Error('key is required'); if (!key) throw new Error('key is required')
uni.setStorageSync(`QY_${key?.toUpperCase()}`, value); uni.setStorageSync(`QY_${key?.toUpperCase()}`, value)
}; }
export const getCache = (key: string) => { export const getCache = (key: string) => {
if (!key) throw new Error('key is required'); if (!key) throw new Error('key is required')
return uni.getStorageSync(`QY_${key?.toUpperCase()}`); return uni.getStorageSync(`QY_${key?.toUpperCase()}`)
}; }
export const removeCache = (key: string) => { export const removeCache = (key: string) => {
if (!key) throw new Error('key is required'); if (!key) throw new Error('key is required')
uni.removeStorageSync(`QY_${key?.toUpperCase()}`); uni.removeStorageSync(`QY_${key?.toUpperCase()}`)
}; }
// 随机ID // 随机ID
export const genId = (prefix?: number | string) => export const genId = (prefix?: number | string) =>
`${prefix || ''}${Math.random().toString(16).slice(2)}`; `${prefix || ''}${Math.random().toString(16).slice(2)}`
// 将数组映射为对象 // 将数组映射为对象
export const ArrToObj = ( export const ArrToObj = (
@ -31,61 +32,61 @@ export const ArrToObj = (
key = 'code', key = 'code',
value = 'value', value = 'value',
): { [key: string]: string } => { ): { [key: string]: string } => {
const obj: anyObj = {}; const obj: anyObj = {}
let i = 0; let i = 0
for (i; i < arr.length; i++) { 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) => { export const $sleep = (time: number) => {
return new Promise(res => { return new Promise(res => {
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
res(0); res(0)
clearTimeout(timeout); clearTimeout(timeout)
}, time); }, time)
}); })
}; }
export function formCheck(rules: anyObj[], data: anyObj) { export function formCheck(rules: anyObj[], data: anyObj) {
let res = true; let res = true
for (const i of rules) { for (const i of rules) {
if (i instanceof Array) { if (i instanceof Array) {
for (const j of i) { for (const j of i) {
if (j.required && !data[j.prop]) { if (j.required && !data[j.prop]) {
res = false; res = false
uni.showToast({ uni.showToast({
title: j.message, title: j.message,
icon: 'none', icon: 'none',
}); })
break; break
} }
if (j.validator) { if (j.validator) {
j.validator(data, data[j.prop], (result: any) => { j.validator(data, data[j.prop], (result: any) => {
if (result instanceof Error) { if (result instanceof Error) {
res = false; res = false
uni.showToast({ uni.showToast({
title: j.message, title: j.message,
icon: 'none', icon: 'none',
}); })
} }
}); })
} }
} }
} else { } else {
if (i.required && !data[i.prop]) { if (i.required && !data[i.prop]) {
res = false; res = false
uni.showToast({ uni.showToast({
title: i.message, title: i.message,
icon: 'none', icon: 'none',
}); })
break; break
} }
} }
} }
return res; return res
} }
// // uniApi转换成同步 // // uniApi转换成同步
@ -121,46 +122,77 @@ export const uploadFile = path =>
filePath: path, filePath: path,
name: 'file', name: 'file',
header: { header: {
Authorization: `Bearer ${getCache('token')}`, Authorization: `Bearer ${db.get('token')}`,
}, },
success: uploadFileRes => { success: uploadFileRes => {
const data = JSON.parse(uploadFileRes.data); const data = JSON.parse(uploadFileRes.data)
if (uploadFileRes.statusCode === 200) { if (uploadFileRes.statusCode === 200) {
resolve(data.data); resolve(data.data)
} else { } else {
reject(data.message); reject(data.message)
} }
}, },
fail: error => { fail: error => {
reject(error); reject(error)
}, },
}); })
}); })
/** /**
* *
*/ */
export const minToHour = (min: number) => { export const minToHour = (min: number) => {
const h = Math.floor(min / 60); const h = Math.floor(min / 60)
const m = min % 60; const m = min % 60
return [h, m]; return [h, m]
}; }
export const formatDate = (time: string) => { export const formatDate = (time: string) => {
const timestamp = new Date(time).getTime(); const timestamp = new Date(time).getTime()
const date = dayjs(timestamp); const date = dayjs(timestamp)
if (date.isToday()) return date.format('HH:mm'); if (date.isToday()) return date.format('HH:mm')
if (date.isYesterday()) return `昨天 ${date.format('HH:mm')}`; if (date.isYesterday()) return `昨天 ${date.format('HH:mm')}`
if (date.isSame(dayjs(), 'week') && (date.day() !== 0 || dayjs().day() === 0)) { if (date.isSame(dayjs(), 'week') && (date.day() !== 0 || dayjs().day() === 0)) {
const daysOfWeek = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']; const daysOfWeek = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
return `${daysOfWeek[date.day()]} ${date.format('HH:mm')}`; 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) => { export const getAvatarUrl = (url: string) => {
if (url && url.includes('http')) { 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: { server: {
port: 5173, port: 1234,
open: true, 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,
// },
// },
// },
}); });