main
king 1 year ago
parent 0d05ea82ac
commit 7f4092cc8a
  1. 1
      src/api/curriculum.ts
  2. 3
      src/api/manage.ts
  3. 2
      src/app.config.ts
  4. 18
      src/hooks/eventsIndex.ts
  5. 4
      src/pages/business/videoInfo/videoInfo.tsx
  6. 57
      src/pages/index/components/videoList.tsx
  7. 4
      src/pages/index/index.tsx
  8. 3
      src/pages/manage/bingUser/bingUser.config.ts
  9. 49
      src/pages/manage/bingUser/bingUser.tsx
  10. 4
      src/pages/manage/offline/offline.config.ts
  11. 11
      src/pages/manage/offline/offline.module.scss
  12. 168
      src/pages/manage/offline/offline.tsx
  13. 1
      src/pages/my/components/header/service.tsx
  14. 19
      src/utils/time.ts
  15. 9
      types/user.d.ts

@ -66,6 +66,7 @@ export interface CurEndParam {
}
export const curriculum = {
/** 部门all */
department() {
return request<{ data: Manage[] }>('/api/v1/department/index', 'GET')
},

@ -120,5 +120,8 @@ export const ManageApi = {
/** 学员学习记录 */
userRecord(curId: number) {
return request<CurLearningRecord>(`/api/v1/course/${curId}/user/index?page=1&size=10000`, "GET")
},
offline(data: Offline) {
return request('/wechat/link', "GET", data)
}
}

@ -58,6 +58,8 @@ export default defineAppConfig({
'addStudent/addStudent',
'depCur/depCur',
'addCur/addCur',
'offline/offline',
'bingUser/bingUser',
]
}
],

@ -0,0 +1,18 @@
import Taro from "@tarojs/taro";
/** 首页全局事件 */
const KEY = 'REFRESHINDEX'
function on(fn: (arg: any) => void) {
Taro.eventCenter.on(KEY, fn)
}
function trigger(data:any){
Taro.eventCenter.trigger(KEY, data)
}
export default {
on,
trigger
}

