Compare commits

...

16 Commits

Author SHA1 Message Date
“zouyf” 2511a6cc32 优化查找图标 2024-11-21 15:02:40 +08:00
白了个白 30b2b9b964 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into baigl 2024-11-21 11:21:16 +08:00
白了个白 cadb8088a6 习题上传:习题内容识别迁移 2024-11-21 11:20:58 +08:00
lyc a9732218f4 Merge pull request 'lyc-dev' (#47) from lyc-dev into main 2024-11-21 10:58:19 +08:00
lyc 538e9190c7 Merge branch 'main' into lyc-dev 2024-11-21 10:57:31 +08:00
lyc 5567e94235 模板 2024-11-21 10:56:35 +08:00
baigl a118afbc64 Merge pull request 'baigl' (#46) from baigl into main
Reviewed-on: #46
2024-11-21 10:38:09 +08:00
白了个白 ab8fe885cb 1 2024-11-21 10:36:00 +08:00
白了个白 853fb871ef 1 2024-11-20 17:35:08 +08:00
白了个白 41db306f77 1 2024-11-20 17:31:14 +08:00
白了个白 0f9c2a7d53 Merge branch 'zouyf_dev' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into baigl 2024-11-20 17:13:31 +08:00
白了个白 bf51f5084f 1 2024-11-20 17:13:07 +08:00
白了个白 2f2350531a 1 2024-11-20 16:20:45 +08:00
白了个白 5cbe56d1bf 作业管理 2024-11-20 15:30:18 +08:00
白了个白 9534622067 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into baigl 2024-11-20 14:33:08 +08:00
白了个白 761f19cf22 习题上传:待完善 2024-11-20 14:32:40 +08:00
16 changed files with 2187 additions and 158 deletions

View File

@ -0,0 +1,65 @@
import request from '@/utils/request'
// 查询知识点列表
export function listKnowlegepoint(query) {
return request({
url: '/point/list',
method: 'get',
params: query
})
}
// 查询一级知识点查下级所有层级
export function childKnowlegepoint(query) {
return request({
url: '/point/child/list',
method: 'get',
params: query
})
}
// 新增
export function addKnowlegepoint(data) {
return request({
url: '/point/add',
method: 'post',
data: data
})
}
// 更新
export function updateKnowlegepoint(data) {
return request({
url: '/point/update',
method: 'post',
data: data
})
}
// 绑定
export function bindKnowlegepoint(data) {
return request({
url: '/point/evalution/bind',
method: 'post',
data: data
})
}
// 查询章节知识点关系
export function getBindlist(query) {
return request({
url: '/point/bind/list',
method: 'get',
params: query
})
}
// 删除
export function delKnowlegepoint(data) {
return request({
url: '/point/bind/delete',
method: 'post',
data: data
})
}

View File

@ -0,0 +1,42 @@
import request from '@/utils/request'
// 新增图片存eos
export function saveUploadFile(data) {
return request({
url: '/education/uploadfile/saveUploadFile',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
})
}
// 新增批量图片存eos
export function saveUploadFiles(data) {
return request({
url: '/education/uploadfile/saveUploadFiles',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
})
}
// 修改basecomment
export function updateUploadFile(data) {
return request({
url: '/education/uploadfile',
method: 'put',
data: data
})
}
// 删除basecomment
export function delUploadFile(id) {
return request({
url: '/education/uploadfile/' + id,
method: 'delete'
})
}

View File

@ -59,7 +59,7 @@ export function editChildTemp(data) {
// 删除子模板 // 删除子模板
export function removeChildTemp(id) { export function removeChildTemp(id) {
return request({ return request({
url: '/education/llmModel/' + id, url: '/education/llmModel/home/' + id,
method: 'delete' method: 'delete'
}) })
} }
@ -100,10 +100,3 @@ export function tempResult(params) {
}) })
} }
// 删除模板结果
export function tempResultRemove(id) {
return request({
url: `/education/result/${id}`,
method: 'get',
})
}

View File

