Compare commits

...

33 Commits

Author SHA1 Message Date
小杨 e1caa441cb add:新增第三方资源筛选; 2024-11-26 09:35:25 +08:00
zouyf ca3f2658a7 Merge pull request '1' (#64) from zouyf_dev into main
Reviewed-on: #64
2024-11-25 11:19:34 +08:00
“zouyf” cd1fc036a2 1 2024-11-25 11:18:45 +08:00
zouyf 727299aac9 Merge pull request 'zouyf_dev' (#63) from zouyf_dev into main
Reviewed-on: #63
2024-11-25 11:07:13 +08:00
lyc 27b0457eef Merge pull request 'edit' (#62) from lyc-dev into main 2024-11-25 11:00:42 +08:00
lyc 34e74c5ec6 edit 2024-11-25 10:59:56 +08:00
“zouyf” 208f5d496f Merge branch 'main' into zouyf_dev 2024-11-25 10:59:40 +08:00
“zouyf” 122fb41690 [习题上传] - 章节下增加对应知识点数据 2024-11-25 10:59:27 +08:00
朱浩 eb4a58b306 Merge remote-tracking branch 'origin/main' 2024-11-25 10:54:33 +08:00
朱浩 a313a0e8b0 BUG修复 2024-11-25 10:54:16 +08:00
“zouyf” 630a7b4c50 1 2024-11-22 16:57:19 +08:00
zhengdegang 01dc5dc643 Merge pull request 'zdg_dev' (#61) from zdg_dev into main
Reviewed-on: #61
2024-11-22 15:57:35 +08:00
zdg 349bdbd181 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into zdg_dev
# Conflicts:
#	src/renderer/index.html
#	src/renderer/src/views/model/index.vue
2024-11-22 15:55:44 +08:00
zdg 8707b54420 pptList 功能二开 2024-11-22 15:18:42 +08:00
朱浩 f08b5a8bee Merge remote-tracking branch 'origin/main' 2024-11-22 11:07:11 +08:00
朱浩 e2255544da BUG修复 2024-11-22 11:06:57 +08:00
zouyf 748a3c4b86 Merge pull request '增加根据用户id查询' (#60) from zouyf_dev into main
Reviewed-on: #60
2024-11-22 11:03:50 +08:00
“zouyf” c4c1115abb 增加根据用户id查询 2024-11-22 11:03:19 +08:00
zouyf eefc4d75f8 Merge pull request 'zouyf_dev' (#59) from zouyf_dev into main
Reviewed-on: #59
2024-11-22 10:50:57 +08:00
“zouyf” db99dbf0d8 Merge branch 'main' into zouyf_dev 2024-11-22 10:49:05 +08:00
“zouyf” 3b6878ece5 更新下划线格式化 2024-11-22 10:48:37 +08:00
朱浩 cbc6f21100 没有教材-的datasetid 2024-11-22 10:47:44 +08:00
朱浩 cefc29df6a 版本更新 2024-11-22 09:58:50 +08:00
朱浩 cb3485f10f Merge remote-tracking branch 'origin/main' 2024-11-22 09:58:09 +08:00
朱浩 cbb6a10c1d 窗口初始化最大化 2024-11-22 09:58:01 +08:00
zouyf 95c93f19ee Merge pull request 'zouyf_dev' (#58) from zouyf_dev into main
Reviewed-on: #58
2024-11-22 09:54:36 +08:00
“zouyf” dcd1a3bb05 1 2024-11-22 09:54:05 +08:00
“zouyf” 5ac33bd1ca 1 2024-11-22 09:53:15 +08:00
yangws dc36821366 Merge pull request 'fix:新增图标;' (#57) from yws_dev into main
Reviewed-on: #57
2024-11-22 09:52:48 +08:00
“zouyf” bd50a7cdf0 Merge branch 'main' into zouyf_dev 2024-11-22 09:42:15 +08:00
“zouyf” 94e609164a 替换菁优网填空标识 2024-11-22 09:41:58 +08:00
zdg 82091fbef5 Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into zdg_dev 2024-11-19 17:26:11 +08:00
zdg 76a14264d7 屏蔽git原始信息 2024-11-19 17:25:57 +08:00
29 changed files with 727 additions and 96 deletions

View File

@ -1,6 +1,6 @@
{
"name": "aix-win-ws",
"version": "2.5.3",
"version": "2.5.4",
"description": "",
"main": "./out/main/index.js",
"author": "上海交大重庆人工智能研究院",

View File

@ -137,7 +137,7 @@ function createMainWindow() {
// mainWindow.setAlwaysOnTop(true, "screen-saver") // 将窗口设置为顶层窗口
// mainWindow.setVisibleOnAllWorkspaces(true) // 如果窗口在所有工作区都可见
// mainWindow.maximize();
mainWindow.maximize();
// 第三步: 开启remote服务
remote.enable(mainWindow.webContents)
}

View File

@ -13,12 +13,12 @@
importPPTXFile(files)
mainMenuVisible = false
}">
<PopoverMenuItem>导入 pptx 文件测试版</PopoverMenuItem>
<PopoverMenuItem>导入 pptx 文件</PopoverMenuItem>
</FileInput>
<PopoverMenuItem @click="setDialogForExport('pptx')">导出文件</PopoverMenuItem>
<PopoverMenuItem @click="resetSlides(); mainMenuVisible = false">重置幻灯片</PopoverMenuItem>
<PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem>
<PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem>
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem> -->
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem> -->
<PopoverMenuItem @click="mainMenuVisible = false; hotkeyDrawerVisible = true">快捷操作</PopoverMenuItem>
</template>
<div class="menu-item"><IconHamburgerButton class="icon" /></div>

View File

@ -7,7 +7,16 @@ export function listKnowlegepoint(query) {
method: 'get',
params: query
})
}
}
// 查询知识点列表
export function listKnowlegepointFormat(query) {
return request({
url: '/point/formatList',
method: 'get',
params: query
})
}
// 查询一级知识点查下级所有层级

View File

@ -0,0 +1,65 @@
<template>
<div id="aptContainer"></div>
</template>
<script>
export default {
props: {
modelValue:[Object,String], // json
width: { //
type: Number,
default: 0
},
height: { //
type: Number,
default: 0
},
domId: { // ID
type: String,
default: 'aptContainer'
}
},
data() {
return {
description: 'apt预览组件-konva',
// konva
konvaStage:null, konvaLayer:null
}
},
mounted() { //
this.initKonva()
},
watch: {
modelValue: {
immediate: true, //
handler(v) { // 12
!!v && this.loadJson()
}
}
},
methods: {
// Konva
initKonva() {
if(!this.width || !this.height) return false // 使
this.konvaStage = new Konva.Stage({
container: "aptContainer", // id of container <div>
width: this.width,
height: this.height,
});
},
//
loadJson(data = this.modelValue) {
if (!data) return false
this.konvaStage = Konva.Node.create(data, this.domId)
}
}
}
</script>
<style lang="scss" scoped>
.aptContainer{
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@ -0,0 +1,27 @@
<template>
<el-link :href="href" target="_blank" type="primary">
<slot name="content">{{content}}</slot>
</el-link>
</template>
<script>
export default {
props: {
href: { //
type: String,
default: 'https://beian.miit.gov.cn'
}
},
data() {
return {
description: '备案号-添加',
content: '备案号苏ICP备2024097972号-1'
}
},
methods: {
}
}
</script>
<style lang="less" scoped>
</style>

View File

@ -1,6 +1,5 @@
<template>
<!-- 表单-组件(自定义) -->
<slot>
<el-row v-bind="rows||{}">
<!-- 其他内容-start -->
<slot name="start"></slot>
@ -80,7 +79,6 @@
<!-- 其他内容-end -->
<slot name="end"></slot>
</el-row>
</slot>
</template>
<script>
export default {
@ -161,7 +159,9 @@ export default {
// --
confirm() {
const formRefs = this.$refs.form
const isBool = this.$attrs.confirm && typeof this.$attrs.confirm === 'function'
this.$emit('confirm', formRefs)
if (isBool) this.$attrs.confirm(formRefs)
},
//
resetFields() {

View File

@ -0,0 +1,44 @@
<template>
<el-pagination v-bind="pageOpt"
@change="(...agrs) => $emit('pageChange',...agrs)"
v-model:current-page="curPage" v-model:page-size="limit" />
</template>
<script>
// -
export default {
name: 'cPage',
props: {
page: { type: Object, required: true },
},
data() {
return {
def: {
// size: 'small',
background: false,
pageSizes: [10, 20, 30, 40, 50, 100],
layout: 'total, sizes, prev, pager, next',
// layout: 'total, sizes, prev, pager, next, jumper',
}
}
},
computed: {
pageOpt() {
return Object.assign({},this.def, this.page)
},
curPage: {
get() { return this.page.curPage },
set(val) { this.page.curPage = val }
},
limit: {
get() { return this.page.limit },
set(val) { this.page.limit = val }
},
},
created() {},
methods: {}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,280 @@
<template>
<!-- 组件 -->
<div>
<slot name="top">
<div class="c-search" :hide="!isFold||isDef" v-if="fItems.length" :style="$attrs.style">
<transition name="el-zoom-in-top">
<c-form v-show="isFold" ref="search" v-if="!noSearch && search" :form="search"
:itemOption="fItems" :option="fOption" :onEnter="fOnEnter" :rows="fRows" :cols="fCols">
<template v-for="item in formSlots" #[item]="data">
<slot :name="`f${item}`" v-bind="data"></slot>
</template>
<template #append>
<slot name="topAdd" v-if="$slots.topAdd"></slot>
<slot name="search" v-if="!$attrs.searchBtnNe">
<el-col style="text-align: center;margin: 5px 0 15px;">
<el-button icon="Search" type="primary" @click="$emit('change','query')">查询</el-button>
<el-button type="warning" @click="$emit('change','reset')">重置</el-button>
</el-col>
</slot>
</template>
</c-form>
</transition>
<div v-if="!isDef" :class="['fold',{hide:!isFold}]" @click="isFold=!isFold">
<!-- <i :class="'el-icon-arrow-' + (isFold?'down':'up')"></i> -->
<el-icon><component :is="isFold?'ArrowUp':'ArrowDown'"></component></el-icon>
</div>
</div>
</slot>
<slot name="start"></slot>
<div :class="['m-list',{'ne':!isMain, hide:!isFold}]">
<slot name="tStart"></slot>
<el-table ref="table" v-bind="tAttrs" v-on="tOns">
<template #empty><slot name="empty">{{emptyText}}</slot></template>
<template #append><slot name="append"></slot></template>
<slot>
<template v-for="(item, index) in optionItems" :key="index">
<el-table-column v-bind="item">
<!-- -表头-自定义 -->
<template #header="{column, $index}">
<slot :name="item.prop+'_header'" :column="column" :$index="$index">
<slot name="header" :column="column" :$index="$index">{{ item.label }}</slot>
</slot>
</template>
<!-- 列内容-自定义 -->
<template #default="{row, column, $index}" v-if="item.type!='selection'">
<slot :name="item.prop" :row="row" :column="column" :$index="$index" :value="row[item.prop]">
<span v-if="item.attrs" v-bind="item.attrs">{{ defVal(row,item, $index, $attrs, column) }}</span>
<slot v-else :row="row" :column="column" :$index="$index" :value="row[item.prop]">{{ defVal(row,item, $index, $attrs, column) }}</slot>
</slot>
</template>
</el-table-column>
</template>
</slot>
</el-table>
<slot name="end"></slot>
<slot name="page">
<c-page v-if="!noPage" :page="page" v-on="$attrs" class="c-page" border="false"></c-page>
</slot>
</div>
</div>
</template>
<script>
import cForm from './cForm.vue'
export default {
// inheritAttrs: false,
components: { cForm },
name: 'cTable',
props: {
option: Array, //
search: Object, //
fItems: { //
type: Array,
default: () => []
},
fOption: { // -
type: Object,
default: () => ({ labelW: '80px' })
// default: () => ({ inline: true, labelW: '80px', size: 'small' })
},
fOnEnter: Function, // ---
fRows: { // -
type: Object,
default: _ => ({ gutter: 20 })
},
fCols: { // - inline
type: Object,
default: _ => ({ span: 8, xs: 24, sm: 12, md: 8, lg: 6 })
},
emptyText: {
type: String,
default: '暂无数据'
},
isDef: { // -
type: Boolean,
default: true
},
isMain: { //
type: Boolean,
default: true
},
fold: { //
type: Boolean,
default: true
},
data: Object, //
page: Object, //
noSearch: Boolean, //
noPage: Boolean, //
noDef: Boolean, //
isMaxHeight: Boolean, //
},
data() {
return {
// -
formSlots: [], isFold: this.fold, height: null,
}
},
computed: {
optionItems() { //
const list = this.option || []
return list.map(o => {
const def = { align: 'center', showOverflowTooltip: true }
if (o.width && o.showOverflowTooltip == undefined){
o.showOverflowTooltip = true //
}
return this.noDef ? o : Object.assign(def, o)
})
.filter(o => o.show ?? true) // -show
.filter(o => o.visible ?? true) // -visible
},
tAttrs() { // $attrs
const attrs = {...this.$attrs}
Object.keys(attrs).forEach(key => {
//
if (!attrs[key]??null) delete attrs[key]
//
else if (/^page.*/.test(key)) delete attrs[key]
})
// 'style', 'class', 't-style', 't-class'
const tArr = Object.keys(attrs).filter(k => k.startsWith('t-'))
if (tArr.length) tArr.forEach(k => attrs[k.slice(2)] = attrs[k])
else ['style', 'class'].forEach(k => delete attrs[k])
//
const hArrs = ['height', 'max-height', 'maxHeight']
const isH = Object.keys(attrs).some(k => hArrs.includes(k))
//
if (!isH) attrs[this.isMaxHeight?'max-height':'height'] = 500
//
if (this.data) attrs.data = this.data
return attrs
},
tOns() { // $on
const attrs = {...this.$attrs}
return Object.keys(attrs).reduce((p, c, a ) => {
if(typeof attrs[c]=='function')p[c]=attrs[c]; return p
}, {})
}
},
created() {},
mounted() {
this.getFormSlots()
},
methods: {
// --
getFormSlots() {
const props = this.fItems.map(o => o.prop)
const keys = Object.keys(this.$slots)
this.formSlots = keys.filter(k => {
const isForm = /^f.*/.test(k) //
const isProp = props.some(p => k.endsWith(p)) // -
return isForm && isProp
}).map(k => k.replace(/^f/, '')) //
},
//
defVal(row, item, rowInd, attr, column) {
switch (item.type) {
case 'index': { // -ind
const { curPage, limit, offset } = attr.page || attr
const start = offset || (curPage - 1) * limit || 0
return rowInd + 1 + start
}
default:
return item.format ? item.format(row[item.prop], row, column, rowInd) : row[item.prop]
}
}
},
}
</script>
<style lang="scss" scoped>
// @import '~@/assets/styles/cmixin';
// $w | $h | $bg | $tBr $tBg
@mixin scrollBar($w:8px,$h:8px,$tBr:20px,
$bg:#d3dce6,$tBg:#99a9bf, $tHbg: #409eff) {
&::-webkit-scrollbar-track-piece {
background: $bg;
}
&::-webkit-scrollbar {
width: $w;
height: $h;
}
&::-webkit-scrollbar-thumb {
background: $tBg;
border-radius: $tBr;
@if $tHbg {
&:hover{
background: $tHbg;
}
}
}
}
:deep(.el-table){
.el-table__expand-column{
overflow: hidden;
}
.el-table__body-wrapper{
@include scrollBar;
}
}
// css
.c-search{
--bg: #fff;
padding-top: 10px;
// padding: 20px 20px 0;
background: var(--bg);
margin-bottom: 30px;
border-radius: 4px;
&[hide=true]{
margin: 0;
padding: 0;
}
.fold{
--box-color: rgba(24,144,255,0.2);
--box-hover-color: rgba(24,144,255,0.6);
width: 100px;
height: 20px;
cursor: pointer;
display: inline-block;
text-align: center;
position: absolute;
background: var(--bg);
border-radius: 0 0 50px 50px;
left: 50%;
transform: translate(-50%,5px);
box-shadow: 0px 3px 3px var(--box-color);
i{font-size: inherit;}
&:hover{
box-shadow: 0px 3px 3px var(--box-hover-color);
i{color: #1890ff;}
}
&.hide{
top: 12px;
border-radius: 50px 50px 0 0;
box-shadow: 0 -3px 3px var(--box-color);
&:hover{box-shadow: 0 -3px 3px var(--box-hover-color);}
}
}
:deep(.el-form){
.el-form-item{
margin-bottom: 10px;
}
}
}
//
.m-list{
padding: 20px;
border-radius: 4px;
&.ne{padding: 0;}
&.hide{
margin-top: 20px;
}
}
.c-page{
background: #fff;
margin-top: 10px;
justify-content: flex-end;
}
</style>

View File

@ -71,4 +71,9 @@ defineExpose({
justify-content: flex-end;
box-sizing: border-box;
}
:deep(.format-work-desc > :is(div):first-child){
display: inline-block;
}
</style>

View File

@ -117,9 +117,9 @@ const saveAdjust = (item) =>{
onMounted(() => {
let data = sessionStore.get('subject.curNode')
Object.assign(curNode, data);
let text = props.modeType == 1 ? '课标': props.modeType == 2 ? '教材' : '考试'
let text = props.modeType == 1||props.modeType == 2 ? '课标' : '考试'
let jsonKey = `${text}-${data.edustage}-${data.edusubject}`
console.log(jsonKey)
params.dataset_id = dataSetJson[jsonKey]
})

View File

@ -56,10 +56,10 @@ const title = computed(() => {
const radio = ref(1)
const radioList = ref([
{ label: '浏览研读', value: 1 },
{ label: '跨学科研读', value: 2 },
{ label: '跨学段研读', value: 3 },
{ label: '课标修订研读', value: 4 },
{ label: '自由研读', value: 5 },
// { label: '', value: 2 },
// { label: '', value: 3 },
// { label: '', value: 4 },
// { label: '', value: 5 },
])
const list = ref([
{

View File

@ -1,7 +1,7 @@
<template>
<div class="container-header flex">
<div class="header-left flex">
<el-button link @click="showDialog = true">
<el-button link @click="onClick">
{{ curNode.edustage}}{{ curNode.edusubject }}{{ type == 1 ? '课标研读': '教材分析'}}<i class="iconfont icon-xiangxia"></i>
</el-button>
</div>
@ -20,12 +20,14 @@
</template>
</el-dropdown>
<div>
<el-button type="primary" link @click="onAdd">
<el-icon>
<Plus />
</el-icon>
添加提示词
</el-button>
<!-- <el-button type="danger">删除</el-button> -->
<!-- <el-button type="primary" link>保存模板</el-button> -->
<el-button type="primary" @click="aiRead">一键研读</el-button>
</div>
@ -53,9 +55,7 @@ const props = defineProps({
default: 1
}
})
watch(() => props.type, (newValue) => {
console.log(newValue, 'newValue2');
}, { immediate: true });
const emit = defineEmits(['changeTemp', 'onRead'])
@ -104,6 +104,11 @@ const onAdd = () => {
wordDialog.value = true
}
const onClick = () =>{
if(props.type == 1) return
showDialog.value = true
}
onUnmounted(() => {
emitter.off('onGetMain')
})

View File

@ -15,6 +15,8 @@ const pdfUrl = ref('')
onMounted(async () =>{
await nextTick()
const { fileurl } = sessionStore.get('subject.curBook')
console.log(fileurl,'fileurl');
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt','.pdf')
})
</script>

View File

@ -269,7 +269,7 @@ const removeItem = async (item) => {
onMounted(() => {
let data = sessionStore.get('subject.curNode')
Object.assign(curNode, data);
let text = props.modeType == 1 ? '课标' : props.modeType == 2 ? '教材' : '考试'
let text = props.modeType == 1 || props.modeType == 2 ? '课标' : '考试'
let jsonKey = `${text}-${data.edustage}-${data.edusubject}`
params.dataset_id = dataSetJson[jsonKey]

View File

@ -15,7 +15,7 @@
</el-tooltip>
</div>
<div class="blockBox">
<el-button @click="currentType = 'selection'"><el-image src="/src/assets/images/mouse-pointer.png"
<el-button @click="currentType = 'selection'"><el-image src="../../../src/assets/images/mouse-pointer.png"
style="width: 14px; height: 14px; color: silver" /></el-button>
</div>
<template v-if="type == 'design'">
@ -123,7 +123,7 @@
<!-- 边框样式 -->
<div class="blockBox">
<el-dropdown @command="updateStyle('lineDash', $event)" placement="top">
<el-button><el-image src="/src/assets/images/borderstyle.png"
<el-button><el-image src="../../../src/assets/images/borderstyle.png"
style="width: 14px; height: 14px"></el-image></el-button>
<template #dropdown>
<el-dropdown-menu>
@ -145,7 +145,7 @@
<!-- 边框粗细 -->
<div class="blockBox">
<el-dropdown @command="updateStyle('lineWidth', $event)" placement="top">
<el-button><el-image src="/src/assets/images/borderwidth.png"
<el-button><el-image src="../../../src/assets/images/borderwidth.png"
style="width: 14px; height: 14px"></el-image></el-button>
<template #dropdown>
<el-dropdown-menu>

View File

@ -59,14 +59,14 @@ export const processList = (row, aloneOption=false) => {
for(; j<workDescArr.length; j++){
const char = String.fromCharCode(65+j);
if (aloneOption) {
tmp += `<div style='width:100%;display:flex;padding: 2px 0'>${char}.${workDescArr[j]}</div>`;
tmp += `<div class="format-work-desc" style='width:100%;display:flex;padding: 2px 0'>${char}.${workDescArr[j]}</div>`;
}
else {
if(j%2 == 0){
tmp += `<div style='width:100%;display:flex;'>`;
}
tmp += `<div style='padding-left:10px;width:50%;overflow:hidden;text-overflow:ellipsis;font-size:0.9em;'>${char}.${workDescArr[j]}</div>`;
tmp += `<div class="format-work-desc" style='padding-left:10px;width:50%;overflow:hidden;text-overflow:ellipsis;font-size:0.9em;'>${char}.${workDescArr[j]}</div>`;
if(j%2 == 1){
tmp += '</div>';
}
@ -153,14 +153,14 @@ export const processList = (row, aloneOption=false) => {
for(; j<optionsArr.length; j++){
const char = String.fromCharCode(65+j);
if (aloneOption) {
tmp += `<div style='width:100%;display:flex;padding: 2px 0'>${char}.${optionsArr[j]}</div>`;
tmp += `<div class="format-work-desc" style='width:100%;display:flex;padding: 2px 0'>${char}.${optionsArr[j]}</div>`;
}
else {
if(j%2 == 0){
tmp += `<div style='width:100%;display:flex;'>`;
}
tmp += `<div style='padding-left: 10px; width: 50%'>${char}.${optionsArr[j]}</div>`;
tmp += `<div class="format-work-desc" style='padding-left: 10px; width: 50%'>${char}.${optionsArr[j]}</div>`;
if(j%2 == 1){
tmp += '</div>';
}
@ -280,14 +280,14 @@ export const processList = (row, aloneOption=false) => {
for(; j<workDescArr.length; j++){
const char = String.fromCharCode(65+j);
if (aloneOption) {
tmp += `<div style='width:100%;display:flex;padding: 2px 0'>${char}.${workDescArr[j]}</div>`;
tmp += `<div class="format-work-desc" style='width:100%;display:flex;padding: 2px 0'>${char}.${workDescArr[j]}</div>`;
}
else {
if(j%2 == 0){
tmp += `<div style='width:100%;display:flex;'>`;
}
tmp += `<div style='padding-left: 10px; width: 50%'>${char}.${workDescArr[j]}</div>`;
tmp += `<div class="format-work-desc" style='padding-left: 10px; width: 50%'>${char}.${workDescArr[j]}</div>`;
if(j%2 == 1){
tmp += '</div>';
}

View File

@ -117,4 +117,8 @@ export const coursewareTypeList = [
label:'素材',
value:6
},
{
label:'视频',
value:12
},
]

View File

@ -120,7 +120,7 @@ import { useRouter, useRoute } from 'vue-router'
import { listEntpcoursework } from '@/api/education/entpCourseWork'
import { listEvaluationclue } from '@/api/classTask'
import { delEntpcoursework } from "@/api/education/entpCourseWork";
import { delEntpcoursework, updateEntpcoursework } from "@/api/education/entpCourseWork";
import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
import QuesItem from "@/views/classTask/newClassTaskAssign/questionUpload/quesItem/index.vue";
@ -284,7 +284,8 @@ const t = function(name, time) {
edustage: userStore.edustage, // this.userStore.edustage,
edusubject: userStore.edusubject, // this.userStore.edusubject,
evalid: props.bookobj.levelSecondId, // this.activeParams.lession.id,
status: "1",
edituserid: userStore.userId,
orderby: 'concat(worktype,timestamp) DESC',
}
@ -424,7 +425,8 @@ const onSubmitExamSingleCallback=(callback) =>{
/** 删除题目按钮操作 */
const handleDelete = async(item, index) => {
await useHandleData(delEntpcoursework, item.id, `确认删除编号为【${index+1}】的题目?` );
//await useHandleData(delEntpcoursework, item.id, `${index+1}` );
await useHandleData(updateEntpcoursework, {id:item.id, status:'0'}, `确认删除编号为【${index+1}】的题目?` );
debounceQueryData();
}
@ -487,6 +489,10 @@ watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
height: calc(100% - 100px);
}
:deep(.format-work-desc > :is(div):first-child){
display: inline-block;
}
// :deep(.el-dialog .question-dialog){
// height: 80vh !important;
// width: 80% !important;

View File

@ -99,6 +99,8 @@ const router = useRouter()
const { proxy } = getCurrentInstance()
const props = defineProps({
})
const curLessionList = ref([]);
const activeParams = reactive({
version: {},
lession: {},

View File

@ -145,8 +145,7 @@
</el-form-item>
<el-form-item :prop="checkAnswer">
<el-checkbox-group v-model="questForm.checkAnswer" style="display:flex; width: 100%">
<el-button @click="addItem" type="primary" style="margin-left: auto;"
:disabled="questForm.list.length>=7">+</el-button>
<el-button @click="addItem" type="primary" style="margin-left: auto;">+</el-button>
<el-button :disabled="questForm.list.length==1" @click="deleteItem(item,index)" type="primary"
style="margin-left: 10px;">-</el-button>
</el-checkbox-group>
@ -406,9 +405,10 @@
<script setup>
import { ElMessage, ElNotification } from 'element-plus'
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 { getBindlist } from '@/api/education/knowledgePoint'
import { getBindlist, listKnowlegepointFormat } from '@/api/education/knowledgePoint'
import { listEvaluation } from '@/api/subject'
import { listEntpcoursework, getEntpcoursework, delEntpcoursework, addEntpcoursework, updateEntpcoursework, uploadEntpcourseworkFile } from "@/api/education/entpCourseWork";
import { isJson } from "@/hooks/useProcessList";
@ -491,7 +491,7 @@ const questForm = reactive({
method: '',
submitIndex: 0, // ([]0, [])
submitType: 0, //
status: 1, //
status: '1', //
list:[
{
text:""
@ -612,10 +612,13 @@ onMounted(() => {
}
yearList.value.push(s)
};
//
})
const checkBoxChange=(v)=>{
// v: []
console.log(v,'vvvvvv')
@ -741,6 +744,10 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
let titleSubjList = ''; // +
const newSubjListparams = []; // list
// 线线()
item.title = item.title.replace(/<!--BA--><div class="quizPutTag" contenteditable="true">(?:&nbsp;)?<\/div><!--EA-->/g, '_____');
if(item.worktype == '复合题') {
// []
newList = [{text:""}];
@ -1000,6 +1007,7 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
const pointArr = item.evalnodeid.split(',');
if (curKnowledgePointList.value.length > 0 && pointArr.length > 0) {
pointArr.forEach(element => {
element = element.trim();
let point = [];
if (getCurKnowledgePointToForm(point, element, curKnowledgePointList.value)) {
point = point.reverse();
@ -1337,8 +1345,10 @@ const submitForm=(formName) =>{
const workType = questForm.worktype.replace('(主观题)', '');
// ()(title_like)
const title = questForm.title.replace(/'/g, "\\'");
console.log(questForm,'???????????????????????')
const title = questForm.title
.replace(/'/g, "\\'")
.replace(/_{3,}/g, "<!--BA--><div class=\"quizPutTag\" contenteditable=\"true\"></div><!--EA-->");
console.log(questForm,'???????????????????????');
let param = {
id: questForm.id, // id
thirdid: 0, // id SID
@ -1660,10 +1670,56 @@ const myMessageShow=(title, msg, status)=>{
// },
// },
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
/**
* @desc: 遍历原知识点数据, 将title字段转为knowTitle以供knowledgePointProps进行tree的格式转换显示
* @return: {*}
* @param {*} list
*/
const updateKnowledgePoint = (list) => {
list.forEach(item => {
if (item.title && item.title != '') {
item.knowTitle = item.title;
}
if (item.children && Array.isArray(item.children)) {
updateKnowledgePoint(item.children);
}
});
return list;
};
watch(() => props.bookobj.levelSecondId, async (newVal, oldVal) => {
console.log(props.bookobj,'课程选择')
// props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId
lessionid.value = props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
/**
* 格式化知识点: 分两种情况
* 1. 语文/英语: 获取学科下的所有知识点(该学科对应无章节与知识点绑定, 故只获取全知识点)
* 2. 其他: 获取当前章节下的所有知识点
*/
let id = props.bookobj.levelSecondId;
if( props.bookobj.node.edustage == '高中' && (props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语') ){
id = props.bookobj.node.rootid;
const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
id = res.rows[0]?.id;
if (id) {
listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,}).then(res => {
//console.log('listKnowlegepointFormat->', res.rows);
curKnowledgePointList.value = updateKnowledgePoint(res.rows);
});
}
}else{
getBindlist({ eid: id }).then(res => {
if (!res.data || res.data.length < 1) {
ElMessage.warning('当前章节下未绑定知识点,暂不更新该试题知识点!');
curKnowledgePointList.value = [];
}
else {
curKnowledgePointList.value = res.data;
}
})
}
})
@ -1674,7 +1730,20 @@ defineExpose({
cropperFormItemCallBack,
})
</script>
<style lang="scss">
.el-cascader-panel {
li[aria-haspopup="true"] {
.el-checkbox {
display: none;
}
}
}
</style>
<style scoped lang="scss">
.questForm-item-cover{
position: relative;
@ -1692,6 +1761,4 @@ defineExpose({
z-index: 9999;
}
}
</style>

View File

@ -111,6 +111,7 @@ import { updateClasswork, listEvaluationclue, listClassworkeval,delClassworkeval
import { listEvaluation } from '@/api/subject'
import { listKnowledgePoint } from "@/api/knowledge/knowledgePoint";
import { getBindlist } from '@/api/education/knowledgePoint'
import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
import { processList } from '@/hooks/useProcessList'
import { useGetHomework } from '@/hooks/useGetHomework'
@ -155,6 +156,7 @@ const entpCourseWorkPointList = ref([
{label: '不限', value: []},
]); // -
const knowledgePointProps = ref({value: 'thirdId', label: 'title'});
//const knowledgePointProps = ref({value: 'thirdId', label: 'knowTitle'});
const entpCourseWorkYearList =ref([
{label: '不限', value: '-1'},
{label: '2024', value: '2024'},
@ -358,8 +360,18 @@ const handleQueryFromEntpCourseWork= async (queryType) => {
/**
* 3知识点
*/
const getEntpCourseWorkPointList = () => {
const getEntpCourseWorkPointList = async () => {
//
// const res = await getBindlist({ eid: props.bookobj.levelSecondId });
// if (!res.data || res.data.length < 1) {
// ElMessage.warning('');
// entpCourseWorkPointList.value = [];
// }
// else {
// entpCourseWorkPointList.value = res.data;
// }
//
listEvaluation({ itemkey: "subject", pageSize: 10, edustage: userStore.edustage, edusubject: userStore.edusubject }).then((res) => {
const evalId = res.rows

View File

@ -60,6 +60,7 @@ import { sessionStore } from '@/utils/store'
import { ElMessage } from 'element-plus'
import { dataSetJson } from '@/utils/comm.js'
import useUserStore from '@/store/modules/user'
import emitter from '@/utils/mitt';
const userInfo = useUserStore().user
const textarea = ref('')
@ -132,6 +133,8 @@ const saveAdjust = (item) =>{
}
const curFile = reactive({})
const dataset_id = ref('')
const fileList = ref([])
@ -144,7 +147,9 @@ const getList = () =>{
Object.assign(curFile, fileList.value[0])
})
}
emitter.on('curFile', (item) =>{
changeFile(item)
})
const changeFile = (val) =>{
Object.assign(curFile, val);
@ -154,7 +159,7 @@ const changeFile = (val) =>{
onMounted(() => {
let data = sessionStore.get('subject.curNode')
Object.assign(curNode, data);
let text = props.modeType == 1 ? '课标': props.modeType == 2 ? '教材' : '考试'
let text = props.modeType == 1 ||props.modeType == 2 ? '课标' : '考试'
let jsonKey = `${text}-${data.edustage}-${data.edusubject}`
params.dataset_id = dataSetJson[jsonKey]

View File

@ -8,16 +8,16 @@
</template>
<div class="dialog-content">
<div class="flex dialog-top">
<el-radio-group v-model="radio" @change="changeRadio">
<!-- <el-radio-group v-model="radio" @change="changeRadio">
<el-radio :value="item.value" v-for="item in radioList">{{ item.label }}</el-radio>
</el-radio-group>
</el-radio-group> -->
</div>
<div class="content-list">
<ul>
<li v-for="(item, index) in list" :class="activeIndex == index ? 'li-active' : ''" @click="clickItem(index)">
<el-image class="img" :src="item.url" />
<span>{{ item.name }}</span>
<li v-for="(item, index) in fileList" :class="activeIndex == index ? 'li-active' : ''" @click="clickItem(index, item)">
<el-image class="img" :src="url" />
<el-text truncated>{{ item.fileName }}</el-text>
</li>
</ul>
</div>
@ -47,6 +47,7 @@ import { sessionStore } from '@/utils/store'
import { dataSetJson } from '@/utils/comm.js'
import { ElMessage } from 'element-plus'
import useUserStore from '@/store/modules/user'
import emitter from '@/utils/mitt';
const userInfo = useUserStore().user
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload");
@ -93,11 +94,7 @@ const changeRadio = () => {
})
}
}
const activeIndex = ref(-1)
const clickItem = (index) => {
activeIndex.value = index
}
const activeIndex = ref(0)
const dataset_id = ref('')
@ -109,7 +106,7 @@ const onSuccess = async (response) =>{
dataset_id: dataset_id.value
}
const res = await completion(data)
console.log(res)
if(res.data.code != 200) return
let docData = {
fileUrl: response.url,
@ -123,19 +120,30 @@ const onSuccess = async (response) =>{
}
const { msg } = await addDoc(docData)
ElMessage.success(msg)
getList()
}
const curNode = reactive({})
const fileList = ref([])
const curFile = reactive({})
const getList = () =>{
docList({
userId: userInfo.userId,
dataset_id: dataset_id.value
}).then( res =>{
console.log(res)
fileList.value = [...res.rows]
Object.assign(curFile, fileList.value[0])
})
}
const clickItem = (index, item) => {
activeIndex.value = index
Object.assign(curFile, item)
emitter.emit('curFile',item)
}
onMounted(() =>{
let data = sessionStore.get('subject.curNode')
@ -174,6 +182,7 @@ onMounted(() =>{
flex-wrap: wrap;
li {
width: 130px;
display: flex;
flex-direction: column;
font-size: 13px;

View File

@ -269,7 +269,7 @@ const removeItem = async (item) => {
onMounted(() => {
let data = sessionStore.get('subject.curNode')
Object.assign(curNode, data);
let text = props.modeType == 1 ? '课标' : props.modeType == 2 ? '教材' : '考试'
let text = props.modeType == 1 || props.modeType == 2? '课标' : '考试'
let jsonKey = `${text}-${data.edustage}-${data.edusubject}`
params.dataset_id = dataSetJson[jsonKey]

View File

@ -1,12 +1,11 @@
<template>
<div>
<div class="page-resource flex">
<div class="page-resource flex mb-4">
<!-- 左侧 教材 目录 -->
<ChooseTextbook @change-book="getData" @node-click="getData" />
<!-- <ChooseTextbook @change-book="getData" @node-click="getData" /> -->
<div class="page-right">
<div class="button-container">
<el-button style="margin-left: 12px;" 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')">作业管理1</el-button> -->
<el-button type="primary" @click="onchange('/model/newClassTaskAssign')">作业管理</el-button>
<el-button type="success" @click="onchange('/model/teaching')">教材研读</el-button>
@ -16,13 +15,34 @@
</div>
</div>
</div>
<el-row class="container">
<!-- 左侧 选择教材 目录 -->
<ChooseTextbook @change-book="changeBook" @node-click="changeBook" />
<!-- 中间 展示内容 -->
<el-col :span="10">
<div class="c-item mb-4 mx-4">
<div class="flex justify-between pb-2">
<h3>教师资源</h3>
<span class="c-btns">
<el-button size="small" text :icon="Refresh" @click="handleAll('refresh')">刷新</el-button>
<el-button size="small" text :icon="Files" @click="handleAll('resource')">资源库</el-button>
<el-button size="small" text :icon="UploadFilled" @click="handleAll('upload')">上传</el-button>
<el-button size="small" text :icon="Plus" @click="handleAll('add')">添加</el-button>
</span>
</div>
<c-table ref="resourRef" v-bind="sourceOpt" t-class="rounded"></c-table>
</div>
</el-col>
</el-row>
</template>
<script setup>
import { onMounted, ref, watch, reactive } from 'vue'
import { useRouter } from 'vue-router'
import { Plus, Refresh, Upload, Files, UploadFilled } from '@element-plus/icons-vue'
import { createWindow } from '@/utils/tool' //
import * as entpcoursefile from '@/api/education/entpcoursefile' // api
//
import ChooseTextbook from '@/components/choose-textbook/index.vue'
const router = useRouter()
@ -35,9 +55,38 @@ const courseObj = reactive({
coursetitle: '',
node: null, //
})
const dt = reactive({
curRow: null, //
})
// ref
const resourRef = ref() // ref
// -cTable
const sourceOpt = reactive({
data: [], //
option: [ //
{ label: '名称', prop: 'title', align: 'left' },
{ label: '类型', prop: 'type' },
{ label: '时间', prop: 'createTime', width: 160, sortable: true },
],
noPage: true, //
isMain: false, //
highlightCurrentRow: true, //
rowClick: (r, c, e) => { //
if (dt.curRow == r) { // -
resourRef.value.$refs.table.setCurrentRow()
dt.curRow = null
} else dt.curRow = r
}
})
sourceOpt.data = [
{ title: '测试学校' },
{ title: '测试学校2' },
{ title: '测试学校3' },
]
//
const getData = (data) => {
// -methods
//
const changeBook = (data) => {
const { textBook, node } = data
let textbookId = textBook.curBookId
let levelSecondId = node.id
@ -71,19 +120,34 @@ const onchange = (path) => {
router.push(path)
}
}
//
const handleAll = (type) =>{
console.log(type)
switch (type) {
case 'refresh': //
break;
case 'resource': //
break;
case 'upload': //
break;
case 'add':{ //
break;
}
}
}
</script>
<style lang="scss" scoped>
.page-resource {
height: 100%;
padding: 10px 15px 0;
// height: 100%;
// padding: 10px 15px 0;
.page-right {
min-width: 0;
display: flex;
flex-direction: column;
flex: 1;
margin-left: 20px;
// margin-left: 20px;
height: 100%;
background: #ffffff;
border-radius: 10px;
@ -94,7 +158,7 @@ const onchange = (path) => {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 1rem 0;
margin: 1rem;
justify-content: flex-start;
.el-button {
@ -105,4 +169,12 @@ const onchange = (path) => {
}
}
}
.container{
height: calc(100% - 32px - 3rem);
.c-item{
.c-btns{
.el-button{margin: 0;}
}
}
}
</style>

View File

@ -32,7 +32,15 @@
</el-row> -->
<el-row class="resoure-btns">
<el-col :span="24" class="query-row flex">
<div class="flex row-left"> <el-select v-model="sourceStore.query.fileSuffix" @change="sourceStore.changeSuffix"
<div class="flex row-left">
<!-- 第三方资源筛选-->
<el-select v-if="isThird" v-model="sourceStore.thirdQuery.type" @change="sourceStore.thirdChangeType"
style="width: 110px">
<el-option v-for="item in coursewareTypeList" :key="item.value" :label="item.label"
:value="item.value" />
</el-select>
<el-select v-else v-model="sourceStore.query.fileSuffix" @change="sourceStore.changeSuffix"
style="width: 110px">
<el-option v-for="item in sourceStore.resourceFormatList" :key="item.value" :label="item.label"
:value="item.value" />
@ -48,7 +56,6 @@
</div>
</el-col>
</el-row>
</div>
</template>

View File

@ -7,7 +7,10 @@
"noEmit": true,
"baseUrl": ".",
"paths": {
"../*": ["./src/*"]
"../*": ["./src/*"],
"@/*": [
"./src/renderer/src/*"
]
}
}
}

View File

@ -1,4 +1,11 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*":["src/renderer/src/*"],
"@root/*":["./*"]
}
},
"files": [],
"references": [
{