feat:手动绑定孩子账号

This commit is contained in:
MJ 2025-08-06 23:44:33 +08:00
parent 549e25155c
commit 81c2f77434
21 changed files with 544 additions and 392 deletions

11
.vscode/settings.json vendored
View File

@ -48,5 +48,14 @@
"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": ["iconfont", "persistedstate", "pinia", "VITE", "Wechat", "Weixin", "xuexiaole"] "cSpell.words": [
"dcloudio",
"iconfont",
"persistedstate",
"pinia",
"VITE",
"Wechat",
"Weixin",
"xuexiaole"
]
} }

9
pnpm-lock.yaml generated
View File

@ -1926,6 +1926,11 @@ packages:
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
hasBin: true
address@1.2.2: address@1.2.2:
resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==}
engines: {node: '>= 10.0.0'} engines: {node: '>= 10.0.0'}
@ -7435,6 +7440,8 @@ snapshots:
acorn@8.11.3: {} acorn@8.11.3: {}
acorn@8.15.0: {}
address@1.2.2: {} address@1.2.2: {}
agent-base@6.0.2: agent-base@6.0.2:
@ -9309,7 +9316,7 @@ snapshots:
jsdom@16.7.0: jsdom@16.7.0:
dependencies: dependencies:
abab: 2.0.6 abab: 2.0.6
acorn: 8.11.3 acorn: 8.15.0
acorn-globals: 6.0.0 acorn-globals: 6.0.0
cssom: 0.4.4 cssom: 0.4.4
cssstyle: 2.3.0 cssstyle: 2.3.0

View File

@ -1,50 +1,50 @@
import { http } from '../request/request'; import { http } from '../request/request'
/** /**
* *
* @param params * @param params
*/ */
export const getCurInfo = async (params: any) => export const getCurInfo = async (params: any) => await http.get<any>('/parentBind/curInfo', params)
await http.get<any>('/parentBind/curInfo', params);
/** /**
* *
* @param data * @param data
*/ */
export const parentBindAdmin = async (data: any) => export const parentBindAdmin = async (data: any) => await http.post<any>('/parentBind/admin', data)
await http.post<any>('/parentBind/admin', data);
/** /**
* *
* @param data * @param data
*/ */
export const parentBindApply = async (data: any) => export const parentBindApply = async (data: any) => await http.post<any>('/parentBind/apply', data)
await http.post<any>('/parentBind/apply', data);
// 手动输入账号绑定孩子
export const manualBindApi = async (childAcc: any) =>
await http.postForm<any>('/parentBind/familyTeacherBindAcc', { childAcc })
/** /**
* - * -
* @param params * @param params
*/ */
export const adminInfo = async (params: any) => export const adminInfo = async (params: any) => await http.get<any>('/parentBind/adminInfo', params)
await http.get<any>('/parentBind/adminInfo', params);
/** /**
* - * -
* @param params * @param params
*/ */
export const applyInfo = async (params: any) => export const applyInfo = async (params: any) =>
await http.get<any>('/parentBind/apply/info', params); await http.get<any>('/parentBind/apply/info', params)
/** /**
* *
* @param data * @param data
*/ */
export const adminApproval = async (data: any) => export const adminApproval = async (data: any) =>
await http.post<any>('/parentBind/admin/approval', data); await http.post<any>('/parentBind/admin/approval', data)
/** /**
* *
* @param data * @param data
*/ */
export const deviceTimeControl = async (data: any) => export const deviceTimeControl = async (data: any) =>
await http.post<any>('/deviceTimeControl', data); await http.post<any>('/deviceTimeControl', data)

View File