@ -43,6 +43,8 @@ import { ElMessageBox } from 'element-plus'
import { modelList } from '@/api/mode/index' import { modelList } from '@/api/mode/index'
import Dialog from './dialog.vue' import Dialog from './dialog.vue'
import keywordDialog from './keyword-dialog.vue' import keywordDialog from './keyword-dialog.vue'
import emitter from '@/utils/mitt';
const wordDialog = ref(false) const wordDialog = ref(false)
const props = defineProps({ const props = defineProps({
@ -70,7 +72,7 @@ const curTemplate = reactive({ name: '', id: '' })
const templateList = ref([]) const templateList = ref([])
// //
const getTemplateList = () => { const getTemplateList = () => {
modelList({ model: props.type, type: 1 }).then(res => { modelList({ model: props.type, type: 1, pageNum: 1, pageSize: 10000 }).then(res => {
templateList.value = res.rows templateList.value = res.rows
Object.assign(curTemplate, res.rows[0]); Object.assign(curTemplate, res.rows[0]);
emit('changeTemp', res.rows[0].id) emit('changeTemp', res.rows[0].id)
@ -94,11 +96,18 @@ const changeTemplate = (val) => {
}) })
} }
emitter.on('onGetMain', () =>{
getTemplateList()
})
const onAdd = () => { const onAdd = () => {
wordDialog.value = true wordDialog.value = true
} }
onUnmounted(() => {
emitter.off('onGetMain')
})
onMounted(() => { onMounted(() => {
getTemplateList() getTemplateList()
}) })
@ -129,5 +138,4 @@ onMounted(() => {
font-weight: bold; font-weight: bold;
} }
} }
</style> </style>

View File

@ -2,18 +2,18 @@
<el-dialog v-model="mode" :show-close="false" width="600" destroy-on-close> <el-dialog v-model="mode" :show-close="false" width="600" destroy-on-close>
<template #header> <template #header>
<div class="custom-header flex"> <div class="custom-header flex">
<span>{{ isAdd ? item && item.ex3 == '1' ? '请输入新的模板名称' : '添加提示词' : '编辑提示词' }}</span> <span>{{ item.ex3 == '1' ? '请输入新的模板名称' : isAdd ? '添加提示词' : '编辑提示词' }}</span>
<i class="iconfont icon-guanbi" @click="mode = false"></i> <i class="iconfont icon-guanbi" @click="mode = false"></i>
</div> </div>
</template> </template>
<div class="dialog-content" v-loading="loading"> <div class="dialog-content" v-loading="loading">
<p class="small-tip" v-if="item && item.ex3 == '1'">*当前模板为系统预设不支持直接操作复制一份为自己的然后再操作</p> <p class="small-tip" v-if="item && item.ex3 == '1'">*当前模板为系统预设不支持直接操作需要复制一份为自己的然后再操作</p>
<el-form :model="form" label-width="auto"> <el-form :model="form" label-width="auto">
<el-form-item label="名称"> <el-form-item label="名称">
<el-input v-model="form.name" /> <el-input v-model="form.name" />
</el-form-item> </el-form-item>
<el-form-item label="提示词" v-if="isAdd ? !(item && item.ex3 == '1') : true"> <el-form-item label="提示词" v-if="item.ex3 == '1' ? false : true">
<el-input v-model="form.prompt" type="textarea" /> <el-input v-model="form.prompt" type="textarea" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -33,10 +33,9 @@
<script setup> <script setup>
import { ref, reactive, watch } from 'vue' import { ref, reactive, watch } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import emitter from '@/utils/mitt';
import { addKeyWords, addChildTemp, editChildTemp } from '@/api/mode/index' import { addKeyWords, addChildTemp, editChildTemp } from '@/api/mode/index'
const mode = defineModel() const mode = defineModel()
const props = defineProps({ const props = defineProps({
modeType: { modeType: {
@ -48,20 +47,25 @@ const props = defineProps({
default: true default: true
}, },
item: { // item: { //
type: Object type: Object,
}, default: () => {
temp: { // return { ex3: '' }
Object
} }
},
tempId: {
type: [String, Number],
default: ''
},
}) })
const form = reactive({ const form = reactive({
name: '', name: '',
prompt: '', prompt: '',
}) })
watch(() => props.isAdd, (newVal) => { watch(() => props.isAdd, (newVal) => {
console.log(newVal)
if (!newVal) { if (!newVal) {
form.name = props.item?.name form.name = props.item?.name
form.prompt = props.item?.prompt form.prompt = props.item?.prompt
@ -71,21 +75,52 @@ watch(() => props.isAdd, (newVal) => {
const loading = ref(false) const loading = ref(false)
const saveAdd = async () => { const saveAdd = async () => {
loading.value = true loading.value = true
if (props.item.ex3 == '1') {
if (props.isAdd) { if (props.isAdd) {
try { try {
var msg = null // copy
// const { msg } = await addKeyWords({ name: form.name, id: props.item.id })
if (props.item.ex3 == '1') { emitter.emit('onGetChild')
var { msg } = await addKeyWords({ name: form.name, id: props.item.id }) ElMessage.success(msg)
mode.value = false
} finally {
loading.value = false
}
} }
else{ else{
onAddChildTemp(props.item.parentId)
}
} else {
if (props.isAdd) {
onAddChildTemp(props.item.id)
}
else {
try {
let data = JSON.parse(JSON.stringify(props.item))
data.name = form.name;
data.prompt = form.prompt
const { msg } = await editChildTemp(data)
emitter.emit('onGetChild')
ElMessage.success(msg)
mode.value = false
} finally {
loading.value = false
}
}
}
}
//
const onAddChildTemp = async (parentId) => {
// //
let obj = { let obj = {
name: form.name, name: form.name,
type: 2, // 2 type: 2, // 2
sortNum: 1, sortNum: 1,
parentId: props.item.id, parentId,
lmType: 1, lmType: 1,
model: props.modeType, model: props.modeType,
prompt: form.prompt, prompt: form.prompt,
@ -93,27 +128,15 @@ const saveAdd = async () => {
ex2: props.item.ex2, // ex2: props.item.ex2, //
ex3: '', // ex3: '', //
} }
var { msg } = await addChildTemp(obj)
}
ElMessage.success(msg)
mode.value = false
} finally {
loading.value = false
}
} else {
//
try { try {
let data = JSON.parse(JSON.stringify(props.item)) var { msg } = await addChildTemp(obj)
data.name = form.name; emitter.emit('onGetChild')
data.prompt = form.prompt
const { msg } = await editChildTemp(data)
ElMessage.success(msg) ElMessage.success(msg)
mode.value = false mode.value = false
} finally { } finally {
loading.value = false loading.value = false
} }
} }
}
</script> </script>
@ -128,6 +151,7 @@ const saveAdd = async () => {
font-weight: bold; font-weight: bold;
} }
} }
.small-tip { .small-tip {
text-align: left; text-align: left;
font-size: 12px; font-size: 12px;

View File

@ -55,13 +55,13 @@
<!--AI 对话调整--> <!--AI 对话调整-->
<AdjustDialog v-model="isAdjust" :modeType="modeType" :item="editItem" @saveAdjust="saveAdjust" /> <AdjustDialog v-model="isAdjust" :modeType="modeType" :item="editItem" @saveAdjust="saveAdjust" />
<!--编辑提示词--> <!--编辑提示词-->
<keywordDialog v-model="isEditKeyWord" :isAdd="!isEditKeyWord" :item="keywordItem"/> <keywordDialog v-model="isEditKeyWord" :isAdd="isAdd" :item="keywordItem" :tempId="tempId" />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, watch } from 'vue'; import { ref, reactive, onMounted, watch, onUnmounted } from 'vue';
import { ElMessage } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import EditDialog from './edit-dialog.vue' import EditDialog from './edit-dialog.vue'
import AdjustDialog from './adjust-dialog.vue' import AdjustDialog from './adjust-dialog.vue'
import keywordDialog from './keyword-dialog.vue'; import keywordDialog from './keyword-dialog.vue';
@ -69,6 +69,7 @@ import { sessionStore } from '@/utils/store'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { tempSave, completion, modelList, removeChildTemp, tempResult } from '@/api/mode/index' import { tempSave, completion, modelList, removeChildTemp, tempResult } from '@/api/mode/index'
import { dataSetJson } from '@/utils/comm.js' import { dataSetJson } from '@/utils/comm.js'
import emitter from '@/utils/mitt';
const userStore = useUserStore() const userStore = useUserStore()
@ -83,10 +84,15 @@ const props = defineProps({
} }
}) })
emitter.on('onGetChild', () =>{
getChildTemplate()
})
// //
const tempLoading = ref(false) const tempLoading = ref(false)
const childTempList = ref([]) const childTempList = ref([])
const getChildTemplate = () => { const getChildTemplate = () => {
tempLoading.value = true tempLoading.value = true
modelList({ model: props.modeType, type: 2, parentId: props.tempId }).then(res => { modelList({ model: props.modeType, type: 2, parentId: props.tempId }).then(res => {
childTempList.value = res.rows childTempList.value = res.rows
@ -98,7 +104,6 @@ const getChildTemplate = () => {
// //
const getTempResult = () => { const getTempResult = () => {
tempResult({ mainModelId: props.tempId }).then(res => { tempResult({ mainModelId: props.tempId }).then(res => {
console.log(res,1000)
let rows = res.rows let rows = res.rows
childTempList.value.forEach(item => { childTempList.value.forEach(item => {
rows.forEach(el => { rows.forEach(el => {
@ -111,8 +116,6 @@ const getTempResult = () =>{
}) })
} }
const isEdit = ref(false) const isEdit = ref(false)
watch(() => props.tempId, (newVal) => { watch(() => props.tempId, (newVal) => {
if (newVal) { if (newVal) {
@ -133,7 +136,6 @@ const params = reactive(
const curNode = reactive({}) const curNode = reactive({})
const getConversation = () => { const getConversation = () => {
getCompletion() getCompletion()
} }
// //
@ -224,18 +226,43 @@ const saveAdjust = (item) => {
// //
const keywordItem = reactive({}) const keywordItem = reactive({})
const isEditKeyWord = ref(false) const isEditKeyWord = ref(false)
const isAdd = ref(true)
const editKeyWord = (item) => { const editKeyWord = (item) => {
console.log(item) console.log(item)
isAdd.value = false
isEditKeyWord.value = true isEditKeyWord.value = true
Object.assign(keywordItem, item) Object.assign(keywordItem, item)
} }
// //
const removeItem = async (item) => { const removeItem = async (item) => {
const { msg } = await removeChildTemp(item.id) if (item.ex3 != '1') {
ElMessage.success(msg) ElMessageBox.confirm(
'确认是否移除?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
console.log(item)
removeChildTemp(item.id).then(res => {
ElMessage.success('操作成功')
getChildTemplate() getChildTemplate()
})
})
}
else{
isAdd.value = false
Object.assign(keywordItem, item)
isEditKeyWord.value = true
}
// const { msg } = await removeChildTemp(item.id)
// ElMessage.success(msg)
// getChildTemplate()
} }
@ -246,8 +273,12 @@ onMounted(() => {
let jsonKey = `${text}-${data.edustage}-${data.edusubject}` let jsonKey = `${text}-${data.edustage}-${data.edusubject}`
params.dataset_id = dataSetJson[jsonKey] params.dataset_id = dataSetJson[jsonKey]
}) })
//
onUnmounted(() => {
emitter.off('onGetChild')
})
defineExpose({ defineExpose({
getConversation getConversation
@ -451,18 +482,20 @@ defineExpose({
} }
} }
.icon-shenglvehao { .icon-shenglvehao {
font-weight: bold; font-weight: bold;
font-size: 22px; font-size: 22px;
} }
:deep(.el-popover) { :deep(.el-popover) {
min-width: 50px; min-width: 50px;
width: 50px !important; width: 50px !important;
} }
.pl-25 { .pl-25 {
padding-left: 25px; padding-left: 25px;
} }
</style> </style>
<style> <style>
.template-custom-popover { .template-custom-popover {

View File

@ -46,7 +46,8 @@ import "tinymce/plugins/anchor"; //锚点
import { ref, reactive, defineProps, defineEmits, nextTick, onMounted, computed, watch } from 'vue' import { ref, reactive, defineProps, defineEmits, nextTick, onMounted, computed, watch } from 'vue'
import { getStaticUrl } from '@/utils/tool' import { getStaticUrl } from '@/utils/tool'
//import { listUploadfile, getUploadFile, delUploadFile, addUploadFile, saveUploadFile } from "@/api/comm/uploadfile"; import useUserStore from '@/store/modules/user'
import { saveUploadFile } from "@/api/file/img";
const emits = defineEmits(["update:modelValue", "setHtml"]); const emits = defineEmits(["update:modelValue", "setHtml"]);
//props便 //props便
@ -108,6 +109,8 @@ const props = defineProps({
}, },
}); });
const userStore = useUserStore().user;
const pasteImgName = ref(''); const pasteImgName = ref('');
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); //
const loading = ref(false); const loading = ref(false);
@ -212,29 +215,31 @@ const init = reactive({
// /() - , [images_upload_handler] // /() - , [images_upload_handler]
file_picker_callback: function(callback, value, meta) { file_picker_callback: function(callback, value, meta) {
return;
// //
let filetype='.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4'; // let filetype='.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4';
let upURL = '/common/upload'; // let upURL = '/common/upload';
// // //
switch(meta.filetype){ // switch(meta.filetype){
case 'image': // case 'image':
filetype='.jpg, .jpeg, .png, .gif'; // filetype='.jpg, .jpeg, .png, .gif';
//upURL='upimg.php'; // //upURL='upimg.php';
break; // break;
case 'media': // case 'media':
filetype='.mp3, .mp4'; // filetype='.mp3, .mp4';
//upURL='upfile.php'; // //upURL='upfile.php';
break; // break;
case 'file': // case 'file':
default: // default:
} // }
// input // // input
let input = document.createElement('input'); // let input = document.createElement('input');
input.setAttribute('type', 'file'); // input.setAttribute('type', 'file');
input.setAttribute('accept', filetype); // input.setAttribute('accept', filetype);
// // //
// input.onchange = function() { // input.onchange = function() {
// const file = this.files[0]; // const file = this.files[0];
// const formData = new FormData(); // const formData = new FormData();
@ -250,7 +255,7 @@ const init = reactive({
// }); // });
// }; // };
input.click(); // input.click();
}, },
// /() // /()
@ -278,22 +283,25 @@ const init = reactive({
formData.append("entpcourseid", 0); formData.append("entpcourseid", 0);
formData.append("filetype", "image"); formData.append("filetype", "image");
formData.append("suffix", "image"); formData.append("suffix", "image");
formData.append("status", '0'); formData.append("status", '1');
if(props.upFileParams?.hasOwnProperty('deptId')){ if(userStore.deptId && userStore.deptId != null){
formData.append("entpid", props.upFileParams.deptId); formData.append("entpid", userStore.deptId);
} }
if(props.upFileParams?.hasOwnProperty('userId')){ if(userStore.userId && userStore.userId != null){
formData.append("userid", props.upFileParams.userId); formData.append("userid", userStore.userId);
} }
if(props.upFileParams?.hasOwnProperty('edudegree')){ if(userStore.edudegree && userStore.edudegree != null){
let edudegree = props.upFileParams.edudegree.toString(); let edudegree = userStore.edudegree.toString();
if(edudegree != '' && edudegree.indexOf('年级') == -1){ if(edudegree != '' && edudegree.indexOf('年级') == -1){
edudegree += '年级'; edudegree += '年级';
} }
formData.append("edudegree", edudegree); formData.append("edudegree", edudegree);
} }
if(props.upFileParams?.hasOwnProperty('edusubject')){ if(userStore.edusubject && userStore.edusubject != null){
formData.append("edusubject", props.upFileParams.edusubject); formData.append("edusubject", userStore.edusubject);
}
if(userStore.edustage && userStore.edustage != null){
formData.append("edustage", userStore.edustage);
} }
if(props.upFileParams?.hasOwnProperty('lessionId')){ if(props.upFileParams?.hasOwnProperty('lessionId')){
formData.append("evalid", props.upFileParams.lessionId); formData.append("evalid", props.upFileParams.lessionId);
@ -302,18 +310,21 @@ const init = reactive({
formData.append("filegroup", props.upFileParams.fileAlias); formData.append("filegroup", props.upFileParams.fileAlias);
} }
loading.value = true; loading.value = true;
console.log('formData->', formData);
// //
// saveUploadFile(formData) saveUploadFile(formData)
// .then((res) => { .then((res) => {
// loading.value = false; console.log('res->', res);
// return resolve(res.fileurl); loading.value = false;
// }) return resolve(res.fileurl);
// .catch((err) => { })
// loading.value = false; .catch((err) => {
// return reject('err:' + err); loading.value = false;
// }); return reject('err:' + err);
});
} }
), ),

View File

@ -73,6 +73,18 @@ export const constantRoutes = [
name: 'teaching-design', name: 'teaching-design',
meta: { title: '教学框架设计' }, meta: { title: '教学框架设计' },
}, },
{
path: 'newClassTaskAssign',
component: () => import('@/views/classTask/newClassTaskAssign/index.vue'),
name: 'newClassTaskAssign',
meta: { title: '作业管理' }
},
{
path: 'questionUpload',
component: () => import('@/views/classTask/newClassTaskAssign/questionUpload/index.vue'),
name: 'questionUpload',
meta: { title: '习题上传' }
},
] ]
}, },
@ -128,26 +140,12 @@ const dynamicRoutes = [
name: 'classTaskAssign', name: 'classTaskAssign',
meta: { title: '作业布置', showBread: true } meta: { title: '作业布置', showBread: true }
}, },
{
path: 'newClassTaskAssign',
component: () => import('@/views/classTask/newClassTaskAssign/index.vue'),
name: 'newClassTaskAssign',
meta: { title: '新作业管理', showBread: true }
},
{
path: 'questionUpload',
component: () => import('@/views/classTask/newClassTaskAssign/questionUpload/index.vue'),
name: 'questionUpload',
meta: { title: '新作业管理', showBread: true }
},
{ {
path: 'classTask', path: 'classTask',
component: () => import('@/views/classTask/classTask.vue'), component: () => import('@/views/classTask/classTask.vue'),
name: 'classCorrect', name: 'classCorrect',
meta: { title: '作业批改', showBread: true } meta: { title: '作业批改', showBread: true }
}, },
{ {
path: '/teach', path: '/teach',
component: () => import('@/views/teach/index.vue'), component: () => import('@/views/teach/index.vue'),

View File

@ -16,7 +16,6 @@
<!-- <i v-if="!isCollapse" class="iconfont icon-xiangzuo" style="color: blue;"></i> --> <!-- <i v-if="!isCollapse" class="iconfont icon-xiangzuo" style="color: blue;"></i> -->
<span>作业设计</span> <span>作业设计</span>
<!-- <i v-if="isCollapse" class="iconfont icon-xiangyou" style="color: blue;"></i> --> <!-- <i v-if="isCollapse" class="iconfont icon-xiangyou" style="color: blue;"></i> -->
<el-button type="primary" @click="goToNewClassTaskAssign">新版作业管理</el-button>
</div> </div>
<div v-else class="unit-top-left"> <div v-else class="unit-top-left">
<i class="iconfont icon-xiangzuo cursor-pointer" style="color: blue;" @click="goBack">返回上页</i> <i class="iconfont icon-xiangzuo cursor-pointer" style="color: blue;" @click="goBack">返回上页</i>
@ -81,9 +80,6 @@ const courseObj = reactive({
}) })
// --------------------------------------------------- // ---------------------------------------------------
const goToNewClassTaskAssign = () => {
router.push({ path: '/newClassTaskAssign', query: { courseObj: JSON.stringify(courseObj)} });
}
// //
const getData = (data) => { const getData = (data) => {

View File

@ -94,6 +94,7 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import { Search } from '@element-plus/icons-vue'
import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue' import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
@ -104,9 +105,8 @@ import { delEntpcoursework } from "@/api/education/entpCourseWork";
import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue' import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
import { useHandleData } from "@/hooks/useHandleData"; import { useHandleData } from "@/hooks/useHandleData";
import { processList } from '@/hooks/useProcessList' import { processList } from '@/hooks/useProcessList'
import { useGetHomework } from '@/hooks/useGetHomework'
import { sessionStore } from '@/utils/store' import { debounce } from '@/utils/comm'
import {throttle,debounce } from '@/utils/comm'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
const router = useRouter() const router = useRouter()
@ -196,7 +196,7 @@ onMounted(() => {
}) })
const goToQuestUpload = () => { const goToQuestUpload = () => {
router.push({ path: '/questionUpload', query: { courseObj: JSON.stringify(props.bookobj) } }); router.push({ path: '/model/questionUpload', query: { courseObj: JSON.stringify(props.bookobj) } });
} }
const initPageParams = () => { const initPageParams = () => {

View File

@ -55,7 +55,19 @@
</div> </div>
<div class="page-right"> <div class="page-right">
<QuesItem ref="refquesItem"
:bookobj="courseObj"
:activeVersion="activeParams.version"
:activeLession="activeParams.lession"
:evalidArr="activeParams.evalidArr"
:curLessionList="curLessionList"
:isCropper="true"
@submit-exam-single-callback="onSubmitExamSingleCallback"
@cancel-exam-single-callback="onCancelExamSingleCallback"
@cropper-exam-form-item="cropperExamFormItem"
:style="{'height':'100%', 'overflow': 'auto', 'padding-top': '10px'}"
>
</QuesItem>
</div> </div>
</div> </div>
</template> </template>
@ -72,14 +84,29 @@ import { editListItem } from '@/hooks/useClassTask'
import { useGetHomework } from '@/hooks/useGetHomework' import { useGetHomework } from '@/hooks/useGetHomework'
import { sessionStore } from '@/utils/store' import { sessionStore } from '@/utils/store'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import useUserStore from '@/store/modules/user'
import { ocrImg2ExamByManualUpl, ocrImg2ItemByManualUpl } from "@/views/classTask/newClassTaskAssign/questionUpload/ocrImg2ExamQues"; import { ocrImg2ExamByManualUpl, ocrImg2ItemByManualUpl } from "@/views/classTask/newClassTaskAssign/questionUpload/ocrImg2ExamQues";
import QuesItem from "@/views/classTask/newClassTaskAssign/questionUpload/quesItem/index.vue";
// const Remote = require('@electron/remote')
// const fs = require('fs');
// const path = require('path');
import useUserStore from '@/store/modules/user'
const userStore = useUserStore().user const userStore = useUserStore().user
const route = useRoute(); const route = useRoute();
const router = useRouter()
const { proxy } = getCurrentInstance() const { proxy } = getCurrentInstance()
const props = defineProps({ const props = defineProps({
}) })
const activeParams = reactive({
version: {},
lession: {},
tab: '国家体系',
evalidArr: [],//id
versionList: [],//list
lessionList: [],//list
});
const propsQueryCourseObj = route.query.courseObj;// const propsQueryCourseObj = route.query.courseObj;//
const courseObj = reactive({ const courseObj = reactive({
@ -120,6 +147,7 @@ const cropOption = reactive({
}) })
onMounted(() => { onMounted(() => {
console.log('propsQueryCourseObj', JSON.parse(propsQueryCourseObj)); console.log('propsQueryCourseObj', JSON.parse(propsQueryCourseObj));
if(propsQueryCourseObj&&JSON.parse(propsQueryCourseObj)){ if(propsQueryCourseObj&&JSON.parse(propsQueryCourseObj)){
@ -146,7 +174,22 @@ const initHomeWork = async()=> {
// taskList.value = res; // taskList.value = res;
// tasklist_loading.value = false; // tasklist_loading.value = false;
} }
const getBase64 = (file) =>{
return new Promise(function (resolve, reject) {
let reader = new FileReader();
let imgResult = "";
reader.readAsDataURL(file);
reader.onload = function () {
imgResult = reader.result;
};
reader.onerror = function (error) {
reject(error);
};
reader.onloadend = function () {
resolve(imgResult);
};
});
}
/** /**
* @desc: 上传本地图片 * @desc: 上传本地图片
* @return: {*} * @return: {*}
@ -162,10 +205,35 @@ const handleImportImg = (uploadFile) => {
} }
console.log('uploadFile', uploadFile); console.log('uploadFile', uploadFile);
// //
getBase64(uploadFile.raw).then(res => {
// console.log('res-------', res);
// Electron 使 URL.createObjectURL
// const base64Data = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/...'; // Base64
// const base64Data = res; // Base64
// const buffer = Buffer.from(base64Data.split(',')[1], 'base64');
// const filePath = path.join(Remote.app.getPath('userData'), 'image.jpg');
// console.log(filePath,'???????????????????');
// fs.writeFileSync(filePath, buffer);
// const buf = fs.readFileSync(filePath)
// console.log(buf);
// const uint8Buffer = Uint8Array.from(buf)
// cropOption.img = window.URL.createObjectURL(new Blob([uint8Buffer]));
// cropOption.img = URL.createObjectURL(new Blob([fs.readFileSync(filePath)]));
// cropOption.img = URL.createObjectURL(new Blob([buffer]));
cropOption.img = res;
// console.log(cropOption.img);
// cropOption.img = window.URL.createObjectURL(new Blob([res]));
// console.log(cropOption.img);
})
// cropOption.img = window.URL.createObjectURL(uploadFile.raw); // cropOption.img = window.URL.createObjectURL(uploadFile.raw);
cropOption.img = window.URL.createObjectURL(new Blob([uploadFile.raw])); // cropOption.img = window.URL.createObjectURL(new Blob([uploadFile.raw]));
console.log(cropOption.img); // cropOption.img = window.URL.createObjectURL(new Blob([uploadFile.raw]));
// console.log(cropOption.img);
ElMessage.success('上传成功'); ElMessage.success('上传成功');
}; };
/** /**
@ -178,6 +246,9 @@ const getClipboardImg = async() => {
for (const item of clipboardItems) { for (const item of clipboardItems) {
for (const type of item.types) { for (const type of item.types) {
if (type.includes('image/')) { if (type.includes('image/')) {
console.log('剪贴板图片type', type);
console.log('剪贴板图片item', item);
console.log('剪贴板图片clipboardItems', clipboardItems);
const blob = await item.getType(type); const blob = await item.getType(type);
// blob Blob // blob Blob
cropOption.img = URL.createObjectURL(blob); cropOption.img = URL.createObjectURL(blob);
@ -213,7 +284,50 @@ const identifyOverallImg =()=>{
}) })
}); });
}; };
/** 单题上传/纠错 抛上来的识别单项内容 */
const cropperExamFormItem=(examType, curItem)=>{
if (cropOption.img == null || cropOption.img == '') {
ElMessage({
message: '识别区域中无图片, 禁止识别',
type: 'error',
});
return;
}
let formValue = null;
proxy.$refs.cropper.getCropData(async (imgBase64) => {
formValue = await ocrImg2ItemByManualUpl(OCR_WORK_TEST, imgBase64, examType, curItem);
if (formValue == null) {
return;
}
nextTick( () => {
// []
let key = curItem;
if (examType === '复合题' && curItem=='workdesc') {
key = 'mulList';
}
else if (curItem=='workdesc') {
key = 'list';
}
proxy.$refs.refquesItem.cropperFormItemCallBack(key, formValue);
})
});
}
//
const onCancelExamSingleCallback=()=>{
//
//
// this.dlgImportSingle.open = false;
};
/** 单题上传/纠错 完成后的回调 */
const onSubmitExamSingleCallback =(callback) =>{
if (callback.submitType !== 1) {
console.log('999-999');
return;
}
//
router.back()
};
</script> </script>

View File

@ -1,5 +1,6 @@
import { ElMessageBox, ElMessage } from "element-plus"; import { ElMessageBox, ElMessage } from "element-plus";
import qs from "qs"; import qs from "qs";
import axios from 'axios'
import { pyOCRAPI } from "@/api/education/entpcoursework"; import { pyOCRAPI } from "@/api/education/entpcoursework";

View File

@ -102,6 +102,8 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import { Search } from '@element-plus/icons-vue'
import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue' import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue'
import {listEntpcoursework, listEntpcourseworkNew, getEntpcoursework} from '@/api/education/entpCourseWork' import {listEntpcoursework, listEntpcourseworkNew, getEntpcoursework} from '@/api/education/entpCourseWork'

View File

@ -2,7 +2,13 @@
<div> <div>
<div class="form-item-cover"> <div class="form-item-cover">
<el-form-item label="答案点评" prop="discuss"> <el-form-item label="答案点评" prop="discuss">
<tinymce v-model="discuss"/> <tinymce
v-model="discuss"
:upFileParams="{
lessionId: 123456,
fileAlias: '单题上传',
}"
/>
</el-form-item> </el-form-item>
</div> </div>
</div> </div>

View File

@ -2,7 +2,8 @@
<div> <div>
<div class="mb-4"> <div class="mb-4">
<el-button type="primary" @click="onchange('/model/curriculum')">课标研读</el-button> <el-button type="primary" @click="onchange('/model/curriculum')">课标研读</el-button>
<el-button type="primary" @click="onchange('/model/management')">作业管理</el-button> <el-button type="primary" @click="onchange('/model/management')">作业管理1</el-button>
<el-button type="primary" @click="onchange('/model/newClassTaskAssign')">作业管理2</el-button>
<el-button type="success" @click="onchange('/model/teaching')">教材研读</el-button> <el-button type="success" @click="onchange('/model/teaching')">教材研读</el-button>
<el-button type="info" @click="onchange('/model/design')">教学框架设计</el-button> <el-button type="info" @click="onchange('/model/design')">教学框架设计</el-button>
<el-button type="success" @click="openPPTist">打开PPTist</el-button> <el-button type="success" @click="openPPTist">打开PPTist</el-button>
@ -13,19 +14,58 @@
</template> </template>
<script setup> <script setup>
import { onMounted, ref, watch, reactive } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { createWindow } from '@/utils/tool' // import { createWindow } from '@/utils/tool' //
import ChooseTextbook from '@/components/choose-textbook/index.vue' import ChooseTextbook from '@/components/choose-textbook/index.vue'
const router = useRouter() const router = useRouter()
const courseObj = reactive({
// : id,id,id,
textbookId: '',
levelFirstId: '',
levelSecondId: '',
coursetitle:'',
node: null, //
//
})
//
const getData = (data) => {
const { textBook, node } = data
let textbookId = textBook.curBookId
let levelSecondId = node.id
let levelFirstId
if (node.parentNode) {
levelFirstId = node.parentNode.id
} else {
levelFirstId = node.id
levelSecondId = ''
}
courseObj.textbookId = textbookId //
courseObj.levelFirstId = levelFirstId //
courseObj.levelSecondId = levelSecondId //
courseObj.coursetitle = node.itemtitle // (/)
courseObj.node = node; //
// ID
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId}))
}
const openPPTist = () =>{ const openPPTist = () =>{
createWindow('open-win', {url: '/pptist'}) createWindow('open-win', {url: '/pptist'})
} }
const onchange = (path) =>{ const onchange = (path) =>{
if(path == '/model/newClassTaskAssign'){
//
router.push({path, query: { courseObj: JSON.stringify(courseObj)}})
}else{
router.push(path) router.push(path)
} }
}
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>