提交 4d4ae210 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 e981353f
...@@ -5,10 +5,17 @@ import type { UploadProps, UploadUserFile } from 'element-plus' ...@@ -5,10 +5,17 @@ import type { UploadProps, UploadUserFile } from 'element-plus'
import md5 from 'blueimp-md5' import md5 from 'blueimp-md5'
import { getSignature } from '@/api/base' import { getSignature } from '@/api/base'
const props = withDefaults(defineProps<{ modelValue: string | []; prefix?: string }>(), { interface Props {
prefix: 'upload/admin/' modelValue: string | { name: string; url: string }[]
prefix?: string
size?: number
}
const props = withDefaults(defineProps<Props>(), {
prefix: 'upload/saas-learn/'
}) })
const emit = defineEmits(['update:modelValue'])
const emit = defineEmits(['update:modelValue', 'success'])
const uploadData = ref() const uploadData = ref()
...@@ -17,7 +24,7 @@ const fileList = ref<UploadUserFile[]>([]) ...@@ -17,7 +24,7 @@ const fileList = ref<UploadUserFile[]>([])
watch( watch(
() => props.modelValue, () => props.modelValue,
value => { value => {
fileList.value = Array.isArray(value) ? [...value] : [] fileList.value = Array.isArray(value) ? value.map(item => ({ ...item })) : []
} }
) )
...@@ -27,6 +34,10 @@ const showFileList = computed(() => { ...@@ -27,6 +34,10 @@ const showFileList = computed(() => {
// 上传之前 // 上传之前
const handleBeforeUpload = async (file: any) => { const handleBeforeUpload = async (file: any) => {
if (props.size && file.size > props.size) {
ElMessage.error(`文件大小不能超过${props.size / 1024 / 1024}M`)
return false
}
const fileName = file.name const fileName = file.name
const key = props.prefix + md5(fileName + new Date().getTime()) + fileName.substr(fileName.lastIndexOf('.')) const key = props.prefix + md5(fileName + new Date().getTime()) + fileName.substr(fileName.lastIndexOf('.'))
const response: Record<string, any> = await getSignature() const response: Record<string, any> = await getSignature()
...@@ -48,18 +59,13 @@ const handleSuccess = (response: any, file: any, files: any) => { ...@@ -48,18 +59,13 @@ const handleSuccess = (response: any, file: any, files: any) => {
emit( emit(
'update:modelValue', 'update:modelValue',
files.map((item: any) => { files.map((item: any) => {
console.log(item, 'items') return { name: item.name, url: item.url || item.raw.url, size: item.raw.size, type: item.raw.type }
return {
name: item.name,
url: item.url || item.raw.url,
size: item.raw.size,
type: item.raw.type || item.raw.url
}
}) })
) )
} else { } else {
emit('update:modelValue', file.raw.url) emit('update:modelValue', file.raw.url)
} }
emit('success', file, files)
} }
// 上传限制 // 上传限制
...@@ -83,7 +89,7 @@ const handleRemove: UploadProps['onRemove'] = (file, files) => { ...@@ -83,7 +89,7 @@ const handleRemove: UploadProps['onRemove'] = (file, files) => {
// 预览 // 预览
const handlePreview: UploadProps['onPreview'] = uploadFile => { const handlePreview: UploadProps['onPreview'] = uploadFile => {
console.log(uploadFile) window.open(uploadFile.url)
} }
</script> </script>
...@@ -100,18 +106,20 @@ const handlePreview: UploadProps['onPreview'] = uploadFile => { ...@@ -100,18 +106,20 @@ const handlePreview: UploadProps['onPreview'] = uploadFile => {
:file-list="fileList" :file-list="fileList"
class="uploader" class="uploader"
> >
<slot>
<template v-if="showFileList"> <template v-if="showFileList">
<template v-if="$attrs['list-type'] === 'picture-card'"> <template v-if="$attrs['list-type'] === 'picture-card'">
<el-icon><Plus /></el-icon> <el-icon><Plus /></el-icon>
</template> </template>
<template v-else> <template v-else>
<el-button round class="app-upload-btn">本地文件</el-button> <el-button round>本地文件</el-button>
</template> </template>
</template> </template>
<div class="avatar-uploader" v-else> <div class="avatar-uploader" v-else>
<el-image :src="(modelValue as string)" fit="contain" v-if="modelValue" /> <el-image :src="(modelValue as string)" fit="contain" v-if="modelValue" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</div> </div>
</slot>
<template #tip> <template #tip>
<div class="el-upload__tip"><slot name="tip"></slot></div> <div class="el-upload__tip"><slot name="tip"></slot></div>
</template> </template>
......
...@@ -28,3 +28,5 @@ app.use(router) ...@@ -28,3 +28,5 @@ app.use(router)
app.use(ElementPlus, { locale: zhCn }) app.use(ElementPlus, { locale: zhCn })
app.mount('#app') app.mount('#app')
document.domain = 'ezijing.com'
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus' // import { ElMessage } from 'element-plus'
import AppUpload from '../../../../../components/base/AppUpload.vue' import AppUpload from '@/components/base/AppUpload.vue'
interface Props { interface Props {
data?: any data?: any
...@@ -9,8 +9,9 @@ interface Props { ...@@ -9,8 +9,9 @@ interface Props {
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits<{ defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>() }>()
const title = $computed(() => { const title = $computed(() => {
......
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus' // import { ElMessage } from 'element-plus'
import AppUpload from '../../../../../components/base/AppUpload.vue'
interface Props { interface Props {
data?: any data?: any
...@@ -9,8 +8,9 @@ interface Props { ...@@ -9,8 +8,9 @@ interface Props {
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits<{ defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>() }>()
const title = $computed(() => { const title = $computed(() => {
......
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus' // import { ElMessage } from 'element-plus'
interface Props { interface Props {
data?: any data?: any
...@@ -8,8 +8,9 @@ interface Props { ...@@ -8,8 +8,9 @@ interface Props {
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits<{ defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>() }>()
const title = $computed(() => { const title = $computed(() => {
......
<script setup lang="ts"> <script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage } from 'element-plus' // import { ElMessage } from 'element-plus'
interface Props { interface Props {
data?: any data?: any
...@@ -8,14 +8,11 @@ interface Props { ...@@ -8,14 +8,11 @@ interface Props {
const props = defineProps<Props>() const props = defineProps<Props>()
const emit = defineEmits<{ defineEmits<{
(e: 'update'): void (e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>() }>()
const title = $computed(() => {
return '新增实验'
})
const formRef = $ref<FormInstance>() const formRef = $ref<FormInstance>()
const form = reactive({ title: '', status: 1 }) const form = reactive({ title: '', status: 1 })
watchEffect(() => { watchEffect(() => {
......
<script setup lang="ts"></script>
<template>
<div>book</div>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts">
import DiscussAddDialog from './DiscussAddDialog.vue'
import DiscussCommentAddDialog from './DiscussCommentAddDialog.vue'
const dialogVisible = $ref(false)
const commentDialogVisible = $ref(false)
</script>
<template>
<el-radio-group>
<el-radio :label="1">我发起的</el-radio>
<el-radio :label="2">我回复的</el-radio>
<el-radio :label="3">我的小组</el-radio>
<el-radio :label="4">我的班级</el-radio>
</el-radio-group>
<el-row justify="end">
<el-button round type="primary" @click="dialogVisible = true">发表新话题</el-button>
</el-row>
<div>discuss</div>
<el-row justify="end">
<el-button round type="primary" @click="commentDialogVisible = true">我要评论</el-button>
</el-row>
<DiscussAddDialog v-model="dialogVisible"></DiscussAddDialog>
<DiscussCommentAddDialog v-model="commentDialogVisible"></DiscussCommentAddDialog>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
// import { ElMessage } from 'element-plus'
interface Props {
data?: any
}
const props = defineProps<Props>()
defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({ title: '', content: '' })
watchEffect(() => {
Object.assign(form, props.data)
})
const rules = ref<FormRules>({
title: [{ required: true, message: '请输入话题标题', trigger: 'blur' }],
content: [{ required: true, message: '请输入话题描述', trigger: 'blur' }]
})
// 提交
function handleSubmit() {
formRef?.validate().then(update)
}
// 修改
const update = () => {
// submitSuggestion(form).then(() => {
// ElMessage({ message: '提交成功', type: 'success' })
// emit('update')
// formRef?.resetFields()
// })
}
</script>
<template>
<el-dialog title="发表新话题" :close-on-click-modal="false" width="600px">
<el-form ref="formRef" :model="form" :rules="rules">
<el-form-item label="话题标题" prop="title">
<el-input v-model="form.title"></el-input>
</el-form-item>
<el-form-item label="话题描述" prop="content">
<el-input type="textarea" v-model="form.content" />
</el-form-item>
<el-row justify="center">
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button>
<el-button type="primary" round auto-insert-space @click="handleSubmit">发布</el-button>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
// import { ElMessage } from 'element-plus'
interface Props {
data?: any
}
const props = defineProps<Props>()
defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({ content: '' })
watchEffect(() => {
Object.assign(form, props.data)
})
const rules = ref<FormRules>({
content: [{ required: true, message: '请输入话题评论内容', trigger: 'blur' }]
})
// 提交
function handleSubmit() {
formRef?.validate().then(update)
}
// 修改
const update = () => {
// submitSuggestion(form).then(() => {
// ElMessage({ message: '提交成功', type: 'success' })
// emit('update')
// formRef?.resetFields()
// })
}
</script>
<template>
<el-dialog title="话题评论" :close-on-click-modal="false" width="600px">
<el-form ref="formRef" :model="form" :rules="rules">
<el-form-item prop="content">
<el-input type="textarea" v-model="form.content" />
</el-form-item>
<el-row justify="center">
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button>
<el-button type="primary" round auto-insert-space @click="handleSubmit">评论</el-button>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
// import { ElMessage } from 'element-plus'
interface Props {
data?: any
}
const props = defineProps<Props>()
defineEmits<{
(e: 'update'): void
(e: 'update:modelValue', visible: boolean): void
}>()
const formRef = $ref<FormInstance>()
const form = reactive({ files: [] })
watchEffect(() => {
Object.assign(form, props.data)
})
const rules = ref<FormRules>({
files: [{ required: true, message: '请输入话题描述', trigger: 'blur' }]
})
// 提交
function handleSubmit() {
formRef?.validate().then(update)
}
// 修改
const update = () => {
// submitSuggestion(form).then(() => {
// ElMessage({ message: '提交成功', type: 'success' })
// emit('update')
// formRef?.resetFields()
// })
}
</script>
<template>
<el-dialog title="上传实验报告" :close-on-click-modal="false" width="600px">
<el-form ref="formRef" :model="form" :rules="rules">
<el-form-item label="实验报告文件" prop="files">
<AppUpload v-model="form.files">
<template #tip>实验报告文件只能上传一个,支持格式包含:doc docx pdf ppt pptx,大小不超过50M</template>
</AppUpload>
</el-form-item>
<el-row justify="center">
<el-button type="primary" round auto-insert-space @click="handleSubmit">保存</el-button>
<el-button round auto-insert-space @click="$emit('update:modelValue', false)">取消</el-button>
</el-row>
</el-form>
</el-dialog>
</template>
<script setup lang="ts"></script>
<template>
<div>result</div>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts"></script>
<template>
<div>video</div>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts"> <script setup lang="ts">
import { HomeFilled, Select, UploadFilled, FullScreen } from '@element-plus/icons-vue' import { HomeFilled, Select, UploadFilled, FullScreen } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'
import ReportDialog from '../components/ReportDialog.vue'
const LAB_URL = import.meta.env.VITE_LAB_URL const Book = defineAsyncComponent(() => import('../components/Book.vue'))
const Video = defineAsyncComponent(() => import('../components/Video.vue'))
const Discuss = defineAsyncComponent(() => import('../components/Discuss.vue'))
const Result = defineAsyncComponent(() => import('../components/Result.vue'))
// 左侧
const formRef = $ref<FormInstance>()
const form = reactive({ course_id: '', e_id: 1 })
const rules = ref<FormRules>({
course_id: [{ required: true, message: '请选择课程', trigger: 'change' }],
e_id: [{ required: true, message: '请选择实验', trigger: 'change' }]
})
// 右侧
const LAB_URL = import.meta.env.VITE_LAB_URL
let iframeKey = $ref(Date.now()) let iframeKey = $ref(Date.now())
// 返回首页 // 返回首页
function handleBackHome() { function handleBackHome() {
iframeKey = Date.now() iframeKey = Date.now()
} }
const reportDialogVisible = $ref(false)
// 是否已经提交
const submitted = $ref(false)
const iframeRef = $ref<HTMLIFrameElement>()
let screenshotLoading = $ref(false)
let screenshotTimestamp = $ref(0)
// 截图
function handleCapture() {
const iframeWindow = iframeRef?.contentWindow
if (!iframeWindow) return
screenshotTimestamp = Date.now()
screenshotLoading = true
// 发送截图消息
iframeWindow?.postMessage({ action: 'screenshot', timestamp: screenshotTimestamp }, '*')
}
// 截图之后
function handleCaptureCallback(event: MessageEvent) {
const { data } = event
if (data.action === 'screenshot' && data.timestamp === screenshotTimestamp) {
console.log(data)
const img = new Image()
img.src = data.dataURL
document.body.appendChild(img)
screenshotLoading = false
}
}
onMounted(() => {
window.addEventListener('message', handleCaptureCallback, false)
})
onUnmounted(() => {
window.removeEventListener('message', handleCaptureCallback, false)
})
</script> </script>
<template> <template>
<section class="lab"> <section class="lab">
<div class="lab-left"></div> <div class="lab-left">
<el-form
:model="form"
:rules="rules"
label-suffix=":"
hide-required-asterisk
ref="formRef"
style="--el-text-color-regular: #fff"
>
<el-form-item label="请选择课程" prop="course_id">
<el-select style="width: 100%"></el-select>
</el-form-item>
<el-form-item label="请选择实验" prop="e_id">
<el-select style="width: 100%"></el-select>
</el-form-item>
</el-form>
<el-tabs type="border-card">
<el-tab-pane label="实训指导" name="first">
<Book></Book>
</el-tab-pane>
<el-tab-pane label="操作视频" name="second">
<Video></Video>
</el-tab-pane>
<el-tab-pane label="讨论交流" name="third">
<Discuss></Discuss>
</el-tab-pane>
<el-tab-pane label="过程与结果" name="fourth">
<Result></Result>
</el-tab-pane>
</el-tabs>
</div>
<div class="lab-right"> <div class="lab-right">
<AppCard> <AppCard>
<el-row justify="space-between"> <el-row justify="space-between">
<el-button type="primary" :icon="HomeFilled" @click="handleBackHome">返回首页</el-button> <el-button type="primary" :icon="HomeFilled" :disabled="submitted" @click="handleBackHome"
>返回首页</el-button
>
<div> <div>
<el-button type="primary" :icon="Select">提交</el-button> <el-button type="primary" :icon="Select" :disabled="submitted">提交</el-button>
<el-button type="primary" :icon="UploadFilled">上传报告</el-button> <el-button type="primary" :icon="UploadFilled" :disabled="submitted" @click="reportDialogVisible = true"
<el-button type="primary" :icon="FullScreen">截图</el-button> >上传报告</el-button
>
<el-button
type="primary"
:icon="FullScreen"
:disabled="submitted"
:loading="screenshotLoading"
@click="handleCapture"
>截图</el-button
>
</div> </div>
</el-row> </el-row>
</AppCard> </AppCard>
<AppCard> <div class="lab-box">
<iframe :src="LAB_URL" :key="iframeKey" frameborder="0" style="width: 100%; height: 70vh"></iframe> <el-empty description="您已经提交该实验,不能再进行操作,切换其他实验再做操作吧。" v-if="submitted" />
</AppCard> <iframe :src="LAB_URL" :key="iframeKey" frameborder="0" class="iframe" ref="iframeRef" v-else></iframe>
</div>
</div> </div>
</section> </section>
<ReportDialog v-model="reportDialogVisible"></ReportDialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -37,11 +129,26 @@ function handleBackHome() { ...@@ -37,11 +129,26 @@ function handleBackHome() {
height: 100%; height: 100%;
} }
.lab-left { .lab-left {
width: 400px; width: 500px;
background-color: #f5f5f5; padding: 20px;
color: #fff;
background-color: rgba(45, 48, 55, 1);
border-radius: 6px;
} }
.lab-right { .lab-right {
margin-left: 20px; margin-left: 20px;
flex: 1; flex: 1;
display: flex;
flex-direction: column;
height: 100%;
}
.lab-box {
flex: 1;
width: 100%;
margin-top: 20px;
}
.iframe {
width: 100%;
height: 100%;
} }
</style> </style>
...@@ -26,7 +26,8 @@ export default defineConfig(({ mode }) => ({ ...@@ -26,7 +26,8 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem')) cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
}, },
proxy: { proxy: {
'/api': 'https://resource-center.ezijing.com' '/api': 'https://resource-center.ezijing.com',
'/lab': 'https://dev.ezijing.com'
} }
}, },
resolve: { resolve: {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论