@ -50,8 +50,8 @@ function switchTab(item, index) {
onMounted(async () => { onMounted(async () => {
currentIndex.value = props.selectedIndex currentIndex.value = props.selectedIndex
// //
await getApplyBindInfoList() notice.value = await getApplyBindInfoList()
notice.value = db.get('applyBindMsg')
list.value = [ list.value = [
{ {
pagePath: '/pages/home/index', pagePath: '/pages/home/index',

View File

@ -0,0 +1,69 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
defineOptions({ name: 'mj-dialog' })
const props = defineProps<{
modelValue: boolean
title?: string
hideCancel?: boolean
hideOk?: boolean
okText?: string
cancelText?: string
maskClosable?: boolean
ok?: any
cancel?: any
}>()
const emit = defineEmits<{
(e: 'update:modelValue', value: boolean): void
}>()
const show = computed({
get: () => props.modelValue,
set: val => {
emit('update:modelValue', val)
},
})
//
const btns = []
if (!props.hideCancel) {
btns.push({
text: props.cancelText || '取消',
color: '#999',
})
}
if (!props.hideOk) {
btns.push({
text: props.okText || '确定',
color: '#615dff',
})
}
const buttons = ref(btns)
function btnClick({ index }) {
if (index === 0) {
props.cancel?.()
emit('update:modelValue', false)
} else {
props.ok?.()
}
}
</script>
<template>
<tui-dialog
:show="show"
:title="title"
:buttons="buttons"
:maskClosable="maskClosable"
@click="btnClick"
>
<template v-slot:content>
<slot />
</template>
</tui-dialog>
</template>
<style lang="scss" scoped></style>

View File

@ -3,7 +3,7 @@ defineOptions({ name: 'mj-empty' })
</script> </script>
<template> <template>
<tui-no-data imgUrl="/static/nodata.png">暂无数据</tui-no-data> <tui-no-data imgUrl="/static/nodata.png">暂无数据</tui-no-data>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -57,7 +57,7 @@ const dialog_default_buttons = [
}, },
{ {
text: '确定', text: '确定',
color: '#333', color: '#615dff',
}, },
] ]
@ -90,6 +90,7 @@ function dialog(options: DialogOptions) {
if (options.cancelColor) { if (options.cancelColor) {
options.buttons[0].color = options.cancelColor options.buttons[0].color = options.cancelColor
} }
//
} }
// //
@ -118,9 +119,12 @@ function dialog(options: DialogOptions) {
clickFn(hide, e) clickFn(hide, e)
} }
// //
if (cancelFn && e.index === 0) { if (e.index === 0) {
cancelFn() if (cancelFn) {
hide() cancelFn(hide)
} else {
hide()
}
} }
// //
const okIdx = (options.buttons?.length || 1) - 1 const okIdx = (options.buttons?.length || 1) - 1

View File

@ -392,12 +392,6 @@
"selectedIconPath": "static/tabBar/studyReport.png", "selectedIconPath": "static/tabBar/studyReport.png",
"text": "学情报告" "text": "学情报告"
}, },
{
"pagePath": "pages/applicationManagement/index",
"iconPath": "static/tabBar/applicationNo.png",
"selectedIconPath": "static/tabBar/application.png",
"text": "应用管控"
},
{ {
"pagePath": "pages/mine/index", "pagePath": "pages/mine/index",
"iconPath": "static/tabBar/mineno.png", "iconPath": "static/tabBar/mineno.png",

View File

@ -8,8 +8,9 @@
<Empty v-if="empty" content="暂无学情报告数据哦~" /> <Empty v-if="empty" content="暂无学情报告数据哦~" />
</mj-page> </mj-page>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue' import { onMounted, ref } from 'vue'
import { onShow } from '@dcloudio/uni-app' import { onShow } from '@dcloudio/uni-app'
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'
@ -20,11 +21,11 @@ import './index.scss'
import { getParentBindChildApi, subjectApi } from '@/api' import { getParentBindChildApi, subjectApi } from '@/api'
import { userStore, bindApplyStore } from '@/store' import { userStore, bindApplyStore } from '@/store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import db from '@/utils/db'
import hud from '@/utils/hud' import hud from '@/utils/hud'
import { badgeStore } from '@/store/badge'
const { userInfo } = storeToRefs(userStore()) const { userInfo } = storeToRefs(userStore())
const { getApplyBindInfoList } = bindApplyStore() const { refreshBadge } = badgeStore()
const childrenList = ref<ChildrenType[]>() // const childrenList = ref<ChildrenType[]>() //
const empty = ref(false) const empty = ref(false)
@ -71,25 +72,9 @@ async function getSubject() {
subjectList.value = data subjectList.value = data
chooseSubject.value = data[0] chooseSubject.value = data[0]
} }
//
async function handleTabBarBadge() {
await getApplyBindInfoList()
const hasApplyMsg = db.get('applyBindMsg')
if (hasApplyMsg) {
uni.setTabBarBadge({
index: 3, // ""tabBar
text: '●',
})
} else {
uni.removeTabBarBadge({
index: 3,
})
}
}
onShow(() => { onShow(() => {
handleTabBarBadge() refreshBadge()
}) })
onMounted(async () => { onMounted(async () => {
@ -97,7 +82,6 @@ onMounted(async () => {
hud.loading() hud.loading()
await getParentBindChild() await getParentBindChild()
await getSubject() await getSubject()
handleTabBarBadge()
} finally { } finally {
hud.hide() hud.hide()
} }

View File

@ -72,7 +72,7 @@
v-for="(i, idx) in navList" v-for="(i, idx) in navList"
:key="idx" :key="idx"
:class="{ navigate_item: true, active: activeNav.type === i.type }" :class="{ navigate_item: true, active: activeNav.type === i.type }"
@click="swicthNav(i)" @click="switchNav(i)"
>{{ i.title }}</text >{{ i.title }}</text
> >
</view> </view>
@ -132,7 +132,6 @@
</view> </view>
</view> </view>
</wd-popup> </wd-popup>
</view> </view>
</template> </template>
@ -147,9 +146,10 @@ import Empty from '@/components/Empty/index.vue'
import { userStore, bindApplyStore } from '@/store' import { userStore, bindApplyStore } from '@/store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import db from '@/utils/db' import db from '@/utils/db'
import { badgeStore } from '@/store/badge'
const { userInfo } = storeToRefs(userStore()) const { userInfo } = storeToRefs(userStore())
const { getApplyBindInfoList } = bindApplyStore() const { refreshBadge } = badgeStore()
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 arrow = `${OSS_URL}/iconfont/down_arrow.png` const arrow = `${OSS_URL}/iconfont/down_arrow.png`
@ -158,7 +158,6 @@ const unchecked = `${OSS_URL}/iconfont/unchecked.png`
const showAllEquipment = ref(false) const showAllEquipment = ref(false)
const showCustomPopup = ref(false) const showCustomPopup = ref(false)
const methodPopup = ref(false) const methodPopup = ref(false)
const methodList = ref([ const methodList = ref([
{ {
@ -218,7 +217,7 @@ function handleChecked(i) {
fetchAppRecord() fetchAppRecord()
} }
function swicthNav(i) { function switchNav(i) {
activeNav.value = i activeNav.value = i
} }
// //
@ -288,31 +287,14 @@ async function fetchAppRecord() {
uni.hideLoading() uni.hideLoading()
} }
} }
//
async function handleTabBarBadge() {
await getApplyBindInfoList()
const hasApplyMsg = db.get('applyBindMsg')
if (hasApplyMsg) {
uni.setTabBarBadge({
index: 3, // ""tabBar
text: '●'
})
} else {
uni.removeTabBarBadge({
index: 3
})
}
}
onShow(() => { onShow(() => {
handleTabBarBadge() refreshBadge()
}) })
onMounted(async () => { onMounted(async () => {
await getParentBindDevice() await getParentBindDevice()
fetchAppRecord() fetchAppRecord()
handleTabBarBadge()
}) })
</script> </script>

View File

@ -1,23 +1,23 @@
<template> <template>
<z-paging ref="paging" v-model="dataList" :auto="false" @query="queryList"> <view class="page-container">
<BackBar title="历史截屏" /> <BackBar title="历史截屏" />
<template v-slot:empty> <scroll-view scroll-y class="scroll-container">
<view class="empty_box"> <view v-if="dataList.length === 0" class="empty_box">
<Empty content="暂无历史截屏数据哦~" /> <Empty content="暂无历史截屏数据哦~" />
</view> </view>
</template> <view v-else class="content">
<view class="content"> <view
<view v-for="(item, index) in dataList"
v-for="(item, index) in dataList" :key="index"
:key="index" class="item"
class="item" @click="previewImageFun(index)"
@click="previewImageFun(index)" >
> <image class="itemImage" :src="item.imageUrl" mode="aspectFill" />
<image class="itemImage" :src="item.imageUrl" mode="aspectFill" /> <view class="time">{{ item.createTime.replace(/-/g, '.') }}</view>
<view class="time">{{ item.createTime.replace(/-/g, '.') }}</view> </view>
</view> </view>
</view> </scroll-view>
</z-paging> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -26,16 +26,18 @@ import { deviceScreenshotRecordList } from '@/api';
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import Empty from '@/components/Empty/index.vue'; import Empty from '@/components/Empty/index.vue';
const dataList = ref([]); const dataList = ref([]);
const paging = ref();
const simSerialNumber = ref(); const simSerialNumber = ref();
function queryList(pageNo: number, pageSize: number) {
function loadData() {
deviceScreenshotRecordList({ deviceScreenshotRecordList({
size: pageSize, size: 1000,
current: pageNo, current: 1,
simSerialNumber: simSerialNumber.value, simSerialNumber: simSerialNumber.value,
}).then(res => { }).then(res => {
paging.value.complete(res.rows); dataList.value = res.rows || [];
}).catch(() => {
dataList.value = [];
}); });
} }
@ -52,12 +54,23 @@ function previewImageFun(idx: any) {
onLoad(option => { onLoad(option => {
simSerialNumber.value = option.simSerialNumber; simSerialNumber.value = option.simSerialNumber;
setTimeout(() => { setTimeout(() => {
paging.value?.reload(); // loadData();
}, 500); }, 500);
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.page-container {
height: 100vh;
display: flex;
flex-direction: column;
}
.scroll-container {
flex: 1;
height: 0;
}
.content { .content {
width: 100%; width: 100%;
display: flex; display: flex;

View File

@ -19,40 +19,40 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app'
import { getDeviceScreenControlApi, lockDeviceScreenApi } from '@/api'; import { getDeviceScreenControlApi, lockDeviceScreenApi } from '@/api'
const OSS_URL = import.meta.env.VITE_OSS_HOST; const OSS_URL = import.meta.env.VITE_OSS_HOST
const simSerialNumber = ref(); const simSerialNumber = ref()
const screenControlInfo = ref<any>({}); const screenControlInfo = ref<any>({})
async function handleMachineScreen() { async function handleMachineScreen() {
try { try {
uni.showLoading({ uni.showLoading({
title: `${screenControlInfo?.value.lockFlag === 1}` ? '解中...' : '锁屏中...', title: `${screenControlInfo?.value.lockFlag === 1}` ? '解中...' : '锁屏中...',
}); })
const data = await lockDeviceScreenApi(simSerialNumber.value); const data = await lockDeviceScreenApi(simSerialNumber.value)
fetchDeviceScreen(); fetchDeviceScreen()
} finally { } finally {
uni.hideLoading(); uni.hideLoading()
} }
} }
async function fetchDeviceScreen() { async function fetchDeviceScreen() {
try { try {
uni.showLoading({ uni.showLoading({
title: '加载中...', title: '加载中...',
}); })
const data = await getDeviceScreenControlApi(simSerialNumber.value); const data = await getDeviceScreenControlApi(simSerialNumber.value)
screenControlInfo.value = data ? data : {}; screenControlInfo.value = data ? data : {}
} finally { } finally {
uni.hideLoading(); uni.hideLoading()
} }
} }
onLoad(option => { onLoad(option => {
simSerialNumber.value = option.simSerialNumber; simSerialNumber.value = option.simSerialNumber
fetchDeviceScreen(); fetchDeviceScreen()
}); })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,9 +1,9 @@
<template> <template>
<mj-page class="teacher-content"> <mj-page class="teacher-content">
<view v-if="equipmentList.length === 0" class="binding" @click="bindDevice"> <!-- <view v-if="equipmentList.length === 0" class="binding">
<image class="scan" :src="scanQr" mode=""></image>扫码绑定设备 <image class="scan" :src="scanQr" mode=""></image>扫码绑定设备
</view> </view> -->
<view v-else class="my_equipment"> <view class="my_equipment">
<view class="header"> <view class="header">
<text>我的设备</text> <text>我的设备</text>
<image <image
@ -57,11 +57,15 @@
</view> </view>
<view class="equipment_item_left"> <view class="equipment_item_left">
<image :src="i.id === showEquipment.id ? checked : unchecked" mode=""></image> <image :src="i.id === showEquipment.id ? checked : unchecked" mode=""></image>
</view> </view </view>
></template> </view>
</template>
<view class="binding" @click="bindDevice"> <view class="binding">
<image class="scan" :src="scanQr" mode=""></image>扫码绑定设备 <view class="scan-bind" @click="scanBind">
<image class="scan" :src="scanQr" mode=""></image>扫码绑定
</view>
<view class="hand-bind" @click="handBind"> 手动绑定 </view>
</view> </view>
</view> </view>
<view class="home_function"> <view class="home_function">
@ -72,25 +76,38 @@
</template> </template>
</view> </view>
<!-- 手动绑定弹框 -->
<mj-dialog
v-model="showHandBindPopup"
title="手动绑定孩子账号"
okText="绑定"
:ok="confirmHandBind"
>
<input
v-model="childAccount"
class="account-input"
placeholder="请输入孩子账号"
type="text"
/>
</mj-dialog>
</mj-page> </mj-page>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, reactive, ref } from 'vue' import { onMounted, reactive, ref } from 'vue'
import { onShow } from '@dcloudio/uni-app' import { onShow } from '@dcloudio/uni-app'
import { getParentBindDeviceApi, parentDeviceCurrentLoginApi } from '@/api'
import { bindApplyStore } from '@/store'
import db from '@/utils/db'
import { userStore } from '@/store' import { userStore } from '@/store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import hud from '@/utils/hud' import hud from '@/utils/hud'
import router from '@/router/router' import router from '@/router/router'
import { badgeStore } from '@/store/badge'
import { getParentBindDeviceApi, manualBindApi } from '@/api'
const store = userStore() const store = userStore()
const { getUserInfo } = store const { getUserInfo } = store
const { userInfo } = storeToRefs(userStore()) const { userInfo } = storeToRefs(userStore())
const { getApplyBindInfoList } = bindApplyStore() const { refreshBadge } = badgeStore()
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`
@ -99,6 +116,10 @@ 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 showHandBindPopup = ref(false)
const childAccount = ref('')
const functionList = reactive([ const functionList = reactive([
{ {
name: '一键锁屏', name: '一键锁屏',
@ -114,20 +135,20 @@ const functionList = reactive([
developing: false, developing: false,
type: 1, type: 1,
}, },
{ // {
name: '时间管控', // name: '',
bg: `${OSS_URL}/urm/home_time_control.png`, // bg: `${OSS_URL}/urm/home_time_control.png`,
developingBg: '', // developingBg: '',
developing: false, // developing: false,
type: 2, // type: 2,
}, // },
{ // {
name: '视频通话', // name: '',
bg: `${OSS_URL}/urm/home_video_call.png`, // bg: `${OSS_URL}/urm/home_video_call.png`,
developingBg: `${OSS_URL}/urm/home_video_developing.png`, // developingBg: `${OSS_URL}/urm/home_video_developing.png`,
developing: true, // developing: true,
type: 3, // type: 3,
}, // },
]) ])
const equipmentList = ref([]) const equipmentList = ref([])
const showEquipment = ref() const showEquipment = ref()
@ -137,10 +158,40 @@ function chooseEquipment(i) {
showEquipment.value = i showEquipment.value = i
} }
function bindDevice() { //
function scanBind() {
router.navigateTo('/pages/home/bindDevice/index') router.navigateTo('/pages/home/bindDevice/index')
} }
//
function handBind() {
showHandBindPopup.value = true
childAccount.value = ''
}
//
function confirmHandBind() {
if (!childAccount.value.trim()) {
hud.error('请输入孩子账号')
return
}
hud.load({
task: async () => {
const res = Number(await manualBindApi(childAccount.value))
if (res === 1) {
hud.success('绑定成功')
} else if (res === 0) {
hud.error('绑定失败')
} else if (res === 2) {
hud.success('已向管理员发送绑定请求')
}
showHandBindPopup.value = false
},
option: '绑定',
})
}
// //
function change(i: any) { function change(i: any) {
if (equipmentList.value.length === 0) { if (equipmentList.value.length === 0) {
@ -198,43 +249,17 @@ async function getParentBindDevice() {
equipmentList.value = data.rows equipmentList.value = data.rows
showEquipment.value = data.rows[0] showEquipment.value = data.rows[0]
} }
// for (let i in data.rows) {
// const _r = await parentDeviceCurrentLoginApi(data.rows[i].id)
// equipmentList.value.push({
// ...data.rows[i],
// curDeviceUserName: _r.curDeviceUserName,
// curDeviceUserAvatar: _r.curDeviceUserAvatar,
// })
// }
// showEquipment.value = data.rows?.length > 0 ? equipmentList.value[0] : {}
}, },
}) })
} }
//
async function handleTabBarBadge() {
await getApplyBindInfoList()
const hasApplyMsg = db.get('applyBindMsg')
if (hasApplyMsg) {
uni.setTabBarBadge({
index: 3, // ""tabBar
text: '●'
})
} else {
uni.removeTabBarBadge({
index: 3
})
}
}
onShow(() => { onShow(() => {
handleTabBarBadge() refreshBadge()
}) })
onMounted(async () => { onMounted(async () => {
await getUserInfo() await getUserInfo()
getParentBindDevice() getParentBindDevice()
handleTabBarBadge()
}) })
</script> </script>
@ -248,7 +273,7 @@ onMounted(async () => {
.binding { .binding {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: space-between;
width: 100%; width: 100%;
height: 120rpx; height: 120rpx;
background-color: #fff; background-color: #fff;
@ -258,11 +283,19 @@ onMounted(async () => {
font-size: 34rpx; font-size: 34rpx;
font-weight: 500; font-weight: 500;
line-height: 52rpx; line-height: 52rpx;
.scan-bind {
.scan { .scan {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;
margin-right: 10rpx; margin-right: 10rpx;
}
}
.scan-bind,
.hand-bind {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
} }
} }
@ -378,4 +411,21 @@ onMounted(async () => {
} }
} }
} }
//
.account-input {
width: 100%;
height: 80rpx;
border: 1px solid #e0e0e0;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
box-sizing: border-box;
color: #333;
&::placeholder {
color: #ccc;
}
}
</style> </style>

View File

@ -1,143 +1,140 @@
<template> <template>
<view class="about_mine"> <view class="about_mine">
<z-paging <view class="container">
ref="paging" <view class="navigate">
v-model="dataList" <text
:paging-style="{ margin: '402rpx 30rpx 0 30rpx' }" v-for="(i, idx) in navList"
:style="{ :key="idx"
height: `calc(100% - 532rpx - 120rpx - 52rpx)`, :class="{ navigate_item: true, active: activeNav.type === i.type }"
}" @click="switchNav(i)"
@query="queryList" >{{ i.title }}</text
> >
<template #top> </view>
<view class="navigate"> <scroll-view scroll-y class="scroll-container">
<text <view v-if="noData" class="empty_box">
v-for="(i, idx) in navList"
:key="idx"
:class="{ navigate_item: true, active: activeNav.type === i.type }"
@click="swicthNav(i)"
>{{ i.title }}</text
>
</view>
</template>
<template v-slot:empty>
<view class="empty_box">
<image :src="empty" mode="" class="empty"></image> <image :src="empty" mode="" class="empty"></image>
<view class="tip">您还没有绑定任何数据快去扫码绑定吧</view> <view class="tip">您还没有绑定任何数据快去扫码绑定吧</view>
<button class="btn" @click="handleBindDevice">扫码绑定</button> <button class="btn" @click="handleBindDevice">扫码绑定</button>
</view> </view>
</template>
<view class="content"> <view v-else class="content">
<!-- 我的孩子 --> <!-- 我的孩子 -->
<template v-if="activeNav.type === 1"> <template v-if="activeNav.type === nav_child">
<view <view
v-for="(i, idx) in dataList" v-for="(i, idx) in childList"
:key="idx" :key="idx"
class="children" class="children"
@click="handleDetialPage(activeNav.type, i)" @click="handleDetailPage(activeNav.type, i)"
> >
<image <image
:src="i?.childAvatar ? i?.childAvatar : defaultAvatar" :src="i?.childAvatar ? i?.childAvatar : defaultAvatar"
mode="" mode=""
class="children_avatar" class="children_avatar"
></image> ></image>
<view class="children-info"> <view class="children-info">
<view class="name_vip"> <view class="name_vip">
<text class="name">{{ i.childName }}</text> <text class="name">{{ i.childName }}</text>
<image <image
v-if="i.currentLevel" v-if="i.currentLevel"
:src="`${OSS_URL}/iconfont/VIP/VIP_${i.currentLevel}.png`" :src="`${OSS_URL}/iconfont/VIP/VIP_${i.currentLevel}.png`"
class="vip" class="vip"
/> />
</view> </view>
<view class="time"> <view class="time">
有效期至{{ i.vipEndTime ? dayjs(i.vipEndTime).format('YYYY.MM.DD') : '-' }} 有效期至{{ i.vipEndTime ? dayjs(i.vipEndTime).format('YYYY.MM.DD') : '-' }}
</view>
</view> </view>
<!-- <view v-if="i.havePurchasedInspector" class="service">
<wd-button class="btn" :round="false" @click.stop="toMySupervisionService(i)"
>督学服务</wd-button
>
</view> -->
</view> </view>
<view v-if="i.havePurchasedInspector" class="service"> </template>
<wd-button class="btn" :round="false" @click.stop="toMySupervisionService(i)" <!-- 我的设备 -->
>督学服务</wd-button <template v-else>
> <view
v-for="(i, idx) in deviceList"
:key="idx"
class="equipment"
@click="handleDetailPage(activeNav.type, i)"
>
序列号<text class="serial">{{ i.simSerialNumber }}</text>
</view> </view>
</view> </template>
</template> </view>
<!-- 我的设备 --> </scroll-view>
<template v-else> </view>
<view
v-for="(i, idx) in dataList"
:key="idx"
class="equipment"
@click="handleDetialPage(activeNav.type, i)"
>
序列号<text class="serial">{{ i.simSerialNumber }}</text>
</view>
</template>
</view>
</z-paging>
</view> </view>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, onMounted, nextTick } from 'vue' import { reactive, ref, onMounted, computed } 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 { userStore } from '@/store' import { userStore } from '@/store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { getCache } from '@/utils'
import router from '@/router/router' import router from '@/router/router'
import type { ChildrenType, DeviceType } from './interface'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import db from '@/utils/db'
const { userInfo } = storeToRefs(userStore()) const { userInfo } = storeToRefs(userStore())
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 empty = `${OSS_URL}/empty.png` const empty = `${OSS_URL}/empty.png`
const nav_child = 1
const nav_device = 2
// //
const activeNav = ref({ const activeNav = ref({
title: '我的孩子', title: '我的孩子',
type: 1, type: nav_child,
}) })
const navList = reactive([ const navList = reactive([
{ {
title: '我的孩子', title: '我的孩子',
type: 1, type: nav_child,
}, },
{ {
title: '我的设备', title: '我的设备',
type: 2, type: nav_device,
}, },
]) ])
const dataList = ref<any[]>([]) const childList = ref<any[]>([])
const paging = ref(null) const deviceList = ref<any[]>([])
function swicthNav(i) { const noData = computed(() => {
paging.value.reload(true) return (
(activeNav.value.type === nav_child && childList.value.length === 0) ||
(activeNav.value.type === nav_device && deviceList.value.length === 0)
)
})
function switchNav(i: any) {
activeNav.value = i activeNav.value = i
loadData()
} }
const queryList = (pageNo: number, pageSize: number) => { const loadData = () => {
if (activeNav.value.type === 1) { if (activeNav.value.type === nav_child) {
getParentBindChildApi({ parentId: userInfo.value.id, current: pageNo, size: pageSize }) getParentBindChildApi({ parentId: userInfo.value.id, current: 1, size: 1000 })
.then(res => { .then(res => {
paging.value.complete(res.rows) childList.value = res.rows || []
}) })
.catch(res => { .catch(res => {
paging.value.complete(false) childList.value = []
}) })
} else { } else {
getParentBindDeviceApi({ parentId: userInfo.value.id, current: pageNo, size: pageSize }) getParentBindDeviceApi({ parentId: userInfo.value.id, current: 1, size: 1000 })
.then(res => { .then(res => {
paging.value.complete(res.rows) deviceList.value = res.rows || []
}) })
.catch(res => { .catch(res => {
paging.value.complete(false) deviceList.value = []
}) })
} }
} }
// //
function handleDetialPage(type: number, obj: any) { function handleDetailPage(type: number, obj: any) {
let details = encodeURIComponent(JSON.stringify(obj)) let details = encodeURIComponent(JSON.stringify(obj))
switch (type) { switch (type) {
case 1: case 1:
@ -167,20 +164,21 @@ const toMySupervisionService = child => {
} }
onShow(() => { onShow(() => {
if (paging.value) { loadData()
paging.value.refresh() })
} onMounted(() => {
loadData()
}) })
onMounted(() => {})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.about_mine { .about_mine {
// .paging_box { .container {
// height: calc(100vh - 532rpx - 120rpx - 52rpx); margin-top: 20px;
// } }
:deep(.zp-empty-view-center) {
display: block; .scroll-container {
margin-top: 30rpx;
} }
.empty_box { .empty_box {
display: flex; display: flex;

View File

@ -1,5 +1,5 @@
<template> <template>
<view class="page"> <mj-page class="page">
<BackBar title="绑定申请" /> <BackBar title="绑定申请" />
<Empty v-if="bindApplyList?.length === 0" content="暂无申请数据哦~" /> <Empty v-if="bindApplyList?.length === 0" content="暂无申请数据哦~" />
<template v-else> <template v-else>
@ -85,67 +85,71 @@
</swiper-item> </swiper-item>
</swiper> </swiper>
</template> </template>
</view> </mj-page>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue'; import { ref, onMounted, nextTick } from 'vue'
import type { BindApplyItemType } from '../interface'; import type { BindApplyItemType } from '../interface'
import { adminApproval } from '@/api'; import { adminApproval } from '@/api'
import { maskPhone, useRelation, debounce } from '@/hooks'; import { useRelation, debounce } from '@/hooks'
import Empty from '@/components/Empty/index.vue'; import Empty from '@/components/Empty/index.vue'
import { bindApplyStore } from '@/store'; import { bindApplyStore } from '@/store'
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia'
import hud from '@/utils/hud'
const { bindApplyList } = storeToRefs(bindApplyStore()); const { bindApplyList } = storeToRefs(bindApplyStore())
const { getApplyBindInfoList } = bindApplyStore(); const { getApplyBindInfoList } = bindApplyStore()
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(0); const current = ref(0)
const showData = ref<BindApplyItemType>(); const showData = ref<BindApplyItemType>()
async function handleBtnFn(e: boolean, id: string) { async function handleBtnFn(e: boolean, id: string) {
adminApproval({ const option = e ? '同意' : '拒绝'
approvalFlag: e, hud.confirmLoad(`确定【${option}】绑定?`, {
id: id, task: async () => {
}).then(async res => { await adminApproval({
uni.showToast({ approvalFlag: e,
title: '提交成功!', id: id,
icon: 'none', })
mask: true, await getApplyBindInfoList()
}); await nextTick()
await getApplyBindInfoList(); if (current.value >= bindApplyList.value.length) {
if (current.value >= bindApplyList.value.length) { current.value = bindApplyList.value.length > 0 ? bindApplyList.value.length - 1 : 0
current.value = bindApplyList.value.length > 0 ? bindApplyList.value.length - 1 : 0; }
} showData.value = bindApplyList.value.length > 0 ? bindApplyList.value[current.value - 1] : {}
showData.value = bindApplyList.value.length > 0 ? bindApplyList.value[current.value - 1] : {}; },
}); option,
hideSuccess: false,
})
} }
const subFun = debounce(handleBtnFn, 500); const subFun = debounce(handleBtnFn, 500)
function switchPage(type) { function switchPage(type) {
switch (type) { switch (type) {
case 'pre': case 'pre':
if (current.value > 0) { if (current.value > 0) {
current.value -= 1; current.value -= 1
showData.value = bindApplyList.value[current.value]; showData.value = bindApplyList.value[current.value]
} }
break; break
case 'next': case 'next':
if (current.value < bindApplyList.value.length - 1) { if (current.value < bindApplyList.value.length - 1) {
current.value += 1; current.value += 1
showData.value = bindApplyList.value[current.value]; showData.value = bindApplyList.value[current.value]
} }
break; break
} }
} }
onMounted(async () => { onMounted(async () => {
await getApplyBindInfoList(); await getApplyBindInfoList()
await nextTick()
showData.value = bindApplyList.value.length > 0 ? bindApplyList.value[0] : {}; showData.value = bindApplyList.value.length > 0 ? bindApplyList.value[0] : {}
}); })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,40 +1,35 @@
<template> <template>
<view class="patriarch_list"> <view class="patriarch_list">
<z-paging <view class="container" :style="{ margin: `${top}rpx 30rpx 0 30rpx` }">
ref="paging" <view class="title">绑定家长</view>
v-model="dataList" <scroll-view scroll-y class="scroll-container">
:paging-style="{ margin: `${top}rpx 30rpx 0 30rpx` }" <view v-if="dataList.length === 0" class="empty_box">
@query="queryList"
>
<template #top>
<view class="title">绑定家长</view>
</template>
<template v-slot:empty>
<view class="empty_box">
<Empty content="暂无绑定家长数据哦~" /> <Empty content="暂无绑定家长数据哦~" />
</view> </view>
</template> <view v-else class="content">
<view v-for="(i, idx) in dataList" :key="idx" class="patriarch"> <view v-for="(i, idx) in dataList" :key="idx" class="patriarch">
<view class="left"> <view class="left">
<image <image
:src="i.parentAvatar ? i.parentAvatar : defaultAvatar" :src="i.parentAvatar ? i.parentAvatar : defaultAvatar"
mode="" mode=""
class="patriarch_avatar" class="patriarch_avatar"
></image> ></image>
<view> <view>
<view class="header"> <view class="header">
<view class="name">{{ i.parentName }}</view> <view class="name">{{ i.parentName }}</view>
<view class="tag"> <view class="tag">
<text v-if="i.adminFlag === 1" class="tag_item manager">管理员</text> <text v-if="i.adminFlag === 1" class="tag_item manager">管理员</text>
<text class="tag_item relation">{{ useRelation1[i.identityType] }}</text> <text class="tag_item relation">{{ useRelation1[i.identityType as keyof typeof useRelation1] }}</text>
</view>
</view>
<view class="phone"> {{ maskPhone(i.parentPhone) }} </view>
</view> </view>
</view> </view>
<view class="phone"> {{ maskPhone(i.parentPhone) }} </view> <view class="right"><button class="unbind_btn" @click="handleUnbind(i as any)">解绑</button></view>
</view> </view>
</view> </view>
<view class="right"><button class="unbind_btn" @click="handleUnbind(i)">解绑</button></view> </scroll-view>
</view> </view>
</z-paging>
<CustomPopup <CustomPopup
v-model="showCustomPopup" v-model="showCustomPopup"
titleText="温馨提示" titleText="温馨提示"
@ -76,31 +71,30 @@ 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 showCustomPopup = ref(false) const showCustomPopup = ref(false)
const unbind = ref<ChildrenType | DeviceType>() const unbind = ref<ChildrenType | DeviceType>()
const dataList = ref<ChildrenType[] | DeviceType[]>() const dataList = ref<ChildrenType[] | DeviceType[]>([])
const paging = ref(null)
const detailInfo = ref<ChildrenType & DeviceType>() const detailInfo = ref<ChildrenType & DeviceType>()
const queryList = (pageNo: number, pageSize: number) => { const loadData = () => {
if (props.type === 1) { if (props.type === 1) {
getParentBindChildApi({ childId: detailInfo.value.childId, current: pageNo, size: pageSize }) getParentBindChildApi({ childId: detailInfo.value.childId, current: 1, size: 1000 })
.then(res => { .then(res => {
paging.value.complete(res.rows) dataList.value = res.rows || []
}) })
.catch(res => { .catch(res => {
paging.value.complete(false) dataList.value = []
}) })
} else { } else {
getParentBindDeviceApi({ getParentBindDeviceApi({
simSerialNumber: detailInfo.value.simSerialNumber, simSerialNumber: detailInfo.value.simSerialNumber,
current: pageNo, current: 1,
size: pageSize, size: 1000,
}) })
.then(res => { .then(res => {
paging.value.complete(res.rows) dataList.value = res.rows || []
}) })
.catch(res => { .catch(res => {
paging.value.complete(false) dataList.value = []
}) })
} }
} }
@ -116,25 +110,40 @@ async function handleConfirmPopup() {
}) })
if (props.type === 1) { if (props.type === 1) {
await childUnBoundParentApi({ await childUnBoundParentApi({
parentId: unbind.value.parentId, parentId: (unbind.value as any).parentId,
childId: detailInfo.value.childId, childId: detailInfo.value.childId,
}) })
} else { } else {
await parentUnBoundDeviceApi({ await parentUnBoundDeviceApi({
parentId: unbind.value.parentId, parentId: (unbind.value as any).parentId,
simSerialNumber: detailInfo.value.simSerialNumber, simSerialNumber: detailInfo.value.simSerialNumber,
}) })
} }
uni.hideLoading() uni.hideLoading()
paging.value.reload() loadData()
showCustomPopup.value = false showCustomPopup.value = false
} }
onLoad(option => { onLoad(option => {
detailInfo.value = JSON.parse(decodeURIComponent(option.details)) detailInfo.value = JSON.parse(decodeURIComponent(option.details))
loadData()
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.patriarch_list { .patriarch_list {
height: 100vh;
.container {
height: calc(100vh - 445rpx);
display: flex;
flex-direction: column;
}
.scroll-container {
flex: 1;
height: 0;
margin-top: 20rpx;
}
.empty_box { .empty_box {
.empty { .empty {
margin-top: 0 !important; margin-top: 0 !important;

View File

@ -1,36 +1,21 @@
<template> <template>
<view class="content"> <view class="content">
<PatriarchCard /> <PatriarchCard />
<AbountMine /> <AboutMine />
</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 { bindApplyStore } from '@/store'
import db from '@/utils/db'
import PatriarchCard from './patriarchCard.vue'; import PatriarchCard from './patriarchCard.vue'
import AbountMine from './aboutMine.vue'; import AboutMine from './aboutMine.vue'
import { badgeStore } from '@/store/badge'
const { getApplyBindInfoList } = bindApplyStore() const { refreshBadge } = badgeStore()
onShow(async () => { onShow(async () => {
// refreshBadge()
await getApplyBindInfoList()
const hasApplyMsg = db.get('applyBindMsg')
if (hasApplyMsg) {
uni.setTabBarBadge({
index: 3, // ""tabBar
text: '●'
})
} else {
uni.removeTabBarBadge({
index: 3
})
}
}) })
</script> </script>

View File

@ -14,7 +14,9 @@
<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">
<image :src="i.photo" mode="" class="photo"></image> <image :src="i.photo" mode="" class="photo"></image>
<text v-if="i.title === '绑定申请' && getCache('applyBindMsg')" class="unread"></text> <text v-if="i.id === id_apply && bindApplyList?.length" class="unread">
{{ bindApplyList?.length }}
</text>
</view> </view>
<text class="title">{{ i.title }}</text> <text class="title">{{ i.title }}</text>
</view> </view>
@ -25,24 +27,25 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import { userStore } from '@/store' import { bindApplyStore, userStore } from '@/store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { getCache } from '@/utils'
import router from '@/router/router' import router from '@/router/router'
import db from '@/utils/db'
const { userInfo } = storeToRefs(userStore()) const { userInfo } = storeToRefs(userStore())
const { bindApplyList } = storeToRefs(bindApplyStore())
const id_apply = 2
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: '',
// photo: `${OSS_URL}/urm/my_scan_binding.png`,
// show: true,
// url: '/pages/home/bindDevice/index',
// },
{ {
title: '扫码绑定', id: id_apply,
photo: `${OSS_URL}/urm/my_scan_binding.png`,
show: true,
url: '/pages/home/bindDevice/index',
},
{
title: '绑定申请', title: '绑定申请',
photo: `${OSS_URL}/urm/my_binding_apply.png`, photo: `${OSS_URL}/urm/my_binding_apply.png`,
show: true, show: true,
@ -153,14 +156,19 @@ onMounted(() => {})
} }
.unread { .unread {
$unread-wh: 24rpx;
display: block; display: block;
position: absolute; position: absolute;
text-align: center;
line-height: $unread-wh;
right: 0; right: 0;
top: 0; top: 0;
width: 16rpx; width: $unread-wh;
height: 16rpx; height: $unread-wh;
font-size: $unread-wh - 6rpx;
background-color: rgba(255, 40, 40, 1); background-color: rgba(255, 40, 40, 1);
border-radius: 50%; border-radius: 50%;
color: white;
} }
} }

26
src/store/badge.ts Normal file
View File

@ -0,0 +1,26 @@
import { defineStore } from 'pinia'
import { bindApplyStore } from './bindApply'
export const badgeStore = defineStore('badge', () => {
const { getApplyBindInfoList } = bindApplyStore()
async function refreshBadge() {
// 我的
const mineIndex = 2
const size = (await getApplyBindInfoList())?.length
if (size) {
uni.setTabBarBadge({
index: mineIndex,
text: `${size}`,
})
} else {
uni.removeTabBarBadge({
index: mineIndex,
})
}
}
return {
refreshBadge,
}
})

View File

@ -1,26 +1,24 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ref } from 'vue' import { ref } from 'vue'
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 applyBindMsg = ref(false)
// 未处理的绑定申请列表 // 未处理的绑定申请列表
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) { applyBindMsg.value = data?.length
db.set('applyBindMsg', false) return data
} else {
db.set('applyBindMsg', true)
}
} catch (err) { } catch (err) {
console.log(err) console.log(err)
} }
} }
return { return {
applyBindMsg,
bindApplyList, bindApplyList,
getApplyBindInfoList, getApplyBindInfoList,
} }

View File

@ -41,23 +41,23 @@ function _toast(type: string, msg: string, duration = default_duration) {
}) })
} }
export async function info(text: string, duration?: number) { async function info(text: string, duration?: number) {
return _toast('info', text, duration) return _toast('info', text, duration)
} }
export async function error(text: string, duration?: number) { async function error(text: string, duration?: number) {
return _toast('error', text, duration) return _toast('error', text, duration)
} }
export async function warn(text: string, duration?: number) { async function warn(text: string, duration?: number) {
return _toast('warn', text, duration) return _toast('warn', text, duration)
} }
export async function success(text: string, duration?: number) { async function success(text: string, duration?: number) {
return _toast('success', text, duration) return _toast('success', text, duration)
} }
export async function primary(text: string, duration?: number) { async function primary(text: string, duration?: number) {
return _toast('primary', text, duration) return _toast('primary', text, duration)
} }
@ -69,6 +69,17 @@ export function dialog(options: DialogOptions) {
dict.callFn(dialog_dict_key, options) dict.callFn(dialog_dict_key, options)
} }
export function confirmLoad(content: any, options: LoadOptions) {
dialog({
title: '确认',
content,
ok: async (hide: any) => {
hide()
load(options)
},
})
}
export function hide() { export function hide() {
dict.callFn(hide_dict_key) dict.callFn(hide_dict_key)
} }
@ -136,4 +147,5 @@ export default {
primary, primary,
hide, hide,
dialog, dialog,
confirmLoad,
} }