@ -6,6 +6,7 @@ import {Profile} from '@/store'
import Catalogue from "./components/catalogue";
import Course from "./components/course";
import Taro from "@tarojs/taro";
import eventsIndex from "@/hooks/eventsIndex";
const VideoInfo: FC = () => {
@ -14,6 +15,9 @@ const VideoInfo: FC = () => {
const [playId, setPlayId] = useState<number | null>(null)
const [preview, setPreview] = useState(false)
eventsIndex.trigger(12)
async function getData() {
const res = await curriculum.courseDep(id, depId)
if (res) {

@ -7,6 +7,7 @@ import styles from '../index.module.scss'
import {formatMinute} from "@/utils/time";
import {userApi} from "@/api";
import Empty from "@/components/empty/empty";
// import eventsIndex from "@/hooks/eventsIndex";
interface Props {
categoryKey: CoursesKey
@ -23,51 +24,11 @@ export const VideoList: FC<Props> = ({categoryKey}) => {
const [page, setPage] = useState(1)
const [records, setRecords] = useState<LearnRecord[]>([])
async function getData() {
try {
const res = await publicApi.course({page: page, pageSize: 10})
const oldData: Courses = JSON.parse(JSON.stringify(data))
oldData.is_finished = res.is_finished.reduce((pre, cur) => {
const index = pre.findIndex(d => d.id === cur.id)
if (index === -1) {
pre.push(cur)
} else {
pre.splice(index, 1, cur)
}
return pre
}, oldData.is_finished)
oldData.is_required = res.is_required.reduce((pre, cur) => {
const index = pre.findIndex(d => d.id === cur.id)
if (index === -1) {
pre.push(cur)
} else {
pre.splice(index, 1, cur)
}
return pre
}, oldData.is_required)
oldData.is_not_finished = res.is_not_finished.reduce((pre, cur) => {
const index = pre.findIndex(d => d.id === cur.id)
if (index === -1) {
pre.push(cur)
} else {
pre.splice(index, 1, cur)
}
return pre
}, oldData.is_not_finished)
oldData.is_not_required = res.is_not_required.reduce((pre, cur) => {
const index = pre.findIndex(d => d.id === cur.id)
if (index === -1) {
pre.push(cur)
} else {
pre.splice(index, 1, cur)
}
return pre
}, oldData.is_not_required)
setData(oldData)
const res = await publicApi.course({page: 1, pageSize: 10 * page})
setData(res)
} catch (e) {
}
}
@ -85,13 +46,15 @@ export const VideoList: FC<Props> = ({categoryKey}) => {
switch (categoryKey) {
case "is_required":
case "is_not_required":
case "is_not_finished":
const find = records.find(d => d?.course_id === id)
if (find) {
if(class_hour === find.finished_count){
return <View className='text-danger'></View>
}
return (<View>{`${class_hour}节/已学${find.finished_count}`}</View>)
}
return (<View>{`${class_hour}节/已学0节`}</View>)
case "is_not_finished":
return (<View>{`${class_hour}节/已学0节`}</View>)
case "is_finished":
return (<View>{`${class_hour}节/已学${class_hour}`}</View>)
}
@ -102,6 +65,10 @@ export const VideoList: FC<Props> = ({categoryKey}) => {
setPage(page + 1)
})
// eventsIndex.on(()=>{
// getRecords()
// })
Taro.useDidShow(() => {
if (init) {
getData()

@ -1,12 +1,12 @@
import {FC, useState} from "react";
import {View} from "@tarojs/components";
import Taro from "@tarojs/taro";
import styles from './index.module.scss'
import {Profile} from '@/store'
// import {Search} from "@/pages/index/components/search";
import {VideoList} from "@/pages/index/components/videoList";
import Tabs, {OnChangOpt, TabList} from "@/components/tabs/tabs";
import {CoursesKey} from "@/api/public";
import Taro from '@tarojs/taro'
const Index: FC = () => {
@ -19,6 +19,8 @@ const Index: FC = () => {
]
const [categoryKey, setCategoryKey] = useState<CoursesKey>('is_required')
function tabChange(data: OnChangOpt) {
setCategoryKey(data.tab?.value as CoursesKey)
}

@ -0,0 +1,3 @@
export default definePageConfig({
navigationBarTitleText: '注册',
})

@ -0,0 +1,49 @@
import {FC} from "react";
import {Button, Form, Input, View} from "@tarojs/components";
import {getCurrentInstance} from "@tarojs/runtime";
import Taro from "@tarojs/taro";
const BingUser: FC = () => {
const {company_id, department_id, start_time, end_time} = getCurrentInstance()?.router?.params as unknown as Offline
Taro.useLoad(() => {
const time = Date.now()
if (!company_id
|| !department_id
|| !start_time
|| !end_time
|| time > new Date(end_time).getTime()
|| time < new Date(start_time).getTime()) {
Taro.showModal({
title: '二维码已过期',
success() {
Taro.reLaunch({url: '/pages/login/login'})
}
})
return
}
})
return (
<View className='h-10 bg-white p-2'>
<Form className='form'>
<View className='item'>
<View></View>
<Input placeholder='请输入用户名' focus/>
</View>
<View className='item'>
<View></View>
<Input type='number' placeholder='请输入手机号'/>
</View>
<Button className='button mt-3' formType='submit'></Button>
</Form>
</View>
)
}
export default BingUser

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '见面会',
enableShareAppMessage: true
})

@ -0,0 +1,11 @@
.page {
background: #fff;
min-height: 100vh;
padding: 20px;
}
.time {
border-bottom: 1px solid #ddd;
padding: 30px 15px;
border-radius: 10px;
}

@ -0,0 +1,168 @@
import {FC, useCallback, useState} from "react";
import {Button, Image, Picker, View} from "@tarojs/components";
import styles from './offline.module.scss'
import Taro from "@tarojs/taro";
import {curriculum} from "@/api";
import {formatDate} from "@/utils/time";
import {getSetting, authorize} from "@tarojs/taro";
import PopPut from "@/components/popPut/popPut";
const Offline: FC = () => {
const [manages, setManages] = useState<Manage[]>([])
const [start, setStart] = useState<string>(formatDate(new Date(), "YY-MM-dd"))
const [end, setEnd] = useState<string>(formatDate(new Date(), "YY-MM-dd"))
const [tempFilePath, setTempFilePath] = useState<string | null>(null);
Taro.useLoad(() => {
curriculum.department().then(res => {
setManages(res.data)
})
})
async function change(e) {
const depName = e.detail.value
if (!depName) {
Taro.showToast({title: '请选择部门', icon: 'error'})
return null
}
const startTime = new Date(start).getTime()
const endTime = new Date(end).getTime()
const depid = manages.find(d => d.name === depName)?.id
const path = encodeURIComponent("/pages/meeting/index")
const qrcodeUrl = `${process.env.TARO_APP_API}/wechat/link?depid=${depid}&start_time=${startTime}&end_time=${endTime}&path=${path}`
Taro.downloadFile({
url: qrcodeUrl,
success(res) {
setTempFilePath(res.tempFilePath)
},
fail() {
Taro.showToast({title: '二维码生产失败', icon: 'error'})
}
}
)
}
// const paintingCanvas = () => {
// Taro.showLoading()
// try {
// Taro.createSelectorQuery().select('#canvasId').fields({node: true, size: true}).exec((res) => {
// const width = res[0].width
// const height = res[0].height
//
// const canvas = res[0].node
//
// Mycanvas = canvas
// const ctx = canvas.getContext('2d')
//
// const dpr = Taro.getSystemInfoSync().pixelRatio
// canvas.width = width * dpr
// canvas.height = height * dpr
// ctx.scale(dpr, dpr)
//
// ctx.fillStyle = '#ffffff'
// ctx.fillRect(0, 0, width, height)
//
// ctx.font = '16px Microsoft YaiHei'
// ctx.fillStyle = 'black'
// ctx.textAlign = 'center';
// ctx.fillText(`${start === end ? `有效期${start}` : `开始:${start} 结束:${end}`}`, width / 2, 280)
//
// Taro.getImageInfo({
// src: 'http://81.69.44.74:39200/kynyxd/images/ILBNTCk3PhC3xEV1zCDAsggudZzkiHJi.png',
// success(res) {
// const img = canvas.createImage()
// img.src = res.path
// img.onload = () => {
// ctx.drawImage(img, (width - 200) / 2, 20, 200, 200)
// }
// }
// })
// })
// } catch (e) {
// Taro.showToast({title: '二维码生成失败', icon: 'error'})
// }
// Taro.hideLoading()
// }
const handleWriteFile = useCallback(() => {
if (tempFilePath) {
Taro.saveImageToPhotosAlbum({
filePath: tempFilePath,
success() {
Taro.showModal({title: '下载成功'})
},
fail() {
Taro.showToast({title: '下载失败', icon: 'error'})
}
})
} else {
Taro.showToast({title: '下载失败', icon: 'error'})
}
}, [tempFilePath])
// function handleWriteFile() {
//
// }
const handleSaveCode = useCallback(() => {
getSetting({
success: function ({authSetting}) {
//没有权限则申请
if (!authSetting["scope.writePhotosAlbum"]) {
authorize({
scope: "scope.writePhotosAlbum",
success: () => {
//存储二维码
handleWriteFile()
},
});
} else {
handleWriteFile()
}
},
});
}, [tempFilePath]);
return (
<View className={styles.page}>
<View className={'flex justify-between ' + styles.time}>
<Picker mode="date" value={start} onChange={(e) => setStart(e.detail.value)} name='start'>
<View>
{start}
</View>
</Picker>
<View></View>
<Picker mode="date" value={start} onChange={(e) => setEnd(e.detail.value)} name='end'>
<View>
{end}
</View>
</Picker>
</View>
<View>
<Picker mode='selector' range={manages} onChange={change} rangeKey='name'>
<PopPut title='部门'/>
</Picker>
</View>
{tempFilePath && <View className='text-center'>
<Image src={tempFilePath} mode='widthFix'/>
<Button className='button' onClick={handleSaveCode}></Button>
</View>}
</View>
)
}
export default Offline

@ -27,6 +27,7 @@ const Service = () => {
oldList.unshift(...[
{title: '部门管理', src: dep, router: '/pages/manage/depAdmin/depAdmin'},
{title: '课程购买', src: buy, router: '/pages/manage/curriculum/curriculum'},
{title: '见面会', src: buy, router: '/pages/manage/offline/offline'},
])
setList(oldList)
}

@ -43,3 +43,22 @@ export function formatDateTime(date, format) {
}
return format;
}
export function formatDate(date, format) {
const year = date.getFullYear(),
month = date.getMonth() + 1,//月份是从0开始的
day = date.getDate(),
hour = date.getHours(),
min = date.getMinutes(),
sec = date.getSeconds();
const preArr = Array.apply(null, Array(10)).map(function (_elem, index) {
return '0' + index;
});
return format.replace(/YY/g, year)
.replace(/MM/g, preArr[month] || month)
.replace(/dd/g, preArr[day] || day)
.replace(/hh/g, preArr[hour] || hour)
.replace(/mm/g, preArr[min] || min)
.replace(/ss/g, preArr[sec] || sec);
}

9
types/user.d.ts vendored

@ -76,7 +76,6 @@ interface CueStats {
}
interface userRecord {
id: number;
duration: number;
@ -91,3 +90,11 @@ interface userRecord{
total_hour_count: number;
finished_count: number;
}
interface Offline {
depid: number
start_time: number
end_time: number
path:string
}

Loading…
Cancel
Save